From bf5f2f6a5d5b7b8906134f4ea48987a8f339a2c4 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 20 May 2025 20:30:11 -0400 Subject: [PATCH] [FIN] Implement Noctis, Prince of Lucis --- .../src/mage/cards/n/NoctisPrinceOfLucis.java | 126 ++++++++++++++++++ Mage.Sets/src/mage/sets/FinalFantasy.java | 4 + Mage/src/main/java/mage/MageIdentifier.java | 1 + 3 files changed, 131 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/n/NoctisPrinceOfLucis.java diff --git a/Mage.Sets/src/mage/cards/n/NoctisPrinceOfLucis.java b/Mage.Sets/src/mage/cards/n/NoctisPrinceOfLucis.java new file mode 100644 index 00000000000..3499f2b11df --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NoctisPrinceOfLucis.java @@ -0,0 +1,126 @@ +package mage.cards.n; + +import mage.MageIdentifier; +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.CostsImpl; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.common.counter.AddCounterEnteringCreatureEffect; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.watchers.Watcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class NoctisPrinceOfLucis extends CardImpl { + + public NoctisPrinceOfLucis(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // You may cast artifact spells from your graveyard by paying 3 life in addition to paying their other costs. If you cast a spell this way, that artifact enters with a finality counter on it. + this.addAbility(new SimpleStaticAbility(new NoctisPrinceOfLucisEffect())); + } + + private NoctisPrinceOfLucis(final NoctisPrinceOfLucis card) { + super(card); + } + + @Override + public NoctisPrinceOfLucis copy() { + return new NoctisPrinceOfLucis(this); + } +} + +class NoctisPrinceOfLucisEffect extends AsThoughEffectImpl { + + NoctisPrinceOfLucisEffect() { + super(AsThoughEffectType.CAST_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.AIDontUseIt); + staticText = "you may cast artifact spells from your graveyard by paying 3 life in addition to paying their " + + "other costs. If you cast a spell this way, that artifact enters with a finality counter on it"; + } + + private NoctisPrinceOfLucisEffect(final NoctisPrinceOfLucisEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public NoctisPrinceOfLucisEffect copy() { + return new NoctisPrinceOfLucisEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + if (!source.isControlledBy(affectedControllerId)) { + return false; + } + Card card = game.getCard(objectId); + Player player = game.getPlayer(affectedControllerId); + if (card == null + || player == null + || !card.isOwnedBy(affectedControllerId) + || !card.isArtifact(game) + || !game.getState().getZone(objectId).match(Zone.GRAVEYARD)) { + return false; + } + Costs newCosts = new CostsImpl<>(); + newCosts.addAll(card.getSpellAbility().getCosts()); + newCosts.add(new PayLifeCost(3)); + player.setCastSourceIdWithAlternateMana( + card.getId(), card.getManaCost(), newCosts, + MageIdentifier.NoctisPrinceOfLucisAlternateCast + ); + return true; + } +} + +class NoctisPrinceOfLucisWatcher extends Watcher { + + NoctisPrinceOfLucisWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (!GameEvent.EventType.SPELL_CAST.equals(event.getType()) + || !event.hasApprovingIdentifier(MageIdentifier.NoctisPrinceOfLucisAlternateCast)) { + return; + } + Spell target = game.getSpell(event.getTargetId()); + if (target != null) { + game.getState().addEffect(new AddCounterEnteringCreatureEffect( + new MageObjectReference(target.getCard(), game), + CounterType.FINALITY.createInstance(), Outcome.UnboostCreature + ), target.getSpellAbility()); + } + } +} diff --git a/Mage.Sets/src/mage/sets/FinalFantasy.java b/Mage.Sets/src/mage/sets/FinalFantasy.java index 6cf5eed8657..3377030ecbb 100644 --- a/Mage.Sets/src/mage/sets/FinalFantasy.java +++ b/Mage.Sets/src/mage/sets/FinalFantasy.java @@ -227,6 +227,10 @@ public final class FinalFantasy extends ExpansionSet { cards.add(new SetCardInfo("Namazu Trader", 107, Rarity.COMMON, mage.cards.n.NamazuTrader.class)); cards.add(new SetCardInfo("Nibelheim Aflame", 146, Rarity.MYTHIC, mage.cards.n.NibelheimAflame.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Nibelheim Aflame", 339, Rarity.MYTHIC, mage.cards.n.NibelheimAflame.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Noctis, Prince of Lucis", 235, Rarity.RARE, mage.cards.n.NoctisPrinceOfLucis.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Noctis, Prince of Lucis", 401, Rarity.RARE, mage.cards.n.NoctisPrinceOfLucis.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Noctis, Prince of Lucis", 500, Rarity.RARE, mage.cards.n.NoctisPrinceOfLucis.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Noctis, Prince of Lucis", 546, Rarity.RARE, mage.cards.n.NoctisPrinceOfLucis.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Paladin's Arms", 28, Rarity.COMMON, mage.cards.p.PaladinsArms.class)); cards.add(new SetCardInfo("Phantom Train", 110, Rarity.UNCOMMON, mage.cards.p.PhantomTrain.class)); cards.add(new SetCardInfo("Phoenix Down", 29, Rarity.UNCOMMON, mage.cards.p.PhoenixDown.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/MageIdentifier.java b/Mage/src/main/java/mage/MageIdentifier.java index fd60b2e5524..b88d00f8a9d 100644 --- a/Mage/src/main/java/mage/MageIdentifier.java +++ b/Mage/src/main/java/mage/MageIdentifier.java @@ -63,6 +63,7 @@ public enum MageIdentifier { IntoThePitAlternateCast, MaestrosAscendencyAlternateCast, NashiMoonSagesScionAlternateCast, + NoctisPrinceOfLucisAlternateCast, OsteomancerAdeptAlternateCast, RafinnesGuidanceAlternateCast, RonaSheoldredsFaithfulAlternateCast,