From e62d1c21242be412248d92fdc5b7026006da5004 Mon Sep 17 00:00:00 2001 From: Susucre <34709007+Susucre@users.noreply.github.com> Date: Tue, 9 Apr 2024 13:08:10 +0200 Subject: [PATCH] [OTC] Implement Thunderclap Drake --- .../src/mage/cards/c/CommandersInsignia.java | 44 +------ .../src/mage/cards/t/ThunderclapDrake.java | 108 ++++++++++++++++++ .../OutlawsOfThunderJunctionCommander.java | 1 + .../CopyNextSpellDelayedTriggeredAbility.java | 2 +- .../CommanderCastFromCommandZoneValue.java | 46 ++++++++ 5 files changed, 162 insertions(+), 39 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/t/ThunderclapDrake.java create mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/CommanderCastFromCommandZoneValue.java diff --git a/Mage.Sets/src/mage/cards/c/CommandersInsignia.java b/Mage.Sets/src/mage/cards/c/CommandersInsignia.java index 7548bf88d6f..9f423c80e63 100644 --- a/Mage.Sets/src/mage/cards/c/CommandersInsignia.java +++ b/Mage.Sets/src/mage/cards/c/CommandersInsignia.java @@ -1,18 +1,12 @@ package mage.cards.c; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.CommanderCastFromCommandZoneValue; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.CommanderCardType; import mage.constants.Duration; -import mage.game.Game; -import mage.players.Player; -import mage.watchers.common.CommanderPlaysCountWatcher; import java.util.UUID; @@ -25,9 +19,11 @@ public final class CommandersInsignia extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // Creatures you control get +1/+1 for each time you've cast your commander from the command zone this game. - this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( - CommandersInsigniaValue.instance, CommandersInsigniaValue.instance, Duration.WhileOnBattlefield - ).setText("Creatures you control get +1/+1 for each time you've cast your commander from the command zone this game."))); + this.addAbility(new SimpleStaticAbility( + new BoostControlledEffect( + CommanderCastFromCommandZoneValue.instance, CommanderCastFromCommandZoneValue.instance, Duration.WhileOnBattlefield + ).setText("Creatures you control get +1/+1 for each time you've cast your commander from the command zone this game.") + ).addHint(CommanderCastFromCommandZoneValue.getHint())); } private CommandersInsignia(final CommandersInsignia card) { @@ -38,32 +34,4 @@ public final class CommandersInsignia extends CardImpl { public CommandersInsignia copy() { return new CommandersInsignia(this); } -} - -enum CommandersInsigniaValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - Player player = game.getPlayer(sourceAbility.getControllerId()); - CommanderPlaysCountWatcher watcher = game.getState().getWatcher(CommanderPlaysCountWatcher.class); - if (player == null || watcher == null) { - return 0; - } - return game - .getCommandersIds(player, CommanderCardType.COMMANDER_OR_OATHBREAKER, false) - .stream() - .mapToInt(watcher::getPlaysCount) - .sum(); - } - - @Override - public DynamicValue copy() { - return instance; - } - - @Override - public String getMessage() { - return ""; - } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/ThunderclapDrake.java b/Mage.Sets/src/mage/cards/t/ThunderclapDrake.java new file mode 100644 index 00000000000..d2aefcc0bd0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThunderclapDrake.java @@ -0,0 +1,108 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.CommanderCastFromCommandZoneValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.common.FilterInstantOrSorceryCard; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class ThunderclapDrake extends CardImpl { + + private static final FilterCard filter = new FilterInstantOrSorceryCard("instant and sorcery spells"); + + public ThunderclapDrake(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.DRAKE); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Instant and sorcery spells you cast cost {1} less to cast. + this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1))); + + // {2}{U}, Sacrifice Thunderclap Drake: When you cast your next instant or sorcery spell this turn, copy it for each time you've cast your commander from the command zone this game. You may choose new targets for the copies. + Ability ability = new SimpleActivatedAbility( + new CreateDelayedTriggeredAbilityEffect( + new CopyNextSpellDelayedTriggeredAbility( + StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, + new ThunderclapDrakeEffect(), + "When you cast your next instant or sorcery spell this turn, " + + "copy it for each time you've cast your commander from the command zone this game. " + + "You may choose new targets for the copies." + ) + ), + new ManaCostsImpl<>("{2}{U}") + ); + ability.addCost(new SacrificeSourceCost()); + ability.addHint(CommanderCastFromCommandZoneValue.getHint()); + this.addAbility(ability); + } + + private ThunderclapDrake(final ThunderclapDrake card) { + super(card); + } + + @Override + public ThunderclapDrake copy() { + return new ThunderclapDrake(this); + } +} + +// Inspired by CommanderStormEffect +class ThunderclapDrakeEffect extends OneShotEffect { + + ThunderclapDrakeEffect() { + super(Outcome.Copy); + staticText = "copy it for each time you've cast your commander from the command zone this game. " + + "You may choose new targets for the copies"; + } + + private ThunderclapDrakeEffect(final ThunderclapDrakeEffect effect) { + super(effect); + } + + @Override + public ThunderclapDrakeEffect copy() { + return new ThunderclapDrakeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Spell spell = (Spell) this.getValue("spellCast"); + int count = CommanderCastFromCommandZoneValue.instance.calculate(game, source, this); + if (spell == null || player == null || count <= 0) { + return false; + } + game.informPlayers(spell.getLogName() + " will be copied " + count + " time" + (count > 1 ? "s" : "") + CardUtil.getSourceLogName(game, source)); + spell.createCopyOnStack(game, source, source.getControllerId(), true, count); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/OutlawsOfThunderJunctionCommander.java b/Mage.Sets/src/mage/sets/OutlawsOfThunderJunctionCommander.java index 42ef0c278a8..99fdbe5a8cc 100644 --- a/Mage.Sets/src/mage/sets/OutlawsOfThunderJunctionCommander.java +++ b/Mage.Sets/src/mage/sets/OutlawsOfThunderJunctionCommander.java @@ -282,6 +282,7 @@ public final class OutlawsOfThunderJunctionCommander extends ExpansionSet { cards.add(new SetCardInfo("Third Path Iconoclast", 244, Rarity.UNCOMMON, mage.cards.t.ThirdPathIconoclast.class)); cards.add(new SetCardInfo("Three Visits", 209, Rarity.UNCOMMON, mage.cards.t.ThreeVisits.class)); cards.add(new SetCardInfo("Thrilling Discovery", 245, Rarity.COMMON, mage.cards.t.ThrillingDiscovery.class)); + cards.add(new SetCardInfo("Thunderclap Drake", 17, Rarity.RARE, mage.cards.t.ThunderclapDrake.class)); cards.add(new SetCardInfo("Titania, Protector of Argoth", 210, Rarity.MYTHIC, mage.cards.t.TitaniaProtectorOfArgoth.class)); cards.add(new SetCardInfo("Tower Winder", 34, Rarity.RARE, mage.cards.t.TowerWinder.class)); cards.add(new SetCardInfo("Trailblazer's Boots", 269, Rarity.UNCOMMON, mage.cards.t.TrailblazersBoots.class)); diff --git a/Mage/src/main/java/mage/abilities/common/delayed/CopyNextSpellDelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/CopyNextSpellDelayedTriggeredAbility.java index 7831c0b940c..e8a14f4a4b4 100644 --- a/Mage/src/main/java/mage/abilities/common/delayed/CopyNextSpellDelayedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/delayed/CopyNextSpellDelayedTriggeredAbility.java @@ -33,7 +33,7 @@ public class CopyNextSpellDelayedTriggeredAbility extends DelayedTriggeredAbilit this.rule = rule; } - private CopyNextSpellDelayedTriggeredAbility(final CopyNextSpellDelayedTriggeredAbility ability) { + protected CopyNextSpellDelayedTriggeredAbility(final CopyNextSpellDelayedTriggeredAbility ability) { super(ability); this.filter = ability.filter; this.rule = ability.rule; diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CommanderCastFromCommandZoneValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CommanderCastFromCommandZoneValue.java new file mode 100644 index 00000000000..b7ad0c3678e --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CommanderCastFromCommandZoneValue.java @@ -0,0 +1,46 @@ +package mage.abilities.dynamicvalue.common; + + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.constants.CommanderCardType; +import mage.game.Game; +import mage.players.Player; +import mage.watchers.common.CommanderPlaysCountWatcher; + +public enum CommanderCastFromCommandZoneValue implements DynamicValue { + instance; + + private static final Hint hint = new ValueHint("Number of times you cast your commander from command zone", instance); + + public static Hint getHint() { + return hint; + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + Player player = game.getPlayer(sourceAbility.getControllerId()); + CommanderPlaysCountWatcher watcher = game.getState().getWatcher(CommanderPlaysCountWatcher.class); + if (player == null || watcher == null) { + return 0; + } + return game + .getCommandersIds(player, CommanderCardType.COMMANDER_OR_OATHBREAKER, false) + .stream() + .mapToInt(watcher::getPlaysCount) + .sum(); + } + + @Override + public DynamicValue copy() { + return instance; + } + + @Override + public String getMessage() { + return ""; + } +} \ No newline at end of file