From bfd1a76bdab71e508f99ffa99f72148baf0042df Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 23 Mar 2021 20:23:58 -0400 Subject: [PATCH] finished refactoring cost adjuster methods --- .../src/mage/cards/g/GhostfireBlade.java | 59 +++++----- .../mage/cards/k/KnollspineInvocation.java | 48 +++++---- Mage.Sets/src/mage/cards/l/Lightsaber.java | 57 +++++++--- .../src/mage/cards/m/MarathWillOfTheWild.java | 35 ++---- .../src/mage/cards/p/PrototypePortal.java | 30 ++++-- .../src/mage/cards/s/SkeletalScrying.java | 102 +++++------------- Mage.Sets/src/mage/cards/s/SoulFoundry.java | 64 +++++------ Mage.Sets/src/mage/cards/v/VoodooDoll.java | 69 ++++++------ 8 files changed, 224 insertions(+), 240 deletions(-) diff --git a/Mage.Sets/src/mage/cards/g/GhostfireBlade.java b/Mage.Sets/src/mage/cards/g/GhostfireBlade.java index 9f4d828a5e..b11633fd27 100644 --- a/Mage.Sets/src/mage/cards/g/GhostfireBlade.java +++ b/Mage.Sets/src/mage/cards/g/GhostfireBlade.java @@ -2,16 +2,14 @@ package mage.cards.g; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.costs.CostAdjuster; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.util.CardUtil; @@ -29,35 +27,15 @@ public final class GhostfireBlade extends CardImpl { this.subtype.add(SubType.EQUIPMENT); // Equipped creature gets +2/+2 - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2))); + this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(2, 2))); // Equip {3} - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(3))); // todo + Ability ability = new EquipAbility(3); + ability.setCostAdjuster(GhostfireBladeAdjuster.instance); + this.addAbility(ability); // Ghostfire Blade's equip ability costs {2} less to activate if it targets a colorless creature. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("{this}'s equip ability costs {2} less to activate if it targets a colorless creature"))); - } - - @Override - public void adjustCosts(Ability ability, Game game) { - if (ability instanceof EquipAbility) { - if (game.inCheckPlayableState()) { - // checking state - boolean canSelectColorlessCreature = CardUtil.getAllPossibleTargets(ability, game).stream() - .map(game::getPermanent) - .filter(Objects::nonNull) - .anyMatch(permanent -> permanent.getColor(game).isColorless()); - if (canSelectColorlessCreature) { - CardUtil.reduceCost(ability, 2); - } - } else { - // real cast state - Permanent targetCreature = game.getPermanent(ability.getTargets().getFirstTarget()); - if (targetCreature != null && targetCreature.getColor(game).isColorless()) { - CardUtil.reduceCost(ability, 2); - } - } - } + this.addAbility(new SimpleStaticAbility(new InfoEffect("{this}'s equip ability costs {2} less to activate if it targets a colorless creature"))); } private GhostfireBlade(final GhostfireBlade card) { @@ -69,3 +47,28 @@ public final class GhostfireBlade extends CardImpl { return new GhostfireBlade(this); } } + +enum GhostfireBladeAdjuster implements CostAdjuster { + instance; + + @Override + public void adjustCosts(Ability ability, Game game) { + // checking state + if (game.inCheckPlayableState()) { + if (CardUtil + .getAllPossibleTargets(ability, game) + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .noneMatch(permanent -> permanent.getColor(game).isColorless())) { + return; + } + } else { + Permanent permanent = game.getPermanent(ability.getFirstTarget()); + if (permanent == null || !permanent.getColor(game).isColorless()) { + return; + } + } + CardUtil.reduceCost(ability, 2); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KnollspineInvocation.java b/Mage.Sets/src/mage/cards/k/KnollspineInvocation.java index 38c0d46c5d..893e525a1b 100644 --- a/Mage.Sets/src/mage/cards/k/KnollspineInvocation.java +++ b/Mage.Sets/src/mage/cards/k/KnollspineInvocation.java @@ -1,10 +1,9 @@ - package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.common.ManacostVariableValue; @@ -17,11 +16,12 @@ import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; -import mage.target.common.TargetCardInHand; import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetCardInHand; + +import java.util.UUID; /** - * * @author anonymous */ public final class KnollspineInvocation extends CardImpl { @@ -29,32 +29,16 @@ public final class KnollspineInvocation extends CardImpl { private static final FilterCard filter = new FilterCard("a card with converted mana cost X"); public KnollspineInvocation(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{R}"); // {X}, Discard a card with converted mana cost X: Knollspine Invocation deals X damage to any target. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(ManacostVariableValue.instance, true), new ManaCostsImpl<>("{X}")); ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter))); ability.addTarget(new TargetAnyTarget()); + ability.setCostAdjuster(KnollspineInvocationAdjuster.instance); this.addAbility(ability); } - @Override - public void adjustCosts(Ability ability, Game game) { - if (ability instanceof SimpleActivatedAbility) { - int xValue = ability.getManaCostsToPay().getX(); - for (Cost cost : ability.getCosts()) { - if (cost instanceof DiscardTargetCost) { - DiscardTargetCost discardCost = (DiscardTargetCost) cost; - discardCost.getTargets().clear(); - FilterCard adjustedFilter = filter.copy(); // don't use it directly, it's static!!!! - adjustedFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); - discardCost.addTarget(new TargetCardInHand(adjustedFilter)); - return; - } - } - } - } - private KnollspineInvocation(final KnollspineInvocation card) { super(card); } @@ -64,3 +48,23 @@ public final class KnollspineInvocation extends CardImpl { return new KnollspineInvocation(this); } } + +enum KnollspineInvocationAdjuster implements CostAdjuster { + instance; + + @Override + public void adjustCosts(Ability ability, Game game) { + int xValue = ability.getManaCostsToPay().getX(); + for (Cost cost : ability.getCosts()) { + if (!(cost instanceof DiscardTargetCost)) { + continue; + } + DiscardTargetCost discardCost = (DiscardTargetCost) cost; + discardCost.getTargets().clear(); + FilterCard adjustedFilter = new FilterCard("a card with converted mana cost X"); + adjustedFilter.add(new ConvertedManaCostPredicate(ComparisonType.EQUAL_TO, xValue)); + discardCost.addTarget(new TargetCardInHand(adjustedFilter)); + return; + } + } +} diff --git a/Mage.Sets/src/mage/cards/l/Lightsaber.java b/Mage.Sets/src/mage/cards/l/Lightsaber.java index 0b83f49328..e280ef9ba8 100644 --- a/Mage.Sets/src/mage/cards/l/Lightsaber.java +++ b/Mage.Sets/src/mage/cards/l/Lightsaber.java @@ -3,6 +3,7 @@ package mage.cards.l; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; @@ -11,15 +12,17 @@ import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.util.CardUtil; +import java.util.Objects; import java.util.UUID; /** - * * @author Styxo */ public final class Lightsaber extends CardImpl { @@ -29,25 +32,18 @@ public final class Lightsaber extends CardImpl { this.subtype.add(SubType.EQUIPMENT); // Equiped creature gets +1/+0 and has firsttrike - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 0))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT))); + this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(1, 0))); + this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect( + FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT + ).setText("and has first strike"))); // Equip 3 - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(3))); + Ability ability = new EquipAbility(3); + ability.setCostAdjuster(LightsaberAdjuster.instance); + this.addAbility(ability); // Lightsaber's equip ability costs {1} if it targets a Jedi or Sith. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("{this}'s equip ability costs {1} if it targets a Jedi or Sith"))); - - } - - @Override - public void adjustCosts(Ability ability, Game game) { - if (ability instanceof EquipAbility) { - Permanent targetCreature = game.getPermanent(ability.getTargets().getFirstTarget()); - if (targetCreature != null && (targetCreature.hasSubtype(SubType.SITH, game) || targetCreature.hasSubtype(SubType.JEDI, game))) { - CardUtil.increaseCost(ability, 1 - ability.getManaCostsToPay().convertedManaCost()); - } - } + this.addAbility(new SimpleStaticAbility(new InfoEffect("{this}'s equip ability costs {1} if it targets a Jedi or Sith"))); } private Lightsaber(final Lightsaber card) { @@ -59,3 +55,30 @@ public final class Lightsaber extends CardImpl { return new Lightsaber(this); } } + +enum LightsaberAdjuster implements CostAdjuster { + instance; + + @Override + public void adjustCosts(Ability ability, Game game) { + if (game.inCheckPlayableState()) { + if (CardUtil + .getAllPossibleTargets(ability, game) + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .noneMatch(permanent -> permanent.hasSubtype(SubType.SITH, game) + || permanent.hasSubtype(SubType.JEDI, game))) { + return; + } + } else { + Permanent permanent = game.getPermanent(ability.getFirstTarget()); + if (permanent == null || !(permanent.hasSubtype(SubType.SITH, game) + || permanent.hasSubtype(SubType.JEDI, game))) { + return; + } + } + ability.getCosts().clear(); + ability.addCost(new GenericManaCost(1)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MarathWillOfTheWild.java b/Mage.Sets/src/mage/cards/m/MarathWillOfTheWild.java index 3148026845..c62667f144 100644 --- a/Mage.Sets/src/mage/cards/m/MarathWillOfTheWild.java +++ b/Mage.Sets/src/mage/cards/m/MarathWillOfTheWild.java @@ -1,7 +1,6 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.Mode; @@ -22,10 +21,9 @@ import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; @@ -35,8 +33,9 @@ import mage.players.Player; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class MarathWillOfTheWild extends CardImpl { @@ -58,7 +57,7 @@ public final class MarathWillOfTheWild extends CardImpl { // {X}, Remove X +1/+1 counters from Marath: Choose one - Put X +1/+1 counters on target creature; effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(0), ManacostVariableValue.instance); effect.setText("Put X +1/+1 counters on target creature"); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}")); + Ability ability = new SimpleActivatedAbility(effect, new ManaCostsImpl("{X}")); ability.addCost(new MarathWillOfTheWildRemoveCountersCost()); ability.addTarget(new TargetCreaturePermanent()); @@ -83,24 +82,6 @@ public final class MarathWillOfTheWild extends CardImpl { this.addAbility(ability); } - @Override - public void adjustCosts(Ability ability, Game game) { - if (ability instanceof SimpleActivatedAbility && ability.getModes().size() == 3) { - Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); - if (sourcePermanent != null) { - int amount = sourcePermanent.getCounters(game).getCount(CounterType.P1P1); - if (amount > 0) { - for (VariableCost cost : ability.getManaCostsToPay().getVariableCosts()) { - if (cost instanceof VariableManaCost) { - ((VariableManaCost) cost).setMaxX(amount); - break; - } - } - } - } - } - } - private MarathWillOfTheWild(final MarathWillOfTheWild card) { super(card); } @@ -113,12 +94,12 @@ public final class MarathWillOfTheWild extends CardImpl { class MarathWillOfTheWildCreateTokenEffect extends OneShotEffect { - public MarathWillOfTheWildCreateTokenEffect() { + MarathWillOfTheWildCreateTokenEffect() { super(Outcome.PutCreatureInPlay); staticText = "create an X/X green Elemental creature token"; } - public MarathWillOfTheWildCreateTokenEffect(final MarathWillOfTheWildCreateTokenEffect effect) { + private MarathWillOfTheWildCreateTokenEffect(final MarathWillOfTheWildCreateTokenEffect effect) { super(effect); } @@ -144,12 +125,12 @@ class MarathWillOfTheWildCreateTokenEffect extends OneShotEffect { class MarathWillOfTheWildRemoveCountersCost extends CostImpl { - public MarathWillOfTheWildRemoveCountersCost() { + MarathWillOfTheWildRemoveCountersCost() { this.text = "Remove X +1/+1 counters from Marath"; } - public MarathWillOfTheWildRemoveCountersCost(MarathWillOfTheWildRemoveCountersCost cost) { + private MarathWillOfTheWildRemoveCountersCost(MarathWillOfTheWildRemoveCountersCost cost) { super(cost); } diff --git a/Mage.Sets/src/mage/cards/p/PrototypePortal.java b/Mage.Sets/src/mage/cards/p/PrototypePortal.java index 1d5be3b4d7..d69fb443b6 100644 --- a/Mage.Sets/src/mage/cards/p/PrototypePortal.java +++ b/Mage.Sets/src/mage/cards/p/PrototypePortal.java @@ -4,6 +4,7 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.VariableCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; @@ -35,11 +36,14 @@ public final class PrototypePortal extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // Imprint - When Prototype Portal enters the battlefield, you may exile an artifact card from your hand. - this.addAbility(new EntersBattlefieldTriggeredAbility(new PrototypePortalEffect(), true)); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new PrototypePortalEffect(), true, "Imprint — " + )); // {X}, {tap}: Create a token that's a copy of the exiled card. X is the converted mana cost of that card. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PrototypePortalCreateTokenEffect(), new ManaCostsImpl("{X}")); + Ability ability = new SimpleActivatedAbility(new PrototypePortalCreateTokenEffect(), new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); + ability.setCostAdjuster(PrototypePortalAdjuster.instance); this.addAbility(ability); } @@ -47,6 +51,15 @@ public final class PrototypePortal extends CardImpl { super(card); } + @Override + public PrototypePortal copy() { + return new PrototypePortal(this); + } +} + +enum PrototypePortalAdjuster implements CostAdjuster { + instance; + @Override public void adjustCosts(Ability ability, Game game) { Permanent card = game.getPermanent(ability.getSourceId()); @@ -66,21 +79,16 @@ public final class PrototypePortal extends CardImpl { } } } - - @Override - public PrototypePortal copy() { - return new PrototypePortal(this); - } } class PrototypePortalEffect extends OneShotEffect { - public PrototypePortalEffect() { + PrototypePortalEffect() { super(Outcome.Benefit); staticText = "exile an artifact card from your hand"; } - public PrototypePortalEffect(PrototypePortalEffect effect) { + private PrototypePortalEffect(PrototypePortalEffect effect) { super(effect); } @@ -115,12 +123,12 @@ class PrototypePortalEffect extends OneShotEffect { class PrototypePortalCreateTokenEffect extends OneShotEffect { - public PrototypePortalCreateTokenEffect() { + PrototypePortalCreateTokenEffect() { super(Outcome.PutCreatureInPlay); this.staticText = "Create a token that's a copy of the exiled card. X is the converted mana cost of that card"; } - public PrototypePortalCreateTokenEffect(final PrototypePortalCreateTokenEffect effect) { + private PrototypePortalCreateTokenEffect(final PrototypePortalCreateTokenEffect effect) { super(effect); } diff --git a/Mage.Sets/src/mage/cards/s/SkeletalScrying.java b/Mage.Sets/src/mage/cards/s/SkeletalScrying.java index 5e62e29fa2..37ac388198 100644 --- a/Mage.Sets/src/mage/cards/s/SkeletalScrying.java +++ b/Mage.Sets/src/mage/cards/s/SkeletalScrying.java @@ -1,114 +1,70 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.ExileFromGraveCost; -import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.ManacostVariableValue; -import mage.abilities.dynamicvalue.common.StaticValue; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.InfoEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; -import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class SkeletalScrying extends CardImpl { public SkeletalScrying(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{B}"); // As an additional cost to cast Skeletal Scrying, exile X cards from your graveyard. - Ability ability = new SimpleStaticAbility(Zone.ALL, new SkeletalScryingRuleEffect()); + Ability ability = new SimpleStaticAbility( + Zone.ALL, + new InfoEffect( + "as an additional cost to cast this spell, " + + "exile X cards from your graveyard" + )); ability.setRuleAtTheTop(true); this.addAbility(ability); - // You draw X cards and you lose X life. - this.getSpellAbility().addEffect(new SkeletalScryingEffect(ManacostVariableValue.instance)); + this.getSpellAbility().setCostAdjuster(SkeletalScryingAdjuster.instance); + // You draw X cards and you lose X life. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect( + ManacostVariableValue.instance + ).setText("you draw X cards")); + this.getSpellAbility().addEffect(new GainLifeEffect( + ManacostVariableValue.instance + ).concatBy("and")); } private SkeletalScrying(final SkeletalScrying card) { super(card); } - @Override - public void adjustCosts(Ability ability, Game game) { - int xValue = ability.getManaCostsToPay().getX(); - if (xValue > 0) { - ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(xValue, xValue, new FilterCard("cards from your graveyard")))); - } - } - @Override public SkeletalScrying copy() { return new SkeletalScrying(this); } } -class SkeletalScryingRuleEffect extends OneShotEffect { - - public SkeletalScryingRuleEffect() { - super(Outcome.Benefit); - this.staticText = "as an additional cost to cast this spell, exile X cards from your graveyard"; - } - - public SkeletalScryingRuleEffect(final SkeletalScryingRuleEffect effect) { - super(effect); - } +enum SkeletalScryingAdjuster implements CostAdjuster { + instance; + private static final FilterCard filter = new FilterCard("cards from your graveyard"); @Override - public SkeletalScryingRuleEffect copy() { - return new SkeletalScryingRuleEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } -} -class SkeletalScryingEffect extends OneShotEffect { - - protected DynamicValue amount; - - public SkeletalScryingEffect(int amount) { - this(StaticValue.get(amount)); - } - - public SkeletalScryingEffect(DynamicValue amount) { - super(Outcome.Neutral); - this.amount = amount.copy(); - staticText = "You draw " + amount + " cards and you lose " + amount + " life"; - } - - public SkeletalScryingEffect(final SkeletalScryingEffect effect) { - super(effect); - this.amount = effect.amount; - } - - @Override - public SkeletalScryingEffect copy() { - return new SkeletalScryingEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if ( controller != null ) { - controller.drawCards(amount.calculate(game, source, this), source, game); - controller.loseLife(amount.calculate(game, source, this), game, source, false); - return true; - } - return false; + public void adjustCosts(Ability ability, Game game) { + int xValue = ability.getManaCostsToPay().getX(); + if (xValue > 0) { + ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(xValue, xValue, filter))); + } } } diff --git a/Mage.Sets/src/mage/cards/s/SoulFoundry.java b/Mage.Sets/src/mage/cards/s/SoulFoundry.java index b6b3287821..1ff9fb7213 100644 --- a/Mage.Sets/src/mage/cards/s/SoulFoundry.java +++ b/Mage.Sets/src/mage/cards/s/SoulFoundry.java @@ -1,10 +1,9 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.VariableCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; @@ -26,8 +25,9 @@ import mage.target.TargetCard; import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class SoulFoundry extends CardImpl { @@ -36,13 +36,15 @@ public final class SoulFoundry extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // Imprint - When Soul Foundry enters the battlefield, you may exile a creature card from your hand. - this.addAbility(new EntersBattlefieldTriggeredAbility(new SoulFoundryImprintEffect(), true, "Imprint — ")); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SoulFoundryImprintEffect(), true, "Imprint — " + )); // {X}, {T}: Create a token that's a copy of the exiled card. X is the converted mana cost of that card. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SoulFoundryEffect(), new ManaCostsImpl("{X}")); + Ability ability = new SimpleActivatedAbility(new SoulFoundryEffect(), new ManaCostsImpl("{X}")); ability.addCost(new TapSourceCost()); + ability.setCostAdjuster(SoulFoundryAdjuster.instance); this.addAbility(ability); - } private SoulFoundry(final SoulFoundry card) { @@ -50,31 +52,33 @@ public final class SoulFoundry extends CardImpl { } @Override - public void adjustCosts(Ability ability, Game game) { - if (ability instanceof SimpleActivatedAbility) { - Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); - if (sourcePermanent != null) { - if (!sourcePermanent.getImprinted().isEmpty()) { - Card imprinted = game.getCard(sourcePermanent.getImprinted().get(0)); - if (imprinted != null) { - ability.getManaCostsToPay().clear(); - ability.getManaCostsToPay().add(0, new GenericManaCost(imprinted.getConvertedManaCost())); - } - } - } + public SoulFoundry copy() { + return new SoulFoundry(this); + } +} - // no {X} anymore as we already have imprinted the card with defined manacost - for (ManaCost cost : ability.getManaCostsToPay()) { - if (cost instanceof VariableCost) { - cost.setPaid(); +enum SoulFoundryAdjuster implements CostAdjuster { + instance; + + @Override + public void adjustCosts(Ability ability, Game game) { + Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); + if (sourcePermanent != null) { + if (!sourcePermanent.getImprinted().isEmpty()) { + Card imprinted = game.getCard(sourcePermanent.getImprinted().get(0)); + if (imprinted != null) { + ability.getManaCostsToPay().clear(); + ability.getManaCostsToPay().add(0, new GenericManaCost(imprinted.getConvertedManaCost())); } } } - } - @Override - public SoulFoundry copy() { - return new SoulFoundry(this); + // no {X} anymore as we already have imprinted the card with defined manacost + for (ManaCost cost : ability.getManaCostsToPay()) { + if (cost instanceof VariableCost) { + cost.setPaid(); + } + } } } @@ -86,12 +90,12 @@ class SoulFoundryImprintEffect extends OneShotEffect { filter.add(CardType.CREATURE.getPredicate()); } - public SoulFoundryImprintEffect() { + SoulFoundryImprintEffect() { super(Outcome.Neutral); staticText = "you may exile a creature card from your hand"; } - public SoulFoundryImprintEffect(SoulFoundryImprintEffect effect) { + private SoulFoundryImprintEffect(SoulFoundryImprintEffect effect) { super(effect); } @@ -128,12 +132,12 @@ class SoulFoundryImprintEffect extends OneShotEffect { class SoulFoundryEffect extends OneShotEffect { - public SoulFoundryEffect() { + SoulFoundryEffect() { super(Outcome.PutCreatureInPlay); this.staticText = "Create a token that's a copy of the exiled card. X is the converted mana cost of that card"; } - public SoulFoundryEffect(final SoulFoundryEffect effect) { + private SoulFoundryEffect(final SoulFoundryEffect effect) { super(effect); } diff --git a/Mage.Sets/src/mage/cards/v/VoodooDoll.java b/Mage.Sets/src/mage/cards/v/VoodooDoll.java index 7b43e5dced..5cbc1565b8 100644 --- a/Mage.Sets/src/mage/cards/v/VoodooDoll.java +++ b/Mage.Sets/src/mage/cards/v/VoodooDoll.java @@ -1,18 +1,16 @@ - package mage.cards.v; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.SourceTappedCondition; -import mage.abilities.costs.VariableCost; +import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.costs.mana.VariableManaCost; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.DamageTargetEffect; @@ -22,51 +20,44 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TargetController; -import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author L_J */ public final class VoodooDoll extends CardImpl { public VoodooDoll(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); // At the beginning of your upkeep, put a pin counter on Voodoo Doll. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.PIN.createInstance()), TargetController.YOU, false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new AddCountersSourceEffect(CounterType.PIN.createInstance()), TargetController.YOU, false + )); + // At the beginning of your end step, if Voodoo Doll is untapped, destroy Voodoo Doll and it deals damage to you equal to the number of pin counters on it. - Ability ability = new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new DestroySourceEffect(), TargetController.YOU, - new InvertCondition(SourceTappedCondition.instance), false); + Ability ability = new ConditionalInterveningIfTriggeredAbility( + new BeginningOfEndStepTriggeredAbility( + new DestroySourceEffect(), TargetController.YOU, false + ), new InvertCondition(SourceTappedCondition.instance), "At the beginning of your end step, " + + "if {this} is untapped, destroy {this} and it deals damage to you equal to the number of pin counters on it." + ); ability.addEffect(new DamageControllerEffect(new CountersSourceCount(CounterType.PIN))); this.addAbility(ability); - // {X}{X}, {T}: Voodoo Doll deals damage equal to the number of pin counters on it to any target. X is the number of pin counters on Voodoo Doll. - Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.PIN)), new ManaCostsImpl("{X}{X}")); - ability2.addCost(new TapSourceCost()); - ability2.addTarget(new TargetAnyTarget()); - for (VariableCost cost : ability2.getManaCosts().getVariableCosts()) { - if (cost instanceof VariableManaCost) { - ((VariableManaCost) cost).setMaxX(0); - break; - } - } - this.addAbility(ability2); - } - @Override - public void adjustCosts(Ability ability, Game game) { - if (ability instanceof SimpleActivatedAbility) { - Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); - if (sourcePermanent != null) { - int pin = sourcePermanent.getCounters(game).getCount(CounterType.PIN); - ability.getManaCostsToPay().clear(); - ability.getManaCostsToPay().add(0, new GenericManaCost(pin * 2)); - } - } + // {X}{X}, {T}: Voodoo Doll deals damage equal to the number of pin counters on it to any target. X is the number of pin counters on Voodoo Doll. + ability = new SimpleActivatedAbility( + new DamageTargetEffect(new CountersSourceCount(CounterType.PIN)), new ManaCostsImpl("{X}{X}") + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetAnyTarget()); + ability.setCostAdjuster(VoodooDollAdjuster.instance); + this.addAbility(ability); } private VoodooDoll(final VoodooDoll card) { @@ -78,3 +69,17 @@ public final class VoodooDoll extends CardImpl { return new VoodooDoll(this); } } + +enum VoodooDollAdjuster implements CostAdjuster { + instance; + + @Override + public void adjustCosts(Ability ability, Game game) { + Permanent sourcePermanent = game.getPermanent(ability.getSourceId()); + if (sourcePermanent != null) { + int pin = sourcePermanent.getCounters(game).getCount(CounterType.PIN); + ability.getManaCostsToPay().clear(); + ability.getManaCostsToPay().add(0, new GenericManaCost(pin * 2)); + } + } +}