diff --git a/Mage.Sets/src/mage/cards/a/AryelKnightOfWindgrace.java b/Mage.Sets/src/mage/cards/a/AryelKnightOfWindgrace.java index 2b6be379b1..5c493e3317 100644 --- a/Mage.Sets/src/mage/cards/a/AryelKnightOfWindgrace.java +++ b/Mage.Sets/src/mage/cards/a/AryelKnightOfWindgrace.java @@ -1,12 +1,12 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCost; import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -15,11 +15,7 @@ import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.ComparisonType; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; @@ -30,8 +26,9 @@ import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.TargetAdjuster; +import java.util.UUID; + /** - * * @author jack-the-BOSS */ public final class AryelKnightOfWindgrace extends CardImpl { @@ -83,7 +80,7 @@ class AryelTapXTargetCost extends VariableCostImpl { } public AryelTapXTargetCost() { - super("controlled untapped Knights you would like to tap"); + super(VariableCostType.NORMAL, "controlled untapped Knights you would like to tap"); this.text = "Tap X untapped Knights you control"; } diff --git a/Mage.Sets/src/mage/cards/b/BlazingShoal.java b/Mage.Sets/src/mage/cards/b/BlazingShoal.java index 38cacbfced..c460a3d722 100644 --- a/Mage.Sets/src/mage/cards/b/BlazingShoal.java +++ b/Mage.Sets/src/mage/cards/b/BlazingShoal.java @@ -1,7 +1,5 @@ - package mage.cards.b; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.costs.AlternativeCostSourceAbility; import mage.abilities.costs.common.ExileFromHandCost; @@ -20,14 +18,15 @@ import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.common.TargetCardInHand; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class BlazingShoal extends CardImpl { public BlazingShoal(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}{R}"); this.subtype.add(SubType.ARCANE); @@ -35,7 +34,7 @@ public final class BlazingShoal extends CardImpl { FilterOwnedCard filter = new FilterOwnedCard("a red card with mana value X from your hand"); filter.add(new ColorPredicate(ObjectColor.RED)); filter.add(Predicates.not(new CardIdPredicate(this.getId()))); // the exile cost can never be paid with the card itself - this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter),true))); + this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter), true))); // Target creature gets +X/+0 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(ExileFromHandCostCardConvertedMana.instance, StaticValue.get(0), Duration.EndOfTurn)); diff --git a/Mage.Sets/src/mage/cards/c/ChamberSentry.java b/Mage.Sets/src/mage/cards/c/ChamberSentry.java index da52d4c0c8..02efeee2f8 100644 --- a/Mage.Sets/src/mage/cards/c/ChamberSentry.java +++ b/Mage.Sets/src/mage/cards/c/ChamberSentry.java @@ -1,12 +1,12 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -26,8 +26,9 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author jmharmon */ public final class ChamberSentry extends CardImpl { @@ -69,7 +70,7 @@ public final class ChamberSentry extends CardImpl { class ChamberSentryRemoveVariableCountersSourceCost extends VariableCostImpl { protected int minimalCountersToPay = 0; - private String counterName; + private final String counterName; public ChamberSentryRemoveVariableCountersSourceCost(Counter counter) { this(counter, 0); @@ -84,7 +85,7 @@ class ChamberSentryRemoveVariableCountersSourceCost extends VariableCostImpl { } public ChamberSentryRemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay, String text) { - super(counter.getName() + " counters to remove"); + super(VariableCostType.NORMAL, counter.getName() + " counters to remove"); this.minimalCountersToPay = minimalCountersToPay; this.counterName = counter.getName(); if (text == null || text.isEmpty()) { diff --git a/Mage.Sets/src/mage/cards/c/ChanneledForce.java b/Mage.Sets/src/mage/cards/c/ChanneledForce.java index 508bf069f3..7e933d2919 100644 --- a/Mage.Sets/src/mage/cards/c/ChanneledForce.java +++ b/Mage.Sets/src/mage/cards/c/ChanneledForce.java @@ -25,7 +25,7 @@ public final class ChanneledForce extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{R}"); // As an additional cost to cast this spell, discard X cards. - this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, false)); + this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, true)); // Target player draws X cards. Channeled Force deals X damage to up to one target creature or planeswalker. this.getSpellAbility().addEffect(new ChanneledForceEffect()); diff --git a/Mage.Sets/src/mage/cards/c/CopperLeafAngel.java b/Mage.Sets/src/mage/cards/c/CopperLeafAngel.java index f1edd7c73a..adb0608707 100644 --- a/Mage.Sets/src/mage/cards/c/CopperLeafAngel.java +++ b/Mage.Sets/src/mage/cards/c/CopperLeafAngel.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -18,25 +16,26 @@ import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterControlledLandPermanent; +import java.util.UUID; + /** - * * @author Rene - bugisemail at gmail.com */ public final class CopperLeafAngel extends CardImpl { public CopperLeafAngel(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); - + this.subtype.add(SubType.ANGEL); this.power = new MageInt(2); this.toughness = new MageInt(2); // Flying this.addAbility(FlyingAbility.getInstance()); - + // {tap}, Sacrifice X lands: Put X +1/+1 counters on Copper-Leaf Angel. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(),GetXValue.instance, false), new TapSourceCost()); - ability.addCost(new SacrificeXTargetCost(new FilterControlledLandPermanent("lands"), false)); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(), GetXValue.instance, false), new TapSourceCost()); + ability.addCost(new SacrificeXTargetCost(new FilterControlledLandPermanent("lands"))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CrystalShard.java b/Mage.Sets/src/mage/cards/c/CrystalShard.java index d8d1427df3..a0a09fec63 100644 --- a/Mage.Sets/src/mage/cards/c/CrystalShard.java +++ b/Mage.Sets/src/mage/cards/c/CrystalShard.java @@ -18,6 +18,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.util.ManaUtil; import java.util.UUID; @@ -79,7 +80,7 @@ class CrystalShardEffect extends OneShotEffect { if (player == null) { return true; } - Cost cost = new GenericManaCost(1); + Cost cost = ManaUtil.createManaCost(1, false); String message = "Pay {1}? (Otherwise " + targetCreature.getName() + " will be returned to its owner's hand)"; if (player.chooseUse(Outcome.Benefit, message, source, game)) { cost.pay(source, game, source, targetCreature.getControllerId(), false, null); diff --git a/Mage.Sets/src/mage/cards/d/DevastatingDreams.java b/Mage.Sets/src/mage/cards/d/DevastatingDreams.java index 14096c1d6d..6d2ef8887c 100644 --- a/Mage.Sets/src/mage/cards/d/DevastatingDreams.java +++ b/Mage.Sets/src/mage/cards/d/DevastatingDreams.java @@ -1,10 +1,9 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.common.DamageAllEffect; @@ -19,21 +18,22 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInHand; +import java.util.UUID; + /** - * * @author emerald000 */ public final class DevastatingDreams extends CardImpl { public DevastatingDreams(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}{R}"); // As an additional cost to cast Devastating Dreams, discard X cards at random. this.getSpellAbility().addCost(new DevastatingDreamsAdditionalCost()); - + // Each player sacrifices X lands. this.getSpellAbility().addEffect(new SacrificeAllEffect(GetXValue.instance, new FilterControlledLandPermanent("lands"))); - + // Devastating Dreams deals X damage to each creature. this.getSpellAbility().addEffect(new DamageAllEffect(GetXValue.instance, new FilterCreaturePermanent())); } @@ -51,7 +51,7 @@ public final class DevastatingDreams extends CardImpl { class DevastatingDreamsAdditionalCost extends VariableCostImpl { DevastatingDreamsAdditionalCost() { - super("cards to discard randomly"); + super(VariableCostType.ADDITIONAL, "cards to discard randomly"); this.text = "as an additional cost to cast this spell, discard X cards at random"; } diff --git a/Mage.Sets/src/mage/cards/e/EverythingamajigC.java b/Mage.Sets/src/mage/cards/e/EverythingamajigC.java index 47998b887a..1e739b37e7 100644 --- a/Mage.Sets/src/mage/cards/e/EverythingamajigC.java +++ b/Mage.Sets/src/mage/cards/e/EverythingamajigC.java @@ -5,6 +5,7 @@ import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.VariableManaCost; @@ -47,7 +48,7 @@ public final class EverythingamajigC extends CardImpl { // Chimeric Staff // X: Everythingamajig becomes an X/X Construct artifact creature until end of turn. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChimericStaffEffect(), new VariableManaCost())); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChimericStaffEffect(), new VariableManaCost(VariableCostType.NORMAL))); } private EverythingamajigC(final EverythingamajigC card) { diff --git a/Mage.Sets/src/mage/cards/e/ExtusOriqOverlord.java b/Mage.Sets/src/mage/cards/e/ExtusOriqOverlord.java index 72c64a97f2..e762a53d39 100644 --- a/Mage.Sets/src/mage/cards/e/ExtusOriqOverlord.java +++ b/Mage.Sets/src/mage/cards/e/ExtusOriqOverlord.java @@ -63,7 +63,7 @@ public final class ExtusOriqOverlord extends ModalDoubleFacesCard { // Awaken the Blood Avatar // Sorcery // As an additional cost to cast this spell, you may sacrifice any number of creatures. This spell costs {2} less to cast for each creature sacrificed this way. - Cost cost = new SacrificeXTargetCost(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT); + Cost cost = new SacrificeXTargetCost(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT, true); cost.setText("As an additional cost to cast this spell, you may sacrifice any number of creatures. " + "This spell costs {2} less to cast for each creature sacrificed this way"); this.getRightHalfCard().getSpellAbility().addCost(cost); diff --git a/Mage.Sets/src/mage/cards/f/Firestorm.java b/Mage.Sets/src/mage/cards/f/Firestorm.java index c00ee422f8..47d626817f 100644 --- a/Mage.Sets/src/mage/cards/f/Firestorm.java +++ b/Mage.Sets/src/mage/cards/f/Firestorm.java @@ -27,7 +27,7 @@ public final class Firestorm extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); // As an additional cost to cast Firestorm, discard X cards. - this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), false)); + this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true)); // Firestorm deals X damage to each of X target creatures and/or players. this.getSpellAbility().addEffect(new FirestormEffect()); diff --git a/Mage.Sets/src/mage/cards/g/GlacianPowerstoneEngineer.java b/Mage.Sets/src/mage/cards/g/GlacianPowerstoneEngineer.java index 77d8237389..fd5cdfc454 100644 --- a/Mage.Sets/src/mage/cards/g/GlacianPowerstoneEngineer.java +++ b/Mage.Sets/src/mage/cards/g/GlacianPowerstoneEngineer.java @@ -5,6 +5,7 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.effects.OneShotEffect; @@ -114,7 +115,7 @@ class GlacianPowerstoneEngineerCost extends VariableCostImpl { } GlacianPowerstoneEngineerCost() { - super("controlled untapped artifacts you would like to tap"); + super(VariableCostType.NORMAL, "controlled untapped artifacts you would like to tap"); this.text = "Tap X untapped artifacts you control"; } diff --git a/Mage.Sets/src/mage/cards/h/HauntingMisery.java b/Mage.Sets/src/mage/cards/h/HauntingMisery.java index 8362c9de65..aac9d2fef1 100644 --- a/Mage.Sets/src/mage/cards/h/HauntingMisery.java +++ b/Mage.Sets/src/mage/cards/h/HauntingMisery.java @@ -1,6 +1,5 @@ package mage.cards.h; -import java.util.UUID; import mage.abilities.costs.common.ExileXFromYourGraveCost; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.common.DamageTargetEffect; @@ -10,8 +9,9 @@ import mage.constants.CardType; import mage.filter.StaticFilters; import mage.target.common.TargetPlayerOrPlaneswalker; +import java.util.UUID; + /** - * * @author markedagain */ public final class HauntingMisery extends CardImpl { @@ -21,6 +21,7 @@ public final class HauntingMisery extends CardImpl { // As an additional cost to cast Haunting Misery, exile X creature cards from your graveyard. this.getSpellAbility().addCost(new ExileXFromYourGraveCost(StaticFilters.FILTER_CARD_CREATURE)); + // Haunting Misery deals X damage to target player. this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); this.getSpellAbility().addEffect(new DamageTargetEffect(GetXValue.instance)); diff --git a/Mage.Sets/src/mage/cards/h/HelmOfObedience.java b/Mage.Sets/src/mage/cards/h/HelmOfObedience.java index a925bb5a9f..b9ea7eea0d 100644 --- a/Mage.Sets/src/mage/cards/h/HelmOfObedience.java +++ b/Mage.Sets/src/mage/cards/h/HelmOfObedience.java @@ -2,6 +2,7 @@ package mage.cards.h; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.dynamicvalue.common.ManacostVariableValue; @@ -28,7 +29,7 @@ public final class HelmOfObedience extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // {X}, {T}: Target opponent puts cards from the top of their library into their graveyard until a creature card or X cards are put into that graveyard this way, whichever comes first. If a creature card is put into that graveyard this way, sacrifice Helm of Obedience and put that card onto the battlefield under your control. X can't be 0. - VariableManaCost xCosts = new VariableManaCost(); + VariableManaCost xCosts = new VariableManaCost(VariableCostType.NORMAL); xCosts.setMinX(1); Ability ability = new SimpleActivatedAbility(new HelmOfObedienceEffect(), xCosts); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/i/InfernalHarvest.java b/Mage.Sets/src/mage/cards/i/InfernalHarvest.java index 2e46cd9521..28a3e0ce38 100644 --- a/Mage.Sets/src/mage/cards/i/InfernalHarvest.java +++ b/Mage.Sets/src/mage/cards/i/InfernalHarvest.java @@ -4,6 +4,7 @@ import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.VariableCostType; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.common.DamageMultiEffect; import mage.cards.CardImpl; @@ -33,7 +34,7 @@ public final class InfernalHarvest extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}"); // As an additional cost to cast Infernal Harvest, return X Swamps you control to their owner's hand. - this.getSpellAbility().addCost(new InfernalHarvestVariableCost()); + this.getSpellAbility().addCost(new InfernalHarvestAdditionalCost()); // Infernal Harvest deals X damage divided as you choose among any number of target creatures. this.getSpellAbility().addEffect(new DamageMultiEffect(GetXValue.instance)); @@ -50,22 +51,22 @@ public final class InfernalHarvest extends CardImpl { } } -class InfernalHarvestVariableCost extends VariableCostImpl { +class InfernalHarvestAdditionalCost extends VariableCostImpl { private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.SWAMP); - InfernalHarvestVariableCost() { - super("Swamps to return"); + InfernalHarvestAdditionalCost() { + super(VariableCostType.ADDITIONAL, "Swamps to return"); this.text = "return " + xText + " Swamps you control to their owner's hand"; } - private InfernalHarvestVariableCost(final InfernalHarvestVariableCost cost) { + private InfernalHarvestAdditionalCost(final InfernalHarvestAdditionalCost cost) { super(cost); } @Override - public InfernalHarvestVariableCost copy() { - return new InfernalHarvestVariableCost(this); + public InfernalHarvestAdditionalCost copy() { + return new InfernalHarvestAdditionalCost(this); } @Override diff --git a/Mage.Sets/src/mage/cards/i/InsidiousDreams.java b/Mage.Sets/src/mage/cards/i/InsidiousDreams.java index d1e15ea53b..af18bb4ef8 100644 --- a/Mage.Sets/src/mage/cards/i/InsidiousDreams.java +++ b/Mage.Sets/src/mage/cards/i/InsidiousDreams.java @@ -1,19 +1,11 @@ - package mage.cards.i; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.costs.Cost; -import mage.abilities.costs.VariableCostImpl; -import mage.abilities.costs.common.DiscardTargetCost; +import mage.abilities.costs.common.DiscardXTargetCost; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; @@ -21,20 +13,20 @@ import mage.filter.FilterCard; import mage.game.Game; import mage.players.Player; import mage.target.TargetCard; -import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author spjspj */ public final class InsidiousDreams extends CardImpl { public InsidiousDreams(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}"); // As an additional cost to cast Insidious Dreams, discard X cards. - this.getSpellAbility().addCost(new InsidiousDreamsAdditionalCost()); + this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true)); // Search your library for X cards. Then shuffle your library and put those cards on top of it in any order. this.getSpellAbility().addEffect(new InsidiousDreamsEffect()); @@ -108,35 +100,3 @@ class InsidiousDreamsEffect extends OneShotEffect { return false; } } - -class InsidiousDreamsAdditionalCost extends VariableCostImpl { - - InsidiousDreamsAdditionalCost() { - super("cards to discard"); - this.text = "discard X cards"; - } - - InsidiousDreamsAdditionalCost(final InsidiousDreamsAdditionalCost cost) { - super(cost); - } - - @Override - public InsidiousDreamsAdditionalCost copy() { - return new InsidiousDreamsAdditionalCost(this); - } - - @Override - public int getMaxValue(Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - return controller.getHand().size(); - } - return 0; - } - - @Override - public Cost getFixedCostsFromAnnouncedValue(int xValue) { - TargetCardInHand target = new TargetCardInHand(xValue, new FilterCard()); - return new DiscardTargetCost(target); - } -} diff --git a/Mage.Sets/src/mage/cards/l/LiquidFire.java b/Mage.Sets/src/mage/cards/l/LiquidFire.java index fa1db49fe0..f6746b2468 100644 --- a/Mage.Sets/src/mage/cards/l/LiquidFire.java +++ b/Mage.Sets/src/mage/cards/l/LiquidFire.java @@ -3,6 +3,7 @@ package mage.cards.l; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.VariableCostType; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.Effect; @@ -27,7 +28,7 @@ public final class LiquidFire extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}"); // As an additional cost to cast Liquid Fire, choose a number between 0 and 5. - this.getSpellAbility().addCost(new LiquidFireCost()); + this.getSpellAbility().addCost(new LiquidFireAdditionalCost()); // Liquid Fire deals X damage to target creature and 5 minus X damage to that creature's controller, where X is the chosen number. DynamicValue choiceValue = GetXValue.instance; this.getSpellAbility().addTarget(new TargetCreaturePermanent()); @@ -79,30 +80,31 @@ public final class LiquidFire extends CardImpl { return new LiquidFireEffect(this); } } - - static class LiquidFireCost extends VariableCostImpl { - public LiquidFireCost() { - super("Choose a Number"); - this.text = "as an additional cost to cast this spell, choose a number between 0 and 5"; - } - - public LiquidFireCost(final LiquidFireCost cost) { - super(cost); - } - - @Override - public Cost copy() { - return new LiquidFireCost(this); - } - - @Override - public Cost getFixedCostsFromAnnouncedValue(int xValue) { - return null; - } - - @Override - public int getMaxValue(Ability source, Game game) { - return 5; - } - } } + +class LiquidFireAdditionalCost extends VariableCostImpl { + + public LiquidFireAdditionalCost() { + super(VariableCostType.ADDITIONAL, "Choose a Number"); + this.text = "as an additional cost to cast this spell, choose a number between 0 and 5"; + } + + public LiquidFireAdditionalCost(final LiquidFireAdditionalCost cost) { + super(cost); + } + + @Override + public Cost copy() { + return new LiquidFireAdditionalCost(this); + } + + @Override + public Cost getFixedCostsFromAnnouncedValue(int xValue) { + return null; + } + + @Override + public int getMaxValue(Ability source, Game game) { + return 5; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MartyrOfBones.java b/Mage.Sets/src/mage/cards/m/MartyrOfBones.java index fd03d562ce..c469930c10 100644 --- a/Mage.Sets/src/mage/cards/m/MartyrOfBones.java +++ b/Mage.Sets/src/mage/cards/m/MartyrOfBones.java @@ -7,6 +7,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCost; import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.RevealTargetFromHandCost; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.GenericManaCost; @@ -84,7 +85,7 @@ class RevealVariableBlackCardsFromHandCost extends VariableCostImpl { } RevealVariableBlackCardsFromHandCost() { - super("black cards to reveal"); + super(VariableCostType.NORMAL, "black cards to reveal"); this.text = "Reveal " + xText + " black cards from {this}"; } diff --git a/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java b/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java index 0cc38eac76..b61b910d7f 100644 --- a/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java +++ b/Mage.Sets/src/mage/cards/m/MerchantsDockhand.java @@ -1,25 +1,20 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.*; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterControlledArtifactPermanent; @@ -29,8 +24,9 @@ import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetControlledPermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class MerchantsDockhand extends CardImpl { @@ -118,7 +114,7 @@ class TapXTargetCost extends VariableCostImpl { } public TapXTargetCost() { - super("controlled untapped artifacts you would like to tap"); + super(VariableCostType.NORMAL, "controlled untapped artifacts you would like to tap"); this.text = "Tap X untapped artifacts you control"; } diff --git a/Mage.Sets/src/mage/cards/m/MirrorEntity.java b/Mage.Sets/src/mage/cards/m/MirrorEntity.java index b4a1f25e68..2e616b5b63 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorEntity.java +++ b/Mage.Sets/src/mage/cards/m/MirrorEntity.java @@ -4,6 +4,7 @@ import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.ContinuousEffectImpl; @@ -38,7 +39,7 @@ public final class MirrorEntity extends CardImpl { Ability ability = new SimpleActivatedAbility(new SetPowerToughnessAllEffect( ManacostVariableValue.REGULAR, ManacostVariableValue.REGULAR, Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES, true - ).setText("Until end of turn, creatures you control have base power and toughness X/X"), new VariableManaCost()); + ).setText("Until end of turn, creatures you control have base power and toughness X/X"), new VariableManaCost(VariableCostType.NORMAL)); ability.addEffect(new MirrorEntityEffect()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NahirisWrath.java b/Mage.Sets/src/mage/cards/n/NahirisWrath.java index eb5f70a0cb..eae4f92b51 100644 --- a/Mage.Sets/src/mage/cards/n/NahirisWrath.java +++ b/Mage.Sets/src/mage/cards/n/NahirisWrath.java @@ -1,11 +1,8 @@ - package mage.cards.n; import mage.abilities.Ability; -import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCost; -import mage.abilities.costs.VariableCostImpl; -import mage.abilities.costs.common.DiscardTargetCost; +import mage.abilities.costs.common.DiscardXTargetCost; import mage.abilities.dynamicvalue.common.DiscardCostCardManaValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; @@ -15,8 +12,6 @@ import mage.constants.CardType; import mage.filter.FilterCard; import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; import mage.game.Game; -import mage.players.Player; -import mage.target.common.TargetCardInHand; import mage.target.common.TargetCreatureOrPlaneswalker; import mage.target.targetadjustment.TargetAdjuster; @@ -31,7 +26,7 @@ public final class NahirisWrath extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); // As an additional cost to cast Nahiri's Wrath, discard X cards. - this.getSpellAbility().addCost(new NahirisWrathAdditionalCost()); + this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true)); // Nahiri's Wrath deals damage equal to the total converted mana cost of the discarded cards to each of up to X target creatures and/or planeswalkers. Effect effect = new DamageTargetEffect(DiscardCostCardManaValue.instance); @@ -58,7 +53,7 @@ enum NahirisWrathAdjuster implements TargetAdjuster { ability.getTargets().clear(); int numTargets = 0; for (VariableCost cost : ability.getCosts().getVariableCosts()) { - if (cost instanceof NahirisWrathAdditionalCost) { + if (cost instanceof DiscardXTargetCost) { numTargets = cost.getAmount(); break; } @@ -67,36 +62,4 @@ enum NahirisWrathAdjuster implements TargetAdjuster { ability.addTarget(new TargetCreatureOrPlaneswalker(0, numTargets, new FilterCreatureOrPlaneswalkerPermanent(), false)); } } -} - -class NahirisWrathAdditionalCost extends VariableCostImpl { - - NahirisWrathAdditionalCost() { - super("cards to discard"); - this.text = "discard X cards"; - } - - NahirisWrathAdditionalCost(final NahirisWrathAdditionalCost cost) { - super(cost); - } - - @Override - public NahirisWrathAdditionalCost copy() { - return new NahirisWrathAdditionalCost(this); - } - - @Override - public int getMaxValue(Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - return controller.getHand().size(); - } - return 0; - } - - @Override - public Cost getFixedCostsFromAnnouncedValue(int xValue) { - TargetCardInHand target = new TargetCardInHand(xValue, new FilterCard("cards to discard")); - return new DiscardTargetCost(target); - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/n/NostalgicDreams.java b/Mage.Sets/src/mage/cards/n/NostalgicDreams.java index 6d9aeed918..695230231f 100644 --- a/Mage.Sets/src/mage/cards/n/NostalgicDreams.java +++ b/Mage.Sets/src/mage/cards/n/NostalgicDreams.java @@ -26,7 +26,7 @@ public final class NostalgicDreams extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}{G}"); // As an additional cost to cast Nostalgic Dreams, discard X cards. - this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), false)); + this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true)); // Return X target cards from your graveyard to your hand. Effect effect = new ReturnFromGraveyardToHandTargetEffect(); diff --git a/Mage.Sets/src/mage/cards/p/Painbringer.java b/Mage.Sets/src/mage/cards/p/Painbringer.java index 7a21225f43..1ad9beda52 100644 --- a/Mage.Sets/src/mage/cards/p/Painbringer.java +++ b/Mage.Sets/src/mage/cards/p/Painbringer.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -12,29 +10,30 @@ import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.dynamicvalue.common.SignInversionDynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostTargetEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.FilterCard; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class Painbringer extends CardImpl { public Painbringer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); - + this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.MINION); this.power = new MageInt(1); this.toughness = new MageInt(1); - // {tap}, Exile any number of cards from your graveyard: Target creature gets -X/-X until end of turn, where X is the number of cards exiled this way. + // {T}, Exile any number of cards from your graveyard: Target creature gets -X/-X until end of turn, where X is the number of cards exiled this way. DynamicValue X = new SignInversionDynamicValue(GetXValue.instance); Effect effect = new BoostTargetEffect(X, X, Duration.EndOfTurn); effect.setText("Target creature gets -X/-X until end of turn, where X is the number of cards exiled this way"); @@ -42,7 +41,7 @@ public final class Painbringer extends CardImpl { ability.addCost(new ExileXFromYourGraveCost(new FilterCard("any number of cards from your graveyard"))); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); - + } private Painbringer(final Painbringer card) { diff --git a/Mage.Sets/src/mage/cards/p/PanopticMirror.java b/Mage.Sets/src/mage/cards/p/PanopticMirror.java index ee1aabaccf..34e7bc91e8 100644 --- a/Mage.Sets/src/mage/cards/p/PanopticMirror.java +++ b/Mage.Sets/src/mage/cards/p/PanopticMirror.java @@ -4,6 +4,7 @@ import mage.ApprovingObject; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.effects.OneShotEffect; @@ -30,7 +31,7 @@ public final class PanopticMirror extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); // Imprint - {X}, {tap}: You may exile an instant or sorcery card with converted mana cost X from your hand. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PanopticMirrorExileEffect(), new VariableManaCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PanopticMirrorExileEffect(), new VariableManaCost(VariableCostType.NORMAL)); ability.addCost(new TapSourceCost()); this.addAbility(ability.setAbilityWord(AbilityWord.IMPRINT)); // At the beginning of your upkeep, you may copy a card exiled with Panoptic Mirror. If you do, you may cast the copy without paying its mana cost. diff --git a/Mage.Sets/src/mage/cards/p/PerniciousDeed.java b/Mage.Sets/src/mage/cards/p/PerniciousDeed.java index a84867f98a..e389e9b1c8 100644 --- a/Mage.Sets/src/mage/cards/p/PerniciousDeed.java +++ b/Mage.Sets/src/mage/cards/p/PerniciousDeed.java @@ -1,8 +1,8 @@ package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.effects.OneShotEffect; @@ -18,6 +18,8 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; +import java.util.UUID; + /** * @author Plopman */ @@ -27,7 +29,7 @@ public final class PerniciousDeed extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{G}"); // {X}, Sacrifice Pernicious Deed: Destroy each artifact, creature, and enchantment with converted mana cost X or less. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PerniciousDeedEffect(), new VariableManaCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PerniciousDeedEffect(), new VariableManaCost(VariableCostType.NORMAL)); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RestlessDreams.java b/Mage.Sets/src/mage/cards/r/RestlessDreams.java index c7246da6d5..c24e7fb174 100644 --- a/Mage.Sets/src/mage/cards/r/RestlessDreams.java +++ b/Mage.Sets/src/mage/cards/r/RestlessDreams.java @@ -26,7 +26,7 @@ public final class RestlessDreams extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}"); // As an additional cost to cast Restless Dreams, discard X cards. - this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, false)); + this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, true)); // Return X target creature cards from your graveyard to your hand. Effect effect = new ReturnFromGraveyardToHandTargetEffect(); diff --git a/Mage.Sets/src/mage/cards/r/RetributionOfTheAncients.java b/Mage.Sets/src/mage/cards/r/RetributionOfTheAncients.java index a58fc99f7f..3aa922b835 100644 --- a/Mage.Sets/src/mage/cards/r/RetributionOfTheAncients.java +++ b/Mage.Sets/src/mage/cards/r/RetributionOfTheAncients.java @@ -1,7 +1,5 @@ - package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveVariableCountersTargetCost; @@ -19,8 +17,9 @@ import mage.counters.CounterType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class RetributionOfTheAncients extends CardImpl { @@ -32,12 +31,11 @@ public final class RetributionOfTheAncients extends CardImpl { } public RetributionOfTheAncients(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}"); - - DynamicValue xValue = new SignInversionDynamicValue(GetXValue.instance); // {B}, Remove X +1/+1 counters from among creatures you control: Target creature gets -X/-X until end of turn. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(xValue,xValue,Duration.EndOfTurn, true), new ManaCostsImpl("{B}")); + DynamicValue xValue = new SignInversionDynamicValue(GetXValue.instance); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(xValue, xValue, Duration.EndOfTurn, true), new ManaCostsImpl("{B}")); ability.addCost(new RemoveVariableCountersTargetCost(filter, CounterType.P1P1, "X", 0)); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/SandsOfDelirium.java b/Mage.Sets/src/mage/cards/s/SandsOfDelirium.java index 5cf023e7cb..e94d9945ba 100644 --- a/Mage.Sets/src/mage/cards/s/SandsOfDelirium.java +++ b/Mage.Sets/src/mage/cards/s/SandsOfDelirium.java @@ -1,10 +1,8 @@ - - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.dynamicvalue.common.ManacostVariableValue; @@ -15,17 +13,18 @@ import mage.constants.CardType; import mage.constants.Zone; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author Loki */ public final class SandsOfDelirium extends CardImpl { public SandsOfDelirium(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // {X}, {tap}: Target player puts the top X cards of their library into their graveyard. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(ManacostVariableValue.REGULAR), new VariableManaCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(ManacostVariableValue.REGULAR), new VariableManaCost(VariableCostType.NORMAL)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/SickeningDreams.java b/Mage.Sets/src/mage/cards/s/SickeningDreams.java index 0fe85106d4..19079354d5 100644 --- a/Mage.Sets/src/mage/cards/s/SickeningDreams.java +++ b/Mage.Sets/src/mage/cards/s/SickeningDreams.java @@ -1,11 +1,6 @@ - package mage.cards.s; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.costs.Cost; -import mage.abilities.costs.VariableCostImpl; -import mage.abilities.costs.common.DiscardTargetCost; +import mage.abilities.costs.common.DiscardXTargetCost; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.common.DamageEverythingEffect; import mage.cards.CardImpl; @@ -13,22 +8,20 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.FilterCard; import mage.filter.common.FilterCreaturePermanent; -import mage.game.Game; -import mage.players.Player; -import mage.target.common.TargetCardInHand; + +import java.util.UUID; /** - * * @author fireshoes */ public final class SickeningDreams extends CardImpl { public SickeningDreams(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}"); // As an additional cost to cast Sickening Dreams, discard X cards. - this.getSpellAbility().addCost(new SickeningDreamsAdditionalCost()); - + this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true)); + // Sickening Dreams deals X damage to each creature and each player. this.getSpellAbility().addEffect(new DamageEverythingEffect(GetXValue.instance, new FilterCreaturePermanent())); } @@ -41,36 +34,4 @@ public final class SickeningDreams extends CardImpl { public SickeningDreams copy() { return new SickeningDreams(this); } -} - -class SickeningDreamsAdditionalCost extends VariableCostImpl { - - SickeningDreamsAdditionalCost() { - super("cards to discard"); - this.text = "discard X cards"; - } - - SickeningDreamsAdditionalCost(final SickeningDreamsAdditionalCost cost) { - super(cost); - } - - @Override - public SickeningDreamsAdditionalCost copy() { - return new SickeningDreamsAdditionalCost(this); - } - - @Override - public int getMaxValue(Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - return controller.getHand().size(); - } - return 0; - } - - @Override - public Cost getFixedCostsFromAnnouncedValue(int xValue) { - TargetCardInHand target = new TargetCardInHand(xValue, new FilterCard()); - return new DiscardTargetCost(target); - } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SpringjackPasture.java b/Mage.Sets/src/mage/cards/s/SpringjackPasture.java index a91e56ea19..ed7b0f7f89 100644 --- a/Mage.Sets/src/mage/cards/s/SpringjackPasture.java +++ b/Mage.Sets/src/mage/cards/s/SpringjackPasture.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.Mana; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -21,10 +19,10 @@ import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.permanent.token.GoatToken; +import java.util.UUID; + /** - * * @author jeffwadsworth - * */ public final class SpringjackPasture extends CardImpl { @@ -35,7 +33,7 @@ public final class SpringjackPasture extends CardImpl { } public SpringjackPasture(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // {tap}: Add {C}. this.addAbility(new ColorlessManaAbility()); @@ -45,11 +43,11 @@ public final class SpringjackPasture extends CardImpl { ability.addCost(new TapSourceCost()); this.addAbility(ability); - // {tap}, Sacrifice X Goats: Add X mana of any one color. You gain X life. + // {T}, Sacrifice X Goats: Add X mana of any one color. You gain X life. ability = new DynamicManaAbility( - new Mana(0, 0, 0, 0,0, 0,1,0), + new Mana(0, 0, 0, 0, 0, 0, 1, 0), GetXValue.instance, - new TapSourceCost(), + new TapSourceCost(), "Add X mana of any one color", true); ability.addCost(new SacrificeXTargetCost(filter)); diff --git a/Mage.Sets/src/mage/cards/t/TalonOfPain.java b/Mage.Sets/src/mage/cards/t/TalonOfPain.java index d3f1583a2a..47d58afe26 100644 --- a/Mage.Sets/src/mage/cards/t/TalonOfPain.java +++ b/Mage.Sets/src/mage/cards/t/TalonOfPain.java @@ -1,12 +1,11 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.VariableCostImpl; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -25,8 +24,9 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author jerekwilson */ public final class TalonOfPain extends CardImpl { @@ -89,19 +89,17 @@ public final class TalonOfPain extends CardImpl { if (controller.hasOpponent(event.getTargetId(), game)) { // a source you control other than Talon of Pain UUID sourceControllerId = game.getControllerId(event.getSourceId()); - if (sourceControllerId != null + // return true so the effect will fire and a charge counter will be added + return sourceControllerId != null && sourceControllerId.equals(this.getControllerId()) - && !this.getSourceId().equals(event.getSourceId())) { - // return true so the effect will fire and a charge counter will be added - return true; - } + && !this.getSourceId().equals(event.getSourceId()); } return false; } @Override public String getTriggerPhrase() { - return "Whenever a source you control other than {this} deals damage to an opponent, " ; + return "Whenever a source you control other than {this} deals damage to an opponent, "; } } } @@ -109,7 +107,7 @@ public final class TalonOfPain extends CardImpl { class TalonOfPainRemoveVariableCountersSourceCost extends VariableCostImpl { protected int minimalCountersToPay = 0; - private String counterName; + private final String counterName; public TalonOfPainRemoveVariableCountersSourceCost(Counter counter) { this(counter, 0); @@ -124,7 +122,7 @@ class TalonOfPainRemoveVariableCountersSourceCost extends VariableCostImpl { } public TalonOfPainRemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay, String text) { - super(counter.getName() + " counters to remove"); + super(VariableCostType.NORMAL, counter.getName() + " counters to remove"); this.minimalCountersToPay = minimalCountersToPay; this.counterName = counter.getName(); if (text == null || text.isEmpty()) { diff --git a/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java b/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java index f7d9846f4b..4c451ad512 100644 --- a/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java +++ b/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java @@ -2,6 +2,7 @@ package mage.cards.t; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.ContinuousEffectImpl; @@ -27,7 +28,7 @@ public final class TestamentOfFaith extends CardImpl { // {X}: Testament of Faith becomes an X/X Wall creature with defender in addition to its other types until end of turn. Ability ability = new SimpleActivatedAbility(new SetPowerToughnessSourceEffect( ManacostVariableValue.REGULAR, Duration.EndOfTurn, SubLayer.SetPT_7b - ).setText("{this} becomes an X/X"), new VariableManaCost()); + ).setText("{this} becomes an X/X"), new VariableManaCost(VariableCostType.NORMAL)); ability.addEffect(new TestamentOfFaithEffect()); ability.addEffect(new GainAbilitySourceEffect( DefenderAbility.getInstance(), Duration.EndOfTurn diff --git a/Mage.Sets/src/mage/cards/t/ThievingSkydiver.java b/Mage.Sets/src/mage/cards/t/ThievingSkydiver.java index 36a1bbf83f..8fa7e69d36 100644 --- a/Mage.Sets/src/mage/cards/t/ThievingSkydiver.java +++ b/Mage.Sets/src/mage/cards/t/ThievingSkydiver.java @@ -38,7 +38,7 @@ public final class ThievingSkydiver extends CardImpl { // Kicker {X}. X can't be 0. KickerAbility kickerAbility = new KickerAbility("{X}"); - kickerAbility.getKickerCosts().stream().forEach(cost -> { + kickerAbility.getKickerCosts().forEach(cost -> { cost.setMinimumCost(1); cost.setReminderText(". X can't be 0."); }); diff --git a/Mage.Sets/src/mage/cards/t/ThoughtDissector.java b/Mage.Sets/src/mage/cards/t/ThoughtDissector.java index 45155f63e6..3c37894aaf 100644 --- a/Mage.Sets/src/mage/cards/t/ThoughtDissector.java +++ b/Mage.Sets/src/mage/cards/t/ThoughtDissector.java @@ -2,6 +2,7 @@ package mage.cards.t; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.VariableManaCost; import mage.abilities.dynamicvalue.common.ManacostVariableValue; @@ -21,17 +22,16 @@ import mage.target.common.TargetOpponent; import java.util.UUID; /** - * * @author noahg */ public final class ThoughtDissector extends CardImpl { public ThoughtDissector(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); - + // {X}, {tap}: Target opponent reveals cards from the top of their library until an artifact card or X cards are revealed, whichever comes first. If an artifact card is revealed this way, put it onto the battlefield under your control and sacrifice Thought Dissector. Put the rest of the revealed cards into that player's graveyard. - SimpleActivatedAbility abilitiy = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThoughtDissectorEffect(), new VariableManaCost()); + SimpleActivatedAbility abilitiy = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThoughtDissectorEffect(), new VariableManaCost(VariableCostType.NORMAL)); abilitiy.addCost(new TapSourceCost()); abilitiy.addTarget(new TargetOpponent()); this.addAbility(abilitiy); @@ -82,7 +82,7 @@ class ThoughtDissectorEffect extends OneShotEffect { break; } else { numberOfCard++; - if (numberOfCard > max){ + if (numberOfCard > max) { break; } nonArtifacts.add(card); diff --git a/Mage.Sets/src/mage/cards/t/TurbulentDreams.java b/Mage.Sets/src/mage/cards/t/TurbulentDreams.java index e2a91ec4d3..01716915bc 100644 --- a/Mage.Sets/src/mage/cards/t/TurbulentDreams.java +++ b/Mage.Sets/src/mage/cards/t/TurbulentDreams.java @@ -26,7 +26,7 @@ public final class TurbulentDreams extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{U}"); // As an additional cost to cast Turbulent Dreams, discard X cards. - this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, false)); + this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, true)); // Return X target nonland permanents to their owners' hands. Effect effect = new ReturnToHandTargetEffect(); diff --git a/Mage.Sets/src/mage/cards/v/VengefulDreams.java b/Mage.Sets/src/mage/cards/v/VengefulDreams.java index efeaad1acc..f02a5a1da6 100644 --- a/Mage.Sets/src/mage/cards/v/VengefulDreams.java +++ b/Mage.Sets/src/mage/cards/v/VengefulDreams.java @@ -25,7 +25,7 @@ public final class VengefulDreams extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}{W}"); // As an additional cost to cast Vengeful Dreams, discard X cards. - this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), false)); + this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true)); // Exile X target attacking creatures. Effect effect = new ExileTargetEffect(); diff --git a/Mage.Sets/src/mage/cards/v/ViciousBetrayal.java b/Mage.Sets/src/mage/cards/v/ViciousBetrayal.java index 596d8dfadb..1c5a03303d 100644 --- a/Mage.Sets/src/mage/cards/v/ViciousBetrayal.java +++ b/Mage.Sets/src/mage/cards/v/ViciousBetrayal.java @@ -1,4 +1,3 @@ - package mage.cards.v; import mage.abilities.Ability; @@ -27,7 +26,7 @@ public final class ViciousBetrayal extends CardImpl { // As an additional cost to cast Vicious Betrayal, sacrifice any number of creatures. - this.getSpellAbility().addCost(new SacrificeXTargetCost(new FilterControlledCreaturePermanent())); + this.getSpellAbility().addCost(new SacrificeXTargetCost(new FilterControlledCreaturePermanent(), true)); // Target creature gets +2/+2 until end of turn for each creature sacrificed this way. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addEffect(new BoostTargetEffect(GetXValue.instance, GetXValue.instance, Duration.EndOfTurn)); diff --git a/Mage.Sets/src/mage/cards/w/WanderingArchaic.java b/Mage.Sets/src/mage/cards/w/WanderingArchaic.java index 95775a39e8..caec8d1b10 100644 --- a/Mage.Sets/src/mage/cards/w/WanderingArchaic.java +++ b/Mage.Sets/src/mage/cards/w/WanderingArchaic.java @@ -3,7 +3,6 @@ package mage.cards.w; import mage.abilities.Ability; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.costs.Cost; -import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; import mage.cards.*; import mage.constants.*; @@ -15,6 +14,7 @@ import mage.game.stack.Spell; import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; +import mage.util.ManaUtil; import java.util.Objects; import java.util.UUID; @@ -85,7 +85,7 @@ class WanderingArchaicEffect extends OneShotEffect { if (controller == null || opponent == null || spell == null) { return false; } - Cost cost = new GenericManaCost(2); + Cost cost = ManaUtil.createManaCost(2, false); if (cost.canPay(source, source, opponent.getId(), game) && opponent.chooseUse(outcome, "Pay {2}?", source, game) && cost.pay(source, game, source, opponent.getId(), false)) { diff --git a/Mage.Sets/src/mage/cards/w/WhirlwindDenial.java b/Mage.Sets/src/mage/cards/w/WhirlwindDenial.java index d13c6bdd90..1df06fd581 100644 --- a/Mage.Sets/src/mage/cards/w/WhirlwindDenial.java +++ b/Mage.Sets/src/mage/cards/w/WhirlwindDenial.java @@ -2,7 +2,6 @@ package mage.cards.w; import mage.abilities.Ability; import mage.abilities.costs.Cost; -import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -10,6 +9,8 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; +import mage.util.ManaUtil; + import java.util.Objects; import java.util.UUID; @@ -65,22 +66,22 @@ class WhirlwindDenialEffect extends OneShotEffect { if (player == null) { return; } - Cost cost = new GenericManaCost(4); + Cost cost = ManaUtil.createManaCost(4, false); if (cost.canPay(source, source, stackObject.getControllerId(), game) && player.chooseUse(outcome, "Pay {4} to prevent " - + stackObject.getIdName() + " from being countered?", source, game) + + stackObject.getIdName() + " from being countered?", source, game) && cost.pay(source, game, source, stackObject.getControllerId(), false)) { - game.informPlayers("The cost was paid by " - + player.getLogName() - + " to prevent " - + stackObject.getIdName() + game.informPlayers("The cost was paid by " + + player.getLogName() + + " to prevent " + + stackObject.getIdName() + " from being countered."); return; } - game.informPlayers("The cost was not paid by " - + player.getLogName() - + " to prevent " - + stackObject.getIdName() + game.informPlayers("The cost was not paid by " + + player.getLogName() + + " to prevent " + + stackObject.getIdName() + " from being countered."); game.getStack().counter(stackObject.getId(), source, game); }); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java index 8afe385617..2b4e91d129 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/KickerTest.java @@ -651,4 +651,68 @@ public class KickerTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Marsh Casualties", 1); assertPowerToughness(playerB, "Centaur Courser", 1, 1); } + + @Test + public void test_FreeCast_Normal() { + skipInitShuffling(); + + // Kicker {2} + // If Ardent Soldier was kicked, it enters the battlefield with a +1/+1 counter on it. + addCard(Zone.LIBRARY, playerA, "Ardent Soldier", 1); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); // for kicker cost + // + // Whenever Etali, Primal Storm attacks, exile the top card of each player's library, + // then you may cast any number of nonland cards exiled this way without paying their mana costs. + addCard(Zone.BATTLEFIELD, playerA, "Etali, Primal Storm", 1); + + checkPlayableAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Ardent Soldier", false); + + // attack and prepare free cast, use kicker + attack(1, playerA, "Etali, Primal Storm", playerB); + setChoice(playerA, true); // cast for free + setChoice(playerA, "Ardent Soldier"); // cast for free + setChoice(playerA, true); // use kicker + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertCounterCount(playerA, "Ardent Soldier", CounterType.P1P1, 1); // from kicker + } + + @Test + public void test_FreeCast_MinXValueMustWork() { + // bug: + // Can cast Thieving Skydiver with kicker's X = 0 on Etali, Primal Storm + skipInitShuffling(); + + // Kicker {X}. X can't be 0. + // When Thieving Skydiver enters the battlefield, if it was kicked, gain control of target artifact with + // converted mana cost X or less. If that artifact is an Equipment, attach it to Thieving Skydiver. + addCard(Zone.LIBRARY, playerA, "Thieving Skydiver", 1); // {1}{U} + addCard(Zone.BATTLEFIELD, playerB, "Brain in a Jar", 1); // {2} + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); // for kicker cost + // + // Whenever Etali, Primal Storm attacks, exile the top card of each player's library, + // then you may cast any number of nonland cards exiled this way without paying their mana costs. + addCard(Zone.BATTLEFIELD, playerA, "Etali, Primal Storm", 1); + + checkPlayableAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Thieving Skydiver", false); + + // attack and prepare free cast + attack(1, playerA, "Etali, Primal Storm", playerB); + setChoice(playerA, true); // cast for free + setChoice(playerA, "Thieving Skydiver"); // cast for free + setChoice(playerA, true); // use kicker + setChoiceAmount(playerA, 2); // X=2 for Kicker X + addTarget(playerA, "Brain in a Jar"); // kicker's target (take control of artifact) + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Brain in a Jar", 1); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/UnboundFlourishingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/UnboundFlourishingTest.java index 71811dea30..5017e677c3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/UnboundFlourishingTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/UnboundFlourishingTest.java @@ -1,5 +1,6 @@ package org.mage.test.cards.continuous; +import mage.abilities.costs.VariableCostType; import mage.abilities.costs.mana.VariableManaCost; import mage.constants.PhaseStep; import mage.constants.Zone; @@ -182,7 +183,7 @@ public class UnboundFlourishingTest extends CardTestPlayerBase { int xInstancesCount = 2; int xAnnouncedValue = 3; int xMultiplier = 2; - VariableManaCost cost = new VariableManaCost(xInstancesCount); + VariableManaCost cost = new VariableManaCost(VariableCostType.NORMAL, xInstancesCount); cost.setAmount(xAnnouncedValue * xMultiplier, xAnnouncedValue * xInstancesCount, false); Assert.assertEquals("instances count", xInstancesCount, cost.getXInstancesCount()); diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index f5ad920bd6..6816176332 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -259,7 +259,7 @@ public abstract class AbilityImpl implements Ability { if (!this.getManaCostsToPay().getVariableCosts().isEmpty()) { int xValue = this.getManaCostsToPay().getX(); this.getManaCostsToPay().clear(); - VariableManaCost xCosts = new VariableManaCost(); + VariableManaCost xCosts = new VariableManaCost(VariableCostType.ADDITIONAL); // no x events - rules from Unbound Flourishing: // - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost. xCosts.setAmount(xValue, xValue, false); @@ -555,9 +555,17 @@ public abstract class AbilityImpl implements Ability { * @return variableManaCost for posting to log later */ protected VariableManaCost handleManaXCosts(Game game, boolean noMana, Player controller) { - // 20121001 - 601.2b - // If the spell has a variable cost that will be paid as it's being cast (such as an {X} in - // its mana cost; see rule 107.3), the player announces the value of that variable. + // 20210723 - 601.2b + // If the spell has alternative or additional costs that will + // be paid as it’s being cast such as buyback or kicker costs (see rules 118.8 and 118.9), + // the player announces their intentions to pay any or all of those costs (see rule 601.2f). + // A player can’t apply two alternative methods of casting or two alternative costs to a + // single spell. If the spell has a variable cost that will be paid as it’s being cast + // (such as an {X} in its mana cost; see rule 107.3), the player announces the value of that + // variable. If the value of that variable is defined in the text of the spell by a choice + // that player would make later in the announcement or resolution of the spell, that player + // makes that choice at this time instead of that later time. + // TODO: Handle announcing other variable costs here like: RemoveVariableCountersSourceCost VariableManaCost variableManaCost = null; for (ManaCost cost : manaCostsToPay) { @@ -574,7 +582,7 @@ public abstract class AbilityImpl implements Ability { if (!variableManaCost.isPaid()) { // should only happen for human players int xValue; int xValueMultiplier = handleManaXMultiplier(game, 1); - if (!noMana) { + if (!noMana || variableManaCost.getCostType().canUseAnnounceOnFreeCast()) { xValue = controller.announceXMana(variableManaCost.getMinX(), variableManaCost.getMaxX(), xValueMultiplier, "Announce the value for " + variableManaCost.getText(), game, this); int amountMana = xValue * variableManaCost.getXInstancesCount(); diff --git a/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCost.java b/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCost.java index a97e768731..f8b4796a30 100644 --- a/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCost.java +++ b/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCost.java @@ -1,8 +1,11 @@ package mage.abilities.costs; -import mage.util.Copyable; - /** + * Virtual optional/additional cost, it must be tranformed to simple cost on resolve in your custom ability. + * Don't forget to set up cost type for variable costs + *
+ * Example: KickerAbility.
+ *
* @author LevelX2
*/
public interface OptionalAdditionalCost extends Cost {
@@ -77,6 +80,13 @@ public interface OptionalAdditionalCost extends Cost {
*/
int getActivateCount();
+ /**
+ * Set cost type to variable costs like additional or normal (example: Kicker)
+ *
+ * @param costType
+ */
+ void setCostType(VariableCostType costType);
+
@Override
OptionalAdditionalCost copy();
}
diff --git a/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCostImpl.java b/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCostImpl.java
index 30b1db820f..10440512d0 100644
--- a/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCostImpl.java
+++ b/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalCostImpl.java
@@ -166,6 +166,12 @@ public class OptionalAdditionalCostImpl extends CostsImpl