[SNC] Implemented Dusk Mangler

This commit is contained in:
Evan Kranzler 2022-04-19 08:37:50 -04:00
parent dcb893dbf7
commit 342eabbfa7
36 changed files with 177 additions and 108 deletions

View file

@ -37,9 +37,8 @@ public final class ArcticNishoba extends CardImpl {
// Cumulative upkeep {G} or {W} // Cumulative upkeep {G} or {W}
this.addAbility(new CumulativeUpkeepAbility(new OrCost( this.addAbility(new CumulativeUpkeepAbility(new OrCost(
new ManaCostsImpl("{G}"), "{G} or {W}", new ManaCostsImpl("{G}"),
new ManaCostsImpl("{W}"), new ManaCostsImpl("{W}")
"{G} or {W}"
))); )));
// When Arctic Nishoba dies, you gain 2 life for each age counter on it. // When Arctic Nishoba dies, you gain 2 life for each age counter on it.

View file

@ -28,9 +28,9 @@ public final class BayouGroff extends CardImpl {
// As an additional cost to cast this spell, sacrifice a creature or pay {3}. // As an additional cost to cast this spell, sacrifice a creature or pay {3}.
this.getSpellAbility().addCost(new OrCost( 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 StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT
)), new GenericManaCost(3), "sacrifice a creature or pay {3}" )), new GenericManaCost(3)
)); ));
} }

View file

@ -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. // As an additional cost to cast this spell, sacrifice a creature or discard a card.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new SacrificeTargetCost(new TargetControlledCreaturePermanent()), "sacrifice a creature or discard a card", new SacrificeTargetCost(new TargetControlledCreaturePermanent()),
new DiscardCardCost(), "sacrifice a creature or discard a card" new DiscardCardCost()
)); ));
// Destroy target creature or planeswalker. // Destroy target creature or planeswalker.

View file

@ -33,10 +33,9 @@ public final class CryptLurker extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfCostPaid( this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfCostPaid(
new DrawCardSourceControllerEffect(1), new DrawCardSourceControllerEffect(1),
new OrCost( new OrCost(
new SacrificeTargetCost(new TargetControlledPermanent( "sacrifice a creature or discard a creature card", new SacrificeTargetCost(new TargetControlledPermanent(
StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT
)), new DiscardTargetCost(new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE_A)), )), new DiscardTargetCost(new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE_A))
"sacrifice a creature or discard a creature card"
) )
))); )));
} }

View file

@ -34,9 +34,8 @@ public final class CrystalShard extends CardImpl {
Ability ability = new SimpleActivatedAbility( Ability ability = new SimpleActivatedAbility(
new CrystalShardEffect(), new CrystalShardEffect(),
new OrCost( new OrCost(
new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), "{3}, {T} or {U}, {T}", new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"),
new CompositeCost(new ManaCostsImpl<>("{U}"), new TapSourceCost(), "{U}, {T}"), new CompositeCost(new ManaCostsImpl<>("{U}"), new TapSourceCost(), "{U}, {T}")
"{3}, {T} or {U}, {T}"
) )
); );
ability.addTarget(new TargetCreaturePermanent()); ability.addTarget(new TargetCreaturePermanent());

View file

@ -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}. // As an additional cost to cast Daring Buccaneer, reveal a Pirate card from your hand or pay {2}.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new RevealTargetFromHandCost(new TargetCardInHand(filter)), "reveal a Pirate card from your hand or pay {2}", new RevealTargetFromHandCost(new TargetCardInHand(filter)),
new GenericManaCost(2), new GenericManaCost(2)
"reveal a Pirate card from your hand or pay {2}")); ));
} }

View file

@ -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}. // As an additional cost to cast this spell, tap an untapped artifact you control or pay {1}.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new TapTargetCost(new TargetControlledPermanent(filter)), "tap an untapped artifact you control or pay {1}", new TapTargetCost(new TargetControlledPermanent(filter)),
new GenericManaCost(1), "tap an untapped artifact you control or pay {1}" new GenericManaCost(1)
)); ));
// Counter target spell. // Counter target spell.

View file

@ -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);
}
}

View file

