From 8bae73cea3e23d5cc0484fdfaeb1979d4475c412 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 1 Oct 2025 13:26:41 -0400 Subject: [PATCH] [FIC] Implement Amarant Coral --- Mage.Sets/src/mage/cards/a/AmarantCoral.java | 50 ++++++++++++++++ .../src/mage/cards/g/GrenzosRuffians.java | 49 ++-------------- Mage.Sets/src/mage/cards/h/HydraOmnivore.java | 49 ++-------------- .../mage/cards/k/KoseiPenitentWarlord.java | 58 ++++--------------- .../mage/cards/v/VincentVengefulAtoner.java | 48 ++++----------- .../src/mage/sets/FinalFantasyCommander.java | 1 + ...DamageEachOtherOpponentThatMuchEffect.java | 47 +++++++++++++++ 7 files changed, 130 insertions(+), 172 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/a/AmarantCoral.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageEachOtherOpponentThatMuchEffect.java diff --git a/Mage.Sets/src/mage/cards/a/AmarantCoral.java b/Mage.Sets/src/mage/cards/a/AmarantCoral.java new file mode 100644 index 00000000000..cbb41f5a7cc --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AmarantCoral.java @@ -0,0 +1,50 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.common.AttacksEachCombatStaticAbility; +import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; +import mage.abilities.effects.common.DamageEachOtherOpponentThatMuchEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AmarantCoral extends CardImpl { + + public AmarantCoral(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.MONK); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Amarant Coral attacks each combat if able. + this.addAbility(new AttacksEachCombatStaticAbility()); + + // No Mercy -- Whenever Amarant Coral deals combat damage to an opponent, it deals that much damage to each other opponent. + this.addAbility(new DealsDamageToOpponentTriggeredAbility( + new DamageEachOtherOpponentThatMuchEffect(), false, true, true + ).withFlavorWord("No Mercy")); + } + + private AmarantCoral(final AmarantCoral card) { + super(card); + } + + @Override + public AmarantCoral copy() { + return new AmarantCoral(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GrenzosRuffians.java b/Mage.Sets/src/mage/cards/g/GrenzosRuffians.java index ab9fadddcf0..2fef6143541 100644 --- a/Mage.Sets/src/mage/cards/g/GrenzosRuffians.java +++ b/Mage.Sets/src/mage/cards/g/GrenzosRuffians.java @@ -1,20 +1,14 @@ package mage.cards.g; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageEachOtherOpponentThatMuchEffect; import mage.abilities.keyword.MeleeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; -import mage.game.Game; -import mage.players.Player; -import java.util.Objects; import java.util.UUID; /** @@ -33,7 +27,9 @@ public final class GrenzosRuffians extends CardImpl { this.addAbility(new MeleeAbility()); // Whenever Grenzo's Ruffians deals combat damage to a opponent, it deals that much damage to each other opponent. - this.addAbility(new DealsDamageToOpponentTriggeredAbility(new GrenzosRuffiansEffect(), false, true, true)); + this.addAbility(new DealsDamageToOpponentTriggeredAbility( + new DamageEachOtherOpponentThatMuchEffect(), false, true, true + )); } private GrenzosRuffians(final GrenzosRuffians card) { @@ -45,40 +41,3 @@ public final class GrenzosRuffians extends CardImpl { return new GrenzosRuffians(this); } } - -class GrenzosRuffiansEffect extends OneShotEffect { - - GrenzosRuffiansEffect() { - super(Outcome.Benefit); - this.staticText = "it deals that much damage to each other opponent"; - } - - private GrenzosRuffiansEffect(final GrenzosRuffiansEffect effect) { - super(effect); - } - - @Override - public GrenzosRuffiansEffect copy() { - return new GrenzosRuffiansEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - UUID damagedOpponent = this.getTargetPointer().getFirst(game, source); - int amount = (Integer) getValue("damage"); - MageObject object = game.getObject(source); - if (object != null && amount > 0 && damagedOpponent != null) { - for (UUID playerId : game.getOpponents(source.getControllerId())) { - if (!Objects.equals(playerId, damagedOpponent)) { - Player opponent = game.getPlayer(playerId); - if (opponent != null) { - int dealtDamage = opponent.damage(amount, source.getSourceId(), source, game); - game.informPlayers(object.getLogName() + " deals " + dealtDamage + " damage to " + opponent.getLogName()); - } - } - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/h/HydraOmnivore.java b/Mage.Sets/src/mage/cards/h/HydraOmnivore.java index 486ae844ed4..d5d637d0232 100644 --- a/Mage.Sets/src/mage/cards/h/HydraOmnivore.java +++ b/Mage.Sets/src/mage/cards/h/HydraOmnivore.java @@ -1,19 +1,13 @@ package mage.cards.h; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageEachOtherOpponentThatMuchEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; -import mage.game.Game; -import mage.players.Player; -import java.util.Objects; import java.util.UUID; /** @@ -29,7 +23,9 @@ public final class HydraOmnivore extends CardImpl { this.toughness = new MageInt(8); // Whenever Hydra Omnivore deals combat damage to an opponent, it deals that much damage to each other opponent. - this.addAbility(new DealsDamageToOpponentTriggeredAbility(new HydraOmnivoreEffect(), false, true, true)); + this.addAbility(new DealsDamageToOpponentTriggeredAbility( + new DamageEachOtherOpponentThatMuchEffect(), false, true, true + )); } private HydraOmnivore(final HydraOmnivore card) { @@ -41,40 +37,3 @@ public final class HydraOmnivore extends CardImpl { return new HydraOmnivore(this); } } - -class HydraOmnivoreEffect extends OneShotEffect { - - HydraOmnivoreEffect() { - super(Outcome.Benefit); - this.staticText = "it deals that much damage to each other opponent"; - } - - private HydraOmnivoreEffect(final HydraOmnivoreEffect effect) { - super(effect); - } - - @Override - public HydraOmnivoreEffect copy() { - return new HydraOmnivoreEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - UUID damagedOpponent = this.getTargetPointer().getFirst(game, source); - int amount = (Integer) getValue("damage"); - MageObject object = game.getObject(source); - if (object != null && amount > 0 && damagedOpponent != null) { - for (UUID playerId : game.getOpponents(source.getControllerId())) { - if (!Objects.equals(playerId, damagedOpponent)) { - Player opponent = game.getPlayer(playerId); - if (opponent != null) { - int dealtDamage = opponent.damage(amount, source.getSourceId(), source, game); - game.informPlayers(object.getLogName() + " deals " + dealtDamage + " damage to " + opponent.getLogName()); - } - } - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/k/KoseiPenitentWarlord.java b/Mage.Sets/src/mage/cards/k/KoseiPenitentWarlord.java index 7765989d096..fd0655969a9 100644 --- a/Mage.Sets/src/mage/cards/k/KoseiPenitentWarlord.java +++ b/Mage.Sets/src/mage/cards/k/KoseiPenitentWarlord.java @@ -6,18 +6,18 @@ import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.SavedDamageValue; +import mage.abilities.effects.common.DamageEachOtherOpponentThatMuchEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.SuperType; import mage.counters.Counter; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; import java.util.Objects; import java.util.UUID; @@ -37,12 +37,16 @@ public final class KoseiPenitentWarlord extends CardImpl { this.toughness = new MageInt(5); // As long as Kosei, Penitent Warlord is enchanted, equipped, and has a counter on it, Kosei has "Whenever Kosei, Penitent Warlord deals combat damage to an opponent, you draw that many cards and Kosei deals that much damage to each other opponent." + Ability ability = new DealsDamageToOpponentTriggeredAbility( + new DrawCardSourceControllerEffect(SavedDamageValue.MANY), + false, true, true + ); + ability.addEffect(new DamageEachOtherOpponentThatMuchEffect() + .setText("and {this} deals that much damage to each other opponent")); this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( - new GainAbilitySourceEffect(new DealsDamageToOpponentTriggeredAbility( - new KoseiPenitentWarlordEffect(), false, true, true - )), KoseiPenitentWarlordCondition.instance, "as long as {this} is enchanted, equipped, " + - "and has a counter on it, {this} has \"Whenever {this} deals combat damage to an opponent, " + - "you draw that many cards and {this} deals that much damage to each other opponent.\"" + new GainAbilitySourceEffect(ability), KoseiPenitentWarlordCondition.instance, "as long as " + + "{this} is enchanted, equipped, and has a counter on it, {this} has \"Whenever {this} deals combat " + + "damage to an opponent, you draw that many cards and {this} deals that much damage to each other opponent.\"" ))); } @@ -82,41 +86,3 @@ enum KoseiPenitentWarlordCondition implements Condition { .anyMatch(permanent -> permanent.hasSubtype(SubType.AURA, game)); } } - -class KoseiPenitentWarlordEffect extends OneShotEffect { - - KoseiPenitentWarlordEffect() { - super(Outcome.Benefit); - staticText = "you draw that many cards and {this} deals that much damage to each other opponent"; - } - - private KoseiPenitentWarlordEffect(final KoseiPenitentWarlordEffect effect) { - super(effect); - } - - @Override - public KoseiPenitentWarlordEffect copy() { - return new KoseiPenitentWarlordEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - int damage = (Integer) getValue("damage"); - if (controller == null || damage < 1) { - return false; - } - controller.drawCards(damage, source, game); - UUID damagedOpponentId = getTargetPointer().getFirst(game, source); - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - if (opponentId.equals(damagedOpponentId)) { - continue; - } - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - opponent.damage(damage, source, game); - } - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/v/VincentVengefulAtoner.java b/Mage.Sets/src/mage/cards/v/VincentVengefulAtoner.java index 40dbccab205..8008cff4965 100644 --- a/Mage.Sets/src/mage/cards/v/VincentVengefulAtoner.java +++ b/Mage.Sets/src/mage/cards/v/VincentVengefulAtoner.java @@ -5,13 +5,14 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DamageEachOtherOpponentThatMuchEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.MenaceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.SuperType; import mage.counters.CounterType; @@ -42,9 +43,10 @@ public final class VincentVengefulAtoner extends CardImpl { )); // Chaos -- Whenever Vincent deals combat damage to an opponent, it deals that much damage to each other opponent if Vincent's power is 7 or greater. - this.addAbility(new DealsDamageToOpponentTriggeredAbility( - new VincentVengefulAtonerEffect(), false, true, true - ).withFlavorWord("Chaos")); + this.addAbility(new DealsDamageToOpponentTriggeredAbility(new ConditionalOneShotEffect( + new DamageEachOtherOpponentThatMuchEffect(), VincentVengefulAtonerCondition.instance, + "it deals that much damage to each other opponent if {this}'s power is 7 or greater" + ), false, true, true).withFlavorWord("Chaos")); } private VincentVengefulAtoner(final VincentVengefulAtoner card) { @@ -57,42 +59,16 @@ public final class VincentVengefulAtoner extends CardImpl { } } -class VincentVengefulAtonerEffect extends OneShotEffect { - - VincentVengefulAtonerEffect() { - super(Outcome.Benefit); - staticText = "it deals that much damage to each other opponent if {this}'s power is 7 or greater"; - } - - private VincentVengefulAtonerEffect(final VincentVengefulAtonerEffect effect) { - super(effect); - } - - @Override - public VincentVengefulAtonerEffect copy() { - return new VincentVengefulAtonerEffect(this); - } +enum VincentVengefulAtonerCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { - if (Optional + return Optional .ofNullable(source.getSourcePermanentOrLKI(game)) .map(MageObject::getPower) .map(MageInt::getValue) - .orElse(0) < 7) { - return false; - } - int amount = (Integer) getValue("damage"); - if (amount < 1) { - return false; - } - UUID targetId = getTargetPointer().getFirst(game, source); - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - Optional.ofNullable(opponentId) - .filter(uuid -> !uuid.equals(targetId)) - .map(game::getPlayer) - .map(player -> player.damage(amount, source, game)); - } - return true; + .filter(x -> x >= 7) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/sets/FinalFantasyCommander.java b/Mage.Sets/src/mage/sets/FinalFantasyCommander.java index 9bdb9842780..c6755827243 100644 --- a/Mage.Sets/src/mage/sets/FinalFantasyCommander.java +++ b/Mage.Sets/src/mage/sets/FinalFantasyCommander.java @@ -27,6 +27,7 @@ public final class FinalFantasyCommander extends ExpansionSet { cards.add(new SetCardInfo("Alphinaud Leveilleur", 140, Rarity.RARE, mage.cards.a.AlphinaudLeveilleur.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Alphinaud Leveilleur", 33, Rarity.RARE, mage.cards.a.AlphinaudLeveilleur.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Altered Ego", 317, Rarity.RARE, mage.cards.a.AlteredEgo.class)); + cards.add(new SetCardInfo("Amarant Coral", 457, Rarity.RARE, mage.cards.a.AmarantCoral.class)); cards.add(new SetCardInfo("An Offer You Can't Refuse", 267, Rarity.UNCOMMON, mage.cards.a.AnOfferYouCantRefuse.class)); cards.add(new SetCardInfo("Angel of the Ruins", 229, Rarity.UNCOMMON, mage.cards.a.AngelOfTheRuins.class)); cards.add(new SetCardInfo("Anger", 289, Rarity.UNCOMMON, mage.cards.a.Anger.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageEachOtherOpponentThatMuchEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageEachOtherOpponentThatMuchEffect.java new file mode 100644 index 00000000000..f7775a2a82e --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageEachOtherOpponentThatMuchEffect.java @@ -0,0 +1,47 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public class DamageEachOtherOpponentThatMuchEffect extends OneShotEffect { + + public DamageEachOtherOpponentThatMuchEffect() { + super(Outcome.Benefit); + staticText = "it deals that much damage to each other opponent"; + } + + private DamageEachOtherOpponentThatMuchEffect(final DamageEachOtherOpponentThatMuchEffect effect) { + super(effect); + } + + @Override + public DamageEachOtherOpponentThatMuchEffect copy() { + return new DamageEachOtherOpponentThatMuchEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int damage = (Integer) getValue("damage"); + if (damage < 1) { + return false; + } + UUID playerId = getTargetPointer().getFirst(game, source); + for (UUID opponentId : game.getOpponents(source.getControllerId())) { + if (opponentId.equals(playerId)) { + continue; + } + Optional.ofNullable(opponentId) + .map(game::getPlayer) + .ifPresent(player -> player.damage(damage, source, game)); + } + return true; + } +}