From 7abb712a03d3f4de997dfe72493b4b79c286a92b Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 29 May 2025 10:11:19 -0400 Subject: [PATCH] [FIC] Implement Yuna, Grand Summoner --- .../src/mage/cards/y/YunaGrandSummoner.java | 107 ++++++++++++++++++ .../src/mage/sets/FinalFantasyCommander.java | 5 + ...unterNextSpellDelayedTriggeredAbility.java | 17 ++- 3 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/y/YunaGrandSummoner.java diff --git a/Mage.Sets/src/mage/cards/y/YunaGrandSummoner.java b/Mage.Sets/src/mage/cards/y/YunaGrandSummoner.java new file mode 100644 index 00000000000..2f12fec8998 --- /dev/null +++ b/Mage.Sets/src/mage/cards/y/YunaGrandSummoner.java @@ -0,0 +1,107 @@ +package mage.cards.y; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; +import mage.abilities.common.delayed.AddCounterNextSpellDelayedTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.mana.AnyColorManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.counters.Counters; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.permanent.CounterAnyPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class YunaGrandSummoner extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent("another permanent you control"); + + static { + filter.add(AnotherPredicate.instance); + filter.add(CounterAnyPredicate.instance); + } + + public YunaGrandSummoner(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{W}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(1); + this.toughness = new MageInt(5); + + // Grand Summon -- {T}: Add one mana of any color. When you next cast a creature spell this turn, that creature enters with two additional +1/+1 counters on it. + AnyColorManaAbility manaAbility = new AnyColorManaAbility(); + manaAbility.addEffect(new CreateDelayedTriggeredAbilityEffect( + new AddCounterNextSpellDelayedTriggeredAbility(2, StaticFilters.FILTER_SPELL_A_CREATURE) + )); + manaAbility.setUndoPossible(false); + this.addAbility(manaAbility.withFlavorWord("Grand Summon")); + + // Whenever another permanent you control is put into a graveyard from the battlefield, if it had one or more counters on it, you may put that number of +1/+1 counters on target creature. + Ability ability = new PutIntoGraveFromBattlefieldAllTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance(), YunaGrandSummonerValue.instance) + .setText("if it had one or more counters on it, " + + "you may put that number of +1/+1 counters on target creature"), + true, filter, false + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + private YunaGrandSummoner(final YunaGrandSummoner card) { + super(card); + } + + @Override + public YunaGrandSummoner copy() { + return new YunaGrandSummoner(this); + } +} + +enum YunaGrandSummonerValue implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return Optional + .ofNullable((Permanent) effect.getValue("permanentDied")) + .map(permanent -> permanent.getCounters(game)) + .map(Counters::getTotalCount) + .orElse(0); + } + + @Override + public YunaGrandSummonerValue copy() { + return this; + } + + @Override + public String getMessage() { + return ""; + } + + @Override + public String toString() { + return "1"; + } +} diff --git a/Mage.Sets/src/mage/sets/FinalFantasyCommander.java b/Mage.Sets/src/mage/sets/FinalFantasyCommander.java index c20ecc17f03..49773be2dfe 100644 --- a/Mage.Sets/src/mage/sets/FinalFantasyCommander.java +++ b/Mage.Sets/src/mage/sets/FinalFantasyCommander.java @@ -435,5 +435,10 @@ public final class FinalFantasyCommander extends ExpansionSet { cards.add(new SetCardInfo("Yuna's Decision", 74, Rarity.RARE, mage.cards.y.YunasDecision.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Yuna's Whistle", 126, Rarity.RARE, mage.cards.y.YunasWhistle.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Yuna's Whistle", 75, Rarity.RARE, mage.cards.y.YunasWhistle.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Yuna, Grand Summoner", 192, Rarity.MYTHIC, mage.cards.y.YunaGrandSummoner.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Yuna, Grand Summoner", 208, Rarity.MYTHIC, mage.cards.y.YunaGrandSummoner.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Yuna, Grand Summoner", 216, Rarity.MYTHIC, mage.cards.y.YunaGrandSummoner.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Yuna, Grand Summoner", 227, Rarity.MYTHIC, mage.cards.y.YunaGrandSummoner.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Yuna, Grand Summoner", 8, Rarity.MYTHIC, mage.cards.y.YunaGrandSummoner.class, NON_FULL_USE_VARIOUS)); } } diff --git a/Mage/src/main/java/mage/abilities/common/delayed/AddCounterNextSpellDelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/AddCounterNextSpellDelayedTriggeredAbility.java index 3a1caca7d31..c9f27e13629 100644 --- a/Mage/src/main/java/mage/abilities/common/delayed/AddCounterNextSpellDelayedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/delayed/AddCounterNextSpellDelayedTriggeredAbility.java @@ -13,6 +13,7 @@ import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.Spell; +import mage.util.CardUtil; /** * @author TheElk801 @@ -26,7 +27,11 @@ public class AddCounterNextSpellDelayedTriggeredAbility extends DelayedTriggered } public AddCounterNextSpellDelayedTriggeredAbility(FilterSpell filter) { - super(new AddCounterNextSpellEffect(), Duration.EndOfTurn, true, false); + this(1, filter); + } + + public AddCounterNextSpellDelayedTriggeredAbility(int amount, FilterSpell filter) { + super(new AddCounterNextSpellEffect(amount), Duration.EndOfTurn, true, false); this.filter = filter; this.setTriggerPhrase("When you next cast " + filter.getMessage() + " this turn, "); } @@ -62,13 +67,17 @@ public class AddCounterNextSpellDelayedTriggeredAbility extends DelayedTriggered class AddCounterNextSpellEffect extends ReplacementEffectImpl { - AddCounterNextSpellEffect() { + private final int amount; + + AddCounterNextSpellEffect(int amount) { super(Duration.EndOfStep, Outcome.BoostCreature); - staticText = "that creature enters the battlefield with an additional +1/+1 counter on it"; + this.amount = amount; + staticText = "that creature enters the battlefield with " + CardUtil.numberToText(amount, "an") + " additional +1/+1 counter" + (amount > 1 ? "s" : "") + " on it"; } private AddCounterNextSpellEffect(AddCounterNextSpellEffect effect) { super(effect); + this.amount = effect.amount; } @Override @@ -89,7 +98,7 @@ class AddCounterNextSpellEffect extends ReplacementEffectImpl { return false; } creature.addCounters( - CounterType.P1P1.createInstance(), source.getControllerId(), + CounterType.P1P1.createInstance(amount), source.getControllerId(), source, game, event.getAppliedEffects() ); discard();