From 6cc717470a773e43549eca5f662e16249aac7052 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 14 May 2025 14:30:46 -0400 Subject: [PATCH] [FIN] Implement Sephiroth, Fabled SOLDIER / Sephiroth, One-Winged Angel --- .../mage/cards/s/SephirothFabledSOLDIER.java | 61 ++++++++ .../mage/cards/s/SephirothOneWingedAngel.java | 136 ++++++++++++++++++ Mage.Sets/src/mage/sets/FinalFantasy.java | 10 ++ .../SephirothOneWingedAngelEmblem.java | 37 +++++ 4 files changed, 244 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SephirothFabledSOLDIER.java create mode 100644 Mage.Sets/src/mage/cards/s/SephirothOneWingedAngel.java create mode 100644 Mage/src/main/java/mage/game/command/emblems/SephirothOneWingedAngelEmblem.java diff --git a/Mage.Sets/src/mage/cards/s/SephirothFabledSOLDIER.java b/Mage.Sets/src/mage/cards/s/SephirothFabledSOLDIER.java new file mode 100644 index 00000000000..2ce8c407227 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SephirothFabledSOLDIER.java @@ -0,0 +1,61 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.*; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; +import mage.watchers.common.AbilityResolvedWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SephirothFabledSOLDIER extends CardImpl { + + public SephirothFabledSOLDIER(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.AVATAR); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.s.SephirothOneWingedAngel.class; + + // Whenever Sephiroth enters or attacks, you may sacrifice another creature. If you do, draw a card. + this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DoIfCostPaid( + new DrawCardSourceControllerEffect(1), + new SacrificeTargetCost(StaticFilters.FILTER_ANOTHER_CREATURE) + ))); + + // Whenever another creature dies, target opponent loses 1 life and you gain 1 life. If this is the fourth time this ability has resolved this turn, transform Sephiroth. + this.addAbility(new TransformAbility()); + Ability ability = new DiesCreatureTriggeredAbility( + new LoseLifeTargetEffect(1), false, + StaticFilters.FILTER_ANOTHER_CREATURE + ); + ability.addEffect(new GainLifeEffect(1).concatBy("and")); + ability.addEffect(new IfAbilityHasResolvedXTimesEffect(4, new TransformSourceEffect())); + this.addAbility(ability, new AbilityResolvedWatcher()); + } + + private SephirothFabledSOLDIER(final SephirothFabledSOLDIER card) { + super(card); + } + + @Override + public SephirothFabledSOLDIER copy() { + return new SephirothFabledSOLDIER(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SephirothOneWingedAngel.java b/Mage.Sets/src/mage/cards/s/SephirothOneWingedAngel.java new file mode 100644 index 00000000000..7b4cb758e14 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SephirothOneWingedAngel.java @@ -0,0 +1,136 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.command.emblems.SephirothOneWingedAngelEmblem; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetSacrifice; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SephirothOneWingedAngel extends CardImpl { + + public SephirothOneWingedAngel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.ANGEL); + this.subtype.add(SubType.NIGHTMARE); + this.subtype.add(SubType.AVATAR); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + this.nightCard = true; + this.color.setBlack(true); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Super Nova -- As this creature transforms into Sephiroth, One-Winged Angel, you get an emblem with "Whenever a creature dies, target opponent loses 1 life and you gain 1 life." + this.addAbility(new SimpleStaticAbility(new SephirothOneWingedAngelEmblemEffect()).withFlavorWord("Super Nova")); + + // Whenever Sephiroth attacks, you may sacrifice any number of other creatures. If you do, draw that many cards. + this.addAbility(new AttacksTriggeredAbility(new SephirothOneWingedAngelSacrificeEffect())); + } + + private SephirothOneWingedAngel(final SephirothOneWingedAngel card) { + super(card); + } + + @Override + public SephirothOneWingedAngel copy() { + return new SephirothOneWingedAngel(this); + } +} + +class SephirothOneWingedAngelEmblemEffect extends ReplacementEffectImpl { + + SephirothOneWingedAngelEmblemEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "as this creature transforms into {this}, " + + "you get an emblem with \"Whenever a creature dies, target opponent loses 1 life and you gain 1 life.\""; + } + + private SephirothOneWingedAngelEmblemEffect(final SephirothOneWingedAngelEmblemEffect effect) { + super(effect); + } + + @Override + public SephirothOneWingedAngelEmblemEffect copy() { + return new SephirothOneWingedAngelEmblemEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Optional.ofNullable(source.getSourceObject(game)) + .ifPresent(obj -> game.addEmblem(new SephirothOneWingedAngelEmblem(), obj, source)); + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMING; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return source.getSourceId().equals(event.getTargetId()) + && source.getSourcePermanentIfItStillExists(game) != null; + } +} + +class SephirothOneWingedAngelSacrificeEffect extends OneShotEffect { + + SephirothOneWingedAngelSacrificeEffect() { + super(Outcome.Benefit); + staticText = "you may sacrifice any number of other creatures. If you do, draw that many cards"; + } + + private SephirothOneWingedAngelSacrificeEffect(final SephirothOneWingedAngelSacrificeEffect effect) { + super(effect); + } + + @Override + public SephirothOneWingedAngelSacrificeEffect copy() { + return new SephirothOneWingedAngelSacrificeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + TargetSacrifice target = new TargetSacrifice( + 0, Integer.MAX_VALUE, StaticFilters.FILTER_ANOTHER_CREATURE + ); + player.choose(outcome, target, source, game); + int count = 0; + for (UUID targetId : target.getTargets()) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null && permanent.sacrifice(source, game)) { + count++; + } + } + if (count < 1) { + return false; + } + player.drawCards(count, source, game); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/FinalFantasy.java b/Mage.Sets/src/mage/sets/FinalFantasy.java index 24690baad50..b2902aa2429 100644 --- a/Mage.Sets/src/mage/sets/FinalFantasy.java +++ b/Mage.Sets/src/mage/sets/FinalFantasy.java @@ -164,6 +164,16 @@ public final class FinalFantasy extends ExpansionSet { cards.add(new SetCardInfo("Rinoa Heartilly", 237, Rarity.UNCOMMON, mage.cards.r.RinoaHeartilly.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Rinoa Heartilly", 502, Rarity.UNCOMMON, mage.cards.r.RinoaHeartilly.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sazh's Chocobo", 200, Rarity.UNCOMMON, mage.cards.s.SazhsChocobo.class)); + cards.add(new SetCardInfo("Sephiroth, Fabled SOLDIER", 115, Rarity.MYTHIC, mage.cards.s.SephirothFabledSOLDIER.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sephiroth, Fabled SOLDIER", 317, Rarity.MYTHIC, mage.cards.s.SephirothFabledSOLDIER.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sephiroth, Fabled SOLDIER", 382, Rarity.MYTHIC, mage.cards.s.SephirothFabledSOLDIER.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sephiroth, Fabled SOLDIER", 451, Rarity.MYTHIC, mage.cards.s.SephirothFabledSOLDIER.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sephiroth, Fabled SOLDIER", 527, Rarity.MYTHIC, mage.cards.s.SephirothFabledSOLDIER.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sephiroth, One-Winged Angel", 115, Rarity.MYTHIC, mage.cards.s.SephirothOneWingedAngel.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sephiroth, One-Winged Angel", 317, Rarity.MYTHIC, mage.cards.s.SephirothOneWingedAngel.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sephiroth, One-Winged Angel", 382, Rarity.MYTHIC, mage.cards.s.SephirothOneWingedAngel.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sephiroth, One-Winged Angel", 451, Rarity.MYTHIC, mage.cards.s.SephirothOneWingedAngel.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sephiroth, One-Winged Angel", 527, Rarity.MYTHIC, mage.cards.s.SephirothOneWingedAngel.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sephiroth, Planet's Heir", 505, Rarity.MYTHIC, mage.cards.s.SephirothPlanetsHeir.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sephiroth, Planet's Heir", 553, Rarity.MYTHIC, mage.cards.s.SephirothPlanetsHeir.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Seymour Flux", 452, Rarity.RARE, mage.cards.s.SeymourFlux.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/game/command/emblems/SephirothOneWingedAngelEmblem.java b/Mage/src/main/java/mage/game/command/emblems/SephirothOneWingedAngelEmblem.java new file mode 100644 index 00000000000..3d30bdf66ce --- /dev/null +++ b/Mage/src/main/java/mage/game/command/emblems/SephirothOneWingedAngelEmblem.java @@ -0,0 +1,37 @@ +package mage.game.command.emblems; + +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.effects.common.LoseLifeSourceControllerEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.command.Emblem; +import mage.target.common.TargetOpponent; + +/** + * @author TheElk801 + */ +public final class SephirothOneWingedAngelEmblem extends Emblem { + + // you get an emblem with "Whenever a creature dies, target opponent loses 1 life and you gain 1 life." + public SephirothOneWingedAngelEmblem() { + super("Emblem Sephiroth"); + Ability ability = new DiesCreatureTriggeredAbility( + Zone.COMMAND, new LoseLifeTargetEffect(1), false, + StaticFilters.FILTER_PERMANENT_A_CREATURE, false + ); + ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and")); + ability.addTarget(new TargetOpponent()); + this.getAbilities().add(ability); + } + + private SephirothOneWingedAngelEmblem(final SephirothOneWingedAngelEmblem card) { + super(card); + } + + @Override + public SephirothOneWingedAngelEmblem copy() { + return new SephirothOneWingedAngelEmblem(this); + } +}