From 9f1031f286d49e66ff8d7cb3ca37fcc2b1952eb0 Mon Sep 17 00:00:00 2001 From: grimreap124 <19590931+grimreap124@users.noreply.github.com> Date: Mon, 2 Sep 2024 03:40:54 +1000 Subject: [PATCH] Implement [M3C] Blaster Hulk/Create EnergySpentOrLostThisTurnCount and update Izzet Generatorium (#12426) * Implement-M3C-Blaster-Hulk * Update BlasterHulk.java * Update BlasterHulk to fix number of targets --------- Co-authored-by: Grath <1895280+Grath@users.noreply.github.com> --- Mage.Sets/src/mage/cards/b/BlasterHulk.java | 68 +++++++++++++++++++ .../src/mage/cards/i/IzzetGeneratorium.java | 68 ++----------------- .../mage/sets/ModernHorizons3Commander.java | 1 + .../EnergySpentOrLostThisTurnCount.java | 31 +++++++++ .../common/EnergySpentOrLostWatcher.java | 47 +++++++++++++ 5 files changed, 152 insertions(+), 63 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/b/BlasterHulk.java create mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/EnergySpentOrLostThisTurnCount.java create mode 100644 Mage/src/main/java/mage/watchers/common/EnergySpentOrLostWatcher.java diff --git a/Mage.Sets/src/mage/cards/b/BlasterHulk.java b/Mage.Sets/src/mage/cards/b/BlasterHulk.java new file mode 100644 index 00000000000..955a1737d4d --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BlasterHulk.java @@ -0,0 +1,68 @@ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAloneSourceTriggeredAbility; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.delayed.ReflexiveTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.costs.common.PayEnergyCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.AttackingCreatureCount; +import mage.abilities.dynamicvalue.common.EnergySpentOrLostThisTurnCount; +import mage.abilities.effects.common.DamageMultiEffect; +import mage.abilities.effects.common.DoWhenCostPaid; +import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect; +import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; +import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; +import mage.abilities.hint.ValueHint; +import mage.constants.SubType; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.common.TargetAnyTargetAmount; + +/** + * + * @author grimreap124 + */ +public final class BlasterHulk extends CardImpl { + + public BlasterHulk(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}{R}{R}"); + + this.subtype.add(SubType.PIRATE); + this.power = new MageInt(8); + this.toughness = new MageInt(8); + + // This spell costs {1} less to cast for each {E} you've paid or lost this turn. + DynamicValue xValue = EnergySpentOrLostThisTurnCount.instance; + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue)) + .addHint(new ValueHint("{E} you've paid or lost this turn", xValue)) + ); + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever Blaster Hulk attacks, you get {E}{E}, then you may pay eight {E}. When you do, Blaster Hulk deals 8 damage divided as you choose among up to eight targets. + Ability ability = new AttacksTriggeredAbility(new GetEnergyCountersControllerEffect(2)); + ReflexiveTriggeredAbility reflexiveAbility = new ReflexiveTriggeredAbility(new DamageMultiEffect(8).setText("{this} deals 8 damage divided as you choose among up to eight targets"), false); + reflexiveAbility.addTarget(new TargetAnyTargetAmount(8)); + ability.addEffect(new DoWhenCostPaid(reflexiveAbility, new PayEnergyCost(8), "Pay eight {E} to deal 8 damage divided as you choose among up to eight targets?")); + + this.addAbility(ability); + } + + private BlasterHulk(final BlasterHulk card) { + super(card); + } + + @Override + public BlasterHulk copy() { + return new BlasterHulk(this); + } +} diff --git a/Mage.Sets/src/mage/cards/i/IzzetGeneratorium.java b/Mage.Sets/src/mage/cards/i/IzzetGeneratorium.java index 437928cd840..87059b58f92 100644 --- a/Mage.Sets/src/mage/cards/i/IzzetGeneratorium.java +++ b/Mage.Sets/src/mage/cards/i/IzzetGeneratorium.java @@ -7,6 +7,7 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.IntCompareCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.EnergySpentOrLostThisTurnCount; import mage.abilities.effects.Effect; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -20,6 +21,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.util.CardUtil; import mage.watchers.Watcher; +import mage.watchers.common.EnergySpentOrLostWatcher; import java.util.HashMap; import java.util.Map; @@ -31,7 +33,7 @@ import java.util.UUID; public final class IzzetGeneratorium extends CardImpl { private static final Condition condition = new IzzetGeneratoriumCondition(); - private static final Hint hint = new ValueHint("{E} paid or lost this turn", IzzetGeneratoriumValue.instance); + private static final Hint hint = new ValueHint("{E} paid or lost this turn", EnergySpentOrLostThisTurnCount.instance); public IzzetGeneratorium(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{U}{R}"); @@ -44,7 +46,7 @@ public final class IzzetGeneratorium extends CardImpl { new DrawCardSourceControllerEffect(1), new TapSourceCost(), condition - ).addHint(hint), new IzzetGeneratoriumWatcher()); + ).addHint(hint), new EnergySpentOrLostWatcher()); } private IzzetGeneratorium(final IzzetGeneratorium card) { @@ -100,71 +102,11 @@ class IzzetGeneratoriumCondition extends IntCompareCondition { @Override protected int getInputValue(Game game, Ability source) { - return IzzetGeneratoriumValue.instance.calculate(game, source, null); + return EnergySpentOrLostThisTurnCount.instance.calculate(game, source, null); } @Override public String toString() { return "if you've paid or lost four or more {E} this turn"; } -} - -enum IzzetGeneratoriumValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return IzzetGeneratoriumWatcher.getAmountEnergyLostOrSpentThisTurn(game, sourceAbility.getControllerId()); - } - - @Override - public IzzetGeneratoriumValue copy() { - return this; - } - - @Override - public String getMessage() { - return "{E} spent or lost this turn"; - } - - @Override - public String toString() { - return "X"; - } -} - -class IzzetGeneratoriumWatcher extends Watcher { - - // player -> amount of energy spent or lost this turn - private final Map energyLostOrSpent = new HashMap<>(); - - IzzetGeneratoriumWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() != GameEvent.EventType.COUNTERS_REMOVED) { - return; - } - if (!event.getData().equals(CounterType.ENERGY.getName())) { - return; - } - int amount = event.getAmount(); - if (amount <= 0) { - return; - } - energyLostOrSpent.compute(event.getTargetId(), (k, i) -> i == null ? amount : Integer.sum(i, amount)); - } - - @Override - public void reset() { - super.reset(); - energyLostOrSpent.clear(); - } - - public static int getAmountEnergyLostOrSpentThisTurn(Game game, UUID playerId) { - IzzetGeneratoriumWatcher watcher = game.getState().getWatcher(IzzetGeneratoriumWatcher.class); - return watcher == null ? 0 : watcher.energyLostOrSpent.getOrDefault(playerId, 0); - } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java b/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java index bc21033183d..7ab7af86874 100644 --- a/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java +++ b/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java @@ -59,6 +59,7 @@ public final class ModernHorizons3Commander extends ExpansionSet { cards.add(new SetCardInfo("Bismuth Mindrender", 51, Rarity.RARE, mage.cards.b.BismuthMindrender.class)); cards.add(new SetCardInfo("Bituminous Blast", 255, Rarity.UNCOMMON, mage.cards.b.BituminousBlast.class)); cards.add(new SetCardInfo("Blast Zone", 322, Rarity.RARE, mage.cards.b.BlastZone.class)); + cards.add(new SetCardInfo("Blaster Hulk", 55, Rarity.RARE, mage.cards.b.BlasterHulk.class)); cards.add(new SetCardInfo("Bloodbraid Challenger", 70, Rarity.RARE, mage.cards.b.BloodbraidChallenger.class)); cards.add(new SetCardInfo("Bloodbraid Elf", 256, Rarity.UNCOMMON, mage.cards.b.BloodbraidElf.class)); cards.add(new SetCardInfo("Bonders' Enclave", 323, Rarity.RARE, mage.cards.b.BondersEnclave.class)); diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/EnergySpentOrLostThisTurnCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/EnergySpentOrLostThisTurnCount.java new file mode 100644 index 00000000000..ab8dec711c9 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/EnergySpentOrLostThisTurnCount.java @@ -0,0 +1,31 @@ +package mage.abilities.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.game.Game; +import mage.watchers.common.EnergySpentOrLostWatcher; + +public enum EnergySpentOrLostThisTurnCount implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return EnergySpentOrLostWatcher.getAmountEnergyLostOrSpentThisTurn(game, sourceAbility.getControllerId()); + } + + @Override + public EnergySpentOrLostThisTurnCount copy() { + return this; + } + + @Override + public String getMessage() { + return "{E} spent or lost this turn"; + } + + @Override + public String toString() { + return "X"; + } +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/watchers/common/EnergySpentOrLostWatcher.java b/Mage/src/main/java/mage/watchers/common/EnergySpentOrLostWatcher.java new file mode 100644 index 00000000000..c06cc097755 --- /dev/null +++ b/Mage/src/main/java/mage/watchers/common/EnergySpentOrLostWatcher.java @@ -0,0 +1,47 @@ +package mage.watchers.common; + +import mage.constants.WatcherScope; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.watchers.Watcher; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class EnergySpentOrLostWatcher extends Watcher { + + // player -> amount of energy spent or lost this turn + private final Map energyLostOrSpent = new HashMap<>(); + + public EnergySpentOrLostWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() != GameEvent.EventType.COUNTERS_REMOVED) { + return; + } + if (!event.getData().equals(CounterType.ENERGY.getName())) { + return; + } + int amount = event.getAmount(); + if (amount <= 0) { + return; + } + energyLostOrSpent.compute(event.getTargetId(), (k, i) -> i == null ? amount : Integer.sum(i, amount)); + } + + @Override + public void reset() { + super.reset(); + energyLostOrSpent.clear(); + } + + public static int getAmountEnergyLostOrSpentThisTurn(Game game, UUID playerId) { + EnergySpentOrLostWatcher watcher = game.getState().getWatcher(EnergySpentOrLostWatcher.class); + return watcher == null ? 0 : watcher.energyLostOrSpent.getOrDefault(playerId, 0); + } +} \ No newline at end of file