From 3f0b37ea99f21ac1326b0a81aef900c060bf3b3d Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sun, 16 Nov 2025 17:22:07 -0500 Subject: [PATCH] [TLA] Implement The Legend of Yangchen / Avatar Yangchen --- .../src/mage/cards/a/AvatarYangchen.java | 57 +++++++++ .../src/mage/cards/t/TheLegendOfYangchen.java | 110 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 4 + 3 files changed, 171 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AvatarYangchen.java create mode 100644 Mage.Sets/src/mage/cards/t/TheLegendOfYangchen.java diff --git a/Mage.Sets/src/mage/cards/a/AvatarYangchen.java b/Mage.Sets/src/mage/cards/a/AvatarYangchen.java new file mode 100644 index 00000000000..558ecad122c --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AvatarYangchen.java @@ -0,0 +1,57 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.CastSecondSpellTriggeredAbility; +import mage.abilities.effects.keyword.AirbendTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterNonlandPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AvatarYangchen extends CardImpl { + + private static final FilterPermanent filter = new FilterNonlandPermanent("other target nonland permanent"); + + static { + filter.add(AnotherPredicate.instance); + } + + public AvatarYangchen(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.AVATAR); + this.power = new MageInt(4); + this.toughness = new MageInt(5); + this.nightCard = true; + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever you cast your second spell each turn, airbend up to one other target nonland permanent. + Ability ability = new CastSecondSpellTriggeredAbility(new AirbendTargetEffect()); + ability.addTarget(new TargetPermanent(0, 1, filter)); + this.addAbility(ability); + } + + private AvatarYangchen(final AvatarYangchen card) { + super(card); + } + + @Override + public AvatarYangchen copy() { + return new AvatarYangchen(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TheLegendOfYangchen.java b/Mage.Sets/src/mage/cards/t/TheLegendOfYangchen.java new file mode 100644 index 00000000000..e38cae32e99 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheLegendOfYangchen.java @@ -0,0 +1,110 @@ +package mage.cards.t; + +import mage.abilities.Ability; +import mage.abilities.common.SagaAbility; +import mage.abilities.effects.Effects; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.DrawCardTargetEffect; +import mage.abilities.effects.common.ExileSagaAndReturnTransformedEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ManaValuePredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetOpponent; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheLegendOfYangchen extends CardImpl { + + public TheLegendOfYangchen(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}"); + + this.subtype.add(SubType.SAGA); + this.secondSideCardClazz = mage.cards.a.AvatarYangchen.class; + + // (As this Saga enters and after your draw step, add a lore counter.) + SagaAbility sagaAbility = new SagaAbility(this); + + // I -- Starting with you, each player chooses up to one permanent with mana value 3 or greater from among permanents your opponents control. Exile those permanents. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, new TheLegendOfYangchenEffect()); + + // II -- You may have target opponent draw three cards. If you do, draw three cards. + sagaAbility.addChapterEffect( + this, SagaChapter.CHAPTER_II, SagaChapter.CHAPTER_II, + new Effects( + new DrawCardTargetEffect(3).setText("have target opponent draw three cards. If you do"), + new DrawCardSourceControllerEffect(3).concatBy(",") + ), new TargetOpponent(), true + ); + + // III -- Exile this Saga, then return it to the battlefield transformed under your control. + this.addAbility(new TransformAbility()); + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, new ExileSagaAndReturnTransformedEffect()); + this.addAbility(sagaAbility); + } + + private TheLegendOfYangchen(final TheLegendOfYangchen card) { + super(card); + } + + @Override + public TheLegendOfYangchen copy() { + return new TheLegendOfYangchen(this); + } +} + +class TheLegendOfYangchenEffect extends OneShotEffect { + + TheLegendOfYangchenEffect() { + super(Outcome.Benefit); + staticText = "starting with you, each player chooses up to one permanent with mana value 3 or greater " + + "from among permanents your opponents control. Exile those permanents"; + } + + private TheLegendOfYangchenEffect(final TheLegendOfYangchenEffect effect) { + super(effect); + } + + @Override + public TheLegendOfYangchenEffect copy() { + return new TheLegendOfYangchenEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + FilterPermanent filter = new FilterPermanent(); + filter.add(new ManaValuePredicate(ComparisonType.MORE_THAN, 2)); + filter.add(Predicates.not(new ControllerIdPredicate(source.getControllerId()))); + Set permanents = new HashSet<>(); + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + TargetPermanent target = new TargetPermanent(0, 1, filter, true); + player.choose(Outcome.Exile, target, source, game); + permanents.add(game.getPermanent(target.getFirstTarget())); + } + permanents.removeIf(Objects::isNull); + if (permanents.isEmpty()) { + return false; + } + Player player = game.getPlayer(source.getControllerId()); + return player != null && player.moveCards(permanents, Zone.EXILED, source, game); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 551052d5e9d..8ea40068b1a 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -72,6 +72,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Avatar Kyoshi", 358, Rarity.MYTHIC, mage.cards.a.AvatarKyoshi.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Avatar Roku", 145, Rarity.MYTHIC, mage.cards.a.AvatarRoku.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Avatar Roku", 357, Rarity.MYTHIC, mage.cards.a.AvatarRoku.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Avatar Yangchen", 27, Rarity.MYTHIC, mage.cards.a.AvatarYangchen.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Avatar Yangchen", 354, Rarity.MYTHIC, mage.cards.a.AvatarYangchen.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Avatar's Wrath", 12, Rarity.RARE, mage.cards.a.AvatarsWrath.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Avatar's Wrath", 365, Rarity.RARE, mage.cards.a.AvatarsWrath.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Azula Always Lies", 84, Rarity.COMMON, mage.cards.a.AzulaAlwaysLies.class)); @@ -339,6 +341,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("The Legend of Kyoshi", 358, Rarity.MYTHIC, mage.cards.t.TheLegendOfKyoshi.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Legend of Roku", 145, Rarity.MYTHIC, mage.cards.t.TheLegendOfRoku.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Legend of Roku", 357, Rarity.MYTHIC, mage.cards.t.TheLegendOfRoku.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Legend of Yangchen", 27, Rarity.MYTHIC, mage.cards.t.TheLegendOfYangchen.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Legend of Yangchen", 354, Rarity.MYTHIC, mage.cards.t.TheLegendOfYangchen.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Lion-Turtle", 232, Rarity.RARE, mage.cards.t.TheLionTurtle.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Lion-Turtle", 328, Rarity.RARE, mage.cards.t.TheLionTurtle.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Mechanist, Aerial Artisan", 369, Rarity.RARE, mage.cards.t.TheMechanistAerialArtisan.class, NON_FULL_USE_VARIOUS));