From cff38b74b9ff2453ad1b2985c01e226ce85da89b Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sat, 12 Feb 2022 14:27:35 -0500 Subject: [PATCH] [NEO] fixed implementation of March additional costs (#8524) --- .../mage/cards/m/MarchOfBurgeoningLife.java | 4 +- .../cards/m/MarchOfOtherworldlyLight.java | 4 +- .../src/mage/cards/m/MarchOfRecklessJoy.java | 4 +- .../src/mage/cards/m/MarchOfSwirlingMist.java | 4 +- .../mage/cards/m/MarchOfWretchedSorrow.java | 4 +- .../mage/abilities/costs/CostAdjuster.java | 5 +- .../ExileCardsFromHandAdjuster.java | 54 +++++++++++++ .../CostsLessForExiledCardsEffect.java | 76 ------------------- .../targetadjustment/TargetAdjuster.java | 6 +- 9 files changed, 72 insertions(+), 89 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/costs/costadjusters/ExileCardsFromHandAdjuster.java delete mode 100644 Mage/src/main/java/mage/abilities/effects/CostsLessForExiledCardsEffect.java diff --git a/Mage.Sets/src/mage/cards/m/MarchOfBurgeoningLife.java b/Mage.Sets/src/mage/cards/m/MarchOfBurgeoningLife.java index 72435cead6..784a9948af 100644 --- a/Mage.Sets/src/mage/cards/m/MarchOfBurgeoningLife.java +++ b/Mage.Sets/src/mage/cards/m/MarchOfBurgeoningLife.java @@ -2,7 +2,7 @@ package mage.cards.m; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.effects.CostsLessForExiledCardsEffect; +import mage.abilities.costs.costadjusters.ExileCardsFromHandAdjuster; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -43,7 +43,7 @@ public final class MarchOfBurgeoningLife extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{G}"); // As an additional cost to cast this spell, you may exile any number of green cards from your hand. This spell costs {2} less to cast for each card exiled this way. - CostsLessForExiledCardsEffect.addCostAndEffect(this, filter); + ExileCardsFromHandAdjuster.addAdjusterAndMessage(this, filter); // Choose target creature with mana value less than X. Search your library for a creature card with the same name as that creature, put it onto the battlefield tapped, then shuffle. this.getSpellAbility().addEffect(new MarchOfBurgeoningLifeEffect()); diff --git a/Mage.Sets/src/mage/cards/m/MarchOfOtherworldlyLight.java b/Mage.Sets/src/mage/cards/m/MarchOfOtherworldlyLight.java index a9f5058054..5d4738b038 100644 --- a/Mage.Sets/src/mage/cards/m/MarchOfOtherworldlyLight.java +++ b/Mage.Sets/src/mage/cards/m/MarchOfOtherworldlyLight.java @@ -2,7 +2,7 @@ package mage.cards.m; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.effects.CostsLessForExiledCardsEffect; +import mage.abilities.costs.costadjusters.ExileCardsFromHandAdjuster; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -34,7 +34,7 @@ public final class MarchOfOtherworldlyLight extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{W}"); // As an additional cost to cast this spell, you may exile any number of white cards from your hand. This spell costs {2} less to cast for each card exiled this way. - CostsLessForExiledCardsEffect.addCostAndEffect(this, filter); + ExileCardsFromHandAdjuster.addAdjusterAndMessage(this, filter); // Exile target artifact, creature, or enchantment with mana value X or less. this.getSpellAbility().addEffect(new ExileTargetEffect( diff --git a/Mage.Sets/src/mage/cards/m/MarchOfRecklessJoy.java b/Mage.Sets/src/mage/cards/m/MarchOfRecklessJoy.java index daf8356cfe..64c513c26d 100644 --- a/Mage.Sets/src/mage/cards/m/MarchOfRecklessJoy.java +++ b/Mage.Sets/src/mage/cards/m/MarchOfRecklessJoy.java @@ -12,10 +12,10 @@ import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.condition.Condition; +import mage.abilities.costs.costadjusters.ExileCardsFromHandAdjuster; import mage.abilities.decorator.ConditionalAsThoughEffect; import mage.abilities.dynamicvalue.common.ManacostVariableValue; import mage.abilities.effects.AsThoughEffectImpl; -import mage.abilities.effects.CostsLessForExiledCardsEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -53,7 +53,7 @@ public final class MarchOfRecklessJoy extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}"); // As an additional cost to cast this spell, you may exile any number of red cards from your hand. This spell costs {2} less to cast for each card exiled this way. - CostsLessForExiledCardsEffect.addCostAndEffect(this, filter); + ExileCardsFromHandAdjuster.addAdjusterAndMessage(this, filter); // Exile the top X cards of your library. You may play up to two of those cards until the end of your next turn. this.getSpellAbility().addEffect(new MarchOfRecklessJoyEffect()); diff --git a/Mage.Sets/src/mage/cards/m/MarchOfSwirlingMist.java b/Mage.Sets/src/mage/cards/m/MarchOfSwirlingMist.java index b4d6760762..0e96217d80 100644 --- a/Mage.Sets/src/mage/cards/m/MarchOfSwirlingMist.java +++ b/Mage.Sets/src/mage/cards/m/MarchOfSwirlingMist.java @@ -2,7 +2,7 @@ package mage.cards.m; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.effects.CostsLessForExiledCardsEffect; +import mage.abilities.costs.costadjusters.ExileCardsFromHandAdjuster; import mage.abilities.effects.common.PhaseOutTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class MarchOfSwirlingMist extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{U}"); // As an additional cost to cast this spell, you may exile any number of blue cards from your hand. This spell costs {2} less to cast for each card exiled this way. - CostsLessForExiledCardsEffect.addCostAndEffect(this, filter); + ExileCardsFromHandAdjuster.addAdjusterAndMessage(this, filter); // Up to X target creatures phase out. this.getSpellAbility().addEffect(new PhaseOutTargetEffect().setText("up to X target creatures phase out")); diff --git a/Mage.Sets/src/mage/cards/m/MarchOfWretchedSorrow.java b/Mage.Sets/src/mage/cards/m/MarchOfWretchedSorrow.java index b36ae0e023..3c61d72da5 100644 --- a/Mage.Sets/src/mage/cards/m/MarchOfWretchedSorrow.java +++ b/Mage.Sets/src/mage/cards/m/MarchOfWretchedSorrow.java @@ -1,8 +1,8 @@ package mage.cards.m; import mage.ObjectColor; +import mage.abilities.costs.costadjusters.ExileCardsFromHandAdjuster; import mage.abilities.dynamicvalue.common.ManacostVariableValue; -import mage.abilities.effects.CostsLessForExiledCardsEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; @@ -29,7 +29,7 @@ public final class MarchOfWretchedSorrow extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{B}"); // As an additional cost to cast this spell, you may exile any number of black cards from your hand. This spell costs {2} less to cast for each card exiled this way. - CostsLessForExiledCardsEffect.addCostAndEffect(this, filter); + ExileCardsFromHandAdjuster.addAdjusterAndMessage(this, filter); // March of Wretched Sorrow deals X damage to target creature or planeswalker and you gain X life. this.getSpellAbility().addEffect(new DamageTargetEffect(ManacostVariableValue.REGULAR)); diff --git a/Mage/src/main/java/mage/abilities/costs/CostAdjuster.java b/Mage/src/main/java/mage/abilities/costs/CostAdjuster.java index b7bc0d23a5..ea1d77449d 100644 --- a/Mage/src/main/java/mage/abilities/costs/CostAdjuster.java +++ b/Mage/src/main/java/mage/abilities/costs/CostAdjuster.java @@ -3,10 +3,13 @@ package mage.abilities.costs; import mage.abilities.Ability; import mage.game.Game; +import java.io.Serializable; + /** * @author TheElk801 */ -public interface CostAdjuster { +@FunctionalInterface +public interface CostAdjuster extends Serializable { /** * Must check playable and real cast states. diff --git a/Mage/src/main/java/mage/abilities/costs/costadjusters/ExileCardsFromHandAdjuster.java b/Mage/src/main/java/mage/abilities/costs/costadjusters/ExileCardsFromHandAdjuster.java new file mode 100644 index 0000000000..bdbe3b1023 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/costs/costadjusters/ExileCardsFromHandAdjuster.java @@ -0,0 +1,54 @@ +package mage.abilities.costs.costadjusters; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.CostAdjuster; +import mage.abilities.costs.common.ExileFromHandCost; +import mage.abilities.effects.common.InfoEffect; +import mage.cards.Card; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInHand; +import mage.util.CardUtil; + +/** + * @author TheElk801 + */ +public class ExileCardsFromHandAdjuster implements CostAdjuster { + + private final FilterCard filter; + + private ExileCardsFromHandAdjuster(FilterCard filter) { + this.filter = filter; + } + + @Override + public void adjustCosts(Ability ability, Game game) { + if (game.inCheckPlayableState()) { + return; + } + Player player = game.getPlayer(ability.getControllerId()); + if (player == null) { + return; + } + int cardCount = player.getHand().count(filter, game); + int toExile = cardCount > 0 ? player.getAmount( + 0, cardCount, "Choose how many " + filter.getMessage() + " to exile", game + ) : 0; + if (toExile > 0) { + ability.addCost(new ExileFromHandCost(new TargetCardInHand(toExile, filter))); + CardUtil.reduceCost(ability, 2 * toExile); + } + } + + public static final void addAdjusterAndMessage(Card card, FilterCard filter) { + card.addAbility(new SimpleStaticAbility( + Zone.ALL, + new InfoEffect("you may exile any number of " + filter.getMessage() + + ". This spell costs {2} less to cast for each card exiled this way") + )); + card.getSpellAbility().setCostAdjuster(new ExileCardsFromHandAdjuster(filter)); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/CostsLessForExiledCardsEffect.java b/Mage/src/main/java/mage/abilities/effects/CostsLessForExiledCardsEffect.java deleted file mode 100644 index 03d0870464..0000000000 --- a/Mage/src/main/java/mage/abilities/effects/CostsLessForExiledCardsEffect.java +++ /dev/null @@ -1,76 +0,0 @@ -package mage.abilities.effects; - -import mage.abilities.Ability; -import mage.abilities.SpellAbility; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.Cost; -import mage.abilities.costs.common.ExileFromHandCost; -import mage.abilities.effects.common.cost.CostModificationEffectImpl; -import mage.cards.Card; -import mage.constants.CostModificationType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.FilterCard; -import mage.game.Game; -import mage.target.common.TargetCardInHand; -import mage.util.CardUtil; - -/** - * @author TheElk801 - */ -public class CostsLessForExiledCardsEffect extends CostModificationEffectImpl { - - private final FilterCard filter; - - private CostsLessForExiledCardsEffect(FilterCard filter) { - super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST); - this.filter = filter; - } - - private CostsLessForExiledCardsEffect(final CostsLessForExiledCardsEffect effect) { - super(effect); - this.filter = effect.filter; - } - - @Override - public boolean apply(Game game, Ability source, Ability abilityToModify) { - SpellAbility spellAbility = (SpellAbility) abilityToModify; - for (Cost cost : spellAbility.getCosts()) { - if (!(cost instanceof ExileFromHandCost)) { - continue; - } - ExileFromHandCost eCost = (ExileFromHandCost) cost; - int reduction; - if (game.inCheckPlayableState()) { - reduction = game.getPlayer(spellAbility.getControllerId()).getHand().count(filter, game); - } else { - reduction = eCost.getCards().size(); - } - CardUtil.adjustCost(spellAbility, reduction * 2); - break; - } - return true; - } - - @Override - public boolean applies(Ability abilityToModify, Ability source, Game game) { - return abilityToModify instanceof SpellAbility - && abilityToModify.getSourceId().equals(source.getSourceId()); - } - - @Override - public CostsLessForExiledCardsEffect copy() { - return new CostsLessForExiledCardsEffect(this); - } - - public static void addCostAndEffect(Card card, FilterCard filter) { - card.getSpellAbility().addCost(new ExileFromHandCost( - new TargetCardInHand(0, Integer.MAX_VALUE, filter) - ).setText("you may exile any number of " + filter.getMessage() - + ". This spell costs {2} less to cast for each card exiled this way")); - Ability ability = new SimpleStaticAbility(Zone.ALL, new CostsLessForExiledCardsEffect(filter)); - ability.setRuleVisible(false); - card.addAbility(ability); - } -} diff --git a/Mage/src/main/java/mage/target/targetadjustment/TargetAdjuster.java b/Mage/src/main/java/mage/target/targetadjustment/TargetAdjuster.java index af173fa18f..2090445445 100644 --- a/Mage/src/main/java/mage/target/targetadjustment/TargetAdjuster.java +++ b/Mage/src/main/java/mage/target/targetadjustment/TargetAdjuster.java @@ -3,11 +3,13 @@ package mage.target.targetadjustment; import mage.abilities.Ability; import mage.game.Game; +import java.io.Serializable; + /** * @author TheElk801 */ -public interface TargetAdjuster { +@FunctionalInterface +public interface TargetAdjuster extends Serializable { void adjustTargets(Ability ability, Game game); - }