diff --git a/Mage.Sets/src/mage/cards/a/ArcticNishoba.java b/Mage.Sets/src/mage/cards/a/ArcticNishoba.java index 72f96426914..873ae4e4690 100644 --- a/Mage.Sets/src/mage/cards/a/ArcticNishoba.java +++ b/Mage.Sets/src/mage/cards/a/ArcticNishoba.java @@ -37,9 +37,8 @@ public final class ArcticNishoba extends CardImpl { // Cumulative upkeep {G} or {W} this.addAbility(new CumulativeUpkeepAbility(new OrCost( - new ManaCostsImpl("{G}"), - new ManaCostsImpl("{W}"), - "{G} or {W}" + "{G} or {W}", new ManaCostsImpl("{G}"), + new ManaCostsImpl("{W}") ))); // When Arctic Nishoba dies, you gain 2 life for each age counter on it. diff --git a/Mage.Sets/src/mage/cards/b/BayouGroff.java b/Mage.Sets/src/mage/cards/b/BayouGroff.java index b45b35fe2bd..52f441c2c2a 100644 --- a/Mage.Sets/src/mage/cards/b/BayouGroff.java +++ b/Mage.Sets/src/mage/cards/b/BayouGroff.java @@ -28,9 +28,9 @@ public final class BayouGroff extends CardImpl { // As an additional cost to cast this spell, sacrifice a creature or pay {3}. this.getSpellAbility().addCost(new OrCost( - new SacrificeTargetCost(new TargetControlledPermanent( + "sacrifice a creature or pay {3}", new SacrificeTargetCost(new TargetControlledPermanent( StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT - )), new GenericManaCost(3), "sacrifice a creature or pay {3}" + )), new GenericManaCost(3) )); } diff --git a/Mage.Sets/src/mage/cards/b/BoneShards.java b/Mage.Sets/src/mage/cards/b/BoneShards.java index 94b45c7385e..8b79ba03d06 100644 --- a/Mage.Sets/src/mage/cards/b/BoneShards.java +++ b/Mage.Sets/src/mage/cards/b/BoneShards.java @@ -22,8 +22,8 @@ public final class BoneShards extends CardImpl { // As an additional cost to cast this spell, sacrifice a creature or discard a card. this.getSpellAbility().addCost(new OrCost( - new SacrificeTargetCost(new TargetControlledCreaturePermanent()), - new DiscardCardCost(), "sacrifice a creature or discard a card" + "sacrifice a creature or discard a card", new SacrificeTargetCost(new TargetControlledCreaturePermanent()), + new DiscardCardCost() )); // Destroy target creature or planeswalker. diff --git a/Mage.Sets/src/mage/cards/c/CryptLurker.java b/Mage.Sets/src/mage/cards/c/CryptLurker.java index 153d25dbef3..903b417678a 100644 --- a/Mage.Sets/src/mage/cards/c/CryptLurker.java +++ b/Mage.Sets/src/mage/cards/c/CryptLurker.java @@ -33,10 +33,9 @@ public final class CryptLurker extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfCostPaid( new DrawCardSourceControllerEffect(1), new OrCost( - new SacrificeTargetCost(new TargetControlledPermanent( + "sacrifice a creature or discard a creature card", new SacrificeTargetCost(new TargetControlledPermanent( StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT - )), new DiscardTargetCost(new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE_A)), - "sacrifice a creature or discard a creature card" + )), new DiscardTargetCost(new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE_A)) ) ))); } diff --git a/Mage.Sets/src/mage/cards/c/CrystalShard.java b/Mage.Sets/src/mage/cards/c/CrystalShard.java index a0a09fec637..ab32c2aa66d 100644 --- a/Mage.Sets/src/mage/cards/c/CrystalShard.java +++ b/Mage.Sets/src/mage/cards/c/CrystalShard.java @@ -34,9 +34,8 @@ public final class CrystalShard extends CardImpl { Ability ability = new SimpleActivatedAbility( new CrystalShardEffect(), new OrCost( - new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), - new CompositeCost(new ManaCostsImpl<>("{U}"), new TapSourceCost(), "{U}, {T}"), - "{3}, {T} or {U}, {T}" + "{3}, {T} or {U}, {T}", new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), + new CompositeCost(new ManaCostsImpl<>("{U}"), new TapSourceCost(), "{U}, {T}") ) ); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/d/DaringBuccaneer.java b/Mage.Sets/src/mage/cards/d/DaringBuccaneer.java index ce392e959b6..6672cfe4959 100644 --- a/Mage.Sets/src/mage/cards/d/DaringBuccaneer.java +++ b/Mage.Sets/src/mage/cards/d/DaringBuccaneer.java @@ -34,9 +34,9 @@ public final class DaringBuccaneer extends CardImpl { // As an additional cost to cast Daring Buccaneer, reveal a Pirate card from your hand or pay {2}. this.getSpellAbility().addCost(new OrCost( - new RevealTargetFromHandCost(new TargetCardInHand(filter)), - new GenericManaCost(2), - "reveal a Pirate card from your hand or pay {2}")); + "reveal a Pirate card from your hand or pay {2}", new RevealTargetFromHandCost(new TargetCardInHand(filter)), + new GenericManaCost(2) + )); } diff --git a/Mage.Sets/src/mage/cards/d/DisruptionProtocol.java b/Mage.Sets/src/mage/cards/d/DisruptionProtocol.java index 017af341b2c..2dffb4ef3cd 100644 --- a/Mage.Sets/src/mage/cards/d/DisruptionProtocol.java +++ b/Mage.Sets/src/mage/cards/d/DisruptionProtocol.java @@ -32,8 +32,8 @@ public final class DisruptionProtocol extends CardImpl { // As an additional cost to cast this spell, tap an untapped artifact you control or pay {1}. this.getSpellAbility().addCost(new OrCost( - new TapTargetCost(new TargetControlledPermanent(filter)), - new GenericManaCost(1), "tap an untapped artifact you control or pay {1}" + "tap an untapped artifact you control or pay {1}", new TapTargetCost(new TargetControlledPermanent(filter)), + new GenericManaCost(1) )); // Counter target spell. diff --git a/Mage.Sets/src/mage/cards/d/DuskMangler.java b/Mage.Sets/src/mage/cards/d/DuskMangler.java new file mode 100644 index 00000000000..8a81b9efbcf --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DuskMangler.java @@ -0,0 +1,58 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.OrCost; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.effects.common.SacrificeOpponentsEffect; +import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DuskMangler extends CardImpl { + + public DuskMangler(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}"); + + this.subtype.add(SubType.HORROR); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // As an additional cost to cast this spell, sacrifice a creature, discard a card, or pay 4 life. + this.getSpellAbility().addCost(new OrCost( + "sacrifice a creature, discard a card, or pay 4 life", + new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT), + new DiscardCardCost(), new PayLifeCost(4) + )); + + // When Dusk Mangler enters the battlefield, each opponent sacrifices a creature, discards a card, and loses 4 life. + Ability ability = new EntersBattlefieldTriggeredAbility( + new SacrificeOpponentsEffect(StaticFilters.FILTER_PERMANENT_A_CREATURE) + ); + ability.addEffect(new DiscardEachPlayerEffect(TargetController.OPPONENT).setText(", discards a card")); + ability.addEffect(new LoseLifeOpponentsEffect(4).setText(", and loses 4 life")); + this.addAbility(ability); + } + + private DuskMangler(final DuskMangler card) { + super(card); + } + + @Override + public DuskMangler copy() { + return new DuskMangler(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EarthenGoo.java b/Mage.Sets/src/mage/cards/e/EarthenGoo.java index 68b38ce2c5f..2a2d98144af 100644 --- a/Mage.Sets/src/mage/cards/e/EarthenGoo.java +++ b/Mage.Sets/src/mage/cards/e/EarthenGoo.java @@ -37,9 +37,8 @@ public final class EarthenGoo extends CardImpl { // Cumulative upkeep {R} or {G} this.addAbility(new CumulativeUpkeepAbility(new OrCost( - new ManaCostsImpl("{R}"), - new ManaCostsImpl("{G}"), - "{R} or {G}" + "{R} or {G}", new ManaCostsImpl("{R}"), + new ManaCostsImpl("{G}") ))); // Earthen Goo gets +1/+1 for each age counter on it. diff --git a/Mage.Sets/src/mage/cards/e/EatenAlive.java b/Mage.Sets/src/mage/cards/e/EatenAlive.java index 27b3da87ebd..36b0cee0670 100644 --- a/Mage.Sets/src/mage/cards/e/EatenAlive.java +++ b/Mage.Sets/src/mage/cards/e/EatenAlive.java @@ -22,8 +22,8 @@ public final class EatenAlive extends CardImpl { // As an additional cost to cast this spell, sacrifice a creature or pay {3}{B}. this.getSpellAbility().addCost(new OrCost( - new SacrificeTargetCost(new TargetControlledCreaturePermanent()), - new ManaCostsImpl<>("{3}{B}"), "sacrifice a creature or pay {3}{B}" + "sacrifice a creature or pay {3}{B}", new SacrificeTargetCost(new TargetControlledCreaturePermanent()), + new ManaCostsImpl<>("{3}{B}") )); // Exile target creature or planeswalker. diff --git a/Mage.Sets/src/mage/cards/e/EmberwildeDjinn.java b/Mage.Sets/src/mage/cards/e/EmberwildeDjinn.java index 520ba488eb4..033ca35f546 100644 --- a/Mage.Sets/src/mage/cards/e/EmberwildeDjinn.java +++ b/Mage.Sets/src/mage/cards/e/EmberwildeDjinn.java @@ -78,7 +78,7 @@ class EmberwildeDjinnEffect extends OneShotEffect { if (player == null || sourceObject == null) { return false; } - Cost cost = new OrCost(new ManaCostsImpl("{R}{R}"), new PayLifeCost(2), "{R}{R} or 2 life"); + Cost cost = new OrCost("{R}{R} or 2 life", new ManaCostsImpl("{R}{R}"), new PayLifeCost(2)); if (player.chooseUse(Outcome.GainControl, "Gain control of " + sourceObject.getLogName() + "?", source, game)) { if (cost.pay(source, game, source, player.getId(), false)) { ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, false, player.getId()); diff --git a/Mage.Sets/src/mage/cards/e/Erosion.java b/Mage.Sets/src/mage/cards/e/Erosion.java index d501240c0b2..a7052b3ca46 100644 --- a/Mage.Sets/src/mage/cards/e/Erosion.java +++ b/Mage.Sets/src/mage/cards/e/Erosion.java @@ -38,7 +38,7 @@ public final class Erosion extends CardImpl { this.addAbility(new EnchantAbility(auraTarget.getTargetName())); // At the beginning of the upkeep of enchanted land's controller, destroy that land unless that player pays {1} or 1 life. - Effect effect = new DoUnlessTargetPlayerOrTargetsControllerPaysEffect(new DestroyAttachedToEffect("enchanted land"), new OrCost(new ManaCostsImpl("{1}"), new PayLifeCost(1), "{1} or 1 life")); + Effect effect = new DoUnlessTargetPlayerOrTargetsControllerPaysEffect(new DestroyAttachedToEffect("enchanted land"), new OrCost("{1} or 1 life", new ManaCostsImpl("{1}"), new PayLifeCost(1))); effect.setText("destroy that land unless that player pays {1} or 1 life"); this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.CONTROLLER_ATTACHED_TO, false, true, "At the beginning of the upkeep of enchanted land's controller, ")); } diff --git a/Mage.Sets/src/mage/cards/f/FinalPayment.java b/Mage.Sets/src/mage/cards/f/FinalPayment.java index 3050ed50f22..d7e7313162c 100644 --- a/Mage.Sets/src/mage/cards/f/FinalPayment.java +++ b/Mage.Sets/src/mage/cards/f/FinalPayment.java @@ -33,8 +33,8 @@ public final class FinalPayment extends CardImpl { final Cost lifeCost = new PayLifeCost(5); final Cost sacrificeCost = new SacrificeTargetCost(new TargetControlledPermanent(filter)); - this.getSpellAbility().addCost(new OrCost(lifeCost, sacrificeCost, - "pay 5 life or sacrifice a creature or enchantment")); + this.getSpellAbility().addCost(new OrCost("pay 5 life or sacrifice a creature or enchantment", lifeCost, sacrificeCost + )); // Destroy target creature this.getSpellAbility().addEffect(new DestroyTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/f/FlamekinBladewhirl.java b/Mage.Sets/src/mage/cards/f/FlamekinBladewhirl.java index 303cd6cf757..edae64c172b 100644 --- a/Mage.Sets/src/mage/cards/f/FlamekinBladewhirl.java +++ b/Mage.Sets/src/mage/cards/f/FlamekinBladewhirl.java @@ -34,9 +34,9 @@ public final class FlamekinBladewhirl extends CardImpl { // As an additional cost to cast Flamekin Bladewhirl, reveal an Elemental card from your hand or pay {3}. this.getSpellAbility().addCost(new OrCost( - new RevealTargetFromHandCost(new TargetCardInHand(filter)), - new GenericManaCost(3), - "reveal an Elemental card from your hand or pay {3}")); + "reveal an Elemental card from your hand or pay {3}", new RevealTargetFromHandCost(new TargetCardInHand(filter)), + new GenericManaCost(3) + )); } private FlamekinBladewhirl(final FlamekinBladewhirl card) { diff --git a/Mage.Sets/src/mage/cards/g/GoldmeadowStalwart.java b/Mage.Sets/src/mage/cards/g/GoldmeadowStalwart.java index 216dbcec536..f7b7778ac3f 100644 --- a/Mage.Sets/src/mage/cards/g/GoldmeadowStalwart.java +++ b/Mage.Sets/src/mage/cards/g/GoldmeadowStalwart.java @@ -34,9 +34,9 @@ public final class GoldmeadowStalwart extends CardImpl { // As an additional cost to cast Goldmeadow Stalwart, reveal a Kithkin card from your hand or pay {3}. this.getSpellAbility().addCost(new OrCost( - new RevealTargetFromHandCost(new TargetCardInHand(filter)), - new GenericManaCost(3), - "reveal a Kithkin card from your hand or pay {3}")); + "reveal a Kithkin card from your hand or pay {3}", new RevealTargetFromHandCost(new TargetCardInHand(filter)), + new GenericManaCost(3) + )); } private GoldmeadowStalwart(final GoldmeadowStalwart card) { diff --git a/Mage.Sets/src/mage/cards/g/GraniteShard.java b/Mage.Sets/src/mage/cards/g/GraniteShard.java index b0edd313684..86fea06fa9c 100644 --- a/Mage.Sets/src/mage/cards/g/GraniteShard.java +++ b/Mage.Sets/src/mage/cards/g/GraniteShard.java @@ -27,9 +27,8 @@ public final class GraniteShard extends CardImpl { Ability ability = new SimpleActivatedAbility( new DamageTargetEffect(1), new OrCost( - new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), - new CompositeCost(new ManaCostsImpl<>("{R}"), new TapSourceCost(), "{R}, {T}"), - "{3}, {T} or {R}, {T}" + "{3}, {T} or {R}, {T}", new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), + new CompositeCost(new ManaCostsImpl<>("{R}"), new TapSourceCost(), "{R}, {T}") ) ); ability.addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/h/HeartwoodShard.java b/Mage.Sets/src/mage/cards/h/HeartwoodShard.java index 84475daa40d..78afe2682d7 100644 --- a/Mage.Sets/src/mage/cards/h/HeartwoodShard.java +++ b/Mage.Sets/src/mage/cards/h/HeartwoodShard.java @@ -29,9 +29,8 @@ public final class HeartwoodShard extends CardImpl { Ability ability = new SimpleActivatedAbility( new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), new OrCost( - new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), - new CompositeCost(new ManaCostsImpl<>("{G}"), new TapSourceCost(), "{G}, {T}"), - "{3}, {T} or {G}, {T}" + "{3}, {T} or {G}, {T}", new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), + new CompositeCost(new ManaCostsImpl<>("{G}"), new TapSourceCost(), "{G}, {T}") ) ); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/i/IonStorm.java b/Mage.Sets/src/mage/cards/i/IonStorm.java index 527456f63c7..be134304d2b 100644 --- a/Mage.Sets/src/mage/cards/i/IonStorm.java +++ b/Mage.Sets/src/mage/cards/i/IonStorm.java @@ -28,7 +28,7 @@ public final class IonStorm extends CardImpl { // {1}{R}, Remove a +1/+1 counter or a charge counter from a permanent you control: Ion Storm deals 2 damage to any target. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), new ManaCostsImpl("{1}{R}")); - ability.addCost(new OrCost(new RemoveCounterCost(new TargetControlledPermanent(), CounterType.P1P1), new RemoveCounterCost(new TargetControlledPermanent(), CounterType.CHARGE), " Remove a +1/+1 counter or a charge counter from a permanent you control")); + ability.addCost(new OrCost(" Remove a +1/+1 counter or a charge counter from a permanent you control", new RemoveCounterCost(new TargetControlledPermanent(), CounterType.P1P1), new RemoveCounterCost(new TargetControlledPermanent(), CounterType.CHARGE))); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java b/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java index bd7d7efeada..bf6a7af4807 100644 --- a/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java +++ b/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java @@ -31,9 +31,8 @@ public final class JotunOwlKeeper extends CardImpl { // Cumulative upkeep {W} or {U} this.addAbility(new CumulativeUpkeepAbility(new OrCost( - new ManaCostsImpl("{W}"), - new ManaCostsImpl("{U}"), - "{W} or {U}" + "{W} or {U}", new ManaCostsImpl("{W}"), + new ManaCostsImpl("{U}") ))); // When Jötun Owl Keeper dies, put a 1/1 white Bird creature token with flying onto the battlefield for each age counter on it. diff --git a/Mage.Sets/src/mage/cards/k/KrovikanWhispers.java b/Mage.Sets/src/mage/cards/k/KrovikanWhispers.java index 9f9575ce691..fd85574f988 100644 --- a/Mage.Sets/src/mage/cards/k/KrovikanWhispers.java +++ b/Mage.Sets/src/mage/cards/k/KrovikanWhispers.java @@ -42,7 +42,7 @@ public final class KrovikanWhispers extends CardImpl { this.addAbility(ability); // Cumulative upkeep-Pay {U} or {B}. - this.addAbility(new CumulativeUpkeepAbility(new OrCost(new ManaCostsImpl("{U}"), new ManaCostsImpl("{B}"), "{U} or {B}"))); + this.addAbility(new CumulativeUpkeepAbility(new OrCost("{U} or {B}", new ManaCostsImpl("{U}"), new ManaCostsImpl("{B}")))); // You control enchanted creature. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ControlEnchantedEffect())); diff --git a/Mage.Sets/src/mage/cards/l/LightningAxe.java b/Mage.Sets/src/mage/cards/l/LightningAxe.java index 4a9b7404d8a..8b917033489 100644 --- a/Mage.Sets/src/mage/cards/l/LightningAxe.java +++ b/Mage.Sets/src/mage/cards/l/LightningAxe.java @@ -22,7 +22,7 @@ public final class LightningAxe extends CardImpl { // As an additional cost to cast Lightning Axe, discard a card or pay {5}. - this.getSpellAbility().addCost(new OrCost(new DiscardCardCost(), new GenericManaCost(5),"discard a card or pay {5}")); + this.getSpellAbility().addCost(new OrCost("discard a card or pay {5}", new DiscardCardCost(), new GenericManaCost(5))); // Lightning Axe deals 5 damage to target creature. this.getSpellAbility().addEffect(new DamageTargetEffect(5)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/l/LimDulsHex.java b/Mage.Sets/src/mage/cards/l/LimDulsHex.java index 5af0a76c39a..9dd7081f6a3 100644 --- a/Mage.Sets/src/mage/cards/l/LimDulsHex.java +++ b/Mage.Sets/src/mage/cards/l/LimDulsHex.java @@ -61,7 +61,7 @@ class LimDulsHexEffect extends OneShotEffect { for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { - OrCost costToPay = new OrCost(new ManaCostsImpl("{B}"), new ManaCostsImpl("{3}"), "{B} or {3}"); + OrCost costToPay = new OrCost("{B} or {3}", new ManaCostsImpl("{B}"), new ManaCostsImpl("{3}")); costToPay.clearPaid(); if (!(player.chooseUse(Outcome.Benefit, "Pay {B} or {3}?", source, game) && costToPay.pay(source, game, source, player.getId(), false, null))) { game.informPlayers(player.getLogName() + " chooses not to pay " + costToPay.getText() + " to prevent 1 damage from " + sourcePermanent.getLogName()); diff --git a/Mage.Sets/src/mage/cards/m/MorkrutBehemoth.java b/Mage.Sets/src/mage/cards/m/MorkrutBehemoth.java index 4dd44b8fbbf..48772fd9b2f 100644 --- a/Mage.Sets/src/mage/cards/m/MorkrutBehemoth.java +++ b/Mage.Sets/src/mage/cards/m/MorkrutBehemoth.java @@ -29,9 +29,9 @@ public final class MorkrutBehemoth extends CardImpl { // As an additional cost to cast this spell, sacrifice a creature or pay {1}{B}. this.getSpellAbility().addCost(new OrCost( - new SacrificeTargetCost(new TargetControlledPermanent( + "sacrifice a creature or pay {1}{B}", new SacrificeTargetCost(new TargetControlledPermanent( StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT - )), new ManaCostsImpl<>("{1}{B}"), "sacrifice a creature or pay {1}{B}" + )), new ManaCostsImpl<>("{1}{B}") )); // Menace diff --git a/Mage.Sets/src/mage/cards/p/PearlShard.java b/Mage.Sets/src/mage/cards/p/PearlShard.java index 80ff4d9bea0..5d8d64eb0b2 100644 --- a/Mage.Sets/src/mage/cards/p/PearlShard.java +++ b/Mage.Sets/src/mage/cards/p/PearlShard.java @@ -29,9 +29,8 @@ public final class PearlShard extends CardImpl { Ability ability = new SimpleActivatedAbility( new PreventDamageToTargetEffect(Duration.EndOfTurn, 2), new OrCost( - new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), - new CompositeCost(new ManaCostsImpl<>("{W}"), new TapSourceCost(), "{W}, {T}"), - "{3}, {T} or {W}, {T}" + "{3}, {T} or {W}, {T}", new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), + new CompositeCost(new ManaCostsImpl<>("{W}"), new TapSourceCost(), "{W}, {T}") ) ); ability.addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/s/SadisticSkymarcher.java b/Mage.Sets/src/mage/cards/s/SadisticSkymarcher.java index 87a0009aa11..e0df9838cdf 100644 --- a/Mage.Sets/src/mage/cards/s/SadisticSkymarcher.java +++ b/Mage.Sets/src/mage/cards/s/SadisticSkymarcher.java @@ -37,9 +37,9 @@ public final class SadisticSkymarcher extends CardImpl { // As an additional cost to cast Sadistic Skymarcher, reveal a Vampire card from your hand or pay {1}. this.getSpellAbility().addCost(new OrCost( - new RevealTargetFromHandCost(new TargetCardInHand(filter)), - new GenericManaCost(1), - "reveal a Vampire card from your hand or pay {1}")); + "reveal a Vampire card from your hand or pay {1}", new RevealTargetFromHandCost(new TargetCardInHand(filter)), + new GenericManaCost(1) + )); // Flying this.addAbility(FlyingAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/s/SkeletonShard.java b/Mage.Sets/src/mage/cards/s/SkeletonShard.java index 2e88996d8fb..01f58335229 100644 --- a/Mage.Sets/src/mage/cards/s/SkeletonShard.java +++ b/Mage.Sets/src/mage/cards/s/SkeletonShard.java @@ -35,9 +35,8 @@ public final class SkeletonShard extends CardImpl { Ability ability = new SimpleActivatedAbility( new ReturnFromGraveyardToHandTargetEffect(), new OrCost( - new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), - new CompositeCost(new ManaCostsImpl<>("{B}"), new TapSourceCost(), "{B}, {T}"), - "{3}, {T} or {B}, {T}" + "{3}, {T} or {B}, {T}", new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), + new CompositeCost(new ManaCostsImpl<>("{B}"), new TapSourceCost(), "{B}, {T}") ) ); ability.addTarget(new TargetCardInYourGraveyard(filter)); diff --git a/Mage.Sets/src/mage/cards/s/SparkHarvest.java b/Mage.Sets/src/mage/cards/s/SparkHarvest.java index 9a3062e78e1..4466c10ae66 100644 --- a/Mage.Sets/src/mage/cards/s/SparkHarvest.java +++ b/Mage.Sets/src/mage/cards/s/SparkHarvest.java @@ -22,8 +22,8 @@ public final class SparkHarvest extends CardImpl { // As an additional cost to cast this spell, sacrifice a creature or pay {3}{B}. this.getSpellAbility().addCost(new OrCost( - new SacrificeTargetCost(new TargetControlledCreaturePermanent()), - new ManaCostsImpl<>("{3}{B}"), "sacrifice a creature or pay {3}{B}" + "sacrifice a creature or pay {3}{B}", new SacrificeTargetCost(new TargetControlledCreaturePermanent()), + new ManaCostsImpl<>("{3}{B}") )); // Destroy target creature or planeswalker. diff --git a/Mage.Sets/src/mage/cards/s/SqueakingPieSneak.java b/Mage.Sets/src/mage/cards/s/SqueakingPieSneak.java index 33528deeb4d..853ef52fd21 100644 --- a/Mage.Sets/src/mage/cards/s/SqueakingPieSneak.java +++ b/Mage.Sets/src/mage/cards/s/SqueakingPieSneak.java @@ -35,9 +35,9 @@ public final class SqueakingPieSneak extends CardImpl { // As an additional cost to cast Squeaking Pie Sneak, reveal a Goblin card from your hand or pay {3}. this.getSpellAbility().addCost(new OrCost( - new RevealTargetFromHandCost(new TargetCardInHand(filter)), - new GenericManaCost(3), - "reveal a Goblin card from your hand or pay {3}")); + "reveal a Goblin card from your hand or pay {3}", new RevealTargetFromHandCost(new TargetCardInHand(filter)), + new GenericManaCost(3) + )); // Fear this.addAbility(FearAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/cards/s/SurtlandElementalist.java b/Mage.Sets/src/mage/cards/s/SurtlandElementalist.java index 2a9b862e848..d2c6d613456 100644 --- a/Mage.Sets/src/mage/cards/s/SurtlandElementalist.java +++ b/Mage.Sets/src/mage/cards/s/SurtlandElementalist.java @@ -38,9 +38,9 @@ public final class SurtlandElementalist extends CardImpl { // As an additional cost to cast this spell, reveal a Giant card from your hand or pay {2}. this.getSpellAbility().addCost(new OrCost( - new RevealTargetFromHandCost(new TargetCardInHand(filter)), - new GenericManaCost(2), - "reveal a Giant card from your hand or pay {2}")); + "reveal a Giant card from your hand or pay {2}", new RevealTargetFromHandCost(new TargetCardInHand(filter)), + new GenericManaCost(2) + )); // Whenever Surtland Elementalist attacks, you may cast an instant or sorcery spell from your hand without paying its mana cost. this.addAbility(new AttacksTriggeredAbility(new CastFromHandForFreeEffect(filter2), true)); diff --git a/Mage.Sets/src/mage/cards/t/ThrullWizard.java b/Mage.Sets/src/mage/cards/t/ThrullWizard.java index ea6d1d49ba9..72a67231701 100644 --- a/Mage.Sets/src/mage/cards/t/ThrullWizard.java +++ b/Mage.Sets/src/mage/cards/t/ThrullWizard.java @@ -40,7 +40,7 @@ public final class ThrullWizard extends CardImpl { this.toughness = new MageInt(1); // {1}{B}: Counter target black spell unless that spell's controller pays {B} or {3}. - Cost cost = new OrCost(new ColoredManaCost(ColoredManaSymbol.B), new GenericManaCost(3), "pay {B} or pay {3}"); + Cost cost = new OrCost("pay {B} or pay {3}", new ColoredManaCost(ColoredManaSymbol.B), new GenericManaCost(3)); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(cost), new ManaCostsImpl("{1}{B}")); ability.addTarget(new TargetSpell(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/ThunderherdMigration.java b/Mage.Sets/src/mage/cards/t/ThunderherdMigration.java index 966f02a773c..e4ab1f076fb 100644 --- a/Mage.Sets/src/mage/cards/t/ThunderherdMigration.java +++ b/Mage.Sets/src/mage/cards/t/ThunderherdMigration.java @@ -32,9 +32,9 @@ public final class ThunderherdMigration extends CardImpl { // As an additional cost to cast Thunderherd Migration, reveal a Dinosaur card from your hand or pay {1}. this.getSpellAbility().addCost(new OrCost( - new RevealTargetFromHandCost(new TargetCardInHand(filter)), - new GenericManaCost(1), - "reveal a Dinosaur card from your hand or pay {1}")); + "reveal a Dinosaur card from your hand or pay {1}", new RevealTargetFromHandCost(new TargetCardInHand(filter)), + new GenericManaCost(1) + )); // Search your library for a basic land card, put it onto the battlefield tapped, then shuffle your library. this.getSpellAbility().addEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true, true)); diff --git a/Mage.Sets/src/mage/cards/t/TidalControl.java b/Mage.Sets/src/mage/cards/t/TidalControl.java index 795cdb1bc5b..34278e0fc74 100644 --- a/Mage.Sets/src/mage/cards/t/TidalControl.java +++ b/Mage.Sets/src/mage/cards/t/TidalControl.java @@ -37,7 +37,7 @@ public final class TidalControl extends CardImpl { this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{2}"))); // Pay 2 life or {2}: Counter target red or green spell. Any player may activate this ability. - SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new OrCost(new PayLifeCost(2), new ManaCostsImpl("{2}"), "pay 2 life or pay {2}")); + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new OrCost("pay 2 life or pay {2}", new PayLifeCost(2), new ManaCostsImpl("{2}"))); ability.addTarget(new TargetSpell(filter)); ability.setMayActivate(TargetController.ANY); ability.addEffect(new InfoEffect("Any player may activate this ability")); diff --git a/Mage.Sets/src/mage/cards/w/WrensRunVanquisher.java b/Mage.Sets/src/mage/cards/w/WrensRunVanquisher.java index e07f8299d02..7aa9903a825 100644 --- a/Mage.Sets/src/mage/cards/w/WrensRunVanquisher.java +++ b/Mage.Sets/src/mage/cards/w/WrensRunVanquisher.java @@ -35,9 +35,9 @@ public final class WrensRunVanquisher extends CardImpl { // As an additional cost to cast Wren's Run Vanquisher, reveal an Elf card from your hand or pay {3}. this.getSpellAbility().addCost(new OrCost( - new RevealTargetFromHandCost(new TargetCardInHand(filter)), - new GenericManaCost(3), - "reveal an Elf card from your hand or pay {3}")); + "reveal an Elf card from your hand or pay {3}", new RevealTargetFromHandCost(new TargetCardInHand(filter)), + new GenericManaCost(3) + )); // Deathtouch this.addAbility(DeathtouchAbility.getInstance()); diff --git a/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java b/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java index 31c3f4fafc7..f25132cd87e 100644 --- a/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java +++ b/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java @@ -93,6 +93,7 @@ public final class StreetsOfNewCapenna extends ExpansionSet { cards.add(new SetCardInfo("Dig Up the Body", 76, Rarity.COMMON, mage.cards.d.DigUpTheBody.class)); cards.add(new SetCardInfo("Disciplined Duelist", 182, Rarity.UNCOMMON, mage.cards.d.DisciplinedDuelist.class)); cards.add(new SetCardInfo("Disdainful Stroke", 39, Rarity.COMMON, mage.cards.d.DisdainfulStroke.class)); + cards.add(new SetCardInfo("Dusk Mangler", 77, Rarity.UNCOMMON, mage.cards.d.DuskMangler.class)); cards.add(new SetCardInfo("Echo Inspector", 40, Rarity.COMMON, mage.cards.e.EchoInspector.class)); cards.add(new SetCardInfo("Elegant Entourage", 143, Rarity.UNCOMMON, mage.cards.e.ElegantEntourage.class)); cards.add(new SetCardInfo("Elspeth Resplendent", 11, Rarity.MYTHIC, mage.cards.e.ElspethResplendent.class)); diff --git a/Mage/src/main/java/mage/abilities/costs/OrCost.java b/Mage/src/main/java/mage/abilities/costs/OrCost.java index c040438282d..9ab8c989acb 100644 --- a/Mage/src/main/java/mage/abilities/costs/OrCost.java +++ b/Mage/src/main/java/mage/abilities/costs/OrCost.java @@ -1,32 +1,32 @@ - package mage.abilities.costs; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCost; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; import mage.target.Targets; -import java.util.UUID; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; public class OrCost implements Cost { - private final Cost firstCost; - private final Cost secondCost; + private final List costs = new ArrayList<>(); private String description; // which cost was slected to pay private Cost selectedCost; - public OrCost(Cost firstCost, Cost secondCost, String description) { - this.firstCost = firstCost; - this.secondCost = secondCost; + public OrCost(String description, Cost... costs) { + Collections.addAll(this.costs, costs); this.description = description; } public OrCost(final OrCost cost) { - this.firstCost = cost.firstCost.copy(); - this.secondCost = cost.secondCost.copy(); + cost.costs.stream().map(Cost::copy).forEach(this.costs::add); this.description = cost.description; this.selectedCost = cost.selectedCost; } @@ -49,7 +49,7 @@ public class OrCost implements Cost { @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { - return firstCost.canPay(ability, source, controllerId, game) || secondCost.canPay(ability, source, controllerId, game); + return costs.stream().anyMatch(cost -> cost.canPay(ability, source, controllerId, game)); } @Override @@ -60,28 +60,47 @@ public class OrCost implements Cost { @Override public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { selectedCost = null; - // if only one can be paid select it - if (!firstCost.canPay(ability, source, controllerId, game)) { - selectedCost = secondCost; + List usable = costs + .stream() + .filter(cost -> cost.canPay(ability, source, controllerId, game)) + .collect(Collectors.toList()); + Player controller = game.getPlayer(controllerId); + if (controller == null) { + return false; } - if (!secondCost.canPay(ability, source, controllerId, game)) { - selectedCost = firstCost; - } - // if both can be paid player has to select - if (selectedCost == null) { - Player controller = game.getPlayer(controllerId); - if (controller != null) { + switch (usable.size()) { + case 0: + return false; + case 1: + selectedCost = usable.get(0); + break; + case 2: StringBuilder sb = new StringBuilder(); - if (firstCost instanceof ManaCost) { + if (usable.get(0) instanceof ManaCost) { sb.append("Pay "); } - sb.append(firstCost.getText()).append('?'); - if (controller.chooseUse(Outcome.Detriment, sb.toString(), ability, game)) { - selectedCost = firstCost; + sb.append(usable.get(0).getText()); + sb.append(" or "); + sb.append(usable.get(1)); + sb.append('?'); + if (controller.chooseUse( + Outcome.Detriment, sb.toString(), null, + usable.get(0).getText(), usable.get(1).getText(), ability, game + )) { + selectedCost = usable.get(0); } else { - selectedCost = secondCost; + selectedCost = usable.get(1); } - } + break; + default: + Map costMap = usable + .stream() + .collect(Collectors.toMap(Cost::getText, Function.identity())); + Choice choice = new ChoiceImpl(true); + choice.setMessage("Choose a cost to pay"); + choice.setChoices(costMap.keySet()); + controller.choose(Outcome.Neutral, choice, game); + selectedCost = costMap.getOrDefault(choice.getChoice(), null); } if (selectedCost == null) { return false; @@ -92,17 +111,13 @@ public class OrCost implements Cost { @Override public boolean isPaid() { - if (selectedCost != null) { - return selectedCost.isPaid(); - } - return false; + return selectedCost != null ? selectedCost.isPaid() : false; } @Override public void clearPaid() { selectedCost = null; - firstCost.clearPaid(); - secondCost.clearPaid(); + costs.stream().forEach(Cost::clearPaid); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsEffect.java index 1e142c4f709..a246d724ca7 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeOpponentsEffect.java @@ -1,6 +1,7 @@ package mage.abilities.effects.common; import mage.abilities.Ability; +import mage.abilities.Mode; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; @@ -40,7 +41,6 @@ public class SacrificeOpponentsEffect extends OneShotEffect { this.amount = amount; this.filter = filter.copy(); this.filter.add(TargetController.YOU.getControllerPredicate()); - setText(); } public SacrificeOpponentsEffect(final SacrificeOpponentsEffect effect) { @@ -79,7 +79,11 @@ public class SacrificeOpponentsEffect extends OneShotEffect { return true; } - private void setText() { + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } StringBuilder sb = new StringBuilder(); sb.append("each opponent sacrifices "); switch (amount.toString()) { @@ -92,6 +96,6 @@ public class SacrificeOpponentsEffect extends OneShotEffect { default: sb.append(CardUtil.numberToText(amount.toString())).append(' ').append(filter.getMessage()); } - staticText = sb.toString(); + return sb.toString(); } }