From 81de1f5e65e002cc1f94da099fad0fa2581bf058 Mon Sep 17 00:00:00 2001 From: nickymikail Date: Sat, 1 Jul 2017 14:43:47 -0700 Subject: [PATCH 01/18] Oketra's Avenger --- .../src/mage/cards/o/OketrasAvenger.java | 68 +++++++++++++++++++ .../src/mage/sets/HourOfDevastation.java | 1 + 2 files changed, 69 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/o/OketrasAvenger.java diff --git a/Mage.Sets/src/mage/cards/o/OketrasAvenger.java b/Mage.Sets/src/mage/cards/o/OketrasAvenger.java new file mode 100644 index 00000000000..9d994c96cf0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OketrasAvenger.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.cards.o; + +import java.util.UUID; + +import mage.MageInt; +import mage.abilities.common.BecomesExertSourceTriggeredAbility; +import mage.abilities.effects.common.PreventCombatDamageToSourceEffect; +import mage.abilities.keyword.ExertAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; + +/** + * + * @author nickymikail + */ +public class OketrasAvenger extends CardImpl { + + public OketrasAvenger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add("Human"); + this.subtype.add("Warrior"); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // You may exert Oketra's Avenger as it attacks. When you do, prevent all combat damage that would be dealt to it this turn. + BecomesExertSourceTriggeredAbility ability = new BecomesExertSourceTriggeredAbility(new PreventCombatDamageToSourceEffect(Duration.EndOfTurn)); + this.addAbility(new ExertAbility(ability)); + } + + public OketrasAvenger(final OketrasAvenger card) { + super(card); + } + + @Override + public OketrasAvenger copy() { + return new OketrasAvenger(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index 3e95c90993d..6fa2e13f2f5 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -108,6 +108,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Nicol Bolas, the Deceiver", 205, Rarity.MYTHIC, mage.cards.n.NicolBolasTheDeceiver.class)); cards.add(new SetCardInfo("Nissa, Genesis Mage", 200, Rarity.MYTHIC, mage.cards.n.NissaGenesisMage.class)); cards.add(new SetCardInfo("Oasis Ritualist", 124, Rarity.COMMON, mage.cards.o.OasisRitualist.class)); + cards.add(new SetCardInfo("Oketra's Avenger", 17, Rarity.COMMON, mage.cards.o.OketrasAvenger.class)); cards.add(new SetCardInfo("Oketra's Last Mercy", 18, Rarity.RARE, mage.cards.o.OketrasLastMercy.class)); cards.add(new SetCardInfo("Open Fire", 105, Rarity.COMMON, mage.cards.o.OpenFire.class)); cards.add(new SetCardInfo("Overwhelming Splendor", 19, Rarity.MYTHIC, mage.cards.o.OverwhelmingSplendor.class)); From f80bcfdfa23ee2020df238cc887d7916a059954c Mon Sep 17 00:00:00 2001 From: nickymikail Date: Sat, 1 Jul 2017 15:02:15 -0700 Subject: [PATCH 02/18] Lurching Rotbeast --- .../src/mage/cards/l/LurchingRotbeast.java | 66 +++++++++++++++++++ .../src/mage/sets/HourOfDevastation.java | 1 + 2 files changed, 67 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LurchingRotbeast.java diff --git a/Mage.Sets/src/mage/cards/l/LurchingRotbeast.java b/Mage.Sets/src/mage/cards/l/LurchingRotbeast.java new file mode 100644 index 00000000000..72cc70c41c1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LurchingRotbeast.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.cards.l; + +import java.util.UUID; + +import mage.MageInt; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.keyword.CyclingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author anonymous + */ +public class LurchingRotbeast extends CardImpl { + + public LurchingRotbeast(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add("Zombie"); + this.subtype.add("Beast"); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // Cycling {B} + this.addAbility(new CyclingAbility(new ManaCostsImpl("{B}"))); + + } + + public LurchingRotbeast(final LurchingRotbeast card) { + super(card); + } + + @Override + public LurchingRotbeast copy() { + return new LurchingRotbeast(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index 6fa2e13f2f5..21949123475 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -101,6 +101,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Khenra Scrapper", 100, Rarity.COMMON, mage.cards.k.KhenraScrapper.class)); cards.add(new SetCardInfo("Kindled Fury", 101, Rarity.COMMON, mage.cards.k.KindledFury.class)); cards.add(new SetCardInfo("Liliana's Defeat", 68, Rarity.UNCOMMON, mage.cards.l.LilianasDefeat.class)); + cards.add(new SetCardInfo("Lurching Rotbeast", 69, Rarity.COMMON, mage.cards.l.LurchingRotbeast.class)); cards.add(new SetCardInfo("Manalith", 164, Rarity.COMMON, mage.cards.m.Manalith.class)); cards.add(new SetCardInfo("Marauding Boneslasher", 70, Rarity.COMMON, mage.cards.m.MaraudingBoneslasher.class)); cards.add(new SetCardInfo("Mountain", 188, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.BFZ_FULL_ART_BASIC, true))); From 186fdb0cacca06cd7e291c21e67c6a28f1be9122 Mon Sep 17 00:00:00 2001 From: nickymikail Date: Sat, 1 Jul 2017 16:15:58 -0700 Subject: [PATCH 03/18] Ruin Rat --- Mage.Sets/src/mage/cards/r/RuinRat.java | 73 +++++++++++++++++++ .../src/mage/sets/HourOfDevastation.java | 1 + 2 files changed, 74 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/r/RuinRat.java diff --git a/Mage.Sets/src/mage/cards/r/RuinRat.java b/Mage.Sets/src/mage/cards/r/RuinRat.java new file mode 100644 index 00000000000..e63e6c0b49e --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RuinRat.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.cards.r; + +import java.util.UUID; + +import mage.MageInt; +import mage.abilities.common.DiesTriggeredAbility; +import mage.filter.FilterCard; +import mage.target.common.TargetCardInOpponentsGraveyard; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author anonymous + */ +public class RuinRat extends CardImpl { + + public RuinRat(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add("Rat"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // When Ruin Rat dies, exile target card from an opponent's graveyard. + DiesTriggeredAbility ability = new DiesTriggeredAbility(new ExileTargetEffect()); + ability.addTarget(new TargetCardInOpponentsGraveyard(new FilterCard())); + this.addAbility(ability); + + } + + public RuinRat(final RuinRat card) { + super(card); + } + + @Override + public RuinRat copy() { + return new RuinRat(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index 21949123475..0d2328dae64 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -121,6 +121,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Razaketh, the Foulblooded", 73, Rarity.MYTHIC, mage.cards.r.RazakethTheFoulblooded.class)); cards.add(new SetCardInfo("Reason // Believe", 154, Rarity.RARE, mage.cards.r.ReasonBelieve.class)); cards.add(new SetCardInfo("Refuse // Cooperate", 156, Rarity.RARE, mage.cards.r.RefuseCooperate.class)); + cards.add(new SetCardInfo("Ruin Rat", 75, Rarity.COMMON, mage.cards.r.RuinRat.class)); cards.add(new SetCardInfo("Samut, the Tested", 144, Rarity.MYTHIC, mage.cards.s.SamutTheTested.class)); cards.add(new SetCardInfo("Sand Strangler", 107, Rarity.UNCOMMON, mage.cards.s.SandStrangler.class)); cards.add(new SetCardInfo("Sandblast", 20, Rarity.COMMON, mage.cards.s.Sandblast.class)); From a1dcaa6a899ad597e13aa79f3c33c1b6d412b85f Mon Sep 17 00:00:00 2001 From: spjspj Date: Sun, 2 Jul 2017 13:49:33 +1000 Subject: [PATCH 04/18] Implement 2 HOU cards --- .../mage/cards/u/UnconventionalTactics.java | 132 ++++++++++++++++++ .../src/mage/cards/v/VileManifestation.java | 85 +++++++++++ .../src/mage/sets/HourOfDevastation.java | 2 + 3 files changed, 219 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/u/UnconventionalTactics.java create mode 100644 Mage.Sets/src/mage/cards/v/VileManifestation.java diff --git a/Mage.Sets/src/mage/cards/u/UnconventionalTactics.java b/Mage.Sets/src/mage/cards/u/UnconventionalTactics.java new file mode 100644 index 00000000000..b642f08b7c1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UnconventionalTactics.java @@ -0,0 +1,132 @@ +/* + * 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.u; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author spjspj + */ +public class UnconventionalTactics extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("zombie creature"); + + static { + filter.add(new SubtypePredicate(SubType.ZOMBIE)); + } + + public UnconventionalTactics(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}"); + + // Target creature gets +3/+3 and gains flying until end of turn. + Effect effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn); + effect.setText("Target creature gets +3/+3"); + this.getSpellAbility().addEffect(effect); + effect = new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn); + effect.setText("and gains flying until end of turn"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Whenever a Zombie enters the battlefield under your control, you may pay {W}. If you do, return Unconventional Tactics from your graveyard to your hand. + this.addAbility(new UnconventionalTacticsTriggeredAbility()); + } + + public UnconventionalTactics(final UnconventionalTactics card) { + super(card); + } + + @Override + public UnconventionalTactics copy() { + return new UnconventionalTactics(this); + } +} + +class UnconventionalTacticsTriggeredAbility extends TriggeredAbilityImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("zombie creature"); + + static { + filter.add(new SubtypePredicate(SubType.ZOMBIE)); + } + + public UnconventionalTacticsTriggeredAbility() { + super(Zone.GRAVEYARD, new DoIfCostPaid(new ReturnToHandSourceEffect(), new ManaCostsImpl("{W}")), false); + } + + public UnconventionalTacticsTriggeredAbility(final UnconventionalTacticsTriggeredAbility ability) { + super(ability); + } + + @Override + public UnconventionalTacticsTriggeredAbility copy() { + return new UnconventionalTacticsTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent.isCreature() + && permanent.getControllerId().equals(this.controllerId) + && filter.match(permanent, game)) { + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever a Zombie enters the battlefield under your control, you may pay {W}. If you do, return {this} from your graveyard to your hand."; + } +} diff --git a/Mage.Sets/src/mage/cards/v/VileManifestation.java b/Mage.Sets/src/mage/cards/v/VileManifestation.java new file mode 100644 index 00000000000..536e69b21e4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VileManifestation.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.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.CyclingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; + +/** + * + * @author spjspj + */ +public class VileManifestation extends CardImpl { + + private static final FilterCard filter = new FilterCard(); + + static { + filter.add(new AbilityPredicate(CyclingAbility.class)); + } + + public VileManifestation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add("Horror"); + this.power = new MageInt(0); + this.toughness = new MageInt(4); + + // Vile Manifestation gets +1/+0 for each card with cycling in your graveyard. + DynamicValue amount = new CardsInControllerGraveyardCount(new FilterCard(filter)); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(amount, new StaticValue(0), Duration.WhileOnBattlefield)); + this.addAbility(ability); + + // Cycling {2} + this.addAbility(new CyclingAbility(new ManaCostsImpl("{2}"))); + } + + public VileManifestation(final VileManifestation card) { + super(card); + } + + @Override + public VileManifestation copy() { + return new VileManifestation(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index b320a23f775..b4d0285f1fd 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -142,10 +142,12 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Torment of Venom", 79, Rarity.COMMON, mage.cards.t.TormentOfVenom.class)); cards.add(new SetCardInfo("Traveler's Amulet", 167, Rarity.COMMON, mage.cards.t.TravelersAmulet.class)); cards.add(new SetCardInfo("Uncage the Menagerie", 137, Rarity.MYTHIC, mage.cards.u.UncageTheMenagerie.class)); + cards.add(new SetCardInfo("Unconventional Tactics", 27, Rarity.UNCOMMON, mage.cards.u.UnconventionalTactics.class)); cards.add(new SetCardInfo("Unesh, Criosphinx Sovereign", 52, Rarity.MYTHIC, mage.cards.u.UneshCriosphinxSovereign.class)); cards.add(new SetCardInfo("Unquenchable Thirst", 53, Rarity.COMMON, mage.cards.u.UnquenchableThirst.class)); cards.add(new SetCardInfo("Unraveling Mummy", 147, Rarity.UNCOMMON, mage.cards.u.UnravelingMummy.class)); cards.add(new SetCardInfo("Unsummon", 54, Rarity.COMMON, mage.cards.u.Unsummon.class)); + cards.add(new SetCardInfo("Vile Manifestation", 80, Rarity.UNCOMMON, mage.cards.v.VileManifestation.class)); cards.add(new SetCardInfo("Visage of Bolas", 208, Rarity.RARE, mage.cards.v.VisageOfBolas.class)); cards.add(new SetCardInfo("Vizier of the Anointed", 55, Rarity.UNCOMMON, mage.cards.v.VizierOfTheAnointed.class)); cards.add(new SetCardInfo("Vizier of the True", 28, Rarity.UNCOMMON, mage.cards.v.VizierOfTheTrue.class)); From dac9f4f4a8a17a0223cfc34eb2cc23e64e8d80c0 Mon Sep 17 00:00:00 2001 From: spjspj Date: Sun, 2 Jul 2017 17:11:48 +1000 Subject: [PATCH 05/18] Implement Tragic Lesson (HOU) --- Mage.Sets/src/mage/cards/t/TragicLesson.java | 111 ++++++++++++++++++ .../src/mage/sets/HourOfDevastation.java | 1 + 2 files changed, 112 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TragicLesson.java diff --git a/Mage.Sets/src/mage/cards/t/TragicLesson.java b/Mage.Sets/src/mage/cards/t/TragicLesson.java new file mode 100644 index 00000000000..f728e0ff652 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TragicLesson.java @@ -0,0 +1,111 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.ReturnToHandChosenControlledPermanentCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author spjspj + */ +public class TragicLesson extends CardImpl { + + public TragicLesson(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); + + // Draw two cards. Then discard a card unless you return a land you control to its owner's hand. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2)); + this.getSpellAbility().addEffect(new TragicLessonEffect()); + } + + public TragicLesson(final TragicLesson card) { + super(card); + } + + @Override + public TragicLesson copy() { + return new TragicLesson(this); + } +} + +class TragicLessonEffect extends OneShotEffect { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("a land you control"); + + static { + filter.add(new CardTypePredicate(CardType.LAND)); + } + + public TragicLessonEffect() { + super(Outcome.Discard); + staticText = "Then discard a card unless you return a land you control to its owner's hand."; + } + + public TragicLessonEffect(final TragicLessonEffect effect) { + super(effect); + } + + @Override + public TragicLessonEffect copy() { + return new TragicLessonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + + if (controller != null + && controller.chooseUse(Outcome.Discard, "Do you want to return a land you control to its owner's hand? If you don't, you must discard 1 card", source, game)) { + Cost cost = new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(filter)); + if (cost.canPay(source, source.getSourceId(), controller.getId(), game)) { + if (cost.pay(source, game, source.getSourceId(), controller.getId(), false, null)) { + return true; + } + } + } + if (controller != null) { + controller.discard(1, false, source, game); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index b4d0285f1fd..d44af937ffc 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -140,6 +140,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Torment of Hailfire", 77, Rarity.RARE, mage.cards.t.TormentOfHailfire.class)); cards.add(new SetCardInfo("Torment of Scarabs", 78, Rarity.UNCOMMON, mage.cards.t.TormentOfScarabs.class)); cards.add(new SetCardInfo("Torment of Venom", 79, Rarity.COMMON, mage.cards.t.TormentOfVenom.class)); + cards.add(new SetCardInfo("Tragic Lesson", 51, Rarity.COMMON, mage.cards.t.TragicLesson.class)); cards.add(new SetCardInfo("Traveler's Amulet", 167, Rarity.COMMON, mage.cards.t.TravelersAmulet.class)); cards.add(new SetCardInfo("Uncage the Menagerie", 137, Rarity.MYTHIC, mage.cards.u.UncageTheMenagerie.class)); cards.add(new SetCardInfo("Unconventional Tactics", 27, Rarity.UNCOMMON, mage.cards.u.UnconventionalTactics.class)); From b573d7288351cf9b2dc62b940d09ac09d7ccf883 Mon Sep 17 00:00:00 2001 From: igoudt Date: Sun, 2 Jul 2017 13:08:03 +0200 Subject: [PATCH 06/18] added UT, fix small bug on Hour of Revelation --- .../src/mage/cards/h/HourOfRevelation.java | 5 ++- .../single/hou/BontusLastReckoningTest.java | 33 +++++++++++++++ .../cards/single/hou/ChampionOfWitsTest.java | 40 +++++++++++++++++++ .../single/hou/HourOfRevelationTest.java | 26 ++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/hou/BontusLastReckoningTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/hou/ChampionOfWitsTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/hou/HourOfRevelationTest.java diff --git a/Mage.Sets/src/mage/cards/h/HourOfRevelation.java b/Mage.Sets/src/mage/cards/h/HourOfRevelation.java index bdbed620dfe..f2b229f4a83 100644 --- a/Mage.Sets/src/mage/cards/h/HourOfRevelation.java +++ b/Mage.Sets/src/mage/cards/h/HourOfRevelation.java @@ -27,7 +27,6 @@ */ package mage.cards.h; -import java.util.UUID; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.effects.common.DestroyAllEffect; @@ -39,6 +38,8 @@ import mage.constants.ComparisonType; import mage.constants.Zone; import mage.filter.common.FilterNonlandPermanent; +import java.util.UUID; + /** * * @author fireshoes @@ -51,7 +52,7 @@ public class HourOfRevelation extends CardImpl { // Hour of Revelation costs {3} less to cast if there are ten or more nonland permanents on the battlefield. SimpleStaticAbility ability = new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(3, new PermanentsOnTheBattlefieldCondition( - new FilterNonlandPermanent("there are ten or more nonland permanents on the battlefield"), ComparisonType.MORE_THAN, 9))); + new FilterNonlandPermanent("there are ten or more nonland permanents on the battlefield"), ComparisonType.MORE_THAN, 9, false))); ability.setRuleAtTheTop(true); this.addAbility(ability); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/BontusLastReckoningTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/BontusLastReckoningTest.java new file mode 100644 index 00000000000..2846c501740 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/BontusLastReckoningTest.java @@ -0,0 +1,33 @@ +package org.mage.test.cards.single.hou; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class BontusLastReckoningTest extends CardTestPlayerBase { + + private String reckoning = "Bontu's Last Reckoning"; + + @Test + public void testDelayedUntap(){ + String pouncer = "Adorned Pouncer"; + String angel = "Angel of Condemnation"; + addCard(Zone.HAND, playerA, reckoning); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); + addCard(Zone.BATTLEFIELD, playerA, pouncer); + addCard(Zone.BATTLEFIELD, playerB, angel); + addCard(Zone.BATTLEFIELD, playerB, "Island"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN,playerA, reckoning); + + setStopAt(3, PhaseStep.PRECOMBAT_MAIN); + + execute(); + + assertTappedCount("Swamp", true, 3); + assertTappedCount("Island", false, 1); + assertGraveyardCount(playerA, pouncer, 1); + assertGraveyardCount(playerB, angel, 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/ChampionOfWitsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/ChampionOfWitsTest.java new file mode 100644 index 00000000000..4a6ec08e3e3 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/ChampionOfWitsTest.java @@ -0,0 +1,40 @@ +package org.mage.test.cards.single.hou; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class ChampionOfWitsTest extends CardTestPlayerBase { + + + private final String champion = "Champion of Wits"; + + @Test + public void testEternalize(){ + addCard(Zone.GRAVEYARD, playerA, champion); + addCard(Zone.BATTLEFIELD,playerA, "Island", 10); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA,"Eternalize {5}{U}{U}"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + + execute(); + assertHandCount(playerA, 2); + } + + @Test + public void testEternalizeWithAnthem(){ + String anthem = "Glorious Anthem"; + addCard(Zone.GRAVEYARD, playerA, champion); + addCard(Zone.BATTLEFIELD,playerA, "Island", 10); + addCard(Zone.BATTLEFIELD, playerA, anthem); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA,"Eternalize {5}{U}{U}"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + + execute(); + assertHandCount(playerA, 3); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/HourOfRevelationTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/HourOfRevelationTest.java new file mode 100644 index 00000000000..2d1f5998d8d --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/HourOfRevelationTest.java @@ -0,0 +1,26 @@ +package org.mage.test.cards.single.hou; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class HourOfRevelationTest extends CardTestPlayerBase { + + private final String hour = "Hour of Revelation"; + + @Test + public void testCountAllPlayers() { + addCard(Zone.HAND, playerA, hour, 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 6); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 5); + addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 5); + + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hour); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertTappedCount("Plains", true, 3); + } +} From e302e5f3024525ab88e8f8744cbdafdaceb95724 Mon Sep 17 00:00:00 2001 From: igoudt Date: Sun, 2 Jul 2017 13:54:10 +0200 Subject: [PATCH 07/18] added dutiful servants, rampagin hippo, scrounger of souls --- .../src/mage/cards/d/DutifulServants.java | 26 ++++++++++++++ .../src/mage/cards/r/RampagingHippo.java | 35 +++++++++++++++++++ .../src/mage/cards/s/ScroungerOfSouls.java | 31 ++++++++++++++++ .../src/mage/sets/HourOfDevastation.java | 8 +++-- 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/d/DutifulServants.java create mode 100644 Mage.Sets/src/mage/cards/r/RampagingHippo.java create mode 100644 Mage.Sets/src/mage/cards/s/ScroungerOfSouls.java diff --git a/Mage.Sets/src/mage/cards/d/DutifulServants.java b/Mage.Sets/src/mage/cards/d/DutifulServants.java new file mode 100644 index 00000000000..d09dfcf50f8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DutifulServants.java @@ -0,0 +1,26 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +public class DutifulServants extends CardImpl { + + public DutifulServants(UUID ownerId, CardSetInfo cardSetInfo){ + super(ownerId, cardSetInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + subtype.add("Zombie"); + power = new MageInt(2); + toughness = new MageInt(5); + } + + public DutifulServants(final DutifulServants dutifulServants){ + super(dutifulServants); + } + + public DutifulServants copy(){ + return new DutifulServants(this); + } +} diff --git a/Mage.Sets/src/mage/cards/r/RampagingHippo.java b/Mage.Sets/src/mage/cards/r/RampagingHippo.java new file mode 100644 index 00000000000..ff5286a99d5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RampagingHippo.java @@ -0,0 +1,35 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.keyword.CyclingAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +public class RampagingHippo extends CardImpl { + + public RampagingHippo(UUID cardID, CardSetInfo cardSetInfo){ + super(cardID, cardSetInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}"); + subtype.add("Hippo"); + power = new MageInt(5); + toughness = new MageInt(6); + + // Trample + addAbility(TrampleAbility.getInstance()); + + // Cycling {2} + addAbility(new CyclingAbility(new ManaCostsImpl("2"))); + } + + public RampagingHippo(final RampagingHippo rampagingHippo){ + super(rampagingHippo); + } + + public RampagingHippo copy(){ + return new RampagingHippo(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/ScroungerOfSouls.java b/Mage.Sets/src/mage/cards/s/ScroungerOfSouls.java new file mode 100644 index 00000000000..c684ab11cd7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScroungerOfSouls.java @@ -0,0 +1,31 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +public class ScroungerOfSouls extends CardImpl { + + public ScroungerOfSouls(UUID cardID, CardSetInfo cardSetInfo){ + super(cardID, cardSetInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); + subtype.add("Horror"); + + power = new MageInt(3); + toughness = new MageInt(4); + + // Lifelink + addAbility(LifelinkAbility.getInstance()); + + } + + public ScroungerOfSouls(final ScroungerOfSouls scroungerOfSouls){ + super(scroungerOfSouls); + } + public ScroungerOfSouls copy(){ + return new ScroungerOfSouls(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index d44af937ffc..bc16f25bcb0 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -27,8 +27,6 @@ */ package mage.sets; -import java.util.ArrayList; -import java.util.List; import mage.cards.CardGraphicInfo; import mage.cards.ExpansionSet; import mage.cards.FrameStyle; @@ -38,6 +36,9 @@ import mage.cards.repository.CardRepository; import mage.constants.Rarity; import mage.constants.SetType; +import java.util.ArrayList; +import java.util.List; + /** * @author fireshoes */ @@ -88,6 +89,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Djeru, With Eyes Open", 10, Rarity.RARE, mage.cards.d.DjeruWithEyesOpen.class)); cards.add(new SetCardInfo("Doomfall", 62, Rarity.UNCOMMON, mage.cards.d.Doomfall.class)); cards.add(new SetCardInfo("Dreamstealer", 63, Rarity.RARE, mage.cards.d.Dreamstealer.class)); + cards.add(new SetCardInfo("Dutiful Servants", 12, Rarity.COMMON, mage.cards.d.DutifulServants.class)); cards.add(new SetCardInfo("Earthshaker Khenra", 90, Rarity.RARE, mage.cards.e.EarthshakerKhenra.class)); cards.add(new SetCardInfo("Fervent Paincaster", 91, Rarity.UNCOMMON, mage.cards.f.FerventPaincaster.class)); cards.add(new SetCardInfo("Forest", 189, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(FrameStyle.BFZ_FULL_ART_BASIC, true))); @@ -116,6 +118,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Plains", 185, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.BFZ_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Pride Sovereign", 126, Rarity.RARE, mage.cards.p.PrideSovereign.class)); cards.add(new SetCardInfo("Proven Combatant", 42, Rarity.COMMON, mage.cards.p.ProvenCombatant.class)); + cards.add(new SetCardInfo("Rampaging Hippo", 128, Rarity.COMMON, mage.cards.r.RampagingHippo.class)); cards.add(new SetCardInfo("Ramunap Excavator", 129, Rarity.RARE, mage.cards.r.RamunapExcavator.class)); cards.add(new SetCardInfo("Ramunap Hydra", 130, Rarity.RARE, mage.cards.r.RamunapHydra.class)); cards.add(new SetCardInfo("Razaketh, the Foulblooded", 73, Rarity.MYTHIC, mage.cards.r.RazakethTheFoulblooded.class)); @@ -124,6 +127,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Samut, the Tested", 144, Rarity.MYTHIC, mage.cards.s.SamutTheTested.class)); cards.add(new SetCardInfo("Sand Strangler", 107, Rarity.UNCOMMON, mage.cards.s.SandStrangler.class)); cards.add(new SetCardInfo("Sandblast", 20, Rarity.COMMON, mage.cards.s.Sandblast.class)); + cards.add(new SetCardInfo("Scrounger of Souls", 76, Rarity.COMMON, mage.cards.s.ScroungerOfSouls.class)); cards.add(new SetCardInfo("Sidewinder Naga", 134, Rarity.COMMON, mage.cards.s.SidewinderNaga.class)); cards.add(new SetCardInfo("Sinuous Striker", 45, Rarity.UNCOMMON, mage.cards.s.SinuousStriker.class)); cards.add(new SetCardInfo("Solemnity", 22, Rarity.RARE, mage.cards.s.Solemnity.class)); From e0464635c47bda4274bc70314a0bd41b51b1dcf8 Mon Sep 17 00:00:00 2001 From: spjspj Date: Sun, 2 Jul 2017 22:48:00 +1000 Subject: [PATCH 08/18] Implement 2 cards (HOU) --- .../src/mage/cards/t/TenaciousHunter.java | 91 +++++++++++++++++++ Mage.Sets/src/mage/cards/t/ThornedMoloch.java | 77 ++++++++++++++++ Mage.Sets/src/mage/cards/t/TragicLesson.java | 3 +- .../src/mage/sets/HourOfDevastation.java | 2 + 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/t/TenaciousHunter.java create mode 100644 Mage.Sets/src/mage/cards/t/ThornedMoloch.java diff --git a/Mage.Sets/src/mage/cards/t/TenaciousHunter.java b/Mage.Sets/src/mage/cards/t/TenaciousHunter.java new file mode 100644 index 00000000000..82d6d6eb508 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TenaciousHunter.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.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.CounterPredicate; + +/** + * + * @author spjspj + */ +public class TenaciousHunter extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature has a -1/-1 counter on it"); + + static { + filter.add(new CounterPredicate(CounterType.M1M1)); + } + + public TenaciousHunter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + + this.subtype.add("Crocodile"); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // As long as a creature has a -1/-1 counter on it, Tenacious Hunter has vigilance and deathtouch. + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, + new ConditionalContinuousEffect(new GainAbilitySourceEffect(VigilanceAbility.getInstance()), + new PermanentsOnTheBattlefieldCondition(filter), + "{this} has Vigilance as long as a creature has a -1/-1 counter on it" + ) + ); + + ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(DeathtouchAbility.getInstance()), + new PermanentsOnTheBattlefieldCondition(filter), + "{this} has Deathtouch as long as a creature has a -1/-1 counter on it" + ) + ); + + this.addAbility(ability); + } + + public TenaciousHunter(final TenaciousHunter card) { + super(card); + } + + @Override + public TenaciousHunter copy() { + return new TenaciousHunter(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/ThornedMoloch.java b/Mage.Sets/src/mage/cards/t/ThornedMoloch.java new file mode 100644 index 00000000000..54275a0f47a --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThornedMoloch.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.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceAttackingCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.ProwessAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +/** + * + * @author spjspj + */ +public class ThornedMoloch extends CardImpl { + + public ThornedMoloch(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add("Lizard"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Prowess + this.addAbility(new ProwessAbility()); + + // Thorned Moloch has first strike as long as it's attacking. + this.addAbility( + new SimpleStaticAbility( + Zone.BATTLEFIELD, + new ConditionalContinuousEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance()), SourceAttackingCondition.instance, "{this} has first strike as long as it's attacking") + ) + ); + + } + + public ThornedMoloch(final ThornedMoloch card) { + super(card); + } + + @Override + public ThornedMoloch copy() { + return new ThornedMoloch(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TragicLesson.java b/Mage.Sets/src/mage/cards/t/TragicLesson.java index f728e0ff652..7ce12df4e36 100644 --- a/Mage.Sets/src/mage/cards/t/TragicLesson.java +++ b/Mage.Sets/src/mage/cards/t/TragicLesson.java @@ -33,6 +33,7 @@ import mage.abilities.costs.Cost; import mage.abilities.costs.common.ReturnToHandChosenControlledPermanentCost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -98,7 +99,7 @@ class TragicLessonEffect extends OneShotEffect { Cost cost = new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(filter)); if (cost.canPay(source, source.getSourceId(), controller.getId(), game)) { if (cost.pay(source, game, source.getSourceId(), controller.getId(), false, null)) { - return true; + return true; } } } diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index d44af937ffc..e1895efa3ce 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -134,9 +134,11 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Supreme Will", 49, Rarity.UNCOMMON, mage.cards.s.SupremeWill.class)); cards.add(new SetCardInfo("Swamp", 187, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.BFZ_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Swarm Intelligence", 50, Rarity.RARE, mage.cards.s.SwarmIntelligence.class)); + cards.add(new SetCardInfo("Tenacious Hunter", 136, Rarity.UNCOMMON, mage.cards.t.TenaciousHunter.class)); cards.add(new SetCardInfo("The Locust God", 139, Rarity.MYTHIC, mage.cards.t.TheLocustGod.class)); cards.add(new SetCardInfo("The Scarab God", 145, Rarity.MYTHIC, mage.cards.t.TheScarabGod.class)); cards.add(new SetCardInfo("The Scorpion God", 146, Rarity.MYTHIC, mage.cards.t.TheScorpionGod.class)); + cards.add(new SetCardInfo("Thorned Moloch", 108, Rarity.COMMON, mage.cards.t.ThornedMoloch.class)); cards.add(new SetCardInfo("Torment of Hailfire", 77, Rarity.RARE, mage.cards.t.TormentOfHailfire.class)); cards.add(new SetCardInfo("Torment of Scarabs", 78, Rarity.UNCOMMON, mage.cards.t.TormentOfScarabs.class)); cards.add(new SetCardInfo("Torment of Venom", 79, Rarity.COMMON, mage.cards.t.TormentOfVenom.class)); From 7028f8ee3d75fce0d2534508e44b87cd705e1f65 Mon Sep 17 00:00:00 2001 From: igoudt Date: Sun, 2 Jul 2017 15:36:18 +0200 Subject: [PATCH 09/18] implement Chaos Maw --- Mage.Sets/src/mage/cards/c/ChaosMaw.java | 36 +++++++++++++++++++ .../src/mage/sets/HourOfDevastation.java | 1 + .../test/cards/single/hou/ChaosMawTest.java | 28 +++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/ChaosMaw.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/hou/ChaosMawTest.java diff --git a/Mage.Sets/src/mage/cards/c/ChaosMaw.java b/Mage.Sets/src/mage/cards/c/ChaosMaw.java new file mode 100644 index 00000000000..32cb6aaf007 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChaosMaw.java @@ -0,0 +1,36 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamageAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; + +import java.util.UUID; + +public class ChaosMaw extends CardImpl { + private static FilterCreaturePermanent filter = new FilterCreaturePermanent("other creature"); + static { + filter.add(new AnotherPredicate()); + } + public ChaosMaw(UUID ownerId, CardSetInfo cardSetInfo){ + super(ownerId, cardSetInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); + subtype.add("Hellion"); + power = new MageInt(6); + toughness = new MageInt(6); + + // When Chaos Maw enters the battlefield, it deals 3 damage to each other creature + addAbility(new EntersBattlefieldTriggeredAbility(new DamageAllEffect(3, filter))); + } + + public ChaosMaw(final ChaosMaw chaosMaw){ + super(chaosMaw); + } + + public ChaosMaw copy(){ + return new ChaosMaw(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index bc16f25bcb0..705461134cc 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -76,6 +76,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Carrion Screecher", 61, Rarity.COMMON, mage.cards.c.CarrionScreecher.class)); cards.add(new SetCardInfo("Champion of Wits", 31, Rarity.RARE, mage.cards.c.ChampionOfWits.class)); cards.add(new SetCardInfo("Chandra's Defeat", 86, Rarity.UNCOMMON, mage.cards.c.ChandrasDefeat.class)); + cards.add(new SetCardInfo("Chaos Maw", 87, Rarity.RARE, mage.cards.c.ChaosMaw.class)); cards.add(new SetCardInfo("Cinder Barrens", 209, Rarity.COMMON, mage.cards.c.CinderBarrens.class)); cards.add(new SetCardInfo("Claim // Fame", 150, Rarity.UNCOMMON, mage.cards.c.ClaimFame.class)); cards.add(new SetCardInfo("Crook of Condemnation", 159, Rarity.UNCOMMON, mage.cards.c.CrookOfCondemnation.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/ChaosMawTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/ChaosMawTest.java new file mode 100644 index 00000000000..33084c51548 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/hou/ChaosMawTest.java @@ -0,0 +1,28 @@ +package org.mage.test.cards.single.hou; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class ChaosMawTest extends CardTestPlayerBase { + + private String chaosMaw = "Chaos Maw"; + + @Test + public void testChaosMaw(){ + addCard(Zone.HAND, playerA, chaosMaw, 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 10); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerB, "Savannah Lions", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chaosMaw ); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + + execute(); + + assertGraveyardCount(playerA, "Grizzly Bears", 1); + assertGraveyardCount(playerB, "Savannah Lions", 1); + } +} From c3c09eab2c26dca07bd1ae8269fc4389cf4a0bcb Mon Sep 17 00:00:00 2001 From: spjspj Date: Mon, 3 Jul 2017 00:23:05 +1000 Subject: [PATCH 10/18] Implement 2 cards (HOU) --- .../src/mage/cards/s/SunscourgeChampion.java | 109 ++++++++++++++++++ .../src/mage/cards/s/SurvivorsEncampment.java | 78 +++++++++++++ .../src/mage/sets/HourOfDevastation.java | 2 + 3 files changed, 189 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SunscourgeChampion.java create mode 100644 Mage.Sets/src/mage/cards/s/SurvivorsEncampment.java diff --git a/Mage.Sets/src/mage/cards/s/SunscourgeChampion.java b/Mage.Sets/src/mage/cards/s/SunscourgeChampion.java new file mode 100644 index 00000000000..1b8287d1272 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SunscourgeChampion.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.s; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.EternalizeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author spjspj + */ +public class SunscourgeChampion extends CardImpl { + + private static String rule = "Eternalize - {2}{W}{W}, Discard a card ({2}{W}{W}, Discard a card, Exile this card from your graveyard: Create a token that's a copy of it, except it's a 4/4 black Zombie"; + + public SunscourgeChampion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add("Human"); + this.subtype.add("Wizard"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // When Sunscourge Champion enters the battlefield, you gain life equal to its power. + this.addAbility(new EntersBattlefieldTriggeredAbility(new SunscourgeChampionEffect(), false)); + + // Eternalize - {2}{W}{W}, Discard a card. + EternalizeAbility ability = new EternalizeAbility(new ManaCostsImpl("{2}{W}{W}"), this, rule); + ability.addCost(new DiscardCardCost()); + this.addAbility(ability); + } + + public SunscourgeChampion(final SunscourgeChampion card) { + super(card); + } + + @Override + public SunscourgeChampion copy() { + return new SunscourgeChampion(this); + } +} + +class SunscourgeChampionEffect extends OneShotEffect { + + public SunscourgeChampionEffect() { + super(Outcome.Benefit); + staticText = "you gain life equal to its power."; + } + + public SunscourgeChampionEffect(final SunscourgeChampionEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller != null && permanent != null && sourceObject != null) { + controller.gainLife(permanent.getPower().getValue(), game); + return true; + } + return false; + } + + @Override + public SunscourgeChampionEffect copy() { + return new SunscourgeChampionEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SurvivorsEncampment.java b/Mage.Sets/src/mage/cards/s/SurvivorsEncampment.java new file mode 100644 index 00000000000..004a584646d --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SurvivorsEncampment.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.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import static mage.cards.s.SpellstutterSprite.filter; +import mage.constants.CardType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author spjspj + */ +public class SurvivorsEncampment extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped creature you control"); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public SurvivorsEncampment(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + this.subtype.add("Desert"); + + // {T}: Add {C} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + + // {T}, Tap an untapped creature you control: Add one mana of any color to your mana pool. + Ability ability = new AnyColorManaAbility(); + ability.addCost(new TapTargetCost(new TargetControlledPermanent(filter))); + this.addAbility(ability); + } + + public SurvivorsEncampment(final SurvivorsEncampment card) { + super(card); + } + + @Override + public SurvivorsEncampment copy() { + return new SurvivorsEncampment(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index e1895efa3ce..4644a6b653c 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -130,8 +130,10 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Steadfast Sentinel", 24, Rarity.COMMON, mage.cards.s.SteadfastSentinel.class)); cards.add(new SetCardInfo("Strategic Planning", 47, Rarity.COMMON, mage.cards.s.StrategicPlanning.class)); cards.add(new SetCardInfo("Struggle // Survive", 151, Rarity.UNCOMMON, mage.cards.s.StruggleSurvive.class)); + cards.add(new SetCardInfo("Sunscourge Champion", 26, Rarity.UNCOMMON, mage.cards.s.SunscourgeChampion.class)); cards.add(new SetCardInfo("Sunset Pyramid", 166, Rarity.UNCOMMON, mage.cards.s.SunsetPyramid.class)); cards.add(new SetCardInfo("Supreme Will", 49, Rarity.UNCOMMON, mage.cards.s.SupremeWill.class)); + cards.add(new SetCardInfo("Survivors' Encampment", 184, Rarity.COMMON, mage.cards.s.SurvivorsEncampment.class)); cards.add(new SetCardInfo("Swamp", 187, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.BFZ_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Swarm Intelligence", 50, Rarity.RARE, mage.cards.s.SwarmIntelligence.class)); cards.add(new SetCardInfo("Tenacious Hunter", 136, Rarity.UNCOMMON, mage.cards.t.TenaciousHunter.class)); From 3debc25a5602a176a5b118ebd30cde4bcdf97be0 Mon Sep 17 00:00:00 2001 From: nickymikail Date: Sun, 2 Jul 2017 10:04:34 -0700 Subject: [PATCH 11/18] suggested fixes --- Mage.Sets/src/mage/cards/l/LurchingRotbeast.java | 2 +- Mage.Sets/src/mage/cards/o/OketrasAvenger.java | 4 ++-- Mage.Sets/src/mage/cards/r/RuinRat.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Mage.Sets/src/mage/cards/l/LurchingRotbeast.java b/Mage.Sets/src/mage/cards/l/LurchingRotbeast.java index 72cc70c41c1..994daf31c6a 100644 --- a/Mage.Sets/src/mage/cards/l/LurchingRotbeast.java +++ b/Mage.Sets/src/mage/cards/l/LurchingRotbeast.java @@ -38,7 +38,7 @@ import mage.constants.CardType; /** * - * @author anonymous + * @author nickymikail */ public class LurchingRotbeast extends CardImpl { diff --git a/Mage.Sets/src/mage/cards/o/OketrasAvenger.java b/Mage.Sets/src/mage/cards/o/OketrasAvenger.java index 9d994c96cf0..1f0e4cc1711 100644 --- a/Mage.Sets/src/mage/cards/o/OketrasAvenger.java +++ b/Mage.Sets/src/mage/cards/o/OketrasAvenger.java @@ -27,8 +27,6 @@ */ package mage.cards.o; -import java.util.UUID; - import mage.MageInt; import mage.abilities.common.BecomesExertSourceTriggeredAbility; import mage.abilities.effects.common.PreventCombatDamageToSourceEffect; @@ -38,6 +36,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import java.util.UUID; + /** * * @author nickymikail diff --git a/Mage.Sets/src/mage/cards/r/RuinRat.java b/Mage.Sets/src/mage/cards/r/RuinRat.java index e63e6c0b49e..db5f2802aea 100644 --- a/Mage.Sets/src/mage/cards/r/RuinRat.java +++ b/Mage.Sets/src/mage/cards/r/RuinRat.java @@ -41,7 +41,7 @@ import mage.constants.CardType; /** * - * @author anonymous + * @author nickymikail */ public class RuinRat extends CardImpl { From 8e4f47894692baf311e403e86201c2d273416f04 Mon Sep 17 00:00:00 2001 From: spjspj Date: Mon, 3 Jul 2017 09:08:24 +1000 Subject: [PATCH 12/18] Implement 2 cards (HOU) --- .../main/java/mage/abilities/keyword/EternalizeAbility.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Mage/src/main/java/mage/abilities/keyword/EternalizeAbility.java b/Mage/src/main/java/mage/abilities/keyword/EternalizeAbility.java index 28d9aec01c7..0fa338038b0 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EternalizeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EternalizeAbility.java @@ -58,6 +58,11 @@ public class EternalizeAbility extends ActivatedAbilityImpl { this.timing = TimingRule.SORCERY; setRule(cost, card); } + + public EternalizeAbility(Cost cost, Card card, String rule) { + this(cost, card); + this.rule = rule; + } public EternalizeAbility(final EternalizeAbility ability) { super(ability); From a3ea1a8f498205c56f91f98ca7bd9dd823984248 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 3 Jul 2017 08:58:48 +0200 Subject: [PATCH 13/18] [HOU] Added 2 cards. --- .../src/mage/cards/a/AppealAuthority.java | 91 +++++++++++++++++++ .../src/mage/cards/b/BurningFistMinotaur.java | 75 +++++++++++++++ .../src/mage/cards/c/ConsignOblivion.java | 61 +++++++++++++ .../src/mage/sets/HourOfDevastation.java | 2 + Utils/cardClass.tmpl | 4 +- Utils/cardSplitClass.tmpl | 11 ++- Utils/gen-card.pl | 8 +- Utils/mtg-cards-data.txt | 10 +- 8 files changed, 248 insertions(+), 14 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/a/AppealAuthority.java create mode 100644 Mage.Sets/src/mage/cards/b/BurningFistMinotaur.java create mode 100644 Mage.Sets/src/mage/cards/c/ConsignOblivion.java diff --git a/Mage.Sets/src/mage/cards/a/AppealAuthority.java b/Mage.Sets/src/mage/cards/a/AppealAuthority.java new file mode 100644 index 00000000000..b8acda0f7b3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AppealAuthority.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.cards.a; + +import java.util.UUID; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.AftermathAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SpellAbilityType; +import mage.constants.TargetController; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class AppealAuthority extends SplitCard { + + public AppealAuthority(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, new CardType[]{CardType.SORCERY}, "{G}", "{1}{W}", SpellAbilityType.SPLIT_AFTERMATH); + + // Appeal + // Until end of turn, target creature gains trample and gets +X/+X, where X is the number of creatures you control. + getLeftHalfCard().getSpellAbility().addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn) + .setText("Until end of turn, target creature gains trample")); + DynamicValue controlledCreatures = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent("the number of creatures you control")); + getLeftHalfCard().getSpellAbility().addEffect(new BoostTargetEffect(controlledCreatures, controlledCreatures, Duration.EndOfTurn, true) + .setText("and gets +X/+X, where X is the number of creatures you control")); + getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Authority + // Aftermath + ((CardImpl) (getRightHalfCard())).addAbility(new AftermathAbility().setRuleAtTheTop(true)); + // Tap up to two target creatures your opponents control. Creatures you control gain vigilance until end of turn. + getRightHalfCard().getSpellAbility().addEffect(new TapTargetEffect()); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures your opponents control"); + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2, filter, false)); + getRightHalfCard().getSpellAbility().addEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), + Duration.EndOfTurn, new FilterControlledCreaturePermanent("creatures"))); + + } + + public AppealAuthority(final AppealAuthority card) { + super(card); + } + + @Override + public AppealAuthority copy() { + return new AppealAuthority(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BurningFistMinotaur.java b/Mage.Sets/src/mage/cards/b/BurningFistMinotaur.java new file mode 100644 index 00000000000..518d7b2b50b --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BurningFistMinotaur.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.cards.b; + +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.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class BurningFistMinotaur extends CardImpl { + + public BurningFistMinotaur(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add("Minotaur"); + this.subtype.add("Wizard"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // {1}{R}, Discard a card: Burning-Fist Minotaur gets +2/+0 until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(2, 0, Duration.EndOfTurn), new ManaCostsImpl("{1}{R}")); + ability.addCost(new DiscardCardCost()); + this.addAbility(ability); + } + + public BurningFistMinotaur(final BurningFistMinotaur card) { + super(card); + } + + @Override + public BurningFistMinotaur copy() { + return new BurningFistMinotaur(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ConsignOblivion.java b/Mage.Sets/src/mage/cards/c/ConsignOblivion.java new file mode 100644 index 00000000000..99ece4cefaf --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ConsignOblivion.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.cards.c; + +import java.util.UUID; + +import mage.cards.CardSetInfo; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.SpellAbilityType; + +/** + * + * @author LevelX2 + */ +public class ConsignOblivion extends SplitCard { + + public ConsignOblivion(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{}, new CardType[]{}, "", "", SpellAbilityType.SPLIT_AFTERMATH); + + + getLeftHalfCard().getSpellAbility().addEffect(new Effect...); + + getRightHalfCard().getSpellAbility().addEffect(new Effect...); + + } + + public ConsignOblivion(final ConsignOblivion card) { + super(card); + } + + @Override + public ConsignOblivion copy() { + return new ConsignOblivion(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index d44af937ffc..bc99d5ab902 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -69,9 +69,11 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Adorned Pouncer", 2, Rarity.RARE, mage.cards.a.AdornedPouncer.class)); cards.add(new SetCardInfo("Angel of Condemnation", 3, Rarity.RARE, mage.cards.a.AngelOfCondemnation.class)); cards.add(new SetCardInfo("Angel of the God-Pharaoh", 4, Rarity.UNCOMMON, mage.cards.a.AngelOfTheGodPharaoh.class)); + cards.add(new SetCardInfo("Appeal // Authority", 152, Rarity.UNCOMMON, mage.cards.a.AppealAuthority.class)); cards.add(new SetCardInfo("Avid Reclaimer", 201, Rarity.UNCOMMON, mage.cards.a.AvidReclaimer.class)); cards.add(new SetCardInfo("Bontu's Last Reckoning", 60, Rarity.RARE, mage.cards.b.BontusLastReckoning.class)); cards.add(new SetCardInfo("Brambleweft Behemoth", 202, Rarity.COMMON, mage.cards.b.BrambleweftBehemoth.class)); + cards.add(new SetCardInfo("Burning-Fist Minotaur", 85, Rarity.UNCOMMON, mage.cards.b.BurningFistMinotaur.class)); cards.add(new SetCardInfo("Carrion Screecher", 61, Rarity.COMMON, mage.cards.c.CarrionScreecher.class)); cards.add(new SetCardInfo("Champion of Wits", 31, Rarity.RARE, mage.cards.c.ChampionOfWits.class)); cards.add(new SetCardInfo("Chandra's Defeat", 86, Rarity.UNCOMMON, mage.cards.c.ChandrasDefeat.class)); diff --git a/Utils/cardClass.tmpl b/Utils/cardClass.tmpl index 27c2518e07a..e5afa68f0aa 100644 --- a/Utils/cardClass.tmpl +++ b/Utils/cardClass.tmpl @@ -29,7 +29,7 @@ package mage.cards.[=$cardNameFirstLetter=]; import java.util.UUID;[= if ($power || $power eq 0) { - if ($planeswalker) { + if ($planeswalker eq 'true') { $OUT .= "\nimport mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility;" }else { $OUT .= "\nimport mage.MageInt;" @@ -50,7 +50,7 @@ public class [=$className=] extends CardImpl { super(ownerId, setInfo, new CardType[]{[=$type=]}, "[=$manaCost=]"); [=$subType=][=$colors=][= if ($power || $power eq 0) { - if ($planeswalker) { + if ($planeswalker eq 'true') { $OUT .= "\n this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility($power));"; } else { $OUT .= "\n this.power = new MageInt($power);"; diff --git a/Utils/cardSplitClass.tmpl b/Utils/cardSplitClass.tmpl index 478db2e8ca1..ca0c7bcf708 100644 --- a/Utils/cardSplitClass.tmpl +++ b/Utils/cardSplitClass.tmpl @@ -32,6 +32,7 @@ import java.util.UUID; import mage.cards.CardSetInfo; import mage.cards.SplitCard; import mage.constants.CardType; +import mage.constants.SpellAbilityType; /** * @@ -40,16 +41,18 @@ import mage.constants.CardType; public class [=$className=] extends SplitCard { public [=$className=](UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{[=$type=]}, "[=$manaCost=]"); - [=$subType=][=$colors=] - - // super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{3}{R}", "{2}{U}", SpellAbilityType.SPLIT_AFTERMATH); + super(ownerId, setInfo, new CardType[]{[=$type=]}, new CardType[]{[=$type=]}, "[=$manaCost=]", "[=$manaCost=]", SpellAbilityType.SPLIT_AFTERMATH); + [=$subType=][=$colors=] [= if ($power || $power eq 0) { $OUT .= "\n this.power = new MageInt($power);"; $OUT .= "\n this.toughness = new MageInt($toughness);"; } =][=$abilities=] + getLeftHalfCard().getSpellAbility().addEffect(new Effect...); + + getRightHalfCard().getSpellAbility().addEffect(new Effect...); + } public [=$className=](final [=$className=] card) { diff --git a/Utils/gen-card.pl b/Utils/gen-card.pl index ceba5aac54e..62529529c79 100755 --- a/Utils/gen-card.pl +++ b/Utils/gen-card.pl @@ -174,12 +174,13 @@ foreach my $setName (keys %{$cards{$cardName}}) { unlink $setFileName.".bak"; print "$setFileName\n"; } - -# Generate the the card +print "Generate the card: ".$card[0]."\n"; +# Generate the card my $result; my $template = Text::Template->new(TYPE => 'FILE', SOURCE => $cardTemplate, DELIMITERS => [ '[=', '=]' ]); $vars{'author'} = $author; $vars{'manaCost'} = fixCost($card[4]); +print "cost ".$vars{'manaCost'}."\n"; $vars{'power'} = $card[6]; $vars{'toughness'} = $card[7]; @@ -190,7 +191,8 @@ my $cardAbilities = $card[8]; my $type = $card[5]; while ($type =~ m/([a-zA-Z]+)( )*/g) { if (exists($cardTypes{$1})) { - push(@types, $cardTypes{$1}); + push(@types, $cardTypes{$1}); +print $cardTypes{$1}."\n"; if ($cardTypes{$1} eq $cardTypes{'Planeswalker'}) { $vars{'planeswalker'} = 'true'; $cardAbilities = $card[7]; diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 4ac72960987..97b60e3474d 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -31651,7 +31651,7 @@ Solemnity|Hour of Devastation|22|R|{2}{W}|Enchantment|||Players can't get counte Solitary Camel|Hour of Devastation|23|C|{2}{W}|Creature - Camel|3|2|Solitary Camel has lifelink as long as you control a desert or there is a desert card in your graveyard. (Damage this creature deals also causes you to gain that much life.)| Steadfast Sentinel|Hour of Devastation|24|C|{3}{W}|Creature - Human Cleric|2|3|Vigilance$Eternalize {4}{W}{W} ({4}{W}{W}, Exile this card from your graveyard: Create a token that's a copy of it, except it's 4/4 black Zombie Human Cleric with no mana cost. Eternalize only as a sorcery.)| Steward of Solidarity|Hour of Devastation|25|U|{1}{W}|Creature - Human Warrior|2|2|{T}, Exert Steward of Solidarity: Create a 1/1 white Warrior creature token with vigilance. (An exerted creature won't untap during your next untap step.)| -Sunscourge Champion|Hour of Devastation|26|U|{2}{W}|Creature - Human Wizard|2|3|When Sunscourge Champion enters the battlefield, you gain life equal to its power.$Eternalize—{2}{W}{W}, Discard a card. ({2}{W}{W}, Discard a card, Exile this card from your graveyard: Create a token that's a copy of it, except it's a 4/4 black Zombie Human Wizard with no mana cost. Eternalize only as a sorcery.)| +Sunscourge Champion|Hour of Devastation|26|U|{2}{W}|Creature - Human Wizard|2|3|When Sunscourge Champion enters the battlefield, you gain life equal to its power.$Eternalize�{2}{W}{W}, Discard a card. ({2}{W}{W}, Discard a card, Exile this card from your graveyard: Create a token that's a copy of it, except it's a 4/4 black Zombie Human Wizard with no mana cost. Eternalize only as a sorcery.)| Unconventional Tactics|Hour of Devastation|27|U|{2}{W}|Sorcery|||Target creature gets +3/+3 and gains flying until end of turn.$Whenever a Zombie enters the battlefield under your control, you may pay {W}. If you do, return Unconventional Tactics from your graveyard to your hand.| Vizier of the True|Hour of Devastation|28|U|{3}{W}|Creature - Human Cleric|3|2|You may exert Vizier of the True as it attacks. (It won't untap during your next untap step.)$Whenever you exert a creature, tap target creature an opponent controls.| Aerial Guide|Hour of Devastation|29|C|{2}{U}|Creature - Drake|2|2|Flying$Whenever Aerial Guide attacks, another target attacking creature gains flying until end of turn.| @@ -31670,11 +31670,11 @@ Ominous Sphinx|Hour of Devastation|41|U|{3}{U}{U}|Creature - Sphinx|4|4|Flying$W Proven Combatant|Hour of Devastation|42|C|{U}|Creature - Human Warrior|1|1|Eternalize {4}{U}{U} ({4}{U}{U}, Exile this card from your graveyard: Create a token that's a copy of it, except it's a 4/4 black Zombie Human Warrior with no mana cost. Eternalize only as a sorcery.) | Riddleform|Hour of Devastation|43|U|{1}{U}|Enchantment|||Whenever you cast a noncreature spell, you may have Riddleform become a 3/3 Sphinx creature with flying in addition to its other types until end of turn.${2}{U}: Scry 1.| Seer of the Last Tomorrow|Hour of Devastation|44|C|{2}{U}|Creature - Naga Cleric|1|4|{U}, {T}, Discard a card: Target player puts the top three cards of his or her library into his or her graveyard.| -Sinuous Striker|Hour of Devastation|45|U|{2}{U}|Creature - Naga Warrior|2|2|{U}: Sinuous Striker gets +1/-1 until end of turn.$Eternalize—{3}{U}{U}, Discard a card. ({3}{U}{U}, Discard a card, Exile this card from your graveyard: Create a token that's a copy of it, except it's a 4/4 black Zombie Naga Warrior with no mana cost. Eternalize only as a sorcery.)| +Sinuous Striker|Hour of Devastation|45|U|{2}{U}|Creature - Naga Warrior|2|2|{U}: Sinuous Striker gets +1/-1 until end of turn.$Eternalize�{3}{U}{U}, Discard a card. ({3}{U}{U}, Discard a card, Exile this card from your graveyard: Create a token that's a copy of it, except it's a 4/4 black Zombie Naga Warrior with no mana cost. Eternalize only as a sorcery.)| Spellweaver Eternal|Hour of Devastation|46|C|{1}{U}|Creature - Zombie Naga Wizard|2|1|Prowess (Whenever you cast a noncreature spell, this creature gets +1/+1 until end of turn.)$Afflict 2 (Whenever this creature becomes blocked, defending player loses 2 life.)| Strategic Planning|Hour of Devastation|47|C|{1}{U}|Sorcery|||Look at the top three cards of your library. Put one of them into your hand and the rest in the graveyard.| Striped Riverwinder|Hour of Devastation|48|C|{6}{U}|Creature - Serpent|5|5|Hexproof (This creature can't be the target of spells or abilities your opponents control.)$Cycling {U} ({U}, Discard this card: Draw a card.)| -Supreme Will|Hour of Devastation|49|U|{2}{U}|Instant|||Choose one —$• Counter target spell unless its controller pays {3}.$• Look at the top four cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order.| +Supreme Will|Hour of Devastation|49|U|{2}{U}|Instant|||Choose one �$� Counter target spell unless its controller pays {3}.$� Look at the top four cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order.| Swarm Intelligence|Hour of Devastation|50|R|{6}{U}|Enchantment|||Whenever you cast an instant or sorcery spell, you may copy that spell. You may choose new targets for the copy.| Tragic Lesson|Hour of Devastation|51|C|{2}{U}|Instant|||Draw two cards. Then discard a card unless you return a land you control to its owner's hand.| Unesh, Criosphinx Sovereign|Hour of Devastation|52|M|{4}{U}{U}|Legendary Creature - Sphinx|4|4|Flying$Sphinx spells you cast cost {2} less to cast.$Whenever Unesh, Criosphinx Sovereign or another Sphinx enters the battlefield under your control, reveal the top four cards of your library. An opponent seperates those cards into two piles. Put one pile into your hand and the other into your graveyard.| @@ -31687,7 +31687,7 @@ Apocalypse Demon|Hour of Devastation|58|R|{4}{B}{B}|Creature - Demon|0|0|Flying$ Banewhip Punisher|Hour of Devastation|59|U|{2}{B}|Creature - Human Warrior|2|2|When Banewhip Punisher enters the battlefield, you may put a -1/-1 counter on target creature.${B}, Sacrifice Banewhip Punisher: Destroy target creature that has a -1/-1 counter on it.| Bontu's Last Reckoning|Hour of Devastation|60|R|{1}{B}{B}|Sorcery|||Destroy all creatures. Lands you control don't untap during your next untap step.| Carrion Screecher|Hour of Devastation|61|C|{3}{B}|Creature - Zombie Bird|3|1|Flying| -Doomfall|Hour of Devastation|62|U|{2}{B}|Sorcery|||Choose one —$• Target player exiles a creature he or she controls.$• Target opponent reveals his or her hand. You choose a nonland card from it. Exile that card.| +Doomfall|Hour of Devastation|62|U|{2}{B}|Sorcery|||Choose one �$� Target player exiles a creature he or she controls.$� Target opponent reveals his or her hand. You choose a nonland card from it. Exile that card.| Dreamstealer|Hour of Devastation|63|R|{2}{B}|Creature - Human Wizard|1|2|Menace$When Dreamstealer deals combat damage to a player, that player discards that many cards.$Eternalize {4}{B}{B} ({4}{B}{B}, Exile this card from your graveyard: Create a token that's a copy of it, except it's 4/4 black Zombie Human Wizard with no mana cost. Eternalize only as a sorcery.)| Grisly Survivor|Hour of Devastation|64|C|{2}{B}|Creature - Minotaur Warrior|2|3|Whenever you cycle or discard a card, Grisly Survivor gets +2/+0 until end of turn.| Hour of Glory|Hour of Devastation|65|R|{3}{B}|Instant|||Exile target creature. If that creature was a God, its controller reveals his or her hand and exiles all cards with the same name as that creature.| @@ -31779,7 +31779,7 @@ Claim // Fame|Hour of Devastation|150|U|{B}|Sorcery|||Return target creature car Struggle // Survive|Hour of Devastation|151|U|{2}{R}|Instant|||Struggle deals damage to target creature equal to the number of lands you control.$Survive {1}{G}$Sorcery$Aftermath (Cast this spell only from your graveyard. Then exile it.)$Each player shuffles his or graveyard into his or her library.| Appeal // Authority|Hour of Devastation|152|U|{G}|Sorcery|||Until end of turn, target creature gains trample and gets +X/+X, where X is the number of creatures you control.$Authority {1}{W}$Sorcery$Aftermath (Cast this spell only from your graveyard. Then exile it.)$Tap up to two target creatures your opponents control. Creatures you control gain vigilance until end of turn.| Leave // Chance|Hour of Devastation|153|R|{1}{W}|Instant|||Return any number of target permanents you own to your hand.$Chance {3}{R}$Sorcery$Aftermath (Cast this spell only from your graveyard. Then exile it.)$Discard any number of cards, then draw that many cards.| -Reason // Live|Hour of Devastation|154|R|{U}|Sorcery|||Scry 3.$Believe {4}{G}$Sorcery$Aftermath$Look at the top card of your library. You may put it onto the battlefield if it's a creature card. If you don't, put it into your hand.| +Reason // Believe|Hour of Devastation|154|R|{U}|Sorcery|||Scry 3.$Believe {4}{G}$Sorcery$Aftermath$Look at the top card of your library. You may put it onto the battlefield if it's a creature card. If you don't, put it into your hand.| Grind // Dust|Hour of Devastation|155|R|{1}{B}|Sorcery|||Put a -1/-1 counter on each of up to two target creatures.$Dust {3}{W}$Sorcery$Aftermath (Cast this spell only from your graveyard. Then exile it.)$Exile any number of target creatures that have -1/-1 counters on them.| Refuse // Cooperate|Hour of Devastation|156|R|{3}{R}|Instant|||Refuse deals damage to target spell's controller equal to that spell's converted mana cost.$Cooperate {2}{U}$Instant$Aftermath (Cast this spell only from your graveyard. Then exile it.)$Copy target instant or sorcery spell. You may choose new targets for the copy.| Driven // Despair|Hour of Devastation|157|R|{1}{G}|Sorcery|||Until end of turn, creatures you control gain trample and "Whenever this creature deals combat damage to a player, draw a card."$Despair {1}{B}$Sorcery$Aftermath$Until end of turn, creatures you control gain menace and "Whenever this creature deals combat damage to a player, that player discards a card."| From 7418c01bed80e1077cb2c4593c54be5f0464d2ae Mon Sep 17 00:00:00 2001 From: spjspj Date: Mon, 3 Jul 2017 19:42:53 +1000 Subject: [PATCH 14/18] Implement 5 cards (HOU) --- Mage.Sets/src/mage/cards/s/SifterWurm.java | 113 ++++++++++++++++++ Mage.Sets/src/mage/cards/s/SolitaryCamel.java | 88 ++++++++++++++ .../src/mage/cards/s/SpellweaverEternal.java | 68 +++++++++++ .../src/mage/cards/s/StewardOfSolidarity.java | 76 ++++++++++++ .../src/mage/cards/s/StripedRiverwinder.java | 68 +++++++++++ .../src/mage/sets/HourOfDevastation.java | 5 + 6 files changed, 418 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SifterWurm.java create mode 100644 Mage.Sets/src/mage/cards/s/SolitaryCamel.java create mode 100644 Mage.Sets/src/mage/cards/s/SpellweaverEternal.java create mode 100644 Mage.Sets/src/mage/cards/s/StewardOfSolidarity.java create mode 100644 Mage.Sets/src/mage/cards/s/StripedRiverwinder.java diff --git a/Mage.Sets/src/mage/cards/s/SifterWurm.java b/Mage.Sets/src/mage/cards/s/SifterWurm.java new file mode 100644 index 00000000000..e464f98f742 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SifterWurm.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.s; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author spjspj + */ +public class SifterWurm extends CardImpl { + + public SifterWurm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}"); + + this.subtype.add("Wurm"); + this.power = new MageInt(7); + this.toughness = new MageInt(7); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // When Sifter Wurm enters the battlefield, scry 3, then reveal the top card of your library. You gain life equal to that card's converted mana cost. + Ability ability = new EntersBattlefieldTriggeredAbility(new SifterWurmEffect()); + this.addAbility(ability); + } + + public SifterWurm(final SifterWurm card) { + super(card); + } + + @Override + public SifterWurm copy() { + return new SifterWurm(this); + } +} + +class SifterWurmEffect extends OneShotEffect { + + public SifterWurmEffect() { + super(Outcome.DrawCard); + this.staticText = "scry 3, then reveal the top card of your library. You gain life equal to that card's converted mana cost."; + } + + public SifterWurmEffect(final SifterWurmEffect effect) { + super(effect); + } + + @Override + public SifterWurmEffect copy() { + return new SifterWurmEffect(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.scry(3, source, game); + + Cards cards = new CardsImpl(); + Card card = controller.getLibrary().getFromTop(game); + + if (card != null) { + cards.add(card); + controller.revealCards(sourceObject.getIdName(), cards, game); + controller.gainLife(card.getConvertedManaCost(), game); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SolitaryCamel.java b/Mage.Sets/src/mage/cards/s/SolitaryCamel.java new file mode 100644 index 00000000000..aa74ec73a77 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SolitaryCamel.java @@ -0,0 +1,88 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.OrCondition; +import mage.abilities.condition.common.CardsInControllerGraveCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author spjspj + */ +public class SolitaryCamel extends CardImpl { + + private static final FilterControlledPermanent filterDesertPermanent = new FilterControlledPermanent("Desert"); + private static final FilterCard filterDesertCard = new FilterCard("Desert card"); + + static { + filterDesertPermanent.add(new SubtypePredicate(SubType.DESERT)); + filterDesertCard.add(new SubtypePredicate(SubType.DESERT)); + } + + public SolitaryCamel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add("Camel"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Solitary Camel has lifelink as long as you control a desert or there is a desert card in your graveyard. + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new GainAbilitySourceEffect(LifelinkAbility.getInstance()), + new OrCondition( + new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(filterDesertPermanent)), + new CardsInControllerGraveCondition(1, filterDesertCard)), + "{this} has lifelink as long as you control a desert or there is a desert card in your graveyard.")); + this.addAbility(ability); + } + + public SolitaryCamel(final SolitaryCamel card) { + super(card); + } + + @Override + public SolitaryCamel copy() { + return new SolitaryCamel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpellweaverEternal.java b/Mage.Sets/src/mage/cards/s/SpellweaverEternal.java new file mode 100644 index 00000000000..9068820ff8e --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpellweaverEternal.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.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.AfflictAbility; +import mage.abilities.keyword.ProwessAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author spjspj + */ +public class SpellweaverEternal extends CardImpl { + + public SpellweaverEternal(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add("Zombie"); + this.subtype.add("Naga"); + this.subtype.add("Wizard"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Prowess + this.addAbility(new ProwessAbility()); + + // Afflict 2 + this.addAbility(new AfflictAbility(2)); + } + + public SpellweaverEternal(final SpellweaverEternal card) { + super(card); + } + + @Override + public SpellweaverEternal copy() { + return new SpellweaverEternal(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/StewardOfSolidarity.java b/Mage.Sets/src/mage/cards/s/StewardOfSolidarity.java new file mode 100644 index 00000000000..be2ec94b355 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StewardOfSolidarity.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.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.ExertSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.permanent.token.WarriorVigilantToken; + +/** + * + * @author spjspj + */ +public class StewardOfSolidarity extends CardImpl { + + public StewardOfSolidarity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add("Human"); + this.subtype.add("Warrior"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {T}, Exert Steward of Solidarity: Create a 1/1 white Warrior creature token with vigilance. + Effect effect = new CreateTokenEffect(new WarriorVigilantToken()); + effect.setText("Create a 1/1 white Warrior creature token with vigilance"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("{1}{W}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new ExertSourceCost()); + this.addAbility(ability); + } + + public StewardOfSolidarity(final StewardOfSolidarity card) { + super(card); + } + + @Override + public StewardOfSolidarity copy() { + return new StewardOfSolidarity(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/StripedRiverwinder.java b/Mage.Sets/src/mage/cards/s/StripedRiverwinder.java new file mode 100644 index 00000000000..22674895aa1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StripedRiverwinder.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.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.HexproofAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.keyword.CyclingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author spjspj + */ +public class StripedRiverwinder extends CardImpl { + + public StripedRiverwinder(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{U}"); + + this.subtype.add("Serpent"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Hexproof + this.addAbility(HexproofAbility.getInstance()); + + // Cycling {U} + this.addAbility(new CyclingAbility(new ManaCostsImpl("{U}"))); + + } + + public StripedRiverwinder(final StripedRiverwinder card) { + super(card); + } + + @Override + public StripedRiverwinder copy() { + return new StripedRiverwinder(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index 4644a6b653c..23aa985e361 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -125,10 +125,15 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Sand Strangler", 107, Rarity.UNCOMMON, mage.cards.s.SandStrangler.class)); cards.add(new SetCardInfo("Sandblast", 20, Rarity.COMMON, mage.cards.s.Sandblast.class)); cards.add(new SetCardInfo("Sidewinder Naga", 134, Rarity.COMMON, mage.cards.s.SidewinderNaga.class)); + cards.add(new SetCardInfo("Sifter Wurm", 135, Rarity.UNCOMMON, mage.cards.s.SifterWurm.class)); cards.add(new SetCardInfo("Sinuous Striker", 45, Rarity.UNCOMMON, mage.cards.s.SinuousStriker.class)); cards.add(new SetCardInfo("Solemnity", 22, Rarity.RARE, mage.cards.s.Solemnity.class)); + cards.add(new SetCardInfo("Solitary Camel", 23, Rarity.COMMON, mage.cards.s.SolitaryCamel.class)); + cards.add(new SetCardInfo("Spellweaver Eternal", 46, Rarity.COMMON, mage.cards.s.SpellweaverEternal.class)); cards.add(new SetCardInfo("Steadfast Sentinel", 24, Rarity.COMMON, mage.cards.s.SteadfastSentinel.class)); + cards.add(new SetCardInfo("Steward of Solidarity", 25, Rarity.UNCOMMON, mage.cards.s.StewardOfSolidarity.class)); cards.add(new SetCardInfo("Strategic Planning", 47, Rarity.COMMON, mage.cards.s.StrategicPlanning.class)); + cards.add(new SetCardInfo("Striped Riverwinder", 48, Rarity.COMMON, mage.cards.s.StripedRiverwinder.class)); cards.add(new SetCardInfo("Struggle // Survive", 151, Rarity.UNCOMMON, mage.cards.s.StruggleSurvive.class)); cards.add(new SetCardInfo("Sunscourge Champion", 26, Rarity.UNCOMMON, mage.cards.s.SunscourgeChampion.class)); cards.add(new SetCardInfo("Sunset Pyramid", 166, Rarity.UNCOMMON, mage.cards.s.SunsetPyramid.class)); From c1f7a1086708190a885a72db38bf4199b5f29ead Mon Sep 17 00:00:00 2001 From: spjspj Date: Mon, 3 Jul 2017 20:25:04 +1000 Subject: [PATCH 15/18] Implement 1 card (HOU) --- Mage.Sets/src/mage/cards/s/ShefetDunes.java | 93 +++++++++++++++++++ .../src/mage/sets/HourOfDevastation.java | 1 + 2 files changed, 94 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/ShefetDunes.java diff --git a/Mage.Sets/src/mage/cards/s/ShefetDunes.java b/Mage.Sets/src/mage/cards/s/ShefetDunes.java new file mode 100644 index 00000000000..9af17369650 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShefetDunes.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.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author spjspj + */ +public class ShefetDunes extends CardImpl { + + private static final FilterControlledPermanent filterDesertPermanent = new FilterControlledPermanent("Desert"); + + static { + filterDesertPermanent.add(new SubtypePredicate(SubType.DESERT)); + } + + public ShefetDunes(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + this.subtype.add("Desert"); + + // {T}: Add {C} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + + // {T}, Pay 1 life: Add {W} to your mana pool. + Ability ability = new WhiteManaAbility(); + ability.addCost(new PayLifeCost(1)); + this.addAbility(ability); + + // {2}{W}{W}, {T}, Sacrifice a Desert: Creatures you control get +1/+1 until end of turn. Activate this ability only any time you could cast a sorcery. + Ability ability2 = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect(1, 1, Duration.EndOfTurn), + new ManaCostsImpl("{2}{W}{W}")); + ability2.addCost(new TapSourceCost()); + ability2.addCost(new SacrificeTargetCost(new TargetControlledPermanent(1, 1, filterDesertPermanent, true))); + this.addAbility(ability2); + } + + public ShefetDunes(final ShefetDunes card) { + super(card); + } + + @Override + public ShefetDunes copy() { + return new ShefetDunes(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index 23aa985e361..7976bad23b3 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -124,6 +124,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Samut, the Tested", 144, Rarity.MYTHIC, mage.cards.s.SamutTheTested.class)); cards.add(new SetCardInfo("Sand Strangler", 107, Rarity.UNCOMMON, mage.cards.s.SandStrangler.class)); cards.add(new SetCardInfo("Sandblast", 20, Rarity.COMMON, mage.cards.s.Sandblast.class)); + cards.add(new SetCardInfo("Shefet Dunes", 183, Rarity.UNCOMMON, mage.cards.s.ShefetDunes.class)); cards.add(new SetCardInfo("Sidewinder Naga", 134, Rarity.COMMON, mage.cards.s.SidewinderNaga.class)); cards.add(new SetCardInfo("Sifter Wurm", 135, Rarity.UNCOMMON, mage.cards.s.SifterWurm.class)); cards.add(new SetCardInfo("Sinuous Striker", 45, Rarity.UNCOMMON, mage.cards.s.SinuousStriker.class)); From 01ae2c0e6bbfcefba5e96b75b2acc67c04fa70e3 Mon Sep 17 00:00:00 2001 From: spjspj Date: Mon, 3 Jul 2017 20:38:42 +1000 Subject: [PATCH 16/18] Implement 1 card (HOU) --- .../mage/cards/s/SeerOfTheLastTomorrow.java | 72 +++++++++++++++++++ .../src/mage/sets/HourOfDevastation.java | 1 + 2 files changed, 73 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SeerOfTheLastTomorrow.java diff --git a/Mage.Sets/src/mage/cards/s/SeerOfTheLastTomorrow.java b/Mage.Sets/src/mage/cards/s/SeerOfTheLastTomorrow.java new file mode 100644 index 00000000000..497799b1de0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SeerOfTheLastTomorrow.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.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.TargetPlayer; + +/** + * + * @author spjspj + */ +public class SeerOfTheLastTomorrow extends CardImpl { + + public SeerOfTheLastTomorrow(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add("Naga"); + this.subtype.add("Cleric"); + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // {U}, {T}, Discard a card: Target player puts the top three cards of his or her library into his or her graveyard. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(3), new ManaCostsImpl("{U}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public SeerOfTheLastTomorrow(final SeerOfTheLastTomorrow card) { + super(card); + } + + @Override + public SeerOfTheLastTomorrow copy() { + return new SeerOfTheLastTomorrow(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index b2e41911a56..3b6358652c6 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -130,6 +130,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Samut, the Tested", 144, Rarity.MYTHIC, mage.cards.s.SamutTheTested.class)); cards.add(new SetCardInfo("Sand Strangler", 107, Rarity.UNCOMMON, mage.cards.s.SandStrangler.class)); cards.add(new SetCardInfo("Sandblast", 20, Rarity.COMMON, mage.cards.s.Sandblast.class)); + cards.add(new SetCardInfo("Seer of the Last Tomorrow", 44, Rarity.COMMON, mage.cards.s.SeerOfTheLastTomorrow.class)); cards.add(new SetCardInfo("Shefet Dunes", 183, Rarity.UNCOMMON, mage.cards.s.ShefetDunes.class)); cards.add(new SetCardInfo("Scrounger of Souls", 76, Rarity.COMMON, mage.cards.s.ScroungerOfSouls.class)); cards.add(new SetCardInfo("Sidewinder Naga", 134, Rarity.COMMON, mage.cards.s.SidewinderNaga.class)); From 422afec3fe85d1ea4b0b43631c8ff2d55cfeb859 Mon Sep 17 00:00:00 2001 From: spjspj Date: Mon, 3 Jul 2017 20:58:42 +1000 Subject: [PATCH 17/18] Implement 1 card (HOU) --- .../src/mage/cards/s/ScavengerGrounds.java | 85 +++++++++++++++++++ .../mage/cards/s/SeerOfTheLastTomorrow.java | 2 + .../src/mage/sets/HourOfDevastation.java | 1 + 3 files changed, 88 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/ScavengerGrounds.java diff --git a/Mage.Sets/src/mage/cards/s/ScavengerGrounds.java b/Mage.Sets/src/mage/cards/s/ScavengerGrounds.java new file mode 100644 index 00000000000..87895e496ed --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScavengerGrounds.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.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.ExileGraveyardAllPlayersEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author spjspj + */ +public class ScavengerGrounds extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("Desert"); + + static { + filter.add(new SubtypePredicate(SubType.DESERT)); + } + + public ScavengerGrounds(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + this.subtype.add("Desert"); + + // {T}: Add {C} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + + // {2}, {T}, Sacrifice a Desert: Exile all cards from all graveyards. + Ability ability2 = new SimpleActivatedAbility( + Zone.BATTLEFIELD, + new ExileGraveyardAllPlayersEffect(), + new ManaCostsImpl("{2}")); + ability2.addCost(new TapSourceCost()); + ability2.addCost(new SacrificeTargetCost(new TargetControlledPermanent(1, 1, filter, true))); + this.addAbility(ability2); + } + + public ScavengerGrounds(final ScavengerGrounds card) { + super(card); + } + + @Override + public ScavengerGrounds copy() { + return new ScavengerGrounds(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SeerOfTheLastTomorrow.java b/Mage.Sets/src/mage/cards/s/SeerOfTheLastTomorrow.java index 497799b1de0..459548306f9 100644 --- a/Mage.Sets/src/mage/cards/s/SeerOfTheLastTomorrow.java +++ b/Mage.Sets/src/mage/cards/s/SeerOfTheLastTomorrow.java @@ -31,6 +31,7 @@ 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.PutLibraryIntoGraveTargetEffect; @@ -57,6 +58,7 @@ public class SeerOfTheLastTomorrow extends CardImpl { // {U}, {T}, Discard a card: Target player puts the top three cards of his or her library into his or her graveyard. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(3), new ManaCostsImpl("{U}")); ability.addCost(new TapSourceCost()); + ability.addCost(new DiscardCardCost()); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index 3b6358652c6..e14f68a7382 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -130,6 +130,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Samut, the Tested", 144, Rarity.MYTHIC, mage.cards.s.SamutTheTested.class)); cards.add(new SetCardInfo("Sand Strangler", 107, Rarity.UNCOMMON, mage.cards.s.SandStrangler.class)); cards.add(new SetCardInfo("Sandblast", 20, Rarity.COMMON, mage.cards.s.Sandblast.class)); + cards.add(new SetCardInfo("Scavenger Grounds", 182, Rarity.RARE, mage.cards.s.ScavengerGrounds.class)); cards.add(new SetCardInfo("Seer of the Last Tomorrow", 44, Rarity.COMMON, mage.cards.s.SeerOfTheLastTomorrow.class)); cards.add(new SetCardInfo("Shefet Dunes", 183, Rarity.UNCOMMON, mage.cards.s.ShefetDunes.class)); cards.add(new SetCardInfo("Scrounger of Souls", 76, Rarity.COMMON, mage.cards.s.ScroungerOfSouls.class)); From 1e1321be143542b2441d56106fc2de30edd547d3 Mon Sep 17 00:00:00 2001 From: spjspj Date: Mon, 3 Jul 2017 23:43:23 +1000 Subject: [PATCH 18/18] Implement 1 card (HOU) --- Mage.Sets/src/mage/cards/s/SavingGrace.java | 176 ++++++++++++++++++ .../src/mage/sets/HourOfDevastation.java | 1 + 2 files changed, 177 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SavingGrace.java diff --git a/Mage.Sets/src/mage/cards/s/SavingGrace.java b/Mage.Sets/src/mage/cards/s/SavingGrace.java new file mode 100644 index 00000000000..287520243cd --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SavingGrace.java @@ -0,0 +1,176 @@ +/* + * 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.keyword.FlashAbility; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.DamageEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author spjspj + */ +public class SavingGrace extends CardImpl { + + public SavingGrace(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); + + this.subtype.add("Aura"); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Enchant creature you control + TargetPermanent auraTarget = new TargetControlledCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // When Saving Grace enters the battlefield, all damage that would be dealt this turn to you and permanents you control is dealt to enchanted creature instead. + this.addAbility(new EntersBattlefieldTriggeredAbility(new SavingGraceReplacementEffect(), false)); + + // Enchanted creature gets +0/+3. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(0, 3, Duration.WhileOnBattlefield))); + } + + public SavingGrace(final SavingGrace card) { + super(card); + } + + @Override + public SavingGrace copy() { + return new SavingGrace(this); + } +} + +class SavingGraceReplacementEffect extends ReplacementEffectImpl { + + SavingGraceReplacementEffect() { + super(Duration.EndOfTurn, Outcome.RedirectDamage); + staticText = "all damage that would be dealt this turn to you and permanents you control is dealt to enchanted creature instead."; + } + + SavingGraceReplacementEffect(final SavingGraceReplacementEffect effect) { + super(effect); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + switch (event.getType()) { + case DAMAGE_CREATURE: + case DAMAGE_PLAYER: + case DAMAGE_PLANESWALKER: + return true; + default: + return false; + } + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER && event.getPlayerId().equals(source.getControllerId())) { + return true; + } + if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE || event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER) { + Permanent targetPermanent = game.getPermanent(event.getTargetId()); + if (targetPermanent != null + && targetPermanent.getControllerId().equals(source.getControllerId())) { + return true; + } + } + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + DamageEvent damageEvent = (DamageEvent) event; + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + + if (sourcePermanent != null) { + Permanent creature = game.getPermanent(sourcePermanent.getAttachedTo()); + + if (creature == null) { + return false; + } + + // Name of old target + Permanent targetPermanent = game.getPermanent(event.getTargetId()); + StringBuilder message = new StringBuilder(); + message.append(creature.getName()).append(": gets "); + message.append(damageEvent.getAmount()).append(" damage redirected from "); + if (targetPermanent != null) { + message.append(targetPermanent.getName()); + } else { + Player targetPlayer = game.getPlayer(event.getTargetId()); + if (targetPlayer != null) { + message.append(targetPlayer.getLogName()); + } else { + message.append("unknown"); + } + + } + game.informPlayers(message.toString()); + // Redirect damage + if (creature != null) { + creature.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects()); + return true; + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public SavingGraceReplacementEffect copy() { + return new SavingGraceReplacementEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/HourOfDevastation.java b/Mage.Sets/src/mage/sets/HourOfDevastation.java index e14f68a7382..65ade5cb876 100644 --- a/Mage.Sets/src/mage/sets/HourOfDevastation.java +++ b/Mage.Sets/src/mage/sets/HourOfDevastation.java @@ -130,6 +130,7 @@ public class HourOfDevastation extends ExpansionSet { cards.add(new SetCardInfo("Samut, the Tested", 144, Rarity.MYTHIC, mage.cards.s.SamutTheTested.class)); cards.add(new SetCardInfo("Sand Strangler", 107, Rarity.UNCOMMON, mage.cards.s.SandStrangler.class)); cards.add(new SetCardInfo("Sandblast", 20, Rarity.COMMON, mage.cards.s.Sandblast.class)); + cards.add(new SetCardInfo("Saving Grace", 21, Rarity.UNCOMMON, mage.cards.s.SavingGrace.class)); cards.add(new SetCardInfo("Scavenger Grounds", 182, Rarity.RARE, mage.cards.s.ScavengerGrounds.class)); cards.add(new SetCardInfo("Seer of the Last Tomorrow", 44, Rarity.COMMON, mage.cards.s.SeerOfTheLastTomorrow.class)); cards.add(new SetCardInfo("Shefet Dunes", 183, Rarity.UNCOMMON, mage.cards.s.ShefetDunes.class));