@ -37,9 +37,8 @@ public final class EarthenGoo extends CardImpl {
// Cumulative upkeep {R} or {G} // Cumulative upkeep {R} or {G}
this.addAbility(new CumulativeUpkeepAbility(new OrCost( this.addAbility(new CumulativeUpkeepAbility(new OrCost(
new ManaCostsImpl("{R}"), "{R} or {G}", new ManaCostsImpl("{R}"),
new ManaCostsImpl("{G}"), new ManaCostsImpl("{G}")
"{R} or {G}"
))); )));
// Earthen Goo gets +1/+1 for each age counter on it. // Earthen Goo gets +1/+1 for each age counter on it.

View file

@ -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}. // As an additional cost to cast this spell, sacrifice a creature or pay {3}{B}.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new SacrificeTargetCost(new TargetControlledCreaturePermanent()), "sacrifice a creature or pay {3}{B}", new SacrificeTargetCost(new TargetControlledCreaturePermanent()),
new ManaCostsImpl<>("{3}{B}"), "sacrifice a creature or pay {3}{B}" new ManaCostsImpl<>("{3}{B}")
)); ));
// Exile target creature or planeswalker. // Exile target creature or planeswalker.

View file

@ -78,7 +78,7 @@ class EmberwildeDjinnEffect extends OneShotEffect {
if (player == null || sourceObject == null) { if (player == null || sourceObject == null) {
return false; 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 (player.chooseUse(Outcome.GainControl, "Gain control of " + sourceObject.getLogName() + "?", source, game)) {
if (cost.pay(source, game, source, player.getId(), false)) { if (cost.pay(source, game, source, player.getId(), false)) {
ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, false, player.getId()); ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, false, player.getId());

View file

@ -38,7 +38,7 @@ public final class Erosion extends CardImpl {
this.addAbility(new EnchantAbility(auraTarget.getTargetName())); 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. // 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"); 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, ")); this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, TargetController.CONTROLLER_ATTACHED_TO, false, true, "At the beginning of the upkeep of enchanted land's controller, "));
} }

View file

@ -33,8 +33,8 @@ public final class FinalPayment extends CardImpl {
final Cost lifeCost = new PayLifeCost(5); final Cost lifeCost = new PayLifeCost(5);
final Cost sacrificeCost = new SacrificeTargetCost(new TargetControlledPermanent(filter)); final Cost sacrificeCost = new SacrificeTargetCost(new TargetControlledPermanent(filter));
this.getSpellAbility().addCost(new OrCost(lifeCost, sacrificeCost, this.getSpellAbility().addCost(new OrCost("pay 5 life or sacrifice a creature or enchantment", lifeCost, sacrificeCost
"pay 5 life or sacrifice a creature or enchantment")); ));
// Destroy target creature // Destroy target creature
this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new DestroyTargetEffect());

View file

@ -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}. // As an additional cost to cast Flamekin Bladewhirl, reveal an Elemental card from your hand or pay {3}.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new RevealTargetFromHandCost(new TargetCardInHand(filter)), "reveal an Elemental card from your hand or pay {3}", new RevealTargetFromHandCost(new TargetCardInHand(filter)),
new GenericManaCost(3), new GenericManaCost(3)
"reveal an Elemental card from your hand or pay {3}")); ));
} }
private FlamekinBladewhirl(final FlamekinBladewhirl card) { private FlamekinBladewhirl(final FlamekinBladewhirl card) {

View file

@ -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}. // As an additional cost to cast Goldmeadow Stalwart, reveal a Kithkin card from your hand or pay {3}.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new RevealTargetFromHandCost(new TargetCardInHand(filter)), "reveal a Kithkin card from your hand or pay {3}", new RevealTargetFromHandCost(new TargetCardInHand(filter)),
new GenericManaCost(3), new GenericManaCost(3)
"reveal a Kithkin card from your hand or pay {3}")); ));
} }
private GoldmeadowStalwart(final GoldmeadowStalwart card) { private GoldmeadowStalwart(final GoldmeadowStalwart card) {

View file

@ -27,9 +27,8 @@ public final class GraniteShard extends CardImpl {
Ability ability = new SimpleActivatedAbility( Ability ability = new SimpleActivatedAbility(
new DamageTargetEffect(1), new DamageTargetEffect(1),
new OrCost( new OrCost(
new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), "{3}, {T} or {R}, {T}", new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"),
new CompositeCost(new ManaCostsImpl<>("{R}"), new TapSourceCost(), "{R}, {T}"), new CompositeCost(new ManaCostsImpl<>("{R}"), new TapSourceCost(), "{R}, {T}")
"{3}, {T} or {R}, {T}"
) )
); );
ability.addTarget(new TargetAnyTarget()); ability.addTarget(new TargetAnyTarget());

View file

@ -29,9 +29,8 @@ public final class HeartwoodShard extends CardImpl {
Ability ability = new SimpleActivatedAbility( Ability ability = new SimpleActivatedAbility(
new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn),
new OrCost( new OrCost(
new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), "{3}, {T} or {G}, {T}", new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"),
new CompositeCost(new ManaCostsImpl<>("{G}"), new TapSourceCost(), "{G}, {T}"), new CompositeCost(new ManaCostsImpl<>("{G}"), new TapSourceCost(), "{G}, {T}")
"{3}, {T} or {G}, {T}"
) )
); );
ability.addTarget(new TargetCreaturePermanent()); ability.addTarget(new TargetCreaturePermanent());

View file

@ -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. // {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 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()); ability.addTarget(new TargetAnyTarget());
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -31,9 +31,8 @@ public final class JotunOwlKeeper extends CardImpl {
// Cumulative upkeep {W} or {U} // Cumulative upkeep {W} or {U}
this.addAbility(new CumulativeUpkeepAbility(new OrCost( this.addAbility(new CumulativeUpkeepAbility(new OrCost(
new ManaCostsImpl("{W}"), "{W} or {U}", new ManaCostsImpl("{W}"),
new ManaCostsImpl("{U}"), new ManaCostsImpl("{U}")
"{W} or {U}"
))); )));
// When J&ouml;tun Owl Keeper dies, put a 1/1 white Bird creature token with flying onto the battlefield for each age counter on it. // When J&ouml;tun Owl Keeper dies, put a 1/1 white Bird creature token with flying onto the battlefield for each age counter on it.

View file

@ -42,7 +42,7 @@ public final class KrovikanWhispers extends CardImpl {
this.addAbility(ability); this.addAbility(ability);
// Cumulative upkeep-Pay {U} or {B}. // 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. // You control enchanted creature.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ControlEnchantedEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ControlEnchantedEffect()));

View file

@ -22,7 +22,7 @@ public final class LightningAxe extends CardImpl {
// As an additional cost to cast Lightning Axe, discard a card or pay {5}. // 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. // Lightning Axe deals 5 damage to target creature.
this.getSpellAbility().addEffect(new DamageTargetEffect(5)); this.getSpellAbility().addEffect(new DamageTargetEffect(5));
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());

View file

@ -61,7 +61,7 @@ class LimDulsHexEffect extends OneShotEffect {
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null) { 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(); costToPay.clearPaid();
if (!(player.chooseUse(Outcome.Benefit, "Pay {B} or {3}?", source, game) && costToPay.pay(source, game, source, player.getId(), false, null))) { 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()); game.informPlayers(player.getLogName() + " chooses not to pay " + costToPay.getText() + " to prevent 1 damage from " + sourcePermanent.getLogName());

View file

@ -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}. // As an additional cost to cast this spell, sacrifice a creature or pay {1}{B}.
this.getSpellAbility().addCost(new OrCost( 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 StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT
)), new ManaCostsImpl<>("{1}{B}"), "sacrifice a creature or pay {1}{B}" )), new ManaCostsImpl<>("{1}{B}")
)); ));
// Menace // Menace

