From a0f2311300c3eb56babd657684c6bb8a9273089c Mon Sep 17 00:00:00 2001 From: AMWJ Date: Mon, 12 Mar 2018 19:50:52 -0400 Subject: [PATCH 1/2] * Implemented Casting Of Bones (https://scryfall.com/card/cst/44b), and added it to Alliances set. * Refactored DrawDiscardOneOfThemEffect to be used in CastingOfBones, KrovikanSorcerer, and SoldeviSage. --- .../src/mage/cards/c/CastingOfBones.java | 75 +++++++++++++ .../src/mage/cards/k/KrovikanSorcerer.java | 57 +--------- Mage.Sets/src/mage/cards/s/SoldeviSage.java | 61 +---------- Mage.Sets/src/mage/sets/Alliances.java | 2 + .../common/DrawDiscardOneOfThemEffect.java | 100 ++++++++++++++++++ 5 files changed, 183 insertions(+), 112 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/c/CastingOfBones.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DrawDiscardOneOfThemEffect.java diff --git a/Mage.Sets/src/mage/cards/c/CastingOfBones.java b/Mage.Sets/src/mage/cards/c/CastingOfBones.java new file mode 100644 index 0000000000..c725c1041b --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CastingOfBones.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.c; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.DiesAttachedTriggeredAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author AMWJ + */ +public class CastingOfBones extends CardImpl { + + public CastingOfBones(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.DrawCard)); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Discard)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // When enchanted creature dies, draw three cards, then discard one of them. + this.addAbility(new DiesAttachedTriggeredAbility(new DrawDiscardControllerEffect(3, 1), "enchanted creature")); + } + + public CastingOfBones(final CastingOfBones card) { + super(card); + } + + @Override + public CastingOfBones copy() { + return new CastingOfBones(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KrovikanSorcerer.java b/Mage.Sets/src/mage/cards/k/KrovikanSorcerer.java index e950d3a058..c7e3ac950b 100644 --- a/Mage.Sets/src/mage/cards/k/KrovikanSorcerer.java +++ b/Mage.Sets/src/mage/cards/k/KrovikanSorcerer.java @@ -34,23 +34,16 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.cards.Card; +import mage.abilities.effects.common.DrawDiscardOneOfThemEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetCard; import mage.target.common.TargetCardInHand; /** @@ -79,7 +72,7 @@ public class KrovikanSorcerer extends CardImpl { this.addAbility(ability); // {tap}, Discard a black card: Draw two cards, then discard one of them. - ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new KrovikanSorcererEffect(), new TapSourceCost()); + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawDiscardOneOfThemEffect(2), new TapSourceCost()); ability.addCost(new DiscardTargetCost(new TargetCardInHand(filterBlack))); this.addAbility(ability); } @@ -92,48 +85,4 @@ public class KrovikanSorcerer extends CardImpl { public KrovikanSorcerer copy() { return new KrovikanSorcerer(this); } -} - -class KrovikanSorcererEffect extends OneShotEffect { - - KrovikanSorcererEffect() { - super(Outcome.DrawCard); - this.staticText = "Draw two cards, then discard one of them"; - } - - KrovikanSorcererEffect(final KrovikanSorcererEffect effect) { - super(effect); - } - - @Override - public KrovikanSorcererEffect copy() { - return new KrovikanSorcererEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - Cards initialHand = player.getHand().copy(); - player.drawCards(2, game); - Cards drawnCards = new CardsImpl(); - for (UUID cardId : player.getHand()) { - if (!initialHand.contains(cardId)) { - drawnCards.add(cardId); - } - } - if (!drawnCards.isEmpty()) { - TargetCard cardToDiscard = new TargetCard(Zone.HAND, new FilterCard("card to discard")); - cardToDiscard.setNotTarget(true); - if (player.choose(Outcome.Discard, drawnCards, cardToDiscard, game)) { - Card card = player.getHand().get(cardToDiscard.getFirstTarget(), game); - if (card != null) { - return player.discard(card, source, game); - } - } - } - return true; - } - return false; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SoldeviSage.java b/Mage.Sets/src/mage/cards/s/SoldeviSage.java index a512f2b301..d351f569c1 100644 --- a/Mage.Sets/src/mage/cards/s/SoldeviSage.java +++ b/Mage.Sets/src/mage/cards/s/SoldeviSage.java @@ -33,21 +33,13 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; +import mage.abilities.effects.common.DrawDiscardOneOfThemEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; import mage.constants.Zone; -import mage.filter.FilterCard; import mage.filter.common.FilterControlledLandPermanent; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetCard; import mage.target.common.TargetControlledPermanent; /** @@ -65,7 +57,7 @@ public class SoldeviSage extends CardImpl { this.toughness = new MageInt(1); // {tap}, Sacrifice two lands: Draw three cards, then discard one of them. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SoldeviSageEffect(), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawDiscardOneOfThemEffect(3), new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(2, 2, new FilterControlledLandPermanent("two lands"), true))); this.addAbility(ability); } @@ -78,51 +70,4 @@ public class SoldeviSage extends CardImpl { public SoldeviSage copy() { return new SoldeviSage(this); } -} - -class SoldeviSageEffect extends OneShotEffect { - - public SoldeviSageEffect() { - super(Outcome.DrawCard); - this.staticText = "Draw three cards, then discard one of them"; - } - - public SoldeviSageEffect(final SoldeviSageEffect effect) { - super(effect); - } - - @Override - public SoldeviSageEffect copy() { - return new SoldeviSageEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - Cards initialHand = player.getHand().copy(); - player.drawCards(3, game); - Cards drawnCards = new CardsImpl(); - for (UUID cardId : player.getHand()) { - if (!initialHand.contains(cardId)) { - drawnCards.add(cardId); - } - } - - if (!drawnCards.isEmpty()) { - TargetCard cardToDiscard = new TargetCard(Zone.HAND, new FilterCard("card to discard")); - cardToDiscard.setNotTarget(true); - if (player.choose(Outcome.Discard, drawnCards, cardToDiscard, game)) { - Card card = player.getHand().get(cardToDiscard.getFirstTarget(), game); - if (card != null) { - return player.discard(card, source, game); - } - } - } - - return true; - } - return false; - } - -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/Alliances.java b/Mage.Sets/src/mage/sets/Alliances.java index 9bb4de97f4..f33330d309 100644 --- a/Mage.Sets/src/mage/sets/Alliances.java +++ b/Mage.Sets/src/mage/sets/Alliances.java @@ -59,6 +59,8 @@ public class Alliances extends ExpansionSet { cards.add(new SetCardInfo("Burnout", 101, Rarity.UNCOMMON, mage.cards.b.Burnout.class)); cards.add(new SetCardInfo("Carrier Pigeons", 125, Rarity.COMMON, CarrierPigeons.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Carrier Pigeons", 126, Rarity.COMMON, CarrierPigeons.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Casting of Bones", 44, Rarity.COMMON, mage.cards.c.CastingOfBones.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Casting of Bones", 45, Rarity.COMMON, mage.cards.c.CastingOfBones.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Chaos Harlequin", 102, Rarity.RARE, mage.cards.c.ChaosHarlequin.class)); cards.add(new SetCardInfo("Contagion", 4, Rarity.UNCOMMON, mage.cards.c.Contagion.class)); cards.add(new SetCardInfo("Deadly Insect", 64, Rarity.COMMON, mage.cards.d.DeadlyInsect.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DrawDiscardOneOfThemEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DrawDiscardOneOfThemEffect.java new file mode 100644 index 0000000000..a849e851e2 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/DrawDiscardOneOfThemEffect.java @@ -0,0 +1,100 @@ +/* + * Copyright 2011 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 java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.util.CardUtil; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class DrawDiscardOneOfThemEffect extends OneShotEffect { + + private int cardsToDraw; + + public DrawDiscardOneOfThemEffect(int cardsToDraw) { + super(Outcome.DrawCard); + this.cardsToDraw = cardsToDraw; + staticText = new StringBuilder("draw ") + .append(cardsToDraw == 1 ? "a" : CardUtil.numberToText(cardsToDraw)) + .append(" card").append(cardsToDraw == 1 ? "" : "s") + .append(", then discard one of them").toString(); + } + + public DrawDiscardOneOfThemEffect(final DrawDiscardOneOfThemEffect effect) { + super(effect); + this.cardsToDraw = effect.cardsToDraw; + } + + @Override + public DrawDiscardOneOfThemEffect copy() { + return new DrawDiscardOneOfThemEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + Cards initialHand = player.getHand().copy(); + player.drawCards(cardsToDraw, game); + Cards drawnCards = new CardsImpl(); + for(UUID cardId : player.getHand()) { + if(!initialHand.contains(cardId)) { + drawnCards.add(cardId); + } + } + + if(!drawnCards.isEmpty()) { + TargetCard cardToDiscard = new TargetCard(Zone.HAND, new FilterCard("card to discard")); + cardToDiscard.setNotTarget(true); + if(player.choose(Outcome.Discard, drawnCards, cardToDiscard, game)) { + Card card = player.getHand().get(cardToDiscard.getFirstTarget(), game); + if(card != null) { + return player.discard(card, source, game); + } + } + } + + return true; + } + return false; + } + +} From 3a441349efd3ddcafadd435f5480b1f50b9093d0 Mon Sep 17 00:00:00 2001 From: AMWJ Date: Mon, 12 Mar 2018 21:32:52 -0400 Subject: [PATCH 2/2] * Corrected use of DrawDiscardOneOfThemEffect, rather than DrawDiscardControllerEffect in CastingOfBones. --- Mage.Sets/src/mage/cards/c/CastingOfBones.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/c/CastingOfBones.java b/Mage.Sets/src/mage/cards/c/CastingOfBones.java index c725c1041b..d1eee89ac9 100644 --- a/Mage.Sets/src/mage/cards/c/CastingOfBones.java +++ b/Mage.Sets/src/mage/cards/c/CastingOfBones.java @@ -33,7 +33,7 @@ import mage.target.common.TargetCreaturePermanent; import mage.abilities.Ability; import mage.abilities.common.DiesAttachedTriggeredAbility; import mage.abilities.effects.common.AttachEffect; -import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.abilities.effects.common.DrawDiscardOneOfThemEffect; import mage.constants.Outcome; import mage.target.TargetPermanent; import mage.abilities.keyword.EnchantAbility; @@ -61,7 +61,7 @@ public class CastingOfBones extends CardImpl { this.addAbility(ability); // When enchanted creature dies, draw three cards, then discard one of them. - this.addAbility(new DiesAttachedTriggeredAbility(new DrawDiscardControllerEffect(3, 1), "enchanted creature")); + this.addAbility(new DiesAttachedTriggeredAbility(new DrawDiscardOneOfThemEffect(3), "enchanted creature")); } public CastingOfBones(final CastingOfBones card) {