From 2f50958e53b0010c681e4f03c1a78ecea43cc8ed Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Wed, 7 Apr 2021 08:53:03 -0400 Subject: [PATCH] [STX] Implemented Reject --- Mage.Sets/src/mage/cards/r/Reject.java | 44 +++++++++++ Mage.Sets/src/mage/cards/s/SpellShrivel.java | 64 +--------------- Mage.Sets/src/mage/cards/s/Syncopate.java | 63 +--------------- .../mage/sets/StrixhavenSchoolOfMages.java | 1 + .../common/CounterUnlessPaysEffect.java | 74 ++++++++++++------- 5 files changed, 98 insertions(+), 148 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/r/Reject.java diff --git a/Mage.Sets/src/mage/cards/r/Reject.java b/Mage.Sets/src/mage/cards/r/Reject.java new file mode 100644 index 0000000000..afcb870c5a --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/Reject.java @@ -0,0 +1,44 @@ +package mage.cards.r; + +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.CounterUnlessPaysEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterSpell; +import mage.filter.predicate.Predicates; +import mage.target.TargetSpell; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Reject extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("creature or planeswalker spell"); + + static { + filter.add(Predicates.or( + CardType.CREATURE.getPredicate(), + CardType.PLANESWALKER.getPredicate() + )); + } + + public Reject(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + // Counter target creature or planeswalker spell unless its controller pays {3}. If that spell is countered this way, exile it instead of putting into its owner's graveyard. + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new GenericManaCost(3), true)); + this.getSpellAbility().addTarget(new TargetSpell(filter)); + } + + private Reject(final Reject card) { + super(card); + } + + @Override + public Reject copy() { + return new Reject(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpellShrivel.java b/Mage.Sets/src/mage/cards/s/SpellShrivel.java index 02ec1047e8..7c5d760256 100644 --- a/Mage.Sets/src/mage/cards/s/SpellShrivel.java +++ b/Mage.Sets/src/mage/cards/s/SpellShrivel.java @@ -1,23 +1,12 @@ package mage.cards.s; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.costs.Cost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.CounterUnlessPaysEffect; import mage.abilities.keyword.DevoidAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.Spell; -import mage.game.stack.StackObject; -import mage.players.Player; import mage.target.TargetSpell; -import mage.util.ManaUtil; import java.util.UUID; @@ -33,7 +22,7 @@ public final class SpellShrivel extends CardImpl { this.addAbility(new DevoidAbility(this.color)); // Counter target spell unless its controller pays {4}. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new SpellShrivelCounterUnlessPaysEffect()); + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new GenericManaCost(4), true)); this.getSpellAbility().addTarget(new TargetSpell()); } @@ -46,50 +35,3 @@ public final class SpellShrivel extends CardImpl { return new SpellShrivel(this); } } - -class SpellShrivelCounterUnlessPaysEffect extends OneShotEffect { - - public SpellShrivelCounterUnlessPaysEffect() { - super(Outcome.Detriment); - } - - public SpellShrivelCounterUnlessPaysEffect(final SpellShrivelCounterUnlessPaysEffect effect) { - super(effect); - } - - @Override - public SpellShrivelCounterUnlessPaysEffect copy() { - return new SpellShrivelCounterUnlessPaysEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - StackObject spell = game.getStack().getStackObject(targetPointer.getFirst(game, source)); - MageObject sourceObject = source.getSourceObject(game); - if ((spell instanceof Spell) && sourceObject != null) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Cost cost = ManaUtil.createManaCost(4, false); - if (!cost.pay(source, game, source, spell.getControllerId(), false)) { - StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget()); - if (stackObject != null && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, source.getFirstTarget(), source, stackObject.getControllerId()))) { - game.informPlayers(sourceObject.getIdName() + ": cost wasn't payed - countering " + stackObject.getName()); - game.rememberLKI(source.getFirstTarget(), Zone.STACK, stackObject); - controller.moveCards((Spell) spell, Zone.EXILED, source, game); - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, source.getFirstTarget(), source, stackObject.getControllerId())); - return true; - } - return false; - } - - } - } - return false; - } - - @Override - public String getText(Mode mode) { - return "Counter target spell unless its controller pays {4}. If that spell is countered this way, exile it instead of putting it into its owner's graveyard"; - } - -} diff --git a/Mage.Sets/src/mage/cards/s/Syncopate.java b/Mage.Sets/src/mage/cards/s/Syncopate.java index 848564de02..b206e221c1 100644 --- a/Mage.Sets/src/mage/cards/s/Syncopate.java +++ b/Mage.Sets/src/mage/cards/s/Syncopate.java @@ -1,23 +1,11 @@ package mage.cards.s; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.costs.Cost; import mage.abilities.dynamicvalue.common.ManacostVariableValue; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CounterUnlessPaysEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.Spell; -import mage.game.stack.StackObject; -import mage.players.Player; import mage.target.TargetSpell; -import mage.util.ManaUtil; import java.util.UUID; @@ -30,7 +18,7 @@ public final class Syncopate extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{U}"); // Counter target spell unless its controller pays {X}. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. - this.getSpellAbility().addEffect(new SyncopateCounterUnlessPaysEffect()); + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(ManacostVariableValue.instance, true)); this.getSpellAbility().addTarget(new TargetSpell()); } @@ -43,50 +31,3 @@ public final class Syncopate extends CardImpl { return new Syncopate(this); } } - -class SyncopateCounterUnlessPaysEffect extends OneShotEffect { - - public SyncopateCounterUnlessPaysEffect() { - super(Outcome.Detriment); - } - - public SyncopateCounterUnlessPaysEffect(final SyncopateCounterUnlessPaysEffect effect) { - super(effect); - } - - @Override - public SyncopateCounterUnlessPaysEffect copy() { - return new SyncopateCounterUnlessPaysEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - StackObject spell = game.getStack().getStackObject(targetPointer.getFirst(game, source)); - MageObject sourceObject = source.getSourceObject(game); - if ((spell instanceof Spell) && sourceObject != null) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - // can be zero cost - Cost cost = ManaUtil.createManaCost(ManacostVariableValue.instance, game, source, this); - if (!cost.pay(source, game, source, spell.getControllerId(), false)) { - StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget()); - if (stackObject != null && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, source.getFirstTarget(), source, stackObject.getControllerId()))) { - game.informPlayers(sourceObject.getIdName() + ": cost wasn't payed - countering " + stackObject.getName()); - game.rememberLKI(source.getFirstTarget(), Zone.STACK, stackObject); - controller.moveCards((Spell) spell, Zone.EXILED, source, game); - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, source.getFirstTarget(), source, stackObject.getControllerId())); - return true; - } - return false; - } - } - } - return false; - } - - @Override - public String getText(Mode mode) { - return "Counter target spell unless its controller pays {X}. If that spell is countered this way, exile it instead of putting it into its owner's graveyard"; - } - -} diff --git a/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java b/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java index f53e82c00e..fa17181e31 100644 --- a/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java +++ b/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java @@ -194,6 +194,7 @@ public final class StrixhavenSchoolOfMages extends ExpansionSet { cards.add(new SetCardInfo("Reckless Amplimancer", 141, Rarity.COMMON, mage.cards.r.RecklessAmplimancer.class)); cards.add(new SetCardInfo("Reconstruct History", 222, Rarity.UNCOMMON, mage.cards.r.ReconstructHistory.class)); cards.add(new SetCardInfo("Reduce to Memory", 25, Rarity.UNCOMMON, mage.cards.r.ReduceToMemory.class)); + cards.add(new SetCardInfo("Reject", 50, Rarity.COMMON, mage.cards.r.Reject.class)); cards.add(new SetCardInfo("Relic Sloth", 223, Rarity.COMMON, mage.cards.r.RelicSloth.class)); cards.add(new SetCardInfo("Resculpt", 51, Rarity.COMMON, mage.cards.r.Resculpt.class)); cards.add(new SetCardInfo("Returned Pastcaller", 224, Rarity.UNCOMMON, mage.cards.r.ReturnedPastcaller.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java index 6105581a7f..1419a03210 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CounterUnlessPaysEffect.java @@ -7,6 +7,8 @@ import mage.abilities.costs.mana.ManaCost; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; +import mage.constants.Zone; +import mage.constants.ZoneDetail; import mage.game.Game; import mage.game.stack.StackObject; import mage.players.Player; @@ -19,15 +21,26 @@ public class CounterUnlessPaysEffect extends OneShotEffect { protected Cost cost; protected DynamicValue genericMana; + private final boolean exile; public CounterUnlessPaysEffect(Cost cost) { + this(cost, false); + } + + public CounterUnlessPaysEffect(Cost cost, boolean exile) { super(Outcome.Detriment); this.cost = cost; + this.exile = exile; } public CounterUnlessPaysEffect(DynamicValue genericMana) { + this(genericMana, false); + } + + public CounterUnlessPaysEffect(DynamicValue genericMana, boolean exile) { super(Outcome.Detriment); this.genericMana = genericMana; + this.exile = exile; } public CounterUnlessPaysEffect(final CounterUnlessPaysEffect effect) { @@ -38,6 +51,7 @@ public class CounterUnlessPaysEffect extends OneShotEffect { if (effect.genericMana != null) { this.genericMana = effect.genericMana.copy(); } + this.exile = effect.exile; } @Override @@ -48,35 +62,40 @@ public class CounterUnlessPaysEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { StackObject spell = game.getStack().getStackObject(targetPointer.getFirst(game, source)); - if (spell != null) { - Player player = game.getPlayer(spell.getControllerId()); - if (player != null) { - Cost costToPay; - String costValueMessage; - if (cost != null) { - costToPay = cost.copy(); - costValueMessage = costToPay.getText(); - } else { - costToPay = ManaUtil.createManaCost(genericMana, game, source, this); - costValueMessage = "{" + genericMana.calculate(game, source, this) + "}"; - } - String message = ""; - if (costToPay instanceof ManaCost) { - message += "Pay "; - } - message += costValueMessage + '?'; + if (spell == null) { + return false; + } + Player player = game.getPlayer(spell.getControllerId()); + if (player == null) { + return false; + } + Cost costToPay; + String costValueMessage; + if (cost != null) { + costToPay = cost.copy(); + costValueMessage = costToPay.getText(); + } else { + costToPay = ManaUtil.createManaCost(genericMana, game, source, this); + costValueMessage = "{" + genericMana.calculate(game, source, this) + "}"; + } + String message = ""; + if (costToPay instanceof ManaCost) { + message += "Pay "; + } + message += costValueMessage + '?'; - costToPay.clearPaid(); - if (!(player.chooseUse(Outcome.Benefit, message, source, game) - && costToPay.pay(source, game, source, spell.getControllerId(), false, null))) { - game.informPlayers(player.getLogName() + " chooses not to pay " + costValueMessage + " to prevent the counter effect"); - return game.getStack().counter(spell.getId(), source, game); - } - game.informPlayers(player.getLogName() + " chooses to pay " + costValueMessage + " to prevent the counter effect"); - return true; + costToPay.clearPaid(); + if (!(player.chooseUse(Outcome.Benefit, message, source, game) + && costToPay.pay(source, game, source, spell.getControllerId(), false, null))) { + game.informPlayers(player.getLogName() + " chooses not to pay " + costValueMessage + " to prevent the counter effect"); + if (exile) { + game.getStack().counter(spell.getId(), source, game, Zone.EXILED, false, ZoneDetail.NONE); + } else { + return game.getStack().counter(spell.getId(), source, game); } } - return false; + game.informPlayers(player.getLogName() + " chooses to pay " + costValueMessage + " to prevent the counter effect"); + return true; } @Override @@ -101,6 +120,9 @@ public class CounterUnlessPaysEffect extends OneShotEffect { sb.append(", where X is "); sb.append(genericMana.getMessage()); } + if (exile) { + sb.append(". If that spell is countered this way, exile it instead of putting into its owner's graveyard."); + } return sb.toString(); }