View file

@ -29,9 +29,8 @@ public final class PearlShard extends CardImpl {
Ability ability = new SimpleActivatedAbility( Ability ability = new SimpleActivatedAbility(
new PreventDamageToTargetEffect(Duration.EndOfTurn, 2), new PreventDamageToTargetEffect(Duration.EndOfTurn, 2),
new OrCost( new OrCost(
new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), "{3}, {T} or {W}, {T}", new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"),
new CompositeCost(new ManaCostsImpl<>("{W}"), new TapSourceCost(), "{W}, {T}"), new CompositeCost(new ManaCostsImpl<>("{W}"), new TapSourceCost(), "{W}, {T}")
"{3}, {T} or {W}, {T}"
) )
); );
ability.addTarget(new TargetAnyTarget()); ability.addTarget(new TargetAnyTarget());

View file

@ -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}. // As an additional cost to cast Sadistic Skymarcher, reveal a Vampire card from your hand or pay {1}.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new RevealTargetFromHandCost(new TargetCardInHand(filter)), "reveal a Vampire card from your hand or pay {1}", new RevealTargetFromHandCost(new TargetCardInHand(filter)),
new GenericManaCost(1), new GenericManaCost(1)
"reveal a Vampire card from your hand or pay {1}")); ));
// Flying // Flying
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());

View file

