From f2480ff5cafd471a93cac6a740dd2a75ea98c12f Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 15 Aug 2017 09:01:25 -0400 Subject: [PATCH 1/5] Implemented Aether Storm --- Mage.Sets/src/mage/cards/a/AetherStorm.java | 113 ++++++++++++++++++ Mage.Sets/src/mage/sets/FifthEdition.java | 1 + Mage.Sets/src/mage/sets/Homelands.java | 1 + Mage.Sets/src/mage/sets/MastersEditionII.java | 11 +- 4 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/a/AetherStorm.java diff --git a/Mage.Sets/src/mage/cards/a/AetherStorm.java b/Mage.Sets/src/mage/cards/a/AetherStorm.java new file mode 100644 index 00000000000..f4598491ecd --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AetherStorm.java @@ -0,0 +1,113 @@ +/* + * 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.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.common.DestroySourceEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author TheElk801 + */ +public class AetherStorm extends CardImpl { + + public AetherStorm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}"); + + // Creature spells can't be cast. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AetherStormReplacementEffect())); + + // Pay 4 life: Destroy Aether Storm. It can't be regenerated. Any player may activate this ability. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroySourceEffect(true), new PayLifeCost(4)); + ability.setMayActivate(TargetController.ANY); + ability.addEffect(new InfoEffect("Any player may activate this ability")); + this.addAbility(ability); + } + + public AetherStorm(final AetherStorm card) { + super(card); + } + + @Override + public AetherStorm copy() { + return new AetherStorm(this); + } +} + +class AetherStormReplacementEffect extends ContinuousRuleModifyingEffectImpl { + + public AetherStormReplacementEffect() { + super(Duration.WhileOnBattlefield, Outcome.Detriment); + staticText = "Creature spells with converted mana cost 4 or greater can't be cast."; + } + + public AetherStormReplacementEffect(final AetherStormReplacementEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public AetherStormReplacementEffect copy() { + return new AetherStormReplacementEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Card card = game.getCard(event.getSourceId()); + if (card != null && card.isCreature()) { + return true; + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/FifthEdition.java b/Mage.Sets/src/mage/sets/FifthEdition.java index 8fa86cf5124..cc26b04bbec 100644 --- a/Mage.Sets/src/mage/sets/FifthEdition.java +++ b/Mage.Sets/src/mage/sets/FifthEdition.java @@ -32,6 +32,7 @@ public class FifthEdition extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("AEther Storm", 70, Rarity.UNCOMMON, mage.cards.a.AetherStorm.class)); cards.add(new SetCardInfo("Abbey Gargoyles", 277, Rarity.UNCOMMON, mage.cards.a.AbbeyGargoyles.class)); cards.add(new SetCardInfo("Abyssal Specter", 1, Rarity.UNCOMMON, mage.cards.a.AbyssalSpecter.class)); cards.add(new SetCardInfo("Adarkar Wastes", 410, Rarity.RARE, mage.cards.a.AdarkarWastes.class)); diff --git a/Mage.Sets/src/mage/sets/Homelands.java b/Mage.Sets/src/mage/sets/Homelands.java index 7d24fd651d1..19629bd5537 100644 --- a/Mage.Sets/src/mage/sets/Homelands.java +++ b/Mage.Sets/src/mage/sets/Homelands.java @@ -64,6 +64,7 @@ public class Homelands extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("AEther Storm", 26, Rarity.UNCOMMON, mage.cards.a.AetherStorm.class)); cards.add(new SetCardInfo("Abbey Gargoyles", 101, Rarity.UNCOMMON, mage.cards.a.AbbeyGargoyles.class)); cards.add(new SetCardInfo("Abbey Matron", 102, Rarity.COMMON, AbbeyMatron.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Abbey Matron", 103, Rarity.COMMON, AbbeyMatron.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index c20addee7b6..a64cc22a543 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -64,6 +64,7 @@ public class MastersEditionII extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("AEther Storm", 39, Rarity.UNCOMMON, mage.cards.a.AetherStorm.class)); cards.add(new SetCardInfo("Abbey Gargoyles", 1, Rarity.UNCOMMON, mage.cards.a.AbbeyGargoyles.class)); cards.add(new SetCardInfo("Adarkar Sentinel", 201, Rarity.COMMON, mage.cards.a.AdarkarSentinel.class)); cards.add(new SetCardInfo("Aeolipile", 202, Rarity.COMMON, mage.cards.a.Aeolipile.class)); @@ -77,9 +78,9 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Aurochs", 153, Rarity.COMMON, mage.cards.a.Aurochs.class)); cards.add(new SetCardInfo("Aysen Bureaucrats", 6, Rarity.COMMON, mage.cards.a.AysenBureaucrats.class)); cards.add(new SetCardInfo("Badlands", 225, Rarity.RARE, mage.cards.b.Badlands.class)); - cards.add(new SetCardInfo("Balduvian Conjurer", 40, Rarity.COMMON, mage.cards.b.BalduvianConjurer.class)); + cards.add(new SetCardInfo("Balduvian Conjurer", 40, Rarity.COMMON, mage.cards.b.BalduvianConjurer.class)); cards.add(new SetCardInfo("Balduvian Dead", 79, Rarity.UNCOMMON, mage.cards.b.BalduvianDead.class)); - cards.add(new SetCardInfo("Balduvian Hydra", 118, Rarity.RARE, mage.cards.b.BalduvianHydra.class)); + cards.add(new SetCardInfo("Balduvian Hydra", 118, Rarity.RARE, mage.cards.b.BalduvianHydra.class)); cards.add(new SetCardInfo("Balduvian Trading Post", 226, Rarity.RARE, mage.cards.b.BalduvianTradingPost.class)); cards.add(new SetCardInfo("Barbed Sextant", 204, Rarity.COMMON, mage.cards.b.BarbedSextant.class)); cards.add(new SetCardInfo("Binding Grasp", 41, Rarity.RARE, mage.cards.b.BindingGrasp.class)); @@ -87,7 +88,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Brainstorm", 42, Rarity.COMMON, mage.cards.b.Brainstorm.class)); cards.add(new SetCardInfo("Brassclaw Orcs", 119, Rarity.COMMON, BrassclawOrcs.class)); cards.add(new SetCardInfo("Brimstone Dragon", 120, Rarity.RARE, mage.cards.b.BrimstoneDragon.class)); - cards.add(new SetCardInfo("Brine Shaman", 80, Rarity.COMMON, mage.cards.b.BrineShaman.class)); + cards.add(new SetCardInfo("Brine Shaman", 80, Rarity.COMMON, mage.cards.b.BrineShaman.class)); cards.add(new SetCardInfo("Browse", 43, Rarity.UNCOMMON, mage.cards.b.Browse.class)); cards.add(new SetCardInfo("Burnout", 121, Rarity.UNCOMMON, mage.cards.b.Burnout.class)); cards.add(new SetCardInfo("Carapace", 155, Rarity.COMMON, mage.cards.c.Carapace.class)); @@ -127,7 +128,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Fungal Bloom", 165, Rarity.RARE, mage.cards.f.FungalBloom.class)); cards.add(new SetCardInfo("Gangrenous Zombies", 92, Rarity.COMMON, mage.cards.g.GangrenousZombies.class)); cards.add(new SetCardInfo("Giant Growth", 167, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); - cards.add(new SetCardInfo("Giant Trap Door Spider", 195, Rarity.UNCOMMON, mage.cards.g.GiantTrapDoorSpider.class)); + cards.add(new SetCardInfo("Giant Trap Door Spider", 195, Rarity.UNCOMMON, mage.cards.g.GiantTrapDoorSpider.class)); cards.add(new SetCardInfo("Glacial Chasm", 229, Rarity.RARE, mage.cards.g.GlacialChasm.class)); cards.add(new SetCardInfo("Glacial Crevasses", 127, Rarity.RARE, mage.cards.g.GlacialCrevasses.class)); cards.add(new SetCardInfo("Gorilla Shaman", 129, Rarity.UNCOMMON, GorillaShaman.class)); @@ -137,7 +138,7 @@ public class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Helm of Obedience", 210, Rarity.RARE, mage.cards.h.HelmOfObedience.class)); cards.add(new SetCardInfo("Icatian Javelineers", 15, Rarity.COMMON, IcatianJavelineers.class)); cards.add(new SetCardInfo("Icatian Scout", 17, Rarity.COMMON, IcatianScout.class)); - cards.add(new SetCardInfo("Iceberg", 49, Rarity.UNCOMMON, mage.cards.i.Iceberg.class)); + cards.add(new SetCardInfo("Iceberg", 49, Rarity.UNCOMMON, mage.cards.i.Iceberg.class)); cards.add(new SetCardInfo("Icequake", 94, Rarity.COMMON, mage.cards.i.Icequake.class)); cards.add(new SetCardInfo("Icy Prison", 50, Rarity.COMMON, mage.cards.i.IcyPrison.class)); cards.add(new SetCardInfo("Ihsan's Shade", 95, Rarity.RARE, mage.cards.i.IhsansShade.class)); From 110b237b583289055b72cf01c0e2140f1169bb4b Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 15 Aug 2017 09:20:16 -0400 Subject: [PATCH 2/5] Implemented Afiya Grove --- Mage.Sets/src/mage/cards/a/AfiyaGrove.java | 144 +++++++++++++++++++++ Mage.Sets/src/mage/sets/Mirage.java | 1 + 2 files changed, 145 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AfiyaGrove.java diff --git a/Mage.Sets/src/mage/cards/a/AfiyaGrove.java b/Mage.Sets/src/mage/cards/a/AfiyaGrove.java new file mode 100644 index 00000000000..eb5b30a742c --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AfiyaGrove.java @@ -0,0 +1,144 @@ +/* + * 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.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.StateTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author TheElk801 + */ +public class AfiyaGrove extends CardImpl { + + public AfiyaGrove(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); + + // Afiya Grove enters the battlefield with three +1/+1 counters on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)), "with three +1/+1 counters on it")); + + // At the beginning of your upkeep, move a +1/+1 counter from Afiya Grove onto target creature. + Ability ability = new BeginningOfUpkeepTriggeredAbility(new MoveCounterToTargetFromSourceEffect(), TargetController.YOU, false); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // When Afiya Grove has no +1/+1 counters on it, sacrifice it. + this.addAbility(new AfiyaGroveNoCountersAbility()); + } + + public AfiyaGrove(final AfiyaGrove card) { + super(card); + } + + @Override + public AfiyaGrove copy() { + return new AfiyaGrove(this); + } +} + +class MoveCounterToTargetFromSourceEffect extends OneShotEffect { + + public MoveCounterToTargetFromSourceEffect() { + super(Outcome.Detriment); + this.staticText = "move a +1/+1 counter from {this} onto target creature"; + } + + public MoveCounterToTargetFromSourceEffect(final MoveCounterToTargetFromSourceEffect effect) { + super(effect); + } + + @Override + public MoveCounterToTargetFromSourceEffect copy() { + return new MoveCounterToTargetFromSourceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourceObject = game.getPermanent(source.getSourceId()); + if (sourceObject != null && controller != null) { + Permanent toPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (toPermanent != null && sourceObject.getCounters(game).getCount(CounterType.P1P1) > 0) { + sourceObject.removeCounters(CounterType.P1P1.createInstance(), game); + toPermanent.addCounters(CounterType.P1P1.createInstance(), source, game); + game.informPlayers("Moved a +1/+1 counter from " + sourceObject.getLogName() + " to " + toPermanent.getLogName()); + } + return true; + } + return false; + } +} + +class AfiyaGroveNoCountersAbility extends StateTriggeredAbility { + + public AfiyaGroveNoCountersAbility() { + super(Zone.BATTLEFIELD, new SacrificeSourceEffect()); + } + + public AfiyaGroveNoCountersAbility(final AfiyaGroveNoCountersAbility ability) { + super(ability); + } + + @Override + public AfiyaGroveNoCountersAbility copy() { + return new AfiyaGroveNoCountersAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = game.getPermanent(getSourceId()); + if (permanent != null && permanent.getCounters(game).getCount(CounterType.P1P1) == 0) { + return true; + } + return false; + } + + @Override + public String getRule() { + return "When {this} has no +1/+1 counters on it, sacrifice it."; + } + +} diff --git a/Mage.Sets/src/mage/sets/Mirage.java b/Mage.Sets/src/mage/sets/Mirage.java index a84117c7589..8742706b664 100644 --- a/Mage.Sets/src/mage/sets/Mirage.java +++ b/Mage.Sets/src/mage/sets/Mirage.java @@ -53,6 +53,7 @@ public class Mirage extends ExpansionSet { this.numBoosterRare = 1; this.ratioBoosterMythic = 0; cards.add(new SetCardInfo("Abyssal Hunter", 1, Rarity.RARE, mage.cards.a.AbyssalHunter.class)); + cards.add(new SetCardInfo("Afiya Grove", 103, Rarity.RARE, mage.cards.a.AfiyaGrove.class)); cards.add(new SetCardInfo("Afterlife", 205, Rarity.UNCOMMON, mage.cards.a.Afterlife.class)); cards.add(new SetCardInfo("Agility", 154, Rarity.COMMON, mage.cards.a.Agility.class)); cards.add(new SetCardInfo("Alarum", 206, Rarity.COMMON, mage.cards.a.Alarum.class)); From 0b691cc97b812d5fb069ab02bfda3c0090439ed7 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 15 Aug 2017 09:27:32 -0400 Subject: [PATCH 3/5] Implemented Air Bladder --- Mage.Sets/src/mage/cards/a/AirBladder.java | 81 ++++++++++++++++++++++ Mage.Sets/src/mage/sets/Nemesis.java | 1 + 2 files changed, 82 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AirBladder.java diff --git a/Mage.Sets/src/mage/cards/a/AirBladder.java b/Mage.Sets/src/mage/cards/a/AirBladder.java new file mode 100644 index 00000000000..f4b74539059 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AirBladder.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.cards.a; + +import java.util.UUID; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.combat.CanBlockOnlyFlyingAttachedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Zone; + +/** + * + * @author TheElk801 + */ +public class AirBladder extends CardImpl { + + public AirBladder(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); + + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature has flying. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA))); + + // Enchanted creature can block only creatures with flying. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockOnlyFlyingAttachedEffect(AttachmentType.AURA))); + + } + + public AirBladder(final AirBladder card) { + super(card); + } + + @Override + public AirBladder copy() { + return new AirBladder(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Nemesis.java b/Mage.Sets/src/mage/sets/Nemesis.java index 76963a07627..2fc8efb9d8f 100644 --- a/Mage.Sets/src/mage/sets/Nemesis.java +++ b/Mage.Sets/src/mage/sets/Nemesis.java @@ -56,6 +56,7 @@ public class Nemesis extends ExpansionSet { this.ratioBoosterMythic = 0; cards.add(new SetCardInfo("Accumulated Knowledge", 26, Rarity.COMMON, mage.cards.a.AccumulatedKnowledge.class)); cards.add(new SetCardInfo("Aether Barrier", 27, Rarity.RARE, mage.cards.a.AetherBarrier.class)); + cards.add(new SetCardInfo("Air Bladder", 28, Rarity.COMMON, mage.cards.a.AirBladder.class)); cards.add(new SetCardInfo("Ancient Hydra", 76, Rarity.UNCOMMON, mage.cards.a.AncientHydra.class)); cards.add(new SetCardInfo("Angelic Favor", 1, Rarity.UNCOMMON, mage.cards.a.AngelicFavor.class)); cards.add(new SetCardInfo("Animate Land", 101, Rarity.UNCOMMON, mage.cards.a.AnimateLand.class)); From 5d8d0f9d9df20e0e8144346c3863f50c5c64ccad Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 15 Aug 2017 09:49:53 -0400 Subject: [PATCH 4/5] Small change to Afiya Grove --- Mage.Sets/src/mage/cards/a/AfiyaGrove.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/a/AfiyaGrove.java b/Mage.Sets/src/mage/cards/a/AfiyaGrove.java index eb5b30a742c..b32ede06f5f 100644 --- a/Mage.Sets/src/mage/cards/a/AfiyaGrove.java +++ b/Mage.Sets/src/mage/cards/a/AfiyaGrove.java @@ -82,7 +82,7 @@ public class AfiyaGrove extends CardImpl { class MoveCounterToTargetFromSourceEffect extends OneShotEffect { public MoveCounterToTargetFromSourceEffect() { - super(Outcome.Detriment); + super(Outcome.Benefit); this.staticText = "move a +1/+1 counter from {this} onto target creature"; } From 57d6a1d99536d1fa5dbc064af9ae5b7477155a39 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 15 Aug 2017 16:03:34 -0400 Subject: [PATCH 5/5] Implemented The Ur-Dragon, added Eminence as an ability word --- Mage.Sets/src/mage/cards/t/TheUrDragon.java | 220 ++++++++++++++++++ Mage.Sets/src/mage/sets/Commander2017.java | 2 +- .../main/java/mage/constants/AbilityWord.java | 1 + 3 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/t/TheUrDragon.java diff --git a/Mage.Sets/src/mage/cards/t/TheUrDragon.java b/Mage.Sets/src/mage/cards/t/TheUrDragon.java new file mode 100644 index 00000000000..7393fbfdfe2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheUrDragon.java @@ -0,0 +1,220 @@ +/* + * 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.t; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.PutPermanentOnBattlefieldEffect; +import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.watchers.Watcher; + +/** + * + * @author TheElk801 + */ +public class TheUrDragon extends CardImpl { + + private static final FilterCard filter = new FilterCard("Dragon spells"); + + static { + filter.add(new SubtypePredicate(SubType.DRAGON)); + } + + public TheUrDragon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{U}{B}{R}{G}"); + + addSuperType(SuperType.LEGENDARY); + this.subtype.add("Dragon"); + this.subtype.add("Avatar"); + this.power = new MageInt(10); + this.toughness = new MageInt(10); + + // Eminence - As long as The Ur-Dragon is in the command zone or on the battlefield, other Dragon spells you cast cost {1} less to cast. + Effect effect = new SpellsCostReductionControllerEffect(filter, 1); + effect.setText("As long as {this} is in the command zone or on the battlefield, other Dragon spells you cast cost {1} less to cast"); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); + ability.setAbilityWord(AbilityWord.EMINENCE); + this.addAbility(ability); + effect = new SpellsCostReductionControllerEffect(filter, 1); + effect.setText(""); + ability = new SimpleStaticAbility(Zone.COMMAND, effect); + this.addAbility(ability); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever one or more Dragons you control attack, draw that many cards, then you may put a permanent card from your hand onto the battlefield + this.addAbility(new TheUrDragonTriggeredAbility(), new DragonsAttackedWatcher()); + } + + public TheUrDragon(final TheUrDragon card) { + super(card); + } + + @Override + public TheUrDragon copy() { + return new TheUrDragon(this); + } +} + +class DragonsAttackedWatcher extends Watcher { + + public final Set attackedThisTurnCreatures = new HashSet<>(); + + public DragonsAttackedWatcher() { + super(DragonsAttackedWatcher.class.getSimpleName(), WatcherScope.GAME); + } + + public DragonsAttackedWatcher(final DragonsAttackedWatcher watcher) { + super(watcher); + this.attackedThisTurnCreatures.addAll(watcher.attackedThisTurnCreatures); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.BEGIN_COMBAT_STEP_PRE) { + this.attackedThisTurnCreatures.clear(); + } + if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED) { + if (game.getPermanent(event.getSourceId()).getSubtype(game).contains(SubType.DRAGON)) { + this.attackedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(), game)); + } + } + } + + public Set getAttackedThisTurnCreatures() { + return this.attackedThisTurnCreatures; + } + + @Override + public DragonsAttackedWatcher copy() { + return new DragonsAttackedWatcher(this); + } + +} + +class TheUrDragonTriggeredAbility extends TriggeredAbilityImpl { + + public TheUrDragonTriggeredAbility() { + super(Zone.BATTLEFIELD, new TheUrDragonEffect(), false); + } + + public TheUrDragonTriggeredAbility(final TheUrDragonTriggeredAbility ability) { + super(ability); + } + + @Override + public TheUrDragonTriggeredAbility copy() { + return new TheUrDragonTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + for (UUID attacker : game.getCombat().getAttackers()) { + Permanent creature = game.getPermanent(attacker); + if (creature != null && creature.getControllerId() == event.getPlayerId() && creature.getSubtype(game).contains(SubType.DRAGON)) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever one or more Dragons you control attack, " + super.getRule(); + } +} + +class TheUrDragonEffect extends OneShotEffect { + + public TheUrDragonEffect() { + super(Outcome.Benefit); + this.staticText = "draw that many cards, then you may put a permanent card from your hand onto the battlefield."; + } + + public TheUrDragonEffect(final TheUrDragonEffect effect) { + super(effect); + } + + @Override + public TheUrDragonEffect copy() { + return new TheUrDragonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + DragonsAttackedWatcher watcher = (DragonsAttackedWatcher) game.getState().getWatchers().get(DragonsAttackedWatcher.class.getSimpleName()); + if (watcher != null) { + int attackingDragons = 0; + for (MageObjectReference attacker : watcher.getAttackedThisTurnCreatures()) { + if (attacker.getPermanentOrLKIBattlefield(game).getControllerId().equals(controller.getId())) { + attackingDragons++; + } + } + if (attackingDragons > 0) { + controller.drawCards(attackingDragons, game); + } + Effect effect = new PutPermanentOnBattlefieldEffect(); + effect.apply(game, source); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Commander2017.java b/Mage.Sets/src/mage/sets/Commander2017.java index c2679d7cc0f..f29c7cc43a6 100644 --- a/Mage.Sets/src/mage/sets/Commander2017.java +++ b/Mage.Sets/src/mage/sets/Commander2017.java @@ -67,10 +67,10 @@ public class Commander2017 extends ExpansionSet { cards.add(new SetCardInfo("Taigam, Ojutai Master", 46, Rarity.MYTHIC, mage.cards.t.TaigamOjutaiMaster.class)); cards.add(new SetCardInfo("Taigam, Sidisi's Hand", 47, Rarity.RARE, mage.cards.t.TaigamSidisisHand.class)); cards.add(new SetCardInfo("Teferi's Protection", 8, Rarity.RARE, mage.cards.t.TeferisProtection.class)); + cards.add(new SetCardInfo("The Ur-Dragon", 48, Rarity.MYTHIC, mage.cards.t.TheUrDragon.class)); cards.add(new SetCardInfo("Traverse the Outlands", 34, Rarity.RARE, mage.cards.t.TraverseTheOutlands.class)); cards.add(new SetCardInfo("Wasitora, Nekoru Queen", 49, Rarity.MYTHIC, mage.cards.w.WasitoraNekoruQueen.class)); cards.add(new SetCardInfo("Kindred Dominance", 18, Rarity.RARE, mage.cards.w.WasitoraNekoruQueen.class)); - } } diff --git a/Mage/src/main/java/mage/constants/AbilityWord.java b/Mage/src/main/java/mage/constants/AbilityWord.java index 7f8fec55b53..892091a6449 100644 --- a/Mage/src/main/java/mage/constants/AbilityWord.java +++ b/Mage/src/main/java/mage/constants/AbilityWord.java @@ -42,6 +42,7 @@ public enum AbilityWord { CONVERGE("Converge"), DELIRIUM("Delirium"), DOMAIN("Domain"), + EMINENCE("Eminence"), FATEFUL_HOUR("Fateful hour"), FEROCIOUS("Ferocious"), FORMIDABLE("Formidable"),