From 6a118d2bfa703816e71d204cca42b56192c285eb Mon Sep 17 00:00:00 2001 From: myersn024 Date: Wed, 18 Feb 2015 08:57:50 -0600 Subject: [PATCH 01/23] Create SkyshipWeatherlight.java --- .../sets/planeshift/SkyshipWeatherlight.java | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java diff --git a/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java b/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java new file mode 100644 index 0000000000..f303fa12a7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java @@ -0,0 +1,136 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.sets.planeshift; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.SearchEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.ExileZone; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; +import mage.util.CardUtil; + +/** + * + * @author nick.myers + */ +public class SkyshipWeatherlight extends CardImpl { + + public SkyshipWeatherlight(UUID ownerId) { + super(ownerId, 133, "Skyship Weatherlight", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "PLS"; + + // When Skyship Weatherlight enters the battlefield, search your library for any number of artifact and/or creature cards and exile them. Then shuffle your library. + this.addAbility(new EntersBattlefieldTriggeredAbility(new SkyshipWeatherlightEffect(), false)); + + // {4}, {tap}, Choose a card at random that was removed from the game with Skyship Weatherlight. Put that card into your hand. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SkyshipWeatherlightEffect2(), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public SkyshipWeatherlight(final SkyshipWeatherlight card) { + super(card); + } + + @Override + public SkyshipWeatherlight copy() { + return new SkyshipWeatherlight(this); + } + +} + +class SkyshipWeatherlightEffect extends SearchEffect { + + private static final FilterCard filter = new FilterCard("artifact and/or creature card"); + + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE))); + } + + public SkyshipWeatherlightEffect() { + + super(new TargetCardInLibrary(0, Integer.MAX_VALUE, filter), Outcome.Neutral); + this.staticText = "search your library for any number of artifact and/or creature cards and remove them from the game. Then shuffle your library."; + + } + + public SkyshipWeatherlightEffect(final SkyshipWeatherlightEffect effect) { + super(effect); + } + + @Override + public SkyshipWeatherlightEffect copy() { + return new SkyshipWeatherlightEffect(this); + } + + @Override + public boolean apply (Game game, Ability source) { + Player you = game.getPlayer(source.getControllerId()); + if (you != null) { + if (you.searchLibrary(target, game)) { + UUID exileZone = CardUtil.getCardExileZoneId(game, source); + if (target.getTargets().size() > 0) { + for (UUID cardID : target.getTargets()) { + Card card = you.getLibrary().getCard(cardID, game); + if (card != null) { + card.moveToExile(exileZone, "Skyship Weatherlight", source.getSourceId(), game); + } + } + } + } + you.shuffleLibrary(game); + } + return false; + } + +} + +class SkyshipWeatherlightEffect2 extends OneShotEffect { + + public SkyshipWeatherlightEffect2() { + super(Outcome.ReturnToHand); + this.staticText = "Choose a card at random that was removed from the game with Skyship Weatherlight. Put that card into your hand."; + } + + public SkyshipWeatherlightEffect2(final SkyshipWeatherlightEffect2 effect) { + super(effect); + } + + @Override + public SkyshipWeatherlightEffect2 copy() { + return new SkyshipWeatherlightEffect2(this); + } + + @Override + public boolean apply(Game game, Ability source) { + ExileZone exZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); + if (exZone != null) { + Card card = exZone.getRandom(game); + card.moveToZone(Zone.HAND, source.getSourceId(), game, false); + } + return true; + } + +} From 6566b0a75573ac11a4d032003367e9deedf3cff4 Mon Sep 17 00:00:00 2001 From: myersn024 Date: Wed, 18 Feb 2015 09:14:12 -0600 Subject: [PATCH 02/23] Update SkyshipWeatherlight.java Added legendary supertype attribute --- Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java b/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java index f303fa12a7..f9bbcb53de 100644 --- a/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java +++ b/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java @@ -37,6 +37,7 @@ public class SkyshipWeatherlight extends CardImpl { public SkyshipWeatherlight(UUID ownerId) { super(ownerId, 133, "Skyship Weatherlight", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}"); this.expansionSetCode = "PLS"; + this.supertype.add("Legendary"); // When Skyship Weatherlight enters the battlefield, search your library for any number of artifact and/or creature cards and exile them. Then shuffle your library. this.addAbility(new EntersBattlefieldTriggeredAbility(new SkyshipWeatherlightEffect(), false)); From fe01b728ac890a41c8861f1699e1a0f38fc749e9 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Wed, 18 Feb 2015 11:28:56 -0600 Subject: [PATCH 03/23] Fixed that Valorous Stance incorrectly prevented regeneration. --- Mage.Sets/src/mage/sets/fatereforged/ValorousStance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/fatereforged/ValorousStance.java b/Mage.Sets/src/mage/sets/fatereforged/ValorousStance.java index 07f3dc1bab..bb030cc410 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/ValorousStance.java +++ b/Mage.Sets/src/mage/sets/fatereforged/ValorousStance.java @@ -64,7 +64,7 @@ public class ValorousStance extends CardImpl { this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // or destroy target creature with toughness 4 or greater. Mode mode1 = new Mode(); - mode1.getEffects().add(new DestroyTargetEffect(true)); + mode1.getEffects().add(new DestroyTargetEffect()); mode1.getTargets().add(new TargetCreaturePermanent(filter)); this.getSpellAbility().addMode(mode1); From 43d1bf899c17a285916744530c54f8c5fec6e63d Mon Sep 17 00:00:00 2001 From: myersn024 Date: Wed, 18 Feb 2015 12:08:09 -0600 Subject: [PATCH 04/23] Implemented EonHub.java Fully tested and working --- Mage.Sets/src/mage/sets/fifthdawn/EonHub.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/fifthdawn/EonHub.java diff --git a/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java b/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java new file mode 100644 index 0000000000..658b6b9e1a --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java @@ -0,0 +1,80 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.sets.fifthdawn; + +import java.util.UUID; +import mage.constants.*; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.cards.CardImpl; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; + +/** + * + * @author nick.myers + */ +public class EonHub extends CardImpl { + + public EonHub(UUID ownerId) { + super(ownerId, 120, "Eon Hub", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{5}"); + this.expansionSetCode = "5DN"; + + // Players skip their upkeep steps. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SkipUpkeepStepEffect())); + } + + public EonHub(final EonHub card) { + super(card); + } + + @Override + public EonHub copy() { + return new EonHub(this); + } + +} + +class SkipUpkeepStepEffect extends ReplacementEffectImpl { + + public SkipUpkeepStepEffect() { + super(Duration.WhileOnBattlefield, Outcome.Neutral); + staticText = "Players skip their upkeep steps"; + } + + public SkipUpkeepStepEffect(final SkipUpkeepStepEffect effect) { + super(effect); + } + + @Override + public SkipUpkeepStepEffect copy() { + return new SkipUpkeepStepEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.UPKEEP_STEP; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + return controller != null && controller.getInRange().contains(event.getPlayerId()); + } + +} From d1366b1da7d38425523e4241e279b44c3fe5cbf8 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Wed, 18 Feb 2015 15:20:47 -0600 Subject: [PATCH 05/23] Added Ragnar, Treva the Renewer, Village Elder, Rushwood Herbalist, Ertai the Corrupted, Sporeback Troll, Dakkon Blackblade, Daru Mender, Niall Silvain. Fixed that Fledgling Imp wrongly discarded at random. Fixed incorrect activation cost on Centaur Glade. --- .../mage/sets/dissension/SporebackTroll.java | 82 +++++++++++++ .../mage/sets/invasion/TrevaTheRenewer.java | 115 ++++++++++++++++++ .../mage/sets/legends/DakkonBlackblade.java | 74 +++++++++++ Mage.Sets/src/mage/sets/legends/Ragnar.java | 73 +++++++++++ .../src/mage/sets/legions/DaruMender.java | 72 +++++++++++ .../mercadianmasques/RushwoodHerbalist.java | 74 +++++++++++ .../src/mage/sets/mirage/VillageElder.java | 82 +++++++++++++ .../src/mage/sets/odyssey/FledglingImp.java | 2 +- .../src/mage/sets/onslaught/CentaurGlade.java | 2 +- .../sets/planeshift/ErtaiTheCorrupted.java | 85 +++++++++++++ .../src/mage/sets/thedark/NiallSilvain.java | 71 +++++++++++ 11 files changed, 730 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/dissension/SporebackTroll.java create mode 100644 Mage.Sets/src/mage/sets/invasion/TrevaTheRenewer.java create mode 100644 Mage.Sets/src/mage/sets/legends/DakkonBlackblade.java create mode 100644 Mage.Sets/src/mage/sets/legends/Ragnar.java create mode 100644 Mage.Sets/src/mage/sets/legions/DaruMender.java create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/RushwoodHerbalist.java create mode 100644 Mage.Sets/src/mage/sets/mirage/VillageElder.java create mode 100644 Mage.Sets/src/mage/sets/planeshift/ErtaiTheCorrupted.java create mode 100644 Mage.Sets/src/mage/sets/thedark/NiallSilvain.java diff --git a/Mage.Sets/src/mage/sets/dissension/SporebackTroll.java b/Mage.Sets/src/mage/sets/dissension/SporebackTroll.java new file mode 100644 index 0000000000..39d0e66023 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dissension/SporebackTroll.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.dissension; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.RegenerateTargetEffect; +import mage.abilities.keyword.GraftAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.CounterPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class SporebackTroll extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature with a +1/+1 counter on it"); + static { + filter.add(new CounterPredicate(CounterType.P1P1)); + } + + public SporebackTroll(UUID ownerId) { + super(ownerId, 94, "Sporeback Troll", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{G}"); + this.expansionSetCode = "DIS"; + this.subtype.add("Troll"); + this.subtype.add("Mutant"); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Graft 2 + this.addAbility(new GraftAbility(this, 2)); + + // {1}{G}: Regenerate target creature with a +1/+1 counter on it. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new ManaCostsImpl("{1}{G}")); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public SporebackTroll(final SporebackTroll card) { + super(card); + } + + @Override + public SporebackTroll copy() { + return new SporebackTroll(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/TrevaTheRenewer.java b/Mage.Sets/src/mage/sets/invasion/TrevaTheRenewer.java new file mode 100644 index 0000000000..df2fd0bc08 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/TrevaTheRenewer.java @@ -0,0 +1,115 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.choices.ChoiceColor; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author fireshoes + */ +public class TrevaTheRenewer extends CardImpl { + + public TrevaTheRenewer(UUID ownerId) { + super(ownerId, 280, "Treva, the Renewer", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}{W}{U}"); + this.expansionSetCode = "INV"; + this.supertype.add("Legendary"); + this.subtype.add("Dragon"); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever Treva, the Renewer deals combat damage to a player, you may pay {2}{W}. If you do, choose a color, then you gain 1 life for each permanent of that color. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DoIfCostPaid(new TrevaTheRenewerEffect(), new ManaCostsImpl("{2}{W}")), false)); + } + + public TrevaTheRenewer(final TrevaTheRenewer card) { + super(card); + } + + @Override + public TrevaTheRenewer copy() { + return new TrevaTheRenewer(this); + } +} + +class TrevaTheRenewerEffect extends OneShotEffect { + + public TrevaTheRenewerEffect() { + super(Outcome.Benefit); + this.staticText = "choose a color, then you gain 1 life for each permanent of that color."; + } + + public TrevaTheRenewerEffect(final TrevaTheRenewerEffect effect) { + super(effect); + } + + @Override + public TrevaTheRenewerEffect copy() { + return new TrevaTheRenewerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + ChoiceColor choice = new ChoiceColor(); + controller.choose(outcome, choice, game); + if (choice.getColor() != null) { + game.informPlayers(new StringBuilder(controller.getName()).append(" chooses ").append(choice.getColor()).toString()); + FilterPermanent filter = new FilterPermanent(); + filter.add(new ColorPredicate(choice.getColor())); + int cardsWithColor = game.getBattlefield().count(filter, source.getSourceId(), controller.getId(), game); + if (cardsWithColor > 0) { + new GainLifeEffect(cardsWithColor).apply(game, source); + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/legends/DakkonBlackblade.java b/Mage.Sets/src/mage/sets/legends/DakkonBlackblade.java new file mode 100644 index 0000000000..64aaf022a7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/legends/DakkonBlackblade.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.legends; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.continious.SetPowerToughnessSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.common.FilterControlledPermanent; + +/** + * + * @author fireshoes + */ +public class DakkonBlackblade extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledLandPermanent("lands you control"); + + public DakkonBlackblade(UUID ownerId) { + super(ownerId, 265, "Dakkon Blackblade", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}{U}{U}{B}"); + this.expansionSetCode = "LEG"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Warrior"); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Dakkon Blackblade's power and toughness are each equal to the number of lands you control. + DynamicValue controlledLands = new PermanentsOnBattlefieldCount(filter); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(controlledLands, Duration.EndOfGame))); + } + + public DakkonBlackblade(final DakkonBlackblade card) { + super(card); + } + + @Override + public DakkonBlackblade copy() { + return new DakkonBlackblade(this); + } +} diff --git a/Mage.Sets/src/mage/sets/legends/Ragnar.java b/Mage.Sets/src/mage/sets/legends/Ragnar.java new file mode 100644 index 0000000000..588eb6e632 --- /dev/null +++ b/Mage.Sets/src/mage/sets/legends/Ragnar.java @@ -0,0 +1,73 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.legends; + +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.RegenerateTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class Ragnar extends CardImpl { + + public Ragnar(UUID ownerId) { + super(ownerId, 290, "Ragnar", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{G}{W}{U}"); + this.expansionSetCode = "LEG"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Cleric"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {G}{W}{U}, {tap}: Regenerate target creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new ManaCostsImpl("{G}{W}{U}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public Ragnar(final Ragnar card) { + super(card); + } + + @Override + public Ragnar copy() { + return new Ragnar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/legions/DaruMender.java b/Mage.Sets/src/mage/sets/legions/DaruMender.java new file mode 100644 index 0000000000..73ed09bf43 --- /dev/null +++ b/Mage.Sets/src/mage/sets/legions/DaruMender.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.legions; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.RegenerateTargetEffect; +import mage.abilities.keyword.MorphAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class DaruMender extends CardImpl { + + public DaruMender(UUID ownerId) { + super(ownerId, 8, "Daru Mender", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{W}"); + this.expansionSetCode = "LGN"; + this.subtype.add("Human"); + this.subtype.add("Cleric"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Morph {W} + this.addAbility(new MorphAbility(this, new ManaCostsImpl("{W}"))); + // When Daru Mender is turned face up, regenerate target creature. + Ability ability = new TurnedFaceUpSourceTriggeredAbility(new RegenerateTargetEffect()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public DaruMender(final DaruMender card) { + super(card); + } + + @Override + public DaruMender copy() { + return new DaruMender(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodHerbalist.java b/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodHerbalist.java new file mode 100644 index 0000000000..5e25e4a79d --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/RushwoodHerbalist.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.mercadianmasques; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.RegenerateTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class RushwoodHerbalist extends CardImpl { + + public RushwoodHerbalist(UUID ownerId) { + super(ownerId, 265, "Rushwood Herbalist", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "MMQ"; + this.subtype.add("Human"); + this.subtype.add("Spellshaper"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {G}, {tap}, Discard a card: Regenerate target creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new ManaCostsImpl("{G}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new DiscardCardCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public RushwoodHerbalist(final RushwoodHerbalist card) { + super(card); + } + + @Override + public RushwoodHerbalist copy() { + return new RushwoodHerbalist(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirage/VillageElder.java b/Mage.Sets/src/mage/sets/mirage/VillageElder.java new file mode 100644 index 0000000000..63deaff25b --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirage/VillageElder.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.mirage; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.RegenerateTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetControlledPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class VillageElder extends CardImpl { + + private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("a Forest"); + static{ + filter.add(new SubtypePredicate("Forest")); + } + + public VillageElder(UUID ownerId) { + super(ownerId, 149, "Village Elder", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{G}"); + this.expansionSetCode = "MIR"; + this.subtype.add("Human"); + this.subtype.add("Druid"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {G}, {tap}, Sacrifice a Forest: Regenerate target creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new ManaCostsImpl("{G}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter))); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public VillageElder(final VillageElder card) { + super(card); + } + + @Override + public VillageElder copy() { + return new VillageElder(this); + } +} diff --git a/Mage.Sets/src/mage/sets/odyssey/FledglingImp.java b/Mage.Sets/src/mage/sets/odyssey/FledglingImp.java index edc475e6e3..b68bad6f17 100644 --- a/Mage.Sets/src/mage/sets/odyssey/FledglingImp.java +++ b/Mage.Sets/src/mage/sets/odyssey/FledglingImp.java @@ -58,7 +58,7 @@ public class FledglingImp extends CardImpl { // {B}, Discard a card: Fledgling Imp gains flying until end of turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{B}")); - ability.addCost(new DiscardCardCost(true)); + ability.addCost(new DiscardCardCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/onslaught/CentaurGlade.java b/Mage.Sets/src/mage/sets/onslaught/CentaurGlade.java index 56259e75f4..75c0807d8d 100644 --- a/Mage.Sets/src/mage/sets/onslaught/CentaurGlade.java +++ b/Mage.Sets/src/mage/sets/onslaught/CentaurGlade.java @@ -49,7 +49,7 @@ public class CentaurGlade extends CardImpl { this.expansionSetCode = "ONS"; // {2}{G}{G}: Put a 3/3 green Centaur creature token onto the battlefield. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new CentaurToken(), 1), new ManaCostsImpl("{3}{G}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new CentaurToken(), 1), new ManaCostsImpl("{2}{G}{G}"))); } public CentaurGlade(final CentaurGlade card) { diff --git a/Mage.Sets/src/mage/sets/planeshift/ErtaiTheCorrupted.java b/Mage.Sets/src/mage/sets/planeshift/ErtaiTheCorrupted.java new file mode 100644 index 0000000000..8771358fb2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planeshift/ErtaiTheCorrupted.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planeshift; + +import java.util.UUID; +import mage.MageInt; +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.CounterTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetSpell; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author fireshoes + */ +public class ErtaiTheCorrupted extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("a creature or enchantment"); + + static { + filter.add(Predicates.or(new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.ENCHANTMENT))); + } + + public ErtaiTheCorrupted(UUID ownerId) { + super(ownerId, 107, "Ertai, the Corrupted", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}{U}{B}"); + this.expansionSetCode = "PLS"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Wizard"); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // {U}, {tap}, Sacrifice a creature or enchantment: Counter target spell. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl("{U}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter))); + ability.addTarget(new TargetSpell()); + this.addAbility(ability); +} + + public ErtaiTheCorrupted(final ErtaiTheCorrupted card) { + super(card); + } + + @Override + public ErtaiTheCorrupted copy() { + return new ErtaiTheCorrupted(this); + } +} diff --git a/Mage.Sets/src/mage/sets/thedark/NiallSilvain.java b/Mage.Sets/src/mage/sets/thedark/NiallSilvain.java new file mode 100644 index 0000000000..9f12aa6672 --- /dev/null +++ b/Mage.Sets/src/mage/sets/thedark/NiallSilvain.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.thedark; + +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.RegenerateTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class NiallSilvain extends CardImpl { + + public NiallSilvain(UUID ownerId) { + super(ownerId, 45, "Niall Silvain", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{G}{G}{G}"); + this.expansionSetCode = "DRK"; + this.subtype.add("Ouphe"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {G}{G}{G}{G}, {tap}: Regenerate target creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new ManaCostsImpl("{G}{G}{G}{G}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public NiallSilvain(final NiallSilvain card) { + super(card); + } + + @Override + public NiallSilvain copy() { + return new NiallSilvain(this); + } +} From d2b94e8dad71769aef0e570cdbc589ae1ca5ecd3 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 18 Feb 2015 23:50:16 +0100 Subject: [PATCH 06/23] * Skyship Weatherlight - Some minor updates to the card. --- .../sets/planeshift/SkyshipWeatherlight.java | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java b/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java index f9bbcb53de..ac5662ad6b 100644 --- a/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java +++ b/Mage.Sets/src/mage/sets/planeshift/SkyshipWeatherlight.java @@ -6,9 +6,10 @@ package mage.sets.planeshift; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; @@ -73,7 +74,7 @@ class SkyshipWeatherlightEffect extends SearchEffect { public SkyshipWeatherlightEffect() { super(new TargetCardInLibrary(0, Integer.MAX_VALUE, filter), Outcome.Neutral); - this.staticText = "search your library for any number of artifact and/or creature cards and remove them from the game. Then shuffle your library."; + this.staticText = "search your library for any number of artifact and/or creature cards and remove them from the game. Then shuffle your library"; } @@ -88,20 +89,22 @@ class SkyshipWeatherlightEffect extends SearchEffect { @Override public boolean apply (Game game, Ability source) { - Player you = game.getPlayer(source.getControllerId()); - if (you != null) { - if (you.searchLibrary(target, game)) { - UUID exileZone = CardUtil.getCardExileZoneId(game, source); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject != null && controller != null) { + if (controller.searchLibrary(target, game)) { + UUID exileZone = CardUtil.getObjectExileZoneId(game, sourceObject); if (target.getTargets().size() > 0) { for (UUID cardID : target.getTargets()) { - Card card = you.getLibrary().getCard(cardID, game); + Card card = controller.getLibrary().getCard(cardID, game); if (card != null) { - card.moveToExile(exileZone, "Skyship Weatherlight", source.getSourceId(), game); + controller.moveCardToExileWithInfo(card, exileZone, sourceObject.getLogName(), source.getSourceId(), game, Zone.LIBRARY); } } } } - you.shuffleLibrary(game); + controller.shuffleLibrary(game); + return true; } return false; } @@ -112,7 +115,7 @@ class SkyshipWeatherlightEffect2 extends OneShotEffect { public SkyshipWeatherlightEffect2() { super(Outcome.ReturnToHand); - this.staticText = "Choose a card at random that was removed from the game with Skyship Weatherlight. Put that card into your hand."; + this.staticText = "Choose a card at random that was removed from the game with {this}. Put that card into your hand"; } public SkyshipWeatherlightEffect2(final SkyshipWeatherlightEffect2 effect) { @@ -126,12 +129,17 @@ class SkyshipWeatherlightEffect2 extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - ExileZone exZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); - if (exZone != null) { - Card card = exZone.getRandom(game); - card.moveToZone(Zone.HAND, source.getSourceId(), game, false); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject != null && controller != null) { + ExileZone exZone = game.getExile().getExileZone(CardUtil.getObjectExileZoneId(game, sourceObject)); + if (exZone != null) { + Card card = exZone.getRandom(game); + controller.moveCardToHandWithInfo(card, source.getSourceId(), game, Zone.EXILED); + } + return true; } - return true; + return false; } } From 04e52cecbea0de83837e4ca724460b42d9bc9892 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 18 Feb 2015 23:54:16 +0100 Subject: [PATCH 07/23] * Nether Traitor - Fixed that it did trigger for every card instead only for creature cards. --- Mage.Sets/src/mage/sets/timespiral/NetherTraitor.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/timespiral/NetherTraitor.java b/Mage.Sets/src/mage/sets/timespiral/NetherTraitor.java index 40b541e0ce..a9e3683bbf 100644 --- a/Mage.Sets/src/mage/sets/timespiral/NetherTraitor.java +++ b/Mage.Sets/src/mage/sets/timespiral/NetherTraitor.java @@ -99,7 +99,10 @@ class NetherTraitorTriggeredAbility extends TriggeredAbilityImpl { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) { Card card = game.getCard(event.getTargetId()); - if (card != null && card.getOwnerId().equals(this.getControllerId()) && !card.getId().equals(this.getSourceId())) { + if (card != null && + card.getOwnerId().equals(this.getControllerId()) && + card.getCardType().contains(CardType.CREATURE)&& + !card.getId().equals(this.getSourceId())) { return true; } } From ebd0215c5b9adeae50d8fc7a73e0d1f56b68f2dc Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 19 Feb 2015 00:16:25 +0100 Subject: [PATCH 08/23] * Frontier Siege - Fixed that the second ability (Kahns) was not optional. --- Mage.Sets/src/mage/sets/fatereforged/FrontierSiege.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/fatereforged/FrontierSiege.java b/Mage.Sets/src/mage/sets/fatereforged/FrontierSiege.java index 5851af8010..5a51ca2367 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/FrontierSiege.java +++ b/Mage.Sets/src/mage/sets/fatereforged/FrontierSiege.java @@ -89,7 +89,7 @@ public class FrontierSiege extends CardImpl { Ability ability2 = new ConditionalTriggeredAbility( new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new FrontierSiegeFightEffect(), filter, true, SetTargetPointer.PERMANENT, ""), new ModeChoiceSourceCondition("Dragons"), - ruleTrigger2); + ruleTrigger2, true); ability2.addTarget(new TargetCreaturePermanent(filter2)); this.addAbility(ability2); From 0d9aad6a05651f64a9f4eda49218ef4e414702fe Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 18 Feb 2015 18:03:42 -0600 Subject: [PATCH 09/23] - Added Torrent of Souls --- .../mage/sets/shadowmoor/TorrentOfSouls.java | 52 ++++++++ .../sets/sorinvstibalt/TorrentOfSouls.java | 123 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/shadowmoor/TorrentOfSouls.java create mode 100644 Mage.Sets/src/mage/sets/sorinvstibalt/TorrentOfSouls.java diff --git a/Mage.Sets/src/mage/sets/shadowmoor/TorrentOfSouls.java b/Mage.Sets/src/mage/sets/shadowmoor/TorrentOfSouls.java new file mode 100644 index 0000000000..d04fe6768f --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/TorrentOfSouls.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.shadowmoor; + +import java.util.UUID; + +/** + * + * @author jeffwadsworth + */ +public class TorrentOfSouls extends mage.sets.sorinvstibalt.TorrentOfSouls { + + public TorrentOfSouls(UUID ownerId) { + super(ownerId); + this.cardNumber = 199; + this.expansionSetCode = "SHM"; + } + + public TorrentOfSouls(final TorrentOfSouls card) { + super(card); + } + + @Override + public TorrentOfSouls copy() { + return new TorrentOfSouls(this); + } +} diff --git a/Mage.Sets/src/mage/sets/sorinvstibalt/TorrentOfSouls.java b/Mage.Sets/src/mage/sets/sorinvstibalt/TorrentOfSouls.java new file mode 100644 index 0000000000..a192ee0113 --- /dev/null +++ b/Mage.Sets/src/mage/sets/sorinvstibalt/TorrentOfSouls.java @@ -0,0 +1,123 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.sorinvstibalt; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.condition.common.ManaWasSpentCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect; +import mage.abilities.effects.common.continious.BoostAllEffect; +import mage.abilities.effects.common.continious.GainAbilityAllEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterCreatureCard; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInYourGraveyard; +import mage.watchers.common.ManaSpentToCastWatcher; + +/** + * + * @author jeffwadsworth + */ +public class TorrentOfSouls extends CardImpl { + + public TorrentOfSouls(UUID ownerId) { + super(ownerId, 71, "Torrent of Souls", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{4}{B/R}"); + this.expansionSetCode = "DDK"; + + // Return up to one target creature card from your graveyard to the battlefield if {B} was spent to cast Torrent of Souls. Creatures target player controls get +2/+0 and gain haste until end of turn if {R} was spent to cast Torrent of Souls. + Target targetCreature = new TargetCardInYourGraveyard(0, 1, new FilterCreatureCard("target creature card in your graveyard")); + Target targetPlayer = new TargetPlayer(); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new ReturnToBattlefieldUnderYourControlTargetEffect(), + new ManaWasSpentCondition(ColoredManaSymbol.B), "Return up to one target creature card from your graveyard to the battlefield if {B} was spent to cast {this}")); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new TorrentOfSoulsEffect(), + new ManaWasSpentCondition(ColoredManaSymbol.R), " Creatures target player controls get +2/+0 and gain haste until end of turn if {R} was spent to cast {this}")); + + this.getSpellAbility().addTarget(targetCreature); + this.getSpellAbility().addTarget(targetPlayer); + + this.addInfo("Info1", "(Do both if {B}{R} was spent.)"); + this.addWatcher(new ManaSpentToCastWatcher()); + + } + + public TorrentOfSouls(final TorrentOfSouls card) { + super(card); + } + + @Override + public TorrentOfSouls copy() { + return new TorrentOfSouls(this); + } +} + +class TorrentOfSoulsEffect extends OneShotEffect { + + public TorrentOfSoulsEffect() { + super(Outcome.BoostCreature); + } + + public TorrentOfSoulsEffect(final TorrentOfSoulsEffect effect) { + super(effect); + } + + @Override + public TorrentOfSoulsEffect copy() { + return new TorrentOfSoulsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetedPlayer = game.getPlayer(source.getTargets().get(1).getFirstTarget()); + if (targetedPlayer != null) { + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new ControllerIdPredicate(targetedPlayer.getId())); + ContinuousEffect boostEffect = new BoostAllEffect(2, 0, Duration.EndOfTurn, filter, true); + ContinuousEffect gainAbilityEffect = new GainAbilityAllEffect(HasteAbility.getInstance(), Duration.EndOfTurn, filter); + game.addEffect(boostEffect, source); + game.addEffect(gainAbilityEffect, source); + return true; + } + return false; + } +} From 391afc0d4c2e6006cba8964a20bf5dcfbad491c6 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Wed, 18 Feb 2015 18:17:19 -0600 Subject: [PATCH 10/23] Fixed that Toxin Sliver wrongly allowed regeneration. Added Phyrexian Negator and Treva the Renewer reprints to DD: Phyrexia vs Coalition. Add Mirri the Cursed, Control of the Court, Dragon Mage, Helm of Possession, and Sisay's Ring --- .../src/mage/sets/legions/ToxinSliver.java | 2 +- .../PhyrexianNegator.java | 54 +++++++++ .../TrevaTheRenewer.java | 52 +++++++++ .../mage/sets/planarchaos/MirriTheCursed.java | 78 +++++++++++++ .../ControlOfTheCourt.java | 98 ++++++++++++++++ .../src/mage/sets/scourge/DragonMage.java | 109 ++++++++++++++++++ .../mage/sets/seventhedition/SisaysRing.java | 77 +++++++++++++ .../mage/sets/tempest/HelmOfPossession.java | 100 ++++++++++++++++ .../src/mage/sets/visions/SisaysRing.java | 54 +++++++++ 9 files changed, 623 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/sets/phyrexiavsthecoalition/PhyrexianNegator.java create mode 100644 Mage.Sets/src/mage/sets/phyrexiavsthecoalition/TrevaTheRenewer.java create mode 100644 Mage.Sets/src/mage/sets/planarchaos/MirriTheCursed.java create mode 100644 Mage.Sets/src/mage/sets/portalthreekingdoms/ControlOfTheCourt.java create mode 100644 Mage.Sets/src/mage/sets/scourge/DragonMage.java create mode 100644 Mage.Sets/src/mage/sets/seventhedition/SisaysRing.java create mode 100644 Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java create mode 100644 Mage.Sets/src/mage/sets/visions/SisaysRing.java diff --git a/Mage.Sets/src/mage/sets/legions/ToxinSliver.java b/Mage.Sets/src/mage/sets/legions/ToxinSliver.java index 34c926e6f7..8901f40af5 100644 --- a/Mage.Sets/src/mage/sets/legions/ToxinSliver.java +++ b/Mage.Sets/src/mage/sets/legions/ToxinSliver.java @@ -57,7 +57,7 @@ public class ToxinSliver extends CardImpl { this.toughness = new MageInt(3); // Whenever a Sliver deals combat damage to a creature, destroy that creature. It can't be regenerated. - this.addAbility(new DealsDamageToACreatureTriggeredAbility(new DestroyTargetEffect(false), true, false, true)); + this.addAbility(new DealsDamageToACreatureTriggeredAbility(new DestroyTargetEffect(true), true, false, true)); } diff --git a/Mage.Sets/src/mage/sets/phyrexiavsthecoalition/PhyrexianNegator.java b/Mage.Sets/src/mage/sets/phyrexiavsthecoalition/PhyrexianNegator.java new file mode 100644 index 0000000000..b49c9c20ad --- /dev/null +++ b/Mage.Sets/src/mage/sets/phyrexiavsthecoalition/PhyrexianNegator.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.phyrexiavsthecoalition; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class PhyrexianNegator extends mage.sets.urzasdestiny.PhyrexianNegator { + + public PhyrexianNegator(UUID ownerId) { + super(ownerId); + this.cardNumber = 1; + this.expansionSetCode = "DDE"; + this.rarity = Rarity.MYTHIC; + } + + public PhyrexianNegator(final PhyrexianNegator card) { + super(card); + } + + @Override + public PhyrexianNegator copy() { + return new PhyrexianNegator(this); + } +} diff --git a/Mage.Sets/src/mage/sets/phyrexiavsthecoalition/TrevaTheRenewer.java b/Mage.Sets/src/mage/sets/phyrexiavsthecoalition/TrevaTheRenewer.java new file mode 100644 index 0000000000..60a0259657 --- /dev/null +++ b/Mage.Sets/src/mage/sets/phyrexiavsthecoalition/TrevaTheRenewer.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.phyrexiavsthecoalition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class TrevaTheRenewer extends mage.sets.invasion.TrevaTheRenewer { + + public TrevaTheRenewer(UUID ownerId) { + super(ownerId); + this.cardNumber = 49; + this.expansionSetCode = "DDE"; + } + + public TrevaTheRenewer(final TrevaTheRenewer card) { + super(card); + } + + @Override + public TrevaTheRenewer copy() { + return new TrevaTheRenewer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/MirriTheCursed.java b/Mage.Sets/src/mage/sets/planarchaos/MirriTheCursed.java new file mode 100644 index 0000000000..525d6c45ee --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/MirriTheCursed.java @@ -0,0 +1,78 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.counters.CounterType; + +/** + * + * @author fireshoes + */ +public class MirriTheCursed extends CardImpl { + + public MirriTheCursed(UUID ownerId) { + super(ownerId, 75, "Mirri the Cursed", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); + this.expansionSetCode = "PLC"; + this.supertype.add("Legendary"); + this.subtype.add("Vampire"); + this.subtype.add("Cat"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + // Haste + this.addAbility(HasteAbility.getInstance()); + // Whenever Mirri the Cursed deals combat damage to a creature, put a +1/+1 counter on Mirri the Cursed. + Ability ability; + ability = new DealsDamageToACreatureTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), true, false, true); + this.addAbility(ability); + } + + public MirriTheCursed(final MirriTheCursed card) { + super(card); + } + + @Override + public MirriTheCursed copy() { + return new MirriTheCursed(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/ControlOfTheCourt.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/ControlOfTheCourt.java new file mode 100644 index 0000000000..504aeb4df0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/ControlOfTheCourt.java @@ -0,0 +1,98 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.portalthreekingdoms; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author fireshoes + */ +public class ControlOfTheCourt extends CardImpl { + + public ControlOfTheCourt(UUID ownerId) { + super(ownerId, 105, "Control of the Court", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{R}"); + this.expansionSetCode = "PTK"; + + // Draw four cards, then discard three cards at random. + this.getSpellAbility().addEffect(new ControlOfTheCourtEffect()); + } + + public ControlOfTheCourt(final ControlOfTheCourt card) { + super(card); + } + + @Override + public ControlOfTheCourt copy() { + return new ControlOfTheCourt(this); + } +} + +class ControlOfTheCourtEffect extends OneShotEffect { + + public ControlOfTheCourtEffect() { + super(Outcome.DrawCard); + this.staticText = "Draw four cards, then discard three cards at random"; + } + + public ControlOfTheCourtEffect(final ControlOfTheCourtEffect effect) { + super(effect); + } + + @Override + public ControlOfTheCourtEffect copy() { + return new ControlOfTheCourtEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + player.drawCards(4, game); + Cards hand = player.getHand(); + for (int i = 0; i < 3; i++) { + Card card = hand.getRandom(game); + if (card != null) { + player.discard(card, source, game); + } + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/scourge/DragonMage.java b/Mage.Sets/src/mage/sets/scourge/DragonMage.java new file mode 100644 index 0000000000..402eaccd77 --- /dev/null +++ b/Mage.Sets/src/mage/sets/scourge/DragonMage.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.sets.scourge; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author fireshoes + */ +public class DragonMage extends CardImpl { + + public DragonMage(UUID ownerId) { + super(ownerId, 87, "Dragon Mage", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); + this.expansionSetCode = "SCG"; + this.subtype.add("Dragon"); + this.subtype.add("Wizard"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever Dragon Mage deals combat damage to a player, each player discards his or her hand and draws seven cards. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DragonMageEffect(), false)); + } + + public DragonMage(final DragonMage card) { + super(card); + } + + @Override + public DragonMage copy() { + return new DragonMage(this); + } +} + +class DragonMageEffect extends OneShotEffect { + + public DragonMageEffect() { + super(Outcome.DrawCard); + this.staticText = "Each player discards his or her hand, then draws seven cards"; + } + + public DragonMageEffect(final DragonMageEffect effect) { + super(effect); + } + + @Override + public DragonMageEffect copy() { + return new DragonMageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID playerId : controller.getInRange()) { + Player player = game.getPlayer(playerId); + if (player != null) { + for (Card card : player.getHand().getCards(game)) { + player.discard(card, source, game); + } + + player.drawCards(7, game); + } + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/seventhedition/SisaysRing.java b/Mage.Sets/src/mage/sets/seventhedition/SisaysRing.java new file mode 100644 index 0000000000..284553f45f --- /dev/null +++ b/Mage.Sets/src/mage/sets/seventhedition/SisaysRing.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.sets.seventhedition; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.effects.common.BasicManaEffect; +import mage.abilities.mana.BasicManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class SisaysRing extends CardImpl { + + public SisaysRing(UUID ownerId) { + super(ownerId, 315, "Sisay's Ring", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "7ED"; + + // {tap}: Add {2} to your mana pool. + this.addAbility(new SisaysRingAbility()); + } + + public SisaysRing(final SisaysRing card) { + super(card); + } + + @Override + public SisaysRing copy() { + return new SisaysRing(this); + } +} + +class SisaysRingAbility extends BasicManaAbility { + + public SisaysRingAbility() { + super(new BasicManaEffect(new Mana(0, 0, 0, 0, 0, 2, 0))); + this.netMana.add(new Mana(0, 0, 0, 0, 0, 2, 0)); + } + + public SisaysRingAbility(final SisaysRingAbility ability) { + super(ability); + } + + @Override + public SisaysRingAbility copy() { + return new SisaysRingAbility(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java b/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java new file mode 100644 index 0000000000..525e9385f2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java @@ -0,0 +1,100 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.tempest; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.continious.GainControlTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class HelmOfPossession extends CardImpl { + + public HelmOfPossession(UUID ownerId) { + super(ownerId, 281, "Helm of Possession", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "TMP"; + + // You may choose not to untap Helm of Possession during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + + // {2}, {tap}, Sacrifice a creature: Gain control of target creature for as long as you control Helm of Possession and Helm of Possession remains tapped. + ConditionalContinousEffect effect = new ConditionalContinousEffect( + new GainControlTargetEffect(Duration.OneUse), + new HelmOfPossessionCondition(), + "Gain control of target creature for as long as you control Helm of Possession and Helm of Possession remains tapped"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent())); + this.addAbility(ability); + } + + public HelmOfPossession(final HelmOfPossession card) { + super(card); + } + + @Override + public HelmOfPossession copy() { + return new HelmOfPossession(this); + } +} + +class HelmOfPossessionCondition implements Condition { + + private UUID controllerId; + + @Override + public boolean apply(Game game, Ability source) { + if (controllerId == null) { + controllerId = source.getControllerId(); + } + Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); + if (permanent != null){ + if (permanent.isTapped()){ + return controllerId == source.getControllerId(); + } + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/visions/SisaysRing.java b/Mage.Sets/src/mage/sets/visions/SisaysRing.java new file mode 100644 index 0000000000..d75fe19d1d --- /dev/null +++ b/Mage.Sets/src/mage/sets/visions/SisaysRing.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.visions; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class SisaysRing extends mage.sets.seventhedition.SisaysRing { + + public SisaysRing(UUID ownerId) { + super(ownerId); + this.cardNumber = 154; + this.expansionSetCode = "VIS"; + this.rarity = Rarity.COMMON; + } + + public SisaysRing(final SisaysRing card) { + super(card); + } + + @Override + public SisaysRing copy() { + return new SisaysRing(this); + } +} From 9528b991f23ca3d4a4af8ab494a5508dbead50a0 Mon Sep 17 00:00:00 2001 From: nickmyers Date: Wed, 18 Feb 2015 20:55:38 -0600 Subject: [PATCH 11/23] --- Mage.Sets/src/mage/sets/fifthdawn/EonHub.java | 25 +++---------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java b/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java index 658b6b9e1a..f9a79e83b4 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java @@ -9,11 +9,11 @@ import java.util.UUID; import mage.constants.*; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; -import mage.players.Player; +import mage.game.events.GameEvent.EventType; +import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; /** * @@ -40,7 +40,7 @@ public class EonHub extends CardImpl { } -class SkipUpkeepStepEffect extends ReplacementEffectImpl { +class SkipUpkeepStepEffect extends ContinuousRuleModifiyingEffectImpl { public SkipUpkeepStepEffect() { super(Duration.WhileOnBattlefield, Outcome.Neutral); @@ -56,25 +56,8 @@ class SkipUpkeepStepEffect extends ReplacementEffectImpl { return new SkipUpkeepStepEffect(this); } - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - return controller != null && controller.getInRange().contains(event.getPlayerId()); + return event.getType() == EventType.UPKEEP_STEP; } - } From 8d0f45052ac384e85178c36bbaa9db7d4024fd8e Mon Sep 17 00:00:00 2001 From: fireshoes Date: Wed, 18 Feb 2015 22:06:22 -0600 Subject: [PATCH 12/23] Fixed that Ohran Viper's card draw was not optional. Added Garzo Zol Plague Queen, Mystic Speculation, Gwendlyn Di Corsi, Jacques le Vert, and Lady Evangela --- .../sets/coldsnap/GarzaZolPlagueQueen.java | 78 +++++++ .../sets/futuresight/MysticSpeculation.java | 62 +++++ .../mage/sets/jacevsvraska/OhranViper.java | 218 +++++++++--------- .../mage/sets/legends/GwendlynDiCorci.java | 72 ++++++ .../src/mage/sets/legends/JacquesLeVert.java | 76 ++++++ .../src/mage/sets/legends/LadyEvangela.java | 78 +++++++ 6 files changed, 475 insertions(+), 109 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/coldsnap/GarzaZolPlagueQueen.java create mode 100644 Mage.Sets/src/mage/sets/futuresight/MysticSpeculation.java create mode 100644 Mage.Sets/src/mage/sets/legends/GwendlynDiCorci.java create mode 100644 Mage.Sets/src/mage/sets/legends/JacquesLeVert.java create mode 100644 Mage.Sets/src/mage/sets/legends/LadyEvangela.java diff --git a/Mage.Sets/src/mage/sets/coldsnap/GarzaZolPlagueQueen.java b/Mage.Sets/src/mage/sets/coldsnap/GarzaZolPlagueQueen.java new file mode 100644 index 0000000000..9f346ca408 --- /dev/null +++ b/Mage.Sets/src/mage/sets/coldsnap/GarzaZolPlagueQueen.java @@ -0,0 +1,78 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.coldsnap; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.DiesAndDealtDamageThisTurnTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.counters.CounterType; + +/** + * + * @author fireshoes + */ +public class GarzaZolPlagueQueen extends CardImpl { + + public GarzaZolPlagueQueen(UUID ownerId) { + super(ownerId, 129, "Garza Zol, Plague Queen", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{U}{B}{R}"); + this.expansionSetCode = "CSP"; + this.supertype.add("Legendary"); + this.subtype.add("Vampire"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever a creature dealt damage by Garza Zol, Plague Queen this turn dies, put a +1/+1 counter on Garza Zol. + this.addAbility(new DiesAndDealtDamageThisTurnTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()))); + + // Whenever Garza Zol deals combat damage to a player, you may draw a card. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), true)); + } + + public GarzaZolPlagueQueen(final GarzaZolPlagueQueen card) { + super(card); + } + + @Override + public GarzaZolPlagueQueen copy() { + return new GarzaZolPlagueQueen(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/MysticSpeculation.java b/Mage.Sets/src/mage/sets/futuresight/MysticSpeculation.java new file mode 100644 index 0000000000..eb612ba137 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/MysticSpeculation.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.futuresight; + +import java.util.UUID; +import mage.abilities.effects.keyword.ScryEffect; +import mage.abilities.keyword.BuybackAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class MysticSpeculation extends CardImpl { + + public MysticSpeculation(UUID ownerId) { + super(ownerId, 41, "Mystic Speculation", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{U}"); + this.expansionSetCode = "FUT"; + + // Buyback {2} + this.addAbility(new BuybackAbility("{2}")); + + // Scry 3. + this.getSpellAbility().addEffect(new ScryEffect(3)); + } + + public MysticSpeculation(final MysticSpeculation card) { + super(card); + } + + @Override + public MysticSpeculation copy() { + return new MysticSpeculation(this); + } +} diff --git a/Mage.Sets/src/mage/sets/jacevsvraska/OhranViper.java b/Mage.Sets/src/mage/sets/jacevsvraska/OhranViper.java index a17401c084..10cb589e3d 100644 --- a/Mage.Sets/src/mage/sets/jacevsvraska/OhranViper.java +++ b/Mage.Sets/src/mage/sets/jacevsvraska/OhranViper.java @@ -1,109 +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.sets.jacevsvraska; - -import java.util.UUID; -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DestroyTargetEffect; -import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.cards.CardImpl; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.targetpointer.FixedTarget; - -/** - * - * @author LevelX2 - */ -public class OhranViper extends CardImpl { - - public OhranViper(UUID ownerId) { - super(ownerId, 57, "Ohran Viper", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{G}{G}"); - this.expansionSetCode = "DDM"; - this.supertype.add("Snow"); - this.subtype.add("Snake"); - - this.color.setGreen(true); - this.power = new MageInt(1); - this.toughness = new MageInt(3); - - // Whenever Ohran Viper deals combat damage to a creature, destroy that creature at end of combat. - this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility(new OhranViperDestroyEffect(), false, true)); - // Whenever Ohran Viper deals combat damage to a player, you may draw a card. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); - } - - public OhranViper(final OhranViper card) { - super(card); - } - - @Override - public OhranViper copy() { - return new OhranViper(this); - } -} - -class OhranViperDestroyEffect extends OneShotEffect { - - OhranViperDestroyEffect() { - super(Outcome.DestroyPermanent); - staticText = "destroy that creature at end of combat"; - } - - OhranViperDestroyEffect(final OhranViperDestroyEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (targetCreature != null) { - AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()); - delayedAbility.setSourceId(source.getSourceId()); - delayedAbility.setControllerId(source.getControllerId()); - delayedAbility.setSourceObject(source.getSourceObject(game)); - delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(targetCreature.getId())); - game.addDelayedTriggeredAbility(delayedAbility); - return true; - } - return false; - } - - @Override - public OhranViperDestroyEffect copy() { - return new OhranViperDestroyEffect(this); - } -} +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.jacevsvraska; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class OhranViper extends CardImpl { + + public OhranViper(UUID ownerId) { + super(ownerId, 57, "Ohran Viper", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{G}{G}"); + this.expansionSetCode = "DDM"; + this.supertype.add("Snow"); + this.subtype.add("Snake"); + + this.color.setGreen(true); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Whenever Ohran Viper deals combat damage to a creature, destroy that creature at end of combat. + this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility(new OhranViperDestroyEffect(), false, true)); + // Whenever Ohran Viper deals combat damage to a player, you may draw a card. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), true)); + } + + public OhranViper(final OhranViper card) { + super(card); + } + + @Override + public OhranViper copy() { + return new OhranViper(this); + } +} + +class OhranViperDestroyEffect extends OneShotEffect { + + OhranViperDestroyEffect() { + super(Outcome.DestroyPermanent); + staticText = "destroy that creature at end of combat"; + } + + OhranViperDestroyEffect(final OhranViperDestroyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (targetCreature != null) { + AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()); + delayedAbility.setSourceId(source.getSourceId()); + delayedAbility.setControllerId(source.getControllerId()); + delayedAbility.setSourceObject(source.getSourceObject(game)); + delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(targetCreature.getId())); + game.addDelayedTriggeredAbility(delayedAbility); + return true; + } + return false; + } + + @Override + public OhranViperDestroyEffect copy() { + return new OhranViperDestroyEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/legends/GwendlynDiCorci.java b/Mage.Sets/src/mage/sets/legends/GwendlynDiCorci.java new file mode 100644 index 0000000000..65156d23e2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/legends/GwendlynDiCorci.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.legends; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPlayer; + +/** + * + * @author fireshoes + */ +public class GwendlynDiCorci extends CardImpl { + + public GwendlynDiCorci(UUID ownerId) { + super(ownerId, 268, "Gwendlyn Di Corci", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{U}{B}{B}{R}"); + this.expansionSetCode = "LEG"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Rogue"); + this.power = new MageInt(3); + this.toughness = new MageInt(5); + + // {tap}: Target player discards a card at random. Activate this ability only during your turn. + Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1, true), new TapSourceCost(), MyTurnCondition.getInstance()); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public GwendlynDiCorci(final GwendlynDiCorci card) { + super(card); + } + + @Override + public GwendlynDiCorci copy() { + return new GwendlynDiCorci(this); + } +} diff --git a/Mage.Sets/src/mage/sets/legends/JacquesLeVert.java b/Mage.Sets/src/mage/sets/legends/JacquesLeVert.java new file mode 100644 index 0000000000..05a1701608 --- /dev/null +++ b/Mage.Sets/src/mage/sets/legends/JacquesLeVert.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.legends; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continious.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author fireshoes + */ +public class JacquesLeVert extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Green creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.GREEN)); + } + + public JacquesLeVert(UUID ownerId) { + super(ownerId, 272, "Jacques le Vert", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{R}{G}{W}"); + this.expansionSetCode = "LEG"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Warrior"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Green creatures you control get +0/+2. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(0,2, Duration.WhileOnBattlefield, filter))); + } + + public JacquesLeVert(final JacquesLeVert card) { + super(card); + } + + @Override + public JacquesLeVert copy() { + return new JacquesLeVert(this); + } +} diff --git a/Mage.Sets/src/mage/sets/legends/LadyEvangela.java b/Mage.Sets/src/mage/sets/legends/LadyEvangela.java new file mode 100644 index 0000000000..c317c54c82 --- /dev/null +++ b/Mage.Sets/src/mage/sets/legends/LadyEvangela.java @@ -0,0 +1,78 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.legends; + +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.Effect; +import mage.abilities.effects.common.PreventDamageByTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author fireshoes + */ +public class LadyEvangela extends CardImpl { + + public LadyEvangela(UUID ownerId) { + super(ownerId, 280, "Lady Evangela", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{W}{U}{B}"); + this.expansionSetCode = "LEG"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Cleric"); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // {W}{B}, {tap}: Prevent all combat damage that would be dealt by target creature this turn. + Effect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn, true); + effect.setText("Prevent all combat damage that would be dealt by target creature this turn."); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{W}{B}")); + ability.addEffect(effect); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public LadyEvangela(final LadyEvangela card) { + super(card); + } + + @Override + public LadyEvangela copy() { + return new LadyEvangela(this); + } +} From 422b92e4adab00a0b677995ca38bd20fea395195 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 19 Feb 2015 08:53:12 +0100 Subject: [PATCH 13/23] Added some comments. --- .../ContinuousRuleModifiyingEffect.java | 2 +- .../ContinuousRuleModifiyingEffectImpl.java | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffect.java b/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffect.java index f6bc9981b6..d985ef1c7e 100644 --- a/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffect.java +++ b/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffect.java @@ -40,7 +40,7 @@ public interface ContinuousRuleModifiyingEffect extends ContinuousEffect { /** * This check for the relevant events is called at first to prevent further actions if - * the current event is ignored from this effect + * the current event is ignored from this effect. Speeds up event handling. * @param event * @param game * @return diff --git a/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffectImpl.java b/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffectImpl.java index ee3fdadb0e..39769df367 100644 --- a/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ContinuousRuleModifiyingEffectImpl.java @@ -62,7 +62,17 @@ public abstract class ContinuousRuleModifiyingEffectImpl extends ContinuousEffec public ContinuousRuleModifiyingEffectImpl(Duration duration, Outcome outcome) { this(duration, outcome, true, false); } - + + /** + * + * @param duration + * @param outcome + * @param messageToUser - Every time the effect replaces an event, the user gets a message in a dialog window. + * Don't set it to true if the event heppens regularly or very often. The message can be + * changed by overriding the getInfoMessage method. + * @param messageToLog - Every time the effect replaces an event, a message is posted to the game log. The message + * can be changed by overriding the getInfoMessage method. + */ public ContinuousRuleModifiyingEffectImpl(Duration duration, Outcome outcome, boolean messageToUser, boolean messageToLog) { super(duration, outcome); this.effectType = EffectType.CONTINUOUS_RULE_MODIFICATION; @@ -78,6 +88,14 @@ public abstract class ContinuousRuleModifiyingEffectImpl extends ContinuousEffec this.messageToGameLog = effect.messageToGameLog; } + /** + * An early check for the event types this effect applies to. This check was added + * to speed up event handling. Once all existing ContinuousRuleModifiyingEffects have + * implemented this method, the method should be changed to abstract here or removed. + * @param event + * @param game + * @return + */ @Override public boolean checksEventType(GameEvent event, Game game) { return true; From d204af0b553898aa4b79baf24dde18d4ede4910f Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 19 Feb 2015 11:21:23 +0100 Subject: [PATCH 14/23] * Turnabout - Fixed possible endless loops for player choices. --- .../src/mage/sets/urzassaga/Turnabout.java | 74 ++++++++++--------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/Mage.Sets/src/mage/sets/urzassaga/Turnabout.java b/Mage.Sets/src/mage/sets/urzassaga/Turnabout.java index 49a11973ec..5d17dac7d5 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/Turnabout.java +++ b/Mage.Sets/src/mage/sets/urzassaga/Turnabout.java @@ -29,15 +29,14 @@ package mage.sets.urzassaga; import java.util.HashSet; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.choices.Choice; import mage.choices.ChoiceImpl; +import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.Rarity; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -53,13 +52,10 @@ import mage.target.TargetPlayer; */ public class Turnabout extends CardImpl { - public Turnabout(UUID ownerId) { super(ownerId, 105, "Turnabout", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{U}{U}"); this.expansionSetCode = "USG"; - this.color.setBlue(true); - // Choose artifact, creature, or land. Tap all untapped permanents of the chosen type target player controls, or untap all tapped permanents of that type that player controls. this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addEffect(new TurnaboutEffect()); @@ -77,20 +73,22 @@ public class Turnabout extends CardImpl { } class TurnaboutEffect extends OneShotEffect { - - private static final HashSet choice = new HashSet(); - static{ + + private static final HashSet choice = new HashSet<>(); + + static { choice.add(CardType.ARTIFACT.toString()); choice.add(CardType.CREATURE.toString()); choice.add(CardType.LAND.toString()); } - - private static final HashSet choice2 = new HashSet(); - static{ + + private static final HashSet choice2 = new HashSet<>(); + + static { choice2.add("Untap"); choice2.add("Tap"); } - + public TurnaboutEffect() { super(Outcome.Benefit); staticText = "Choose artifact, creature, or land. Tap all untapped permanents of the chosen type target player controls, or untap all tapped permanents of that type that player controls"; @@ -107,52 +105,56 @@ class TurnaboutEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); + Player controller = game.getPlayer(source.getControllerId()); UUID target = source.getFirstTarget(); - if(player != null && target != null){ + if (controller != null && target != null) { Choice choiceImpl = new ChoiceImpl(); choiceImpl.setChoices(choice); - while(!player.choose(outcome.Neutral, choiceImpl, game)); + while (!controller.choose(Outcome.Neutral, choiceImpl, game)) { + if (!controller.isInGame()) { + return false; + } + } CardType type; String choosenType = choiceImpl.getChoice(); - - if(choosenType.equals(CardType.ARTIFACT.toString())){ + + if (choosenType.equals(CardType.ARTIFACT.toString())) { type = CardType.ARTIFACT; - }else if(choosenType.equals(CardType.LAND.toString())){ + } else if (choosenType.equals(CardType.LAND.toString())) { type = CardType.LAND; - }else{ - type = CardType.CREATURE; + } else { + type = CardType.CREATURE; } - + choiceImpl = new ChoiceImpl(); choiceImpl.setChoices(choice2); - while(!player.choose(outcome.Neutral, choiceImpl, game)); - + while (!controller.choose(Outcome.Neutral, choiceImpl, game)) { + if (!controller.isInGame()) { + return false; + } + } + FilterPermanent filter = new FilterPermanent(); filter.add(new CardTypePredicate(type)); - - - if(choiceImpl.getChoice().equals("Untap")){ + + if (choiceImpl.getChoice().equals("Untap")) { filter.add(new TappedPredicate()); for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - if(permanent.getControllerId().equals(target)){ + if (permanent.getControllerId().equals(target)) { permanent.untap(game); } } - } - else{ + } else { filter.add(Predicates.not(new TappedPredicate())); for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - if(permanent.getControllerId().equals(target)){ + if (permanent.getControllerId().equals(target)) { permanent.tap(game); } } } - - + } - - + return true; } -} \ No newline at end of file +} From 548a53e32ee25055c52f6b0a282a55d602520ba6 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 19 Feb 2015 14:20:08 +0100 Subject: [PATCH 15/23] * Penumbra Wurm - Fixed wrong P/T of created token from 3/3 to 6/6. --- .../src/mage/sets/apocalypse/PenumbraWurm.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Mage.Sets/src/mage/sets/apocalypse/PenumbraWurm.java b/Mage.Sets/src/mage/sets/apocalypse/PenumbraWurm.java index b0d5727071..5362ef89d5 100644 --- a/Mage.Sets/src/mage/sets/apocalypse/PenumbraWurm.java +++ b/Mage.Sets/src/mage/sets/apocalypse/PenumbraWurm.java @@ -28,13 +28,13 @@ package mage.sets.apocalypse; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.game.permanent.token.Token; /** @@ -47,10 +47,14 @@ public class PenumbraWurm extends CardImpl { super(ownerId, 84, "Penumbra Wurm", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{G}{G}"); this.expansionSetCode = "APC"; this.subtype.add("Wurm"); - this.color.setGreen(true); + this.power = new MageInt(6); this.toughness = new MageInt(6); + + // Trample this.addAbility(TrampleAbility.getInstance()); + + // When Penumbra Wurm dies, put a 6/6 black Wurm creature token with trample onto the battlefield. this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new PenumbraWurmToken(), 1), false)); } @@ -70,8 +74,9 @@ class PenumbraWurmToken extends Token { cardType.add(CardType.CREATURE); color.setBlack(true); subtype.add("Wurm"); - power = new MageInt(3); - toughness = new MageInt(3); + power = new MageInt(6); + toughness = new MageInt(6); + this.addAbility(TrampleAbility.getInstance()); } -} \ No newline at end of file +} From 0dcb496b2ef60277a9c2643bc722769b8a010cf0 Mon Sep 17 00:00:00 2001 From: myersn024 Date: Thu, 19 Feb 2015 08:31:03 -0600 Subject: [PATCH 16/23] Updated based on recommendations from LevelX2 --- Mage.Sets/src/mage/sets/fifthdawn/EonHub.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java b/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java index f9a79e83b4..18bf50f662 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/EonHub.java @@ -14,6 +14,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; +import mage.players.Player; /** * @@ -43,7 +44,7 @@ public class EonHub extends CardImpl { class SkipUpkeepStepEffect extends ContinuousRuleModifiyingEffectImpl { public SkipUpkeepStepEffect() { - super(Duration.WhileOnBattlefield, Outcome.Neutral); + super(Duration.WhileOnBattlefield, Outcome.Neutral, false, false); staticText = "Players skip their upkeep steps"; } @@ -58,6 +59,7 @@ class SkipUpkeepStepEffect extends ContinuousRuleModifiyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getType() == EventType.UPKEEP_STEP; + Player controller = game.getPlayer(source.getControllerId()); + return event.getType() == EventType.UPKEEP_STEP && controller != null && controller.getInRange().contains(event.getPlayerId()); } } From b3e9731549986b6bd82fdd72f9e022c152618ed2 Mon Sep 17 00:00:00 2001 From: fireshoes Date: Thu, 19 Feb 2015 12:58:14 -0600 Subject: [PATCH 17/23] Updated Control of the Court, Goblin Lore, Sisay's RIng, Ur Golem's Eye, Dragon Mage, and Helm of Possession --- .../src/mage/sets/darksteel/UrGolemsEye.java | 144 ++++++++---------- .../ControlOfTheCourt.java | 49 +----- .../src/mage/sets/scourge/DragonMage.java | 51 +------ .../mage/sets/seventhedition/SisaysRing.java | 24 +-- .../mage/sets/tempest/HelmOfPossession.java | 4 +- Mage.Sets/src/mage/sets/tenth/GoblinLore.java | 52 +------ 6 files changed, 94 insertions(+), 230 deletions(-) diff --git a/Mage.Sets/src/mage/sets/darksteel/UrGolemsEye.java b/Mage.Sets/src/mage/sets/darksteel/UrGolemsEye.java index 1c5b141dce..00a0be0f4a 100644 --- a/Mage.Sets/src/mage/sets/darksteel/UrGolemsEye.java +++ b/Mage.Sets/src/mage/sets/darksteel/UrGolemsEye.java @@ -1,79 +1,65 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ - -package mage.sets.darksteel; - -import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.Mana; -import mage.abilities.effects.common.BasicManaEffect; -import mage.abilities.mana.BasicManaAbility; -import mage.cards.CardImpl; - -/** - * - * @author Loki - */ -public class UrGolemsEye extends CardImpl { - - public UrGolemsEye (UUID ownerId) { - super(ownerId, 155, "Ur-Golem's Eye", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{4}"); - this.expansionSetCode = "DST"; - this.addAbility(new UrGolemsEyeAbility()); - } - - public UrGolemsEye (final UrGolemsEye card) { - super(card); - } - - @Override - public UrGolemsEye copy() { - return new UrGolemsEye(this); - } - -} - -class UrGolemsEyeAbility extends BasicManaAbility { - - public UrGolemsEyeAbility() { - super(new BasicManaEffect(new Mana(0, 0, 0, 0, 0, 2, 0))); - this.netMana.add(new Mana(0, 0, 0, 0, 0, 2, 0)); - } - - public UrGolemsEyeAbility(final UrGolemsEyeAbility ability) { - super(ability); - } - - @Override - public UrGolemsEyeAbility copy() { - return new UrGolemsEyeAbility(this); - } -} - +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.sets.darksteel; + +import java.util.UUID; + +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.Mana; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.Zone; + +/** + * + * @author Loki + */ +public class UrGolemsEye extends CardImpl { + + public UrGolemsEye (UUID ownerId) { + super(ownerId, 155, "Ur-Golem's Eye", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "DST"; + + // {tap}: Add {2} to your mana pool. + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new Mana(0,0,0,0,0,2,0), new TapSourceCost())); + } + + public UrGolemsEye (final UrGolemsEye card) { + super(card); + } + + @Override + public UrGolemsEye copy() { + return new UrGolemsEye(this); + } + +} + diff --git a/Mage.Sets/src/mage/sets/portalthreekingdoms/ControlOfTheCourt.java b/Mage.Sets/src/mage/sets/portalthreekingdoms/ControlOfTheCourt.java index 504aeb4df0..7e3a19baef 100644 --- a/Mage.Sets/src/mage/sets/portalthreekingdoms/ControlOfTheCourt.java +++ b/Mage.Sets/src/mage/sets/portalthreekingdoms/ControlOfTheCourt.java @@ -28,16 +28,12 @@ package mage.sets.portalthreekingdoms; import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; import mage.cards.CardImpl; -import mage.cards.Cards; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; -import mage.game.Game; -import mage.players.Player; /** * @@ -50,7 +46,10 @@ public class ControlOfTheCourt extends CardImpl { this.expansionSetCode = "PTK"; // Draw four cards, then discard three cards at random. - this.getSpellAbility().addEffect(new ControlOfTheCourtEffect()); + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4)); + Effect effect = new DiscardControllerEffect(3, true); + effect.setText("then discard three cards at random"); + this.getSpellAbility().addEffect(effect); } public ControlOfTheCourt(final ControlOfTheCourt card) { @@ -61,38 +60,4 @@ public class ControlOfTheCourt extends CardImpl { public ControlOfTheCourt copy() { return new ControlOfTheCourt(this); } -} - -class ControlOfTheCourtEffect extends OneShotEffect { - - public ControlOfTheCourtEffect() { - super(Outcome.DrawCard); - this.staticText = "Draw four cards, then discard three cards at random"; - } - - public ControlOfTheCourtEffect(final ControlOfTheCourtEffect effect) { - super(effect); - } - - @Override - public ControlOfTheCourtEffect copy() { - return new ControlOfTheCourtEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - player.drawCards(4, game); - Cards hand = player.getHand(); - for (int i = 0; i < 3; i++) { - Card card = hand.getRandom(game); - if (card != null) { - player.discard(card, source, game); - } - } - return true; - } - return false; - } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/scourge/DragonMage.java b/Mage.Sets/src/mage/sets/scourge/DragonMage.java index 402eaccd77..5d5e9ebe16 100644 --- a/Mage.Sets/src/mage/sets/scourge/DragonMage.java +++ b/Mage.Sets/src/mage/sets/scourge/DragonMage.java @@ -31,16 +31,13 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DrawCardAllEffect; +import mage.abilities.effects.common.discard.DiscardHandAllEffect; import mage.abilities.keyword.FlyingAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; -import mage.game.Game; -import mage.players.Player; /** * @@ -59,7 +56,11 @@ public class DragonMage extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Whenever Dragon Mage deals combat damage to a player, each player discards his or her hand and draws seven cards. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DragonMageEffect(), false)); + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DiscardHandAllEffect(), false); + Effect effect = new DrawCardAllEffect(7); + effect.setText("and draws seven cards"); + ability.addEffect(effect); + this.addAbility(ability); } public DragonMage(final DragonMage card) { @@ -70,40 +71,4 @@ public class DragonMage extends CardImpl { public DragonMage copy() { return new DragonMage(this); } -} - -class DragonMageEffect extends OneShotEffect { - - public DragonMageEffect() { - super(Outcome.DrawCard); - this.staticText = "Each player discards his or her hand, then draws seven cards"; - } - - public DragonMageEffect(final DragonMageEffect effect) { - super(effect); - } - - @Override - public DragonMageEffect copy() { - return new DragonMageEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (UUID playerId : controller.getInRange()) { - Player player = game.getPlayer(playerId); - if (player != null) { - for (Card card : player.getHand().getCards(game)) { - player.discard(card, source, game); - } - - player.drawCards(7, game); - } - } - return true; - } - return false; - } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/seventhedition/SisaysRing.java b/Mage.Sets/src/mage/sets/seventhedition/SisaysRing.java index 284553f45f..9232bea4d4 100644 --- a/Mage.Sets/src/mage/sets/seventhedition/SisaysRing.java +++ b/Mage.Sets/src/mage/sets/seventhedition/SisaysRing.java @@ -29,11 +29,12 @@ package mage.sets.seventhedition; import java.util.UUID; import mage.Mana; -import mage.abilities.effects.common.BasicManaEffect; -import mage.abilities.mana.BasicManaAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; +import mage.constants.Zone; /** * @@ -46,7 +47,7 @@ public class SisaysRing extends CardImpl { this.expansionSetCode = "7ED"; // {tap}: Add {2} to your mana pool. - this.addAbility(new SisaysRingAbility()); + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new Mana(0,0,0,0,0,2,0), new TapSourceCost())); } public SisaysRing(final SisaysRing card) { @@ -57,21 +58,4 @@ public class SisaysRing extends CardImpl { public SisaysRing copy() { return new SisaysRing(this); } -} - -class SisaysRingAbility extends BasicManaAbility { - - public SisaysRingAbility() { - super(new BasicManaEffect(new Mana(0, 0, 0, 0, 0, 2, 0))); - this.netMana.add(new Mana(0, 0, 0, 0, 0, 2, 0)); - } - - public SisaysRingAbility(final SisaysRingAbility ability) { - super(ability); - } - - @Override - public SisaysRingAbility copy() { - return new SisaysRingAbility(this); - } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java b/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java index 525e9385f2..df74b9f609 100644 --- a/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java +++ b/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java @@ -61,9 +61,9 @@ public class HelmOfPossession extends CardImpl { // {2}, {tap}, Sacrifice a creature: Gain control of target creature for as long as you control Helm of Possession and Helm of Possession remains tapped. ConditionalContinousEffect effect = new ConditionalContinousEffect( - new GainControlTargetEffect(Duration.OneUse), + new GainControlTargetEffect(Duration.Custom), new HelmOfPossessionCondition(), - "Gain control of target creature for as long as you control Helm of Possession and Helm of Possession remains tapped"); + "Gain control of target creature for as long as you control {this} and {this} remains tapped"); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent())); diff --git a/Mage.Sets/src/mage/sets/tenth/GoblinLore.java b/Mage.Sets/src/mage/sets/tenth/GoblinLore.java index 82e1175967..3044328568 100644 --- a/Mage.Sets/src/mage/sets/tenth/GoblinLore.java +++ b/Mage.Sets/src/mage/sets/tenth/GoblinLore.java @@ -29,15 +29,11 @@ package mage.sets.tenth; import java.util.UUID; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; import mage.cards.CardImpl; -import mage.cards.Cards; -import mage.game.Game; -import mage.players.Player; /** * @@ -52,8 +48,10 @@ public class GoblinLore extends CardImpl { this.color.setRed(true); // Draw four cards, then discard three cards at random. - this.getSpellAbility().addEffect(new GoblinLoreEffect()); - } + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4)); + Effect effect = new DiscardControllerEffect(3, true); + effect.setText("then discard three cards at random"); + this.getSpellAbility().addEffect(effect); } public GoblinLore(final GoblinLore card) { super(card); @@ -63,38 +61,4 @@ public class GoblinLore extends CardImpl { public GoblinLore copy() { return new GoblinLore(this); } -} - -class GoblinLoreEffect extends OneShotEffect { - - public GoblinLoreEffect() { - super(Outcome.DrawCard); - this.staticText = "Draw four cards, then discard three cards at random"; - } - - public GoblinLoreEffect(final GoblinLoreEffect effect) { - super(effect); - } - - @Override - public GoblinLoreEffect copy() { - return new GoblinLoreEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - player.drawCards(4, game); - Cards hand = player.getHand(); - for (int i = 0; i < 3; i++) { - Card card = hand.getRandom(game); - if (card != null) { - player.discard(card, source, game); - } - } - return true; - } - return false; - } -} +} \ No newline at end of file From e3ebbae5beef31e8cd1f908031943eca92ace372 Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 19 Feb 2015 15:48:23 -0600 Subject: [PATCH 18/23] - Added Barkshell Blessing, Ghastly Discovery, Giantbaiting, and Traitors Roar. --- .../sets/shadowmoor/BarkshellBlessing.java | 65 ++++++++++ .../sets/shadowmoor/GhastlyDiscovery.java | 94 ++++++++++++++ .../mage/sets/shadowmoor/Giantbaiting.java | 121 ++++++++++++++++++ .../mage/sets/shadowmoor/TraitorsRoar.java | 111 ++++++++++++++++ 4 files changed, 391 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/shadowmoor/BarkshellBlessing.java create mode 100644 Mage.Sets/src/mage/sets/shadowmoor/GhastlyDiscovery.java create mode 100644 Mage.Sets/src/mage/sets/shadowmoor/Giantbaiting.java create mode 100644 Mage.Sets/src/mage/sets/shadowmoor/TraitorsRoar.java diff --git a/Mage.Sets/src/mage/sets/shadowmoor/BarkshellBlessing.java b/Mage.Sets/src/mage/sets/shadowmoor/BarkshellBlessing.java new file mode 100644 index 0000000000..c806574d51 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/BarkshellBlessing.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.shadowmoor; + +import java.util.UUID; +import mage.abilities.effects.common.continious.BoostTargetEffect; +import mage.abilities.keyword.ConspireAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author jeffwadsworth + */ +public class BarkshellBlessing extends CardImpl { + + public BarkshellBlessing(UUID ownerId) { + super(ownerId, 224, "Barkshell Blessing", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{G/W}"); + this.expansionSetCode = "SHM"; + + // Target creature gets +2/+2 until end of turn. + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); + + // Conspire + this.addAbility(new ConspireAbility(this)); + } + + public BarkshellBlessing(final BarkshellBlessing card) { + super(card); + } + + @Override + public BarkshellBlessing copy() { + return new BarkshellBlessing(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/GhastlyDiscovery.java b/Mage.Sets/src/mage/sets/shadowmoor/GhastlyDiscovery.java new file mode 100644 index 0000000000..2b317197e3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/GhastlyDiscovery.java @@ -0,0 +1,94 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.shadowmoor; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.ConspireAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author jeffwadsworth + */ +public class GhastlyDiscovery extends CardImpl { + + public GhastlyDiscovery(UUID ownerId) { + super(ownerId, 39, "Ghastly Discovery", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{U}"); + this.expansionSetCode = "SHM"; + + // Draw two cards, then discard a card. + this.getSpellAbility().addEffect(new GhastlyDiscoveryEffect()); + + // Conspire + this.addAbility(new ConspireAbility(this)); + } + + public GhastlyDiscovery(final GhastlyDiscovery card) { + super(card); + } + + @Override + public GhastlyDiscovery copy() { + return new GhastlyDiscovery(this); + } +} + +class GhastlyDiscoveryEffect extends OneShotEffect { + + public GhastlyDiscoveryEffect() { + super(Outcome.Benefit); + this.staticText = "Draw two cards, then discard a card"; + } + + public GhastlyDiscoveryEffect(final GhastlyDiscoveryEffect effect) { + super(effect); + } + + @Override + public GhastlyDiscoveryEffect copy() { + return new GhastlyDiscoveryEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + controller.drawCards(2, game); + controller.discard(1, false, source, game); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/Giantbaiting.java b/Mage.Sets/src/mage/sets/shadowmoor/Giantbaiting.java new file mode 100644 index 0000000000..8a291f6b3e --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/Giantbaiting.java @@ -0,0 +1,121 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.shadowmoor; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.keyword.ConspireAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.permanent.token.Token; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author jeffwadsworth + */ +public class Giantbaiting extends CardImpl { + + public Giantbaiting(UUID ownerId) { + super(ownerId, 207, "Giantbaiting", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{R/G}"); + this.expansionSetCode = "SHM"; + + // Put a 4/4 red and green Giant Warrior creature token with haste onto the battlefield. Exile it at the beginning of the next end step. + this.getSpellAbility().addEffect(new GiantbaitingEffect()); + + // Conspire + this.addAbility(new ConspireAbility(this)); + + } + + public Giantbaiting(final Giantbaiting card) { + super(card); + } + + @Override + public Giantbaiting copy() { + return new Giantbaiting(this); + } +} + +class GiantbaitingEffect extends OneShotEffect { + + public GiantbaitingEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Put a 4/4 red and green Giant Warrior creature token with haste onto the battlefield. Exile it at the beginning of the next end step"; + } + + public GiantbaitingEffect(final GiantbaitingEffect effect) { + super(effect); + } + + @Override + public GiantbaitingEffect copy() { + return new GiantbaitingEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Token token = new GiantWarriorToken(); + if (token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId())) { + ExileTargetEffect exileEffect = new ExileTargetEffect(); + exileEffect.setTargetPointer(new FixedTarget(token.getLastAddedToken())); + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect); + delayedAbility.setSourceId(source.getSourceId()); + delayedAbility.setControllerId(source.getControllerId()); + delayedAbility.setSourceObject(source.getSourceObject(game)); + game.addDelayedTriggeredAbility(delayedAbility); + return true; + } + return false; + } +} + +class GiantWarriorToken extends Token { + + GiantWarriorToken() { + super("Giant Warrior", "4/4 red and green Giant Warrior creature token with haste"); + cardType.add(CardType.CREATURE); + color.setRed(true); + color.setGreen(true); + subtype.add("Giant"); + subtype.add("Warrior"); + power = new MageInt(4); + toughness = new MageInt(4); + this.addAbility(HasteAbility.getInstance()); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/TraitorsRoar.java b/Mage.Sets/src/mage/sets/shadowmoor/TraitorsRoar.java new file mode 100644 index 0000000000..90021a3dbb --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/TraitorsRoar.java @@ -0,0 +1,111 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.shadowmoor; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.ConspireAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author jeffwadsworth + */ +public class TraitorsRoar extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creature"); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public TraitorsRoar(UUID ownerId) { + super(ownerId, 200, "Traitor's Roar", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{4}{B/R}"); + this.expansionSetCode = "SHM"; + + // Tap target untapped creature. It deals damage equal to its power to its controller. + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addEffect(new TraitorsRoarEffect()); + + // Conspire + this.addAbility(new ConspireAbility(this)); + + } + + public TraitorsRoar(final TraitorsRoar card) { + super(card); + } + + @Override + public TraitorsRoar copy() { + return new TraitorsRoar(this); + } +} + +class TraitorsRoarEffect extends OneShotEffect { + + public TraitorsRoarEffect() { + super(Outcome.Detriment); + this.staticText = "Tap target untapped creature. It deals damage equal to its power to its controller"; + } + + public TraitorsRoarEffect(final TraitorsRoarEffect effect) { + super(effect); + } + + @Override + public TraitorsRoarEffect copy() { + return new TraitorsRoarEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + boolean applied = false; + Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source)); + if (targetCreature != null) { + applied = targetCreature.tap(game); + Player controller = game.getPlayer(targetCreature.getControllerId()); + if (controller != null) { + controller.damage(targetCreature.getPower().getValue(), source.getSourceId(), game, false, true); + applied = true; + } + } + return applied; + } +} From 019f6722a7076f50637aaebc8c94f1ef00b29ecd Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 20 Feb 2015 02:14:32 +0100 Subject: [PATCH 19/23] * Some minor changes. --- .../src/mage/sets/conflux/QuenchableFire.java | 6 ++- .../mage/sets/jacevsvraska/OhranViper.java | 41 ++++--------------- .../mirrodinbesieged/ContestedWarZone.java | 17 +++++--- .../sets/scarsofmirrodin/LeoninArbiter.java | 22 +++++++--- ...TheEndOfCombatDelayedTriggeredAbility.java | 6 ++- .../costs/common/ExileFromGraveCost.java | 15 ++++++- .../CreateDelayedTriggeredAbilityEffect.java | 12 ++++-- Mage/src/mage/util/ManaUtil.java | 2 +- 8 files changed, 69 insertions(+), 52 deletions(-) diff --git a/Mage.Sets/src/mage/sets/conflux/QuenchableFire.java b/Mage.Sets/src/mage/sets/conflux/QuenchableFire.java index fb8c888ef1..381ff57eae 100644 --- a/Mage.Sets/src/mage/sets/conflux/QuenchableFire.java +++ b/Mage.Sets/src/mage/sets/conflux/QuenchableFire.java @@ -56,7 +56,9 @@ public class QuenchableFire extends CardImpl { public QuenchableFire(UUID ownerId) { super(ownerId, 70, "Quenchable Fire", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{R}"); this.expansionSetCode = "CON"; - this.color.setRed(true); + + // Quenchable Fire deals 3 damage to target player. + // It deals an additional 3 damage to that player at the beginning of your next upkeep step unless he or she pays {U} before that step. this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addEffect(new DamageTargetEffect(3)); this.getSpellAbility().addEffect(new QuenchableFireEffect()); @@ -97,6 +99,7 @@ class QuenchableFireEffect extends OneShotEffect { delayedAbility.setSourceObject(source.getSourceObject(game)); delayedAbility.getTargets().addAll(source.getTargets()); game.addDelayedTriggeredAbility(delayedAbility); + //create special action QuenchableFireSpecialAction newAction = new QuenchableFireSpecialAction(delayedAbility.getId()); delayedAbility.setSpecialActionId(newAction.getId()); @@ -149,6 +152,7 @@ class QuenchableFireDelayedTriggeredAbility extends DelayedTriggeredAbility { class QuenchableFireSpecialAction extends SpecialAction { public QuenchableFireSpecialAction(UUID effectId) { + super(); this.addCost(new ManaCostsImpl("{U}")); this.addEffect(new RemoveDelayedTriggeredAbilityEffect(effectId)); this.addEffect(new RemoveSpecialActionEffect(this.getId())); diff --git a/Mage.Sets/src/mage/sets/jacevsvraska/OhranViper.java b/Mage.Sets/src/mage/sets/jacevsvraska/OhranViper.java index 10cb589e3d..54ecd4de0f 100644 --- a/Mage.Sets/src/mage/sets/jacevsvraska/OhranViper.java +++ b/Mage.Sets/src/mage/sets/jacevsvraska/OhranViper.java @@ -34,6 +34,7 @@ import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; @@ -56,12 +57,16 @@ public class OhranViper extends CardImpl { this.supertype.add("Snow"); this.subtype.add("Snake"); - this.color.setGreen(true); this.power = new MageInt(1); this.toughness = new MageInt(3); // Whenever Ohran Viper deals combat damage to a creature, destroy that creature at end of combat. - this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility(new OhranViperDestroyEffect(), false, true)); + this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility( + new CreateDelayedTriggeredAbilityEffect( + new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect("destroy that creature at end of combat")), true), + false, + true)); + // Whenever Ohran Viper deals combat damage to a player, you may draw a card. this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), true)); } @@ -75,35 +80,3 @@ public class OhranViper extends CardImpl { return new OhranViper(this); } } - -class OhranViperDestroyEffect extends OneShotEffect { - - OhranViperDestroyEffect() { - super(Outcome.DestroyPermanent); - staticText = "destroy that creature at end of combat"; - } - - OhranViperDestroyEffect(final OhranViperDestroyEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (targetCreature != null) { - AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()); - delayedAbility.setSourceId(source.getSourceId()); - delayedAbility.setControllerId(source.getControllerId()); - delayedAbility.setSourceObject(source.getSourceObject(game)); - delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(targetCreature.getId())); - game.addDelayedTriggeredAbility(delayedAbility); - return true; - } - return false; - } - - @Override - public OhranViperDestroyEffect copy() { - return new OhranViperDestroyEffect(this); - } -} diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/ContestedWarZone.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/ContestedWarZone.java index f61d7dfae0..79ec587b60 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/ContestedWarZone.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/ContestedWarZone.java @@ -28,6 +28,7 @@ package mage.sets.mirrodinbesieged; import java.util.UUID; +import mage.Mana; import mage.constants.CardType; import mage.constants.Duration; @@ -45,6 +46,7 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.continious.BoostAllEffect; import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.filter.common.FilterAttackingCreature; import mage.game.Game; @@ -102,13 +104,18 @@ class ContestedWarZoneAbility extends TriggeredAbilityImpl { return new ContestedWarZoneAbility(this); } + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event instanceof DamagedPlayerEvent) { - DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; - Permanent p = game.getPermanent(event.getSourceId()); - if (damageEvent.getPlayerId().equals(controllerId) && damageEvent.isCombatDamage() && p != null && p.getCardType().contains(CardType.CREATURE)) { - game.getState().setValue(sourceId.toString(), p.getControllerId()); + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; + if (damageEvent.isCombatDamage()) { + Permanent permanent = game.getPermanent(event.getSourceId()); + if (damageEvent.getPlayerId().equals(getControllerId()) && permanent != null && permanent.getCardType().contains(CardType.CREATURE)) { + game.getState().setValue(getSourceId().toString(), permanent.getControllerId()); return true; } } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/LeoninArbiter.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/LeoninArbiter.java index 78a947af4e..4d57695e39 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/LeoninArbiter.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/LeoninArbiter.java @@ -27,16 +27,25 @@ */ package mage.sets.scarsofmirrodin; -import java.util.*; - -import mage.abilities.SpecialAction; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.*; -import mage.constants.*; +import java.util.AbstractMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.SpecialAction; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; +import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; @@ -62,6 +71,7 @@ public class LeoninArbiter extends CardImpl { // Players can't search libraries. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LeoninArbiterCantSearchEffect(keyString))); + // Any player may pay {2} for that player to ignore this effect until end of turn. this.addAbility(new LeoninArbiterSpecialAction(keyString)); } diff --git a/Mage/src/mage/abilities/common/delayed/AtTheEndOfCombatDelayedTriggeredAbility.java b/Mage/src/mage/abilities/common/delayed/AtTheEndOfCombatDelayedTriggeredAbility.java index 33eef81a18..6cec07678c 100644 --- a/Mage/src/mage/abilities/common/delayed/AtTheEndOfCombatDelayedTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/delayed/AtTheEndOfCombatDelayedTriggeredAbility.java @@ -31,6 +31,10 @@ public class AtTheEndOfCombatDelayedTriggeredAbility extends DelayedTriggeredAbi @Override public String getRule() { - return "At end of combat, " + modes.getText(); + String ruleText = modes.getText(); + if (ruleText.contains("at end of combat")) { + return ruleText; + } + return "At end of combat, " + ruleText; } } diff --git a/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java b/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java index 7dd5fef4bd..8d7ce093b8 100644 --- a/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java +++ b/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java @@ -28,6 +28,8 @@ package mage.abilities.costs.common; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.CostImpl; @@ -46,10 +48,16 @@ import mage.util.CardUtil; */ public class ExileFromGraveCost extends CostImpl { + private final List exiledCards = new ArrayList<>(); + public ExileFromGraveCost(TargetCardInYourGraveyard target) { this.addTarget(target); if (target.getMaxNumberOfTargets() > 1) { - this.text = "Exile " + CardUtil.numberToText(target.getMaxNumberOfTargets()) + " " + target.getTargetName(); + this.text = "Exile " + + (target.getNumberOfTargets() < target.getMaxNumberOfTargets() ? "up to ":"") + + CardUtil.numberToText(target.getMaxNumberOfTargets()) + + " " + + target.getTargetName(); } else { this.text = "Exile " + target.getTargetName(); @@ -72,6 +80,7 @@ public class ExileFromGraveCost extends CostImpl { public ExileFromGraveCost(final ExileFromGraveCost cost) { super(cost); + this.exiledCards.addAll(cost.getExiledCards()); } @Override @@ -84,6 +93,7 @@ public class ExileFromGraveCost extends CostImpl { if (card == null || !game.getState().getZone(targetId).equals(Zone.GRAVEYARD)) { return false; } + exiledCards.add(card); paid |= controller.moveCardToExileWithInfo(card, null, null, sourceId, game, Zone.GRAVEYARD); } } @@ -102,4 +112,7 @@ public class ExileFromGraveCost extends CostImpl { return new ExileFromGraveCost(this); } + public List getExiledCards() { + return exiledCards; + } } diff --git a/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java b/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java index c896fb6652..08627a8d60 100644 --- a/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java +++ b/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java @@ -72,9 +72,15 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect { delayedAbility.setControllerId(source.getControllerId()); delayedAbility.setSourceObject(source.getSourceObject(game)); if (this.copyTargets) { - delayedAbility.getTargets().addAll(source.getTargets()); - for(Effect effect : delayedAbility.getEffects()) { - effect.getTargetPointer().init(game, source); + if (source.getTargets().isEmpty()) { + for(Effect effect : delayedAbility.getEffects()) { + effect.setTargetPointer(targetPointer); + } + } else { + delayedAbility.getTargets().addAll(source.getTargets()); + for(Effect effect : delayedAbility.getEffects()) { + effect.getTargetPointer().init(game, source); + } } } game.addDelayedTriggeredAbility(delayedAbility); diff --git a/Mage/src/mage/util/ManaUtil.java b/Mage/src/mage/util/ManaUtil.java index 7dcb73a38b..160a483d45 100644 --- a/Mage/src/mage/util/ManaUtil.java +++ b/Mage/src/mage/util/ManaUtil.java @@ -85,7 +85,7 @@ public class ManaUtil { chosenManaAbility = chosenManaAbilityForHybrid != null ? chosenManaAbilityForHybrid : chosenManaAbility; } - if (countColored.size() == 0) { // seems there is no colorful mana we can pay for + if (countColored.isEmpty()) { // seems there is no colorful mana we can pay for // try to pay {1} if (unpaidMana.getColorless() > 0) { // use any (lets choose first) From 0c730768955215d5bd1480c6ed8bfc7f78658a78 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 20 Feb 2015 02:15:22 +0100 Subject: [PATCH 20/23] * Added AlternateManaPaymentAbility interface and handling. --- Mage.Common/src/mage/view/GameView.java | 14 +++++- .../src/mage/player/human/HumanPlayer.java | 38 +++++++++++--- .../fatereforged/GhastlyConscription.java | 5 -- Mage/src/mage/abilities/SpecialAction.java | 23 ++++++++- Mage/src/mage/abilities/SpecialActions.java | 20 +++++++- .../mana/AlternateManaPaymentAbility.java | 50 +++++++++++++++++++ .../abilities/costs/mana/ManaCostsImpl.java | 28 +++++++++-- 7 files changed, 158 insertions(+), 20 deletions(-) create mode 100644 Mage/src/mage/abilities/costs/mana/AlternateManaPaymentAbility.java diff --git a/Mage.Common/src/mage/view/GameView.java b/Mage.Common/src/mage/view/GameView.java index e82272227f..bd6203a9ee 100644 --- a/Mage.Common/src/mage/view/GameView.java +++ b/Mage.Common/src/mage/view/GameView.java @@ -84,10 +84,14 @@ public class GameView implements Serializable { public GameView(GameState state, Game game, UUID createdForPlayerId, UUID watcherUserId) { + Player createdForPlayer = null; this.isPlayer = createdForPlayerId != null; this.priorityTime = game.getPriorityTime(); for (Player player: state.getPlayers().values()) { players.add(new PlayerView(player, state, game, createdForPlayerId, watcherUserId)); + if (player.getId().equals(createdForPlayerId)) { + createdForPlayer = player; + } } for (StackObject stackObject: state.getStack()) { if (stackObject instanceof StackAbility) { @@ -161,7 +165,15 @@ public class GameView implements Serializable { for (CombatGroup combatGroup: state.getCombat().getGroups()) { combat.add(new CombatGroupView(combatGroup, game)); } - this.special = state.getSpecialActions().getControlledBy(state.getPriorityPlayerId()).size() > 0; + if (isPlayer) { + // has only to be set for active palyer with priority (e.g. pay mana by delve or Quenchable Fire special action) + if (state.getPriorityPlayerId() == createdForPlayerId && createdForPlayer != null) { + this.special = state.getSpecialActions().getControlledBy(state.getPriorityPlayerId(), createdForPlayer.isInPayManaMode()).size() > 0; + } + } else { + this.special = false; + } + CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher"); if (watcher != null) { spellsCastCurrentTurn = watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn(); diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index dafa114022..9c863bc9f3 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -627,6 +627,8 @@ public class HumanPlayer extends PlayerImpl { playManaAbilities(unpaid, game); } else if (response.getString() != null && response.getString().equals("special")) { if (unpaid instanceof ManaCostsImpl) { + specialManaAction(unpaid, game); + // TODO: delve or convoke cards with PhyrexianManaCost won't work together (this combinaton does not exist yet) ManaCostsImpl costs = (ManaCostsImpl) unpaid; for (ManaCost cost : costs.getUnpaid()) { if (cost instanceof PhyrexianManaCost) { @@ -970,14 +972,34 @@ public class HumanPlayer extends PlayerImpl { draft.firePickCardEvent(playerId); } - protected void specialAction(Game game) { - updateGameStatePriority("specialAction", game); - LinkedHashMap specialActions = game.getState().getSpecialActions().getControlledBy(playerId); - game.fireGetChoiceEvent(playerId, name, null, new ArrayList<>(specialActions.values())); - waitForResponse(game); - if (response.getUUID() != null) { - if (specialActions.containsKey(response.getUUID())) { - activateAbility(specialActions.get(response.getUUID()), game); + protected void specialAction(Game game) { + LinkedHashMap specialActions = game.getState().getSpecialActions().getControlledBy(playerId, false); + if (!specialActions.isEmpty()) { + updateGameStatePriority("specialAction", game); + game.fireGetChoiceEvent(playerId, name, null, new ArrayList<>(specialActions.values())); + waitForResponse(game); + if (response.getUUID() != null) { + if (specialActions.containsKey(response.getUUID())) { + activateAbility(specialActions.get(response.getUUID()), game); + } + } + } + } + + protected void specialManaAction(ManaCost unpaid, Game game) { + LinkedHashMap specialActions = game.getState().getSpecialActions().getControlledBy(playerId, true); + if (!specialActions.isEmpty()) { + updateGameStatePriority("specialAction", game); + game.fireGetChoiceEvent(playerId, name, null, new ArrayList<>(specialActions.values())); + waitForResponse(game); + if (response.getUUID() != null) { + if (specialActions.containsKey(response.getUUID())) { + SpecialAction specialAction = specialActions.get(response.getUUID()); + if (specialAction != null) { + specialAction.setUnpaidMana(unpaid); + activateAbility(specialActions.get(response.getUUID()), game); + } + } } } } diff --git a/Mage.Sets/src/mage/sets/fatereforged/GhastlyConscription.java b/Mage.Sets/src/mage/sets/fatereforged/GhastlyConscription.java index 4cfac2a503..f4dd69f1cc 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/GhastlyConscription.java +++ b/Mage.Sets/src/mage/sets/fatereforged/GhastlyConscription.java @@ -32,10 +32,8 @@ import java.util.Collections; import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continious.BecomesFaceDownCreatureEffect; import mage.abilities.effects.common.continious.BecomesFaceDownCreatureEffect.FaceDownType; @@ -48,11 +46,8 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.common.FilterCreatureCard; import mage.game.Game; -import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.PermanentCard; import mage.players.Player; import mage.target.TargetPlayer; -import mage.target.targetpointer.FixedTarget; /** * diff --git a/Mage/src/mage/abilities/SpecialAction.java b/Mage/src/mage/abilities/SpecialAction.java index eeae5e6f9f..bd3fdfda70 100644 --- a/Mage/src/mage/abilities/SpecialAction.java +++ b/Mage/src/mage/abilities/SpecialAction.java @@ -28,6 +28,7 @@ package mage.abilities; +import mage.abilities.costs.mana.ManaCost; import mage.constants.AbilityType; import mage.constants.Zone; @@ -37,17 +38,37 @@ import mage.constants.Zone; */ public abstract class SpecialAction extends ActivatedAbilityImpl { + private boolean manaAction; + protected ManaCost unpaidMana; + public SpecialAction() { this(Zone.ALL); } public SpecialAction(Zone zone) { + this(zone, false); + } + public SpecialAction(Zone zone, boolean manaAction) { super(AbilityType.SPECIAL_ACTION, zone); this.usesStack = false; + this.manaAction = manaAction; } public SpecialAction(final SpecialAction action) { super(action); + this.manaAction = action.manaAction; + this.unpaidMana = action.unpaidMana; } -} \ No newline at end of file + public boolean isManaAction() { + return manaAction; + } + + public void setUnpaidMana(ManaCost manaCost) { + this.unpaidMana = manaCost; + } + + public ManaCost getUnpaidMana() { + return unpaidMana; + } +} diff --git a/Mage/src/mage/abilities/SpecialActions.java b/Mage/src/mage/abilities/SpecialActions.java index f0c70e1f94..43ec620b2a 100644 --- a/Mage/src/mage/abilities/SpecialActions.java +++ b/Mage/src/mage/abilities/SpecialActions.java @@ -28,6 +28,7 @@ package mage.abilities; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.UUID; @@ -43,10 +44,17 @@ public class SpecialActions extends AbilitiesImpl { super(actions); } - public LinkedHashMap getControlledBy(UUID controllerId) { + /** + * + * @param controllerId + * @param manaAction true = if mana actions should get returned + * false = only non mana actions get returned + * @return + */ + public LinkedHashMap getControlledBy(UUID controllerId, boolean manaAction) { LinkedHashMap controlledBy = new LinkedHashMap<>(); for (SpecialAction action: this) { - if (action.getControllerId().equals(controllerId)) { + if (action.getControllerId().equals(controllerId) && action.isManaAction() == manaAction) { controlledBy.put(action.id, action); } } @@ -58,4 +66,12 @@ public class SpecialActions extends AbilitiesImpl { return new SpecialActions(this); } + public void removeManaActions() { + for (Iterator iterator = this.iterator(); iterator.hasNext();) { + SpecialAction next = iterator.next(); + if (next.isManaAction()) { + iterator.remove(); + } + } + } } diff --git a/Mage/src/mage/abilities/costs/mana/AlternateManaPaymentAbility.java b/Mage/src/mage/abilities/costs/mana/AlternateManaPaymentAbility.java new file mode 100644 index 0000000000..2b1dfa38e1 --- /dev/null +++ b/Mage/src/mage/abilities/costs/mana/AlternateManaPaymentAbility.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.costs.mana; + +import mage.abilities.Ability; +import mage.game.Game; + +/** + * Interface for abilities that allow the player to pay mana costs of a spell in alternate ways. + * For the payment SpecialActions are used. + * + * Example of such an alternate payment ability: {@link mage.abilities.keyword.DelveAbility} + * + * @author LevelX2 + */ +public interface AlternateManaPaymentAbility { + /** + * Adds the special action to the state, that allows the user to do the alternate mana payment + * + * @param source + * @param game + * @param unpaid unapaid mana costs of the spell + */ + void addSpecialAction(Ability source, Game game, ManaCost unpaid); +} \ No newline at end of file diff --git a/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java b/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java index e2cc69ce2a..7b34a9701c 100644 --- a/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java +++ b/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java @@ -33,9 +33,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import mage.MageObject; import mage.Mana; import mage.abilities.Ability; import mage.abilities.costs.VariableCost; +import mage.abilities.keyword.DelveAbility; import mage.abilities.mana.ManaOptions; import mage.constants.ColoredManaSymbol; import mage.filter.Filter; @@ -117,18 +119,38 @@ public class ManaCostsImpl extends ArrayList implements M } Player player = game.getPlayer(controllerId); - assignPayment(game, ability, player.getManaPool()); + assignPayment(game, ability, player.getManaPool()); while (!isPaid()) { + addSpecialManaPayAbilities(ability, game); if (player.playMana(this.getUnpaid(), game)) { assignPayment(game, ability, player.getManaPool()); - } - else { + } else { return false; } + game.getState().getSpecialActions().removeManaActions(); } return true; } + /** + * This activates the special button if there exists special ways to pay the mana (Delve, Convoke) + * + * @param ability + * @param game + */ + private void addSpecialManaPayAbilities(Ability source, Game game) { + // check for special mana payment possibilities + MageObject mageObject = source.getSourceObject(game); + if (mageObject != null) { + for (Ability ability :mageObject.getAbilities()) { + if (ability instanceof AlternateManaPaymentAbility) { + ((AlternateManaPaymentAbility) ability).addSpecialAction(source, game, getUnpaid()); + } + } + } + } + + /** * bookmarks the current state and restores it if player doesn't pay the mana cost * From 306a0874dd38bf6e02010e887fa84759a5c10bbb Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 20 Feb 2015 02:16:58 +0100 Subject: [PATCH 21/23] * Reworked Delve and Convoke to be more rule conform. --- .../abilities/keyword/ConvokeAbility.java | 260 +++++++++++------- .../mage/abilities/keyword/DelveAbility.java | 132 +++++---- 2 files changed, 250 insertions(+), 142 deletions(-) diff --git a/Mage/src/mage/abilities/keyword/ConvokeAbility.java b/Mage/src/mage/abilities/keyword/ConvokeAbility.java index b56631c0cc..9db9db18ed 100644 --- a/Mage/src/mage/abilities/keyword/ConvokeAbility.java +++ b/Mage/src/mage/abilities/keyword/ConvokeAbility.java @@ -28,28 +28,33 @@ package mage.abilities.keyword; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; +import mage.Mana; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.SpellAbility; +import mage.abilities.SpecialAction; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.AdjustingSourceCosts; +import mage.abilities.costs.mana.AlternateManaPaymentAbility; import mage.abilities.costs.mana.ManaCost; -import mage.abilities.costs.mana.ManaCosts; -import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; import mage.choices.Choice; import mage.choices.ChoiceImpl; +import mage.constants.AbilityType; +import mage.constants.ManaType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.players.ManaPool; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetControlledCreaturePermanent; -import mage.util.CardUtil; /* * 502.46. Convoke @@ -84,13 +89,7 @@ import mage.util.CardUtil; * * @author LevelX2 */ -public class ConvokeAbility extends SimpleStaticAbility implements AdjustingSourceCosts { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); - - static { - filter.add(Predicates.not(new TappedPredicate())); - } +public class ConvokeAbility extends SimpleStaticAbility implements AlternateManaPaymentAbility { public ConvokeAbility() { super(Zone.STACK, null); @@ -107,96 +106,171 @@ public class ConvokeAbility extends SimpleStaticAbility implements AdjustingSour } @Override - public void adjustCosts(Ability ability, Game game) { - Player player = game.getPlayer(controllerId); - if (player == null || !(ability instanceof SpellAbility)) { - return; - } - Target target = new TargetControlledCreaturePermanent(1, Integer.MAX_VALUE, filter,true); - target.setTargetName("creatures to convoke"); - if (!target.canChoose(sourceId, controllerId, game)) { - return; - } - if (player.chooseUse(Outcome.Detriment, "Convoke creatures?", game)) { - player.chooseTarget(Outcome.Tap, target, ability, game); - if (target.getTargets().size() > 0) { - for (UUID creatureId: target.getTargets()) { - Permanent perm = game.getPermanent(creatureId); - if (perm == null || ability.getManaCostsToPay().convertedManaCost() == 0) { - continue; + public void addSpecialAction(Ability source, Game game, ManaCost unpaid) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && controller.getGraveyard().size() > 0) { + if (unpaid.getMana().getColorless() > 0 && source.getAbilityType().equals(AbilityType.SPELL)) { + SpecialAction specialAction = new ConvokeSpecialAction(unpaid); + specialAction.setControllerId(source.getControllerId()); + specialAction.setSourceId(source.getSourceId()); + // create filter for possible creatures to tap + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); + filter.add(Predicates.not(new TappedPredicate())); + if (unpaid.getMana().getColorless() == 0) { + List colorPredicates = new ArrayList<>(); + if (unpaid.getMana().getBlack() > 0) { + colorPredicates.add(new ColorPredicate(ObjectColor.BLACK)); } - if (!perm.isTapped() && perm.tap(game)) { - ManaCosts manaCostsToReduce = new ManaCostsImpl<>(); - int costBefore = ability.getManaCostsToPay().convertedManaCost(); - Choice chooseManaType = buildChoice(perm.getColor(), ability.getManaCostsToPay()); - if (chooseManaType.getChoices().size() > 0) { - if (chooseManaType.getChoices().size() > 1) { - chooseManaType.getChoices().add("Colorless"); - chooseManaType.setMessage("Choose mana color to reduce from " + perm.getName()); - while (!chooseManaType.isChosen()) { - player.choose(Outcome.Benefit, chooseManaType, game); - } - } else { - chooseManaType.setChoice(chooseManaType.getChoices().iterator().next()); - } - if (chooseManaType.getChoice().equals("Black")) { - manaCostsToReduce.load("{B}"); - } - if (chooseManaType.getChoice().equals("Blue")) { - manaCostsToReduce.load("{U}"); - } - if (chooseManaType.getChoice().equals("Green")) { - manaCostsToReduce.load("{G}"); - } - if (chooseManaType.getChoice().equals("White")) { - manaCostsToReduce.load("{W}"); - } - if (chooseManaType.getChoice().equals("Red")) { - manaCostsToReduce.load("{R}"); - } - if (chooseManaType.getChoice().equals("Colorless")) { - manaCostsToReduce.load("{1}"); - } - CardUtil.reduceCost((SpellAbility)ability, manaCostsToReduce); - } else { - manaCostsToReduce.load("{1}"); - CardUtil.reduceCost((SpellAbility)ability, manaCostsToReduce); - } - if (costBefore == ability.getManaCostsToPay().convertedManaCost()) { - // creature could not reduce mana costs so tap must be reverted - perm.untap(game); - } else { - game.informPlayers("Convoke: " + player.getName() + " taps " + perm.getLogName() + " to reduce mana costs by " + manaCostsToReduce.getText()); - } + if (unpaid.getMana().getBlue() > 0) { + colorPredicates.add(new ColorPredicate(ObjectColor.BLUE)); } + if (unpaid.getMana().getRed() > 0) { + colorPredicates.add(new ColorPredicate(ObjectColor.RED)); + } + if (unpaid.getMana().getGreen() > 0) { + colorPredicates.add(new ColorPredicate(ObjectColor.GREEN)); + } + if (unpaid.getMana().getWhite() > 0) { + colorPredicates.add(new ColorPredicate(ObjectColor.WHITE)); + } + filter.add(Predicates.or(colorPredicates)); + } + Target target = new TargetControlledCreaturePermanent(1, 1, filter, true); + target.setTargetName("creature to convoke"); + specialAction.addTarget(target); + if (specialAction.canActivate(source.getControllerId(), game)) { + game.getState().getSpecialActions().add(specialAction); } } } } - private Choice buildChoice(ObjectColor creatureColor, ManaCosts manaCostsSpell) { - Choice choice = new ChoiceImpl(); - String spellCosts = manaCostsSpell.getText(); - if (creatureColor.isBlack() && spellCosts.contains("B")) { - choice.getChoices().add("Black"); - } - if (creatureColor.isBlue() && spellCosts.contains("U")) { - choice.getChoices().add("Blue"); - } - if (creatureColor.isGreen() && spellCosts.contains("G")) { - choice.getChoices().add("Green"); - } - if (creatureColor.isRed() && spellCosts.contains("R")) { - choice.getChoices().add("Red"); - } - if (creatureColor.isWhite() && spellCosts.contains("W")) { - choice.getChoices().add("White"); - } - return choice; - } - @Override public String getRule() { return "Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)"; } } + +class ConvokeSpecialAction extends SpecialAction { + + public ConvokeSpecialAction(ManaCost unpaid) { + super(Zone.ALL, true); + setRuleVisible(false); + this.addEffect(new ConvokeEffect(unpaid)); + } + + public ConvokeSpecialAction(final ConvokeSpecialAction ability) { + super(ability); + } + + @Override + public ConvokeSpecialAction copy() { + return new ConvokeSpecialAction(this); + } +} + +class ConvokeEffect extends OneShotEffect { + + private final ManaCost unpaid; + + public ConvokeEffect(ManaCost unpaid) { + super(Outcome.Benefit); + this.unpaid = unpaid; + this.staticText = "Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)"; + } + + public ConvokeEffect(final ConvokeEffect effect) { + super(effect); + this.unpaid = effect.unpaid; + } + + @Override + public ConvokeEffect copy() { + return new ConvokeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID creatureId: this.getTargetPointer().getTargets(game, source)) { + Permanent perm = game.getPermanent(creatureId); + if (perm == null) { + continue; + } + String manaName; + if (!perm.isTapped() && perm.tap(game)) { + ManaPool manaPool = controller.getManaPool(); + Choice chooseManaType = buildChoice(perm.getColor(), unpaid.getMana()); + if (chooseManaType.getChoices().size() > 0) { + if (chooseManaType.getChoices().size() > 1) { + chooseManaType.getChoices().add("Colorless"); + chooseManaType.setMessage("Choose mana color to reduce from " + perm.getName()); + while (!chooseManaType.isChosen()) { + controller.choose(Outcome.Benefit, chooseManaType, game); + if (!controller.isInGame()) { + return false; + } + } + } else { + chooseManaType.setChoice(chooseManaType.getChoices().iterator().next()); + } + if (chooseManaType.getChoice().equals("Black")) { + manaPool.addMana(Mana.BlackMana, game, source); + manaPool.unlockManaType(ManaType.BLACK); + } + if (chooseManaType.getChoice().equals("Blue")) { + manaPool.addMana(Mana.BlueMana, game, source); + manaPool.unlockManaType(ManaType.BLUE); + } + if (chooseManaType.getChoice().equals("Green")) { + manaPool.addMana(Mana.GreenMana, game, source); + manaPool.unlockManaType(ManaType.GREEN); + } + if (chooseManaType.getChoice().equals("White")) { + manaPool.addMana(Mana.WhiteMana, game, source); + manaPool.unlockManaType(ManaType.WHITE); + } + if (chooseManaType.getChoice().equals("Red")) { + manaPool.addMana(Mana.RedMana, game, source); + manaPool.unlockManaType(ManaType.RED); + } + if (chooseManaType.getChoice().equals("Colorless")) { + manaPool.addMana(Mana.ColorlessMana, game, source); + manaPool.unlockManaType(ManaType.COLORLESS); + } + manaName = chooseManaType.getChoice().toLowerCase(); + } else { + manaPool.addMana(Mana.ColorlessMana, game, source); + manaPool.unlockManaType(ManaType.COLORLESS); + manaName = "colorless"; + } + game.informPlayers("Convoke: " + controller.getName() + " taps " + perm.getLogName() + " to pay one " + manaName + " mana"); + } + + } + return true; + } + return false; + } + + private Choice buildChoice(ObjectColor creatureColor, Mana mana) { + Choice choice = new ChoiceImpl(); + if (creatureColor.isBlack() && mana.getBlack() > 0) { + choice.getChoices().add("Black"); + } + if (creatureColor.isBlue() && mana.getBlue() > 0) { + choice.getChoices().add("Blue"); + } + if (creatureColor.isGreen() && mana.getGreen() > 0) { + choice.getChoices().add("Green"); + } + if (creatureColor.isRed() && mana.getRed() > 0) { + choice.getChoices().add("Red"); + } + if (creatureColor.isWhite() && mana.getWhite() > 0) { + choice.getChoices().add("White"); + } + return choice; + } +} diff --git a/Mage/src/mage/abilities/keyword/DelveAbility.java b/Mage/src/mage/abilities/keyword/DelveAbility.java index 5f2106dc0c..492de5d9c3 100644 --- a/Mage/src/mage/abilities/keyword/DelveAbility.java +++ b/Mage/src/mage/abilities/keyword/DelveAbility.java @@ -29,18 +29,23 @@ package mage.abilities.keyword; import java.util.ArrayList; import java.util.List; -import java.util.UUID; +import mage.Mana; import mage.abilities.Ability; -import mage.abilities.SpellAbility; +import mage.abilities.SpecialAction; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.AdjustingSourceCosts; +import mage.abilities.costs.common.ExileFromGraveCost; +import mage.abilities.costs.mana.AlternateManaPaymentAbility; +import mage.abilities.costs.mana.ManaCost; +import mage.abilities.effects.OneShotEffect; import mage.cards.Card; +import mage.constants.AbilityType; +import mage.constants.ManaType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; +import mage.players.ManaPool; import mage.players.Player; -import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; import mage.util.CardUtil; @@ -71,22 +76,16 @@ import mage.util.CardUtil; * increase the mana costs. */ - public class DelveAbility extends SimpleStaticAbility implements AdjustingSourceCosts { + public class DelveAbility extends SimpleStaticAbility implements AlternateManaPaymentAbility { - private List delvedCards; public DelveAbility() { super(Zone.STACK, null); this.setRuleAtTheTop(true); - this.delvedCards = null; } public DelveAbility(final DelveAbility ability) { super(ability); - if (ability.delvedCards != null) { - this.delvedCards = new ArrayList<>(); - this.delvedCards.addAll(ability.delvedCards); - } } @Override @@ -95,46 +94,81 @@ import mage.util.CardUtil; } @Override - public void adjustCosts(Ability ability, Game game) { - Player player = game.getPlayer(controllerId); - if (player == null || !(ability instanceof SpellAbility)) { - return; - } - Target target = new TargetCardInYourGraveyard(1, Integer.MAX_VALUE, new FilterCard()); - target.setTargetName("cards to delve from your graveyard"); - target.setNotTarget(true); - if (!target.canChoose(sourceId, controllerId, game)) { - return; - } - if (!CardUtil.isCheckPlayableMode(ability) && - player.chooseUse(Outcome.Detriment, "Delve cards from your graveyard?", game)) { - player.chooseTarget(Outcome.Detriment, target, ability, game); - if (target.getTargets().size() > 0) { - delvedCards = new ArrayList<>(); - int adjCost = 0; - for (UUID cardId: target.getTargets()) { - Card card = game.getCard(cardId); - if (card == null) { - continue; - } - delvedCards.add(card); - player.moveCardToExileWithInfo(card, null, "", getSourceId(), game, Zone.GRAVEYARD); - ++adjCost; - } - game.informPlayers(new StringBuilder("Delve: ").append(player.getName()).append(" exiled ") - .append(adjCost).append(" card").append(adjCost != 1?"s":"").append(" from his or her graveyard").toString()); - CardUtil.adjustCost((SpellAbility)ability, adjCost); - } - } + public String getRule() { + return "Delve (Each card you exile from your graveyard while casting this spell pays for {1})"; } @Override - public String getRule() { - return "Delve (You may exile any number of cards from your graveyard as you cast this spell. It costs {1} less to cast for each card exiled this way.)"; + public void addSpecialAction(Ability source, Game game, ManaCost unpaid) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && controller.getGraveyard().size() > 0) { + if (unpaid.getMana().getColorless() > 0 && source.getAbilityType().equals(AbilityType.SPELL)) { + SpecialAction specialAction = new DelveSpecialAction(); + specialAction.setControllerId(source.getControllerId()); + specialAction.setSourceId(source.getSourceId()); + specialAction.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard( + 0, Math.min(controller.getGraveyard().size(), unpaid.getMana().getColorless()), new FilterCard()))); + if (specialAction.canActivate(source.getControllerId(), game)) { + game.getState().getSpecialActions().add(specialAction); + } + } + } + } +} + +class DelveSpecialAction extends SpecialAction { + + public DelveSpecialAction() { + super(Zone.ALL, true); + this.addEffect(new DelveEffect()); + } + + public DelveSpecialAction(final DelveSpecialAction ability) { + super(ability); + } + + @Override + public DelveSpecialAction copy() { + return new DelveSpecialAction(this); + } +} + +class DelveEffect extends OneShotEffect { + + public DelveEffect() { + super(Outcome.Benefit); + this.staticText = "Delve (Each card you exile from your graveyard while casting this spell pays for {1}.)"; + } + + public DelveEffect(final DelveEffect effect) { + super(effect); + } + + @Override + public DelveEffect copy() { + return new DelveEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + ExileFromGraveCost exileFromGraveCost = (ExileFromGraveCost) source.getCosts().get(0); + List exiledCards = exileFromGraveCost.getExiledCards(); + if (exiledCards.size() > 0) { + ManaPool manaPool = controller.getManaPool(); + manaPool.addMana(new Mana(0,0,0,0,0,exiledCards.size(),0), game, source); + manaPool.unlockManaType(ManaType.COLORLESS); + String keyString = CardUtil.getCardZoneString("delvedCards", source.getSourceId(), game); + List delvedCards = (List) game.getState().getValue(keyString); + if (delvedCards == null) { + game.getState().setValue(keyString, exiledCards); + } else { + delvedCards.addAll(exiledCards); + } + } + return true; + } + return false; } - - public List getDelvedCards() { - return delvedCards; - } - } From d07d3228a12b3b8e6a844858ff2ee561eb133cb4 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 20 Feb 2015 02:18:00 +0100 Subject: [PATCH 22/23] * Soulflayer - Fixed a bug that Soulflayer had abilities from previous casts when leaving and returning to battlefield. --- .../mage/sets/fatereforged/Soulflayer.java | 94 ++++++++++--------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fatereforged/Soulflayer.java b/Mage.Sets/src/mage/sets/fatereforged/Soulflayer.java index 670450071a..306bafcd85 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/Soulflayer.java +++ b/Mage.Sets/src/mage/sets/fatereforged/Soulflayer.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Set; import java.util.UUID; import mage.MageInt; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; @@ -59,6 +60,7 @@ import mage.constants.SubLayer; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.util.CardUtil; /** * @@ -95,10 +97,11 @@ public class Soulflayer extends CardImpl { class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect { private Set abilitiesToAdd; + private MageObjectReference objectReference = null; public SoulflayerEffect() { super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); - staticText = "If a creature card with flying was exiled with Soulflayer's delve ability, Soulflayer has flying. The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, reach, trample, and vigilance"; + staticText = "If a creature card with flying was exiled with {this}'s delve ability, {this} has flying. The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, reach, trample, and vigilance"; abilitiesToAdd = null; } @@ -108,6 +111,7 @@ class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect { this.abilitiesToAdd = new HashSet<>(); this.abilitiesToAdd.addAll(effect.abilitiesToAdd); } + this.objectReference = effect.objectReference; } @Override @@ -119,51 +123,49 @@ class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - if (abilitiesToAdd == null) { - for (Ability ability :permanent.getAbilities()) { - if (ability instanceof DelveAbility) { - List delvedCards = ((DelveAbility) ability).getDelvedCards(); - abilitiesToAdd = new HashSet<>(); - if (delvedCards != null) { - for(Card card: delvedCards) { - if (!card.getCardType().contains(CardType.CREATURE)) { - continue; - } - for (Ability cardAbility: card.getAbilities()) { - if (cardAbility instanceof FlyingAbility) { - abilitiesToAdd.add(FlyingAbility.getInstance()); - } - if (cardAbility instanceof FirstStrikeAbility) { - abilitiesToAdd.add(FirstStrikeAbility.getInstance()); - } - if (cardAbility instanceof DoubleStrikeAbility) { - abilitiesToAdd.add(DoubleStrikeAbility.getInstance()); - } - if (cardAbility instanceof DeathtouchAbility) { - abilitiesToAdd.add(DeathtouchAbility.getInstance()); - } - if (cardAbility instanceof HasteAbility) { - abilitiesToAdd.add(HasteAbility.getInstance()); - } - if (cardAbility instanceof HexproofAbility) { - abilitiesToAdd.add(HexproofAbility.getInstance()); - } - if (cardAbility instanceof IndestructibleAbility) { - abilitiesToAdd.add(IndestructibleAbility.getInstance()); - } - if (cardAbility instanceof LifelinkAbility) { - abilitiesToAdd.add(LifelinkAbility.getInstance()); - } - if (cardAbility instanceof ReachAbility) { - abilitiesToAdd.add(ReachAbility.getInstance()); - } - if (cardAbility instanceof TrampleAbility) { - abilitiesToAdd.add(TrampleAbility.getInstance()); - } - if (cardAbility instanceof VigilanceAbility) { - abilitiesToAdd.add(VigilanceAbility.getInstance()); - } - } + if (objectReference == null || !objectReference.refersTo(permanent)) { + abilitiesToAdd = new HashSet<>(); + this.objectReference = new MageObjectReference(permanent); + String keyString = CardUtil.getCardZoneString("delvedCards", source.getSourceId(), game, true); + List delvedCards = (List) game.getState().getValue(keyString); + if (delvedCards != null) { + for(Card card: delvedCards) { + if (!card.getCardType().contains(CardType.CREATURE)) { + continue; + } + for (Ability cardAbility: card.getAbilities()) { + if (cardAbility instanceof FlyingAbility) { + abilitiesToAdd.add(FlyingAbility.getInstance()); + } + if (cardAbility instanceof FirstStrikeAbility) { + abilitiesToAdd.add(FirstStrikeAbility.getInstance()); + } + if (cardAbility instanceof DoubleStrikeAbility) { + abilitiesToAdd.add(DoubleStrikeAbility.getInstance()); + } + if (cardAbility instanceof DeathtouchAbility) { + abilitiesToAdd.add(DeathtouchAbility.getInstance()); + } + if (cardAbility instanceof HasteAbility) { + abilitiesToAdd.add(HasteAbility.getInstance()); + } + if (cardAbility instanceof HexproofAbility) { + abilitiesToAdd.add(HexproofAbility.getInstance()); + } + if (cardAbility instanceof IndestructibleAbility) { + abilitiesToAdd.add(IndestructibleAbility.getInstance()); + } + if (cardAbility instanceof LifelinkAbility) { + abilitiesToAdd.add(LifelinkAbility.getInstance()); + } + if (cardAbility instanceof ReachAbility) { + abilitiesToAdd.add(ReachAbility.getInstance()); + } + if (cardAbility instanceof TrampleAbility) { + abilitiesToAdd.add(TrampleAbility.getInstance()); + } + if (cardAbility instanceof VigilanceAbility) { + abilitiesToAdd.add(VigilanceAbility.getInstance()); } } } From 887cc094c9fe56a070de79c73e577cda3ea52f52 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 20 Feb 2015 09:54:45 +0100 Subject: [PATCH 23/23] Some minor changes to Phantasmal Terrain. --- .../sets/limitedalpha/PhantasmalTerrain.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java b/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java index c7cd532448..f38d3ea0f7 100644 --- a/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java +++ b/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java @@ -28,6 +28,7 @@ package mage.sets.limitedalpha; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; @@ -66,8 +67,6 @@ public class PhantasmalTerrain extends CardImpl { this.expansionSetCode = "LEA"; this.subtype.add("Aura"); - this.color.setBlue(true); - // Enchant land TargetPermanent auraTarget = new TargetLandPermanent(); this.getSpellAbility().addTarget(auraTarget); @@ -95,7 +94,7 @@ class PhantasmalTerrainChooseEffect extends OneShotEffect { public PhantasmalTerrainChooseEffect() { super(Outcome.Neutral); - this.staticText = "choose a basic land type."; + this.staticText = "choose a basic land type"; } public PhantasmalTerrainChooseEffect(final PhantasmalTerrainChooseEffect effect) { @@ -109,18 +108,18 @@ class PhantasmalTerrainChooseEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject != null && controller != null) { ChoiceImpl choices = new ChoiceImpl(true); choices.setMessage("Choose basic land type"); - choices.isRequired(); choices.getChoices().add("Forest"); choices.getChoices().add("Plains"); choices.getChoices().add("Mountain"); choices.getChoices().add("Island"); choices.getChoices().add("Swamp"); - if (player.choose(Outcome.Neutral, choices, game)) { - game.informPlayers(new StringBuilder("Phantasmal Terrain: ").append(" chosen basic land type is ").append(choices.getChoice()).toString()); + if (controller.choose(Outcome.Neutral, choices, game)) { + game.informPlayers(sourceObject.getLogName() + ": chosen basic land type is " + choices.getChoice()); game.getState().setValue(source.getSourceId().toString() + "_PhantasmalTerrain", choices.getChoice()); return true; } @@ -134,7 +133,7 @@ class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl { public PhantasmalTerrainContinuousEffect(){ super(Duration.WhileOnBattlefield, Outcome.Neutral); - this.staticText = "Enchanted land is the chosen type."; + this.staticText = "enchanted land is the chosen type"; } public PhantasmalTerrainContinuousEffect(final PhantasmalTerrainContinuousEffect effect) {