From 29dfe89fe512f49750623fb6bbd9d3ae4272ce15 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 14 Dec 2014 15:12:47 +0100 Subject: [PATCH 01/36] * Hallowed Spiritkeeper - Fixed that all cards in graveyard were count instead of only creature cards. --- .../src/mage/sets/commander2014/HallowedSpiritkeeper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/commander2014/HallowedSpiritkeeper.java b/Mage.Sets/src/mage/sets/commander2014/HallowedSpiritkeeper.java index cb71a5eac0..1af1ad9233 100644 --- a/Mage.Sets/src/mage/sets/commander2014/HallowedSpiritkeeper.java +++ b/Mage.Sets/src/mage/sets/commander2014/HallowedSpiritkeeper.java @@ -38,6 +38,7 @@ import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; +import mage.filter.common.FilterCreatureCard; import mage.game.permanent.token.Token; /** @@ -59,7 +60,7 @@ public class HallowedSpiritkeeper extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // When Hallowed Spiritkeeper dies, put X 1/1 white Spirit creature tokens with flying onto the battlefield, where X is the number of creature cards in your graveyard. - Effect effect = new CreateTokenEffect(new HallowedSpiritkeeperSpiritToken(), new CardsInControllerGraveyardCount()); + Effect effect = new CreateTokenEffect(new HallowedSpiritkeeperSpiritToken(), new CardsInControllerGraveyardCount(new FilterCreatureCard("creature cards"))); effect.setText("put X 1/1 white Spirit creature tokens with flying onto the battlefield, where X is the number of creature cards in your graveyard"); this.addAbility(new DiesTriggeredAbility(effect, false)); From 37ac205332bdc2130900b496cc6c1d68bbe02f7e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 14 Dec 2014 15:15:39 +0100 Subject: [PATCH 02/36] * Primal Clay - Fixed choice replacement effect that blocked interface. --- .../mage/sets/fifthedition/PrimalClay.java | 76 +++++++++++-------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fifthedition/PrimalClay.java b/Mage.Sets/src/mage/sets/fifthedition/PrimalClay.java index 11d9f07db0..20ffbe9ad6 100644 --- a/Mage.Sets/src/mage/sets/fifthedition/PrimalClay.java +++ b/Mage.Sets/src/mage/sets/fifthedition/PrimalClay.java @@ -27,6 +27,7 @@ */ package mage.sets.fifthedition; +import java.util.Set; import java.util.UUID; import mage.constants.*; @@ -41,6 +42,7 @@ import mage.cards.CardImpl; import mage.choices.ChoiceImpl; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.players.Player; /** * @@ -57,9 +59,7 @@ public class PrimalClay extends CardImpl { this.toughness = new MageInt(0); // As Primal Clay enters the battlefield, it becomes your choice of a 3/3 artifact creature, a 2/2 artifact creature with flying, or a 1/6 Wall artifact creature with defender in addition to its other types. - Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new EntersBattlefieldEffect(new PrimalClayEffect(), "As {this} enters the battlefield, it becomes your choice of a 3/3 artifact creature, a 2/2 artifact creature with flying, or a 1/6 Wall artifact creature with defender in addition to its other types")); - ability.addChoice(new PrimalClayChoice()); - this.addAbility(ability); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EntersBattlefieldEffect(new PrimalClayEffect(), "As {this} enters the battlefield, it becomes your choice of a 3/3 artifact creature, a 2/2 artifact creature with flying, or a 1/6 Wall artifact creature with defender in addition to its other types"))); } public PrimalClay(final PrimalClay card) { @@ -73,35 +73,68 @@ public class PrimalClay extends CardImpl { } class PrimalClayEffect extends ContinuousEffectImpl { + + private final static String choice1 = "a 3/3 artifact creature"; + private final static String choice2 = "a 2/2 artifact creature with flying"; + private final static String choice3 = "a 1/6 Wall artifact creature with defender"; + + String choice; + PrimalClayEffect() { super(Duration.WhileOnBattlefield, Outcome.BecomeCreature); } PrimalClayEffect(final PrimalClayEffect effect) { super(effect); + this.choice = effect.choice; } + @Override + public void init(Ability source, Game game) { + super.init(source, game); + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (controller != null && permanent != null) { + ChoiceImpl primalClayChoice = new ChoiceImpl(); + Set choices = primalClayChoice.getChoices(); + choices.add(choice1); + choices.add(choice2); + choices.add(choice3); + primalClayChoice.setMessage("Choose for " + permanent.getLogName() + " to be"); + while (!primalClayChoice.isChosen()) { + if (!controller.isInGame()) { + discard(); + return; + } + controller.choose(outcome, primalClayChoice, game); + } + this.choice = primalClayChoice.getChoice(); + return; + } + discard(); + } + + @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent permanent = game.getPermanent(source.getSourceId()); - PrimalClayChoice choice = (PrimalClayChoice) source.getChoices().get(0); if (permanent == null) { + discard(); return false; } - switch (layer) { case PTChangingEffects_7: if (sublayer.equals(SubLayer.SetPT_7b)) { - switch (choice.getChoice()) { - case "a 3/3 artifact creature": + switch (choice) { + case choice1: permanent.getPower().setValue(3); permanent.getToughness().setValue(3); break; - case "a 2/2 artifact creature with flying": + case choice2: permanent.getPower().setValue(2); permanent.getToughness().setValue(2); break; - case "a 1/6 Wall artifact creature with defender": + case choice3: permanent.getPower().setValue(1); permanent.getToughness().setValue(6); break; @@ -109,11 +142,11 @@ class PrimalClayEffect extends ContinuousEffectImpl { } break; case AbilityAddingRemovingEffects_6: - switch (choice.getChoice()) { - case "a 2/2 artifact creature with flying": + switch (choice) { + case choice2: permanent.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game); break; - case "a 1/6 Wall artifact creature with defender": + case choice3: permanent.addAbility(DefenderAbility.getInstance(), source.getSourceId(), game); break; } @@ -137,22 +170,3 @@ class PrimalClayEffect extends ContinuousEffectImpl { return new PrimalClayEffect(this); } } - -class PrimalClayChoice extends ChoiceImpl { - PrimalClayChoice() { - super(true); - this.setMessage("Choose for Primal Clay to be"); - this.choices.add("a 3/3 artifact creature"); - this.choices.add("a 2/2 artifact creature with flying"); - this.choices.add("a 1/6 Wall artifact creature with defender"); - } - - PrimalClayChoice(final PrimalClayChoice choice) { - super(choice); - } - - @Override - public PrimalClayChoice copy() { - return new PrimalClayChoice(this); - } -} \ No newline at end of file From 6bccbccce63bef8d299b6ee3afb51b14741734e1 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 14 Dec 2014 16:43:57 +0100 Subject: [PATCH 03/36] * Veil of Secrecy - Fixed missing target definition. --- .../src/mage/sets/betrayersofkamigawa/VeilOfSecrecy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/VeilOfSecrecy.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/VeilOfSecrecy.java index a0ec672be1..bb60c9aa10 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/VeilOfSecrecy.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/VeilOfSecrecy.java @@ -42,6 +42,7 @@ import mage.constants.Rarity; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; /** * @@ -60,10 +61,9 @@ public class VeilOfSecrecy extends CardImpl { this.expansionSetCode = "BOK"; this.subtype.add("Arcane"); - this.color.setBlue(true); - // Target creature gains shroud until end of turn and is unblockable this turn. Effect effect = new GainAbilityTargetEffect(ShroudAbility.getInstance(), Duration.EndOfTurn); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); effect.setText("Target creature gains shroud until end of turn"); this.getSpellAbility().addEffect(effect); effect = new UnblockableTargetEffect(); From 424448b38f8d396b7691f92f80902c1dcc1c71d9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 14 Dec 2014 22:54:58 +0100 Subject: [PATCH 04/36] * Handling of resource images fixed. --- .../mage/client/util/gui/GuiDisplayUtil.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/util/gui/GuiDisplayUtil.java b/Mage.Client/src/main/java/mage/client/util/gui/GuiDisplayUtil.java index ed4d9c1f28..d13da77a3f 100644 --- a/Mage.Client/src/main/java/mage/client/util/gui/GuiDisplayUtil.java +++ b/Mage.Client/src/main/java/mage/client/util/gui/GuiDisplayUtil.java @@ -12,7 +12,9 @@ import org.mage.card.arcane.UI; import javax.swing.*; import java.awt.*; +import java.net.URL; import java.util.ArrayList; +import org.mage.plugins.card.utils.impl.ImageManagerImpl; public class GuiDisplayUtil { private static final Font cardNameFont = new Font("Calibri", Font.BOLD, 15); @@ -200,19 +202,19 @@ public class GuiDisplayUtil { buffer.append(""); buffer.append("
"); if(card.getColor().isWhite()) { - buffer.append("W"); + buffer.append("W"); } if(card.getColor().isBlue()) { - buffer.append("U"); + buffer.append("U"); } if(card.getColor().isBlack()) { - buffer.append("B"); + buffer.append("B"); } if(card.getColor().isRed()) { - buffer.append("R"); + buffer.append("R"); } if(card.getColor().isGreen()) { - buffer.append("G"); + buffer.append("G"); } if(!card.getColor().isColorless()) { buffer.append("  "); @@ -312,7 +314,11 @@ public class GuiDisplayUtil { buffer.append("
"); return buffer; } - + + private static String getResourcePath(String image) { + return GuiDisplayUtil.class.getClassLoader().getResource(image).toString(); + } + private static String getTypes(CardView card) { String types = ""; for (String superType : card.getSuperTypes()) { From 9ba6f74bf6e6a03a64e53373217d4755d6f005e4 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 14 Dec 2014 22:55:16 +0100 Subject: [PATCH 05/36] * improved message for missing cards on the server. --- Mage/src/mage/cards/decks/Deck.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Mage/src/mage/cards/decks/Deck.java b/Mage/src/mage/cards/decks/Deck.java index 5b0caa8fb0..f7655fd795 100644 --- a/Mage/src/mage/cards/decks/Deck.java +++ b/Mage/src/mage/cards/decks/Deck.java @@ -58,7 +58,7 @@ public class Deck implements Serializable { if (card != null) { deck.cards.add(card); } else if (!ignoreErrors) { - throw new GameException("Error loading card - " + deckCardInfo.getCardName() + " for deck - " + deck.getName()); + throw createCardNotFoundGameException(deckCardInfo, deckCardLists.getName()); } } for (DeckCardInfo deckCardInfo: deckCardLists.getSideboard()) { @@ -66,13 +66,19 @@ public class Deck implements Serializable { if (card != null) { deck.sideboard.add(card); } else if (!ignoreErrors) { - throw new GameException("Error loading card - " + deckCardInfo.getCardName() + " for deck - " + deck.getName()); + throw createCardNotFoundGameException(deckCardInfo, deckCardLists.getName()); } } return deck; } + private static GameException createCardNotFoundGameException(DeckCardInfo deckCardInfo, String deckName) { + return new GameException("Card not found - " + deckCardInfo.getCardName() + " - " + deckCardInfo.getSetCode() + " for deck - " + deckName + "\n" + + "Possible reason is, that you use cards in your deck, that are only supported in newer versions of the server.\n" + + "So it can help to use the same card from another set, that's already supported from this server." ); + } + private static Card createCard(DeckCardInfo deckCardInfo, boolean mockCards) { CardInfo cardInfo = CardRepository.instance.findCard(deckCardInfo.getSetCode(), deckCardInfo.getCardNum()); if (cardInfo == null) { From 7b738474a98feab6fd574f31e107410669b45a26 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 14 Dec 2014 22:56:37 +0100 Subject: [PATCH 06/36] * Some fixes to the exile effects with duration. Fixed that exiled cards/permanets did not come back if causing card was put into play and exiled by Whip of Erebos. --- Mage.Client/serverlist.txt | 2 +- .../sets/journeyintonyx/BanishingLight.java | 89 +------------ .../mage/sets/journeyintonyx/BrainMaggot.java | 38 +++--- .../sets/khansoftarkir/KheruLichLord.java | 2 +- .../sets/khansoftarkir/SuspensionField.java | 84 +----------- .../mage/sets/magic2014/BanisherPriest.java | 89 +------------ .../mage/sets/magic2014/ColossalWhale.java | 82 +----------- .../sets/magic2015/ConstrictingSliver.java | 115 +---------------- .../sets/returntoravnica/DryadMilitant.java | 2 +- .../mage/sets/theros/ChainedToTheRocks.java | 86 +------------ .../src/mage/sets/theros/WhipOfErebos.java | 4 +- .../mage/abilities/TriggeredAbilities.java | 2 +- ...LeaveReturnExiledToBattlefieldAbility.java | 121 ++++++++++++++++++ .../CreateDelayedTriggeredAbilityEffect.java | 6 +- .../effects/common/ExileSourceEffect.java | 7 +- 15 files changed, 187 insertions(+), 542 deletions(-) create mode 100644 Mage/src/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java diff --git a/Mage.Client/serverlist.txt b/Mage.Client/serverlist.txt index 33df5c541a..b7f106d4c9 100644 --- a/Mage.Client/serverlist.txt +++ b/Mage.Client/serverlist.txt @@ -1,5 +1,5 @@ woogerworks (Version 1.3.0 dev 2014-10-29V2) :xmage.woogerworks.com:17171 XMage.info 1 (Version 1.3.0 dev 2014-11-29v3) :176.31.186.181:17171 -XMage.info 2 (Version 1.3.0 dev 2014-11-29V3) :176.31.186.181:17000 +XMage.info 2 (Version 1.3.0 dev 2014-11-29V4) :176.31.186.181:17000 Seedds Server (Version 1.3.0 dev 2014-11-29v2) :115.29.203.80:17171 localhost -> connect to your local server (must be started):localhost:17171 diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/BanishingLight.java b/Mage.Sets/src/mage/sets/journeyintonyx/BanishingLight.java index 6cf75ce9f1..63346de075 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/BanishingLight.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/BanishingLight.java @@ -27,29 +27,24 @@ */ package mage.sets.journeyintonyx; -import java.util.LinkedList; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.ExileTargetEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.common.FilterNonlandPermanent; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.ExileZone; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; +import mage.util.CardUtil; /** * @@ -72,10 +67,8 @@ public class BanishingLight extends CardImpl { // When Banishing Light enters the battlefield, exile target nonland permanent an opponent controls until Banishing Light leaves the battlefield. Ability ability = new EntersBattlefieldTriggeredAbility(new BanishingLightExileEffect()); ability.addTarget(new TargetPermanent(filter)); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); this.addAbility(ability); - // Implemented as triggered effect that doesn't uses the stack (implementation with watcher does not work correctly because if the returned creature - // has a DiesTriggeredAll ability it triggers for the dying / battlefield leaving source object, what shouldn't happen) - this.addAbility(new BanishingLightReturnExiledAbility()); } public BanishingLight(final BanishingLight card) { @@ -110,79 +103,7 @@ class BanishingLightExileEffect extends OneShotEffect { // If Banishing Light leaves the battlefield before its triggered ability resolves, // the target won't be exiled. if (permanent != null) { - return new ExileTargetEffect(source.getSourceId(), permanent.getName()).apply(game, source); - } - return false; - } -} - -/** - * Returns the exiled card as source permanent leaves battlefield - * Uses no stack - * @author LevelX2 - */ - -class BanishingLightReturnExiledAbility extends TriggeredAbilityImpl { - - public BanishingLightReturnExiledAbility() { - super(Zone.BATTLEFIELD, new ReturnExiledCreatureEffect()); - this.usesStack = false; - this.setRuleVisible(false); - } - - public BanishingLightReturnExiledAbility(final BanishingLightReturnExiledAbility ability) { - super(ability); - } - - @Override - public BanishingLightReturnExiledAbility copy() { - return new BanishingLightReturnExiledAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - return true; - } - } - return false; - } -} - -class ReturnExiledCreatureEffect extends OneShotEffect { - - public ReturnExiledCreatureEffect() { - super(Outcome.Benefit); - this.staticText = "Return exiled permanent"; - } - - public ReturnExiledCreatureEffect(final ReturnExiledCreatureEffect effect) { - super(effect); - } - - @Override - public ReturnExiledCreatureEffect copy() { - return new ReturnExiledCreatureEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - ExileZone exile = game.getExile().getExileZone(source.getSourceId()); - Card sourceCard = game.getCard(source.getSourceId()); - if (exile != null && sourceCard != null) { - LinkedList cards = new LinkedList<>(exile); - for (UUID cardId : cards) { - Card card = game.getCard(cardId); - card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); - game.informPlayers(new StringBuilder(sourceCard.getName()).append(": ").append(card.getName()).append(" returns to battlefield from exile").toString()); - } - exile.clear(); - return true; - } + return new ExileTargetEffect(CardUtil.getCardExileZoneId(game, source), permanent.getName()).apply(game, source); } return false; } diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java b/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java index 6f49d77ef8..46c455db42 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java @@ -31,12 +31,14 @@ import java.util.LinkedList; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; @@ -70,10 +72,8 @@ public class BrainMaggot extends CardImpl { // When Brain Maggot enters the battlefield, target opponent reveals his or her hand and you choose a nonland card from it. Exile that card until Brain Maggot leaves the battlefield. Ability ability = new EntersBattlefieldTriggeredAbility(new BrainMaggotExileEffect()); ability.addTarget(new TargetOpponent()); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new BrainMaggotReturnExiledCreatureAbility())); this.addAbility(ability); - // Implemented as triggered effect that doesn't uses the stack (implementation with watcher does not work correctly because if the returned creature - // has a DiesTriggeredAll ability it triggers for the dying / battlefield leaving source object, what shouldn't happen) - this.addAbility(new BrainMaggotReturnExiledAbility()); } public BrainMaggot(final BrainMaggot card) { @@ -108,15 +108,17 @@ class BrainMaggotExileEffect extends OneShotEffect { Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source)); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (controller != null && opponent != null && sourcePermanent != null) { - opponent.revealCards(sourcePermanent.getLogName(), opponent.getHand(), game); + if (!opponent.getHand().isEmpty()) { + opponent.revealCards(sourcePermanent.getLogName(), opponent.getHand(), game); - FilterCard filter = new FilterNonlandCard("nonland card to exile"); - TargetCard target = new TargetCard(Zone.HAND, filter); - if (opponent.getHand().count(filter, game) > 0 && controller.choose(Outcome.Exile, opponent.getHand(), target, game)) { - Card card = opponent.getHand().get(target.getFirstTarget(), game); - // If source permanent leaves the battlefield before its triggered ability resolves, the target card won't be exiled. - if (card != null && game.getState().getZone(source.getSourceId()) == Zone.BATTLEFIELD) { - controller.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getName(), source.getSourceId(), game, Zone.HAND); + FilterCard filter = new FilterNonlandCard("nonland card to exile"); + TargetCard target = new TargetCard(Zone.HAND, filter); + if (opponent.getHand().count(filter, game) > 0 && controller.choose(Outcome.Exile, opponent.getHand(), target, game)) { + Card card = opponent.getHand().get(target.getFirstTarget(), game); + // If source permanent leaves the battlefield before its triggered ability resolves, the target card won't be exiled. + if (card != null && game.getState().getZone(source.getSourceId()) == Zone.BATTLEFIELD) { + controller.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getName(), source.getSourceId(), game, Zone.HAND); + } } } return true; @@ -132,21 +134,21 @@ class BrainMaggotExileEffect extends OneShotEffect { * @author LevelX2 */ -class BrainMaggotReturnExiledAbility extends TriggeredAbilityImpl { +class BrainMaggotReturnExiledCreatureAbility extends DelayedTriggeredAbility { - public BrainMaggotReturnExiledAbility() { - super(Zone.BATTLEFIELD, new BrainMaggotReturnExiledCreatureEffect()); + public BrainMaggotReturnExiledCreatureAbility() { + super(new BrainMaggotReturnExiledCreatureEffect(), Duration.OneUse); this.usesStack = false; this.setRuleVisible(false); } - public BrainMaggotReturnExiledAbility(final BrainMaggotReturnExiledAbility ability) { + public BrainMaggotReturnExiledCreatureAbility(final BrainMaggotReturnExiledCreatureAbility ability) { super(ability); } @Override - public BrainMaggotReturnExiledAbility copy() { - return new BrainMaggotReturnExiledAbility(this); + public BrainMaggotReturnExiledCreatureAbility copy() { + return new BrainMaggotReturnExiledCreatureAbility(this); } @Override diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/KheruLichLord.java b/Mage.Sets/src/mage/sets/khansoftarkir/KheruLichLord.java index 371372235b..bcbd847eb3 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/KheruLichLord.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/KheruLichLord.java @@ -179,7 +179,7 @@ class KheruLichLordReplacementEffect extends ReplacementEffectImpl { if (controller != null) { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (card != null) { - controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, null); + controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, game.getState().getZone(card.getId())); } } return true; diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/SuspensionField.java b/Mage.Sets/src/mage/sets/khansoftarkir/SuspensionField.java index 78ce0e25c6..0eb6fe8efb 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/SuspensionField.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/SuspensionField.java @@ -27,29 +27,24 @@ */ package mage.sets.khansoftarkir; -import java.util.LinkedList; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.ExileTargetEffect; -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.Filter.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; -import mage.game.ExileZone; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; /** * @@ -71,10 +66,9 @@ public class SuspensionField extends CardImpl { // When Suspension Field enters the battlefield, you may exile target creature with toughness 3 or greater until Suspension Field leaves the battlefield. Ability ability = new EntersBattlefieldTriggeredAbility(new SuspensionFieldExileEffect(), true); ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); this.addAbility(ability); - // Implemented as triggered effect that doesn't uses the stack (implementation with watcher does not work correctly because if the returned creature - // has a DiesTriggeredAll ability it triggers for the dying / battlefield leaving source object, what shouldn't happen) - this.addAbility(new SuspensionFieldReturnExiledAbility()); + } public SuspensionField(final SuspensionField card) { @@ -108,73 +102,7 @@ class SuspensionFieldExileEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); // If Suspension Field leaves the battlefield before its triggered ability resolves, the target won't be exiled. if (sourcePermanent != null) { - return new ExileTargetEffect(source.getSourceId(), sourcePermanent.getName()).apply(game, source); - } - return false; - } -} - -class SuspensionFieldReturnExiledAbility extends TriggeredAbilityImpl { - - SuspensionFieldReturnExiledAbility() { - super(Zone.BATTLEFIELD, new SuspensionFieldReturnExiledCreatureEffect()); - this.usesStack = false; - this.setRuleVisible(false); - } - - SuspensionFieldReturnExiledAbility(final SuspensionFieldReturnExiledAbility ability) { - super(ability); - } - - @Override - public SuspensionFieldReturnExiledAbility copy() { - return new SuspensionFieldReturnExiledAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - return true; - } - } - return false; - } -} - -class SuspensionFieldReturnExiledCreatureEffect extends OneShotEffect { - - SuspensionFieldReturnExiledCreatureEffect() { - super(Outcome.Benefit); - this.staticText = "Return exiled permanent"; - } - - SuspensionFieldReturnExiledCreatureEffect(final SuspensionFieldReturnExiledCreatureEffect effect) { - super(effect); - } - - @Override - public SuspensionFieldReturnExiledCreatureEffect copy() { - return new SuspensionFieldReturnExiledCreatureEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - ExileZone exile = game.getExile().getExileZone(source.getSourceId()); - Card sourceCard = game.getCard(source.getSourceId()); - if (exile != null && sourceCard != null) { - LinkedList cards = new LinkedList<>(exile); - for (UUID cardId : cards) { - Card card = game.getCard(cardId); - card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); - game.informPlayers(new StringBuilder(sourceCard.getName()).append(": ").append(card.getName()).append(" returns to battlefield from exile").toString()); - } - exile.clear(); - return true; - } + return new ExileTargetEffect(CardUtil.getCardExileZoneId(game, source), sourcePermanent.getName()).apply(game, source); } return false; } diff --git a/Mage.Sets/src/mage/sets/magic2014/BanisherPriest.java b/Mage.Sets/src/mage/sets/magic2014/BanisherPriest.java index c084ce8781..e420e96e84 100644 --- a/Mage.Sets/src/mage/sets/magic2014/BanisherPriest.java +++ b/Mage.Sets/src/mage/sets/magic2014/BanisherPriest.java @@ -27,30 +27,25 @@ */ package mage.sets.magic2014; -import java.util.LinkedList; import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.ExileTargetEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.ExileZone; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; /** * @@ -76,13 +71,8 @@ public class BanisherPriest extends CardImpl { // When Banisher Priest enters the battlefield, exile target creature an opponent controls until Banisher Priest leaves the battlefield. Ability ability = new EntersBattlefieldTriggeredAbility(new BanisherPriestExileEffect()); ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); this.addAbility(ability); - // Implemented as triggered effect that doesn't uses the stack (implementation with watcher does not work correctly because if the returned creature - // has a DiesTriggeredAll ability it triggers for the dying Banish Priest, what shouldn't happen) - this.addAbility(new BanisherPriestReturnExiledAbility()); - - - } public BanisherPriest(final BanisherPriest card) { @@ -117,76 +107,7 @@ class BanisherPriestExileEffect extends OneShotEffect { // If Banisher Priest leaves the battlefield before its triggered ability resolves, // the target creature won't be exiled. if (permanent != null) { - return new ExileTargetEffect(source.getSourceId(), permanent.getName()).apply(game, source); - } - return false; - } -} - -/** - * Returns the exiled card as Banisher Priest leaves battlefield - * Uses no stack - * @author LevelX2 - */ - -class BanisherPriestReturnExiledAbility extends TriggeredAbilityImpl { - - public BanisherPriestReturnExiledAbility() { - super(Zone.BATTLEFIELD, new ReturnExiledCreatureEffect()); - this.usesStack = false; - this.setRuleVisible(false); - } - - public BanisherPriestReturnExiledAbility(final BanisherPriestReturnExiledAbility ability) { - super(ability); - } - - @Override - public BanisherPriestReturnExiledAbility copy() { - return new BanisherPriestReturnExiledAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - return true; - } - } - return false; - } -} - -class ReturnExiledCreatureEffect extends OneShotEffect { - - public ReturnExiledCreatureEffect() { - super(Outcome.Benefit); - this.staticText = "Return exiled creature"; - } - - public ReturnExiledCreatureEffect(final ReturnExiledCreatureEffect effect) { - super(effect); - } - - @Override - public ReturnExiledCreatureEffect copy() { - return new ReturnExiledCreatureEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - ExileZone exile = game.getExile().getExileZone(source.getSourceId()); - MageObject sourceObject = game.getObject(source.getSourceId()); - if (exile != null && sourceObject != null) { - LinkedList cards = new LinkedList<>(exile); - for (UUID cardId : cards) { - Card card = game.getCard(cardId); - card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); - game.informPlayers(new StringBuilder(sourceObject.getLogName()).append(": ").append(card.getName()).append(" returns to battlefield from exile").toString()); - } - exile.clear(); - return true; + return new ExileTargetEffect(CardUtil.getCardExileZoneId(game, source), permanent.getName()).apply(game, source); } return false; } diff --git a/Mage.Sets/src/mage/sets/magic2014/ColossalWhale.java b/Mage.Sets/src/mage/sets/magic2014/ColossalWhale.java index 7cd032a54f..28dc2a1716 100644 --- a/Mage.Sets/src/mage/sets/magic2014/ColossalWhale.java +++ b/Mage.Sets/src/mage/sets/magic2014/ColossalWhale.java @@ -27,15 +27,15 @@ */ package mage.sets.magic2014; -import java.util.LinkedList; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.IslandwalkAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; @@ -43,12 +43,11 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; /** * @@ -69,9 +68,6 @@ public class ColossalWhale extends CardImpl { this.addAbility(new IslandwalkAbility()); // Whenever Colossal Whale attacks, you may exile target creature defending player controls until Colossal Whale leaves the battlefield. this.addAbility(new ColossalWhaleAbility()); - // Implemented as triggered effect that doesn't uses the stack (implementation with watcher does not work correctly because if the returned creature - // has a DiesTriggeredAll ability it triggers for the dying Banish Priest, what shouldn't happen) - this.addAbility(new ColossalWhaleReturnExiledAbility()); } @@ -90,6 +86,7 @@ class ColossalWhaleAbility extends TriggeredAbilityImpl { public ColossalWhaleAbility() { super(Zone.BATTLEFIELD, null); this.addEffect(new ColossalWhaleExileEffect()); + this.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); } public ColossalWhaleAbility(final ColossalWhaleAbility ability) { @@ -144,76 +141,7 @@ class ColossalWhaleExileEffect extends OneShotEffect { // If Whale leaves the battlefield before its triggered ability resolves, // the target creature won't be exiled. if (permanent != null) { - return new ExileTargetEffect(source.getSourceId(), permanent.getName()).apply(game, source); - } - return false; - } -} - -/** - * Returns the exiled card as Banisher Priest leaves battlefield - * Uses no stack - * @author LevelX2 - */ - -class ColossalWhaleReturnExiledAbility extends TriggeredAbilityImpl { - - public ColossalWhaleReturnExiledAbility() { - super(Zone.BATTLEFIELD, new ReturnExiledCreatureColossalWhaleEffect()); - this.usesStack = false; - this.setRuleVisible(false); - } - - public ColossalWhaleReturnExiledAbility(final ColossalWhaleReturnExiledAbility ability) { - super(ability); - } - - @Override - public ColossalWhaleReturnExiledAbility copy() { - return new ColossalWhaleReturnExiledAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - return true; - } - } - return false; - } -} - -class ReturnExiledCreatureColossalWhaleEffect extends OneShotEffect { - - public ReturnExiledCreatureColossalWhaleEffect() { - super(Outcome.Benefit); - this.staticText = "Return exiled creatures"; - } - - public ReturnExiledCreatureColossalWhaleEffect(final ReturnExiledCreatureColossalWhaleEffect effect) { - super(effect); - } - - @Override - public ReturnExiledCreatureColossalWhaleEffect copy() { - return new ReturnExiledCreatureColossalWhaleEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - ExileZone exile = game.getExile().getExileZone(source.getSourceId()); - Card sourceCard = game.getCard(source.getSourceId()); - if (exile != null && sourceCard != null) { - LinkedList cards = new LinkedList<>(exile); - for (UUID cardId : cards) { - Card card = game.getCard(cardId); - card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); - game.informPlayers(new StringBuilder(sourceCard.getName()).append(": ").append(card.getName()).append(" returns to battlefield from exile").toString()); - } - exile.clear(); - return true; + return new ExileTargetEffect(CardUtil.getCardExileZoneId(game, source), permanent.getName()).apply(game, source); } return false; } diff --git a/Mage.Sets/src/mage/sets/magic2015/ConstrictingSliver.java b/Mage.Sets/src/mage/sets/magic2015/ConstrictingSliver.java index bf13c13e21..22f31040e9 100644 --- a/Mage.Sets/src/mage/sets/magic2015/ConstrictingSliver.java +++ b/Mage.Sets/src/mage/sets/magic2015/ConstrictingSliver.java @@ -27,18 +27,16 @@ */ package mage.sets.magic2015; -import java.util.LinkedList; import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.continious.GainAbilityAllEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; @@ -49,13 +47,10 @@ import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.ExileZone; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; /** * @@ -83,7 +78,7 @@ public class ConstrictingSliver extends CardImpl { // until this creature leaves the battlefield." Ability ability = new EntersBattlefieldTriggeredAbility(new ConstrictingSliverExileEffect(), true); ability.addTarget(new TargetCreaturePermanent(filterTarget)); - ability.addEffect(new ConstrictingSliverAddDelayedReturnEffect()); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, new FilterControlledCreaturePermanent("Sliver","Sliver creatures"), @@ -123,107 +118,7 @@ class ConstrictingSliverExileEffect extends OneShotEffect { // If the creature leaves the battlefield before its triggered ability resolves, // the target creature won't be exiled. if (permanent != null) { - return new ExileTargetEffect(source.getSourceId(), permanent.getLogName()).apply(game, source); - } - return false; - } -} - -class ConstrictingSliverAddDelayedReturnEffect extends OneShotEffect { - - public ConstrictingSliverAddDelayedReturnEffect() { - super(Outcome.Benefit); - this.staticText = ""; - } - - public ConstrictingSliverAddDelayedReturnEffect(final ConstrictingSliverAddDelayedReturnEffect effect) { - super(effect); - } - - @Override - public ConstrictingSliverAddDelayedReturnEffect copy() { - return new ConstrictingSliverAddDelayedReturnEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - DelayedTriggeredAbility delayedAbility = new ConstrictingSliverReturnExiledCreatureAbility(); - delayedAbility.setSourceId(source.getSourceId()); - delayedAbility.setControllerId(source.getControllerId()); - game.addDelayedTriggeredAbility(delayedAbility); - return true; - } -} - - -/** - * Returns the exiled card as creature leaves battlefield - * Uses no stack - * @author LevelX2 - */ - -class ConstrictingSliverReturnExiledCreatureAbility extends DelayedTriggeredAbility { - - public ConstrictingSliverReturnExiledCreatureAbility() { - super(new ConstrictingSliverReturnExiledCreatureEffect(), Duration.OneUse); - this.usesStack = false; - this.setRuleVisible(false); - } - - public ConstrictingSliverReturnExiledCreatureAbility(final ConstrictingSliverReturnExiledCreatureAbility ability) { - super(ability); - } - - @Override - public ConstrictingSliverReturnExiledCreatureAbility copy() { - return new ConstrictingSliverReturnExiledCreatureAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - return true; - } - } - return false; - } -} - -class ConstrictingSliverReturnExiledCreatureEffect extends OneShotEffect { - - public ConstrictingSliverReturnExiledCreatureEffect() { - super(Outcome.Benefit); - this.staticText = "Return exiled creatures"; - } - - public ConstrictingSliverReturnExiledCreatureEffect(final ConstrictingSliverReturnExiledCreatureEffect effect) { - super(effect); - } - - @Override - public ConstrictingSliverReturnExiledCreatureEffect copy() { - return new ConstrictingSliverReturnExiledCreatureEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - ExileZone exile = game.getExile().getExileZone(source.getSourceId()); - MageObject sourceObject = game.getObject(source.getSourceId()); - if (exile != null && sourceObject != null) { - LinkedList cards = new LinkedList<>(exile); - for (UUID cardId : cards) { - Card card = game.getCard(cardId); - card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); - game.informPlayers(new StringBuilder(sourceObject.getName()).append(": ").append(card.getName()).append(" returns to battlefield from exile").toString()); - } - exile.clear(); - return true; - } - + return new ExileTargetEffect(CardUtil.getCardExileZoneId(game, source), permanent.getLogName()).apply(game, source); } return false; } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/DryadMilitant.java b/Mage.Sets/src/mage/sets/returntoravnica/DryadMilitant.java index e59ca85834..0649915a4a 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/DryadMilitant.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/DryadMilitant.java @@ -102,7 +102,7 @@ class DryadMilitantReplacementEffect extends ReplacementEffectImpl { if (controller != null) { Card card = game.getCard(event.getTargetId()); if (card != null) { - return controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, null); + return controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, game.getState().getZone(card.getId())); } } return false; diff --git a/Mage.Sets/src/mage/sets/theros/ChainedToTheRocks.java b/Mage.Sets/src/mage/sets/theros/ChainedToTheRocks.java index 832d37d6e6..a3bb45fe77 100644 --- a/Mage.Sets/src/mage/sets/theros/ChainedToTheRocks.java +++ b/Mage.Sets/src/mage/sets/theros/ChainedToTheRocks.java @@ -27,33 +27,29 @@ */ package mage.sets.theros; -import java.util.LinkedList; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.EnchantAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.ExileZone; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; /** * If the land Chained to the Rocks is enchanting stops being a Mountain or another player @@ -112,10 +108,8 @@ public class ChainedToTheRocks extends CardImpl { // When Chained to the Rocks enters the battlefield, exile target creature an opponent controls until Chained to the Rocks leaves the battlefield. (That creature returns under its owner's control.) ability = new EntersBattlefieldTriggeredAbility(new ChainedToTheRocksEffect()); ability.addTarget(new TargetCreaturePermanent(filterTarget)); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); this.addAbility(ability); - // Implemented as triggered effect that doesn't uses the stack (implementation with watcher does not work correctly because if the returned creature - // has a DiesTriggeredAll ability it triggers for the battlefield leaving Chained to the Rocks, what shouldn't happen) - this.addAbility(new ChainedToTheRocksReturnExiledAbility()); } @@ -151,77 +145,7 @@ class ChainedToTheRocksEffect extends OneShotEffect { // If Chained to the Rocks leaves the battlefield before its triggered ability resolves, // the target creature won't be exiled. if (permanent != null) { - return new ExileTargetEffect(source.getSourceId(), permanent.getLogName()).apply(game, source); - } - return false; - } -} - - -/** - * Returns the exiled card as Chained to the Rocks leaves battlefield - * Uses no stack - * @author LevelX2 - */ - -class ChainedToTheRocksReturnExiledAbility extends TriggeredAbilityImpl { - - public ChainedToTheRocksReturnExiledAbility() { - super(Zone.BATTLEFIELD, new ReturnExiledCreatureChainedToTheRocksEffect()); - this.usesStack = false; - this.setRuleVisible(false); - } - - public ChainedToTheRocksReturnExiledAbility(final ChainedToTheRocksReturnExiledAbility ability) { - super(ability); - } - - @Override - public ChainedToTheRocksReturnExiledAbility copy() { - return new ChainedToTheRocksReturnExiledAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD) { - return true; - } - } - return false; - } -} - -class ReturnExiledCreatureChainedToTheRocksEffect extends OneShotEffect { - - public ReturnExiledCreatureChainedToTheRocksEffect() { - super(Outcome.Benefit); - this.staticText = "Return exiled creatures"; - } - - public ReturnExiledCreatureChainedToTheRocksEffect(final ReturnExiledCreatureChainedToTheRocksEffect effect) { - super(effect); - } - - @Override - public ReturnExiledCreatureChainedToTheRocksEffect copy() { - return new ReturnExiledCreatureChainedToTheRocksEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - ExileZone exile = game.getExile().getExileZone(source.getSourceId()); - Card sourceCard = game.getCard(source.getSourceId()); - if (exile != null && sourceCard != null) { - LinkedList cards = new LinkedList<>(exile); - for (UUID cardId : cards) { - Card card = game.getCard(cardId); - card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); - game.informPlayers(new StringBuilder(sourceCard.getName()).append(": ").append(card.getName()).append(" returns to battlefield from exile").toString()); - } - exile.clear(); - return true; + return new ExileTargetEffect(CardUtil.getCardExileZoneId(game, source), permanent.getLogName()).apply(game, source); } return false; } diff --git a/Mage.Sets/src/mage/sets/theros/WhipOfErebos.java b/Mage.Sets/src/mage/sets/theros/WhipOfErebos.java index ef7c1e92a2..bcf0cebff6 100644 --- a/Mage.Sets/src/mage/sets/theros/WhipOfErebos.java +++ b/Mage.Sets/src/mage/sets/theros/WhipOfErebos.java @@ -156,8 +156,8 @@ class WhipOfErebosReplacementEffect extends ReplacementEffectImpl { public boolean replaceEvent(GameEvent event, Ability source, Game game) { Card card = game.getCard(source.getFirstTarget()); Player controller = game.getPlayer(source.getControllerId()); - if (card != null && controller != null) { - controller.moveCardToExileWithInfo(card, null, null, source.getSourceId(), game, null); + if (card != null && controller != null) { + controller.moveCardToExileWithInfo(card, null, null, source.getSourceId(), game, Zone.BATTLEFIELD); } return true; } diff --git a/Mage/src/mage/abilities/TriggeredAbilities.java b/Mage/src/mage/abilities/TriggeredAbilities.java index 2cb04a6ee7..731f82686b 100644 --- a/Mage/src/mage/abilities/TriggeredAbilities.java +++ b/Mage/src/mage/abilities/TriggeredAbilities.java @@ -85,7 +85,7 @@ public class TriggeredAbilities extends ConcurrentHashMap cards = new LinkedList<>(exile); + for (UUID cardId : cards) { + Card card = game.getCard(cardId); + if (card != null) { + Player owner = game.getPlayer(card.getOwnerId()); + if (owner != null && owner.isInGame()) { + owner.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId()); + } + } + } + exile.clear(); + return true; + } + } + return false; + } +} diff --git a/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java b/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java index 2e9227ddad..d22210f53d 100644 --- a/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java +++ b/Mage/src/mage/abilities/effects/common/CreateDelayedTriggeredAbilityEffect.java @@ -85,7 +85,11 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()){ return staticText; } - return ability.getRule(); + if (ability.getRuleVisible()) { + return ability.getRule(); + } else { + return ""; + } } } diff --git a/Mage/src/mage/abilities/effects/common/ExileSourceEffect.java b/Mage/src/mage/abilities/effects/common/ExileSourceEffect.java index 279bbb0794..1f047fdfca 100644 --- a/Mage/src/mage/abilities/effects/common/ExileSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/ExileSourceEffect.java @@ -67,17 +67,18 @@ public class ExileSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - if (!game.getState().getZone(source.getSourceId()).match(onlyfromZone)) { + Zone zone = game.getState().getZone(source.getSourceId()); + if (!zone.match(onlyfromZone)) { return false; } Permanent permanent = game.getPermanent(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); if (permanent != null) { - return controller.moveCardToExileWithInfo(permanent, null, null, source.getSourceId(), game, null); + return controller.moveCardToExileWithInfo(permanent, null, null, source.getSourceId(), game, zone); } else { Card card = game.getCard(source.getSourceId()); if (card != null) { - return controller.moveCardToExileWithInfo(card, null, null, source.getSourceId(), game, null); + return controller.moveCardToExileWithInfo(card, null, null, source.getSourceId(), game, zone); } } return false; From 43a90c68052f4ba608d59b46e14bb22cfb8b9435 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 14 Dec 2014 22:56:50 +0100 Subject: [PATCH 07/36] Added logging statement. --- Mage.Server/src/main/java/mage/server/SessionManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManager.java index e33d6994f9..2bf3e9e4fc 100644 --- a/Mage.Server/src/main/java/mage/server/SessionManager.java +++ b/Mage.Server/src/main/java/mage/server/SessionManager.java @@ -119,6 +119,7 @@ public class SessionManager { // session was removed meanwhile by another thread so we can return return; } + logger.debug("DISCONNECT " + reason.toString() + " - sessionId: "+ sessionId); sessions.remove(sessionId); switch (reason) { case Disconnected: From 8fadaf9a591391e273a1589df3e6f8bdb05fbc0e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 16 Dec 2014 08:27:31 +0100 Subject: [PATCH 08/36] * Jeering Instigator - Fixed that its ability did not trigger as it is turned face up. --- .../src/mage/sets/khansoftarkir/JeeringInstigator.java | 3 ++- Mage/src/mage/abilities/keyword/MorphAbility.java | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/JeeringInstigator.java b/Mage.Sets/src/mage/sets/khansoftarkir/JeeringInstigator.java index 6acb0b49e4..32e3a43683 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/JeeringInstigator.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/JeeringInstigator.java @@ -76,7 +76,8 @@ public class JeeringInstigator extends CardImpl { Ability ability = new ConditionalTriggeredAbility( new TurnedFaceUpSourceTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn),false, false), MyTurnCondition.getInstance(), - "When {this} is turned face up, if it's your turn, gain control of another target creature until end of turn."); + "When {this} is turned face up, if it's your turn, gain control of another target creature until end of turn. Untap that creature. It gains haste until end of turn."); + ability.setWorksFaceDown(true); Effect effect = new UntapTargetEffect(); effect.setText("Untap that creature"); ability.addEffect(effect); diff --git a/Mage/src/mage/abilities/keyword/MorphAbility.java b/Mage/src/mage/abilities/keyword/MorphAbility.java index 4e4e306da6..cdff80b738 100644 --- a/Mage/src/mage/abilities/keyword/MorphAbility.java +++ b/Mage/src/mage/abilities/keyword/MorphAbility.java @@ -352,14 +352,14 @@ class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implements Sour // gained abilities from other sources won't be removed continue; } - // TODO: Add flag "works also face down" to ability and use it to control ability removement instead of instanceof check if (ability.getWorksFaceDown()) { ability.setRuleVisible(false); continue; - } - if (!ability.getRuleVisible() && !ability.getEffects().isEmpty()) { - if (ability.getEffects().get(0) instanceof BecomesFaceDownCreatureEffect) { - continue; + } else { + if (!ability.getRuleVisible() && !ability.getEffects().isEmpty()) { + if (ability.getEffects().get(0) instanceof BecomesFaceDownCreatureEffect) { + continue; + } } } abilities.add(ability); From b2586a653f8a71f848884125128b17875ce54411 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 16 Dec 2014 13:09:48 +0100 Subject: [PATCH 09/36] * Multiplayer Commander - Fixed that the starting player wrongly skipped his draw step. --- .../src/mage/game/CommanderFreeForAll.java | 7 +++++++ Mage/src/mage/game/GameCommanderImpl.java | 9 +++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAll.java b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAll.java index 9332dfe964..1dc151f90b 100644 --- a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAll.java +++ b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAll.java @@ -28,6 +28,7 @@ package mage.game; +import java.util.UUID; import mage.constants.MultiplayerAttackOption; import mage.constants.RangeOfInfluence; import mage.game.match.MatchType; @@ -49,6 +50,12 @@ public class CommanderFreeForAll extends GameCommanderImpl { this.numPlayers = game.numPlayers; } + @Override + protected void init(UUID choosingPlayerId, GameOptions gameOptions) { + startingPlayerSkipsDraw = false; + super.init(choosingPlayerId, gameOptions); + } + @Override public MatchType getGameType() { return new CommanderFreeForAllType(); diff --git a/Mage/src/mage/game/GameCommanderImpl.java b/Mage/src/mage/game/GameCommanderImpl.java index d83f04592d..da41b36c23 100644 --- a/Mage/src/mage/game/GameCommanderImpl.java +++ b/Mage/src/mage/game/GameCommanderImpl.java @@ -61,6 +61,7 @@ public abstract class GameCommanderImpl extends GameImpl { private final Set commanderCombatWatcher = new HashSet<>(); protected boolean alsoLibrary; // replace also commander going to library + protected boolean startingPlayerSkipsDraw = true; public GameCommanderImpl(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) { super(attackOption, range, freeMulligans, startLife); @@ -68,6 +69,8 @@ public abstract class GameCommanderImpl extends GameImpl { public GameCommanderImpl(final GameCommanderImpl game) { super(game); + this.alsoLibrary = game.alsoLibrary; + this.startingPlayerSkipsDraw = game.startingPlayerSkipsDraw; } @Override @@ -104,9 +107,11 @@ public abstract class GameCommanderImpl extends GameImpl { } this.getState().addAbility(ability, this.getId(), null); - state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW)); + if (startingPlayerSkipsDraw) { + state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW)); + } } - + //20130711 /*903.8. The Commander variant uses an alternate mulligan rule. From 4bac5f320df9c493d9ca23c3b0588c40bf86237c Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 16 Dec 2014 13:16:03 +0100 Subject: [PATCH 10/36] * Gift of Estates - Fixed that all kind of lands instead of only Plains cards could be searched. --- .../src/mage/sets/commander2014/GiftOfEstates.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/commander2014/GiftOfEstates.java b/Mage.Sets/src/mage/sets/commander2014/GiftOfEstates.java index 1ff5d72919..78873ff1e8 100644 --- a/Mage.Sets/src/mage/sets/commander2014/GiftOfEstates.java +++ b/Mage.Sets/src/mage/sets/commander2014/GiftOfEstates.java @@ -34,8 +34,9 @@ import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.filter.common.FilterBasicLandCard; +import mage.filter.FilterCard; import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; import mage.target.common.TargetCardInLibrary; /** @@ -43,6 +44,13 @@ import mage.target.common.TargetCardInLibrary; * @author LevelX2 */ public class GiftOfEstates extends CardImpl { + + private static final FilterCard filter = new FilterCard("Plains cards"); + + static { + filter.add(new SubtypePredicate("Plains")); + } + public GiftOfEstates(UUID ownerId) { super(ownerId, 73, "Gift of Estates", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{W}"); @@ -52,7 +60,7 @@ public class GiftOfEstates extends CardImpl { // If an opponent controls more lands than you, search your library for up to three Plains cards, reveal them, and put them into your hand. Then shuffle your library. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 3, new FilterBasicLandCard()), true), + new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 3, filter), true), new OpponentControllsMoreCondition(new FilterLandPermanent("lands")))); } From 3b1afebf3ef02d02b82743271fae313882b4ce08 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 16 Dec 2014 13:19:43 +0100 Subject: [PATCH 11/36] =?UTF-8?q?*=20Knight=20of=20the=20White=20Orchid=20?= =?UTF-8?q?-=20Fixed=20that=20the=20searched=20Plains=20was=20moved=20to?= =?UTF-8?q?=20hand=20instead=20correctly=20to=20batt=C3=B6efield.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java b/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java index 4183fdf161..8c097f1eb0 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/KnightOfTheWhiteOrchid.java @@ -36,6 +36,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.OpponentControllsMoreCondition; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.filter.common.FilterBySubtypeCard; @@ -62,7 +63,7 @@ public class KnightOfTheWhiteOrchid extends CardImpl { // When Knight of the White Orchid enters the battlefield, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield, then shuffle your library. this.addAbility(new ConditionalTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 1, new FilterBySubtypeCard("Plains")), true), true), + new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, new FilterBySubtypeCard("Plains")), false), true), new OpponentControllsMoreCondition(new FilterLandPermanent("lands")), "When {this} enters the battlefield, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield, then shuffle your library")); From 15d7b1dd97901cc0513f460503645441d5e0b219 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 16 Dec 2014 13:21:47 +0100 Subject: [PATCH 12/36] * Ward of Bones - Fixed wrong casting costs of {1} to {6}. --- Mage.Sets/src/mage/sets/eventide/WardOfBones.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/eventide/WardOfBones.java b/Mage.Sets/src/mage/sets/eventide/WardOfBones.java index 6e072df973..8ec71a56eb 100644 --- a/Mage.Sets/src/mage/sets/eventide/WardOfBones.java +++ b/Mage.Sets/src/mage/sets/eventide/WardOfBones.java @@ -55,7 +55,7 @@ import mage.players.Player; public class WardOfBones extends CardImpl { public WardOfBones(UUID ownerId) { - super(ownerId, 174, "Ward of Bones", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{1}"); + super(ownerId, 174, "Ward of Bones", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{6}"); this.expansionSetCode = "EVE"; // Each opponent who controls more creatures than you can't play creature cards. The same is true for artifacts, enchantments, and lands. From 14fed76e623b3753cd304090208be8adc08945bd Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 16 Dec 2014 13:51:07 +0100 Subject: [PATCH 13/36] * Wild Growth - Fixed that the additional green mana was not added to the mana pool. --- Mage.Sets/src/mage/sets/iceage/WildGrowth.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/iceage/WildGrowth.java b/Mage.Sets/src/mage/sets/iceage/WildGrowth.java index 6f59e2ae67..8070da7dc6 100644 --- a/Mage.Sets/src/mage/sets/iceage/WildGrowth.java +++ b/Mage.Sets/src/mage/sets/iceage/WildGrowth.java @@ -33,9 +33,9 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.Mana; import mage.abilities.Ability; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.AddManaToManaPoolTargetControllerEffect; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.ManaEffect; import mage.abilities.keyword.EnchantAbility; import mage.abilities.mana.TriggeredManaAbility; import mage.cards.CardImpl; @@ -45,9 +45,9 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -99,11 +99,17 @@ class WildGrowthTriggeredAbility extends TriggeredManaAbility { } @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent enchantment = game.getPermanent(this.getSourceId()); + public boolean checkTrigger(GameEvent event, Game game) { if(event.getType() == GameEvent.EventType.TAPPED_FOR_MANA){ + Permanent enchantment = game.getPermanent(this.getSourceId()); if (enchantment != null && event.getSourceId().equals(enchantment.getAttachedTo())) { - return true; + Permanent permanent = game.getPermanent(event.getSourceId()); + if (permanent != null) { + for(Effect effect : getEffects()) { + effect.setTargetPointer(new FixedTarget(permanent.getControllerId())); + } + return true; + } } } return false; From 1141e4c2fa7f7ebc93b4aca5973ac180dab454f4 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 16 Dec 2014 15:07:13 +0100 Subject: [PATCH 14/36] * Fixed two Morph Tests. --- .../test/cards/abilities/keywords/MorphTest.java | 13 ++++++++----- Mage/src/mage/abilities/keyword/MorphAbility.java | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java index 49be400076..f6cc00537a 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java @@ -97,7 +97,7 @@ public class MorphTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker"); setChoice(playerA, "Yes"); // cast it face down as 2/2 creature - attack(3, playerA, "face down creature"); + attack(3, playerA, ""); activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "{4}{G}: Turn this face-down permanent face up."); setStopAt(3, PhaseStep.END_TURN); @@ -113,13 +113,15 @@ public class MorphTest extends CardTestPlayerBase { } /** - * Test triggered turn face up ability of Pine Walker did not trigger as - * long as Pine Walker is not turned face up. + * Test that the triggered "turned face up" ability of Pine Walker does not trigger + * aas long as Pine Walker is not turned face up. * */ @Test public void testDoesNotTriggerFaceDown() { + // Whenever Pine Walker or another creature you control is turned face up, untap that creature. addCard(Zone.HAND, playerA, "Pine Walker"); + // When Icefeather Aven is turned face up, you may return another target creature to its owner's hand. addCard(Zone.HAND, playerA, "Icefeather Aven"); addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); addCard(Zone.BATTLEFIELD, playerA, "Island", 3); @@ -129,14 +131,15 @@ public class MorphTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Icefeather Aven"); setChoice(playerA, "Yes"); // cast it face down as 2/2 creature - attack(3, playerA, "face down creature"); - attack(3, playerA, "face down creature"); + attack(3, playerA, ""); + attack(3, playerA, ""); activateAbility(3, PhaseStep.DECLARE_BLOCKERS, playerA, "{1}{G}{U}: Turn this face-down permanent face up."); setChoice(playerA, "No"); // Don't use return permanent to hand effect setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); execute(); + assertLife(playerA, 20); assertLife(playerB, 16); assertHandCount(playerA, "Pine Walker", 0); diff --git a/Mage/src/mage/abilities/keyword/MorphAbility.java b/Mage/src/mage/abilities/keyword/MorphAbility.java index cdff80b738..355c71d820 100644 --- a/Mage/src/mage/abilities/keyword/MorphAbility.java +++ b/Mage/src/mage/abilities/keyword/MorphAbility.java @@ -308,7 +308,7 @@ class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implements Sour protected int zoneChangeCounter; protected Ability turnFaceUpAbility = null; - public BecomesFaceDownCreatureEffect(Costs morphCosts) { + public BecomesFaceDownCreatureEffect(Costs morphCosts) { super(Duration.WhileOnBattlefield, Outcome.BecomeCreature); this.zoneChangeCounter = Integer.MIN_VALUE; if (morphCosts != null) { From a12fa6e3a1f2c36b3e79bc8455bd73fec41a1ea9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 16 Dec 2014 18:01:56 +0100 Subject: [PATCH 15/36] Some minor changes to cards and framework classes. --- .../mage/sets/morningtide/UnstoppableAsh.java | 5 -- .../sets/newphyrexia/SwordOfWarAndPeace.java | 16 +++- .../riseoftheeldrazi/MerfolkObserver.java | 43 +---------- .../saviorsofkamigawa/AkutaBornOfAsh.java | 6 ++ .../ConditionalActivatedAbility.java | 9 ++- .../LookLibraryTopCardTargetPlayerEffect.java | 76 +++++++++++++++++++ .../common/PreventDamageToTargetEffect.java | 10 ++- 7 files changed, 113 insertions(+), 52 deletions(-) create mode 100644 Mage/src/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java diff --git a/Mage.Sets/src/mage/sets/morningtide/UnstoppableAsh.java b/Mage.Sets/src/mage/sets/morningtide/UnstoppableAsh.java index 72d7ae4002..72b1097dba 100644 --- a/Mage.Sets/src/mage/sets/morningtide/UnstoppableAsh.java +++ b/Mage.Sets/src/mage/sets/morningtide/UnstoppableAsh.java @@ -29,23 +29,18 @@ package mage.sets.morningtide; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.BecomesBlockedAllTriggeredAbility; import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continious.BoostTargetEffect; import mage.abilities.keyword.ChampionAbility; import mage.abilities.keyword.TrampleAbility; 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.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; /** * diff --git a/Mage.Sets/src/mage/sets/newphyrexia/SwordOfWarAndPeace.java b/Mage.Sets/src/mage/sets/newphyrexia/SwordOfWarAndPeace.java index 916322cc5a..5e117b2482 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/SwordOfWarAndPeace.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/SwordOfWarAndPeace.java @@ -41,6 +41,7 @@ import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.dynamicvalue.common.CardsInControllerHandCount; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.continious.BoostEquippedEffect; @@ -75,10 +76,19 @@ public class SwordOfWarAndPeace extends CardImpl { super(ownerId, 161, "Sword of War and Peace", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT}, "{3}"); this.expansionSetCode = "NPH"; this.subtype.add("Equipment"); - this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(new ProtectionAbility(filter), AttachmentType.EQUIPMENT))); + + // Equipped creature gets +2/+2 and has protection from red and from white. + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2)); + Effect effect = new GainAbilityAttachedEffect(new ProtectionAbility(filter), AttachmentType.EQUIPMENT); + effect.setText("and has protection from red and from white"); + ability.addEffect(effect); + this.addAbility(ability); + + // Whenever equipped creature deals combat damage to a player, Sword of War and Peace deals damage to that player equal to the number of cards in his or her hand and you gain 1 life for each card in your hand. this.addAbility(new SwordOfWarAndPeaceAbility()); + + // Equip {2} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); } public SwordOfWarAndPeace (final SwordOfWarAndPeace card) { diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/MerfolkObserver.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/MerfolkObserver.java index a975724228..cac4c81285 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/MerfolkObserver.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/MerfolkObserver.java @@ -29,17 +29,11 @@ package mage.sets.riseoftheeldrazi; import java.util.UUID; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; +import mage.abilities.effects.common.LookLibraryTopCardTargetPlayerEffect; import mage.cards.CardImpl; -import mage.cards.CardsImpl; -import mage.game.Game; -import mage.players.Player; import mage.target.TargetPlayer; /** @@ -59,7 +53,7 @@ public class MerfolkObserver extends CardImpl { this.toughness = new MageInt(1); // When Merfolk Observer enters the battlefield, look at the top card of target player's library. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new MerfolkObserverEffect()); + EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new LookLibraryTopCardTargetPlayerEffect()); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } @@ -73,36 +67,3 @@ public class MerfolkObserver extends CardImpl { return new MerfolkObserver(this); } } - -class MerfolkObserverEffect extends OneShotEffect { - - public MerfolkObserverEffect() { - super(Outcome.Benefit); - this.staticText = "look at the top card of target player's library"; - } - - public MerfolkObserverEffect(final MerfolkObserverEffect effect) { - super(effect); - } - - @Override - public MerfolkObserverEffect copy() { - return new MerfolkObserverEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Player targetPlayer = game.getPlayer(source.getFirstTarget()); - if (player != null && targetPlayer != null) { - Card card = targetPlayer.getLibrary().getFromTop(game); - if (card != null) { - CardsImpl cards = new CardsImpl(); - cards.add(card); - player.lookAtCards("Merfolk Observer", cards, game); - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/AkutaBornOfAsh.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/AkutaBornOfAsh.java index a2e106a892..d8fa6b881b 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/AkutaBornOfAsh.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/AkutaBornOfAsh.java @@ -107,4 +107,10 @@ class MoreCardsInHandThanOpponentsCondition implements Condition { } return true; } + + @Override + public String toString() { + return "you have more cards in hand than each opponent"; + } + } diff --git a/Mage/src/mage/abilities/decorator/ConditionalActivatedAbility.java b/Mage/src/mage/abilities/decorator/ConditionalActivatedAbility.java index a9b57f91c1..457722a855 100644 --- a/Mage/src/mage/abilities/decorator/ConditionalActivatedAbility.java +++ b/Mage/src/mage/abilities/decorator/ConditionalActivatedAbility.java @@ -22,11 +22,16 @@ import mage.game.Game; */ public class ConditionalActivatedAbility extends ActivatedAbilityImpl { + private static final Effects emptyEffects = new Effects(); + private final Condition condition; private String ruleText = null; - private static final Effects emptyEffects = new Effects(); - + public ConditionalActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) { + super(zone, effect, cost); + this.condition = condition; + } + public ConditionalActivatedAbility(Zone zone, Effect effect, ManaCosts cost, Condition condition, String rule) { super(zone, effect, cost); this.condition = condition; diff --git a/Mage/src/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java b/Mage/src/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.java new file mode 100644 index 0000000000..fda6b269f3 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/LookLibraryTopCardTargetPlayerEffect.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.abilities.effects.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardsImpl; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ + +public class LookLibraryTopCardTargetPlayerEffect extends OneShotEffect { + + public LookLibraryTopCardTargetPlayerEffect() { + super(Outcome.Benefit); + this.staticText = "look at the top card of target player's library"; + } + + public LookLibraryTopCardTargetPlayerEffect(final LookLibraryTopCardTargetPlayerEffect effect) { + super(effect); + } + + @Override + public LookLibraryTopCardTargetPlayerEffect copy() { + return new LookLibraryTopCardTargetPlayerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (player != null && targetPlayer != null && sourceObject != null) { + Card card = targetPlayer.getLibrary().getFromTop(game); + if (card != null) { + CardsImpl cards = new CardsImpl(); + cards.add(card); + player.lookAtCards(sourceObject.getLogName(), cards, game); + } + return true; + } + return false; + } +} diff --git a/Mage/src/mage/abilities/effects/common/PreventDamageToTargetEffect.java b/Mage/src/mage/abilities/effects/common/PreventDamageToTargetEffect.java index 3b6e22f950..5cd2220158 100644 --- a/Mage/src/mage/abilities/effects/common/PreventDamageToTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/PreventDamageToTargetEffect.java @@ -82,7 +82,15 @@ public class PreventDamageToTargetEffect extends PreventionEffectImpl { } else { sb.append("Prevent the next ").append(amountToPrevent).append(" damage that would be dealt to target "); } - sb.append(mode.getTargets().get(0).getTargetName()).append(" ").append(duration.toString()); + sb.append(mode.getTargets().get(0).getTargetName()); + if (!duration.toString().isEmpty()) { + sb.append(" "); + if (duration.equals(Duration.EndOfTurn)) { + sb.append("this turn"); + } else { + sb.append(duration.toString()); + } + } return sb.toString(); } From 23f2897bdf1ff300c613cbe002041f1df73d24e2 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 16 Dec 2014 18:02:46 +0100 Subject: [PATCH 16/36] Added Mishra's Bauble, Goblin Chirurgeon, Lighning Crafter, Brightstone Ritual and Mana Echoes. --- .../src/mage/sets/coldsnap/MishrasBauble.java | 73 ++++++++++++ .../sets/fallenempires/GoblinChirurgeon.java | 74 ++++++++++++ .../sets/morningtide/LightningCrafter.java | 74 ++++++++++++ .../sets/onslaught/BrightstoneRitual.java | 61 ++++++++++ .../src/mage/sets/onslaught/ManaEchoes.java | 106 ++++++++++++++++++ 5 files changed, 388 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/coldsnap/MishrasBauble.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/GoblinChirurgeon.java create mode 100644 Mage.Sets/src/mage/sets/morningtide/LightningCrafter.java create mode 100644 Mage.Sets/src/mage/sets/onslaught/BrightstoneRitual.java create mode 100644 Mage.Sets/src/mage/sets/onslaught/ManaEchoes.java diff --git a/Mage.Sets/src/mage/sets/coldsnap/MishrasBauble.java b/Mage.Sets/src/mage/sets/coldsnap/MishrasBauble.java new file mode 100644 index 0000000000..8d94de4551 --- /dev/null +++ b/Mage.Sets/src/mage/sets/coldsnap/MishrasBauble.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.coldsnap; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.LookLibraryTopCardTargetPlayerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPlayer; + +/** + * + * @author LevelX2 + */ +public class MishrasBauble extends CardImpl { + + public MishrasBauble(UUID ownerId) { + super(ownerId, 138, "Mishra's Bauble", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{0}"); + this.expansionSetCode = "CSP"; + + // {T}, Sacrifice Mishra's Bauble: Look at the top card of target player's library. Draw a card at the beginning of the next turn's upkeep. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryTopCardTargetPlayerEffect(), new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect( + new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1), Duration.OneUse))); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public MishrasBauble(final MishrasBauble card) { + super(card); + } + + @Override + public MishrasBauble copy() { + return new MishrasBauble(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/GoblinChirurgeon.java b/Mage.Sets/src/mage/sets/fallenempires/GoblinChirurgeon.java new file mode 100644 index 0000000000..12933f7f7d --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/GoblinChirurgeon.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.fallenempires; + +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.effects.common.RegenerateTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class GoblinChirurgeon extends CardImpl { + + public GoblinChirurgeon(UUID ownerId) { + super(ownerId, 110, "Goblin Chirurgeon", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{R}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Goblin"); + this.subtype.add("Shaman"); + this.power = new MageInt(0); + this.toughness = new MageInt(2); + + // Sacrifice a Goblin: Regenerate target creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new RegenerateTargetEffect(), + new SacrificeTargetCost(new TargetControlledCreaturePermanent(new FilterControlledCreaturePermanent("Goblin","a Goblin")))); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public GoblinChirurgeon(final GoblinChirurgeon card) { + super(card); + } + + @Override + public GoblinChirurgeon copy() { + return new GoblinChirurgeon(this); + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/LightningCrafter.java b/Mage.Sets/src/mage/sets/morningtide/LightningCrafter.java new file mode 100644 index 0000000000..db2d19cd27 --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/LightningCrafter.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.morningtide; + +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.effects.common.DamageTargetEffect; +import mage.abilities.keyword.ChampionAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LevelX2 + */ +public class LightningCrafter extends CardImpl { + + public LightningCrafter(UUID ownerId) { + super(ownerId, 93, "Lightning Crafter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{R}"); + this.expansionSetCode = "MOR"; + this.subtype.add("Goblin"); + this.subtype.add("Shaman"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Champion a Goblin or Shaman + this.addAbility(new ChampionAbility(this, new String[]{"Goblin", "Shaman"})); + + // {T}: Lightning Crafter deals 3 damage to target creature or player. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(3), new TapSourceCost()); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public LightningCrafter(final LightningCrafter card) { + super(card); + } + + @Override + public LightningCrafter copy() { + return new LightningCrafter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/onslaught/BrightstoneRitual.java b/Mage.Sets/src/mage/sets/onslaught/BrightstoneRitual.java new file mode 100644 index 0000000000..896507e5b5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/onslaught/BrightstoneRitual.java @@ -0,0 +1,61 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.onslaught; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.DynamicManaEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class BrightstoneRitual extends CardImpl { + + public BrightstoneRitual(UUID ownerId) { + super(ownerId, 191, "Brightstone Ritual", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{R}"); + this.expansionSetCode = "ONS"; + + // Add {R} to your mana pool for each Goblin on the battlefield. + this.getSpellAbility().addEffect(new DynamicManaEffect(Mana.RedMana, new PermanentsOnBattlefieldCount(new FilterCreaturePermanent("Goblin","Goblin on the battlefield")))); + } + + public BrightstoneRitual(final BrightstoneRitual card) { + super(card); + } + + @Override + public BrightstoneRitual copy() { + return new BrightstoneRitual(this); + } +} diff --git a/Mage.Sets/src/mage/sets/onslaught/ManaEchoes.java b/Mage.Sets/src/mage/sets/onslaught/ManaEchoes.java new file mode 100644 index 0000000000..6c2aeca84d --- /dev/null +++ b/Mage.Sets/src/mage/sets/onslaught/ManaEchoes.java @@ -0,0 +1,106 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.onslaught; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class ManaEchoes extends CardImpl { + + public ManaEchoes(UUID ownerId) { + super(ownerId, 218, "Mana Echoes", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}"); + this.expansionSetCode = "ONS"; + + // Whenever a creature enters the battlefield, you may add {X} to your mana pool, where X is the number of creatures you control that share a creature type with it. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, + new ManaEchoesEffect(), new FilterCreaturePermanent("a creature"), true, SetTargetPointer.PERMANENT, "")); + } + + public ManaEchoes(final ManaEchoes card) { + super(card); + } + + @Override + public ManaEchoes copy() { + return new ManaEchoes(this); + } +} + +class ManaEchoesEffect extends OneShotEffect { + + public ManaEchoesEffect() { + super(Outcome.Benefit); + this.staticText = "you may add {X} to your mana pool, where X is the number of creatures you control that share a creature type with it"; + } + + public ManaEchoesEffect(final ManaEchoesEffect effect) { + super(effect); + } + + @Override + public ManaEchoesEffect copy() { + return new ManaEchoesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); + if (controller != null && permanent != null) { + int foundCreatures = 0; + for (Permanent perm: game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { + if (CardUtil.shareSubtypes(permanent, perm)) { + foundCreatures ++; + } + } + if (foundCreatures > 0) { + controller.getManaPool().addMana(new Mana(0,0,0,0,0,foundCreatures,0), game, source); + } + return true; + } + return false; + } +} From 5cb101b26b9285d5249107d05b9db54dde40e578 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 16 Dec 2014 18:03:03 +0100 Subject: [PATCH 17/36] [SOK] Added 7 white cards. --- .../saviorsofkamigawa/KitsuneBonesetter.java | 77 +++++++++++ .../saviorsofkamigawa/KitsuneLoreweaver.java | 72 ++++++++++ .../KiyomaroFirstToStand.java | 128 ++++++++++++++++++ .../saviorsofkamigawa/PresenceOfTheWise.java | 61 +++++++++ .../saviorsofkamigawa/PromiseOfBunrei.java | 105 ++++++++++++++ .../sets/saviorsofkamigawa/Reverence.java | 103 ++++++++++++++ .../saviorsofkamigawa/SpiritualVisit.java | 64 +++++++++ 7 files changed, 610 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/KitsuneBonesetter.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/KitsuneLoreweaver.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/KiyomaroFirstToStand.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/PresenceOfTheWise.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/PromiseOfBunrei.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/Reverence.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/SpiritualVisit.java diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/KitsuneBonesetter.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KitsuneBonesetter.java new file mode 100644 index 0000000000..8032e82b94 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KitsuneBonesetter.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.saviorsofkamigawa; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.PreventDamageToTargetEffect; +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 LevelX2 + */ +public class KitsuneBonesetter extends CardImpl { + + public KitsuneBonesetter(UUID ownerId) { + super(ownerId, 15, "Kitsune Bonesetter", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "SOK"; + this.subtype.add("Fox"); + this.subtype.add("Cleric"); + this.power = new MageInt(0); + this.toughness = new MageInt(1); + + + // {tap}: Prevent the next 3 damage that would be dealt to target creature this turn. Activate this ability only if you have more cards in hand than each opponent. + Ability ability = new ConditionalActivatedAbility( + Zone.BATTLEFIELD, + new PreventDamageToTargetEffect(Duration.EndOfTurn, 3), + new TapSourceCost(), + new MoreCardsInHandThanOpponentsCondition() + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public KitsuneBonesetter(final KitsuneBonesetter card) { + super(card); + } + + @Override + public KitsuneBonesetter copy() { + return new KitsuneBonesetter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/KitsuneLoreweaver.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KitsuneLoreweaver.java new file mode 100644 index 0000000000..63b4a9d83a --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KitsuneLoreweaver.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.saviorsofkamigawa; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.CardsInControllerHandCount; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continious.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class KitsuneLoreweaver extends CardImpl { + + public KitsuneLoreweaver(UUID ownerId) { + super(ownerId, 17, "Kitsune Loreweaver", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "SOK"; + this.subtype.add("Fox"); + this.subtype.add("Cleric"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // {1}{W}: Kitsune Loreweaver gets +0/+X until end of turn, where X is the number of cards in your hand. + Effect effect = new BoostSourceEffect(new StaticValue(0), new CardsInControllerHandCount(), Duration.EndOfTurn, true); + effect.setText("{this} gets +0/+X until end of turn, where X is the number of cards in your hand"); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{W}"))); + } + + public KitsuneLoreweaver(final KitsuneLoreweaver card) { + super(card); + } + + @Override + public KitsuneLoreweaver copy() { + return new KitsuneLoreweaver(this); + } +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/KiyomaroFirstToStand.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KiyomaroFirstToStand.java new file mode 100644 index 0000000000..1447382e94 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/KiyomaroFirstToStand.java @@ -0,0 +1,128 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CardsInHandCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CardsInControllerHandCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.continious.GainAbilitySourceEffect; +import mage.abilities.effects.common.continious.SetPowerToughnessSourceEffect; +import mage.abilities.keyword.VigilanceAbility; +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.events.GameEvent; + +/** + * + * @author LevelX2 + */ +public class KiyomaroFirstToStand extends CardImpl { + + public KiyomaroFirstToStand(UUID ownerId) { + super(ownerId, 18, "Kiyomaro, First to Stand", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + this.expansionSetCode = "SOK"; + this.supertype.add("Legendary"); + this.subtype.add("Spirit"); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Kiyomaro, First to Stand's power and toughness are each equal to the number of cards in your hand. + DynamicValue xValue= new CardsInControllerHandCount(); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(xValue, Duration.EndOfGame))); + + // As long as you have four or more cards in hand, Kiyomaro has vigilance. + Condition condition = new CardsInHandCondition(CardsInHandCondition.CountType.MORE_THAN,3); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect( + new GainAbilitySourceEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield), condition, + "As long as you have four or more cards in hand, {this} has vigilance")); + this.addAbility(ability); + + // Whenever Kiyomaro deals damage, if you have seven or more cards in hand, you gain 7 life. + this.addAbility(new ConditionalTriggeredAbility( + new KiyomaroFirstToStandDealsDamageTriggeredAbility(), + new CardsInHandCondition(CardsInHandCondition.CountType.MORE_THAN, 6), + "Whenever {this} deals damage, if you have seven or more cards in hand, you gain 7 life" + )); + } + + public KiyomaroFirstToStand(final KiyomaroFirstToStand card) { + super(card); + } + + @Override + public KiyomaroFirstToStand copy() { + return new KiyomaroFirstToStand(this); + } +} + +class KiyomaroFirstToStandDealsDamageTriggeredAbility extends TriggeredAbilityImpl { + + public KiyomaroFirstToStandDealsDamageTriggeredAbility() { + super(Zone.BATTLEFIELD, new GainLifeEffect(7), false); + } + + public KiyomaroFirstToStandDealsDamageTriggeredAbility(final KiyomaroFirstToStandDealsDamageTriggeredAbility ability) { + super(ability); + } + + @Override + public KiyomaroFirstToStandDealsDamageTriggeredAbility copy() { + return new KiyomaroFirstToStandDealsDamageTriggeredAbility(this); + } + + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType().equals(GameEvent.EventType.DAMAGED_CREATURE) + || event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER) + || event.getType().equals(GameEvent.EventType.DAMAGED_PLANESWALKER)) { + if (event.getSourceId().equals(this.getSourceId())) { + for (Effect effect : this.getEffects()) { + effect.setValue("damage", event.getAmount()); + } + return true; + } + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/PresenceOfTheWise.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/PresenceOfTheWise.java new file mode 100644 index 0000000000..89e18d6525 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/PresenceOfTheWise.java @@ -0,0 +1,61 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.saviorsofkamigawa; + +import java.util.UUID; +import mage.abilities.dynamicvalue.MultipliedValue; +import mage.abilities.dynamicvalue.common.CardsInControllerHandCount; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class PresenceOfTheWise extends CardImpl { + + public PresenceOfTheWise(UUID ownerId) { + super(ownerId, 23, "Presence of the Wise", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{W}{W}"); + this.expansionSetCode = "SOK"; + + // You gain 2 life for each card in your hand. + this.getSpellAbility().addEffect(new GainLifeEffect( + new MultipliedValue(new CardsInControllerHandCount(), 2),"You gain 2 life for each card in your hand")); + } + + public PresenceOfTheWise(final PresenceOfTheWise card) { + super(card); + } + + @Override + public PresenceOfTheWise copy() { + return new PresenceOfTheWise(this); + } +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/PromiseOfBunrei.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/PromiseOfBunrei.java new file mode 100644 index 0000000000..a8a5652b05 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/PromiseOfBunrei.java @@ -0,0 +1,105 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.SpiritToken; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class PromiseOfBunrei extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public PromiseOfBunrei(UUID ownerId) { + super(ownerId, 24, "Promise of Bunrei", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); + this.expansionSetCode = "SOK"; + + // When a creature you control dies, sacrifice Promise of Bunrei. If you do, put four 1/1 colorless Spirit creature tokens onto the battlefield. + this.addAbility(new DiesCreatureTriggeredAbility(new PromiseOfBunreiEffect(), false, filter)); + } + + public PromiseOfBunrei(final PromiseOfBunrei card) { + super(card); + } + + @Override + public PromiseOfBunrei copy() { + return new PromiseOfBunrei(this); + } +} + +class PromiseOfBunreiEffect extends OneShotEffect { + + public PromiseOfBunreiEffect() { + super(Outcome.Benefit); + this.staticText = "sacrifice {this}. If you do, put four 1/1 colorless Spirit creature tokens onto the battlefield"; + } + + public PromiseOfBunreiEffect(final PromiseOfBunreiEffect effect) { + super(effect); + } + + @Override + public PromiseOfBunreiEffect copy() { + return new PromiseOfBunreiEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (controller != null && permanent != null) { + if (permanent.sacrifice(source.getSourceId(), game)) { + return new CreateTokenEffect(new SpiritToken(), 4).apply(game, source); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/Reverence.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/Reverence.java new file mode 100644 index 0000000000..4e94da01ee --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/Reverence.java @@ -0,0 +1,103 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.RestrictionEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.Filter; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class Reverence extends CardImpl { + + public Reverence(UUID ownerId) { + super(ownerId, 26, "Reverence", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); + this.expansionSetCode = "SOK"; + + // Creatures with power 2 or less can't attack you. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ReverenceRestrictionEffect())); + } + + public Reverence(final Reverence card) { + super(card); + } + + @Override + public Reverence copy() { + return new Reverence(this); + } +} + +class ReverenceRestrictionEffect extends RestrictionEffect { + + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures with power 2 or less"); + + static { + filter.add(new PowerPredicate(Filter.ComparisonType.LessThan, 3)); + } + + ReverenceRestrictionEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "Creatures with power 2 or less can't attack you"; + } + + ReverenceRestrictionEffect(final ReverenceRestrictionEffect effect) { + super(effect); + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + return filter.match(permanent, source.getSourceId(), source.getControllerId(), game); + } + + @Override + public boolean canAttack(UUID defenderId, Ability source, Game game) { + return !defenderId.equals(source.getControllerId()); + } + + @Override + public ReverenceRestrictionEffect copy() { + return new ReverenceRestrictionEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/SpiritualVisit.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/SpiritualVisit.java new file mode 100644 index 0000000000..3912f290fb --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/SpiritualVisit.java @@ -0,0 +1,64 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.SpliceOntoArcaneAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.permanent.token.SpiritToken; + +/** + * + * @author LevelX2 + */ +public class SpiritualVisit extends CardImpl { + + public SpiritualVisit(UUID ownerId) { + super(ownerId, 29, "Spiritual Visit", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{W}"); + this.expansionSetCode = "SOK"; + this.subtype.add("Arcane"); + + // Put a 1/1 colorless Spirit creature token onto the battlefield. + this.getSpellAbility().addEffect(new CreateTokenEffect(new SpiritToken())); + + // Splice onto Arcane {W} + this.addAbility(new SpliceOntoArcaneAbility("{W}")); + } + + public SpiritualVisit(final SpiritualVisit card) { + super(card); + } + + @Override + public SpiritualVisit copy() { + return new SpiritualVisit(this); + } +} From 5fcea7e6df14980943f9a9e6b03879d8dd13b95c Mon Sep 17 00:00:00 2001 From: emerald000 Date: Tue, 16 Dec 2014 13:58:13 -0500 Subject: [PATCH 18/36] Added Plea for Power, Spelljack and Wild Research. --- .../mage/sets/apocalypse/WildResearch.java | 126 ++++++++++++++ .../mage/sets/conspiracy/PleaForPower.java | 52 ++++++ .../src/mage/sets/judgment/Spelljack.java | 162 ++++++++++++++++++ .../sets/vintagemasters/PleaForPower.java | 108 ++++++++++++ 4 files changed, 448 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/apocalypse/WildResearch.java create mode 100644 Mage.Sets/src/mage/sets/conspiracy/PleaForPower.java create mode 100644 Mage.Sets/src/mage/sets/judgment/Spelljack.java create mode 100644 Mage.Sets/src/mage/sets/vintagemasters/PleaForPower.java diff --git a/Mage.Sets/src/mage/sets/apocalypse/WildResearch.java b/Mage.Sets/src/mage/sets/apocalypse/WildResearch.java new file mode 100644 index 0000000000..37eba90ac7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/apocalypse/WildResearch.java @@ -0,0 +1,126 @@ +/* + * 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.apocalypse; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author emerald000 + */ +public class WildResearch extends CardImpl { + + private static final FilterCard filterEnchantment = new FilterCard("enchantment card"); + private static final FilterCard filterInstant = new FilterCard("instant card"); + static { + filterEnchantment.add(new CardTypePredicate(CardType.ENCHANTMENT)); + filterInstant.add(new CardTypePredicate(CardType.INSTANT)); + } + + public WildResearch(UUID ownerId) { + super(ownerId, 72, "Wild Research", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + this.expansionSetCode = "APC"; + + // {1}{W}: Search your library for an enchantment card and reveal that card. Put it into your hand, then discard a card at random. Then shuffle your library. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new WildResearchEffect(filterEnchantment), new ManaCostsImpl<>("{1}{W}"))); + + // {1}{U}: Search your library for an instant card and reveal that card. Put it into your hand, then discard a card at random. Then shuffle your library. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new WildResearchEffect(filterInstant), new ManaCostsImpl<>("{1}{U}"))); + + } + + public WildResearch(final WildResearch card) { + super(card); + } + + @Override + public WildResearch copy() { + return new WildResearch(this); + } +} + +class WildResearchEffect extends OneShotEffect { + + protected final FilterCard filter; + + WildResearchEffect(FilterCard filter) { + super(Outcome.DrawCard); + this.staticText = "Search your library for an " + filter.getMessage() + " and reveal that card. Put it into your hand, then discard a card at random. Then shuffle your library."; + this.filter = filter; + } + + WildResearchEffect(final WildResearchEffect effect) { + super(effect); + this.filter = effect.filter; + } + + @Override + public WildResearchEffect copy() { + return new WildResearchEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + TargetCardInLibrary target = new TargetCardInLibrary(filter); + if (player.searchLibrary(target, game)) { + if (target.getTargets().size() > 0) { + Card card = player.getLibrary().remove(target.getFirstTarget(), game); + if (card != null) { + player.moveCardToHandWithInfo(card, source.getSourceId(), game, Zone.LIBRARY); + Cards cards = new CardsImpl(); + cards.add(card); + player.revealCards("Wild Research", cards, game, true); + } + } + } + player.discardOne(true, source, game); + player.shuffleLibrary(game); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/conspiracy/PleaForPower.java b/Mage.Sets/src/mage/sets/conspiracy/PleaForPower.java new file mode 100644 index 0000000000..2411d07cbc --- /dev/null +++ b/Mage.Sets/src/mage/sets/conspiracy/PleaForPower.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.conspiracy; + +import java.util.UUID; + +/** + * + * @author emerald000 + */ +public class PleaForPower extends mage.sets.vintagemasters.PleaForPower { + + public PleaForPower(UUID ownerId) { + super(ownerId); + this.cardNumber = 24; + this.expansionSetCode = "CNS"; + } + + public PleaForPower(final PleaForPower card) { + super(card); + } + + @Override + public PleaForPower copy() { + return new PleaForPower(this); + } +} diff --git a/Mage.Sets/src/mage/sets/judgment/Spelljack.java b/Mage.Sets/src/mage/sets/judgment/Spelljack.java new file mode 100644 index 0000000000..00703ee289 --- /dev/null +++ b/Mage.Sets/src/mage/sets/judgment/Spelljack.java @@ -0,0 +1,162 @@ +/* + * 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.judgment; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; +import mage.players.Player; +import mage.target.TargetSpell; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author emerald000 + */ +public class Spelljack extends CardImpl { + + public Spelljack(UUID ownerId) { + super(ownerId, 51, "Spelljack", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{3}{U}{U}{U}"); + this.expansionSetCode = "JUD"; + + // Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. You may play it without paying its mana cost for as long as it remains exiled. + this.getSpellAbility().addEffect(new SpelljackEffect()); + this.getSpellAbility().addTarget(new TargetSpell()); + } + + public Spelljack(final Spelljack card) { + super(card); + } + + @Override + public Spelljack copy() { + return new Spelljack(this); + } +} + +class SpelljackEffect extends OneShotEffect { + + SpelljackEffect() { + super(Outcome.PlayForFree); + this.staticText = "Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. You may play it without paying its mana cost for as long as it remains exiled"; + } + + SpelljackEffect(final SpelljackEffect effect) { + super(effect); + } + + @Override + public SpelljackEffect copy() { + return new SpelljackEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + UUID objectId = targetPointer.getFirst(game, source); + UUID sourceId = source.getSourceId(); + + StackObject stackObject = game.getStack().getStackObject(objectId); + if (stackObject != null && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) { + game.rememberLKI(objectId, Zone.STACK, stackObject); + game.getStack().remove(stackObject); + if (!((Spell) stackObject).isCopiedSpell()) { + MageObject card = game.getObject(stackObject.getSourceId()); + if (card instanceof Card) { + ((Card) card).moveToZone(Zone.EXILED, sourceId, game, true); + ContinuousEffect effect = new SpelljackCastFromExileEffect(); + effect.setTargetPointer(new FixedTarget(card.getId())); + game.addEffect(effect, source); + } + } + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId())); + return true; + } + return false; + } +} + +class SpelljackCastFromExileEffect extends AsThoughEffectImpl { + + SpelljackCastFromExileEffect() { + super(AsThoughEffectType.PLAY_FROM_NON_HAND_ZONE, Duration.Custom, Outcome.Benefit); + staticText = "You may cast that card without paying its mana cost as long as it remains exiled"; + } + + SpelljackCastFromExileEffect(final SpelljackCastFromExileEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public SpelljackCastFromExileEffect copy() { + return new SpelljackCastFromExileEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + if (affectedControllerId.equals(source.getControllerId())) { + if (getTargetPointer().getFirst(game, source) == null) { + this.discard(); + return false; + } + if (sourceId.equals(getTargetPointer().getFirst(game, source))) { + Card card = game.getCard(sourceId); + if (card != null) { + if (game.getState().getZone(sourceId) == Zone.EXILED) { + Player player = game.getPlayer(affectedControllerId); + player.setCastSourceIdWithoutMana(sourceId); + return true; + } + else { + this.discard(); + } + } + } + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/vintagemasters/PleaForPower.java b/Mage.Sets/src/mage/sets/vintagemasters/PleaForPower.java new file mode 100644 index 0000000000..0a0668a2d9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/PleaForPower.java @@ -0,0 +1,108 @@ +/* + * 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.vintagemasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.turn.AddExtraTurnControllerEffect; +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 emerald000 + */ +public class PleaForPower extends CardImpl { + + public PleaForPower(UUID ownerId) { + super(ownerId, 87, "Plea for Power", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{U}"); + this.expansionSetCode = "VMA"; + + // Will of the council - Starting with you, each player votes for time or knowledge. If time gets more votes, take an extra turn after this one. If knowledge gets more votes or the vote is tied, draw three cards. + this.getSpellAbility().addEffect(new PleaForPowerEffect()); + } + + public PleaForPower(final PleaForPower card) { + super(card); + } + + @Override + public PleaForPower copy() { + return new PleaForPower(this); + } +} + +class PleaForPowerEffect extends OneShotEffect { + + PleaForPowerEffect() { + super(Outcome.Benefit); + this.staticText = "Will of the council — Starting with you, each player votes for time or knowledge. If time gets more votes, take an extra turn after this one. If knowledge gets more votes or the vote is tied, draw three cards"; + } + + PleaForPowerEffect(final PleaForPowerEffect effect) { + super(effect); + } + + @Override + public PleaForPowerEffect copy() { + return new PleaForPowerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int timeCount = 0; + int knowledgeCount = 0; + for (UUID playerId : controller.getInRange()) { + Player player = game.getPlayer(playerId); + if (player.chooseUse(Outcome.ExtraTurn, "Choose time?", game)) { + timeCount++; + game.informPlayers(player.getName() + " has chosen: time"); + } + else { + knowledgeCount++; + game.informPlayers(player.getName() + " has chosen: knowledge"); + } + } + if (timeCount > knowledgeCount) { + new AddExtraTurnControllerEffect().apply(game, source); + } + else { + controller.drawCards(3, game); + } + return true; + } + return false; + } +} From 43efa36c6fa6536529dfa11a3f511b80ae2fd834 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 17 Dec 2014 08:35:42 +0100 Subject: [PATCH 19/36] * Added Phyrexian Devourer and Miren the Moaning Well. --- .../sets/alliances/PhyrexianDevourer.java | 197 ++++++++++++++++++ .../MirenTheMoaningWell.java | 112 ++++++++++ 2 files changed, 309 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/alliances/PhyrexianDevourer.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/MirenTheMoaningWell.java diff --git a/Mage.Sets/src/mage/sets/alliances/PhyrexianDevourer.java b/Mage.Sets/src/mage/sets/alliances/PhyrexianDevourer.java new file mode 100644 index 0000000000..8c1990ff7b --- /dev/null +++ b/Mage.Sets/src/mage/sets/alliances/PhyrexianDevourer.java @@ -0,0 +1,197 @@ +/* + * 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.alliances; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.StateTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +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.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class PhyrexianDevourer extends CardImpl { + + public PhyrexianDevourer(UUID ownerId) { + super(ownerId, 167, "Phyrexian Devourer", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}"); + this.expansionSetCode = "ALL"; + this.subtype.add("Construct"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Phyrexian Devourer's power is 7 or greater, sacrifice it. + this.addAbility(new PhyrexianDevourerStateTriggeredAbility()); + + // Exile the top card of your library: Put X +1/+1 counters on Phyrexian Devourer, where X is the exiled card's converted mana cost. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PhyrexianDevourerEffect(), new ExileTopCardLibraryCost())); + + } + + public PhyrexianDevourer(final PhyrexianDevourer card) { + super(card); + } + + @Override + public PhyrexianDevourer copy() { + return new PhyrexianDevourer(this); + } +} + +class PhyrexianDevourerStateTriggeredAbility extends StateTriggeredAbility { + + public PhyrexianDevourerStateTriggeredAbility() { + super(Zone.BATTLEFIELD, new SacrificeSourceEffect()); + } + + public PhyrexianDevourerStateTriggeredAbility(final PhyrexianDevourerStateTriggeredAbility ability) { + super(ability); + } + + @Override + public PhyrexianDevourerStateTriggeredAbility copy() { + return new PhyrexianDevourerStateTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = game.getPermanent(getSourceId()); + if(permanent != null && permanent.getPower().getValue() >= 7){ + return true; + } + return false; + } + + @Override + public String getRule() { + return "When {this}'s power is 7 or greater, sacrifice it."; + } + +} + +class PhyrexianDevourerEffect extends OneShotEffect { + + public PhyrexianDevourerEffect() { + super(Outcome.BoostCreature); + this.staticText = "Put X +1/+1 counters on {this}, where X is the exiled card's converted mana cost"; + } + + public PhyrexianDevourerEffect(final PhyrexianDevourerEffect effect) { + super(effect); + } + + @Override + public PhyrexianDevourerEffect copy() { + return new PhyrexianDevourerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Card card = null; + for (Cost cost: source.getCosts()) { + if (cost instanceof ExileTopCardLibraryCost) { + card = ((ExileTopCardLibraryCost)cost).getCard(); + } + } + if (card != null) { + int amount = card.getManaCost().convertedManaCost(); + if (amount > 0) { + return new AddCountersSourceEffect(CounterType.P1P1.createInstance(amount)).apply(game, source); + } + } + return true; + } + return false; + } +} + +class ExileTopCardLibraryCost extends CostImpl { + + Card card; + + public ExileTopCardLibraryCost() { + this.text = "Exile the top card of your library"; + } + + public ExileTopCardLibraryCost(final ExileTopCardLibraryCost cost) { + super(cost); + this.card = cost.getCard(); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { + Player controller = game.getPlayer(controllerId); + if (controller != null) { + card = controller.getLibrary().getFromTop(game); + if (card != null) { + paid = controller.moveCardToExileWithInfo(card, null, "", sourceId, game, Zone.LIBRARY); + } + } + return paid; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + Player controller = game.getPlayer(controllerId); + if (controller != null) { + return controller.getLibrary().size() > 0; + } + return false; + } + + @Override + public ExileTopCardLibraryCost copy() { + return new ExileTopCardLibraryCost(this); + } + + public Card getCard() { + return card; + } + +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/MirenTheMoaningWell.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MirenTheMoaningWell.java new file mode 100644 index 0000000000..44c86acf12 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MirenTheMoaningWell.java @@ -0,0 +1,112 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class MirenTheMoaningWell extends CardImpl { + + public MirenTheMoaningWell(UUID ownerId) { + super(ownerId, 163, "Miren, the Moaning Well", Rarity.RARE, new CardType[]{CardType.LAND}, ""); + this.expansionSetCode = "SOK"; + this.supertype.add("Legendary"); + + // {tap}: Add {1} to your mana pool. + this.addAbility(new ColorlessManaAbility()); + + // {3}, {tap}, Sacrifice a creature: You gain life equal to the sacrificed creature's toughness. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MirenTheMoaningWellEffect(), new GenericManaCost(3)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1,1,new FilterControlledCreaturePermanent("a creature"), true))); + this.addAbility(ability); + } + + public MirenTheMoaningWell(final MirenTheMoaningWell card) { + super(card); + } + + @Override + public MirenTheMoaningWell copy() { + return new MirenTheMoaningWell(this); + } +} + +class MirenTheMoaningWellEffect extends OneShotEffect { + + public MirenTheMoaningWellEffect() { + super(Outcome.GainLife); + this.staticText = "You gain life equal to the sacrificed creature's toughness"; + } + + public MirenTheMoaningWellEffect(final MirenTheMoaningWellEffect effect) { + super(effect); + } + + @Override + public MirenTheMoaningWellEffect copy() { + return new MirenTheMoaningWellEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (Cost cost : source.getCosts()) { + if (cost instanceof SacrificeTargetCost) { + int amount = ((SacrificeTargetCost) cost).getPermanents().get(0).getToughness().getValue(); + if (amount > 0) { + controller.gainLife(amount, game); + } + } + } + return true; + } + return false; + } +} From c4541e49ee03f636db58e5e05692c7408bb73b58 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 17 Dec 2014 15:26:22 +0100 Subject: [PATCH 20/36] Some changes to net mana handling. --- .../mage/sets/commander2013/OpalPalace.java | 88 ++----------------- .../CommanderColorIdentityManaAbility.java | 9 +- Mage/src/mage/abilities/mana/ManaAbility.java | 2 +- .../abilities/mana/SimpleManaAbility.java | 18 ++++ 4 files changed, 30 insertions(+), 87 deletions(-) diff --git a/Mage.Sets/src/mage/sets/commander2013/OpalPalace.java b/Mage.Sets/src/mage/sets/commander2013/OpalPalace.java index d3852b649f..3fc632ea51 100644 --- a/Mage.Sets/src/mage/sets/commander2013/OpalPalace.java +++ b/Mage.Sets/src/mage/sets/commander2013/OpalPalace.java @@ -32,13 +32,15 @@ import java.util.List; import java.util.UUID; import mage.Mana; import mage.abilities.Ability; +import mage.abilities.common.EmptyEffect; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.ManaEffect; import mage.abilities.mana.ColorlessManaAbility; -import mage.abilities.mana.SimpleManaAbility; +import mage.abilities.mana.CommanderColorIdentityManaAbility; +import mage.abilities.mana.ManaAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.choices.Choice; @@ -71,7 +73,7 @@ public class OpalPalace extends CardImpl { // {tap}: Add {1} to your mana pool. this.addAbility(new ColorlessManaAbility()); // {1}, {tap}: Add to your mana pool one mana of any color in your commander's color identity. If you spend this mana to cast your commander, it enters the battlefield with a number of +1/+1 counters on it equal to the number of times it's been cast from the command zone this game. - Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new OpalPalaceManaEffect(), new GenericManaCost(1)); + Ability ability = new CommanderColorIdentityManaAbility(new GenericManaCost(1)); ability.addCost(new TapSourceCost()); this.addAbility(ability); @@ -92,87 +94,9 @@ public class OpalPalace extends CardImpl { } } -class OpalPalaceManaEffect extends ManaEffect { - - public OpalPalaceManaEffect() { - super(); - this.staticText = "Add to your mana pool one mana of any color in your commander's color identity. If you spend this mana to cast your commander, it enters the battlefield with a number of +1/+1 counters on it equal to the number of times it's been cast from the command zone this game"; - } - - public OpalPalaceManaEffect(final OpalPalaceManaEffect effect) { - super(effect); - } - - @Override - public OpalPalaceManaEffect copy() { - return new OpalPalaceManaEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Card commander = game.getCard(controller.getCommanderId()); - if (commander != null) { - Mana commanderMana = commander.getManaCost().getMana(); - Choice choice = new ChoiceImpl(true); - choice.setMessage("Pick a mana color"); - if (commanderMana.getBlack() > 0) { - choice.getChoices().add("Black"); - } - if (commanderMana.getRed() > 0) { - choice.getChoices().add("Red"); - } - if (commanderMana.getBlue() > 0) { - choice.getChoices().add("Blue"); - } - if (commanderMana.getGreen() > 0) { - choice.getChoices().add("Green"); - } - if (commanderMana.getWhite() > 0) { - choice.getChoices().add("White"); - } - if (choice.getChoices().size() > 0) { - Mana mana = new Mana(); - if (choice.getChoices().size() == 1) { - choice.setChoice(choice.getChoices().iterator().next()); - } else { - controller.choose(outcome, choice, game); - } - if (choice.getChoice().equals("Black")) { - mana.addBlack(); - } else if (choice.getChoice().equals("Blue")) { - mana.addBlue(); - } else if (choice.getChoice().equals("Red")) { - mana.addRed(); - } else if (choice.getChoice().equals("Green")) { - mana.addGreen(); - } else if (choice.getChoice().equals("White")) { - mana.addWhite(); - } - // set to indicate, that the mana can boost the commander - mana.setFlag(true); - checkToFirePossibleEvents(mana, game, source); - controller.getManaPool().addMana(mana, game, source); - - } - return true; - } - } - return false; - } - - @Override - public Mana getMana(Game game, Ability source) { - return null; - } - - -} - class OpalPalaceWatcher extends Watcher { - public List commanderId = new ArrayList(); + public List commanderId = new ArrayList<>(); public OpalPalaceWatcher() { super("ManaPaidFromOpalPalaceWatcher", WatcherScope.CARD); @@ -249,7 +173,7 @@ class OpalPalaceEntersBattlefieldEffect extends ReplacementEffectImpl { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { Integer castCount = (Integer)game.getState().getValue(permanent.getId() + "_castCount"); - if (castCount != null && castCount.intValue() > 0) { + if (castCount != null && castCount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(castCount), game); } } diff --git a/Mage/src/mage/abilities/mana/CommanderColorIdentityManaAbility.java b/Mage/src/mage/abilities/mana/CommanderColorIdentityManaAbility.java index d355063621..2d4807cf89 100644 --- a/Mage/src/mage/abilities/mana/CommanderColorIdentityManaAbility.java +++ b/Mage/src/mage/abilities/mana/CommanderColorIdentityManaAbility.java @@ -36,12 +36,9 @@ import mage.abilities.effects.common.ManaEffect; import mage.cards.Card; import mage.choices.Choice; import mage.choices.ChoiceImpl; -import mage.constants.AbilityType; import mage.constants.ColoredManaSymbol; import mage.constants.Zone; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ManaEvent; import mage.players.Player; /** @@ -54,7 +51,11 @@ public class CommanderColorIdentityManaAbility extends ManaAbility { public CommanderColorIdentityManaAbility() { super(Zone.BATTLEFIELD, new CommanderIdentityManaEffect(),new TapSourceCost()); } - + + public CommanderColorIdentityManaAbility(Cost cost) { + super(Zone.BATTLEFIELD, new CommanderIdentityManaEffect(), cost); + } + public CommanderColorIdentityManaAbility(final CommanderColorIdentityManaAbility ability) { super(ability); } diff --git a/Mage/src/mage/abilities/mana/ManaAbility.java b/Mage/src/mage/abilities/mana/ManaAbility.java index bccdaaf9a4..15affee8ef 100644 --- a/Mage/src/mage/abilities/mana/ManaAbility.java +++ b/Mage/src/mage/abilities/mana/ManaAbility.java @@ -58,7 +58,7 @@ public abstract class ManaAbility extends ActivatedAbilityImpl { } } - public ManaAbility(ManaAbility ability) { + public ManaAbility(final ManaAbility ability) { super(ability); this.netMana.addAll(ability.netMana); } diff --git a/Mage/src/mage/abilities/mana/SimpleManaAbility.java b/Mage/src/mage/abilities/mana/SimpleManaAbility.java index 289b1031b2..fdc58c9826 100644 --- a/Mage/src/mage/abilities/mana/SimpleManaAbility.java +++ b/Mage/src/mage/abilities/mana/SimpleManaAbility.java @@ -28,11 +28,14 @@ package mage.abilities.mana; +import java.util.List; import mage.Mana; import mage.abilities.costs.Cost; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.BasicManaEffect; import mage.abilities.effects.common.ManaEffect; import mage.constants.Zone; +import mage.game.Game; /** * @@ -58,4 +61,19 @@ public class SimpleManaAbility extends ManaAbility { return new SimpleManaAbility(this); } + @Override + public List getNetMana(Game game) { + if (netMana.isEmpty()) { + for (Effect effect: getEffects()) { + if (effect instanceof ManaEffect) { + Mana effectMana =((ManaEffect)effect).getMana(game, this); + if (effectMana != null) { + netMana.add(effectMana); + } + } + } + } + return netMana; + } + } From cef17e53e92e9d344c3c2d2af53f2d58098afee0 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 17 Dec 2014 15:27:20 +0100 Subject: [PATCH 21/36] * Nezumi Graverobber - Fixed that flip side was not shown in big image. --- .../mage/sets/championsofkamigawa/NezumiGraverobber.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/NezumiGraverobber.java b/Mage.Sets/src/mage/sets/championsofkamigawa/NezumiGraverobber.java index c2a187ffd7..175e21f872 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/NezumiGraverobber.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/NezumiGraverobber.java @@ -65,7 +65,7 @@ public class NezumiGraverobber extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); this.flipCard = true; - this.flipCardName = "Nighteyes The Desecrator"; + this.flipCardName = "Nighteyes the Desecrator"; // {1}{B}: Exile target card from an opponent's graveyard. If no cards are in that graveyard, flip Nezumi Graverobber. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new ManaCostsImpl("{1}{B}")); @@ -118,8 +118,9 @@ class NezumiGraverobberFlipEffect extends OneShotEffect { } class NighteyesTheDesecratorToken extends Token { - NighteyesTheDesecratorToken() { - super("Nighteyes The Desecrator", ""); + + NighteyesTheDesecratorToken() { + super("Nighteyes the Desecrator", ""); supertype.add("Legendary"); cardType.add(CardType.CREATURE); color.setBlack(true); From 4d658909ee6c8b31f4ca5b6739b9ecfb514a9526 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 17 Dec 2014 15:28:33 +0100 Subject: [PATCH 22/36] Added Sentinel, Wakestone Gargoyle, Silhana Starfletcher and Orchard Warden. --- Mage.Client/serverlist.txt | 2 +- .../src/mage/sets/apocalypse/Cromat.java | 2 +- .../src/mage/sets/coldsnap/MishrasBauble.java | 2 +- .../sets/conspiracy/WakestoneGargoyle.java | 80 ++++++++++++ .../sets/dissension/WakestoneGargoyle.java | 54 ++++++++ .../sets/guildpact/SilhanaStarfletcher.java | 120 ++++++++++++++++++ Mage.Sets/src/mage/sets/legends/Sentinel.java | 115 +++++++++++++++++ .../src/mage/sets/legions/WardSliver.java | 1 - .../mage/sets/morningtide/OrchardWarden.java | 109 ++++++++++++++++ .../mage/sets/stronghold/RollingStones.java | 4 +- ...AsThoughtItDidntHaveDefenderAllEffect.java | 22 +++- .../continious/SetToughnessSourceEffect.java | 4 + 12 files changed, 502 insertions(+), 13 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/conspiracy/WakestoneGargoyle.java create mode 100644 Mage.Sets/src/mage/sets/dissension/WakestoneGargoyle.java create mode 100644 Mage.Sets/src/mage/sets/guildpact/SilhanaStarfletcher.java create mode 100644 Mage.Sets/src/mage/sets/legends/Sentinel.java create mode 100644 Mage.Sets/src/mage/sets/morningtide/OrchardWarden.java diff --git a/Mage.Client/serverlist.txt b/Mage.Client/serverlist.txt index b7f106d4c9..41c2909e7f 100644 --- a/Mage.Client/serverlist.txt +++ b/Mage.Client/serverlist.txt @@ -1,5 +1,5 @@ woogerworks (Version 1.3.0 dev 2014-10-29V2) :xmage.woogerworks.com:17171 -XMage.info 1 (Version 1.3.0 dev 2014-11-29v3) :176.31.186.181:17171 +XMage.info 1 (Version 1.3.0 dev 2014-11-29v4) :176.31.186.181:17171 XMage.info 2 (Version 1.3.0 dev 2014-11-29V4) :176.31.186.181:17000 Seedds Server (Version 1.3.0 dev 2014-11-29v2) :115.29.203.80:17171 localhost -> connect to your local server (must be started):localhost:17171 diff --git a/Mage.Sets/src/mage/sets/apocalypse/Cromat.java b/Mage.Sets/src/mage/sets/apocalypse/Cromat.java index 24356d737e..6d848d5b64 100644 --- a/Mage.Sets/src/mage/sets/apocalypse/Cromat.java +++ b/Mage.Sets/src/mage/sets/apocalypse/Cromat.java @@ -70,7 +70,7 @@ public class Cromat extends CardImpl { this.toughness = new MageInt(5); // {W}{B}: Destroy target creature blocking or blocked by Cromat. - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature blocking or blocked by {this}"); + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature blocking or blocked by Cromat"); filter.add(Predicates.or(new BlockedByIdPredicate(this.getId()), new BlockingAttackerIdPredicate(this.getId()))); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{W}{B}")); diff --git a/Mage.Sets/src/mage/sets/coldsnap/MishrasBauble.java b/Mage.Sets/src/mage/sets/coldsnap/MishrasBauble.java index 8d94de4551..69d9e18ba0 100644 --- a/Mage.Sets/src/mage/sets/coldsnap/MishrasBauble.java +++ b/Mage.Sets/src/mage/sets/coldsnap/MishrasBauble.java @@ -57,7 +57,7 @@ public class MishrasBauble extends CardImpl { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryTopCardTargetPlayerEffect(), new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); ability.addEffect(new CreateDelayedTriggeredAbilityEffect( - new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1), Duration.OneUse))); + new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1), Duration.OneUse), false)); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/conspiracy/WakestoneGargoyle.java b/Mage.Sets/src/mage/sets/conspiracy/WakestoneGargoyle.java new file mode 100644 index 0000000000..ef7df54b8b --- /dev/null +++ b/Mage.Sets/src/mage/sets/conspiracy/WakestoneGargoyle.java @@ -0,0 +1,80 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.conspiracy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.combat.CanAttackAsThoughtItDidntHaveDefenderAllEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; + +/** + * + * @author LevelX2 + */ +public class WakestoneGargoyle extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Creatures you control with defender"); + + static { + filter.add(new AbilityPredicate(DefenderAbility.class)); + } + + public WakestoneGargoyle(UUID ownerId) { + super(ownerId, 88, "Wakestone Gargoyle", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{W}"); + this.expansionSetCode = "CNS"; + this.subtype.add("Gargoyle"); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + // Flying + this.addAbility(FlyingAbility.getInstance()); + // {1}{W}: Creatures you control with defender can attack this turn as though they didn't have defender. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CanAttackAsThoughtItDidntHaveDefenderAllEffect(Duration.EndOfTurn, filter), new ManaCostsImpl("{1}{W}") )); + } + + public WakestoneGargoyle(final WakestoneGargoyle card) { + super(card); + } + + @Override + public WakestoneGargoyle copy() { + return new WakestoneGargoyle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/dissension/WakestoneGargoyle.java b/Mage.Sets/src/mage/sets/dissension/WakestoneGargoyle.java new file mode 100644 index 0000000000..2f2a35d9a2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dissension/WakestoneGargoyle.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.dissension; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class WakestoneGargoyle extends mage.sets.conspiracy.WakestoneGargoyle { + + public WakestoneGargoyle(UUID ownerId) { + super(ownerId); + this.cardNumber = 21; + this.expansionSetCode = "DIS"; + this.rarity = Rarity.RARE; + } + + public WakestoneGargoyle(final WakestoneGargoyle card) { + super(card); + } + + @Override + public WakestoneGargoyle copy() { + return new WakestoneGargoyle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/guildpact/SilhanaStarfletcher.java b/Mage.Sets/src/mage/sets/guildpact/SilhanaStarfletcher.java new file mode 100644 index 0000000000..c86b5925f9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/guildpact/SilhanaStarfletcher.java @@ -0,0 +1,120 @@ +/* + * 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.guildpact; + +import java.util.UUID; +import mage.MageInt; +import mage.Mana; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.ChooseColorEffect; +import mage.abilities.effects.common.ManaEffect; +import mage.abilities.keyword.ReachAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class SilhanaStarfletcher extends CardImpl { + + public SilhanaStarfletcher(UUID ownerId) { + super(ownerId, 95, "Silhana Starfletcher", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "GPT"; + this.subtype.add("Elf"); + this.subtype.add("Druid"); + this.subtype.add("Archer"); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // As Silhana Starfletcher enters the battlefield, choose a color. + this.addAbility(new EntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral))); + + // {tap}: Add one mana of the chosen color to your mana pool. + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new SilhanaStarfletcherManaEffect(), new TapSourceCost())); + + } + + public SilhanaStarfletcher(final SilhanaStarfletcher card) { + super(card); + } + + @Override + public SilhanaStarfletcher copy() { + return new SilhanaStarfletcher(this); + } +} + +class SilhanaStarfletcherManaEffect extends ManaEffect { + + public SilhanaStarfletcherManaEffect() { + super(); + staticText = "Add one mana of the chosen color to your mana pool"; + } + + public SilhanaStarfletcherManaEffect(final SilhanaStarfletcherManaEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + player.getManaPool().addMana(getMana(game, source), game, source); + } + return true; + } + + @Override + public Mana getMana(Game game, Ability source) { + ObjectColor color = (ObjectColor) game.getState().getValue(source.getSourceId() + "_color"); + if (color != null) { + return new Mana(ColoredManaSymbol.lookup(color.toString().charAt(0))); + } else { + return null; + } + } + + @Override + public SilhanaStarfletcherManaEffect copy() { + return new SilhanaStarfletcherManaEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/legends/Sentinel.java b/Mage.Sets/src/mage/sets/legends/Sentinel.java new file mode 100644 index 0000000000..a61e3732b1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/legends/Sentinel.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.legends; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.SetToughnessSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.BlockedByIdPredicate; +import mage.filter.predicate.permanent.BlockingAttackerIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class Sentinel extends CardImpl { + + public Sentinel(UUID ownerId) { + super(ownerId, 239, "Sentinel", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); + this.expansionSetCode = "LEG"; + this.subtype.add("Shapeshifter"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature blocking or blocked by Sentinel"); + filter.add(Predicates.or(new BlockedByIdPredicate(this.getId()), + new BlockingAttackerIdPredicate(this.getId()))); + // 0: Change Sentinel's base toughness to 1 plus the power of target creature blocking or blocked by Sentinel. (This effect lasts indefinitely.) + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SentinelEffect(), new GenericManaCost(0)); + ability.addTarget(null); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + + } + + public Sentinel(final Sentinel card) { + super(card); + } + + @Override + public Sentinel copy() { + return new Sentinel(this); + } +} + +class SentinelEffect extends OneShotEffect { + + public SentinelEffect() { + super(Outcome.Detriment); + this.staticText = "Change {this}'s base toughness to 1 plus the power of target creature blocking or blocked by {this}. (This effect lasts indefinitely.)"; + } + + public SentinelEffect(final SentinelEffect effect) { + super(effect); + } + + @Override + public SentinelEffect copy() { + return new SentinelEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent targetPermanent = game.getPermanentOrLKIBattlefield(targetPointer.getFirst(game, source)); + if (controller != null && targetPermanent != null) { + int newToughness = targetPermanent.getPower().getValue() + 1; + game.addEffect(new SetToughnessSourceEffect(new StaticValue(newToughness), Duration.Custom), source); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/legions/WardSliver.java b/Mage.Sets/src/mage/sets/legions/WardSliver.java index ceb0886b4d..1135f0b183 100644 --- a/Mage.Sets/src/mage/sets/legions/WardSliver.java +++ b/Mage.Sets/src/mage/sets/legions/WardSliver.java @@ -37,7 +37,6 @@ import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; -import mage.choices.Choice; import mage.choices.ChoiceColor; import mage.constants.CardType; import mage.constants.Duration; diff --git a/Mage.Sets/src/mage/sets/morningtide/OrchardWarden.java b/Mage.Sets/src/mage/sets/morningtide/OrchardWarden.java new file mode 100644 index 0000000000..02eaba24f2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/OrchardWarden.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.morningtide; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class OrchardWarden extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another Treefolk creature"); + + static { + filter.add(new SubtypePredicate("Treefolk")); + filter.add(new AnotherPredicate()); + } + + public OrchardWarden(UUID ownerId) { + super(ownerId, 131, "Orchard Warden", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{4}{G}{G}"); + this.expansionSetCode = "MOR"; + this.subtype.add("Treefolk"); + this.subtype.add("Shaman"); + this.power = new MageInt(4); + this.toughness = new MageInt(6); + + // Whenever another Treefolk creature enters the battlefield under your control, you may gain life equal to that creature's toughness. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new OrchardWardenffect(), filter, true, SetTargetPointer.PERMANENT, "")); + } + + public OrchardWarden(final OrchardWarden card) { + super(card); + } + + @Override + public OrchardWarden copy() { + return new OrchardWarden(this); + } +} + +class OrchardWardenffect extends OneShotEffect { + + public OrchardWardenffect() { + super(Outcome.GainLife); + this.staticText = "you may gain life equal to that creature's toughness"; + } + + public OrchardWardenffect(final OrchardWardenffect effect) { + super(effect); + } + + @Override + public OrchardWardenffect copy() { + return new OrchardWardenffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); + if (controller != null && permanent != null) { + controller.gainLife(permanent.getToughness().getValue(), game); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/stronghold/RollingStones.java b/Mage.Sets/src/mage/sets/stronghold/RollingStones.java index f0cc84832c..aaebcec168 100644 --- a/Mage.Sets/src/mage/sets/stronghold/RollingStones.java +++ b/Mage.Sets/src/mage/sets/stronghold/RollingStones.java @@ -35,7 +35,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Rarity; import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.SubtypePredicate; /** @@ -44,7 +44,7 @@ import mage.filter.predicate.mageobject.SubtypePredicate; */ public class RollingStones extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Wall creatures"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Wall creatures"); static { filter.add(new SubtypePredicate("Wall")); diff --git a/Mage/src/mage/abilities/effects/common/combat/CanAttackAsThoughtItDidntHaveDefenderAllEffect.java b/Mage/src/mage/abilities/effects/common/combat/CanAttackAsThoughtItDidntHaveDefenderAllEffect.java index d30c4a03e2..11b4b3b945 100644 --- a/Mage/src/mage/abilities/effects/common/combat/CanAttackAsThoughtItDidntHaveDefenderAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/combat/CanAttackAsThoughtItDidntHaveDefenderAllEffect.java @@ -72,15 +72,23 @@ public class CanAttackAsThoughtItDidntHaveDefenderAllEffect extends AsThoughEffe } @Override - public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - Permanent permanent = game.getPermanent(sourceId); - if (permanent != null && filter.match(permanent, game)) { - return true; - } - return false; + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + Permanent permanent = game.getPermanent(objectId); + return permanent != null && filter.match(permanent, game); } private String getText() { - return filter.getMessage() + " can attack as though they didn't have defender"; + StringBuilder sb = new StringBuilder(filter.getMessage()); + sb.append(" can attack "); + if (!duration.toString().isEmpty()) { + if(Duration.EndOfTurn.equals(duration)) { + sb.append("this turn"); + } else { + sb.append(duration.toString()); + } + sb.append(" "); + } + sb.append("as though they didn't have defender"); + return sb.toString(); } } diff --git a/Mage/src/mage/abilities/effects/common/continious/SetToughnessSourceEffect.java b/Mage/src/mage/abilities/effects/common/continious/SetToughnessSourceEffect.java index f171ce5d3d..24c1552cf6 100644 --- a/Mage/src/mage/abilities/effects/common/continious/SetToughnessSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/continious/SetToughnessSourceEffect.java @@ -68,6 +68,10 @@ public class SetToughnessSourceEffect extends ContinuousEffectImpl { int value = amount.calculate(game, source, this); mageObject.getToughness().setValue(value); return true; + } else { + if (Duration.Custom.equals(duration)) { + discard(); + } } return false; } From bd5ac3756df14729ac97a35cab140a4b2b19d885 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 17 Dec 2014 17:03:00 +0100 Subject: [PATCH 23/36] [SOK] Added 3 cards. --- .../sets/saviorsofkamigawa/CowedByWisdom.java | 145 +++++++++++++++ .../saviorsofkamigawa/CurtainOfLight.java | 156 ++++++++++++++++ .../ErayoSoratamiAscendant.java | 169 ++++++++++++++++++ Mage/src/mage/game/combat/Combat.java | 18 +- Mage/src/mage/game/combat/CombatGroup.java | 9 + .../common/CastSpellLastTurnWatcher.java | 8 + 6 files changed, 496 insertions(+), 9 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/CowedByWisdom.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/CurtainOfLight.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/ErayoSoratamiAscendant.java diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/CowedByWisdom.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/CowedByWisdom.java new file mode 100644 index 0000000000..cb8acbbbf0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/CowedByWisdom.java @@ -0,0 +1,145 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class CowedByWisdom extends CardImpl { + + public CowedByWisdom(UUID ownerId) { + super(ownerId, 5, "Cowed by Wisdom", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{W}"); + this.expansionSetCode = "SOK"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.UnboostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature can't attack or block unless its controller pays {1} for each card in your hand. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CowedByWisdomEffect())); + } + + public CowedByWisdom(final CowedByWisdom card) { + super(card); + } + + @Override + public CowedByWisdom copy() { + return new CowedByWisdom(this); + } +} + +class CowedByWisdomEffect extends ReplacementEffectImpl { + + private static final String effectText = "Enchanted creature can't attack or block unless its controller pays {1} for each card in your hand"; + + CowedByWisdomEffect ( ) { + super(Duration.WhileOnBattlefield, Outcome.Neutral); + staticText = effectText; + } + + CowedByWisdomEffect ( CowedByWisdomEffect effect ) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player player = game.getPlayer(event.getPlayerId()); + Player controller = game.getPlayer(source.getControllerId()); + if (player != null && controller != null) { + if (controller.getHand().isEmpty()) { + return false; + } + String chooseText; + int cardsInHand = controller.getHand().size(); + if (event.getType().equals(GameEvent.EventType.DECLARE_ATTACKER)) { + chooseText = "Pay {" + cardsInHand + "} to attack?"; + } else { + chooseText = "Pay {" + cardsInHand + "} to block?"; + } + ManaCostsImpl attackBlockTax = new ManaCostsImpl("{" + cardsInHand + "}"); + if (attackBlockTax.canPay(source, source.getSourceId(), event.getPlayerId(), game) + && player.chooseUse(Outcome.Neutral, chooseText, game)) { + if (attackBlockTax.payOrRollback(source, game, source.getSourceId(), event.getPlayerId())) { + return false; + } + } + return true; + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType().equals(GameEvent.EventType.DECLARE_ATTACKER)) { + Permanent attacker = game.getPermanent(event.getSourceId()); + return attacker != null && attacker.getAttachments().contains(source.getSourceId()); + } + if (event.getType().equals(GameEvent.EventType.DECLARE_BLOCKER)) { + Permanent blocker = game.getPermanent(event.getSourceId()); + return blocker != null && blocker.getAttachments().contains(source.getSourceId()); + } + return false; + } + + @Override + public CowedByWisdomEffect copy() { + return new CowedByWisdomEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/CurtainOfLight.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/CurtainOfLight.java new file mode 100644 index 0000000000..5e33e0904d --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/CurtainOfLight.java @@ -0,0 +1,156 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.constants.Rarity; +import mage.constants.TurnPhase; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.AttackingPredicate; +import mage.filter.predicate.permanent.BlockingPredicate; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class CurtainOfLight extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked attacking creature"); + + static { + filter.add(new AttackingPredicate()); + filter.add(Predicates.not(new BlockingPredicate())); + } + + public CurtainOfLight(UUID ownerId) { + super(ownerId, 6, "Curtain of Light", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{W}"); + this.expansionSetCode = "SOK"; + + // Cast Curtain of Light only during combat after blockers are declared. + Ability ability = new SimpleStaticAbility(Zone.ALL, new CurtainOfLightRuleModifyingEffect()); + ability.setRuleAtTheTop(true); + this.addAbility(ability); + + // Target unblocked attacking creature becomes blocked. + this.getSpellAbility().addEffect(new CurtainOfLightEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + public CurtainOfLight(final CurtainOfLight card) { + super(card); + } + + @Override + public CurtainOfLight copy() { + return new CurtainOfLight(this); + } +} + +class CurtainOfLightRuleModifyingEffect extends ContinuousRuleModifiyingEffectImpl { + + CurtainOfLightRuleModifyingEffect() { + super(Duration.EndOfGame, Outcome.Detriment); + staticText = "Cast {this} only during combat after blockers are declared"; + } + + CurtainOfLightRuleModifyingEffect(final CurtainOfLightRuleModifyingEffect effect) { + super(effect); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType().equals(GameEvent.EventType.CAST_SPELL) && event.getSourceId().equals(source.getSourceId())) { + return !game.getPhase().getType().equals(TurnPhase.COMBAT) || + game.getStep().getType().equals(PhaseStep.BEGIN_COMBAT) || + game.getStep().getType().equals(PhaseStep.DECLARE_ATTACKERS); + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public CurtainOfLightRuleModifyingEffect copy() { + return new CurtainOfLightRuleModifyingEffect(this); + } +} + +class CurtainOfLightEffect extends OneShotEffect { + + public CurtainOfLightEffect() { + super(Outcome.Benefit); + this.staticText = "Target unblocked attacking creature becomes blocked"; + } + + public CurtainOfLightEffect(final CurtainOfLightEffect effect) { + super(effect); + } + + @Override + public CurtainOfLightEffect copy() { + return new CurtainOfLightEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (controller != null && permanent != null) { + CombatGroup combatGroup = game.getCombat().findGroup(permanent.getId()); + if (combatGroup != null) { + combatGroup.setBlocked(true); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/ErayoSoratamiAscendant.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/ErayoSoratamiAscendant.java new file mode 100644 index 0000000000..a5bccc1785 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/ErayoSoratamiAscendant.java @@ -0,0 +1,169 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.abilities.effects.common.FlipSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.Token; +import mage.target.targetpointer.FixedTarget; +import mage.watchers.common.CastSpellLastTurnWatcher; + +/** + * + * @author LevelX2 + */ +public class ErayoSoratamiAscendant extends CardImpl { + + public ErayoSoratamiAscendant(UUID ownerId) { + super(ownerId, 35, "Erayo, Soratami Ascendant", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}"); + this.expansionSetCode = "SOK"; + this.supertype.add("Legendary"); + this.subtype.add("Moonfolk"); + this.subtype.add("Monk"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + this.flipCard = true; + this.flipCardName = "Erayo's Essence"; + + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever the fourth spell of a turn is cast, flip Erayo, Soratami Ascendant. + this.addAbility(new ErayoSoratamiAscendantTriggeredAbility()); + + } + + public ErayoSoratamiAscendant(final ErayoSoratamiAscendant card) { + super(card); + } + + @Override + public ErayoSoratamiAscendant copy() { + return new ErayoSoratamiAscendant(this); + } +} + +class ErayoSoratamiAscendantTriggeredAbility extends TriggeredAbilityImpl { + + public ErayoSoratamiAscendantTriggeredAbility() { + super(Zone.BATTLEFIELD, getFlipEffect(), false); + } + + private static Effect getFlipEffect() { + Effect effect = new FlipSourceEffect(new ErayosEssence()); + effect.setText("flip {this}"); + return effect; + } + + public ErayoSoratamiAscendantTriggeredAbility(final ErayoSoratamiAscendantTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.SPELL_CAST) { + CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher"); + if (watcher != null && watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn() == 4) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever the fourth spell of a turn is cast, " + super.getRule(); + } + + @Override + public ErayoSoratamiAscendantTriggeredAbility copy() { + return new ErayoSoratamiAscendantTriggeredAbility(this); + } +} + +class ErayosEssence extends Token { + + ErayosEssence () { + super("Erayo's Essence", ""); + supertype.add("Legendary"); + cardType.add(CardType.ENCHANTMENT); + + color.setBlue(true); + + // Whenever an opponent casts a spell for the first time in a turn, counter that spell. + this.addAbility(new ErayosEssenceTriggeredAbility()); + } +} +class ErayosEssenceTriggeredAbility extends TriggeredAbilityImpl { + + public ErayosEssenceTriggeredAbility() { + super(Zone.BATTLEFIELD, new CounterTargetEffect(), false); + } + + public ErayosEssenceTriggeredAbility(final ErayosEssenceTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.SPELL_CAST) { + if (game.getOpponents(getControllerId()).contains(event.getPlayerId())) { + CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher"); + if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 1) { + for (Effect effect : getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getTargetId())); + } + return true; + } + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever an opponent casts a spell for the first time in a turn, counter that spell."; + } + + @Override + public ErayosEssenceTriggeredAbility copy() { + return new ErayosEssenceTriggeredAbility(this); + } +} diff --git a/Mage/src/mage/game/combat/Combat.java b/Mage/src/mage/game/combat/Combat.java index 94bae0a0ec..79b5afb2aa 100644 --- a/Mage/src/mage/game/combat/Combat.java +++ b/Mage/src/mage/game/combat/Combat.java @@ -923,15 +923,15 @@ public class Combat implements Serializable, Copyable { return null; } - public int totalUnblockedDamage(Game game) { - int total = 0; - for (CombatGroup group : groups) { - if (group.getBlockers().isEmpty()) { - total += group.totalAttackerDamage(game); - } - } - return total; - } +// public int totalUnblockedDamage(Game game) { +// int total = 0; +// for (CombatGroup group : groups) { +// if (group.getBlockers().isEmpty()) { +// total += group.totalAttackerDamage(game); +// } +// } +// return total; +// } public boolean attacksAlone() { return (groups.size() == 1 && groups.get(0).getAttackers().size() == 1); diff --git a/Mage/src/mage/game/combat/CombatGroup.java b/Mage/src/mage/game/combat/CombatGroup.java index 8467189f57..370e5478f5 100644 --- a/Mage/src/mage/game/combat/CombatGroup.java +++ b/Mage/src/mage/game/combat/CombatGroup.java @@ -605,6 +605,15 @@ public class CombatGroup implements Serializable, Copyable { } } + /** + * There are effects, that set an attacker to be blcoked. + * Therefore this setter can be used. + * @param blocked + */ + public void setBlocked(boolean blocked) { + this.blocked = blocked; + } + @Override public CombatGroup copy() { return new CombatGroup(this); diff --git a/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java b/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java index bb2d579a30..a0b6e4cb30 100644 --- a/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java +++ b/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java @@ -96,6 +96,14 @@ public class CastSpellLastTurnWatcher extends Watcher { public Map getAmountOfSpellsCastOnCurrentTurn() { return amountOfSpellsCastOnCurrentTurn; } + + public int getAmountOfSpellsAllPlayersCastOnCurrentTurn() { + int totalAmount = 0; + for(Integer amount: amountOfSpellsCastOnCurrentTurn.values()) { + totalAmount += amount; + } + return totalAmount; + } public int getAmountOfSpellsPlayerCastOnCurrentTurn(UUID playerId) { Integer value = amountOfSpellsCastOnCurrentTurn.get(playerId); From ab4b96a2d82fe87e82e457acaeee8a136e03df87 Mon Sep 17 00:00:00 2001 From: emerald000 Date: Wed, 17 Dec 2014 13:18:24 -0500 Subject: [PATCH 24/36] Added Arcum Dagsson and Avatar of Woe. --- .../src/mage/sets/archenemy/AvatarOfWoe.java | 126 +++++++++++++++++ .../src/mage/sets/coldsnap/ArcumDagsson.java | 133 ++++++++++++++++++ .../src/mage/sets/commander/AvatarOfWoe.java | 52 +++++++ .../src/mage/sets/prophecy/AvatarOfWoe.java | 52 +++++++ .../mage/sets/timeshifted/AvatarOfWoe.java | 54 +++++++ 5 files changed, 417 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/archenemy/AvatarOfWoe.java create mode 100644 Mage.Sets/src/mage/sets/coldsnap/ArcumDagsson.java create mode 100644 Mage.Sets/src/mage/sets/commander/AvatarOfWoe.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/AvatarOfWoe.java create mode 100644 Mage.Sets/src/mage/sets/timeshifted/AvatarOfWoe.java diff --git a/Mage.Sets/src/mage/sets/archenemy/AvatarOfWoe.java b/Mage.Sets/src/mage/sets/archenemy/AvatarOfWoe.java new file mode 100644 index 0000000000..f5863fcf5b --- /dev/null +++ b/Mage.Sets/src/mage/sets/archenemy/AvatarOfWoe.java @@ -0,0 +1,126 @@ +/* + * 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.archenemy; + +import java.util.UUID; +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.abilities.keyword.FearAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.CostModificationType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author emerald000 + */ +public class AvatarOfWoe extends CardImpl { + + public AvatarOfWoe(UUID ownerId) { + super(ownerId, 9, "Avatar of Woe", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{6}{B}{B}"); + this.expansionSetCode = "ARC"; + this.subtype.add("Avatar"); + this.power = new MageInt(6); + this.toughness = new MageInt(5); + + // If there are ten or more creature cards total in all graveyards, Avatar of Woe costs {6} less to cast. + this.addAbility(new SimpleStaticAbility(Zone.STACK, new AvatarOfWoeCostReductionEffect())); + + // Fear + this.addAbility(FearAbility.getInstance()); + + // {tap}: Destroy target creature. It can't be regenerated. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(true), new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public AvatarOfWoe(final AvatarOfWoe card) { + super(card); + } + + @Override + public AvatarOfWoe copy() { + return new AvatarOfWoe(this); + } +} + +class AvatarOfWoeCostReductionEffect extends CostModificationEffectImpl { + + AvatarOfWoeCostReductionEffect() { + super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST); + staticText = "If there are ten or more creature cards total in all graveyards, {this} costs {6} less to cast"; + } + + AvatarOfWoeCostReductionEffect(final AvatarOfWoeCostReductionEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + SpellAbility spellAbility = (SpellAbility) abilityToModify; + Mana mana = spellAbility.getManaCostsToPay().getMana(); + if (mana.getColorless() > 0) { + int newCount = mana.getColorless() - 6; + if (newCount < 0) { + newCount = 0; + } + mana.setColorless(newCount); + spellAbility.getManaCostsToPay().load(mana.toString()); + return true; + } + return false; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + return abilityToModify.getSourceId().equals(source.getSourceId()) + && (abilityToModify instanceof SpellAbility) + && new CardsInAllGraveyardsCount(new FilterCreatureCard()).calculate(game, source, this) >= 10; + } + + @Override + public AvatarOfWoeCostReductionEffect copy() { + return new AvatarOfWoeCostReductionEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/coldsnap/ArcumDagsson.java b/Mage.Sets/src/mage/sets/coldsnap/ArcumDagsson.java new file mode 100644 index 0000000000..599c9f69ce --- /dev/null +++ b/Mage.Sets/src/mage/sets/coldsnap/ArcumDagsson.java @@ -0,0 +1,133 @@ +/* + * 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.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +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.FilterPermanent; +import mage.filter.common.FilterArtifactCard; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author emerald000 + */ +public class ArcumDagsson extends CardImpl { + + private static final FilterPermanent filter = new FilterArtifactPermanent("artifact creature"); + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + } + + public ArcumDagsson(UUID ownerId) { + super(ownerId, 27, "Arcum Dagsson", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{U}"); + this.expansionSetCode = "CSP"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Artificer"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {tap}: Target artifact creature's controller sacrifices it. That player may search his or her library for a noncreature artifact card, put it onto the battlefield, then shuffle his or her library. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ArcumDagssonEffect(), new TapSourceCost()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public ArcumDagsson(final ArcumDagsson card) { + super(card); + } + + @Override + public ArcumDagsson copy() { + return new ArcumDagsson(this); + } +} + +class ArcumDagssonEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterArtifactCard("noncreature artifact card"); + static { + filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + } + + ArcumDagssonEffect() { + super(Outcome.Removal); + this.staticText = "Target artifact creature's controller sacrifices it. That player may search his or her library for a noncreature artifact card, put it onto the battlefield, then shuffle his or her library"; + } + + ArcumDagssonEffect(final ArcumDagssonEffect effect) { + super(effect); + } + + @Override + public ArcumDagssonEffect copy() { + return new ArcumDagssonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent artifactCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (artifactCreature != null) { + Player player = game.getPlayer(artifactCreature.getControllerId()); + if (player != null) { + artifactCreature.sacrifice(source.getSourceId(), game); + if (player.chooseUse(Outcome.PutCardInPlay, "Search your library for a noncreature artifact card?", game)) { + TargetCardInLibrary target = new TargetCardInLibrary(filter); + if (player.searchLibrary(target, game)) { + Card card = game.getCard(target.getFirstTarget()); + if (card != null) { + player.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId()); + } + } + player.shuffleLibrary(game); + } + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/commander/AvatarOfWoe.java b/Mage.Sets/src/mage/sets/commander/AvatarOfWoe.java new file mode 100644 index 0000000000..25784b416a --- /dev/null +++ b/Mage.Sets/src/mage/sets/commander/AvatarOfWoe.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.commander; + +import java.util.UUID; + +/** + * + * @author emerald000 + */ +public class AvatarOfWoe extends mage.sets.archenemy.AvatarOfWoe { + + public AvatarOfWoe(UUID ownerId) { + super(ownerId); + this.cardNumber = 73; + this.expansionSetCode = "CMD"; + } + + public AvatarOfWoe(final AvatarOfWoe card) { + super(card); + } + + @Override + public AvatarOfWoe copy() { + return new AvatarOfWoe(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/AvatarOfWoe.java b/Mage.Sets/src/mage/sets/prophecy/AvatarOfWoe.java new file mode 100644 index 0000000000..fb28b39ded --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/AvatarOfWoe.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.prophecy; + +import java.util.UUID; + +/** + * + * @author emerald000 + */ +public class AvatarOfWoe extends mage.sets.archenemy.AvatarOfWoe { + + public AvatarOfWoe(UUID ownerId) { + super(ownerId); + this.cardNumber = 56; + this.expansionSetCode = "PCY"; + } + + public AvatarOfWoe(final AvatarOfWoe card) { + super(card); + } + + @Override + public AvatarOfWoe copy() { + return new AvatarOfWoe(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timeshifted/AvatarOfWoe.java b/Mage.Sets/src/mage/sets/timeshifted/AvatarOfWoe.java new file mode 100644 index 0000000000..89562bccca --- /dev/null +++ b/Mage.Sets/src/mage/sets/timeshifted/AvatarOfWoe.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.timeshifted; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author emerald000 + */ +public class AvatarOfWoe extends mage.sets.archenemy.AvatarOfWoe { + + public AvatarOfWoe(UUID ownerId) { + super(ownerId); + this.cardNumber = 37; + this.expansionSetCode = "TSB"; + this.rarity = Rarity.SPECIAL; + } + + public AvatarOfWoe(final AvatarOfWoe card) { + super(card); + } + + @Override + public AvatarOfWoe copy() { + return new AvatarOfWoe(this); + } +} From 5e864a377621b26b4e3c650548e8138b17d0de2e Mon Sep 17 00:00:00 2001 From: kholdfuzion Date: Wed, 17 Dec 2014 13:57:35 -0600 Subject: [PATCH 25/36] Add Hand of Death Fix Rally the Horde --- .../src/mage/sets/portal/HandOfDeath.java | 52 ++++++++++++++ .../sets/portalsecondage/HandOfDeath.java | 52 ++++++++++++++ .../mage/sets/starter1999/HandOfDeath.java | 52 ++++++++++++++ .../mage/sets/starter2000/HandOfDeath.java | 72 +++++++++++++++++++ 4 files changed, 228 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/portal/HandOfDeath.java create mode 100644 Mage.Sets/src/mage/sets/portalsecondage/HandOfDeath.java create mode 100644 Mage.Sets/src/mage/sets/starter1999/HandOfDeath.java create mode 100644 Mage.Sets/src/mage/sets/starter2000/HandOfDeath.java diff --git a/Mage.Sets/src/mage/sets/portal/HandOfDeath.java b/Mage.Sets/src/mage/sets/portal/HandOfDeath.java new file mode 100644 index 0000000000..65f858f7b1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portal/HandOfDeath.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.portal; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class HandOfDeath extends mage.sets.starter2000.HandOfDeath { + + public HandOfDeath(UUID ownerId) { + super(ownerId); + this.cardNumber = 14; + this.expansionSetCode = "POR"; + } + + public HandOfDeath(final HandOfDeath card) { + super(card); + } + + @Override + public HandOfDeath copy() { + return new HandOfDeath(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalsecondage/HandOfDeath.java b/Mage.Sets/src/mage/sets/portalsecondage/HandOfDeath.java new file mode 100644 index 0000000000..bcfaebb4ef --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalsecondage/HandOfDeath.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.portalsecondage; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class HandOfDeath extends mage.sets.starter2000.HandOfDeath { + + public HandOfDeath(UUID ownerId) { + super(ownerId); + this.cardNumber = 14; + this.expansionSetCode = "PO2"; + } + + public HandOfDeath(final HandOfDeath card) { + super(card); + } + + @Override + public HandOfDeath copy() { + return new HandOfDeath(this); + } +} diff --git a/Mage.Sets/src/mage/sets/starter1999/HandOfDeath.java b/Mage.Sets/src/mage/sets/starter1999/HandOfDeath.java new file mode 100644 index 0000000000..afb5cb20ff --- /dev/null +++ b/Mage.Sets/src/mage/sets/starter1999/HandOfDeath.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.starter1999; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class HandOfDeath extends mage.sets.starter2000.HandOfDeath { + + public HandOfDeath(UUID ownerId) { + super(ownerId); + this.cardNumber = 80; + this.expansionSetCode = "S99"; + } + + public HandOfDeath(final HandOfDeath card) { + super(card); + } + + @Override + public HandOfDeath copy() { + return new HandOfDeath(this); + } +} diff --git a/Mage.Sets/src/mage/sets/starter2000/HandOfDeath.java b/Mage.Sets/src/mage/sets/starter2000/HandOfDeath.java new file mode 100644 index 0000000000..6ae00588dc --- /dev/null +++ b/Mage.Sets/src/mage/sets/starter2000/HandOfDeath.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.starter2000; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author anonymous + */ +public class HandOfDeath extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonblack creature"); + + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); + } + + public HandOfDeath(UUID ownerId) { + super(ownerId, 6, "Hand of Death", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{B}"); + this.expansionSetCode = "S00"; + + this.color.setBlack(true); + + // Destroy target nonblack creature. + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + } + + public HandOfDeath(final HandOfDeath card) { + super(card); + } + + @Override + public HandOfDeath copy() { + return new HandOfDeath(this); + } +} From 9ac1076ad70f86968ce1e1c7891e232a9b2e3bff Mon Sep 17 00:00:00 2001 From: kholdfuzion Date: Wed, 17 Dec 2014 14:12:20 -0600 Subject: [PATCH 26/36] Add Waves of Aggression --- .../mage/sets/eventide/WavesOfAggression.java | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/eventide/WavesOfAggression.java diff --git a/Mage.Sets/src/mage/sets/eventide/WavesOfAggression.java b/Mage.Sets/src/mage/sets/eventide/WavesOfAggression.java new file mode 100644 index 0000000000..d146ecd8b2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eventide/WavesOfAggression.java @@ -0,0 +1,191 @@ +/* + * 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.eventide; + +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.RetraceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TimingRule; +import mage.constants.TurnPhase; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.turn.TurnMod; +import mage.watchers.Watcher; +import mage.watchers.common.AttackedThisTurnWatcher; + +/** + * + * @author anonymous + */ +public class WavesOfAggression extends CardImpl { + + public WavesOfAggression(UUID ownerId) { + super(ownerId, 148, "Waves of Aggression", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{R/W}{R/W}"); + this.expansionSetCode = "EVE"; + + this.color.setRed(true); + this.color.setWhite(true); + + // Untap all creatures that attacked this turn. After this main phase, there is an additional combat phase followed by an additional main phase. + this.addWatcher(new AttackedThisTurnWatcher()); + this.getSpellAbility().addEffect(new WavesOfAggressionUntapEffect()); + this.getSpellAbility().addEffect(new WavesOfAggressionAddPhasesEffect()); + // Retrace + this.addAbility(new RetraceAbility(new ManaCostsImpl("{3}{R/W}{R/W}"), TimingRule.SORCERY)); + } + + public WavesOfAggression(final WavesOfAggression card) { + super(card); + } + + @Override + public WavesOfAggression copy() { + return new WavesOfAggression(this); + } +} + +class WavesOfAggressionUntapEffect extends OneShotEffect { + + public WavesOfAggressionUntapEffect() { + super(Outcome.Benefit); + staticText = "Untap all creatures that attacked this turn"; + } + + public WavesOfAggressionUntapEffect(final WavesOfAggressionUntapEffect effect) { + super(effect); + } + + @Override + public WavesOfAggressionUntapEffect copy() { + return new WavesOfAggressionUntapEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Watcher watcher = game.getState().getWatchers().get("AttackedThisTurn"); + if (watcher != null && watcher instanceof AttackedThisTurnWatcher) { + Set attackedThisTurn = ((AttackedThisTurnWatcher) watcher).getAttackedThisTurnCreatures(); + for (UUID uuid : attackedThisTurn) { + Permanent permanent = game.getPermanent(uuid); + if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) { + permanent.untap(game); + } + } + return true; + } + return false; + } +} + +class WavesOfAggressionAddPhasesEffect extends OneShotEffect { + + public WavesOfAggressionAddPhasesEffect() { + super(Outcome.Benefit); + staticText = "After this main phase, there is an additional combat phase followed by an additional main phase"; + } + + public WavesOfAggressionAddPhasesEffect(final WavesOfAggressionAddPhasesEffect effect) { + super(effect); + } + + @Override + public WavesOfAggressionAddPhasesEffect copy() { + return new WavesOfAggressionAddPhasesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + // 15.07.2006 If it's somehow not a main phase when Fury of the Horde resolves, all it does is untap all creatures that attacked that turn. No new phases are created. + if (TurnPhase.PRECOMBAT_MAIN.equals(game.getTurn().getPhaseType()) || TurnPhase.POSTCOMBAT_MAIN.equals(game.getTurn().getPhaseType())) { + // we can't add two turn modes at once, will add additional post combat on delayed trigger resolution + TurnMod combat = new TurnMod(source.getControllerId(), TurnPhase.COMBAT, TurnPhase.POSTCOMBAT_MAIN, false); + game.getState().getTurnMods().add(combat); + WavesOfAggressionDelayedAddMainPhaseAbility delayedTriggeredAbility = new WavesOfAggressionDelayedAddMainPhaseAbility(); + delayedTriggeredAbility.setSourceId(source.getSourceId()); + delayedTriggeredAbility.setControllerId(source.getControllerId()); + delayedTriggeredAbility.setConnectedTurnMod(combat.getId()); + game.addDelayedTriggeredAbility(delayedTriggeredAbility); + return true; + } + return false; + } +} + +class WavesOfAggressionDelayedAddMainPhaseAbility extends DelayedTriggeredAbility { + + private UUID connectedTurnMod; + private boolean enabled; + + public WavesOfAggressionDelayedAddMainPhaseAbility() { + super(null, Duration.EndOfTurn); + this.usesStack = false; // don't show this to the user + } + + public WavesOfAggressionDelayedAddMainPhaseAbility(WavesOfAggressionDelayedAddMainPhaseAbility ability) { + super(ability); + this.connectedTurnMod = ability.connectedTurnMod; + this.enabled = ability.enabled; + } + + @Override + public WavesOfAggressionDelayedAddMainPhaseAbility copy() { + return new WavesOfAggressionDelayedAddMainPhaseAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.PHASE_CHANGED && this.connectedTurnMod.equals(event.getSourceId())) { + enabled = true; + } + if (event.getType() == GameEvent.EventType.COMBAT_PHASE_PRE && enabled) { + // add additional post combat main phase after that - after phase == null because add it after this combat + game.getState().getTurnMods().add(new TurnMod(getControllerId(), TurnPhase.POSTCOMBAT_MAIN, null, false)); + enabled = false; + } + return false; + } + + public void setConnectedTurnMod(UUID connectedTurnMod) { + this.connectedTurnMod = connectedTurnMod; + } + + @Override + public String getRule() { + return "add additional post combat main phase"; + } +} From a3db429525328303f377b66cdeb53d1ad10fd652 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 17 Dec 2014 21:32:18 +0100 Subject: [PATCH 27/36] * Fixed mana effect, that added addional mana to the effect controller instead of the controller of the mana source (Dictate of Karametra, Keeper of Progenitus, Heartbeat of Spring, Zur-Taa Ancient). --- .../AddManaOfAnyColorTargetCanProduceEffect.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorTargetCanProduceEffect.java b/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorTargetCanProduceEffect.java index 36a5c4e82b..32c2dd833a 100644 --- a/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorTargetCanProduceEffect.java +++ b/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorTargetCanProduceEffect.java @@ -57,9 +57,12 @@ public class AddManaOfAnyColorTargetCanProduceEffect extends ManaEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(this.targetPointer.getFirst(game, source)); - if (controller != null && permanent != null) { + if (permanent != null) { + Player targetController = game.getPlayer(permanent.getControllerId()); + if (targetController == null) { + return false; + } Abilities mana = permanent.getAbilities().getManaAbilities(Zone.BATTLEFIELD); Mana types = new Mana(); for (ManaAbility ability : mana) { @@ -91,7 +94,7 @@ public class AddManaOfAnyColorTargetCanProduceEffect extends ManaEffect { if (choice.getChoices().size() == 1) { choice.setChoice(choice.getChoices().iterator().next()); } else { - controller.choose(outcome, choice, game); + targetController.choose(outcome, choice, game); } if (choice.getChoice() == null) { return false; @@ -117,7 +120,7 @@ public class AddManaOfAnyColorTargetCanProduceEffect extends ManaEffect { newMana.setColorless(1); break; } - controller.getManaPool().addMana(newMana, game, source); + targetController.getManaPool().addMana(newMana, game, source); checkToFirePossibleEvents(newMana, game, source); } return true; From 2cea085420d68f7587186dd0e1732c9a80eae0c5 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 18 Dec 2014 00:36:46 +0100 Subject: [PATCH 28/36] [SOK] Added 5 blue cards. --- .../betrayersofkamigawa/HeedTheMists.java | 52 +++---- .../ChargeAcrossTheAraba.java | 4 +- .../sets/saviorsofkamigawa/OboroEnvoy.java | 84 +++++++++++ .../saviorsofkamigawa/OppressiveWill.java | 112 +++++++++++++++ .../SakashimaTheImpostor.java | 135 ++++++++++++++++++ .../saviorsofkamigawa/ShiftingBorders.java | 66 +++++++++ .../SoramaroFirstToDream.java | 86 +++++++++++ .../dynamicvalue/common/SweepNumber.java | 8 +- .../common/LookLibraryControllerEffect.java | 3 + .../effects/keyword/SweepEffect.java | 6 +- 10 files changed, 521 insertions(+), 35 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/OboroEnvoy.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/OppressiveWill.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/SakashimaTheImpostor.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/ShiftingBorders.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/SoramaroFirstToDream.java diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/HeedTheMists.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/HeedTheMists.java index e39f8f5c0f..b9884dbfe0 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/HeedTheMists.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/HeedTheMists.java @@ -50,7 +50,7 @@ public class HeedTheMists extends CardImpl { super(ownerId, 36, "Heed the Mists", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{U}{U}"); this.expansionSetCode = "BOK"; this.subtype.add("Arcane"); - + this.color.setBlue(true); // Put the top card of your library into your graveyard, then draw cards equal to that card's converted mana cost. @@ -65,36 +65,36 @@ public class HeedTheMists extends CardImpl { public HeedTheMists copy() { return new HeedTheMists(this); } - + private class HeedTheMistsEffect extends OneShotEffect { - public HeedTheMistsEffect() { - super(Outcome.DrawCard); - staticText = "Put the top card of your library into your graveyard, then draw cards equal to that card's converted mana cost"; - } + public HeedTheMistsEffect() { + super(Outcome.DrawCard); + staticText = "Put the top card of your library into your graveyard, then draw cards equal to that card's converted mana cost"; + } - public HeedTheMistsEffect(HeedTheMistsEffect effect) { - super(effect); - } + public HeedTheMistsEffect(HeedTheMistsEffect effect) { + super(effect); + } - @Override - public boolean apply(Game game, Ability source) { - boolean result = false; - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - Card card = player.getLibrary().removeFromTop(game); - if (card != null) { - int cmc = card.getManaCost().convertedManaCost(); - result = card.moveToZone(Zone.GRAVEYARD, source.getSourceId(), game, true); - player.drawCards(cmc, game); - } - } - return result; + @Override + public boolean apply(Game game, Ability source) { + boolean result = false; + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Card card = controller.getLibrary().removeFromTop(game); + if (card != null) { + int cmc = card.getManaCost().convertedManaCost(); + controller.moveCardToGraveyardWithInfo(card, source.getSourceId(), game, Zone.LIBRARY); + controller.drawCards(cmc, game); + } } + return result; + } - @Override - public HeedTheMistsEffect copy() { - return new HeedTheMistsEffect(this); - } + @Override + public HeedTheMistsEffect copy() { + return new HeedTheMistsEffect(this); + } } } diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/ChargeAcrossTheAraba.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/ChargeAcrossTheAraba.java index 3eabd4590e..c5e9c0c6d1 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/ChargeAcrossTheAraba.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/ChargeAcrossTheAraba.java @@ -1,4 +1,4 @@ -/* + /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -30,8 +30,8 @@ package mage.sets.saviorsofkamigawa; import java.util.UUID; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.SweepNumber; -import mage.abilities.effects.keyword.SweepEffect; import mage.abilities.effects.common.continious.BoostControlledEffect; +import mage.abilities.effects.keyword.SweepEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/OboroEnvoy.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/OboroEnvoy.java new file mode 100644 index 0000000000..5000c71c9c --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/OboroEnvoy.java @@ -0,0 +1,84 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.ReturnToHandTargetCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.common.CardsInControllerHandCount; +import mage.abilities.dynamicvalue.common.SignInversionDynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continious.BoostTargetEffect; +import mage.abilities.keyword.FlyingAbility; +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.target.common.TargetControlledPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class OboroEnvoy extends CardImpl { + + public OboroEnvoy(UUID ownerId) { + super(ownerId, 49, "Oboro Envoy", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{U}"); + this.expansionSetCode = "SOK"; + this.subtype.add("Moonfolk"); + this.subtype.add("Wizard"); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // {2}, Return a land you control to its owner's hand: Target creature gets -X/-0 until end of turn, where X is the number of cards in your hand. + Effect effect = new BoostTargetEffect(new SignInversionDynamicValue(new CardsInControllerHandCount()), new StaticValue(-0), Duration.EndOfTurn); + effect.setText("Target creature gets -X/-0 until end of turn, where X is the number of cards in your hand"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(2)); + ability.addCost(new ReturnToHandTargetCost(new TargetControlledPermanent(new FilterControlledLandPermanent("a land")))); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public OboroEnvoy(final OboroEnvoy card) { + super(card); + } + + @Override + public OboroEnvoy copy() { + return new OboroEnvoy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/OppressiveWill.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/OppressiveWill.java new file mode 100644 index 0000000000..35a812dd6a --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/OppressiveWill.java @@ -0,0 +1,112 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.stack.StackObject; +import mage.players.Player; +import mage.target.TargetSpell; + +/** + * + * @author LevelX2 + */ +public class OppressiveWill extends CardImpl { + + public OppressiveWill(UUID ownerId) { + super(ownerId, 50, "Oppressive Will", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{U}"); + this.expansionSetCode = "SOK"; + + // Counter target spell unless its controller pays {1} for each card in your hand. + this.getSpellAbility().addEffect(new SpellSyphonEffect()); + this.getSpellAbility().addTarget(new TargetSpell()); + } + + public OppressiveWill(final OppressiveWill card) { + super(card); + } + + @Override + public OppressiveWill copy() { + return new OppressiveWill(this); + } +} + +class SpellSyphonEffect extends OneShotEffect { + + public SpellSyphonEffect() { + super(Outcome.Benefit); + } + + public SpellSyphonEffect(final SpellSyphonEffect effect) { + super(effect); + } + + @Override + public SpellSyphonEffect copy() { + return new SpellSyphonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + StackObject spell = game.getStack().getStackObject(targetPointer.getFirst(game, source)); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (sourceObject != null && spell != null) { + Player player = game.getPlayer(spell.getControllerId()); + Player controller = game.getPlayer(source.getControllerId()); + if (player != null && controller != null) { + int amount = controller.getHand().size(); + if (amount > 0) { + GenericManaCost cost = new GenericManaCost(amount); + if (!cost.pay(source, game, spell.getControllerId(), spell.getControllerId(), false)) { + game.informPlayers(sourceObject.getLogName() + ": cost wasn't payed - countering target spell."); + return game.getStack().counter(source.getFirstTarget(), source.getSourceId(), game); + } + } + return true; + } + } + return false; + } + + @Override + public String getText(Mode mode) { + return "Counter target spell unless its controller pays {1} for each card in your hand"; + } + +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/SakashimaTheImpostor.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/SakashimaTheImpostor.java new file mode 100644 index 0000000000..5e769b0a00 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/SakashimaTheImpostor.java @@ -0,0 +1,135 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.util.functions.ApplyToPermanent; + +/** + * + * @author LevelX2 + */ +public class SakashimaTheImpostor extends CardImpl { + + private static final String abilityText = "You may have {this} enter the battlefield as a copy of any creature on the battlefield, except its name is still Sakashima the Impostor, it's legendary in addition to its other types, and it gains \"{2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step.\""; + + public SakashimaTheImpostor(UUID ownerId) { + super(ownerId, 53, "Sakashima the Impostor", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); + this.expansionSetCode = "SOK"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Rogue"); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // You may have Sakashima the Impostor enter the battlefield as a copy of any creature on the battlefield, except its name is still Sakashima the Impostor, it's legendary in addition to its other types, and it gains "{2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step." + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new EntersBattlefieldEffect( + new SakashimaTheImpostorCopyEffect(), abilityText, true)); + this.addAbility(ability); + } + + public SakashimaTheImpostor(final SakashimaTheImpostor card) { + super(card); + } + + @Override + public SakashimaTheImpostor copy() { + return new SakashimaTheImpostor(this); + } +} + +class SakashimaTheImpostorCopyEffect extends OneShotEffect { + + public SakashimaTheImpostorCopyEffect() { + super(Outcome.Copy); + } + + public SakashimaTheImpostorCopyEffect(final SakashimaTheImpostorCopyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (player != null && sourcePermanent != null) { + Target target = new TargetPermanent(new FilterCreaturePermanent()); + target.setNotTarget(true); + if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) { + player.choose(Outcome.Copy, target, source.getSourceId(), game); + Permanent copyFromPermanent = game.getPermanent(target.getFirstTarget()); + if (copyFromPermanent != null) { + game.copyPermanent(copyFromPermanent, sourcePermanent, source, new ApplyToPermanent() { + @Override + public Boolean apply(Game game, Permanent permanent) { + if (!permanent.getSupertype().contains("Legendary")) { + permanent.getSubtype().add("Legendary"); + } + permanent.setName("Sakashima the Impostor"); + // {2}{U}{U}: Return Sakashima the Impostor to its owner's hand at the beginning of the next end step + permanent.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, + new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnToHandSourceEffect(true)), false), + new ManaCostsImpl("{2}{U}{U}") + ), game); + return true; + } + }); + + return true; + } + } + } + return false; + } + + @Override + public SakashimaTheImpostorCopyEffect copy() { + return new SakashimaTheImpostorCopyEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/ShiftingBorders.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/ShiftingBorders.java new file mode 100644 index 0000000000..056882c4b2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/ShiftingBorders.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.saviorsofkamigawa; + +import java.util.UUID; +import mage.abilities.effects.common.continious.ExchangeControlTargetEffect; +import mage.abilities.keyword.SpliceOntoArcaneAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author LevelX2 + */ +public class ShiftingBorders extends CardImpl { + + public ShiftingBorders(UUID ownerId) { + super(ownerId, 56, "Shifting Borders", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{3}{U}"); + this.expansionSetCode = "SOK"; + this.subtype.add("Arcane"); + + // Exchange control of two target lands. + this.getSpellAbility().addEffect(new ExchangeControlTargetEffect(Duration.EndOfGame, "Exchange control of two target lands")); + this.getSpellAbility().addTarget(new TargetLandPermanent(2)); + + // Splice onto Arcane {3}{U} + this.addAbility(new SpliceOntoArcaneAbility("{3}{U}")); + } + + public ShiftingBorders(final ShiftingBorders card) { + super(card); + } + + @Override + public ShiftingBorders copy() { + return new ShiftingBorders(this); + } +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/SoramaroFirstToDream.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/SoramaroFirstToDream.java new file mode 100644 index 0000000000..f2fa8c08c1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/SoramaroFirstToDream.java @@ -0,0 +1,86 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.ReturnToHandTargetCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CardsInControllerHandCount; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continious.SetPowerToughnessSourceEffect; +import mage.abilities.keyword.FlyingAbility; +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.target.common.TargetControlledPermanent; + +/** + * + * @author LevelX2 + */ +public class SoramaroFirstToDream extends CardImpl { + + public SoramaroFirstToDream(UUID ownerId) { + super(ownerId, 58, "Soramaro, First to Dream", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{U}{U}"); + this.expansionSetCode = "SOK"; + this.supertype.add("Legendary"); + this.subtype.add("Spirit"); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Soramaro, First to Dream's power and toughness are each equal to the number of cards in your hand. + DynamicValue xValue= new CardsInControllerHandCount(); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(xValue, Duration.EndOfGame))); + + // {4}, Return a land you control to its owner's hand: Draw a card. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new ReturnToHandTargetCost(new TargetControlledPermanent(new FilterControlledLandPermanent("a land")))); + this.addAbility(ability); + + } + + public SoramaroFirstToDream(final SoramaroFirstToDream card) { + super(card); + } + + @Override + public SoramaroFirstToDream copy() { + return new SoramaroFirstToDream(this); + } +} diff --git a/Mage/src/mage/abilities/dynamicvalue/common/SweepNumber.java b/Mage/src/mage/abilities/dynamicvalue/common/SweepNumber.java index 27ffa7d6e4..2f47aeab8d 100644 --- a/Mage/src/mage/abilities/dynamicvalue/common/SweepNumber.java +++ b/Mage/src/mage/abilities/dynamicvalue/common/SweepNumber.java @@ -40,8 +40,8 @@ import mage.game.Game; public class SweepNumber implements DynamicValue { private int zoneChangeCounter = 0; - private String sweepSubtype; - private boolean previousZone; + private final String sweepSubtype; + private final boolean previousZone; public SweepNumber(String sweepSubtype, boolean previousZone) { this.sweepSubtype = sweepSubtype; @@ -62,7 +62,7 @@ public class SweepNumber implements DynamicValue { int number = 0; Integer sweepNumber = (Integer) game.getState().getValue(new StringBuilder("sweep").append(source.getSourceId()).append(zoneChangeCounter).toString()); if (sweepNumber != null) { - number = sweepNumber.intValue(); + number = sweepNumber; } return number; } @@ -79,6 +79,6 @@ public class SweepNumber implements DynamicValue { @Override public String getMessage() { - return new StringBuilder("the number of ").append(sweepSubtype).append("s returned this way").toString(); + return new StringBuilder("the number of ").append(sweepSubtype).append(sweepSubtype.endsWith("s") ? "":"s").append(" returned this way").toString(); } } diff --git a/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java b/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java index 87529bf822..fe2fa546ef 100644 --- a/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java +++ b/Mage/src/mage/abilities/effects/common/LookLibraryControllerEffect.java @@ -221,6 +221,9 @@ public class LookLibraryControllerEffect extends OneShotEffect { } public String setText(Mode mode, String middleText) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } int numberLook; try { numberLook = Integer.parseInt(numberOfCards.toString()); diff --git a/Mage/src/mage/abilities/effects/keyword/SweepEffect.java b/Mage/src/mage/abilities/effects/keyword/SweepEffect.java index 610facfb70..01b1069355 100644 --- a/Mage/src/mage/abilities/effects/keyword/SweepEffect.java +++ b/Mage/src/mage/abilities/effects/keyword/SweepEffect.java @@ -48,12 +48,12 @@ import mage.util.CardUtil; */ public class SweepEffect extends OneShotEffect { - private String sweepSubtype; + private final String sweepSubtype; public SweepEffect(String sweepSubtype) { super(Outcome.Benefit); this.sweepSubtype = sweepSubtype; - this.staticText = new StringBuilder("Sweep - Return any number of ").append(sweepSubtype).append(sweepSubtype.endsWith("s")?"":"s").append(" you control to their owner's hand").toString(); + this.staticText = "Sweep - Return any number of "+ sweepSubtype + (sweepSubtype.endsWith("s") ? "":"s") + " you control to their owner's hand"; } public SweepEffect(final SweepEffect effect) { @@ -77,7 +77,7 @@ public class SweepEffect extends OneShotEffect { game.getState().setValue(CardUtil.getCardZoneString("sweep", source.getSourceId(), game), target.getTargets().size()); for (UUID uuid : target.getTargets()) { Permanent land = game.getPermanent(uuid); - land.moveToZone(Zone.HAND, source.getSourceId(), game, false); + controller.moveCardToHandWithInfo(land, source.getSourceId(), game, Zone.HAND); } } return true; From 79e3ef2cf63b7b22345f75a071ba7d3c5a907f29 Mon Sep 17 00:00:00 2001 From: kholdfuzion Date: Wed, 17 Dec 2014 14:29:31 -0600 Subject: [PATCH 29/36] Add Twiddle --- .../src/mage/sets/eighthedition/Twiddle.java | 52 ++++++++++++++ .../src/mage/sets/fifthedition/Twiddle.java | 52 ++++++++++++++ .../src/mage/sets/fourthedition/Twiddle.java | 52 ++++++++++++++ .../src/mage/sets/limitedalpha/Twiddle.java | 52 ++++++++++++++ .../src/mage/sets/limitedbeta/Twiddle.java | 52 ++++++++++++++ .../src/mage/sets/seventhedition/Twiddle.java | 52 ++++++++++++++ .../mage/sets/unlimitededition/Twiddle.java | 72 +++++++++++++++++++ 7 files changed, 384 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/eighthedition/Twiddle.java create mode 100644 Mage.Sets/src/mage/sets/fifthedition/Twiddle.java create mode 100644 Mage.Sets/src/mage/sets/fourthedition/Twiddle.java create mode 100644 Mage.Sets/src/mage/sets/limitedalpha/Twiddle.java create mode 100644 Mage.Sets/src/mage/sets/limitedbeta/Twiddle.java create mode 100644 Mage.Sets/src/mage/sets/seventhedition/Twiddle.java create mode 100644 Mage.Sets/src/mage/sets/unlimitededition/Twiddle.java diff --git a/Mage.Sets/src/mage/sets/eighthedition/Twiddle.java b/Mage.Sets/src/mage/sets/eighthedition/Twiddle.java new file mode 100644 index 0000000000..9dbab90865 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eighthedition/Twiddle.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.eighthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Twiddle extends mage.sets.unlimitededition.Twiddle { + + public Twiddle(UUID ownerId) { + super(ownerId); + this.cardNumber = 111; + this.expansionSetCode = "8ED"; + } + + public Twiddle(final Twiddle card) { + super(card); + } + + @Override + public Twiddle copy() { + return new Twiddle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/Twiddle.java b/Mage.Sets/src/mage/sets/fifthedition/Twiddle.java new file mode 100644 index 0000000000..ba8c6e7ff0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/Twiddle.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.fifthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Twiddle extends mage.sets.unlimitededition.Twiddle { + + public Twiddle(UUID ownerId) { + super(ownerId); + this.cardNumber = 130; + this.expansionSetCode = "5ED"; + } + + public Twiddle(final Twiddle card) { + super(card); + } + + @Override + public Twiddle copy() { + return new Twiddle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fourthedition/Twiddle.java b/Mage.Sets/src/mage/sets/fourthedition/Twiddle.java new file mode 100644 index 0000000000..3d0ed49f75 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fourthedition/Twiddle.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fourthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Twiddle extends mage.sets.unlimitededition.Twiddle { + + public Twiddle(UUID ownerId) { + super(ownerId); + this.cardNumber = 109; + this.expansionSetCode = "4ED"; + } + + public Twiddle(final Twiddle card) { + super(card); + } + + @Override + public Twiddle copy() { + return new Twiddle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedalpha/Twiddle.java b/Mage.Sets/src/mage/sets/limitedalpha/Twiddle.java new file mode 100644 index 0000000000..dd587c133b --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedalpha/Twiddle.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.limitedalpha; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Twiddle extends mage.sets.unlimitededition.Twiddle { + + public Twiddle(UUID ownerId) { + super(ownerId); + this.cardNumber = 86; + this.expansionSetCode = "LEA"; + } + + public Twiddle(final Twiddle card) { + super(card); + } + + @Override + public Twiddle copy() { + return new Twiddle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedbeta/Twiddle.java b/Mage.Sets/src/mage/sets/limitedbeta/Twiddle.java new file mode 100644 index 0000000000..afeffdf147 --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedbeta/Twiddle.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.limitedbeta; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Twiddle extends mage.sets.unlimitededition.Twiddle { + + public Twiddle(UUID ownerId) { + super(ownerId); + this.cardNumber = 86; + this.expansionSetCode = "LEB"; + } + + public Twiddle(final Twiddle card) { + super(card); + } + + @Override + public Twiddle copy() { + return new Twiddle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/seventhedition/Twiddle.java b/Mage.Sets/src/mage/sets/seventhedition/Twiddle.java new file mode 100644 index 0000000000..bb294bff81 --- /dev/null +++ b/Mage.Sets/src/mage/sets/seventhedition/Twiddle.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.seventhedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Twiddle extends mage.sets.unlimitededition.Twiddle { + + public Twiddle(UUID ownerId) { + super(ownerId); + this.cardNumber = 107; + this.expansionSetCode = "7ED"; + } + + public Twiddle(final Twiddle card) { + super(card); + } + + @Override + public Twiddle copy() { + return new Twiddle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/unlimitededition/Twiddle.java b/Mage.Sets/src/mage/sets/unlimitededition/Twiddle.java new file mode 100644 index 0000000000..46c8de4c78 --- /dev/null +++ b/Mage.Sets/src/mage/sets/unlimitededition/Twiddle.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.unlimitededition; + +import java.util.UUID; +import mage.abilities.effects.common.MayTapOrUntapTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetPermanent; + +/** + * + * @author anonymous + */ +public class Twiddle extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("artifact, creature, or land"); + + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.LAND))); + } + + public Twiddle(UUID ownerId) { + super(ownerId, 86, "Twiddle", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{U}"); + this.expansionSetCode = "2ED"; + + // You may tap or untap target artifact, creature, or land. + this.getSpellAbility().addEffect(new MayTapOrUntapTargetEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + } + + public Twiddle(final Twiddle card) { + super(card); + } + + @Override + public Twiddle copy() { + return new Twiddle(this); + } +} From 2e89eef39bf34c0844215de8bf3a057ad202b63b Mon Sep 17 00:00:00 2001 From: kholdfuzion Date: Wed, 17 Dec 2014 20:24:50 -0600 Subject: [PATCH 30/36] Add Storm Front --- .../src/mage/sets/tempest/StormFront.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/tempest/StormFront.java diff --git a/Mage.Sets/src/mage/sets/tempest/StormFront.java b/Mage.Sets/src/mage/sets/tempest/StormFront.java new file mode 100644 index 0000000000..641b11bf16 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tempest/StormFront.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.tempest; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author KholdFuzion + */ +public class StormFront extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with flying"); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public StormFront(UUID ownerId) { + super(ownerId, 153, "Storm Front", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{G}"); + this.expansionSetCode = "TMP"; + + // {G}{G}: Tap target creature with flying. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new ManaCostsImpl("{G}{G}")); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public StormFront(final StormFront card) { + super(card); + } + + @Override + public StormFront copy() { + return new StormFront(this); + } +} From 4373a33b73dd223cc2455c32d2dc74de2a74eb7a Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 18 Dec 2014 08:39:35 +0100 Subject: [PATCH 31/36] * Holiday Cube 2014 - Fixed year in name, added missing card. --- .../tournament/cubes/HolidayCube2014.java | 1135 +++++++++-------- 1 file changed, 568 insertions(+), 567 deletions(-) diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/cubes/HolidayCube2014.java b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/cubes/HolidayCube2014.java index daf924ab1c..a42fabab15 100644 --- a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/cubes/HolidayCube2014.java +++ b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/cubes/HolidayCube2014.java @@ -1,30 +1,30 @@ /* -* 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. -*/ + * 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.tournament.cubes; import mage.game.draft.DraftCube; @@ -34,548 +34,549 @@ import mage.game.draft.DraftCube; * @author fireshoes */ public class HolidayCube2014 extends DraftCube { - - public HolidayCube2014() { - super("MTGO Holiday Cube 2013"); - cubeCards.add(new CardIdentity("Accorder Paladin","")); - cubeCards.add(new CardIdentity("Banisher Priest","")); - cubeCards.add(new CardIdentity("Brimaz, King of Oreskos","")); - cubeCards.add(new CardIdentity("Council's Judgment","")); - cubeCards.add(new CardIdentity("Imposing Sovereign","")); - cubeCards.add(new CardIdentity("Leonin Arbiter","")); - cubeCards.add(new CardIdentity("Aven Mindcensor","")); - cubeCards.add(new CardIdentity("Banishing Light","")); - cubeCards.add(new CardIdentity("Containment Priest","")); - cubeCards.add(new CardIdentity("Hallowed Spiritkeeper","")); - cubeCards.add(new CardIdentity("Iona, Shield of Emeria","")); - cubeCards.add(new CardIdentity("Spirit of the Labyrinth","")); - cubeCards.add(new CardIdentity("Honor of the Pure","")); - cubeCards.add(new CardIdentity("Path to Exile","")); - cubeCards.add(new CardIdentity("Land Tax","")); - cubeCards.add(new CardIdentity("Exalted Angel","")); - cubeCards.add(new CardIdentity("Mana Tithe","")); - cubeCards.add(new CardIdentity("Spectral Procession","")); - cubeCards.add(new CardIdentity("Wall of Omens","")); - cubeCards.add(new CardIdentity("Sun Titan","")); - cubeCards.add(new CardIdentity("Leonin Relic-Warder","")); - cubeCards.add(new CardIdentity("Elesh Norn, Grand Cenobite","")); - cubeCards.add(new CardIdentity("Lingering Souls","")); - cubeCards.add(new CardIdentity("Terminus","")); - cubeCards.add(new CardIdentity("Disenchant","")); - cubeCards.add(new CardIdentity("Mother of Runes","")); - cubeCards.add(new CardIdentity("Weathered Wayfarer","")); - cubeCards.add(new CardIdentity("Ravages of War","")); - cubeCards.add(new CardIdentity("Student of Warfare","")); - cubeCards.add(new CardIdentity("Swords to Plowshares","")); - cubeCards.add(new CardIdentity("Elspeth Tirel","")); - cubeCards.add(new CardIdentity("Mirran Crusader","")); - cubeCards.add(new CardIdentity("Elite Vanguard","")); - cubeCards.add(new CardIdentity("Day of Judgment","")); - cubeCards.add(new CardIdentity("Silverblade Paladin","")); - cubeCards.add(new CardIdentity("Soldier of the Pantheon","")); - cubeCards.add(new CardIdentity("Enlightened Tutor","")); - cubeCards.add(new CardIdentity("Parallax Wave","")); - cubeCards.add(new CardIdentity("Kami of Ancient Law","")); - cubeCards.add(new CardIdentity("Isamaru, Hound of Konda","")); - cubeCards.add(new CardIdentity("Savannah Lions","")); - cubeCards.add(new CardIdentity("Wrath of God","")); - cubeCards.add(new CardIdentity("Cloudgoat Ranger","")); - cubeCards.add(new CardIdentity("Reveillark","")); - cubeCards.add(new CardIdentity("Flickerwisp","")); - cubeCards.add(new CardIdentity("Ranger of Eos","")); - cubeCards.add(new CardIdentity("Elspeth, Knight-Errant","")); - cubeCards.add(new CardIdentity("Balance","")); - cubeCards.add(new CardIdentity("Journey to Nowhere","")); - cubeCards.add(new CardIdentity("Emeria Angel","")); - cubeCards.add(new CardIdentity("Ajani Goldmane","")); - cubeCards.add(new CardIdentity("Porcelain Legionnaire","")); - cubeCards.add(new CardIdentity("Blade Splicer","")); - cubeCards.add(new CardIdentity("Thalia, Guardian of Thraben","")); - cubeCards.add(new CardIdentity("Restoration Angel","")); - cubeCards.add(new CardIdentity("Moat","")); - cubeCards.add(new CardIdentity("Elspeth, Sun's Champion","")); - cubeCards.add(new CardIdentity("Spear of Heliod","")); - cubeCards.add(new CardIdentity("Unexpectedly Absent","")); - cubeCards.add(new CardIdentity("Armageddon","")); - cubeCards.add(new CardIdentity("Faith's Fetters","")); - cubeCards.add(new CardIdentity("Stoneforge Mystic","")); - cubeCards.add(new CardIdentity("Baneslayer Angel","")); - cubeCards.add(new CardIdentity("Hero of Bladehold","")); - cubeCards.add(new CardIdentity("Oblivion Ring","")); - cubeCards.add(new CardIdentity("Ajani, Caller of the Pride","")); - cubeCards.add(new CardIdentity("Angel of Serenity","")); - cubeCards.add(new CardIdentity("Archangel of Thune","")); - cubeCards.add(new CardIdentity("Gideon Jura","")); - cubeCards.add(new CardIdentity("Augur of Bolas","")); - cubeCards.add(new CardIdentity("Delver of Secrets","")); - cubeCards.add(new CardIdentity("Ponder","")); - cubeCards.add(new CardIdentity("Talrand, Sky Summoner","")); - cubeCards.add(new CardIdentity("Thada Adel, Acquisitor","")); - cubeCards.add(new CardIdentity("Kira, Great Glass-Spinner","")); - cubeCards.add(new CardIdentity("Deceiver Exarch","")); - cubeCards.add(new CardIdentity("Grand Architect","")); - cubeCards.add(new CardIdentity("Pestermite","")); - cubeCards.add(new CardIdentity("Repeal","")); - cubeCards.add(new CardIdentity("Tezzeret the Seeker","")); - cubeCards.add(new CardIdentity("Thirst for Knowledge","")); - cubeCards.add(new CardIdentity("Mana Drain","")); - cubeCards.add(new CardIdentity("Frantic Search","")); - cubeCards.add(new CardIdentity("Treachery","")); - cubeCards.add(new CardIdentity("Brainstorm","")); - cubeCards.add(new CardIdentity("Brain Freeze","")); - cubeCards.add(new CardIdentity("Venser, Shaper Savant","")); - cubeCards.add(new CardIdentity("Sower of Temptation","")); - cubeCards.add(new CardIdentity("Consecrated Sphinx","")); - cubeCards.add(new CardIdentity("Snapcaster Mage","")); - cubeCards.add(new CardIdentity("True-Name Nemesis","")); - cubeCards.add(new CardIdentity("Force Spike","")); - cubeCards.add(new CardIdentity("Upheaval","")); - cubeCards.add(new CardIdentity("Gifts Ungiven","")); - cubeCards.add(new CardIdentity("Compulsive Research","")); - cubeCards.add(new CardIdentity("Riftwing Cloudskate","")); - cubeCards.add(new CardIdentity("Glen Elendra Archmage","")); - cubeCards.add(new CardIdentity("Inkwell Leviathan","")); - cubeCards.add(new CardIdentity("Tinker","")); - cubeCards.add(new CardIdentity("Jace, the Mind Sculptor","")); - cubeCards.add(new CardIdentity("Old Man of the Sea","")); - cubeCards.add(new CardIdentity("Mystical Tutor","")); - cubeCards.add(new CardIdentity("Impulse","")); - cubeCards.add(new CardIdentity("Turnabout","")); - cubeCards.add(new CardIdentity("Palinchron","")); - cubeCards.add(new CardIdentity("Daze","")); - cubeCards.add(new CardIdentity("Meloku the Clouded Mirror","")); - cubeCards.add(new CardIdentity("Remand","")); - cubeCards.add(new CardIdentity("Looter il-Kor","")); - cubeCards.add(new CardIdentity("Mulldrifter","")); - cubeCards.add(new CardIdentity("Cryptic Command","")); - cubeCards.add(new CardIdentity("Serendib Efreet","")); - cubeCards.add(new CardIdentity("Jace Beleren","")); - cubeCards.add(new CardIdentity("Preordain","")); - cubeCards.add(new CardIdentity("Fact or Fiction","")); - cubeCards.add(new CardIdentity("Mana Leak","")); - cubeCards.add(new CardIdentity("Frost Titan","")); - cubeCards.add(new CardIdentity("Phantasmal Image","")); - cubeCards.add(new CardIdentity("Dungeon Geists","")); - cubeCards.add(new CardIdentity("Tamiyo, the Moon Sage","")); - cubeCards.add(new CardIdentity("Timetwister","")); - cubeCards.add(new CardIdentity("Show and Tell","")); - cubeCards.add(new CardIdentity("Memory Lapse","")); - cubeCards.add(new CardIdentity("Opposition","")); - cubeCards.add(new CardIdentity("Mind's Desire","")); - cubeCards.add(new CardIdentity("Vendilion Clique","")); - cubeCards.add(new CardIdentity("Counterspell","")); - cubeCards.add(new CardIdentity("Force of Will","")); - cubeCards.add(new CardIdentity("Control Magic","")); - cubeCards.add(new CardIdentity("Jace, Architect of Thought","")); - cubeCards.add(new CardIdentity("Time Walk","")); - cubeCards.add(new CardIdentity("Bribery","")); - cubeCards.add(new CardIdentity("Ancestral Recall","")); - cubeCards.add(new CardIdentity("Ancestral Vision","")); - cubeCards.add(new CardIdentity("Phyrexian Metamorph","")); - cubeCards.add(new CardIdentity("Time Spiral","")); - cubeCards.add(new CardIdentity("Trinket Mage","")); - cubeCards.add(new CardIdentity("Bloadsoaked Champion","")); - cubeCards.add(new CardIdentity("Brain Maggot","")); - cubeCards.add(new CardIdentity("Carnophage","")); - cubeCards.add(new CardIdentity("Desecration Demon","")); - cubeCards.add(new CardIdentity("Geralf's Messenger","")); - cubeCards.add(new CardIdentity("Imperial Seal","")); - cubeCards.add(new CardIdentity("Massacre Wurm","")); - cubeCards.add(new CardIdentity("Master of the Feast","")); - cubeCards.add(new CardIdentity("Murderous Cut","")); - cubeCards.add(new CardIdentity("Ophiomancer","")); - cubeCards.add(new CardIdentity("Pack Rat","")); - cubeCards.add(new CardIdentity("Phyrexian Negator","")); - cubeCards.add(new CardIdentity("Tombstalker","")); - cubeCards.add(new CardIdentity("Vampire Lacerator","")); - cubeCards.add(new CardIdentity("Yawgmoth's Bargain","")); - cubeCards.add(new CardIdentity("Recurring Nightmare","")); - cubeCards.add(new CardIdentity("Buried Alive","")); - cubeCards.add(new CardIdentity("Tendrils of Agony","")); - cubeCards.add(new CardIdentity("Unburial Rites","")); - cubeCards.add(new CardIdentity("Mesmeric Fiend","")); - cubeCards.add(new CardIdentity("Gatekeeper of Malakir","")); - cubeCards.add(new CardIdentity("Grave Titan","")); - cubeCards.add(new CardIdentity("Phyrexian Obliterator","")); - cubeCards.add(new CardIdentity("Necromancy","")); - cubeCards.add(new CardIdentity("Yawgmoth's Will","")); - cubeCards.add(new CardIdentity("Nezumi Shortfang","")); - cubeCards.add(new CardIdentity("Dark Confidant","")); - cubeCards.add(new CardIdentity("Go for the Throat","")); - cubeCards.add(new CardIdentity("Sheoldred, Whispering One","")); - cubeCards.add(new CardIdentity("Bloodline Keeper","")); - cubeCards.add(new CardIdentity("Animate Dead","")); - cubeCards.add(new CardIdentity("Gravecrawler","")); - cubeCards.add(new CardIdentity("Griselbrand","")); - cubeCards.add(new CardIdentity("Vampiric Tutor","")); - cubeCards.add(new CardIdentity("Living Death","")); - cubeCards.add(new CardIdentity("Reanimate","")); - cubeCards.add(new CardIdentity("Bone Shredder","")); - cubeCards.add(new CardIdentity("Braids, Cabal Minion","")); - cubeCards.add(new CardIdentity("Entomb","")); - cubeCards.add(new CardIdentity("Putrid Imp","")); - cubeCards.add(new CardIdentity("Nezumi Graverobber","")); - cubeCards.add(new CardIdentity("Damnation","")); - cubeCards.add(new CardIdentity("Nekrataal","")); - cubeCards.add(new CardIdentity("Shriekmaw","")); - cubeCards.add(new CardIdentity("Bitterblossom","")); - cubeCards.add(new CardIdentity("Demonic Tutor","")); - cubeCards.add(new CardIdentity("Necropotence","")); - cubeCards.add(new CardIdentity("Disfigure","")); - cubeCards.add(new CardIdentity("Vampire Nighthawk","")); - cubeCards.add(new CardIdentity("Duress","")); - cubeCards.add(new CardIdentity("Skinrender","")); - cubeCards.add(new CardIdentity("Dismember","")); - cubeCards.add(new CardIdentity("Diregraf Ghoul","")); - cubeCards.add(new CardIdentity("Liliana of the Veil","")); - cubeCards.add(new CardIdentity("Hymn to Tourach","")); - cubeCards.add(new CardIdentity("Ultimate Price","")); - cubeCards.add(new CardIdentity("Nether Void","")); - cubeCards.add(new CardIdentity("The Abyss","")); - cubeCards.add(new CardIdentity("Lifebane Zombie","")); - cubeCards.add(new CardIdentity("Thoughtseize","")); - cubeCards.add(new CardIdentity("Hero's Downfall","")); - cubeCards.add(new CardIdentity("Diabolic Edict","")); - cubeCards.add(new CardIdentity("Sarcomancy","")); - cubeCards.add(new CardIdentity("Oona's Prowler","")); - cubeCards.add(new CardIdentity("Dark Ritual","")); - cubeCards.add(new CardIdentity("Hypnotic Specter","")); - cubeCards.add(new CardIdentity("Bloodghast","")); - cubeCards.add(new CardIdentity("Inquisition of Kozilek","")); - cubeCards.add(new CardIdentity("Mind Twist","")); - cubeCards.add(new CardIdentity("Borderland Marauder","")); - cubeCards.add(new CardIdentity("Burst Lightining","")); - cubeCards.add(new CardIdentity("Crater's Claws","")); - cubeCards.add(new CardIdentity("Daretti, Scrap Savant","")); - cubeCards.add(new CardIdentity("Dualcaster Mage","")); - cubeCards.add(new CardIdentity("Eidolon of the Great Revel","")); - cubeCards.add(new CardIdentity("Gore-house Chainwalker","")); - cubeCards.add(new CardIdentity("Guttersnipe","")); - cubeCards.add(new CardIdentity("Imperial Recruiter","")); - cubeCards.add(new CardIdentity("Kiki-Jiki, Mirror Breaker","")); - cubeCards.add(new CardIdentity("Lightning Mauler","")); - cubeCards.add(new CardIdentity("Lightning Strike","")); - cubeCards.add(new CardIdentity("Manic Vandal","")); - cubeCards.add(new CardIdentity("Prophetic Flamespeaker","")); - cubeCards.add(new CardIdentity("Sarkhan, the Dragonspeaker","")); - cubeCards.add(new CardIdentity("Searing Spear","")); - cubeCards.add(new CardIdentity("Splinter Twin","")); - cubeCards.add(new CardIdentity("Stormbreath Dragon","")); - cubeCards.add(new CardIdentity("Stromkirk Noble","")); - cubeCards.add(new CardIdentity("Through the Breach","")); - cubeCards.add(new CardIdentity("Young Pyromancer","")); - cubeCards.add(new CardIdentity("Frenzied Goblin","")); - cubeCards.add(new CardIdentity("Torch Fiend","")); - cubeCards.add(new CardIdentity("Chandra's Phoenix","")); - cubeCards.add(new CardIdentity("Avalanche Riders","")); - cubeCards.add(new CardIdentity("Goblin Welder","")); - cubeCards.add(new CardIdentity("Firebolt","")); - cubeCards.add(new CardIdentity("Sulfuric Vortex","")); - cubeCards.add(new CardIdentity("Seething Song","")); - cubeCards.add(new CardIdentity("Rift Bolt","")); - cubeCards.add(new CardIdentity("Hellrider","")); - cubeCards.add(new CardIdentity("Koth of the Hammer","")); - cubeCards.add(new CardIdentity("Jackal Pup","")); - cubeCards.add(new CardIdentity("Incinerate","")); - cubeCards.add(new CardIdentity("Grim Lavamancer","")); - cubeCards.add(new CardIdentity("Bonfire of the Damned","")); - cubeCards.add(new CardIdentity("Thundermaw Hellkite","")); - cubeCards.add(new CardIdentity("Magma Jet","")); - cubeCards.add(new CardIdentity("Firedrinker Satyr","")); - cubeCards.add(new CardIdentity("Wildfire","")); - cubeCards.add(new CardIdentity("Sneak Attack","")); - cubeCards.add(new CardIdentity("Molten Rain","")); - cubeCards.add(new CardIdentity("Char","")); - cubeCards.add(new CardIdentity("Empty the Warrens","")); - cubeCards.add(new CardIdentity("Ancient Grudge","")); - cubeCards.add(new CardIdentity("Greater Gargadon","")); - cubeCards.add(new CardIdentity("Magus of the Moon","")); - cubeCards.add(new CardIdentity("Smash to Smithereens","")); - cubeCards.add(new CardIdentity("Siege-Gang Commander","")); - cubeCards.add(new CardIdentity("Burning of Xinye","")); - cubeCards.add(new CardIdentity("Goblin Guide","")); - cubeCards.add(new CardIdentity("Searing Blaze","")); - cubeCards.add(new CardIdentity("Kargan Dragonlord","")); - cubeCards.add(new CardIdentity("Wheel of Fortune","")); - cubeCards.add(new CardIdentity("Arc Trail","")); - cubeCards.add(new CardIdentity("Spikeshot Elder","")); - cubeCards.add(new CardIdentity("Flametongue Kavu","")); - cubeCards.add(new CardIdentity("Inferno Titan","")); - cubeCards.add(new CardIdentity("Brimstone Volley","")); - cubeCards.add(new CardIdentity("Faithless Looting","")); - cubeCards.add(new CardIdentity("Zealous Conscripts","")); - cubeCards.add(new CardIdentity("Mizzium Mortars","")); - cubeCards.add(new CardIdentity("Goblin Vandal","")); - cubeCards.add(new CardIdentity("Lightning Bolt","")); - cubeCards.add(new CardIdentity("Chain Lightning","")); - cubeCards.add(new CardIdentity("Fireblast","")); - cubeCards.add(new CardIdentity("Chandra, Pyromaster","")); - cubeCards.add(new CardIdentity("Hero of Oxid Ridge","")); - cubeCards.add(new CardIdentity("Courser of Kruphix","")); - cubeCards.add(new CardIdentity("Craterhoof Behemoth","")); - cubeCards.add(new CardIdentity("Freyalise, Llanowar's Fury","")); - cubeCards.add(new CardIdentity("Krosan Grip","")); - cubeCards.add(new CardIdentity("Life from the Loam","")); - cubeCards.add(new CardIdentity("Nature's Claim","")); - cubeCards.add(new CardIdentity("Nissa, Worldwaker","")); - cubeCards.add(new CardIdentity("Oath of Druids","")); - cubeCards.add(new CardIdentity("Pattern of Rebirth","")); - cubeCards.add(new CardIdentity("Rancor","")); - cubeCards.add(new CardIdentity("Reclamation Sage","")); - cubeCards.add(new CardIdentity("Sakura-Tribe Elder","")); - cubeCards.add(new CardIdentity("Search for Tomorrow","")); - cubeCards.add(new CardIdentity("Song of the Dryads","")); - cubeCards.add(new CardIdentity("Troll Ascetic","")); - cubeCards.add(new CardIdentity("Wall of Roots","")); - cubeCards.add(new CardIdentity("Yavimaya Elder","")); - cubeCards.add(new CardIdentity("Indrik Stomphowler","")); - cubeCards.add(new CardIdentity("Lotus Cobra","")); - cubeCards.add(new CardIdentity("Primeval Titan","")); - cubeCards.add(new CardIdentity("Birds of Paradise","")); - cubeCards.add(new CardIdentity("Wall of Blossoms","")); - cubeCards.add(new CardIdentity("Tooth and Nail","")); - cubeCards.add(new CardIdentity("Eternal Witness","")); - cubeCards.add(new CardIdentity("Primal Command","")); - cubeCards.add(new CardIdentity("Stunted Growth","")); - cubeCards.add(new CardIdentity("Master of the Wild Hunt","")); - cubeCards.add(new CardIdentity("Harmonize","")); - cubeCards.add(new CardIdentity("Terastodon","")); - cubeCards.add(new CardIdentity("Garruk Wildspeaker","")); - cubeCards.add(new CardIdentity("Birthing Pod","")); - cubeCards.add(new CardIdentity("Scavenging Ooze","")); - cubeCards.add(new CardIdentity("Avacyn's Pilgrim","")); - cubeCards.add(new CardIdentity("Wolfir Silverheart","")); - cubeCards.add(new CardIdentity("Eureka","")); - cubeCards.add(new CardIdentity("Garruk, Caller of Beasts","")); - cubeCards.add(new CardIdentity("Natural Order","")); - cubeCards.add(new CardIdentity("Deranged Hermit","")); - cubeCards.add(new CardIdentity("Plow Under","")); - cubeCards.add(new CardIdentity("Heartbeat of Spring","")); - cubeCards.add(new CardIdentity("Woodfall Primus","")); - cubeCards.add(new CardIdentity("Noble Hierarch","")); - cubeCards.add(new CardIdentity("Oracle of Mul Daya","")); - cubeCards.add(new CardIdentity("Arbor Elf","")); - cubeCards.add(new CardIdentity("Joraga Treespeaker","")); - cubeCards.add(new CardIdentity("Vengevine","")); - cubeCards.add(new CardIdentity("Fauna Shaman","")); - cubeCards.add(new CardIdentity("Genesis Wave","")); - cubeCards.add(new CardIdentity("Thrun, the Last Troll","")); - cubeCards.add(new CardIdentity("Beast Within","")); - cubeCards.add(new CardIdentity("Garruk Relentless","")); - cubeCards.add(new CardIdentity("Polukranos, World Eater","")); - cubeCards.add(new CardIdentity("Rofellos, Llanowar Emissary","")); - cubeCards.add(new CardIdentity("Elves of Deep Shadow","")); - cubeCards.add(new CardIdentity("Tarmogoyf","")); - cubeCards.add(new CardIdentity("Avenger of Zendikar","")); - cubeCards.add(new CardIdentity("Green Sun's Zenith","")); - cubeCards.add(new CardIdentity("Acidic Slime","")); - cubeCards.add(new CardIdentity("Garruk, Primal Hunter","")); - cubeCards.add(new CardIdentity("Llanowar Elves","")); - cubeCards.add(new CardIdentity("Regrowth","")); - cubeCards.add(new CardIdentity("Fyndhorn Elves","")); - cubeCards.add(new CardIdentity("Thragtusk","")); - cubeCards.add(new CardIdentity("Elvish Mystic","")); - cubeCards.add(new CardIdentity("Sylvan Caryatid","")); - cubeCards.add(new CardIdentity("Survival of the Fittest","")); - cubeCards.add(new CardIdentity("Sylvan Library","")); - cubeCards.add(new CardIdentity("Bazaar of Baghdad","")); - cubeCards.add(new CardIdentity("Clifftop Retreat","")); - cubeCards.add(new CardIdentity("Dragonskull Summit","")); - cubeCards.add(new CardIdentity("Drowned Catacomb","")); - cubeCards.add(new CardIdentity("Glacial Fortress","")); - cubeCards.add(new CardIdentity("Hinterland Harbor","")); - cubeCards.add(new CardIdentity("Isolated Chapel","")); - cubeCards.add(new CardIdentity("Mutavault","")); - cubeCards.add(new CardIdentity("Rootbound Crag","")); - cubeCards.add(new CardIdentity("Sulfur Falls","")); - cubeCards.add(new CardIdentity("Sunpetal Grove","")); - cubeCards.add(new CardIdentity("Urborg, Tomb of Yawgmoth","")); - cubeCards.add(new CardIdentity("Woodland Cemetary","")); - cubeCards.add(new CardIdentity("Savannah","")); - cubeCards.add(new CardIdentity("Bayou","")); - cubeCards.add(new CardIdentity("Scrubland","")); - cubeCards.add(new CardIdentity("Blood Crypt","")); - cubeCards.add(new CardIdentity("Brushland","")); - cubeCards.add(new CardIdentity("Caves of Koilos","")); - cubeCards.add(new CardIdentity("Ghitu Encampment","")); - cubeCards.add(new CardIdentity("Hallowed Fountain","")); - cubeCards.add(new CardIdentity("Library of Alexandria","")); - cubeCards.add(new CardIdentity("Llanowar Wastes","")); - cubeCards.add(new CardIdentity("Marsh Flats","")); - cubeCards.add(new CardIdentity("Mishra's Workshop","")); - cubeCards.add(new CardIdentity("Treetop Village","")); - cubeCards.add(new CardIdentity("Adarkar Wastes","")); - cubeCards.add(new CardIdentity("Plateau","")); - cubeCards.add(new CardIdentity("Rishadan Port","")); - cubeCards.add(new CardIdentity("Scalding Tarn","")); - cubeCards.add(new CardIdentity("Shivan Reef","")); - cubeCards.add(new CardIdentity("Steam Vents","")); - cubeCards.add(new CardIdentity("Strip Mine","")); - cubeCards.add(new CardIdentity("Taiga","")); - cubeCards.add(new CardIdentity("Tropical Island","")); - cubeCards.add(new CardIdentity("Tundra","")); - cubeCards.add(new CardIdentity("Underground River","")); - cubeCards.add(new CardIdentity("Volcanic Island","")); - cubeCards.add(new CardIdentity("Windbrisk Heights","")); - cubeCards.add(new CardIdentity("Wooded Foothills","")); - cubeCards.add(new CardIdentity("Ancient Tomb","")); - cubeCards.add(new CardIdentity("Badlands","")); - cubeCards.add(new CardIdentity("Arid Mesa","")); - cubeCards.add(new CardIdentity("Misty Rainforest","")); - cubeCards.add(new CardIdentity("Maze of Ith","")); - cubeCards.add(new CardIdentity("Teetering Peaks","")); - cubeCards.add(new CardIdentity("Underground Sea","")); - cubeCards.add(new CardIdentity("Bloodstained Mire","")); - cubeCards.add(new CardIdentity("Watery Grave","")); - cubeCards.add(new CardIdentity("Sacred Foundry","")); - cubeCards.add(new CardIdentity("Stomping Ground","")); - cubeCards.add(new CardIdentity("Godless Shrine","")); - cubeCards.add(new CardIdentity("Breeding Pool","")); - cubeCards.add(new CardIdentity("Sulfurous Springs","")); - cubeCards.add(new CardIdentity("Yavimaya Coast","")); - cubeCards.add(new CardIdentity("Karplusan Forest","")); - cubeCards.add(new CardIdentity("Verdant Catacombs","")); - cubeCards.add(new CardIdentity("Wasteland","")); - cubeCards.add(new CardIdentity("Mishra's Factory","")); - cubeCards.add(new CardIdentity("Karakas","")); - cubeCards.add(new CardIdentity("Temple Garden","")); - cubeCards.add(new CardIdentity("Overgrown Tomb","")); - cubeCards.add(new CardIdentity("Volrath's Stronghold","")); - cubeCards.add(new CardIdentity("Gaea's Cradle","")); - cubeCards.add(new CardIdentity("Tolarian Academy","")); - cubeCards.add(new CardIdentity("Flooded Strand","")); - cubeCards.add(new CardIdentity("Polluted Delta","")); - cubeCards.add(new CardIdentity("Windswept Heath","")); - cubeCards.add(new CardIdentity("Academy Ruins","")); - cubeCards.add(new CardIdentity("Battlefield Forge","")); - cubeCards.add(new CardIdentity("Ashiok, Nightmare Weaver","")); - cubeCards.add(new CardIdentity("Boros Charm","")); - cubeCards.add(new CardIdentity("Boros Reckoner","")); - cubeCards.add(new CardIdentity("Burning-Tree Emissary","")); - cubeCards.add(new CardIdentity("Dack Fayden","")); - cubeCards.add(new CardIdentity("Detention Sphere","")); - cubeCards.add(new CardIdentity("Fire // Ice","")); - cubeCards.add(new CardIdentity("Gaddock Teeg","")); - cubeCards.add(new CardIdentity("Garruk, Apex Predator","")); - cubeCards.add(new CardIdentity("Gerrard's Verdict","")); - cubeCards.add(new CardIdentity("Goblin Electromancer","")); - cubeCards.add(new CardIdentity("Kiora, the Crashing Wave","")); - cubeCards.add(new CardIdentity("Kiora's Follower","")); - cubeCards.add(new CardIdentity("Nightveil Specter","")); - cubeCards.add(new CardIdentity("Olivia Voldaren","")); - cubeCards.add(new CardIdentity("Progenitus","")); - cubeCards.add(new CardIdentity("Qasali Pridemage","")); - cubeCards.add(new CardIdentity("Sin Collector","")); - cubeCards.add(new CardIdentity("Supreme Verdict","")); - cubeCards.add(new CardIdentity("Terminate","")); - cubeCards.add(new CardIdentity("Ral Zarek","")); - cubeCards.add(new CardIdentity("Pernicious Deed","")); - cubeCards.add(new CardIdentity("Lightning Helix","")); - cubeCards.add(new CardIdentity("Electrolyze","")); - cubeCards.add(new CardIdentity("Kitchen Finks","")); - cubeCards.add(new CardIdentity("Tidehollow Sculler","")); - cubeCards.add(new CardIdentity("Nicol Bolas, Planeswalker","")); - cubeCards.add(new CardIdentity("Sphinx of the Steel Wind","")); - cubeCards.add(new CardIdentity("Huntmaster of the Fells","")); - cubeCards.add(new CardIdentity("Mirari's Wake","")); - cubeCards.add(new CardIdentity("Venser, the Sojourner","")); - cubeCards.add(new CardIdentity("Shardless Agent","")); - cubeCards.add(new CardIdentity("Abrupt Decay","")); - cubeCards.add(new CardIdentity("Domri Rade","")); - cubeCards.add(new CardIdentity("Trygon Predator","")); - cubeCards.add(new CardIdentity("Figure of Destiny","")); - cubeCards.add(new CardIdentity("Bloodbraid Elf","")); - cubeCards.add(new CardIdentity("Edric, Spymaster of Trest","")); - cubeCards.add(new CardIdentity("Geist of Saint Traft","")); - cubeCards.add(new CardIdentity("Falkenrath Aristocrat","")); - cubeCards.add(new CardIdentity("Rakdos Cackler","")); - cubeCards.add(new CardIdentity("Dreadbore","")); - cubeCards.add(new CardIdentity("Vraska the Unseen","")); - cubeCards.add(new CardIdentity("Shadowmage Infiltrator","")); - cubeCards.add(new CardIdentity("Ajani Vengeant","")); - cubeCards.add(new CardIdentity("Vindicate","")); - cubeCards.add(new CardIdentity("Maelstrom Pulse","")); - cubeCards.add(new CardIdentity("Tezzeret, Agent of Bolas","")); - cubeCards.add(new CardIdentity("Sorin, Lord of Innistrad","")); - cubeCards.add(new CardIdentity("Baleful Strix","")); - cubeCards.add(new CardIdentity("Xenagos, the Reveler","")); - cubeCards.add(new CardIdentity("Sphinx's Revelation","")); - cubeCards.add(new CardIdentity("Voice of Resurgence","")); - cubeCards.add(new CardIdentity("AEther Vial","")); - cubeCards.add(new CardIdentity("Isochron Scepter","")); - cubeCards.add(new CardIdentity("Pithing Needle","")); - cubeCards.add(new CardIdentity("Relic of Progenitus","")); - cubeCards.add(new CardIdentity("Spellskite","")); - cubeCards.add(new CardIdentity("Time Vault","")); - cubeCards.add(new CardIdentity("Voltaic Key","")); - cubeCards.add(new CardIdentity("Null Rod","")); - cubeCards.add(new CardIdentity("Cursed Scroll","")); - cubeCards.add(new CardIdentity("Emrakul, the Aeons Torn","")); - cubeCards.add(new CardIdentity("Kozilek, Butcher of Truth","")); - cubeCards.add(new CardIdentity("Ulamog, the Infinite Gyre","")); - cubeCards.add(new CardIdentity("Shrine of Burning Rage","")); - cubeCards.add(new CardIdentity("Batterskull","")); - cubeCards.add(new CardIdentity("Lion's Eye Diamond","")); - cubeCards.add(new CardIdentity("Grim Monolith","")); - cubeCards.add(new CardIdentity("Memory Jar","")); - cubeCards.add(new CardIdentity("Mox Diamond","")); - cubeCards.add(new CardIdentity("Nevinyrral's Disk","")); - cubeCards.add(new CardIdentity("Orzhov Signet","")); - cubeCards.add(new CardIdentity("Rakdos Signet","")); - cubeCards.add(new CardIdentity("Sol Ring","")); - cubeCards.add(new CardIdentity("Tangle Wire","")); - cubeCards.add(new CardIdentity("Thran Dynamo","")); - cubeCards.add(new CardIdentity("Winter Orb","")); - cubeCards.add(new CardIdentity("Masticore","")); - cubeCards.add(new CardIdentity("Myr Battlesphere","")); - cubeCards.add(new CardIdentity("Molten-Tail Masticore","")); - cubeCards.add(new CardIdentity("Phyrexian Revoker","")); - cubeCards.add(new CardIdentity("Solemn Simulacrum","")); - cubeCards.add(new CardIdentity("Sword of Body and Mind","")); - cubeCards.add(new CardIdentity("Sword of Feast and Famine","")); - cubeCards.add(new CardIdentity("Sword of War and Peace","")); - cubeCards.add(new CardIdentity("Chrome Mox","")); - cubeCards.add(new CardIdentity("Gilded Lotus","")); - cubeCards.add(new CardIdentity("Sword of Light and Shadow","")); - cubeCards.add(new CardIdentity("Pentad Prism","")); - cubeCards.add(new CardIdentity("Coalition Relic","")); - cubeCards.add(new CardIdentity("Wurmcoil Engine","")); - cubeCards.add(new CardIdentity("Azorius Signet","")); - cubeCards.add(new CardIdentity("Simic Signet","")); - cubeCards.add(new CardIdentity("Basalt Monolith","")); - cubeCards.add(new CardIdentity("Mox Sapphire","")); - cubeCards.add(new CardIdentity("Mox Pearl","")); - cubeCards.add(new CardIdentity("Mox Ruby","")); - cubeCards.add(new CardIdentity("Mox Emerald","")); - cubeCards.add(new CardIdentity("Mox Jet","")); - cubeCards.add(new CardIdentity("Black Lotus","")); - cubeCards.add(new CardIdentity("Boros Signet","")); - cubeCards.add(new CardIdentity("Blightsteel Colossus","")); - cubeCards.add(new CardIdentity("Dimir Signet","")); - cubeCards.add(new CardIdentity("Everflowing Chalice","")); - cubeCards.add(new CardIdentity("Gruul Signet","")); - cubeCards.add(new CardIdentity("Izzet Signet","")); - cubeCards.add(new CardIdentity("Golgari Signet","")); - cubeCards.add(new CardIdentity("Lodestone Golem","")); - cubeCards.add(new CardIdentity("Lotus Bloom","")); - cubeCards.add(new CardIdentity("Mana Crypt","")); - cubeCards.add(new CardIdentity("Mana Vault","")); - cubeCards.add(new CardIdentity("Selesnya Signet","")); - cubeCards.add(new CardIdentity("Metalworker","")); - cubeCards.add(new CardIdentity("Scroll Rack","")); - cubeCards.add(new CardIdentity("Worn Powerstone","")); - cubeCards.add(new CardIdentity("Smokestack","")); - cubeCards.add(new CardIdentity("Lightning Greaves","")); - cubeCards.add(new CardIdentity("Sundering Titan","")); - cubeCards.add(new CardIdentity("Sword of Fire and Ice","")); - cubeCards.add(new CardIdentity("Skullclamp","")); - cubeCards.add(new CardIdentity("Vedalken Shackles","")); - cubeCards.add(new CardIdentity("Crucible of Worlds","")); - cubeCards.add(new CardIdentity("Sensei's Divining Top","")); - cubeCards.add(new CardIdentity("Umezawa's Jitte","")); - cubeCards.add(new CardIdentity("Manriki-Gusari","")); - cubeCards.add(new CardIdentity("Karn Liberated","")); + public HolidayCube2014() { + super("MTGO Holiday Cube 2014"); + + cubeCards.add(new CardIdentity("Abrupt Decay", "")); + cubeCards.add(new CardIdentity("Academy Ruins", "")); + cubeCards.add(new CardIdentity("Accorder Paladin", "")); + cubeCards.add(new CardIdentity("Acidic Slime", "")); + cubeCards.add(new CardIdentity("Adarkar Wastes", "")); + cubeCards.add(new CardIdentity("AEther Vial", "")); + cubeCards.add(new CardIdentity("Ajani Goldmane", "")); + cubeCards.add(new CardIdentity("Ajani Vengeant", "")); + cubeCards.add(new CardIdentity("Ajani, Caller of the Pride", "")); + cubeCards.add(new CardIdentity("Ancestral Recall", "")); + cubeCards.add(new CardIdentity("Ancestral Vision", "")); + cubeCards.add(new CardIdentity("Ancient Grudge", "")); + cubeCards.add(new CardIdentity("Ancient Tomb", "")); + cubeCards.add(new CardIdentity("Angel of Serenity", "")); + cubeCards.add(new CardIdentity("Animate Dead", "")); + cubeCards.add(new CardIdentity("Arbor Elf", "")); + cubeCards.add(new CardIdentity("Arc Trail", "")); + cubeCards.add(new CardIdentity("Archangel of Thune", "")); + cubeCards.add(new CardIdentity("Arid Mesa", "")); + cubeCards.add(new CardIdentity("Armageddon", "")); + cubeCards.add(new CardIdentity("Ashiok, Nightmare Weaver", "")); + cubeCards.add(new CardIdentity("Augur of Bolas", "")); + cubeCards.add(new CardIdentity("Avacyn's Pilgrim", "")); + cubeCards.add(new CardIdentity("Avalanche Riders", "")); + cubeCards.add(new CardIdentity("Aven Mindcensor", "")); + cubeCards.add(new CardIdentity("Avenger of Zendikar", "")); + cubeCards.add(new CardIdentity("Awakening Zone", "")); + cubeCards.add(new CardIdentity("Azorius Signet", "")); + cubeCards.add(new CardIdentity("Badlands", "")); + cubeCards.add(new CardIdentity("Balance", "")); + cubeCards.add(new CardIdentity("Baleful Strix", "")); + cubeCards.add(new CardIdentity("Baneslayer Angel", "")); + cubeCards.add(new CardIdentity("Banisher Priest", "")); + cubeCards.add(new CardIdentity("Banishing Light", "")); + cubeCards.add(new CardIdentity("Basalt Monolith", "")); + cubeCards.add(new CardIdentity("Batterskull", "")); + cubeCards.add(new CardIdentity("Battlefield Forge", "")); + cubeCards.add(new CardIdentity("Bayou", "")); + cubeCards.add(new CardIdentity("Bazaar of Baghdad", "")); + cubeCards.add(new CardIdentity("Beast Within", "")); + cubeCards.add(new CardIdentity("Birds of Paradise", "")); + cubeCards.add(new CardIdentity("Birthing Pod", "")); + cubeCards.add(new CardIdentity("Bitterblossom", "")); + cubeCards.add(new CardIdentity("Black Lotus", "")); + cubeCards.add(new CardIdentity("Blade Splicer", "")); + cubeCards.add(new CardIdentity("Blightsteel Colossus", "")); + cubeCards.add(new CardIdentity("Blood Crypt", "")); + cubeCards.add(new CardIdentity("Bloodbraid Elf", "")); + cubeCards.add(new CardIdentity("Bloodghast", "")); + cubeCards.add(new CardIdentity("Bloodline Keeper", "")); + cubeCards.add(new CardIdentity("Bloodsoaked Champion", "")); + cubeCards.add(new CardIdentity("Bloodstained Mire", "")); + cubeCards.add(new CardIdentity("Bone Shredder", "")); + cubeCards.add(new CardIdentity("Bonfire of the Damned", "")); + cubeCards.add(new CardIdentity("Borderland Marauder", "")); + cubeCards.add(new CardIdentity("Boros Charm", "")); + cubeCards.add(new CardIdentity("Boros Reckoner", "")); + cubeCards.add(new CardIdentity("Boros Signet", "")); + cubeCards.add(new CardIdentity("Braids, Cabal Minion", "")); + cubeCards.add(new CardIdentity("Brain Freeze", "")); + cubeCards.add(new CardIdentity("Brain Maggot", "")); + cubeCards.add(new CardIdentity("Brainstorm", "")); + cubeCards.add(new CardIdentity("Breeding Pool", "")); + cubeCards.add(new CardIdentity("Bribery", "")); + cubeCards.add(new CardIdentity("Brimaz, King of Oreskos", "")); + cubeCards.add(new CardIdentity("Brimstone Volley", "")); + cubeCards.add(new CardIdentity("Brushland", "")); + cubeCards.add(new CardIdentity("Buried Alive", "")); + cubeCards.add(new CardIdentity("Burning of Xinye", "")); + cubeCards.add(new CardIdentity("Burning-Tree Emissary", "")); + cubeCards.add(new CardIdentity("Burst Lightning", "")); + cubeCards.add(new CardIdentity("Carnophage", "")); + cubeCards.add(new CardIdentity("Caves of Koilos", "")); + cubeCards.add(new CardIdentity("Chain Lightning", "")); + cubeCards.add(new CardIdentity("Chandra, Pyromaster", "")); + cubeCards.add(new CardIdentity("Chandra's Phoenix", "")); + cubeCards.add(new CardIdentity("Char", "")); + cubeCards.add(new CardIdentity("Chrome Mox", "")); + cubeCards.add(new CardIdentity("Clifftop Retreat", "")); + cubeCards.add(new CardIdentity("Cloudgoat Ranger", "")); + cubeCards.add(new CardIdentity("Coalition Relic", "")); + cubeCards.add(new CardIdentity("Compulsive Research", "")); + cubeCards.add(new CardIdentity("Consecrated Sphinx", "")); + cubeCards.add(new CardIdentity("Containment Priest", "")); + cubeCards.add(new CardIdentity("Control Magic", "")); + cubeCards.add(new CardIdentity("Council's Judgment", "")); + cubeCards.add(new CardIdentity("Counterspell", "")); + cubeCards.add(new CardIdentity("Courser of Kruphix", "")); + cubeCards.add(new CardIdentity("Crater's Claws", "")); + cubeCards.add(new CardIdentity("Craterhoof Behemoth", "")); + cubeCards.add(new CardIdentity("Crucible of Worlds", "")); + cubeCards.add(new CardIdentity("Cryptic Command", "")); + cubeCards.add(new CardIdentity("Cursed Scroll", "")); + cubeCards.add(new CardIdentity("Dack Fayden", "")); + cubeCards.add(new CardIdentity("Damnation", "")); + cubeCards.add(new CardIdentity("Daretti, Scrap Savant", "")); + cubeCards.add(new CardIdentity("Dark Confidant", "")); + cubeCards.add(new CardIdentity("Dark Ritual", "")); + cubeCards.add(new CardIdentity("Day of Judgment", "")); + cubeCards.add(new CardIdentity("Daze", "")); + cubeCards.add(new CardIdentity("Deceiver Exarch", "")); + cubeCards.add(new CardIdentity("Delver of Secrets", "")); + cubeCards.add(new CardIdentity("Demonic Tutor", "")); + cubeCards.add(new CardIdentity("Deranged Hermit", "")); + cubeCards.add(new CardIdentity("Desecration Demon", "")); + cubeCards.add(new CardIdentity("Detention Sphere", "")); + cubeCards.add(new CardIdentity("Diabolic Edict", "")); + cubeCards.add(new CardIdentity("Dimir Signet", "")); + cubeCards.add(new CardIdentity("Diregraf Ghoul", "")); + cubeCards.add(new CardIdentity("Disenchant", "")); + cubeCards.add(new CardIdentity("Disfigure", "")); + cubeCards.add(new CardIdentity("Dismember", "")); + cubeCards.add(new CardIdentity("Domri Rade", "")); + cubeCards.add(new CardIdentity("Dragonskull Summit", "")); + cubeCards.add(new CardIdentity("Dreadbore", "")); + cubeCards.add(new CardIdentity("Drowned Catacomb", "")); + cubeCards.add(new CardIdentity("Dualcaster Mage", "")); + cubeCards.add(new CardIdentity("Dungeon Geists", "")); + cubeCards.add(new CardIdentity("Duress", "")); + cubeCards.add(new CardIdentity("Edric, Spymaster of Trest", "")); + cubeCards.add(new CardIdentity("Eidolon of the Great Revel", "")); + cubeCards.add(new CardIdentity("Electrolyze", "")); + cubeCards.add(new CardIdentity("Elesh Norn, Grand Cenobite", "")); + cubeCards.add(new CardIdentity("Elite Vanguard", "")); + cubeCards.add(new CardIdentity("Elspeth Tirel", "")); + cubeCards.add(new CardIdentity("Elspeth, Knight-Errant", "")); + cubeCards.add(new CardIdentity("Elspeth, Sun's Champion", "")); + cubeCards.add(new CardIdentity("Elves of Deep Shadow", "")); + cubeCards.add(new CardIdentity("Elvish Mystic", "")); + cubeCards.add(new CardIdentity("Emeria Angel", "")); + cubeCards.add(new CardIdentity("Empty the Warrens", "")); + cubeCards.add(new CardIdentity("Emrakul, the Aeons Torn", "")); + cubeCards.add(new CardIdentity("Enlightened Tutor", "")); + cubeCards.add(new CardIdentity("Entomb", "")); + cubeCards.add(new CardIdentity("Eternal Witness", "")); + cubeCards.add(new CardIdentity("Eureka", "")); + cubeCards.add(new CardIdentity("Everflowing Chalice", "")); + cubeCards.add(new CardIdentity("Exalted Angel", "")); + cubeCards.add(new CardIdentity("Fact or Fiction", "")); + cubeCards.add(new CardIdentity("Faith's Fetters", "")); + cubeCards.add(new CardIdentity("Faithless Looting", "")); + cubeCards.add(new CardIdentity("Falkenrath Aristocrat", "")); + cubeCards.add(new CardIdentity("Fauna Shaman", "")); + cubeCards.add(new CardIdentity("Figure of Destiny", "")); + cubeCards.add(new CardIdentity("Fire & Ice", "")); + cubeCards.add(new CardIdentity("Fireblast", "")); + cubeCards.add(new CardIdentity("Firebolt", "")); + cubeCards.add(new CardIdentity("Firedrinker Satyr", "")); + cubeCards.add(new CardIdentity("Flametongue Kavu", "")); + cubeCards.add(new CardIdentity("Flickerwisp", "")); + cubeCards.add(new CardIdentity("Flooded Strand", "")); + cubeCards.add(new CardIdentity("Force of Will", "")); + cubeCards.add(new CardIdentity("Force Spike", "")); + cubeCards.add(new CardIdentity("Frantic Search", "")); + cubeCards.add(new CardIdentity("Frenzied Goblin", "")); + cubeCards.add(new CardIdentity("Freyalise, Llanowar's Fury", "")); + cubeCards.add(new CardIdentity("Frost Titan", "")); + cubeCards.add(new CardIdentity("Fyndhorn Elves", "")); + cubeCards.add(new CardIdentity("Gaddock Teeg", "")); + cubeCards.add(new CardIdentity("Gaea's Cradle", "")); + cubeCards.add(new CardIdentity("Garruk Relentless", "")); + cubeCards.add(new CardIdentity("Garruk Wildspeaker", "")); + cubeCards.add(new CardIdentity("Garruk, Apex Predator", "")); + cubeCards.add(new CardIdentity("Garruk, Caller of Beasts", "")); + cubeCards.add(new CardIdentity("Garruk, Primal Hunter", "")); + cubeCards.add(new CardIdentity("Gatekeeper of Malakir", "")); + cubeCards.add(new CardIdentity("Geist of Saint Traft", "")); + cubeCards.add(new CardIdentity("Genesis Wave", "")); + cubeCards.add(new CardIdentity("Geralf's Messenger", "")); + cubeCards.add(new CardIdentity("Gerrard's Verdict", "")); + cubeCards.add(new CardIdentity("Ghitu Encampment", "")); + cubeCards.add(new CardIdentity("Gideon Jura", "")); + cubeCards.add(new CardIdentity("Gifts Ungiven", "")); + cubeCards.add(new CardIdentity("Gilded Lotus", "")); + cubeCards.add(new CardIdentity("Glacial Fortress", "")); + cubeCards.add(new CardIdentity("Glen Elendra Archmage", "")); + cubeCards.add(new CardIdentity("Go for the Throat", "")); + cubeCards.add(new CardIdentity("Goblin Electromancer", "")); + cubeCards.add(new CardIdentity("Goblin Guide", "")); + cubeCards.add(new CardIdentity("Goblin Vandal", "")); + cubeCards.add(new CardIdentity("Goblin Welder", "")); + cubeCards.add(new CardIdentity("Godless Shrine", "")); + cubeCards.add(new CardIdentity("Golgari Signet", "")); + cubeCards.add(new CardIdentity("Gore-House Chainwalker", "")); + cubeCards.add(new CardIdentity("Grand Architect", "")); + cubeCards.add(new CardIdentity("Grave Titan", "")); + cubeCards.add(new CardIdentity("Gravecrawler", "")); + cubeCards.add(new CardIdentity("Greater Gargadon", "")); + cubeCards.add(new CardIdentity("Green Sun's Zenith", "")); + cubeCards.add(new CardIdentity("Grim Lavamancer", "")); + cubeCards.add(new CardIdentity("Grim Monolith", "")); + cubeCards.add(new CardIdentity("Griselbrand", "")); + cubeCards.add(new CardIdentity("Gruul Signet", "")); + cubeCards.add(new CardIdentity("Guttersnipe", "")); + cubeCards.add(new CardIdentity("Hallowed Fountain", "")); + cubeCards.add(new CardIdentity("Hallowed Spiritkeeper", "")); + cubeCards.add(new CardIdentity("Harmonize", "")); + cubeCards.add(new CardIdentity("Heartbeat of Spring", "")); + cubeCards.add(new CardIdentity("Hellrider", "")); + cubeCards.add(new CardIdentity("Hero of Bladehold", "")); + cubeCards.add(new CardIdentity("Hero of Oxid Ridge ", "")); + cubeCards.add(new CardIdentity("Hero's Downfall", "")); + cubeCards.add(new CardIdentity("Hinterland Harbor", "")); + cubeCards.add(new CardIdentity("Honor of the Pure", "")); + cubeCards.add(new CardIdentity("Huntmaster of the Fells", "")); + cubeCards.add(new CardIdentity("Hymn to Tourach", "")); + cubeCards.add(new CardIdentity("Hypnotic Specter", "")); + cubeCards.add(new CardIdentity("Imperial Recruiter", "")); + cubeCards.add(new CardIdentity("Imperial Seal", "")); + cubeCards.add(new CardIdentity("Imposing Sovereign", "")); + cubeCards.add(new CardIdentity("Impulse", "")); + cubeCards.add(new CardIdentity("Incinerate", "")); + cubeCards.add(new CardIdentity("Indrik Stomphowler", "")); + cubeCards.add(new CardIdentity("Inferno Titan", "")); + cubeCards.add(new CardIdentity("Inkwell Leviathan", "")); + cubeCards.add(new CardIdentity("Inquisition of Kozilek", "")); + cubeCards.add(new CardIdentity("Iona, Shield of Emeria", "")); + cubeCards.add(new CardIdentity("Isamaru, Hound of Konda", "")); + cubeCards.add(new CardIdentity("Isochron Scepter", "")); + cubeCards.add(new CardIdentity("Isolated Chapel", "")); + cubeCards.add(new CardIdentity("Izzet Signet", "")); + cubeCards.add(new CardIdentity("Jace Beleren", "")); + cubeCards.add(new CardIdentity("Jace, Architect of Thought", "")); + cubeCards.add(new CardIdentity("Jace, the Mind Sculptor", "")); + cubeCards.add(new CardIdentity("Jackal Pup", "")); + cubeCards.add(new CardIdentity("Joraga Treespeaker", "")); + cubeCards.add(new CardIdentity("Journey to Nowhere", "")); + cubeCards.add(new CardIdentity("Kami of Ancient Law", "")); + cubeCards.add(new CardIdentity("Karakas", "")); + cubeCards.add(new CardIdentity("Kargan Dragonlord", "")); + cubeCards.add(new CardIdentity("Karn Liberated", "")); + cubeCards.add(new CardIdentity("Karplusan Forest", "")); + cubeCards.add(new CardIdentity("Kiki-Jiki, Mirror Breaker", "")); + cubeCards.add(new CardIdentity("Kiora, the Crashing Wave", "")); + cubeCards.add(new CardIdentity("Kiora's Follower", "")); + cubeCards.add(new CardIdentity("Kira, Great Glass-Spinner", "")); + cubeCards.add(new CardIdentity("Kitchen Finks", "")); + cubeCards.add(new CardIdentity("Koth of the Hammer", "")); + cubeCards.add(new CardIdentity("Kozilek, Butcher of Truth", "")); + cubeCards.add(new CardIdentity("Krosan Grip", "")); + cubeCards.add(new CardIdentity("Land Tax", "")); + cubeCards.add(new CardIdentity("Leonin Arbiter", "")); + cubeCards.add(new CardIdentity("Leonin Relic-Warder", "")); + cubeCards.add(new CardIdentity("Library of Alexandria", "")); + cubeCards.add(new CardIdentity("Life from the Loam", "")); + cubeCards.add(new CardIdentity("Lifebane Zombie", "")); + cubeCards.add(new CardIdentity("Lightning Bolt", "")); + cubeCards.add(new CardIdentity("Lightning Greaves", "")); + cubeCards.add(new CardIdentity("Lightning Helix", "")); + cubeCards.add(new CardIdentity("Lightning Mauler", "")); + cubeCards.add(new CardIdentity("Lightning Strike", "")); + cubeCards.add(new CardIdentity("Liliana of the Veil", "")); + cubeCards.add(new CardIdentity("Lingering Souls", "")); + cubeCards.add(new CardIdentity("Lion's Eye Diamond", "")); + cubeCards.add(new CardIdentity("Living Death", "")); + cubeCards.add(new CardIdentity("Llanowar Elves", "")); + cubeCards.add(new CardIdentity("Llanowar Wastes", "")); + cubeCards.add(new CardIdentity("Lodestone Golem", "")); + cubeCards.add(new CardIdentity("Looter il-Kor", "")); + cubeCards.add(new CardIdentity("Lotus Bloom", "")); + cubeCards.add(new CardIdentity("Lotus Cobra", "")); + cubeCards.add(new CardIdentity("Maelstrom Pulse", "")); + cubeCards.add(new CardIdentity("Magma Jet", "")); + cubeCards.add(new CardIdentity("Magus of the Moon", "")); + cubeCards.add(new CardIdentity("Mana Crypt", "")); + cubeCards.add(new CardIdentity("Mana Drain", "")); + cubeCards.add(new CardIdentity("Mana Leak", "")); + cubeCards.add(new CardIdentity("Mana Tithe", "")); + cubeCards.add(new CardIdentity("Mana Vault", "")); + cubeCards.add(new CardIdentity("Manic Vandal", "")); + cubeCards.add(new CardIdentity("Manriki-Gusari", "")); + cubeCards.add(new CardIdentity("Marsh Flats", "")); + cubeCards.add(new CardIdentity("Massacre Wurm", "")); + cubeCards.add(new CardIdentity("Master of the Feast", "")); + cubeCards.add(new CardIdentity("Master of the Wild Hunt", "")); + cubeCards.add(new CardIdentity("Masticore", "")); + cubeCards.add(new CardIdentity("Maze of Ith", "")); + cubeCards.add(new CardIdentity("Meloku the Clouded Mirror", "")); + cubeCards.add(new CardIdentity("Memory Jar", "")); + cubeCards.add(new CardIdentity("Memory Lapse", "")); + cubeCards.add(new CardIdentity("Mesmeric Fiend", "")); + cubeCards.add(new CardIdentity("Metalworker", "")); + cubeCards.add(new CardIdentity("Mind Twist", "")); + cubeCards.add(new CardIdentity("Mind's Desire", "")); + cubeCards.add(new CardIdentity("Mirari's Wake", "")); + cubeCards.add(new CardIdentity("Mirran Crusader", "")); + cubeCards.add(new CardIdentity("Mishra's Factory", "")); + cubeCards.add(new CardIdentity("Mishra's Workshop", "")); + cubeCards.add(new CardIdentity("Misty Rainforest", "")); + cubeCards.add(new CardIdentity("Mizzium Mortars", "")); + cubeCards.add(new CardIdentity("Moat", "")); + cubeCards.add(new CardIdentity("Molten Rain", "")); + cubeCards.add(new CardIdentity("Molten-Tail Masticore", "")); + cubeCards.add(new CardIdentity("Mother of Runes", "")); + cubeCards.add(new CardIdentity("Mox Diamond", "")); + cubeCards.add(new CardIdentity("Mox Emerald", "")); + cubeCards.add(new CardIdentity("Mox Jet", "")); + cubeCards.add(new CardIdentity("Mox Pearl", "")); + cubeCards.add(new CardIdentity("Mox Ruby", "")); + cubeCards.add(new CardIdentity("Mox Sapphire", "")); + cubeCards.add(new CardIdentity("Mulldrifter", "")); + cubeCards.add(new CardIdentity("Murderous Cut", "")); + cubeCards.add(new CardIdentity("Mutavault", "")); + cubeCards.add(new CardIdentity("Myr Battlesphere", "")); + cubeCards.add(new CardIdentity("Mystical Tutor", "")); + cubeCards.add(new CardIdentity("Natural Order", "")); + cubeCards.add(new CardIdentity("Nature's Claim", "")); + cubeCards.add(new CardIdentity("Necromancy", "")); + cubeCards.add(new CardIdentity("Necropotence", "")); + cubeCards.add(new CardIdentity("Nekrataal", "")); + cubeCards.add(new CardIdentity("Nether Void", "")); + cubeCards.add(new CardIdentity("Nevinyrral's Disk", "")); + cubeCards.add(new CardIdentity("Nezumi Graverobber", "")); + cubeCards.add(new CardIdentity("Nezumi Shortfang", "")); + cubeCards.add(new CardIdentity("Nicol Bolas, Planeswalker", "")); + cubeCards.add(new CardIdentity("Nightveil Specter", "")); + cubeCards.add(new CardIdentity("Nissa, Worldwaker", "")); + cubeCards.add(new CardIdentity("Noble Hierarch", "")); + cubeCards.add(new CardIdentity("Null Rod", "")); + cubeCards.add(new CardIdentity("Oath of Druids", "")); + cubeCards.add(new CardIdentity("Oblivion Ring", "")); + cubeCards.add(new CardIdentity("Old Man of the Sea", "")); + cubeCards.add(new CardIdentity("Olivia Voldaren", "")); + cubeCards.add(new CardIdentity("Oona's Prowler", "")); + cubeCards.add(new CardIdentity("Ophiomancer", "")); + cubeCards.add(new CardIdentity("Opposition", "")); + cubeCards.add(new CardIdentity("Oracle of Mul Daya", "")); + cubeCards.add(new CardIdentity("Orzhov Signet", "")); + cubeCards.add(new CardIdentity("Overgrown Tomb", "")); + cubeCards.add(new CardIdentity("Pack Rat", "")); + cubeCards.add(new CardIdentity("Palinchron", "")); + cubeCards.add(new CardIdentity("Parallax Wave", "")); + cubeCards.add(new CardIdentity("Path to Exile", "")); + cubeCards.add(new CardIdentity("Pattern of Rebirth", "")); + cubeCards.add(new CardIdentity("Pentad Prism", "")); + cubeCards.add(new CardIdentity("Pernicious Deed", "")); + cubeCards.add(new CardIdentity("Pestermite", "")); + cubeCards.add(new CardIdentity("Phantasmal Image", "")); + cubeCards.add(new CardIdentity("Phyrexian Metamorph", "")); + cubeCards.add(new CardIdentity("Phyrexian Negator", "")); + cubeCards.add(new CardIdentity("Phyrexian Obliterator", "")); + cubeCards.add(new CardIdentity("Phyrexian Revoker", "")); + cubeCards.add(new CardIdentity("Pithing Needle", "")); + cubeCards.add(new CardIdentity("Plateau", "")); + cubeCards.add(new CardIdentity("Plow Under", "")); + cubeCards.add(new CardIdentity("Polluted Delta", "")); + cubeCards.add(new CardIdentity("Polukranos, World Eater", "")); + cubeCards.add(new CardIdentity("Ponder", "")); + cubeCards.add(new CardIdentity("Porcelain Legionnaire", "")); + cubeCards.add(new CardIdentity("Preordain", "")); + cubeCards.add(new CardIdentity("Primal Command", "")); + cubeCards.add(new CardIdentity("Primeval Titan", "")); + cubeCards.add(new CardIdentity("Progenitus", "")); + cubeCards.add(new CardIdentity("Prophetic Flamespeaker", "")); + cubeCards.add(new CardIdentity("Putrid Imp", "")); + cubeCards.add(new CardIdentity("Qasali Pridemage", "")); + cubeCards.add(new CardIdentity("Rakdos Cackler", "")); + cubeCards.add(new CardIdentity("Rakdos Signet", "")); + cubeCards.add(new CardIdentity("Ral Zarek", "")); + cubeCards.add(new CardIdentity("Rancor", "")); + cubeCards.add(new CardIdentity("Ranger of Eos", "")); + cubeCards.add(new CardIdentity("Ravages of War", "")); + cubeCards.add(new CardIdentity("Reanimate", "")); + cubeCards.add(new CardIdentity("Reclamation Sage", "")); + cubeCards.add(new CardIdentity("Recurring Nightmare", "")); + cubeCards.add(new CardIdentity("Regrowth", "")); + cubeCards.add(new CardIdentity("Relic of Progenitus", "")); + cubeCards.add(new CardIdentity("Remand", "")); + cubeCards.add(new CardIdentity("Repeal", "")); + cubeCards.add(new CardIdentity("Restoration Angel", "")); + cubeCards.add(new CardIdentity("Reveillark", "")); + cubeCards.add(new CardIdentity("Rift Bolt", "")); + cubeCards.add(new CardIdentity("Riftwing Cloudskate", "")); + cubeCards.add(new CardIdentity("Rishadan Port", "")); + cubeCards.add(new CardIdentity("Rofellos, Llanowar Emissary", "")); + cubeCards.add(new CardIdentity("Rootbound Crag", "")); + cubeCards.add(new CardIdentity("Sacred Foundry", "")); + cubeCards.add(new CardIdentity("Sakura-Tribe Elder", "")); + cubeCards.add(new CardIdentity("Sarcomancy", "")); + cubeCards.add(new CardIdentity("Sarkhan, the Dragonspeaker", "")); + cubeCards.add(new CardIdentity("Savannah", "")); + cubeCards.add(new CardIdentity("Savannah Lions", "")); + cubeCards.add(new CardIdentity("Scalding Tarn", "")); + cubeCards.add(new CardIdentity("Scavenging Ooze", "")); + cubeCards.add(new CardIdentity("Scroll Rack", "")); + cubeCards.add(new CardIdentity("Scrubland", "")); + cubeCards.add(new CardIdentity("Search for Tomorrow", "")); + cubeCards.add(new CardIdentity("Searing Blaze", "")); + cubeCards.add(new CardIdentity("Searing Spear", "")); + cubeCards.add(new CardIdentity("Seething Song", "")); + cubeCards.add(new CardIdentity("Selesnya Signet", "")); + cubeCards.add(new CardIdentity("Sensei's Divining Top", "")); + cubeCards.add(new CardIdentity("Serendib Efreet", "")); + cubeCards.add(new CardIdentity("Shadowmage Infiltrator", "")); + cubeCards.add(new CardIdentity("Shardless Agent", "")); + cubeCards.add(new CardIdentity("Sheoldred, Whispering One", "")); + cubeCards.add(new CardIdentity("Shivan Reef", "")); + cubeCards.add(new CardIdentity("Show and Tell", "")); + cubeCards.add(new CardIdentity("Shriekmaw", "")); + cubeCards.add(new CardIdentity("Shrine of Burning Rage", "")); + cubeCards.add(new CardIdentity("Siege-Gang Commander", "")); + cubeCards.add(new CardIdentity("Silverblade Paladin", "")); + cubeCards.add(new CardIdentity("Simic Signet", "")); + cubeCards.add(new CardIdentity("Sin Collector", "")); + cubeCards.add(new CardIdentity("Skinrender", "")); + cubeCards.add(new CardIdentity("Skullclamp", "")); + cubeCards.add(new CardIdentity("Smash to Smithereens", "")); + cubeCards.add(new CardIdentity("Smokestack", "")); + cubeCards.add(new CardIdentity("Snapcaster Mage", "")); + cubeCards.add(new CardIdentity("Sneak Attack", "")); + cubeCards.add(new CardIdentity("Sol Ring", "")); + cubeCards.add(new CardIdentity("Soldier of the Pantheon", "")); + cubeCards.add(new CardIdentity("Solemn Simulacrum", "")); + cubeCards.add(new CardIdentity("Song of the Dryads", "")); + cubeCards.add(new CardIdentity("Sorin, Lord of Innistrad", "")); + cubeCards.add(new CardIdentity("Sower of Temptation", "")); + cubeCards.add(new CardIdentity("Spear of Heliod", "")); + cubeCards.add(new CardIdentity("Spectral Procession", "")); + cubeCards.add(new CardIdentity("Spellskite", "")); + cubeCards.add(new CardIdentity("Sphinx of the Steel Wind", "")); + cubeCards.add(new CardIdentity("Sphinx's Revelation", "")); + cubeCards.add(new CardIdentity("Spikeshot Elder", "")); + cubeCards.add(new CardIdentity("Spirit of the Labyrinth", "")); + cubeCards.add(new CardIdentity("Splinter Twin", "")); + cubeCards.add(new CardIdentity("Steam Vents", "")); + cubeCards.add(new CardIdentity("Stomping Ground", "")); + cubeCards.add(new CardIdentity("Stoneforge Mystic", "")); + cubeCards.add(new CardIdentity("Stormbreath Dragon", "")); + cubeCards.add(new CardIdentity("Strip Mine", "")); + cubeCards.add(new CardIdentity("Stromkirk Noble", "")); + cubeCards.add(new CardIdentity("Student of Warfare", "")); + cubeCards.add(new CardIdentity("Stunted Growth", "")); + cubeCards.add(new CardIdentity("Sulfur Falls", "")); + cubeCards.add(new CardIdentity("Sulfuric Vortex", "")); + cubeCards.add(new CardIdentity("Sulfurous Springs", "")); + cubeCards.add(new CardIdentity("Sun Titan", "")); + cubeCards.add(new CardIdentity("Sundering Titan", "")); + cubeCards.add(new CardIdentity("Sunpetal Grove", "")); + cubeCards.add(new CardIdentity("Supreme Verdict", "")); + cubeCards.add(new CardIdentity("Survival of the Fittest", "")); + cubeCards.add(new CardIdentity("Sword of Body and Mind", "")); + cubeCards.add(new CardIdentity("Sword of Feast and Famine", "")); + cubeCards.add(new CardIdentity("Sword of Fire and Ice", "")); + cubeCards.add(new CardIdentity("Sword of Light and Shadow", "")); + cubeCards.add(new CardIdentity("Sword of War and Peace", "")); + cubeCards.add(new CardIdentity("Swords to Plowshares", "")); + cubeCards.add(new CardIdentity("Sylvan Caryatid", "")); + cubeCards.add(new CardIdentity("Sylvan Library", "")); + cubeCards.add(new CardIdentity("Taiga", "")); + cubeCards.add(new CardIdentity("Talrand, Sky Summoner", "")); + cubeCards.add(new CardIdentity("Tamiyo, the Moon Sage", "")); + cubeCards.add(new CardIdentity("Tangle Wire", "")); + cubeCards.add(new CardIdentity("Tarmogoyf", "")); + cubeCards.add(new CardIdentity("Teetering Peaks", "")); + cubeCards.add(new CardIdentity("Temple Garden", "")); + cubeCards.add(new CardIdentity("Tendrils of Agony", "")); + cubeCards.add(new CardIdentity("Terastodon", "")); + cubeCards.add(new CardIdentity("Terminate", "")); + cubeCards.add(new CardIdentity("Terminus", "")); + cubeCards.add(new CardIdentity("Tezzeret the Seeker", "")); + cubeCards.add(new CardIdentity("Tezzeret, Agent of Bolas", "")); + cubeCards.add(new CardIdentity("Thada Adel, Acquisitor", "")); + cubeCards.add(new CardIdentity("Thalia, Guardian of Thraben", "")); + cubeCards.add(new CardIdentity("The Abyss", "")); + cubeCards.add(new CardIdentity("Thirst for Knowledge", "")); + cubeCards.add(new CardIdentity("Thoughtseize", "")); + cubeCards.add(new CardIdentity("Thragtusk", "")); + cubeCards.add(new CardIdentity("Thran Dynamo", "")); + cubeCards.add(new CardIdentity("Through the Breach", "")); + cubeCards.add(new CardIdentity("Thrun, the Last Troll", "")); + cubeCards.add(new CardIdentity("Thundermaw Hellkite", "")); + cubeCards.add(new CardIdentity("Tidehollow Sculler", "")); + cubeCards.add(new CardIdentity("Time Spiral", "")); + cubeCards.add(new CardIdentity("Time Vault", "")); + cubeCards.add(new CardIdentity("Time Walk", "")); + cubeCards.add(new CardIdentity("Timetwister", "")); + cubeCards.add(new CardIdentity("Tinker", "")); + cubeCards.add(new CardIdentity("Tolarian Academy", "")); + cubeCards.add(new CardIdentity("Tombstalker", "")); + cubeCards.add(new CardIdentity("Tooth and Nail", "")); + cubeCards.add(new CardIdentity("Torch Fiend", "")); + cubeCards.add(new CardIdentity("Treachery", "")); + cubeCards.add(new CardIdentity("Treetop Village", "")); + cubeCards.add(new CardIdentity("Trinket Mage", "")); + cubeCards.add(new CardIdentity("Troll Ascetic", "")); + cubeCards.add(new CardIdentity("Tropical Island", "")); + cubeCards.add(new CardIdentity("True-Name Nemesis", "")); + cubeCards.add(new CardIdentity("Trygon Predator", "")); + cubeCards.add(new CardIdentity("Tundra", "")); + cubeCards.add(new CardIdentity("Turnabout", "")); + cubeCards.add(new CardIdentity("Ulamog, the Infinite Gyre", "")); + cubeCards.add(new CardIdentity("Ultimate Price", "")); + cubeCards.add(new CardIdentity("Umezawa's Jitte", "")); + cubeCards.add(new CardIdentity("Unburial Rites", "")); + cubeCards.add(new CardIdentity("Underground River", "")); + cubeCards.add(new CardIdentity("Underground Sea", "")); + cubeCards.add(new CardIdentity("Unexpectedly Absent", "")); + cubeCards.add(new CardIdentity("Upheaval", "")); + cubeCards.add(new CardIdentity("Urborg, Tomb of Yawgmoth", "")); + cubeCards.add(new CardIdentity("Vampire Lacerator", "")); + cubeCards.add(new CardIdentity("Vampire Nighthawk", "")); + cubeCards.add(new CardIdentity("Vampiric Tutor", "")); + cubeCards.add(new CardIdentity("Vedalken Shackles", "")); + cubeCards.add(new CardIdentity("Vendilion Clique", "")); + cubeCards.add(new CardIdentity("Vengevine", "")); + cubeCards.add(new CardIdentity("Venser, Shaper Savant", "")); + cubeCards.add(new CardIdentity("Venser, the Sojourner", "")); + cubeCards.add(new CardIdentity("Verdant Catacombs", "")); + cubeCards.add(new CardIdentity("Vindicate", "")); + cubeCards.add(new CardIdentity("Voice of Resurgence", "")); + cubeCards.add(new CardIdentity("Volcanic Island", "")); + cubeCards.add(new CardIdentity("Volrath's Stronghold", "")); + cubeCards.add(new CardIdentity("Voltaic Key", "")); + cubeCards.add(new CardIdentity("Vraska the Unseen", "")); + cubeCards.add(new CardIdentity("Wall of Blossoms", "")); + cubeCards.add(new CardIdentity("Wall of Omens", "")); + cubeCards.add(new CardIdentity("Wall of Roots", "")); + cubeCards.add(new CardIdentity("Wasteland", "")); + cubeCards.add(new CardIdentity("Watery Grave", "")); + cubeCards.add(new CardIdentity("Weathered Wayfarer", "")); + cubeCards.add(new CardIdentity("Wheel of Fortune", "")); + cubeCards.add(new CardIdentity("Wildfire", "")); + cubeCards.add(new CardIdentity("Windbrisk Heights", "")); + cubeCards.add(new CardIdentity("Windswept Heath", "")); + cubeCards.add(new CardIdentity("Winter Orb", "")); + cubeCards.add(new CardIdentity("Wolfir Silverheart", "")); + cubeCards.add(new CardIdentity("Wooded Foothills", "")); + cubeCards.add(new CardIdentity("Woodfall Primus", "")); + cubeCards.add(new CardIdentity("Woodland Cemetery", "")); + cubeCards.add(new CardIdentity("Worn Powerstone", "")); + cubeCards.add(new CardIdentity("Wrath of God", "")); + cubeCards.add(new CardIdentity("Wurmcoil Engine", "")); + cubeCards.add(new CardIdentity("Xenagos, the Reveler", "")); + cubeCards.add(new CardIdentity("Yavimaya Coast", "")); + cubeCards.add(new CardIdentity("Yavimaya Elder", "")); + cubeCards.add(new CardIdentity("Yawgmoth's Bargain", "")); + cubeCards.add(new CardIdentity("Yawgmoth's Will", "")); + cubeCards.add(new CardIdentity("Young Pyromancer", "")); + cubeCards.add(new CardIdentity("Zealous Conscripts", "")); } } From 10aee35cb6109d26d1a76b9cbe89260c86ad18e9 Mon Sep 17 00:00:00 2001 From: emerald000 Date: Thu, 18 Dec 2014 13:56:51 -0500 Subject: [PATCH 32/36] Added Battlewand Oak and Crime // Punishment. --- .../mage/sets/dissension/CrimePunishment.java | 110 ++++++++++++++++++ .../src/mage/sets/lorwyn/BattlewandOak.java | 79 +++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/dissension/CrimePunishment.java create mode 100644 Mage.Sets/src/mage/sets/lorwyn/BattlewandOak.java diff --git a/Mage.Sets/src/mage/sets/dissension/CrimePunishment.java b/Mage.Sets/src/mage/sets/dissension/CrimePunishment.java new file mode 100644 index 0000000000..45e60615bc --- /dev/null +++ b/Mage.Sets/src/mage/sets/dissension/CrimePunishment.java @@ -0,0 +1,110 @@ +/* + * 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.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.cards.SplitCard; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCardInOpponentsGraveyard; + + + +public class CrimePunishment extends SplitCard { + + private static final FilterCard filter = new FilterCard("creature or enchantment card from an opponent's graveyard"); + static { + filter.add(Predicates.or(new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.ENCHANTMENT))); + } + + public CrimePunishment(UUID ownerId) { + super(ownerId, 150, "Crime", "Punishment", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{W}{B}", "{X}{B}{G}", false); + this.expansionSetCode = "DIS"; + + // Crime + // Put target creature or enchantment card from an opponent's graveyard onto the battlefield under your control. + this.getLeftHalfCard().getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCardInOpponentsGraveyard(filter)); + + // Punishment + // Destroy each artifact, creature, and enchantment with converted mana cost X. + this.getRightHalfCard().getSpellAbility().addEffect(new PunishmentEffect()); + + } + + public CrimePunishment(final CrimePunishment card) { + super(card); + } + + @Override + public CrimePunishment copy() { + return new CrimePunishment(this); + } +} + +class PunishmentEffect extends OneShotEffect { + + PunishmentEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "Destroy each artifact, creature, and enchantment with converted mana cost X"; + } + + PunishmentEffect(final PunishmentEffect effect) { + super(effect); + } + + @Override + public PunishmentEffect copy() { + return new PunishmentEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { + if (permanent != null + && permanent.getManaCost().convertedManaCost() == source.getManaCostsToPay().getX() + && (permanent.getCardType().contains(CardType.ARTIFACT) + || permanent.getCardType().contains(CardType.CREATURE) + || permanent.getCardType().contains(CardType.ENCHANTMENT))) { + permanent.destroy(source.getSourceId(), game, false); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/BattlewandOak.java b/Mage.Sets/src/mage/sets/lorwyn/BattlewandOak.java new file mode 100644 index 0000000000..3656af8ff7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/BattlewandOak.java @@ -0,0 +1,79 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.lorwyn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.continious.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author emerald000 + */ +public class BattlewandOak extends CardImpl { + + private static final FilterPermanent filterForest = new FilterPermanent("a Forest"); + private static final FilterSpell filterTreefolk = new FilterSpell("a Treefolk spell"); + static { + filterForest.add(new SubtypePredicate("Forest")); + filterTreefolk.add(new SubtypePredicate("Treefolk")); + } + + public BattlewandOak(UUID ownerId) { + super(ownerId, 197, "Battlewand Oak", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "LRW"; + this.subtype.add("Treefolk"); + this.subtype.add("Warrior"); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Whenever a Forest enters the battlefield under your control, Battlewand Oak gets +2/+2 until end of turn. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new BoostSourceEffect(2, 2, Duration.EndOfTurn), filterForest)); + + // Whenever you cast a Treefolk spell, Battlewand Oak gets +2/+2 until end of turn. + this.addAbility(new SpellCastControllerTriggeredAbility(new BoostSourceEffect(2, 2, Duration.EndOfTurn), filterTreefolk, false)); + } + + public BattlewandOak(final BattlewandOak card) { + super(card); + } + + @Override + public BattlewandOak copy() { + return new BattlewandOak(this); + } +} From cf4ca3a85a50948ca481e6aa2c96922d1977fc07 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 19 Dec 2014 12:21:57 +0100 Subject: [PATCH 33/36] * Mistform Sliver - Fixed a bug that a chosen subtype was not added correctly. --- Mage.Sets/src/mage/sets/legions/MistformSliver.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/sets/legions/MistformSliver.java b/Mage.Sets/src/mage/sets/legions/MistformSliver.java index 3b1674dd06..c956ab5fce 100644 --- a/Mage.Sets/src/mage/sets/legions/MistformSliver.java +++ b/Mage.Sets/src/mage/sets/legions/MistformSliver.java @@ -33,7 +33,9 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.AddCardSubTypeTargetEffect; import mage.abilities.effects.common.continious.GainAbilityAllEffect; import mage.cards.CardImpl; import mage.cards.repository.CardRepository; @@ -48,6 +50,8 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; /** * @@ -105,9 +109,9 @@ public class MistformSliver extends CardImpl { } } game.informPlayers(permanent.getName() + ": " + player.getName() + " has chosen " + typeChoice.getChoice()); - game.getState().setValue(permanent.getId() + "_type", typeChoice.getChoice().toString()); - permanent.addInfo("chosen type", "Chosen type: " + typeChoice.getChoice() + ""); - permanent.getSubtype().add(typeChoice.getChoice()); + ContinuousEffect effect = new AddCardSubTypeTargetEffect(typeChoice.getChoice(), Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(permanent.getId())); + game.addEffect(effect, source); } return false; } From 3e7039eb70397db1a6c29b90a0656ac736080457 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 19 Dec 2014 12:37:07 +0100 Subject: [PATCH 34/36] Added some cards. --- .../src/mage/sets/darksteel/DrossGolem.java | 66 ++++++++ .../src/mage/sets/darksteel/OxiddaGolem.java | 52 +++++++ .../src/mage/sets/darksteel/TangleGolem.java | 62 ++++++++ Mage.Sets/src/mage/sets/invasion/Dredge.java | 73 +++++++++ .../mage/sets/jacevschandra/OxiddaGolem.java | 66 ++++++++ .../sets/saviorsofkamigawa/ShapeStealer.java | 108 +++++++++++++ .../src/mage/sets/scourge/OneWithNature.java | 79 ++++++++++ .../mage/sets/urzassaga/KarnSilverGolem.java | 145 ++++++++++++++++++ .../sets/vintagemasters/KarnSilverGolem.java | 52 +++++++ .../effects/common/SacrificeEffect.java | 6 +- Mage/src/mage/game/combat/CombatGroup.java | 1 + 11 files changed, 709 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/sets/darksteel/DrossGolem.java create mode 100644 Mage.Sets/src/mage/sets/darksteel/OxiddaGolem.java create mode 100644 Mage.Sets/src/mage/sets/darksteel/TangleGolem.java create mode 100644 Mage.Sets/src/mage/sets/invasion/Dredge.java create mode 100644 Mage.Sets/src/mage/sets/jacevschandra/OxiddaGolem.java create mode 100644 Mage.Sets/src/mage/sets/saviorsofkamigawa/ShapeStealer.java create mode 100644 Mage.Sets/src/mage/sets/scourge/OneWithNature.java create mode 100644 Mage.Sets/src/mage/sets/urzassaga/KarnSilverGolem.java create mode 100644 Mage.Sets/src/mage/sets/vintagemasters/KarnSilverGolem.java diff --git a/Mage.Sets/src/mage/sets/darksteel/DrossGolem.java b/Mage.Sets/src/mage/sets/darksteel/DrossGolem.java new file mode 100644 index 0000000000..9b49ed39f4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/darksteel/DrossGolem.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.darksteel; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.AffinityForLandTypeAbility; +import mage.abilities.keyword.FearAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class DrossGolem extends CardImpl { + + public DrossGolem(UUID ownerId) { + super(ownerId, 119, "Dross Golem", Rarity.COMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); + this.expansionSetCode = "DST"; + this.subtype.add("Golem"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Affinity for Swamps + this.addAbility(new AffinityForLandTypeAbility("Swamp", "Swamps")); + + // Fear + this.addAbility(FearAbility.getInstance()); + } + + public DrossGolem(final DrossGolem card) { + super(card); + } + + @Override + public DrossGolem copy() { + return new DrossGolem(this); + } +} diff --git a/Mage.Sets/src/mage/sets/darksteel/OxiddaGolem.java b/Mage.Sets/src/mage/sets/darksteel/OxiddaGolem.java new file mode 100644 index 0000000000..0e6256036f --- /dev/null +++ b/Mage.Sets/src/mage/sets/darksteel/OxiddaGolem.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.darksteel; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class OxiddaGolem extends mage.sets.jacevschandra.OxiddaGolem { + + public OxiddaGolem(UUID ownerId) { + super(ownerId); + this.cardNumber = 135; + this.expansionSetCode = "DST"; + } + + public OxiddaGolem(final OxiddaGolem card) { + super(card); + } + + @Override + public OxiddaGolem copy() { + return new OxiddaGolem(this); + } +} diff --git a/Mage.Sets/src/mage/sets/darksteel/TangleGolem.java b/Mage.Sets/src/mage/sets/darksteel/TangleGolem.java new file mode 100644 index 0000000000..26ed9e0c74 --- /dev/null +++ b/Mage.Sets/src/mage/sets/darksteel/TangleGolem.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.darksteel; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.AffinityForLandTypeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class TangleGolem extends CardImpl { + + public TangleGolem(UUID ownerId) { + super(ownerId, 151, "Tangle Golem", Rarity.COMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}"); + this.expansionSetCode = "DST"; + this.subtype.add("Golem"); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Affinity for Forests + this.addAbility(new AffinityForLandTypeAbility("Forest", "Forests")); + } + + public TangleGolem(final TangleGolem card) { + super(card); + } + + @Override + public TangleGolem copy() { + return new TangleGolem(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/Dredge.java b/Mage.Sets/src/mage/sets/invasion/Dredge.java new file mode 100644 index 0000000000..9f9d27e9ce --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/Dredge.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.invasion; + +import java.util.UUID; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.SacrificeControllerEffect; +import mage.abilities.effects.common.SacrificeTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetPermanent; + +/** + * + * @author LevelX2 + */ +public class Dredge extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("a creature or land"); + + static { + filter.add(Predicates.or(new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.LAND))); + } + + public Dredge(UUID ownerId) { + super(ownerId, 103, "Dredge", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{B}"); + this.expansionSetCode = "INV"; + + // Sacrifice a creature or land. + this.getSpellAbility().addEffect(new SacrificeControllerEffect(filter, 1, "")); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + public Dredge(final Dredge card) { + super(card); + } + + @Override + public Dredge copy() { + return new Dredge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/jacevschandra/OxiddaGolem.java b/Mage.Sets/src/mage/sets/jacevschandra/OxiddaGolem.java new file mode 100644 index 0000000000..38c7a5c514 --- /dev/null +++ b/Mage.Sets/src/mage/sets/jacevschandra/OxiddaGolem.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.jacevschandra; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.AffinityForLandTypeAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class OxiddaGolem extends CardImpl { + + public OxiddaGolem(UUID ownerId) { + super(ownerId, 46, "Oxidda Golem", Rarity.COMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}"); + this.expansionSetCode = "DD2"; + this.subtype.add("Golem"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Affinity for Mountains + this.addAbility(new AffinityForLandTypeAbility("Mountain", "Mountains")); + + // Haste + this.addAbility(HasteAbility.getInstance()); + } + + public OxiddaGolem(final OxiddaGolem card) { + super(card); + } + + @Override + public OxiddaGolem copy() { + return new OxiddaGolem(this); + } +} diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/ShapeStealer.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/ShapeStealer.java new file mode 100644 index 0000000000..02ce4403bb --- /dev/null +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/ShapeStealer.java @@ -0,0 +1,108 @@ +/* + * 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.saviorsofkamigawa; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BlocksOrBecomesBlockedByCreatureTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.SetPowerToughnessSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class ShapeStealer extends CardImpl { + + public ShapeStealer(UUID ownerId) { + super(ownerId, 55, "Shape Stealer", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{U}{U}"); + this.expansionSetCode = "SOK"; + this.subtype.add("Shapeshifter"); + this.subtype.add("Spirit"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + + // This ability triggers once for each creature blocked by or blocking Shape Stealer. + // If multiple creatures block it, Shape Stealer's power and toughness will change for + // each one in succession. The first trigger put on the stack will be the last to resolve, + // so that will set Shape Stealer's final power and toughness. + // Whenever Shape Stealer blocks or becomes blocked by a creature, change Shape Stealer's power and toughness to that creature's power and toughness until end of turn. + this.addAbility(new BlocksOrBecomesBlockedByCreatureTriggeredAbility(new ShapeStealerEffect(), false)); + } + + public ShapeStealer(final ShapeStealer card) { + super(card); + } + + @Override + public ShapeStealer copy() { + return new ShapeStealer(this); + } +} + +class ShapeStealerEffect extends OneShotEffect { + + public ShapeStealerEffect() { + super(Outcome.Detriment); + this.staticText = "change {this}'s power and toughness to that creature's power and toughness until end of turn"; + } + + public ShapeStealerEffect(final ShapeStealerEffect effect) { + super(effect); + } + + @Override + public ShapeStealerEffect copy() { + return new ShapeStealerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + ContinuousEffect effect = new SetPowerToughnessSourceEffect(permanent.getPower().getValue(), permanent.getToughness().getValue(), Duration.EndOfTurn); + game.addEffect(effect, source); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/scourge/OneWithNature.java b/Mage.Sets/src/mage/sets/scourge/OneWithNature.java new file mode 100644 index 0000000000..909913eba3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/scourge/OneWithNature.java @@ -0,0 +1,79 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.scourge; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToAPlayerAttachedTriggeredAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterBasicLandCard; +import mage.target.TargetPermanent; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class OneWithNature extends CardImpl { + + public OneWithNature(UUID ownerId) { + super(ownerId, 125, "One with Nature", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{G}"); + this.expansionSetCode = "SCG"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.PutLandInPlay)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Whenever enchanted creature deals combat damage to a player, you may search your library for a basic land card, put that card onto the battlefield tapped, then shuffle your library. + ability = new DealsDamageToAPlayerAttachedTriggeredAbility( + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(new FilterBasicLandCard()), true, Outcome.PutLandInPlay), + "enchanted creature", true, false, true, TargetController.ANY); + this.addAbility(ability); + } + + public OneWithNature(final OneWithNature card) { + super(card); + } + + @Override + public OneWithNature copy() { + return new OneWithNature(this); + } +} diff --git a/Mage.Sets/src/mage/sets/urzassaga/KarnSilverGolem.java b/Mage.Sets/src/mage/sets/urzassaga/KarnSilverGolem.java new file mode 100644 index 0000000000..2d6e98b7a1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/urzassaga/KarnSilverGolem.java @@ -0,0 +1,145 @@ +/* + * 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.urzassaga; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continious.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import static mage.constants.Layer.PTChangingEffects_7; +import static mage.constants.Layer.TypeChangingEffects_4; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +/** + * + * @author LevelX2 + */ +public class KarnSilverGolem extends CardImpl { + + private static final FilterArtifactPermanent filterNonCreature = new FilterArtifactPermanent("noncreature artifact"); + + static { + filterNonCreature.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + } + + public KarnSilverGolem(UUID ownerId) { + super(ownerId, 298, "Karn, Silver Golem", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); + this.expansionSetCode = "USG"; + this.supertype.add("Legendary"); + this.subtype.add("Golem"); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Whenever Karn, Silver Golem blocks or becomes blocked, it gets -4/+4 until end of turn. + this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new BoostSourceEffect(-4, +4, Duration.EndOfTurn), false)); + + // {1}: Target noncreature artifact becomes an artifact creature with power and toughness each equal to its converted mana cost until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new KarnSilverGolemEffect(), new ManaCostsImpl("{1")); + ability.addTarget(new TargetPermanent(filterNonCreature)); + this.addAbility(ability); + } + + public KarnSilverGolem(final KarnSilverGolem card) { + super(card); + } + + @Override + public KarnSilverGolem copy() { + return new KarnSilverGolem(this); + } +} + +class KarnSilverGolemEffect extends ContinuousEffectImpl { + + public KarnSilverGolemEffect() { + super(Duration.EndOfTurn, Outcome.BecomeCreature); + staticText = "Target noncreature artifact becomes an artifact creature with power and toughness each equal to its converted mana cost until end of turn"; + } + + public KarnSilverGolemEffect(final KarnSilverGolemEffect effect) { + super(effect); + } + + @Override + public KarnSilverGolemEffect copy() { + return new KarnSilverGolemEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent artifact = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (artifact == null) { + return false; + } + switch (layer) { + case TypeChangingEffects_4: + if (sublayer == SubLayer.NA) { + if (!artifact.getCardType().contains(CardType.CREATURE)) { + artifact.getCardType().add(CardType.CREATURE); + } + } + break; + + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + int cmc = artifact.getManaCost().convertedManaCost(); + artifact.getPower().setValue(cmc); + artifact.getToughness().setValue(cmc); + } + } + return true; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.PTChangingEffects_7 || layer == Layer.TypeChangingEffects_4; + } +} diff --git a/Mage.Sets/src/mage/sets/vintagemasters/KarnSilverGolem.java b/Mage.Sets/src/mage/sets/vintagemasters/KarnSilverGolem.java new file mode 100644 index 0000000000..cd5ff64405 --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/KarnSilverGolem.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.vintagemasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class KarnSilverGolem extends mage.sets.urzassaga.KarnSilverGolem { + + public KarnSilverGolem(UUID ownerId) { + super(ownerId); + this.cardNumber = 270; + this.expansionSetCode = "VMA"; + } + + public KarnSilverGolem(final KarnSilverGolem card) { + super(card); + } + + @Override + public KarnSilverGolem copy() { + return new KarnSilverGolem(this); + } +} diff --git a/Mage/src/mage/abilities/effects/common/SacrificeEffect.java b/Mage/src/mage/abilities/effects/common/SacrificeEffect.java index 4e55554f2e..60e159e6d9 100644 --- a/Mage/src/mage/abilities/effects/common/SacrificeEffect.java +++ b/Mage/src/mage/abilities/effects/common/SacrificeEffect.java @@ -127,7 +127,11 @@ public class SacrificeEffect extends OneShotEffect{ if (preText != null && (preText.endsWith("player") || preText.endsWith("opponent"))) { sb.append(" sacrifices "); } else { - sb.append(" sacrifice "); + if (preText == null || preText.isEmpty()) { + sb.append("sacrifice "); + } else { + sb.append(" sacrifice "); + } } sb.append(CardUtil.numberToText(count.toString(), "a")).append(" "); sb.append(filter.getMessage()); diff --git a/Mage/src/mage/game/combat/CombatGroup.java b/Mage/src/mage/game/combat/CombatGroup.java index 370e5478f5..806a0fb8b9 100644 --- a/Mage/src/mage/game/combat/CombatGroup.java +++ b/Mage/src/mage/game/combat/CombatGroup.java @@ -521,6 +521,7 @@ public class CombatGroup implements Serializable, Copyable { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BLOCKER_DECLARED, attackerId, blockerId, players.get(blockerId))); } } + if(!blockers.isEmpty()) { for (UUID attackerId: attackers) { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, attackerId, null)); From f6805bc105f361e6c9fe2fc7e2f93568b4b698c9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 19 Dec 2014 16:04:06 +0100 Subject: [PATCH 35/36] * Akroma, Angel of Fury - Fixed wrong colors of her protection ability. --- Mage.Sets/src/mage/sets/commander/AkromaAngelOfFury.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/commander/AkromaAngelOfFury.java b/Mage.Sets/src/mage/sets/commander/AkromaAngelOfFury.java index 086816e688..5fbae5933d 100644 --- a/Mage.Sets/src/mage/sets/commander/AkromaAngelOfFury.java +++ b/Mage.Sets/src/mage/sets/commander/AkromaAngelOfFury.java @@ -56,7 +56,7 @@ public class AkromaAngelOfFury extends CardImpl { private static final FilterCard protectionFilter = new FilterCard("white and from blue"); static { - protectionFilter.add(Predicates.or(new ColorPredicate(ObjectColor.BLACK),new ColorPredicate(ObjectColor.RED))); + protectionFilter.add(Predicates.or(new ColorPredicate(ObjectColor.WHITE),new ColorPredicate(ObjectColor.BLUE))); } public AkromaAngelOfFury(UUID ownerId) { From c81231b40cdd315c0cf1190ac65726464689f913 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 19 Dec 2014 23:56:11 +0100 Subject: [PATCH 36/36] * Balance - reworded user selection text. Other minor changes. --- .../mage/sets/commander2013/PrimalVigor.java | 8 ++------ .../src/mage/sets/limitedbeta/Balance.java | 6 +++--- .../sets/modernmasters/DoublingSeason.java | 8 +++----- .../scarsofmirrodin/SwordOfBodyAndMind.java | 19 ++++++++++++++----- .../mage/sets/vintagemasters/ManaCrypt.java | 5 +---- ...romGraveyardToBattlefieldTargetEffect.java | 2 +- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Mage.Sets/src/mage/sets/commander2013/PrimalVigor.java b/Mage.Sets/src/mage/sets/commander2013/PrimalVigor.java index 5e4b3cce47..561bd6d0a5 100644 --- a/Mage.Sets/src/mage/sets/commander2013/PrimalVigor.java +++ b/Mage.Sets/src/mage/sets/commander2013/PrimalVigor.java @@ -125,17 +125,13 @@ class PrimalVigorCounterEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent p = game.getPermanent(event.getTargetId()); - if (p != null) { - p.addCounters(CounterType.P1P1.createInstance(event.getAmount() * 2), game, event.getAppliedEffects()); - return true; - } + event.setAmount(event.getAmount() *2); return false; } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.ADD_COUNTER) { + if (event.getType() == GameEvent.EventType.ADD_COUNTERS) { Permanent target = game.getPermanent(event.getTargetId()); if (target != null && filter.match(target, game) && event.getData() != null && event.getData().equals("+1/+1")) { diff --git a/Mage.Sets/src/mage/sets/limitedbeta/Balance.java b/Mage.Sets/src/mage/sets/limitedbeta/Balance.java index 3cade0bfa3..b82ea427f6 100644 --- a/Mage.Sets/src/mage/sets/limitedbeta/Balance.java +++ b/Mage.Sets/src/mage/sets/limitedbeta/Balance.java @@ -109,7 +109,7 @@ class BalanceEffect extends OneShotEffect { for (UUID playerId : controller.getInRange()) { Player player = game.getPlayer(playerId); if (player != null) { - TargetControlledPermanent target = new TargetControlledPermanent(minLand, minLand, new FilterControlledLandPermanent(), true); + TargetControlledPermanent target = new TargetControlledPermanent(minLand, minLand, new FilterControlledLandPermanent("lands to keep"), true); if (target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledLandPermanent(), player.getId(), source.getSourceId(), game)) { if (permanent != null && !target.getTargets().contains(permanent.getId())) { @@ -143,7 +143,7 @@ class BalanceEffect extends OneShotEffect { for (UUID playerId : controller.getInRange()) { Player player = game.getPlayer(playerId); if (player != null) { - TargetControlledPermanent target = new TargetControlledPermanent(minCreature, minCreature, new FilterControlledCreaturePermanent(), true); + TargetControlledPermanent target = new TargetControlledPermanent(minCreature, minCreature, new FilterControlledCreaturePermanent("creatures to keep"), true); if (target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), player.getId(), source.getSourceId(), game)) { if (permanent != null && !target.getTargets().contains(permanent.getId())) { @@ -178,7 +178,7 @@ class BalanceEffect extends OneShotEffect { Player player = game.getPlayer(playerId); if (player != null) { Cards cards = new CardsImpl(); - TargetCardInHand target = new TargetCardInHand(minCard, new FilterCard()); + TargetCardInHand target = new TargetCardInHand(minCard, new FilterCard("cards to keep")); if (target.choose(Outcome.Discard, player.getId(), source.getSourceId(), game)) { for (Card card : player.getHand().getCards(game)) { if (card != null && !target.getTargets().contains(card.getId())) { diff --git a/Mage.Sets/src/mage/sets/modernmasters/DoublingSeason.java b/Mage.Sets/src/mage/sets/modernmasters/DoublingSeason.java index 08618b0a05..85af496af9 100644 --- a/Mage.Sets/src/mage/sets/modernmasters/DoublingSeason.java +++ b/Mage.Sets/src/mage/sets/modernmasters/DoublingSeason.java @@ -27,7 +27,6 @@ */ package mage.sets.modernmasters; -import java.util.Locale; import java.util.UUID; import mage.constants.CardType; import mage.constants.Duration; @@ -38,8 +37,6 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.CardImpl; -import mage.counters.Counter; -import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -96,7 +93,7 @@ class DoublingSeasonTokenEffect extends ReplacementEffectImpl { case CREATE_TOKEN: StackObject spell = game.getStack().getStackObject(event.getSourceId()); if (spell != null && spell.getControllerId().equals(source.getControllerId())) { - event.setAmount(event.getAmount() * 2); + return true; } } return false; @@ -109,7 +106,8 @@ class DoublingSeasonTokenEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return apply(game, source); + event.setAmount(event.getAmount() * 2); + return false; } } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/SwordOfBodyAndMind.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/SwordOfBodyAndMind.java index c118c6cc9c..fc03426c95 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/SwordOfBodyAndMind.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/SwordOfBodyAndMind.java @@ -56,6 +56,7 @@ import mage.game.permanent.token.WolfToken; import mage.target.targetpointer.FixedTarget; import java.util.UUID; +import mage.abilities.Ability; /** * @@ -71,15 +72,23 @@ public class SwordOfBodyAndMind extends CardImpl { new ColorPredicate(ObjectColor.BLUE))); } - public SwordOfBodyAndMind (UUID ownerId) { super(ownerId, 208, "Sword of Body and Mind", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT}, "{3}"); this.expansionSetCode = "SOM"; this.subtype.add("Equipment"); - this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(new ProtectionAbility(filter), AttachmentType.EQUIPMENT))); + + // Equipped creature gets +2/+2 and has protection from green and from blue. + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2)); + Effect effect = new GainAbilityAttachedEffect(new ProtectionAbility(filter), AttachmentType.EQUIPMENT); + effect.setText("and has protection from green and from blue"); + ability.addEffect(effect); + this.addAbility(ability); + + // Whenever equipped creature deals combat damage to a player, you put a 2/2 green Wolf creature token onto the battlefield and that player puts the top ten cards of his or her library into his or her graveyard. this.addAbility(new SwordOfBodyAndMindAbility()); + + // Equip {2} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); } public SwordOfBodyAndMind (final SwordOfBodyAndMind card) { @@ -115,7 +124,7 @@ class SwordOfBodyAndMindAbility extends TriggeredAbilityImpl { Permanent p = game.getPermanent(event.getSourceId()); if (damageEvent.isCombatDamage() && p != null && p.getAttachments().contains(this.getSourceId())) { for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getPlayerId())); + effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } return true; } diff --git a/Mage.Sets/src/mage/sets/vintagemasters/ManaCrypt.java b/Mage.Sets/src/mage/sets/vintagemasters/ManaCrypt.java index 7b323bb62c..81e1a720dc 100644 --- a/Mage.Sets/src/mage/sets/vintagemasters/ManaCrypt.java +++ b/Mage.Sets/src/mage/sets/vintagemasters/ManaCrypt.java @@ -27,7 +27,6 @@ */ package mage.sets.vintagemasters; -import java.util.List; import java.util.UUID; import mage.Mana; import mage.abilities.Ability; @@ -41,9 +40,7 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; /** @@ -76,7 +73,7 @@ public class ManaCrypt extends CardImpl { class ManaCryptEffect extends OneShotEffect { ManaCryptEffect() { - super(Outcome.Sacrifice); + super(Outcome.Damage); staticText = "flip a coin. If you lose the flip, {this} Crypt deals 3 damage to you"; } diff --git a/Mage/src/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java b/Mage/src/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java index bd532f9b50..ac3d0c472d 100644 --- a/Mage/src/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java @@ -76,7 +76,7 @@ public class ReturnFromGraveyardToBattlefieldTargetEffect extends OneShotEffect Card card = game.getCard(targetId); if (card != null) { if (player.putOntoBattlefieldWithInfo(card, game, Zone.GRAVEYARD, source.getSourceId(), tapped)) { - Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent permanent = game.getPermanent(targetId); if (permanent != null) { permanent.changeControllerId(source.getControllerId(), game); }