@ -35,9 +35,8 @@ public final class SkeletonShard extends CardImpl {
Ability ability = new SimpleActivatedAbility( Ability ability = new SimpleActivatedAbility(
new ReturnFromGraveyardToHandTargetEffect(), new ReturnFromGraveyardToHandTargetEffect(),
new OrCost( new OrCost(
new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"), "{3}, {T} or {B}, {T}", new CompositeCost(new GenericManaCost(3), new TapSourceCost(), "{3}, {T}"),
new CompositeCost(new ManaCostsImpl<>("{B}"), new TapSourceCost(), "{B}, {T}"), new CompositeCost(new ManaCostsImpl<>("{B}"), new TapSourceCost(), "{B}, {T}")
"{3}, {T} or {B}, {T}"
) )
); );
ability.addTarget(new TargetCardInYourGraveyard(filter)); ability.addTarget(new TargetCardInYourGraveyard(filter));

View file

@ -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}. // As an additional cost to cast this spell, sacrifice a creature or pay {3}{B}.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new SacrificeTargetCost(new TargetControlledCreaturePermanent()), "sacrifice a creature or pay {3}{B}", new SacrificeTargetCost(new TargetControlledCreaturePermanent()),
new ManaCostsImpl<>("{3}{B}"), "sacrifice a creature or pay {3}{B}" new ManaCostsImpl<>("{3}{B}")
)); ));
// Destroy target creature or planeswalker. // Destroy target creature or planeswalker.

View file

@ -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}. // As an additional cost to cast Squeaking Pie Sneak, reveal a Goblin card from your hand or pay {3}.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new RevealTargetFromHandCost(new TargetCardInHand(filter)), "reveal a Goblin card from your hand or pay {3}", new RevealTargetFromHandCost(new TargetCardInHand(filter)),
new GenericManaCost(3), new GenericManaCost(3)
"reveal a Goblin card from your hand or pay {3}")); ));
// Fear // Fear
this.addAbility(FearAbility.getInstance()); this.addAbility(FearAbility.getInstance());
} }

View file

@ -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}. // As an additional cost to cast this spell, reveal a Giant card from your hand or pay {2}.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new RevealTargetFromHandCost(new TargetCardInHand(filter)), "reveal a Giant card from your hand or pay {2}", new RevealTargetFromHandCost(new TargetCardInHand(filter)),
new GenericManaCost(2), new GenericManaCost(2)
"reveal a Giant card from your hand or pay {2}")); ));
// Whenever Surtland Elementalist attacks, you may cast an instant or sorcery spell from your hand without paying its mana cost. // 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)); this.addAbility(new AttacksTriggeredAbility(new CastFromHandForFreeEffect(filter2), true));

View file

@ -40,7 +40,7 @@ public final class ThrullWizard extends CardImpl {
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// {1}{B}: Counter target black spell unless that spell's controller pays {B} or {3}. // {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 ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(cost), new ManaCostsImpl("{1}{B}"));
ability.addTarget(new TargetSpell(filter)); ability.addTarget(new TargetSpell(filter));
this.addAbility(ability); this.addAbility(ability);

View file

@ -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}. // As an additional cost to cast Thunderherd Migration, reveal a Dinosaur card from your hand or pay {1}.
this.getSpellAbility().addCost(new OrCost( this.getSpellAbility().addCost(new OrCost(
new RevealTargetFromHandCost(new TargetCardInHand(filter)), "reveal a Dinosaur card from your hand or pay {1}", new RevealTargetFromHandCost(new TargetCardInHand(filter)),
new GenericManaCost(1), new GenericManaCost(1)
"reveal a Dinosaur card from your hand or pay {1}")); ));
// Search your library for a basic land card, put it onto the battlefield tapped, then shuffle your library. // 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)); this.getSpellAbility().addEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true, true));

View file

@ -37,7 +37,7 @@ public final class TidalControl extends CardImpl {
this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{2}"))); this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{2}")));
// Pay 2 life or {2}: Counter target red or green spell. Any player may activate this ability. // 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.addTarget(new TargetSpell(filter));
ability.setMayActivate(TargetController.ANY); ability.setMayActivate(TargetController.ANY);
ability.addEffect(new InfoEffect("Any player may activate this ability")); ability.addEffect(new InfoEffect("Any player may activate this ability"));

View file

@ -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}. // 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( this.getSpellAbility().addCost(new OrCost(
new RevealTargetFromHandCost(new TargetCardInHand(filter)), "reveal an Elf card from your hand or pay {3}", new RevealTargetFromHandCost(new TargetCardInHand(filter)),
new GenericManaCost(3), new GenericManaCost(3)
"reveal an Elf card from your hand or pay {3}")); ));
// Deathtouch // Deathtouch
this.addAbility(DeathtouchAbility.getInstance()); this.addAbility(DeathtouchAbility.getInstance());

View file

@ -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("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("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("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("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("Elegant Entourage", 143, Rarity.UNCOMMON, mage.cards.e.ElegantEntourage.class));
cards.add(new SetCardInfo("Elspeth Resplendent", 11, Rarity.MYTHIC, mage.cards.e.ElspethResplendent.class)); cards.add(new SetCardInfo("Elspeth Resplendent", 11, Rarity.MYTHIC, mage.cards.e.ElspethResplendent.class));

View file

@ -1,32 +1,32 @@
package mage.abilities.costs; package mage.abilities.costs;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCost;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.game.Game; import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.target.Targets; 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 { public class OrCost implements Cost {
private final Cost firstCost; private final List<Cost> costs = new ArrayList<>();
private final Cost secondCost;
private String description; private String description;
// which cost was slected to pay // which cost was slected to pay
private Cost selectedCost; private Cost selectedCost;
public OrCost(Cost firstCost, Cost secondCost, String description) { public OrCost(String description, Cost... costs) {
this.firstCost = firstCost; Collections.addAll(this.costs, costs);
this.secondCost = secondCost;
this.description = description; this.description = description;
} }
public OrCost(final OrCost cost) { public OrCost(final OrCost cost) {
this.firstCost = cost.firstCost.copy(); cost.costs.stream().map(Cost::copy).forEach(this.costs::add);
this.secondCost = cost.secondCost.copy();
this.description = cost.description; this.description = cost.description;
this.selectedCost = cost.selectedCost; this.selectedCost = cost.selectedCost;
} }
@ -49,7 +49,7 @@ public class OrCost implements Cost {
@Override @Override
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { 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 @Override
@ -60,28 +60,47 @@ public class OrCost implements Cost {
@Override @Override
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
selectedCost = null; selectedCost = null;
// if only one can be paid select it List<Cost> usable = costs
if (!firstCost.canPay(ability, source, controllerId, game)) { .stream()
selectedCost = secondCost; .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)) { switch (usable.size()) {
selectedCost = firstCost; case 0:
} return false;
// if both can be paid player has to select case 1:
if (selectedCost == null) { selectedCost = usable.get(0);
Player controller = game.getPlayer(controllerId); break;
if (controller != null) { case 2:
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (firstCost instanceof ManaCost) { if (usable.get(0) instanceof ManaCost) {
sb.append("Pay "); sb.append("Pay ");
} }
sb.append(firstCost.getText()).append('?'); sb.append(usable.get(0).getText());
if (controller.chooseUse(Outcome.Detriment, sb.toString(), ability, game)) { sb.append(" or ");
selectedCost = firstCost; 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 { } else {
selectedCost = secondCost; selectedCost = usable.get(1);
} }
} break;
default:
Map<String, Cost> 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) { if (selectedCost == null) {
return false; return false;
@ -92,17 +111,13 @@ public class OrCost implements Cost {
@Override @Override
public boolean isPaid() { public boolean isPaid() {
if (selectedCost != null) { return selectedCost != null ? selectedCost.isPaid() : false;
return selectedCost.isPaid();
}
return false;
} }
@Override @Override
public void clearPaid() { public void clearPaid() {
selectedCost = null; selectedCost = null;
firstCost.clearPaid(); costs.stream().forEach(Cost::clearPaid);
secondCost.clearPaid();
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package mage.abilities.effects.common; package mage.abilities.effects.common;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
@ -40,7 +41,6 @@ public class SacrificeOpponentsEffect extends OneShotEffect {
this.amount = amount; this.amount = amount;
this.filter = filter.copy(); this.filter = filter.copy();
this.filter.add(TargetController.YOU.getControllerPredicate()); this.filter.add(TargetController.YOU.getControllerPredicate());
setText();
} }
public SacrificeOpponentsEffect(final SacrificeOpponentsEffect effect) { public SacrificeOpponentsEffect(final SacrificeOpponentsEffect effect) {
@ -79,7 +79,11 @@ public class SacrificeOpponentsEffect extends OneShotEffect {
return true; return true;
} }
private void setText() { @Override
public String getText(Mode mode) {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("each opponent sacrifices "); sb.append("each opponent sacrifices ");
switch (amount.toString()) { switch (amount.toString()) {
@ -92,6 +96,6 @@ public class SacrificeOpponentsEffect extends OneShotEffect {
default: default:
sb.append(CardUtil.numberToText(amount.toString())).append(' ').append(filter.getMessage()); sb.append(CardUtil.numberToText(amount.toString())).append(' ').append(filter.getMessage());
} }
staticText = sb.toString(); return sb.toString();
} }
} }