From 9c799b432dbf324f6ad77fd99abdad8d8d837e60 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 29 Oct 2025 10:17:39 -0400 Subject: [PATCH 001/261] [TLA] Implement Gran-Gran --- Mage.Sets/src/mage/cards/g/GranGran.java | 63 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 64 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/g/GranGran.java diff --git a/Mage.Sets/src/mage/cards/g/GranGran.java b/Mage.Sets/src/mage/cards/g/GranGran.java new file mode 100644 index 00000000000..58ec5b3c6a7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GranGran.java @@ -0,0 +1,63 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.common.BecomesTappedSourceTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GranGran extends CardImpl { + + private static final Condition condition = new CardsInControllerGraveyardCondition(3, new FilterCard(SubType.LESSON)); + private static final Hint hint = new ValueHint( + "Lesson cards in your graveyard", new CardsInControllerGraveyardCount(new FilterCard(SubType.LESSON)) + ); + + public GranGran(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.PEASANT); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // Whenever Gran-Gran becomes tapped, draw a card, then discard a card. + this.addAbility(new BecomesTappedSourceTriggeredAbility(new DrawDiscardControllerEffect(1, 1))); + + // Noncreature spells you cast cost {1} less to cast as long as there are three or more Lesson cards in your graveyard. + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new SpellsCostReductionControllerEffect(StaticFilters.FILTER_CARD_NON_CREATURE, 1), + condition, "noncreature spells you cast cost {1} less to cast as long as " + + "there are three or more Lesson cards in your graveyard" + )).addHint(hint)); + } + + private GranGran(final GranGran card) { + super(card); + } + + @Override + public GranGran copy() { + return new GranGran(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index bafb3066ad8..7f41f742534 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -82,6 +82,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Geyser Leaper", 52, Rarity.COMMON, mage.cards.g.GeyserLeaper.class)); cards.add(new SetCardInfo("Giant Koi", 53, Rarity.COMMON, mage.cards.g.GiantKoi.class)); cards.add(new SetCardInfo("Glider Kids", 21, Rarity.COMMON, mage.cards.g.GliderKids.class)); + cards.add(new SetCardInfo("Gran-Gran", 54, Rarity.UNCOMMON, mage.cards.g.GranGran.class)); cards.add(new SetCardInfo("Hakoda, Selfless Commander", 366, Rarity.RARE, mage.cards.h.HakodaSelflessCommander.class)); cards.add(new SetCardInfo("Haru, Hidden Talent", 182, Rarity.UNCOMMON, mage.cards.h.HaruHiddenTalent.class)); cards.add(new SetCardInfo("Heartless Act", 103, Rarity.UNCOMMON, mage.cards.h.HeartlessAct.class)); -- 2.47.2 From 459fe81ee4d0a5f8cedcf78622cf7acf5b03eec4 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 29 Oct 2025 15:29:40 -0400 Subject: [PATCH 002/261] [TLA] Implement Badgermole Cub --- Mage.Sets/src/mage/cards/b/BadgermoleCub.java | 53 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 55 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BadgermoleCub.java diff --git a/Mage.Sets/src/mage/cards/b/BadgermoleCub.java b/Mage.Sets/src/mage/cards/b/BadgermoleCub.java new file mode 100644 index 00000000000..92c28dfcb12 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BadgermoleCub.java @@ -0,0 +1,53 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.TapForManaAllTriggeredManaAbility; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.abilities.effects.mana.BasicManaEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SetTargetPointer; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BadgermoleCub extends CardImpl { + + public BadgermoleCub(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.BADGER); + this.subtype.add(SubType.MOLE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When this creature enters, earthbend 1. + Ability ability = new EntersBattlefieldTriggeredAbility(new EarthbendTargetEffect(1)); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability); + + // Whenever you tap a creature for mana, add an additional {G}. + this.addAbility(new TapForManaAllTriggeredManaAbility( + new BasicManaEffect(Mana.GreenMana(1)).setText("add an additional {G}"), + StaticFilters.FILTER_CONTROLLED_CREATURE, SetTargetPointer.NONE + ).setTriggerPhrase("Whenever you tap a creature for mana, ")); + } + + private BadgermoleCub(final BadgermoleCub card) { + super(card); + } + + @Override + public BadgermoleCub copy() { + return new BadgermoleCub(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 7f41f742534..00da1afc7e1 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -43,6 +43,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Azula Always Lies", 84, Rarity.COMMON, mage.cards.a.AzulaAlwaysLies.class)); cards.add(new SetCardInfo("Azula, On the Hunt", 85, Rarity.UNCOMMON, mage.cards.a.AzulaOnTheHunt.class)); cards.add(new SetCardInfo("Badgermole", 166, Rarity.COMMON, mage.cards.b.Badgermole.class)); + cards.add(new SetCardInfo("Badgermole Cub", 167, Rarity.MYTHIC, mage.cards.b.BadgermoleCub.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Badgermole Cub", 326, Rarity.MYTHIC, mage.cards.b.BadgermoleCub.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Barrels of Blasting Jelly", 254, Rarity.COMMON, mage.cards.b.BarrelsOfBlastingJelly.class)); cards.add(new SetCardInfo("Beetle-Headed Merchants", 86, Rarity.COMMON, mage.cards.b.BeetleHeadedMerchants.class)); cards.add(new SetCardInfo("Bender's Waterskin", 255, Rarity.COMMON, mage.cards.b.BendersWaterskin.class)); -- 2.47.2 From 085fe1116016c5095f2c731cc5fb710a245652b6 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 29 Oct 2025 15:31:48 -0400 Subject: [PATCH 003/261] [TLA] Implement Cycle of Renewal --- .../src/mage/cards/c/CycleOfRenewal.java | 39 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 40 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CycleOfRenewal.java diff --git a/Mage.Sets/src/mage/cards/c/CycleOfRenewal.java b/Mage.Sets/src/mage/cards/c/CycleOfRenewal.java new file mode 100644 index 00000000000..29c8d2ae227 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CycleOfRenewal.java @@ -0,0 +1,39 @@ +package mage.cards.c; + +import mage.abilities.effects.common.SacrificeControllerEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCardInLibrary; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CycleOfRenewal extends CardImpl { + + public CycleOfRenewal(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}"); + + this.subtype.add(SubType.LESSON); + + // Sacrifice a land. Search your library for up to two basic land cards, put them onto the battlefield tapped, then shuffle. + this.getSpellAbility().addEffect(new SacrificeControllerEffect(StaticFilters.FILTER_LAND, 1, "")); + this.getSpellAbility().addEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary( + 0, 2, StaticFilters.FILTER_CARD_BASIC_LAND + ), true)); + } + + private CycleOfRenewal(final CycleOfRenewal card) { + super(card); + } + + @Override + public CycleOfRenewal copy() { + return new CycleOfRenewal(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 00da1afc7e1..d194d6e2090 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -53,6 +53,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Cat-Owl", 212, Rarity.COMMON, mage.cards.c.CatOwl.class)); cards.add(new SetCardInfo("Corrupt Court Official", 92, Rarity.COMMON, mage.cards.c.CorruptCourtOfficial.class)); cards.add(new SetCardInfo("Cunning Maneuver", 130, Rarity.COMMON, mage.cards.c.CunningManeuver.class)); + cards.add(new SetCardInfo("Cycle of Renewal", 170, Rarity.COMMON, mage.cards.c.CycleOfRenewal.class)); cards.add(new SetCardInfo("Dai Li Indoctrination", 93, Rarity.COMMON, mage.cards.d.DaiLiIndoctrination.class)); cards.add(new SetCardInfo("Deserter's Disciple", 131, Rarity.COMMON, mage.cards.d.DesertersDisciple.class)); cards.add(new SetCardInfo("Earth Kingdom Soldier", 216, Rarity.COMMON, mage.cards.e.EarthKingdomSoldier.class)); -- 2.47.2 From 8cd27af5a58c11424986618be52c8e9e229c8c5d Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 29 Oct 2025 15:35:03 -0400 Subject: [PATCH 004/261] [TLA] Implement Invasion Tactics --- .../src/mage/cards/i/InvasionTactics.java | 46 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 47 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/InvasionTactics.java diff --git a/Mage.Sets/src/mage/cards/i/InvasionTactics.java b/Mage.Sets/src/mage/cards/i/InvasionTactics.java new file mode 100644 index 00000000000..10bd57a35ad --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InvasionTactics.java @@ -0,0 +1,46 @@ +package mage.cards.i; + +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class InvasionTactics extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.ALLY, "Allies you control"); + + public InvasionTactics(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}"); + + // When this enchantment enters, creatures you control get +2/+2 until end of turn. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new BoostControlledEffect(2, 2, Duration.EndOfTurn) + )); + + // Whenever one or more Allies you control deal combat damage to a player, draw a card. + this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility( + new DrawCardSourceControllerEffect(1), filter + )); + } + + private InvasionTactics(final InvasionTactics card) { + super(card); + } + + @Override + public InvasionTactics copy() { + return new InvasionTactics(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index d194d6e2090..536ca36d4a7 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -93,6 +93,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Hog-Monkey", 104, Rarity.COMMON, mage.cards.h.HogMonkey.class)); cards.add(new SetCardInfo("How to Start a Riot", 140, Rarity.COMMON, mage.cards.h.HowToStartARiot.class)); cards.add(new SetCardInfo("Iguana Parrot", 56, Rarity.COMMON, mage.cards.i.IguanaParrot.class)); + cards.add(new SetCardInfo("Invasion Tactics", 183, Rarity.UNCOMMON, mage.cards.i.InvasionTactics.class)); cards.add(new SetCardInfo("Island", 283, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Island", 288, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Island", 293, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); -- 2.47.2 From 3188c157df95f03fdb956cb43d59a4d4451a3ced Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 29 Oct 2025 15:40:40 -0400 Subject: [PATCH 005/261] [TLA] Implement Leaves from the Vine --- .../src/mage/cards/l/LeavesFromTheVine.java | 86 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 87 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LeavesFromTheVine.java diff --git a/Mage.Sets/src/mage/cards/l/LeavesFromTheVine.java b/Mage.Sets/src/mage/cards/l/LeavesFromTheVine.java new file mode 100644 index 00000000000..1046163cc73 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LeavesFromTheVine.java @@ -0,0 +1,86 @@ +package mage.cards.l; + +import mage.abilities.common.SagaAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.MillCardsControllerEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SagaChapter; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.game.permanent.token.FoodToken; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class LeavesFromTheVine extends CardImpl { + + private static final FilterCard filter = new FilterCard(); + + static { + filter.add(Predicates.or( + CardType.CREATURE.getPredicate(), + SubType.LESSON.getPredicate() + )); + } + + private static final Condition condition = new CardsInControllerGraveyardCondition(1, filter); + private static final Hint hint = new ConditionHint( + condition, "There's a creature or Lesson card in your graveyard" + ); + + public LeavesFromTheVine(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); + + this.subtype.add(SubType.SAGA); + + // (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.) + SagaAbility sagaAbility = new SagaAbility(this); + + // I -- Mill three cards, then create a Food token. + sagaAbility.addChapterEffect( + this, SagaChapter.CHAPTER_I, + new MillCardsControllerEffect(3), + new CreateTokenEffect(new FoodToken()).concatBy(", then") + ); + + // II -- Put a +1/+1 counter on each of up to two target creatures you control. + sagaAbility.addChapterEffect( + this, SagaChapter.CHAPTER_II, + new AddCountersTargetEffect(CounterType.P1P1.createInstance()), + new TargetControlledCreaturePermanent(0, 2) + ); + + // III -- Draw a card if there's a creature or Lesson card in your graveyard. + sagaAbility.addChapterEffect( + this, SagaChapter.CHAPTER_III, + new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(1), condition, + "draw a card if there's a creature or Lesson card in your graveyard" + ) + ); + this.addAbility(sagaAbility); + } + + private LeavesFromTheVine(final LeavesFromTheVine card) { + super(card); + } + + @Override + public LeavesFromTheVine copy() { + return new LeavesFromTheVine(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 536ca36d4a7..e9caa7e3d37 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -106,6 +106,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Katara, the Fearless", 305, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, the Fearless", 350, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, the Fearless", 361, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Leaves from the Vine", 185, Rarity.UNCOMMON, mage.cards.l.LeavesFromTheVine.class)); cards.add(new SetCardInfo("Lightning Strike", 146, Rarity.COMMON, mage.cards.l.LightningStrike.class)); cards.add(new SetCardInfo("Long Feng, Grand Secretariat", 233, Rarity.UNCOMMON, mage.cards.l.LongFengGrandSecretariat.class)); cards.add(new SetCardInfo("Master Pakku", 63, Rarity.UNCOMMON, mage.cards.m.MasterPakku.class)); -- 2.47.2 From 9d2d7827efe660916846d918e073c2a183561ee9 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 29 Oct 2025 15:49:21 -0400 Subject: [PATCH 006/261] [TLA] Implement Ran and Shaw --- Mage.Sets/src/mage/cards/r/RanAndShaw.java | 115 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 117 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/r/RanAndShaw.java diff --git a/Mage.Sets/src/mage/cards/r/RanAndShaw.java b/Mage.Sets/src/mage/cards/r/RanAndShaw.java new file mode 100644 index 00000000000..cf9e298805b --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RanAndShaw.java @@ -0,0 +1,115 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.condition.common.CastFromEverywhereSourceCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.abilities.keyword.FirebendingAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RanAndShaw extends CardImpl { + + private static final FilterCard filter = new FilterCard(); + + static { + filter.add(Predicates.or( + SubType.DRAGON.getPredicate(), + SubType.LESSON.getPredicate() + )); + } + + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(SubType.DRAGON, "Dragons"); + private static final Condition condition = new CompoundCondition( + "you cast them and there are three or more Dragon and/or Lesson cards in your graveyard", + CastFromEverywhereSourceCondition.instance, new CardsInControllerGraveyardCondition(3, filter) + ); + private static final Hint hint = new ValueHint( + "Dragon and Lesson cards in your graveyard", new CardsInControllerGraveyardCount(filter) + ); + + public RanAndShaw(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.DRAGON); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Firebending 2 + this.addAbility(new FirebendingAbility(2)); + + // When Ran and Shaw enter, if you cast them and there are three or more Dragon and/or Lesson cards in your graveyard, create a token that's a copy of Ran and Shaw, except it's not legendary. + this.addAbility(new EntersBattlefieldTriggeredAbility(new RanAndShawEffect()) + .withInterveningIf(condition) + .setTriggerPhrase("When {this} enter, ") + .addHint(hint)); + + // {3}{R}: Dragons you control get +2/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility(new BoostControlledEffect( + 2, 0, Duration.EndOfTurn, filter2 + ), new ManaCostsImpl<>("{3}{R}"))); + } + + private RanAndShaw(final RanAndShaw card) { + super(card); + } + + @Override + public RanAndShaw copy() { + return new RanAndShaw(this); + } +} + +class RanAndShawEffect extends OneShotEffect { + + RanAndShawEffect() { + super(Outcome.Benefit); + staticText = "create a token that's a copy of {this}, except it's not legendary"; + } + + private RanAndShawEffect(final RanAndShawEffect effect) { + super(effect); + } + + @Override + public RanAndShawEffect copy() { + return new RanAndShawEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = source.getSourcePermanentOrLKI(game); + return permanent != null + && new CreateTokenCopyTargetEffect() + .setIsntLegendary(true) + .setSavedPermanent(permanent) + .apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index e9caa7e3d37..c325f990126 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -130,6 +130,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Plains", 292, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Pretending Poxbearers", 237, Rarity.COMMON, mage.cards.p.PretendingPoxbearers.class)); cards.add(new SetCardInfo("Rabaroo Troop", 32, Rarity.COMMON, mage.cards.r.RabarooTroop.class)); + cards.add(new SetCardInfo("Ran and Shaw", 150, Rarity.RARE, mage.cards.r.RanAndShaw.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ran and Shaw", 325, Rarity.RARE, mage.cards.r.RanAndShaw.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Raucous Audience", 190, Rarity.COMMON, mage.cards.r.RaucousAudience.class)); cards.add(new SetCardInfo("Razor Rings", 33, Rarity.COMMON, mage.cards.r.RazorRings.class)); cards.add(new SetCardInfo("Rebellious Captives", 191, Rarity.COMMON, mage.cards.r.RebelliousCaptives.class)); -- 2.47.2 From d3b0531777af10239d59a0917dbb2ee7e60e7536 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 29 Oct 2025 15:59:43 -0400 Subject: [PATCH 007/261] [TLA] Implement Solstice Revelations --- .../src/mage/cards/s/SolsticeRevelations.java | 114 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + Mage/src/main/java/mage/util/CardUtil.java | 4 +- 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/s/SolsticeRevelations.java diff --git a/Mage.Sets/src/mage/cards/s/SolsticeRevelations.java b/Mage.Sets/src/mage/cards/s/SolsticeRevelations.java new file mode 100644 index 00000000000..250f545d70a --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SolsticeRevelations.java @@ -0,0 +1,114 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlashbackAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SolsticeRevelations extends CardImpl { + + public SolsticeRevelations(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}"); + + this.subtype.add(SubType.LESSON); + + // Exile cards from the top of your library until you exile a nonland card. You may cast that card without paying its mana cost if the spell's mana value is less than the number of Mountains you control. If you don't cast that card this way, put it into your hand. + this.getSpellAbility().addEffect(new SolsticeRevelationsEffect()); + + // Flashback {6}{R} + this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{6}{R}"))); + } + + private SolsticeRevelations(final SolsticeRevelations card) { + super(card); + } + + @Override + public SolsticeRevelations copy() { + return new SolsticeRevelations(this); + } +} + +enum SolsticeRevelationsPredicate implements ObjectSourcePlayerPredicate { + instance; + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.MOUNTAIN); + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return input.getObject().getManaValue() + < game.getBattlefield().count(filter, input.getPlayerId(), input.getSource(), game); + } +} + +class SolsticeRevelationsEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard(); + + static { + filter.add(SolsticeRevelationsPredicate.instance); + } + + SolsticeRevelationsEffect() { + super(Outcome.Benefit); + staticText = "exile cards from the top of your library until you exile a nonland card. " + + "You may cast that card without paying its mana cost if the spell's mana value is less than " + + "the number of Mountains you control. If you don't cast that card this way, put it into your hand"; + } + + private SolsticeRevelationsEffect(final SolsticeRevelationsEffect effect) { + super(effect); + } + + @Override + public SolsticeRevelationsEffect copy() { + return new SolsticeRevelationsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Card card = getCard(player, game, source); + if (card == null) { + return false; + } + if (!CardUtil.castSpellWithAttributesForFree(player, source, game, card, filter)) { + player.moveCards(card, Zone.HAND, source, game); + } + return true; + } + + private static Card getCard(Player player, Game game, Ability source) { + for (Card card : player.getLibrary().getCards(game)) { + player.moveCards(card, Zone.EXILED, source, game); + game.processAction(); + if (!card.isLand(game)) { + return card; + } + } + return null; + } + +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index c325f990126..50e56f00795 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -146,6 +146,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 240, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 383, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Lateral Strategist", 241, Rarity.UNCOMMON, mage.cards.s.SokkaLateralStrategist.class)); + cards.add(new SetCardInfo("Solstice Revelations", 153, Rarity.UNCOMMON, mage.cards.s.SolsticeRevelations.class)); cards.add(new SetCardInfo("Southern Air Temple", 36, Rarity.UNCOMMON, mage.cards.s.SouthernAirTemple.class)); cards.add(new SetCardInfo("Sozin's Comet", 154, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sozin's Comet", 309, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 65a79575a4b..db9ff9e8543 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -1536,7 +1536,7 @@ public final class CardUtil { } else { chosenAbility = player.chooseAbilityForCast(cardToCast, game, true); } - boolean result = false; + boolean result; if (chosenAbility instanceof SpellAbility) { result = player.cast( (SpellAbility) chosenAbility, @@ -1545,6 +1545,8 @@ public final class CardUtil { } else if (playLand && chosenAbility instanceof PlayLandAbility) { Card land = game.getCard(chosenAbility.getSourceId()); result = player.playLand(land, game, true); + } else { + result = false; } partsToCast.forEach(card -> game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null)); if (result && spellCastTracker != null) { -- 2.47.2 From 4b3cacbf2be251ec8bb3b575f2fb357652a17130 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 29 Oct 2025 16:02:17 -0400 Subject: [PATCH 008/261] [TLA] Implement Sokka, Tenacious Tactician --- .../mage/cards/s/SokkaTenaciousTactician.java | 69 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 71 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SokkaTenaciousTactician.java diff --git a/Mage.Sets/src/mage/cards/s/SokkaTenaciousTactician.java b/Mage.Sets/src/mage/cards/s/SokkaTenaciousTactician.java new file mode 100644 index 00000000000..0c68b943bda --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SokkaTenaciousTactician.java @@ -0,0 +1,69 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.abilities.keyword.ProwessAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.game.permanent.token.AllyToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SokkaTenaciousTactician extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent(SubType.ALLY, "Allies"); + + public SokkaTenaciousTactician(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Menace + this.addAbility(new MenaceAbility()); + + // Prowess + this.addAbility(new ProwessAbility()); + + // Other Allies you control have menace and prowess. + Ability ability = new SimpleStaticAbility(new GainAbilityControlledEffect( + new MenaceAbility(false), Duration.WhileOnBattlefield, filter, true + )); + ability.addEffect(new GainAbilityControlledEffect( + new ProwessAbility(), Duration.WhileOnBattlefield, filter, true + ).setText("and prowess")); + this.addAbility(ability); + + // Whenever you cast a noncreature spell, create a 1/1 white Ally creature token. + this.addAbility(new SpellCastControllerTriggeredAbility( + new CreateTokenEffect(new AllyToken()), StaticFilters.FILTER_SPELL_A_NON_CREATURE, false + )); + } + + private SokkaTenaciousTactician(final SokkaTenaciousTactician card) { + super(card); + } + + @Override + public SokkaTenaciousTactician copy() { + return new SokkaTenaciousTactician(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 50e56f00795..842a5e63735 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -146,6 +146,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 240, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 383, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Lateral Strategist", 241, Rarity.UNCOMMON, mage.cards.s.SokkaLateralStrategist.class)); + cards.add(new SetCardInfo("Sokka, Tenacious Tactician", 242, Rarity.RARE, mage.cards.s.SokkaTenaciousTactician.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sokka, Tenacious Tactician", 352, Rarity.RARE, mage.cards.s.SokkaTenaciousTactician.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Solstice Revelations", 153, Rarity.UNCOMMON, mage.cards.s.SolsticeRevelations.class)); cards.add(new SetCardInfo("Southern Air Temple", 36, Rarity.UNCOMMON, mage.cards.s.SouthernAirTemple.class)); cards.add(new SetCardInfo("Sozin's Comet", 154, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From b489efa05caf4d2f97abb59e59d19928df88f78a Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 29 Oct 2025 16:08:39 -0400 Subject: [PATCH 009/261] [TLE] update spoiler and reprints --- .../src/mage/sets/AvatarTheLastAirbenderEternal.java | 5 +++++ Utils/mtg-cards-data.txt | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 94e8c0a0588..890d7f05de1 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -33,10 +33,13 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Aang, Airbending Master", 74, Rarity.MYTHIC, mage.cards.a.AangAirbendingMaster.class)); cards.add(new SetCardInfo("Aardvark Sloth", 212, Rarity.COMMON, mage.cards.a.AardvarkSloth.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aardvark Sloth", 267, Rarity.COMMON, mage.cards.a.AardvarkSloth.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Agent of Treachery", 9, Rarity.MYTHIC, mage.cards.a.AgentOfTreachery.class)); cards.add(new SetCardInfo("Allied Teamwork", 213, Rarity.RARE, mage.cards.a.AlliedTeamwork.class)); cards.add(new SetCardInfo("Appa, Aang's Companion", 214, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Appa, Aang's Companion", 268, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Arcane Signet", 315, Rarity.RARE, mage.cards.a.ArcaneSignet.class)); cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 130, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class)); + cards.add(new SetCardInfo("Bribery", 10, Rarity.MYTHIC, mage.cards.b.Bribery.class)); cards.add(new SetCardInfo("Bumi, Eclectic Earthbender", 248, Rarity.RARE, mage.cards.b.BumiEclecticEarthbender.class)); cards.add(new SetCardInfo("Capital Guard", 234, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Capital Guard", 277, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); @@ -112,6 +115,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Sledding Otter-Penguin", 273, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 219, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 274, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sol Ring", 316, Rarity.RARE, mage.cards.s.SolRing.class)); + cards.add(new SetCardInfo("Swiftfoot Boots", 317, Rarity.RARE, mage.cards.s.SwiftfootBoots.class)); cards.add(new SetCardInfo("The Cabbage Merchant", 134, Rarity.RARE, mage.cards.t.TheCabbageMerchant.class)); cards.add(new SetCardInfo("The Great Henge", 41, Rarity.MYTHIC, mage.cards.t.TheGreatHenge.class)); cards.add(new SetCardInfo("The Terror of Serpent's Pass", 225, Rarity.RARE, mage.cards.t.TheTerrorOfSerpentsPass.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 96c65b0e288..483f50aa1e5 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -60273,6 +60273,8 @@ Spider-Sense|Marvel's Spider-Man|284|R|{1}{U}|Instant|||Web-slinging {U}$Counter Radioactive Spider|Marvel's Spider-Man|285|R|{G}|Creature - Spider|1|1|Reach, deathtouch$Fateful Bite -- {2}, Sacrifice this creature: Search your library for a Spider Hero card, reveal it, put it into your hand, then shuffle. Activate only as a sorcery.| Gwenom, Remorseless|Marvel's Spider-Man|286|M|{3}{B}{B}|Legendary Creature - Symbiote Spider Hero|4|4|Deathtouch, lifelink$Whenever Gwenom attacks, until end of turn you may look at the top card of your library any time and you may play cards from the top of your library. If you cast a spell this way, pay life equal to its mana value rather than pay its mana cost.| Release to Memory|Avatar: The Last Airbender Eternal|5|M|{3}{W}|Instant|||Exile target opponent's graveyard. For each creature card exiled this way, create a 1/1 colorless Spirit creature token.| +Agent of Treachery|Avatar: The Last Airbender Eternal|9|M|{5}{U}{U}|Creature - Human Rogue|2|3|When this creature enters, gain control of target permanent.$At the beginning of your end step, if you control three or more permanents you don't own, draw three cards.| +Bribery|Avatar: The Last Airbender Eternal|10|M|{3}{U}{U}|Sorcery|||Search target opponent's library for a creature card and put that card onto the battlefield under your control. Then that player shuffles.| Force of Negation|Avatar: The Last Airbender Eternal|13|M|{1}{U}{U}|Instant|||If it's not your turn, you may exile a blue card from your hand rather than pay this spell's mana cost.$Counter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.| Mystic Remora|Avatar: The Last Airbender Eternal|16|M|{U}|Enchantment|||Cumulative upkeep {1}$Whenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}.| Cruel Tutor|Avatar: The Last Airbender Eternal|24|M|{2}{B}|Sorcery|||Search your library for a card, then shuffle and put that card on top. You lose 2 life.| @@ -60282,7 +60284,11 @@ Eladamri's Call|Avatar: The Last Airbender Eternal|48|M|{G}{W}|Instant|||Search Dark Depths|Avatar: The Last Airbender Eternal|56|M||Legendary Snow Land|||Dark Depths enters with ten ice counters on it.${3}: Remove an ice counter from Dark Depths.$When Dark Depths has no ice counters on it, sacrifice it. If you do, create Marit Lage, a legendary 20/20 black Avatar creature token with flying and indestructible.| Valakut, the Molten Pinnacle|Avatar: The Last Airbender Eternal|61|M||Land|||This land enters tapped.$Whenever a Mountain you control enters, if you control at least five other Mountains, you may have this land deal 3 damage to any target.${T}: Add {R}.| Katara's Reversal|Avatar: The Last Airbender Eternal|63|R|{2}{U}{U}|Instant|||Counter up to four target spells and/or abilities.$Untap up to four target artifacts and/or creatures.| +Aang and Katara|Avatar: The Last Airbender Eternal|69|R|{3}{G}{W}{U}|Legendary Creature - Human Avatar Ally|5|5|Whenever Aang and Katara enter or attack, create X 1/1 white Ally creature tokens, where X is the number of tapped artifacts and/or creatures you control.| +Toph, Greatest Earthbender|Avatar: The Last Airbender Eternal|70|R|{2}{R}{G}|Legendary Creature - Human Warrior Ally|3|3|When Toph enters, earthbend X, where X is the amount of mana spent to cast her. Land creatures you control have double strike.| Sokka and Suki|Avatar: The Last Airbender Eternal|71|R|{U}{R}{W}|Legendary Creature - Human Warrior Ally|3|3|Whenever Sokka and Suki or another Ally you control enters, attach up to one target Equipment you control to that creature.$Whenever an Equipment you control enters, create a 1/1 white Ally creature token.| +Momo's Heist|Avatar: The Last Airbender Eternal|72|R|{2}{R}|Sorcery|||Gain control of target artifact. Untap it. It gains haste. At the beginning of the next end step, sacrifice it.| +Uncle's Musings|Avatar: The Last Airbender Eternal|73|R|{2}{G}{G}|Sorcery|||Converge -- Return up to X permanent cards from your graveyard to your hand, where X is the number of colors of mana spent to cast this spell.$Exile Uncle's Musings.| Aang, Airbending Master|Avatar: The Last Airbender Eternal|74|M|{4}{W}|Legendary Creature - Human Avatar Ally|4|4|When Aang enters, airbend another target creature.$Whenever one or more creatures you control leave the battlefield without dying, you get an experience counter.$At the beginning of your upkeep, create a 1/1 white Ally creature token for each experience counter you have.| Sokka, Swordmaster|Avatar: The Last Airbender Eternal|83|M|{2}{W}|Legendary Creature - Human Warrior Ally|3|3|Vigilance$Equipment spells you cast cost {1} less to cast for each Ally you control.$At the beginning of combat on your turn, attach up to one target Equipment you control to Sokka.| Katara, Waterbending Master|Avatar: The Last Airbender Eternal|93|M|{1}{U}|Legendary Creature - Human Warrior Ally|1|3|Whenever you cast a spell during an opponent's turn, you get an experience counter.$Whenever Katara attacks, you may draw a card for each experience counter you have. If you do, discard a card.| @@ -60393,6 +60399,9 @@ Plains|Avatar: The Last Airbender Eternal|301|C||Basic Land - Plains|||({T}: Add Plains|Avatar: The Last Airbender Eternal|302|C||Basic Land - Plains|||({T}: Add {W}.)| Plains|Avatar: The Last Airbender Eternal|303|C||Basic Land - Plains|||({T}: Add {W}.)| Plains|Avatar: The Last Airbender Eternal|304|C||Basic Land - Plains|||({T}: Add {W}.)| +Arcane Signet|Avatar: The Last Airbender Eternal|315|R|{2}|Artifact|||{T}: Add one mana of any color in your commander's color identity.| +Sol Ring|Avatar: The Last Airbender Eternal|316|R|{1}|Artifact|||{T}: Add {C}{C}.| +Swiftfoot Boots|Avatar: The Last Airbender Eternal|317|R|{2}|Artifact - Equipment|||Equipped creature has hexproof and haste.$Equip {1}| Eirdu, Carrier of Dawn|Lorwyn Eclipsed|13|M|{3}{W}{W}|Legendary Creature - Elemental God|5|5|Flying, lifelink$Creature spells you cast have convoke.$At the beginning of your first main phase, you may pay {B}. If you do, transform Eirdu.| Isilu, Carrier of Twilight|Lorwyn Eclipsed|13|M||Legendary Creature - Elemental God|5|5|Flying, lifelink$Each other nontoken creature you control has persist.$At the beginning of your first main phase, you may pay {W}. If you do, transform Isilu.| Morningtide's Light|Lorwyn Eclipsed|27|M|{3}{W}|Sorcery|||Exile any number of target creatures. At the beginning of the next end step, return those cards to the battlefield tapped under their owners' control.$Until your next turn, prevent all damage that would be dealt to you.$Exile Morningtide's Light.| -- 2.47.2 From 13bf2126d33e023a225001aca01320adfaec7d4e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 29 Oct 2025 16:28:37 -0400 Subject: [PATCH 010/261] fix error --- Mage.Sets/src/mage/cards/g/GranGran.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/g/GranGran.java b/Mage.Sets/src/mage/cards/g/GranGran.java index 58ec5b3c6a7..fcd4d51fdd8 100644 --- a/Mage.Sets/src/mage/cards/g/GranGran.java +++ b/Mage.Sets/src/mage/cards/g/GranGran.java @@ -5,7 +5,7 @@ import mage.abilities.common.BecomesTappedSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; -import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.decorator.ConditionalCostModificationEffect; import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; @@ -45,7 +45,7 @@ public final class GranGran extends CardImpl { this.addAbility(new BecomesTappedSourceTriggeredAbility(new DrawDiscardControllerEffect(1, 1))); // Noncreature spells you cast cost {1} less to cast as long as there are three or more Lesson cards in your graveyard. - this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + this.addAbility(new SimpleStaticAbility(new ConditionalCostModificationEffect( new SpellsCostReductionControllerEffect(StaticFilters.FILTER_CARD_NON_CREATURE, 1), condition, "noncreature spells you cast cost {1} less to cast as long as " + "there are three or more Lesson cards in your graveyard" -- 2.47.2 From 37ade28c311bb840d210a289334e603471078862 Mon Sep 17 00:00:00 2001 From: PurpleCrowbar <26198472+PurpleCrowbar@users.noreply.github.com> Date: Wed, 29 Oct 2025 20:27:41 +0000 Subject: [PATCH 011/261] Fix preference menu tooltip, minor preference menu clarity improvements --- .../main/java/mage/client/dialog/PreferencesDialog.form | 8 ++++---- .../main/java/mage/client/dialog/PreferencesDialog.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form index e6bf6d18f40..771001da5c3 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form @@ -2115,6 +2115,9 @@ + + + @@ -2254,16 +2257,13 @@ - + - - - diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index 85c9a155c22..13004ab13bf 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -2155,6 +2155,8 @@ public class PreferencesDialog extends javax.swing.JDialog { } }); + txtBackgroundImagePath.setToolTipText("The selected image will be used as the background picture. Requires client restart to see changes."); + btnBrowseBackgroundImage.setText("Browse..."); btnBrowseBackgroundImage.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -2254,15 +2256,13 @@ public class PreferencesDialog extends javax.swing.JDialog { panelCardImages.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Card images")); - cbUseDefaultImageFolder.setText("Use default location to save images"); + cbUseDefaultImageFolder.setText("Use default location to save card images"); cbUseDefaultImageFolder.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cbUseDefaultImageFolderActionPerformed(evt); } }); - txtImageFolderPath.setToolTipText("The selected image will be used as background picture. You have to restart MAGE to view a changed background image."); - btnBrowseImageLocation.setText("Browse..."); btnBrowseImageLocation.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { -- 2.47.2 From d98d59cc55d96157f5b9a312329d494c6043d7ae Mon Sep 17 00:00:00 2001 From: jmlundeen Date: Wed, 29 Oct 2025 21:00:11 -0500 Subject: [PATCH 012/261] rework MayhemLandAbility to work properly --- .../src/mage/cards/o/OscorpIndustries.java | 4 +- .../single/spm/OscorpIndustriesTest.java | 54 ++++++++++++++- .../abilities/keyword/MayhemLandAbility.java | 66 +++++++++++-------- 3 files changed, 92 insertions(+), 32 deletions(-) diff --git a/Mage.Sets/src/mage/cards/o/OscorpIndustries.java b/Mage.Sets/src/mage/cards/o/OscorpIndustries.java index f694701108b..d2bf00ac565 100644 --- a/Mage.Sets/src/mage/cards/o/OscorpIndustries.java +++ b/Mage.Sets/src/mage/cards/o/OscorpIndustries.java @@ -20,7 +20,7 @@ import java.util.UUID; public final class OscorpIndustries extends CardImpl { public OscorpIndustries(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, null); // This land enters tapped. @@ -35,7 +35,7 @@ public final class OscorpIndustries extends CardImpl { this.addAbility(new RedManaAbility()); // Mayhem - this.addAbility(new MayhemLandAbility(this)); + this.addAbility(new MayhemLandAbility()); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/spm/OscorpIndustriesTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/spm/OscorpIndustriesTest.java index 364cc480059..4e3f23468fa 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/spm/OscorpIndustriesTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/spm/OscorpIndustriesTest.java @@ -41,7 +41,7 @@ public class OscorpIndustriesTest extends CardTestPlayerBase { activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw"); setChoice(playerA, oscorpIndustries); - playLand(1, PhaseStep.POSTCOMBAT_MAIN, playerA, oscorpIndustries + " with Mayhem"); + playLand(1, PhaseStep.POSTCOMBAT_MAIN, playerA, oscorpIndustries); setStopAt(1, PhaseStep.END_TURN); execute(); @@ -49,4 +49,56 @@ public class OscorpIndustriesTest extends CardTestPlayerBase { assertLife(playerA, 20 - 2); assertPermanentCount(playerA, oscorpIndustries, 1); } + + @Test + public void testOscorpIndustriesNoMayhem() { + setStrictChooseMode(true); + + addCard(Zone.HAND, playerA, oscorpIndustries); + addCard(Zone.BATTLEFIELD, playerA, thoughtCourier); + + playLand(1, PhaseStep.POSTCOMBAT_MAIN, playerA, oscorpIndustries); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 20); + assertPermanentCount(playerA, oscorpIndustries, 1); + } + + @Test + public void testCantPlayWithoutDiscard() { + setStrictChooseMode(true); + + addCard(Zone.GRAVEYARD, playerA, oscorpIndustries); + + checkPlayableAbility("Can't play without discard", 1, PhaseStep.PRECOMBAT_MAIN, playerA, + "Play " + oscorpIndustries, false); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 20); + assertPermanentCount(playerA, oscorpIndustries, 0); + } + + @Test + public void testOscorpIndustriesNextTurn() { + setStrictChooseMode(true); + + addCard(Zone.HAND, playerA, oscorpIndustries); + addCard(Zone.BATTLEFIELD, playerA, thoughtCourier); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw"); + setChoice(playerA, oscorpIndustries); + + checkPlayableAbility("Can't play without discard", 3, PhaseStep.PRECOMBAT_MAIN, playerA, + "Play " + oscorpIndustries, false); + + setStopAt(3, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertLife(playerA, 20); + assertPermanentCount(playerA, oscorpIndustries, 0); + } } \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/keyword/MayhemLandAbility.java b/Mage/src/main/java/mage/abilities/keyword/MayhemLandAbility.java index 14c5d962023..064028ae4d0 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MayhemLandAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MayhemLandAbility.java @@ -1,23 +1,22 @@ package mage.abilities.keyword; -import mage.MageIdentifier; -import mage.abilities.PlayLandAbility; -import mage.cards.Card; -import mage.constants.Zone; +import mage.abilities.Ability; +import mage.abilities.StaticAbility; +import mage.abilities.effects.AsThoughEffect; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.constants.*; import mage.game.Game; -import java.util.Set; import java.util.UUID; -public class MayhemLandAbility extends PlayLandAbility { +public class MayhemLandAbility extends StaticAbility { private final String rule; - public MayhemLandAbility(Card card) { - super(card.getName()); - this.zone = Zone.GRAVEYARD; + public MayhemLandAbility() { + super(AbilityType.STATIC, Zone.GRAVEYARD); this.newId(); - this.name += " with Mayhem"; + this.addEffect(new MayhemPlayEffect()); this.addWatcher(new MayhemWatcher()); this.setRuleAtTheTop(true); this.rule = "Mayhem " + @@ -30,24 +29,6 @@ public class MayhemLandAbility extends PlayLandAbility { this.rule = ability.rule; } - @Override - public ActivationStatus canActivate(UUID playerId, Game game) { - if (!Zone.GRAVEYARD.match(game.getState().getZone(getSourceId())) - || !MayhemWatcher.checkCard(getSourceId(), game)) { - return ActivationStatus.getFalse(); - } - return super.canActivate(playerId, game); - } - - @Override - public boolean activate(Game game, Set allowedIdentifiers, boolean noMana) { - if (!super.activate(game, allowedIdentifiers, noMana)) { - return false; - } - this.setCostsTag(MayhemAbility.MAYHEM_ACTIVATION_VALUE_KEY, null); - return true; - } - @Override public MayhemLandAbility copy() { return new MayhemLandAbility(this); @@ -57,4 +38,31 @@ public class MayhemLandAbility extends PlayLandAbility { public String getRule() { return rule; } - } \ No newline at end of file +} + +class MayhemPlayEffect extends AsThoughEffectImpl { + + public MayhemPlayEffect() { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileInGraveyard, Outcome.Neutral); + } + + public MayhemPlayEffect(final MayhemPlayEffect effect) { + super(effect); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + return Zone.GRAVEYARD.match(game.getState().getZone(sourceId)) + && MayhemWatcher.checkCard(sourceId, game); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public AsThoughEffect copy() { + return new MayhemPlayEffect(this); + } +} \ No newline at end of file -- 2.47.2 From 3c0593a7fad0cf8791cd28b0dba6f0cef8c40548 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Thu, 30 Oct 2025 09:37:04 -0400 Subject: [PATCH 013/261] Update Duel Commander ban list. --- .../Mage.Deck.Constructed/src/mage/deck/DuelCommander.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java index cc4e1c45827..e86103dafc9 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java @@ -44,7 +44,6 @@ public class DuelCommander extends Commander { banned.add("Library of Alexandria"); banned.add("Lion's Eye Diamond"); banned.add("Lotus Petal"); - banned.add("Loyal Retainers"); banned.add("Lutri, the Spellchaser"); banned.add("Maddening Hex"); banned.add("Mana Crypt"); @@ -93,8 +92,6 @@ public class DuelCommander extends Commander { bannedCommander.add("Ajani, Nacatl Pariah"); bannedCommander.add("Arahbo, Roar of the World"); - bannedCommander.add("Asmoranomardicadaistinaculdacar"); - bannedCommander.add("Baral, Chief of Compliance"); bannedCommander.add("Breya, Etherium Shaper"); bannedCommander.add("Derevi, Empyrial Tactician"); bannedCommander.add("Dihada, Binder of Wills"); @@ -102,7 +99,6 @@ public class DuelCommander extends Commander { bannedCommander.add("Edric, Spymaster of Trest"); bannedCommander.add("Emry, Lurker of the Loch"); bannedCommander.add("Eris, Roar of the Storm"); - bannedCommander.add("Esior, Wardwing Familiar"); bannedCommander.add("Ezio Auditore da Firenze"); bannedCommander.add("Geist of Saint Traft"); bannedCommander.add("Inalla, Archmage Ritualist"); @@ -116,7 +112,6 @@ public class DuelCommander extends Commander { bannedCommander.add("Omnath, Locus of Creation"); bannedCommander.add("Prime Speaker Vannifar"); bannedCommander.add("Raffine, Scheming Seer"); - bannedCommander.add("Rofellos, Llanowar Emissary"); bannedCommander.add("Shorikai, Genesis Engine"); bannedCommander.add("Tamiyo, Inquisitive Student"); bannedCommander.add("Tasigur, the Golden Fang"); -- 2.47.2 From 6db11cc0005121e362e168472a008a9b35222036 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 13:14:35 -0400 Subject: [PATCH 014/261] [TLA] update spoiler --- .../src/mage/sets/AvatarTheLastAirbender.java | 4 +-- Utils/mtg-cards-data.txt | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 842a5e63735..cddae2375c1 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -12,7 +12,7 @@ import java.util.List; */ public final class AvatarTheLastAirbender extends ExpansionSet { - private static final List unfinished = Arrays.asList("Aang's Iceberg", "Avatar Aang", "Flexible Waterbender", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "The Legend of Kuruk", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); + private static final List unfinished = Arrays.asList("Aang's Iceberg", "Avatar Aang", "Flexible Waterbender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "The Legend of Kuruk", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); private static final AvatarTheLastAirbender instance = new AvatarTheLastAirbender(); public static AvatarTheLastAirbender getInstance() { @@ -42,9 +42,9 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Avatar Enthusiasts", 11, Rarity.COMMON, mage.cards.a.AvatarEnthusiasts.class)); cards.add(new SetCardInfo("Azula Always Lies", 84, Rarity.COMMON, mage.cards.a.AzulaAlwaysLies.class)); cards.add(new SetCardInfo("Azula, On the Hunt", 85, Rarity.UNCOMMON, mage.cards.a.AzulaOnTheHunt.class)); - cards.add(new SetCardInfo("Badgermole", 166, Rarity.COMMON, mage.cards.b.Badgermole.class)); cards.add(new SetCardInfo("Badgermole Cub", 167, Rarity.MYTHIC, mage.cards.b.BadgermoleCub.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Badgermole Cub", 326, Rarity.MYTHIC, mage.cards.b.BadgermoleCub.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Badgermole", 166, Rarity.COMMON, mage.cards.b.Badgermole.class)); cards.add(new SetCardInfo("Barrels of Blasting Jelly", 254, Rarity.COMMON, mage.cards.b.BarrelsOfBlastingJelly.class)); cards.add(new SetCardInfo("Beetle-Headed Merchants", 86, Rarity.COMMON, mage.cards.b.BeetleHeadedMerchants.class)); cards.add(new SetCardInfo("Bender's Waterskin", 255, Rarity.COMMON, mage.cards.b.BendersWaterskin.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 483f50aa1e5..9bea6e17ce7 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59769,10 +59769,14 @@ Airbender Ascension|Avatar: The Last Airbender|6|R|{1}{W}|Enchantment|||When thi Airbending Lesson|Avatar: The Last Airbender|8|C|{2}{W}|Instant - Lesson|||Airbend target nonland permanent.$Draw a card.| Appa, Steadfast Guardian|Avatar: The Last Airbender|10|M|{2}{W}{W}|Legendary Creature - Bison Ally|3|4|Flash$Flying$When Appa enters, airbend any number of other target nonland permanents you control.$Whenever you cast a spell from exile, create a 1/1 white Ally creature token.| Avatar Enthusiasts|Avatar: The Last Airbender|11|C|{2}{W}|Creature - Human Peasant Ally|2|2|Whenever another Ally you control enters, put a +1/+1 counter on this creature.| +Compassionate Healer|Avatar: The Last Airbender|13|C|{1}{W}|Creature - Human Cleric Ally|2|2|Whenever this creature becomes tapped, you gain 1 life and scry 1.| +Fancy Footwork|Avatar: The Last Airbender|19|U|{2}{W}|Instant - Lesson|||Untap one or two target creatures. They each get +2/+2 until end of turn.| Glider Kids|Avatar: The Last Airbender|21|C|{2}{W}|Creature - Human Pilot Ally|2|3|Flying$When this creature enters, scry 1.| +Glider Staff|Avatar: The Last Airbender|22|U|{2}{W}|Artifact - Equipment|||When this Equipment enters, airbend up to one target creature.$Equipped creature gets +1/+1 and has flying.$Equip {2}| Jeong Jeong's Deserters|Avatar: The Last Airbender|25|C|{1}{W}|Creature - Human Rebel Ally|1|2|When this creature enters, put a +1/+1 counter on target creature.| Master Piandao|Avatar: The Last Airbender|28|U|{4}{W}|Legendary Creature - Human Warrior Ally|4|4|First strike$Whenever Master Piandao attacks, look at the top four cards of your library. You may reveal an Ally, Equipment, or Lesson card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| Momo, Friendly Flier|Avatar: The Last Airbender|29|R|{W}|Legendary Creature - Lemur Bat Ally|1|1|Flying$The first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast.$Whenever another creature you control with flying enters, Momo gets +1/+1 until end of turn.| +Momo, Playful Pet|Avatar: The Last Airbender|30|U|{W}|Legendary Creature - Lemur Bat Ally|1|1|Flying, vigilance$When Momo leaves the battlefield, choose one --$* Create a Food token.$* Put a +1/+1 counter on target creature you control.$* Scry 2.| Path to Redemption|Avatar: The Last Airbender|31|C|{1}{W}|Enchantment - Aura|||Enchant creature$Enchanted creature can't attack or block.${5}, Sacrifice this Aura: Exile enchanted creature. Create a 1/1 white Ally creature token. Activate only during your turn.| Rabaroo Troop|Avatar: The Last Airbender|32|C|{3}{W}{W}|Creature - Rabbit Kangaroo|3|5|Landfall -- Whenever a land you control enters, this creature gains flying until end of turn and you gain 1 life.$Plainscycling {2}| Razor Rings|Avatar: The Last Airbender|33|C|{1}{W}|Instant|||Razor Rings deals 4 damage to target attacking or blocking creature. You gain life equal to the excess damage dealt this way.| @@ -59781,6 +59785,7 @@ Water Tribe Rallier|Avatar: The Last Airbender|42|U|{1}{W}|Creature - Human Sold Yip Yip!|Avatar: The Last Airbender|43|C|{W}|Instant - Lesson|||Target creature you control gets +2/+2 until end of turn. If that creature is an Ally, it also gains flying until end of turn.| First-Time Flyer|Avatar: The Last Airbender|49|C|{1}{U}|Creature - Human Pilot Ally|1|2|Flying$This creature gets +1/+1 as long as there's a Lesson card in your graveyard.| Flexible Waterbender|Avatar: The Last Airbender|50|C|{3}{U}|Creature - Human Warrior Ally|2|5|Vigilance$Waterbend {3}: This creature has base power and toughness 5/2 until end of turn.| +Forecasting Fortune Teller|Avatar: The Last Airbender|51|C|{1}{U}|Creature - Human Advisor Ally|1|3|When this creature enters, create a Clue token.| Geyser Leaper|Avatar: The Last Airbender|52|C|{4}{U}|Creature - Human Warrior Ally|4|3|Flying$Waterbend {4}: Draw a card, then discard a card.| Giant Koi|Avatar: The Last Airbender|53|C|{4}{U}{U}|Creature - Fish|5|7|Waterbend {3}: This creature can't be blocked this turn.$Islandcycling {2}| Gran-Gran|Avatar: The Last Airbender|54|U|{U}|Legendary Creature - Human Peasant Ally|1|2|Whenever Gran-Gran becomes tapped, draw a card, then discard a card.$Noncreature spells you cast cost {1} less to cast as long as there are three or more Lesson cards in your graveyard.| @@ -59790,14 +59795,18 @@ It'll Quench Ya!|Avatar: The Last Airbender|58|C|{1}{U}|Instant - Lesson|||Count Katara, Bending Prodigy|Avatar: The Last Airbender|59|U|{2}{U}|Legendary Creature - Human Warrior Ally|2|3|At the beginning of your end step, if Katara is tapped, put a +1/+1 counter on her.$Waterbend {6}: Draw a card.| The Legend of Kuruk|Avatar: The Last Airbender|61|M|{2}{U}{U}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I, II -- Scry 2, then draw a card.$III -- Exile this Saga, then return it to the battlefield$transformed under your control.| Avatar Kuruk|Avatar: The Last Airbender|61|M||Legendary Creature - Avatar|4|3|Whenever you cast a spell, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."$Exhaust -- Waterbend {20}: Take an extra turn after this one.| +Lost Days|Avatar: The Last Airbender|62|C|{4}{U}|Instant - Lesson|||The owner of target creature or enchantment puts it into their library second from the top or on the bottom. You create a Clue token.| Master Pakku|Avatar: The Last Airbender|63|U|{1}{U}|Legendary Creature - Human Advisor Ally|1|3|Prowess$Whenever Master Pakku becomes tapped, target player mills X cards, where X is the number of Lesson cards in your graveyard.| +The Mechanist, Aerial Artisan|Avatar: The Last Airbender|64|R|{2}{U}|Legendary Creature - Human Artificer Ally|1|3|Whenever you cast a noncreature spell, create a Clue token.${T}: Until end of turn, target artifact token you control becomes a 3/1 Construct artifact creature with flying.| North Pole Patrol|Avatar: The Last Airbender|65|U|{2}{U}|Creature - Human Soldier Ally|2|3|{T}: Untap another target permanent you control.$Waterbend {3}, {T}: Tap target creature an opponent controls.| Otter-Penguin|Avatar: The Last Airbender|67|C|{1}{U}|Creature - Otter Bird|2|1|Whenever you draw your second card each turn, this creature gets +1/+2 until end of turn and can't be blocked this turn.| Rowdy Snowballers|Avatar: The Last Airbender|68|C|{2}{U}|Creature - Human Peasant Ally|2|2|When this creature enters, tap target creature an opponent controls and put a stun counter on it.| Secret of Bloodbending|Avatar: The Last Airbender|69|M|{U}{U}{U}{U}|Sorcery - Lesson|||As an additional cost to cast this spell, you may waterbend {10}.$You control target opponent during their next combat phase. If this spell's additional cost was paid, you control that player during their next turn instead.$Exile Secret of Bloodbending.| Serpent of the Pass|Avatar: The Last Airbender|70|U|{5}{U}{U}|Creature - Serpent|6|5|If there are three or more Lesson cards in your graveyard, you may cast this spell as though it had flash.$This spell costs {1} less to cast for each noncreature, nonland card in your graveyard.| Sokka's Haiku|Avatar: The Last Airbender|71|U|{3}{U}{U}|Instant - Lesson|||Counter target spell.$Draw a card, then mill three cards.$Untap target land.| +Teo, Spirited Glider|Avatar: The Last Airbender|74|U|{3}{U}|Legendary Creature - Human Pilot Ally|1|4|Flying$Whenever one or more creatures you control with flying attack, draw a card, then discard a card. When you discard a nonland card this way, put a +1/+1 counter on target creature you control.| Tiger-Seal|Avatar: The Last Airbender|75|R|{U}|Creature - Cat Seal|3|3|Vigilance$At the beginning of your upkeep, tap this creature.$Whenever you draw your second card each turn, untap this creature.| +Ty Lee, Chi Blocker|Avatar: The Last Airbender|76|R|{2}{U}|Legendary Creature - Human Performer Ally|2|1|Flash$Prowess$When Ty Lee enters, tap up to one target creature. It doesn't untap during its controller's untap step for as long as you control Ty Lee.| Wan Shi Tong, Librarian|Avatar: The Last Airbender|78|M|{X}{U}{U}|Legendary Creature - Bird Spirit|1|1|Flash$Flying, vigilance$When Wan Shi Tong enters, put X +1/+1 counters on him. Then draw half X cards, rounded down.$Whenever an opponent searches their library, put a +1/+1 counter on Wan Shi Tong and draw a card.| Waterbending Lesson|Avatar: The Last Airbender|80|C|{3}{U}|Sorcery - Lesson|||Draw three cards. Then discard a card unless you waterbend {2}.| Watery Grasp|Avatar: The Last Airbender|82|C|{U}|Enchantment - Aura|||Enchant creature$Enchanted creature doesn't untap during its controller's untap step.$Waterbend {5}: Enchanted creature's owner shuffles it into their library.| @@ -59814,12 +59823,15 @@ Day of Black Sun|Avatar: The Last Airbender|94|R|{X}{B}{B}|Sorcery|||Each creatu Epic Downfall|Avatar: The Last Airbender|96|U|{1}{B}|Sorcery|||Exile target creature with mana value 3 or greater.| The Fire Nation Drill|Avatar: The Last Airbender|98|R|{2}{B}{B}|Legendary Artifact - Vehicle|6|3|Trample$When The Fire Nation Drill enters, you may tap it. When you do, destroy target creature with power 4 or less.${1}: Permanents your opponents control lose hexproof and indestructible until end of turn.$Crew 2| Fire Nation Engineer|Avatar: The Last Airbender|99|U|{2}{B}|Creature - Human Artificer|2|3|Raid -- At the beginning of your end step, if you attacked this turn, put a +1/+1 counter on another target creature or Vehicle you control.| +Foggy Swamp Visions|Avatar: The Last Airbender|102|R|{1}{B}{B}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Exile X target creature cards from graveyards. For each creature card exiled this way, create a token that's a copy of it. At the beginning of your next end step, sacrifice those tokens.| Heartless Act|Avatar: The Last Airbender|103|U|{1}{B}|Instant|||Choose one --$* Destroy target creature with no counters on it.$* Remove up to three counters from target creature.| Hog-Monkey|Avatar: The Last Airbender|104|C|{2}{B}|Creature - Boar Monkey|3|2|At the beginning of combat on your turn, target creature you control with a +1/+1 counter on it gains menace until end of turn.$Exhaust -- {5}: Put two +1/+1 counters on this creature.| Merchant of Many Hats|Avatar: The Last Airbender|110|C|{1}{B}|Creature - Human Peasant Ally|2|2|{2}{B}: Return this card from your graveyard to your hand.| +Northern Air Temple|Avatar: The Last Airbender|111|U|{B}|Legendary Enchantment - Shrine|||When Northern Air Temple enters, each opponent loses X life and you gain X life, where X is the number of Shrines you control.$Whenever another Shrine you control enters, each opponent loses 1 life and you gain 1 life.| Ozai's Cruelty|Avatar: The Last Airbender|113|U|{2}{B}|Sorcery - Lesson|||Ozai's Cruelty deals 2 damage to target player. That player discards two cards.| The Rise of Sozin|Avatar: The Last Airbender|117|M|{4}{B}{B}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I -- Destroy all creatures.$II -- Choose a card name. Search target opponent's graveyard, hand, and library for up to four cards with that name and exile them. Then that player shuffles.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| Fire Lord Sozin|Avatar: The Last Airbender|117|M||Legendary Creature - Human Noble|5|5|Menace, firebending 3$Whenever Fire Lord Sozin deals combat damage to a player, you may pay {X}. When you do, put any number of target creature cards with total mana value X or less from that player's graveyard onto the battlefield under your control.| +Tundra Tank|Avatar: The Last Airbender|121|U|{2}{B}|Artifact - Vehicle|4|4|Firebending 1$When this Vehicle enters, target creature you control gains indestructible until end of turn.$Crew 1| The Cave of Two Lovers|Avatar: The Last Airbender|126|U|{3}{R}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I -- Create two 1/1 white Ally creature tokens.$II -- Search your library for a Mountain or Cave card, reveal it, put it into your hand,$then shuffle.$III -- Earthbend 3.| Crescent Island Temple|Avatar: The Last Airbender|129|U|{3}{R}|Legendary Enchantment - Shrine|||When Crescent Island Temple enters, for each Shrine you control, create a 1/1 red Monk creature token with prowess.$Whenever another Shrine you control enters, create a 1/1 red Monk creature token with prowess.| Cunning Maneuver|Avatar: The Last Airbender|130|C|{1}{R}|Instant|||Target creature gets +3/+1 until end of turn.$Create a Clue token.| @@ -59839,6 +59851,7 @@ Redirect Lightning|Avatar: The Last Airbender|151|R|{R}|Instant - Lesson|||As an Rough Rhino Cavalry|Avatar: The Last Airbender|152|C|{4}{R}|Creature - Human Mercenary|5|5|Firebending 2$Exhaust -- {8}: Put two +1/+1 counters on this creature. It gains trample until end of turn.| Solstice Revelations|Avatar: The Last Airbender|153|U|{2}{R}|Instant - Lesson|||Exile cards from the top of your library until you exile a nonland card. You may cast that card without paying its mana cost if the spell's mana value is less than the number of Mountains you control. If you don't cast that card this way, put it into your hand.$Flashback {6}{R}| Sozin's Comet|Avatar: The Last Airbender|154|M|{3}{R}{R}|Sorcery|||Each creature you control gains firebending 5 until end of turn.$Foretell {2}{R}| +Ty Lee, Artful Acrobat|Avatar: The Last Airbender|158|U|{2}{R}|Legendary Creature - Human Performer|3|2|Prowess$Whenever Ty Lee attacks, you may pay {1}. When you do, target creature can't block this turn.| War Balloon|Avatar: The Last Airbender|159|U|{2}{R}|Artifact - Vehicle|4|3|Flying${1}: Put a fire counter on this Vehicle.$As long as this Vehicle has three or more fire counters on it, it's an artifact creature.$Crew 3| Yuyan Archers|Avatar: The Last Airbender|161|C|{1}{R}|Creature - Human Archer|3|1|Reach$When this creature enters, you may discard a card. If you do, draw a card.| Zuko, Exiled Prince|Avatar: The Last Airbender|163|U|{3}{R}|Legendary Creature - Human Noble|4|3|Firebending 3${3}: Exile the top card of your library. You may play that card this turn.| @@ -59846,6 +59859,7 @@ Allies at Last|Avatar: The Last Airbender|164|U|{2}{G}|Instant|||Affinity for Al Badgermole|Avatar: The Last Airbender|166|C|{4}{G}|Creature - Badger Mole|4|4|When this creature enters, earthbend 2.$Creatures you control with +1/+1 counters on them have trample.| Badgermole Cub|Avatar: The Last Airbender|167|M|{1}{G}|Creature - Badger Mole|2|2|When this creature enters, earthbend 1.$Whenever you tap a creature for mana, add an additional {G}.| Cycle of Renewal|Avatar: The Last Airbender|170|C|{2}{G}|Instant - Lesson|||Sacrifice a land. Search your library for up to two basic land cards, put them onto the battlefield tapped, then shuffle.| +Diligent Zookeeper|Avatar: The Last Airbender|171|R|{3}{G}|Creature - Human Citizen Ally|4|4|Each non-Human creature you control gets +1/+1 for each of its creature types, to a maximum of 10.| Earth Rumble|Avatar: The Last Airbender|174|U|{3}{G}|Sorcery|||Earthbend 2. When you do, up to one target creature you control fights target creature an opponent controls.| Earthbending Lesson|Avatar: The Last Airbender|176|C|{3}{G}|Sorcery - Lesson|||Earthbend 4.| Flopsie, Bumi's Buddy|Avatar: The Last Airbender|179|U|{4}{G}{G}|Legendary Creature - Ape Goat|4|4|When Flopsie enters, put a +1/+1 counter on each creature you control.$Each creature you control with power 4 or greater can't be blocked by more than one creature.| @@ -59861,13 +59875,16 @@ Saber-Tooth Moose-Lion|Avatar: The Last Airbender|194|C|{4}{G}{G}|Creature - Elk Seismic Sense|Avatar: The Last Airbender|195|U|{G}|Sorcery - Lesson|||Look at the top X cards of your library, where X is the number of lands you control. You may reveal a creature or land card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| Sparring Dummy|Avatar: The Last Airbender|197|U|{1}{G}|Artifact Creature - Scarecrow|1|3|Defender${T}: Mill a card. You may put a land card milled this way into your hand. You gain 2 life if a Lesson card is milled this way.| Toph, the Blind Bandit|Avatar: The Last Airbender|198|U|{2}{G}|Legendary Creature - Human Warrior Ally|*|3|When Toph enters, earthbend 2.$Toph's power is equal to the number of +1/+1 counters on lands you control.| +True Ancestry|Avatar: The Last Airbender|199|U|{1}{G}|Sorcery - Lesson|||Return up to one target permanent card from your graveyard to your hand.$Create a Clue token.| Turtle-Duck|Avatar: The Last Airbender|200|C|{G}|Creature - Turtle Bird|0|4|{3}: Until end of turn, this creature has base power 4 and gains trample.| +Unlucky Cabbage Merchant|Avatar: The Last Airbender|201|U|{1}{G}|Creature - Human Citizen|2|2|When this creature enters, create a Food token.$Whenever you sacrifice a Food, you may search your library for a basic land card and put it onto the battlefield tapped. If you search your library this way, put this creature on the bottom of its owner's library, then shuffle.| Aang, at the Crossroads|Avatar: The Last Airbender|203|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| Aang, Destined Savior|Avatar: The Last Airbender|203|R||Legendary Creature - Avatar Ally|4|4|Flying$Land creatures you control have vigilance.$At the beginning of combat on your turn, earthbend 2.| Abandon Attachments|Avatar: The Last Airbender|205|C|{1}{U/R}|Instant - Lesson|||You may discard a card. If you do, draw two cards.| Avatar Aang|Avatar: The Last Airbender|207|M|{R}{G}{W}{U}|Legendary Creature - Human Avatar Ally|4|4|Flying, firebending 2$Whenever you waterbend, earthbend, firebend, or airbend, draw a card. Then if you've done all four this turn, transform Avatar Aang.| Aang, Master of Elements|Avatar: The Last Airbender|207|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Azula, Cunning Usurper|Avatar: The Last Airbender|208|R|{2}{U}{B}{B}|Legendary Creature - Human Noble Rogue|4|4|Firebending 2$When Azula enters, target opponent exiles a nontoken creature they control, then they exile a nonland card from their graveyard.$During your turn, you may cast cards exiled with Azula and you may cast them as though they had flash. Mana of any type can be spent to cast those spells.| +Bumi, Unleashed|Avatar: The Last Airbender|211|M|{3}{R}{G}|Legendary Creature - Human Noble Ally|5|4|Trample$When Bumi enters, earthbend 4.$Whenever Bumi deals combat damage to a player, untap all lands you control. After this phase, there is an additional combat phase. Only land creatures can attack during that combat phase.| Cat-Owl|Avatar: The Last Airbender|212|C|{3}{W/U}|Creature - Cat Bird|3|3|Flying$Whenever this creature attacks, untap target artifact or creature.| Dai Li Agents|Avatar: The Last Airbender|214|U|{3}{B}{G}|Creature - Human Soldier|3|4|When this creature enters, earthbend 1, then earthbend 1.$Whenever this creature attacks, each opponent loses X life and you gain X life, where X is the number of creatures you control with +1/+1 counters on them.| Dragonfly Swarm|Avatar: The Last Airbender|215|U|{1}{U}{R}|Creature - Dragon Insect|*|3|Flying, ward {1}$This creature's power is equal to the number of noncreature, nonland cards in your graveyard.$When this creature dies, if there's a Lesson card in your graveyard, draw a card.| @@ -59897,8 +59914,11 @@ Vindictive Warden|Avatar: The Last Airbender|249|C|{2}{B/R}|Creature - Human Sol White Lotus Reinforcements|Avatar: The Last Airbender|251|U|{1}{G}{W}|Creature - Human Soldier Ally|2|3|Vigilance$Other Allies you control get +1/+1.| Barrels of Blasting Jelly|Avatar: The Last Airbender|254|C|{1}|Artifact|||{1}: Add one mana of any color. Activate only once each turn.${5}, {T}, Sacrifice this artifact: It deals 5 damage to target creature.| Bender's Waterskin|Avatar: The Last Airbender|255|C|{3}|Artifact|||Untap this artifact during each other player's untap step.${T}: Add one mana of any color.| +Planetarium of Wan Shi Tong|Avatar: The Last Airbender|259|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| Trusty Boomerang|Avatar: The Last Airbender|260|U|{1}|Artifact - Equipment|||Equipped creature has "{1}, {T}: Tap target creature. Return Trusty Boomerang to its owner's hand."$Equip {1}| White Lotus Tile|Avatar: The Last Airbender|262|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| +Secret Tunnel|Avatar: The Last Airbender|278|R||Land - Cave|||This land can't be blocked.${T}: Add {C}.${4}, {T}: Two target creatures you control that share a creature type can't be blocked this turn.| +White Lotus Hideout|Avatar: The Last Airbender|281|U||Land|||{T}: Add {C}.${T}: Add one mana of any color. Spend this mana only to cast a Lesson or Shrine spell.${1}, {T}: Add one mana of any color.| Plains|Avatar: The Last Airbender|282|C||Basic Land - Plains|||({T}: Add {W}.)| Island|Avatar: The Last Airbender|283|C||Basic Land - Island|||({T}: Add {U}.)| Swamp|Avatar: The Last Airbender|284|C||Basic Land - Swamp|||({T}: Add {B}.)| @@ -59935,6 +59955,7 @@ Wan Shi Tong, Librarian|Avatar: The Last Airbender|320|M|{X}{U}{U}|Legendary Cre The Fire Nation Drill|Avatar: The Last Airbender|321|R|{2}{B}{B}|Legendary Artifact - Vehicle|6|3|Trample$When The Fire Nation Drill enters, you may tap it. When you do, destroy target creature with power 4 or less.${1}: Permanents your opponents control lose hexproof and indestructible until end of turn.$Crew 2| Ran and Shaw|Avatar: The Last Airbender|325|R|{3}{R}{R}|Legendary Creature - Dragon|4|4|Flying, firebending 2$When Ran and Shaw enter, if you cast them and there are three or more Dragon and/or Lesson cards in your graveyard, create a token that's a copy of Ran and Shaw, except it's not legendary.${3}{R}: Dragons you control get +2/+0 until end of turn.| Badgermole Cub|Avatar: The Last Airbender|326|M|{1}{G}|Creature - Badger Mole|2|2|When this creature enters, earthbend 1.$Whenever you tap a creature for mana, add an additional {G}.| +Diligent Zookeeper|Avatar: The Last Airbender|327|R|{3}{G}|Creature - Human Citizen Ally|4|4|Each non-Human creature you control gets +1/+1 for each of its creature types, to a maximum of 10.| The Lion-Turtle|Avatar: The Last Airbender|328|R|{1}{G}{U}|Legendary Creature - Elder Cat Turtle|3|6|Vigilance, reach$When The Lion-Turtle enters, you gain 3 life.$The Lion-Turtle can't attack or block unless there are three or more Lesson cards in your graveyard.${T}: Add one mana of any color.| White Lotus Tile|Avatar: The Last Airbender|330|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| Sozin's Comet|Avatar: The Last Airbender|332|M|{3}{R}{R}|Sorcery|||Each creature you control gains firebending 5 until end of turn.$Foretell {2}{R}| @@ -59943,11 +59964,13 @@ Ozai, the Phoenix King|Avatar: The Last Airbender|335|M|{2}{B}{B}{R}{R}|Legendar Aang's Iceberg|Avatar: The Last Airbender|336|R|{2}{W}|Enchantment|||Flash$When this enchantment enters, exile up to one other target nonland permanent until this enchantment leaves the battlefield.$Waterbend {3}: Sacrifice this enchantment. If you do, scry 2.| Secret of Bloodbending|Avatar: The Last Airbender|337|M|{U}{U}{U}{U}|Sorcery - Lesson|||As an additional cost to cast this spell, you may waterbend {10}.$You control target opponent during their next combat phase. If this spell's additional cost was paid, you control that player during their next turn instead.$Exile Secret of Bloodbending.| Yue, the Moon Spirit|Avatar: The Last Airbender|338|R|{3}{U}|Legendary Creature - Spirit Ally|3|3|Flying, vigilance$Waterbend {5}, {T}: You may cast a noncreature spell from your hand without paying its mana cost.| +Foggy Swamp Visions|Avatar: The Last Airbender|339|R|{1}{B}{B}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Exile X target creature cards from graveyards. For each creature card exiled this way, create a token that's a copy of it. At the beginning of your next end step, sacrifice those tokens.| Fated Firepower|Avatar: The Last Airbender|341|M|{X}{R}{R}{R}|Enchantment|||Flash$This enchantment enters with X fire counters on it.$If a source you control would deal damage to an opponent or a permanent an opponent controls, it deals that much damage plus an amount of damage equal to the number of fire counters on this enchantment instead.| Firebending Student|Avatar: The Last Airbender|342|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| Redirect Lightning|Avatar: The Last Airbender|343|R|{R}|Instant - Lesson|||As an additional cost to cast this spell, pay 5 life or pay {2}.$Change the target of target spell or ability with a single target.| Aang, at the Crossroads|Avatar: The Last Airbender|346|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| Aang, Destined Savior|Avatar: The Last Airbender|346|R||Legendary Creature - Avatar Ally|4|4|Flying$Land creatures you control have vigilance.$At the beginning of combat on your turn, earthbend 2.| +Bumi, Unleashed|Avatar: The Last Airbender|348|M|{3}{R}{G}|Legendary Creature - Human Noble Ally|5|4|Trample$When Bumi enters, earthbend 4.$Whenever Bumi deals combat damage to a player, untap all lands you control. After this phase, there is an additional combat phase. Only land creatures can attack during that combat phase.| Iroh, Grand Lotus|Avatar: The Last Airbender|349|R|{3}{G}{U}{R}|Legendary Creature - Human Noble Ally|5|5|Firebending 2$During your turn, each non-Lesson instant and sorcery card in your graveyard has flashback. The flashback cost is equal to that card's mana cost.$During your turn, each Lesson card in your graveyard has flashback {1}.| Katara, the Fearless|Avatar: The Last Airbender|350|R|{G}{W}{U}|Legendary Creature - Human Warrior Ally|3|3|If a triggered ability of an Ally you control triggers, that ability triggers an additional time.| Katara, Water Tribe's Hope|Avatar: The Last Airbender|351|R|{2}{W}{U}{U}|Legendary Creature - Human Warrior Ally|3|3|Vigilance$When Katara enters, create a 1/1 white Ally creature token.$Waterbend {X}: Creatures you control have base power and toughness X/X until end of turn. X can't be 0. Activate only during your turn.| @@ -59966,10 +59989,14 @@ Avatar Aang|Avatar: The Last Airbender|363|M|{R}{G}{W}{U}|Legendary Creature - H Aang, Master of Elements|Avatar: The Last Airbender|363|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Airbender Ascension|Avatar: The Last Airbender|364|R|{1}{W}|Enchantment|||When this enchantment enters, airbend up to one target creature.$Whenever a creature you control enters, put a quest counter on this enchantment.$At the beginning of your end step, if this enchantment has four or more quest counters on it, exile up to one target creature you control, then return it to the battlefield under its owner's control.| Hakoda, Selfless Commander|Avatar: The Last Airbender|366|R|{3}{W}|Legendary Creature - Human Warrior Ally|3|5|Vigilance$You may look at the top card of your library any time.$You may cast Ally spells from the top of your library.$Sacrifice Hakoda: Creatures you control get +0/+5 and gain indestructible until end of turn.| +The Mechanist, Aerial Artisan|Avatar: The Last Airbender|369|R|{2}{U}|Legendary Creature - Human Artificer Ally|1|3|Whenever you cast a noncreature spell, create a Clue token.${T}: Until end of turn, target artifact token you control becomes a 3/1 Construct artifact creature with flying.| +Ty Lee, Chi Blocker|Avatar: The Last Airbender|371|R|{2}{U}|Legendary Creature - Human Performer Ally|2|1|Flash$Prowess$When Ty Lee enters, tap up to one target creature. It doesn't untap during its controller's untap step for as long as you control Ty Lee.| Boiling Rock Rioter|Avatar: The Last Airbender|372|R|{2}{B}|Creature - Human Rogue Ally|3|3|Firebending 1$Tap an untapped Ally you control: Exile target card from a graveyard.$Whenever this creature attacks, you may cast an Ally spell from among cards you own exiled with this creature.| Day of Black Sun|Avatar: The Last Airbender|373|R|{X}{B}{B}|Sorcery|||Each creature with mana value X or less loses all abilities until end of turn. Destroy those creatures.| Earth King's Lieutenant|Avatar: The Last Airbender|380|R|{G}{W}|Creature - Human Soldier Ally|1|1|Trample$When this creature enters, put a +1/+1 counter on each other Ally creature you control.$Whenever another Ally you control enters, put a +1/+1 counter on this creature.| Sokka, Bold Boomeranger|Avatar: The Last Airbender|383|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.| +Planetarium of Wan Shi Tong|Avatar: The Last Airbender|385|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| +Secret Tunnel|Avatar: The Last Airbender|392|R||Land - Cave|||This land can't be blocked.${T}: Add {C}.${4}, {T}: Two target creatures you control that share a creature type can't be blocked this turn.| Firebending Student|Avatar: The Last Airbender|393|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| Momo, Friendly Flier|Avatar: The Last Airbender|394|R|{W}|Legendary Creature - Lemur Bat Ally|1|1|Flying$The first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast.$Whenever another creature you control with flying enters, Momo gets +1/+1 until end of turn.| Anti-Venom, Horrifying Healer|Marvel's Spider-Man|1|M|{W}{W}{W}{W}{W}|Legendary Creature - Symbiote Hero|5|5|When Anti-Venom enters, if he was cast, return target creature card from your graveyard to the battlefield.$If damage would be dealt to Anti-Venom, prevent that damage and put that many +1/+1 counters on him.| -- 2.47.2 From b1ca3804ccdd518fa257c2619f84cfb0adb501b3 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 13:16:14 -0400 Subject: [PATCH 015/261] [TLA] Implement True Ancestry --- Mage.Sets/src/mage/cards/t/TrueAncestry.java | 41 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 42 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TrueAncestry.java diff --git a/Mage.Sets/src/mage/cards/t/TrueAncestry.java b/Mage.Sets/src/mage/cards/t/TrueAncestry.java new file mode 100644 index 00000000000..43074a1e138 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TrueAncestry.java @@ -0,0 +1,41 @@ +package mage.cards.t; + +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.game.permanent.token.ClueArtifactToken; +import mage.target.common.TargetCardInYourGraveyard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TrueAncestry extends CardImpl { + + public TrueAncestry(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}"); + + this.subtype.add(SubType.LESSON); + + // Return up to one target permanent card from your graveyard to your hand. + this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 1, StaticFilters.FILTER_CARD_PERMANENT)); + + // Create a Clue token. + this.getSpellAbility().addEffect(new CreateTokenEffect(new ClueArtifactToken()).concatBy("
")); + } + + private TrueAncestry(final TrueAncestry card) { + super(card); + } + + @Override + public TrueAncestry copy() { + return new TrueAncestry(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index cddae2375c1..baf5a522f1e 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -166,6 +166,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Toph, the First Metalbender", 247, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Toph, the First Metalbender", 353, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Toph, the First Metalbender", 362, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("True Ancestry", 199, Rarity.UNCOMMON, mage.cards.t.TrueAncestry.class)); cards.add(new SetCardInfo("Turtle-Duck", 200, Rarity.COMMON, mage.cards.t.TurtleDuck.class)); cards.add(new SetCardInfo("Vindictive Warden", 249, Rarity.COMMON, mage.cards.v.VindictiveWarden.class)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); -- 2.47.2 From fb4317a9885ecf1b0602f4ee10bd49fb3f3c4ba8 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 13:17:06 -0400 Subject: [PATCH 016/261] [TLA] Implement Forecasting Fortune Teller --- .../cards/f/ForecastingFortuneTeller.java | 40 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 41 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/ForecastingFortuneTeller.java diff --git a/Mage.Sets/src/mage/cards/f/ForecastingFortuneTeller.java b/Mage.Sets/src/mage/cards/f/ForecastingFortuneTeller.java new file mode 100644 index 00000000000..d994797a041 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForecastingFortuneTeller.java @@ -0,0 +1,40 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.ClueArtifactToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ForecastingFortuneTeller extends CardImpl { + + public ForecastingFortuneTeller(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ADVISOR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // When this creature enters, create a Clue token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ClueArtifactToken()))); + } + + private ForecastingFortuneTeller(final ForecastingFortuneTeller card) { + super(card); + } + + @Override + public ForecastingFortuneTeller copy() { + return new ForecastingFortuneTeller(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index baf5a522f1e..c6db6c305f5 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -79,6 +79,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("First-Time Flyer", 49, Rarity.COMMON, mage.cards.f.FirstTimeFlyer.class)); cards.add(new SetCardInfo("Flexible Waterbender", 50, Rarity.COMMON, mage.cards.f.FlexibleWaterbender.class)); cards.add(new SetCardInfo("Flopsie, Bumi's Buddy", 179, Rarity.UNCOMMON, mage.cards.f.FlopsieBumisBuddy.class)); + cards.add(new SetCardInfo("Forecasting Fortune Teller", 51, Rarity.COMMON, mage.cards.f.ForecastingFortuneTeller.class)); cards.add(new SetCardInfo("Forest", 286, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Forest", 291, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Forest", 296, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); -- 2.47.2 From ba4c030009e389feaae01024c8d887aa8cbfc5c8 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 13:18:33 -0400 Subject: [PATCH 017/261] [TLA] Implement Fancy Footwork --- Mage.Sets/src/mage/cards/f/FancyFootwork.java | 37 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 38 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FancyFootwork.java diff --git a/Mage.Sets/src/mage/cards/f/FancyFootwork.java b/Mage.Sets/src/mage/cards/f/FancyFootwork.java new file mode 100644 index 00000000000..45336365344 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FancyFootwork.java @@ -0,0 +1,37 @@ +package mage.cards.f; + +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FancyFootwork extends CardImpl { + + public FancyFootwork(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); + + this.subtype.add(SubType.LESSON); + + // Untap one or two target creatures. They each get +2/+2 until end of turn. + this.getSpellAbility().addEffect(new UntapTargetEffect()); + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2).setText("They each get +2/+2 until end of turn")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(1, 2)); + } + + private FancyFootwork(final FancyFootwork card) { + super(card); + } + + @Override + public FancyFootwork copy() { + return new FancyFootwork(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index c6db6c305f5..1070336e31b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -61,6 +61,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Earth Village Ruffians", 219, Rarity.COMMON, mage.cards.e.EarthVillageRuffians.class)); cards.add(new SetCardInfo("Earthbending Lesson", 176, Rarity.COMMON, mage.cards.e.EarthbendingLesson.class)); cards.add(new SetCardInfo("Epic Downfall", 96, Rarity.UNCOMMON, mage.cards.e.EpicDownfall.class)); + cards.add(new SetCardInfo("Fancy Footwork", 19, Rarity.UNCOMMON, mage.cards.f.FancyFootwork.class)); cards.add(new SetCardInfo("Fated Firepower", 132, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fated Firepower", 297, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fated Firepower", 341, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From ed34fa40613822e505bafb7e62c579a1dd9db932 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 13:20:13 -0400 Subject: [PATCH 018/261] [TLA] Implement Ty Lee, Artful Acrobat --- .../src/mage/cards/t/TyLeeArtfulAcrobat.java | 51 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 52 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TyLeeArtfulAcrobat.java diff --git a/Mage.Sets/src/mage/cards/t/TyLeeArtfulAcrobat.java b/Mage.Sets/src/mage/cards/t/TyLeeArtfulAcrobat.java new file mode 100644 index 00000000000..2a70fc7b031 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TyLeeArtfulAcrobat.java @@ -0,0 +1,51 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.delayed.ReflexiveTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DoWhenCostPaid; +import mage.abilities.effects.common.combat.CantBlockTargetEffect; +import mage.abilities.keyword.ProwessAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TyLeeArtfulAcrobat extends CardImpl { + + public TyLeeArtfulAcrobat(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.PERFORMER); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Prowess + this.addAbility(new ProwessAbility()); + + // Whenever Ty Lee attacks, you may pay {1}. When you do, target creature can't block this turn. + ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(new CantBlockTargetEffect(Duration.EndOfTurn), false); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(new AttacksTriggeredAbility(new DoWhenCostPaid(ability, new GenericManaCost(1), "Pay {1}?"))); + } + + private TyLeeArtfulAcrobat(final TyLeeArtfulAcrobat card) { + super(card); + } + + @Override + public TyLeeArtfulAcrobat copy() { + return new TyLeeArtfulAcrobat(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 1070336e31b..ba24f92af67 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -170,6 +170,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Toph, the First Metalbender", 362, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("True Ancestry", 199, Rarity.UNCOMMON, mage.cards.t.TrueAncestry.class)); cards.add(new SetCardInfo("Turtle-Duck", 200, Rarity.COMMON, mage.cards.t.TurtleDuck.class)); + cards.add(new SetCardInfo("Ty Lee, Artful Acrobat", 158, Rarity.UNCOMMON, mage.cards.t.TyLeeArtfulAcrobat.class)); cards.add(new SetCardInfo("Vindictive Warden", 249, Rarity.COMMON, mage.cards.v.VindictiveWarden.class)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); cards.add(new SetCardInfo("Watery Grasp", 82, Rarity.COMMON, mage.cards.w.WateryGrasp.class)); -- 2.47.2 From 87b040b86fa841b9cb5a57bc1b66068cb601051a Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 13:21:53 -0400 Subject: [PATCH 019/261] [TLA] Implement Momo, Playful Pet --- .../src/mage/cards/m/MomoPlayfulPet.java | 65 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 66 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MomoPlayfulPet.java diff --git a/Mage.Sets/src/mage/cards/m/MomoPlayfulPet.java b/Mage.Sets/src/mage/cards/m/MomoPlayfulPet.java new file mode 100644 index 00000000000..48eede2e37e --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MomoPlayfulPet.java @@ -0,0 +1,65 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +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.game.permanent.token.FoodToken; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MomoPlayfulPet extends CardImpl { + + public MomoPlayfulPet(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.LEMUR); + this.subtype.add(SubType.BAT); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // When Momo leaves the battlefield, choose one -- + // * Create a Food token. + Ability ability = new LeavesBattlefieldTriggeredAbility(new CreateTokenEffect(new FoodToken())); + + // * Put a +1/+1 counter on target creature you control. + ability.addMode(new Mode(new AddCountersTargetEffect(CounterType.P1P1.createInstance())) + .addTarget(new TargetControlledCreaturePermanent())); + + // * Scry 2. + ability.addMode(new Mode(new ScryEffect(2))); + this.addAbility(ability); + } + + private MomoPlayfulPet(final MomoPlayfulPet card) { + super(card); + } + + @Override + public MomoPlayfulPet copy() { + return new MomoPlayfulPet(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index ba24f92af67..08cc97bcbba 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -117,6 +117,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Momo, Friendly Flier", 29, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Momo, Friendly Flier", 317, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Momo, Friendly Flier", 394, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Momo, Playful Pet", 30, Rarity.UNCOMMON, mage.cards.m.MomoPlayfulPet.class)); cards.add(new SetCardInfo("Mongoose Lizard", 148, Rarity.COMMON, mage.cards.m.MongooseLizard.class)); cards.add(new SetCardInfo("Mountain", 285, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 290, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); -- 2.47.2 From 955fe401729cebdd4445f7e46c47051869a622c1 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 13:24:14 -0400 Subject: [PATCH 020/261] [TLA] Implement War Balloon --- Mage.Sets/src/mage/cards/w/WarBalloon.java | 63 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 64 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/w/WarBalloon.java diff --git a/Mage.Sets/src/mage/cards/w/WarBalloon.java b/Mage.Sets/src/mage/cards/w/WarBalloon.java new file mode 100644 index 00000000000..c1374c9a8a5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WarBalloon.java @@ -0,0 +1,63 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.CrewAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.counters.CounterType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WarBalloon extends CardImpl { + + private static final Condition condition = new SourceHasCounterCondition(CounterType.FIRE, 3); + + public WarBalloon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{R}"); + + this.subtype.add(SubType.VEHICLE); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {1}: Put a fire counter on this Vehicle. + this.addAbility(new SimpleActivatedAbility( + new AddCountersSourceEffect(CounterType.FIRE.createInstance()), new GenericManaCost(1) + )); + + // As long as this Vehicle has three or more fire counters on it, it's an artifact creature. + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new AddCardTypeSourceEffect(Duration.WhileOnBattlefield, CardType.ARTIFACT, CardType.CREATURE), + condition, "as long as {this} has three or more fire counters on it, it's an artifact creature" + ))); + + // Crew 3 + this.addAbility(new CrewAbility(3)); + } + + private WarBalloon(final WarBalloon card) { + super(card); + } + + @Override + public WarBalloon copy() { + return new WarBalloon(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 08cc97bcbba..a4eb7bd0b9b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -173,6 +173,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Turtle-Duck", 200, Rarity.COMMON, mage.cards.t.TurtleDuck.class)); cards.add(new SetCardInfo("Ty Lee, Artful Acrobat", 158, Rarity.UNCOMMON, mage.cards.t.TyLeeArtfulAcrobat.class)); cards.add(new SetCardInfo("Vindictive Warden", 249, Rarity.COMMON, mage.cards.v.VindictiveWarden.class)); + cards.add(new SetCardInfo("War Balloon", 159, Rarity.UNCOMMON, mage.cards.w.WarBalloon.class)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); cards.add(new SetCardInfo("Watery Grasp", 82, Rarity.COMMON, mage.cards.w.WateryGrasp.class)); cards.add(new SetCardInfo("White Lotus Reinforcements", 251, Rarity.UNCOMMON, mage.cards.w.WhiteLotusReinforcements.class)); -- 2.47.2 From 2218ec0ae4af341875c42a4050337b5aa4d80a6f Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 13:25:32 -0400 Subject: [PATCH 021/261] [TLA] Implement Uncle Iroh --- Mage.Sets/src/mage/cards/u/UncleIroh.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/u/UncleIroh.java diff --git a/Mage.Sets/src/mage/cards/u/UncleIroh.java b/Mage.Sets/src/mage/cards/u/UncleIroh.java new file mode 100644 index 00000000000..b4f17a16898 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UncleIroh.java @@ -0,0 +1,48 @@ +package mage.cards.u; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +import mage.abilities.keyword.FirebendingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterCard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UncleIroh extends CardImpl { + + private static final FilterCard filter = new FilterCard(SubType.LESSON, "Lesson spells"); + + public UncleIroh(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R/G}{R/G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // Firebending 1 + this.addAbility(new FirebendingAbility(1)); + + // Lesson spells you cast cost {1} less to cast. + this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1))); + } + + private UncleIroh(final UncleIroh card) { + super(card); + } + + @Override + public UncleIroh copy() { + return new UncleIroh(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index a4eb7bd0b9b..f0765fe1908 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -172,6 +172,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("True Ancestry", 199, Rarity.UNCOMMON, mage.cards.t.TrueAncestry.class)); cards.add(new SetCardInfo("Turtle-Duck", 200, Rarity.COMMON, mage.cards.t.TurtleDuck.class)); cards.add(new SetCardInfo("Ty Lee, Artful Acrobat", 158, Rarity.UNCOMMON, mage.cards.t.TyLeeArtfulAcrobat.class)); + cards.add(new SetCardInfo("Uncle Iroh", 248, Rarity.UNCOMMON, mage.cards.u.UncleIroh.class)); cards.add(new SetCardInfo("Vindictive Warden", 249, Rarity.COMMON, mage.cards.v.VindictiveWarden.class)); cards.add(new SetCardInfo("War Balloon", 159, Rarity.UNCOMMON, mage.cards.w.WarBalloon.class)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); -- 2.47.2 From 4e46920b5075d700fa23fe666beec576959a8047 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 13:26:38 -0400 Subject: [PATCH 022/261] [TLA] Implement Sun Warriors --- Mage.Sets/src/mage/cards/s/SunWarriors.java | 46 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 47 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SunWarriors.java diff --git a/Mage.Sets/src/mage/cards/s/SunWarriors.java b/Mage.Sets/src/mage/cards/s/SunWarriors.java new file mode 100644 index 00000000000..1d7e33d3f4f --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SunWarriors.java @@ -0,0 +1,46 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.common.CreaturesYouControlCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.FirebendingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.AllyToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SunWarriors extends CardImpl { + + public SunWarriors(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(5); + + // Firebending X, where X is the number of creatures you control. + this.addAbility(new FirebendingAbility(CreaturesYouControlCount.PLURAL)); + + // {5}: Create a 1/1 white Ally creature token. + this.addAbility(new SimpleActivatedAbility(new CreateTokenEffect(new AllyToken()), new GenericManaCost(5))); + } + + private SunWarriors(final SunWarriors card) { + super(card); + } + + @Override + public SunWarriors copy() { + return new SunWarriors(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index f0765fe1908..57990ef5c4b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -157,6 +157,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Sozin's Comet", 309, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sozin's Comet", 332, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Suki, Kyoshi Warrior", 243, Rarity.UNCOMMON, mage.cards.s.SukiKyoshiWarrior.class)); + cards.add(new SetCardInfo("Sun Warriors", 244, Rarity.UNCOMMON, mage.cards.s.SunWarriors.class)); cards.add(new SetCardInfo("Swamp", 284, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Swamp", 289, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swamp", 294, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); -- 2.47.2 From 3ebe6ec782870e6c92a68b8736aed2bc3b0bfa53 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 16:16:38 -0400 Subject: [PATCH 023/261] [TLA] Implement Compassionate Healer --- .../src/mage/cards/c/CompassionateHealer.java | 43 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 44 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CompassionateHealer.java diff --git a/Mage.Sets/src/mage/cards/c/CompassionateHealer.java b/Mage.Sets/src/mage/cards/c/CompassionateHealer.java new file mode 100644 index 00000000000..657ca96d331 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CompassionateHealer.java @@ -0,0 +1,43 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BecomesTappedSourceTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CompassionateHealer extends CardImpl { + + public CompassionateHealer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever this creature becomes tapped, you gain 1 life and scry 1. + Ability ability = new BecomesTappedSourceTriggeredAbility(new GainLifeEffect(1)); + ability.addEffect(new ScryEffect(1).concatBy("and")); + this.addAbility(ability); + } + + private CompassionateHealer(final CompassionateHealer card) { + super(card); + } + + @Override + public CompassionateHealer copy() { + return new CompassionateHealer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 57990ef5c4b..69f4e22c2da 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -51,6 +51,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Buzzard-Wasp Colony", 88, Rarity.UNCOMMON, mage.cards.b.BuzzardWaspColony.class)); cards.add(new SetCardInfo("Cat-Gator", 91, Rarity.UNCOMMON, mage.cards.c.CatGator.class)); cards.add(new SetCardInfo("Cat-Owl", 212, Rarity.COMMON, mage.cards.c.CatOwl.class)); + cards.add(new SetCardInfo("Compassionate Healer", 13, Rarity.COMMON, mage.cards.c.CompassionateHealer.class)); cards.add(new SetCardInfo("Corrupt Court Official", 92, Rarity.COMMON, mage.cards.c.CorruptCourtOfficial.class)); cards.add(new SetCardInfo("Cunning Maneuver", 130, Rarity.COMMON, mage.cards.c.CunningManeuver.class)); cards.add(new SetCardInfo("Cycle of Renewal", 170, Rarity.COMMON, mage.cards.c.CycleOfRenewal.class)); -- 2.47.2 From 75f26e345346dbed8fa70307250a808a183caf17 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 16:21:25 -0400 Subject: [PATCH 024/261] [TLA] Implement Dragonfly Swarm --- .../src/mage/cards/d/DragonflySwarm.java | 77 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 78 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/d/DragonflySwarm.java diff --git a/Mage.Sets/src/mage/cards/d/DragonflySwarm.java b/Mage.Sets/src/mage/cards/d/DragonflySwarm.java new file mode 100644 index 00000000000..be39d818143 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DragonflySwarm.java @@ -0,0 +1,77 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.SetBasePowerSourceEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.WardAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DragonflySwarm extends CardImpl { + + private static final FilterCard filter = new FilterCard("noncreature, nonland cards"); + + static { + filter.add(Predicates.not(CardType.CREATURE.getPredicate())); + filter.add(Predicates.not(CardType.LAND.getPredicate())); + } + + private static final DynamicValue xValue = new CardsInControllerGraveyardCount(filter); + private static final Condition condition = new CompoundCondition( + "there's a Lesson card in your graveyard", + new CardsInControllerGraveyardCondition(1, new FilterCard(SubType.LESSON)) + ); + private static final Hint hint = new ConditionHint(condition); + + public DragonflySwarm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}"); + + this.subtype.add(SubType.DRAGON); + this.subtype.add(SubType.INSECT); + this.power = new MageInt(0); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Ward {1} + this.addAbility(new WardAbility(new ManaCostsImpl<>("{1}"))); + + // This creature's power is equal to the number of noncreature, nonland cards in your graveyard. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerSourceEffect(xValue))); + + // When this creature dies, if there's a Lesson card in your graveyard, draw a card. + this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(condition).addHint(hint)); + } + + private DragonflySwarm(final DragonflySwarm card) { + super(card); + } + + @Override + public DragonflySwarm copy() { + return new DragonflySwarm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 69f4e22c2da..413663a6871 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -57,6 +57,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Cycle of Renewal", 170, Rarity.COMMON, mage.cards.c.CycleOfRenewal.class)); cards.add(new SetCardInfo("Dai Li Indoctrination", 93, Rarity.COMMON, mage.cards.d.DaiLiIndoctrination.class)); cards.add(new SetCardInfo("Deserter's Disciple", 131, Rarity.COMMON, mage.cards.d.DesertersDisciple.class)); + cards.add(new SetCardInfo("Dragonfly Swarm", 215, Rarity.UNCOMMON, mage.cards.d.DragonflySwarm.class)); cards.add(new SetCardInfo("Earth Kingdom Soldier", 216, Rarity.COMMON, mage.cards.e.EarthKingdomSoldier.class)); cards.add(new SetCardInfo("Earth Rumble", 174, Rarity.UNCOMMON, mage.cards.e.EarthRumble.class)); cards.add(new SetCardInfo("Earth Village Ruffians", 219, Rarity.COMMON, mage.cards.e.EarthVillageRuffians.class)); -- 2.47.2 From 5c1c402fbfd020876e4b5d6453a565665e3a3b86 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 16:23:43 -0400 Subject: [PATCH 025/261] [TLA] Implement Fire Lord Azula --- Mage.Sets/src/mage/cards/f/FireLordAzula.java | 49 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 3 ++ 2 files changed, 52 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FireLordAzula.java diff --git a/Mage.Sets/src/mage/cards/f/FireLordAzula.java b/Mage.Sets/src/mage/cards/f/FireLordAzula.java new file mode 100644 index 00000000000..4505fa07faa --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FireLordAzula.java @@ -0,0 +1,49 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.CopyStackObjectEffect; +import mage.abilities.keyword.FirebendingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SetTargetPointer; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FireLordAzula extends CardImpl { + + public FireLordAzula(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Firebending 2 + this.addAbility(new FirebendingAbility(2)); + + // Whenever you cast a spell while Fire Lord Azula is attacking, copy that spell. You may choose new targets for the copy. + this.addAbility(new SpellCastControllerTriggeredAbility( + new CopyStackObjectEffect("that spell"), + StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL + )); + } + + private FireLordAzula(final FireLordAzula card) { + super(card); + } + + @Override + public FireLordAzula copy() { + return new FireLordAzula(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 413663a6871..11a5dac2254 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -67,6 +67,9 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Fated Firepower", 132, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fated Firepower", 297, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fated Firepower", 341, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fire Lord Azula", 220, Rarity.RARE, mage.cards.f.FireLordAzula.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fire Lord Azula", 313, Rarity.RARE, mage.cards.f.FireLordAzula.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fire Lord Azula", 334, Rarity.RARE, mage.cards.f.FireLordAzula.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Lord Sozin", 117, Rarity.MYTHIC, mage.cards.f.FireLordSozin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Lord Sozin", 356, Rarity.MYTHIC, mage.cards.f.FireLordSozin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Lord Zuko", 221, Rarity.RARE, mage.cards.f.FireLordZuko.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 4b5b2e191e5021701ed0149c2cb2f1281475e080 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 16:25:24 -0400 Subject: [PATCH 026/261] [TLA] Implement Glider Staff --- Mage.Sets/src/mage/cards/g/GliderStaff.java | 54 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 55 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/g/GliderStaff.java diff --git a/Mage.Sets/src/mage/cards/g/GliderStaff.java b/Mage.Sets/src/mage/cards/g/GliderStaff.java new file mode 100644 index 00000000000..f3a47ca0d51 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GliderStaff.java @@ -0,0 +1,54 @@ +package mage.cards.g; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.effects.keyword.AirbendTargetEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GliderStaff extends CardImpl { + + public GliderStaff(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{W}"); + + this.subtype.add(SubType.EQUIPMENT); + + // When this Equipment enters, airbend up to one target creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new AirbendTargetEffect()); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + this.addAbility(ability); + + // Equipped creature gets +1/+1 and has flying. + ability = new SimpleStaticAbility(new BoostEquippedEffect(1, 1)); + ability.addEffect(new GainAbilityAttachedEffect( + FlyingAbility.getInstance(), AttachmentType.EQUIPMENT + ).setText("and has flying")); + this.addAbility(ability); + + // Equip {2} + this.addAbility(new EquipAbility(2)); + } + + private GliderStaff(final GliderStaff card) { + super(card); + } + + @Override + public GliderStaff copy() { + return new GliderStaff(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 11a5dac2254..971bca83f36 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -92,6 +92,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Geyser Leaper", 52, Rarity.COMMON, mage.cards.g.GeyserLeaper.class)); cards.add(new SetCardInfo("Giant Koi", 53, Rarity.COMMON, mage.cards.g.GiantKoi.class)); cards.add(new SetCardInfo("Glider Kids", 21, Rarity.COMMON, mage.cards.g.GliderKids.class)); + cards.add(new SetCardInfo("Glider Staff", 22, Rarity.UNCOMMON, mage.cards.g.GliderStaff.class)); cards.add(new SetCardInfo("Gran-Gran", 54, Rarity.UNCOMMON, mage.cards.g.GranGran.class)); cards.add(new SetCardInfo("Hakoda, Selfless Commander", 366, Rarity.RARE, mage.cards.h.HakodaSelflessCommander.class)); cards.add(new SetCardInfo("Haru, Hidden Talent", 182, Rarity.UNCOMMON, mage.cards.h.HaruHiddenTalent.class)); -- 2.47.2 From 0e21b91fd3455d408585bb11b073faf9eb11db13 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 16:27:21 -0400 Subject: [PATCH 027/261] [TLA] Implement Seismic Sense --- Mage.Sets/src/mage/cards/s/SeismicSense.java | 42 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 43 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SeismicSense.java diff --git a/Mage.Sets/src/mage/cards/s/SeismicSense.java b/Mage.Sets/src/mage/cards/s/SeismicSense.java new file mode 100644 index 00000000000..2c27cb23a7b --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SeismicSense.java @@ -0,0 +1,42 @@ +package mage.cards.s; + +import mage.abilities.dynamicvalue.common.LandsYouControlCount; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.hint.common.LandsYouControlHint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.PutCards; +import mage.constants.SubType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SeismicSense extends CardImpl { + + public SeismicSense(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}"); + + this.subtype.add(SubType.LESSON); + + // Look at the top X cards of your library, where X is the number of lands you control. You may reveal a creature or land card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. + this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect( + LandsYouControlCount.instance, 1, + StaticFilters.FILTER_CARD_CREATURE_OR_LAND, + PutCards.HAND, PutCards.BOTTOM_RANDOM + )); + this.getSpellAbility().addHint(LandsYouControlHint.instance); + } + + private SeismicSense(final SeismicSense card) { + super(card); + } + + @Override + public SeismicSense copy() { + return new SeismicSense(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 971bca83f36..45c66b6bd26 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -150,6 +150,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Rough Rhino Cavalry", 152, Rarity.COMMON, mage.cards.r.RoughRhinoCavalry.class)); cards.add(new SetCardInfo("Rowdy Snowballers", 68, Rarity.COMMON, mage.cards.r.RowdySnowballers.class)); cards.add(new SetCardInfo("Saber-Tooth Moose-Lion", 194, Rarity.COMMON, mage.cards.s.SaberToothMooseLion.class)); + cards.add(new SetCardInfo("Seismic Sense", 195, Rarity.UNCOMMON, mage.cards.s.SeismicSense.class)); cards.add(new SetCardInfo("Serpent of the Pass", 70, Rarity.UNCOMMON, mage.cards.s.SerpentOfThePass.class)); cards.add(new SetCardInfo("Sokka's Haiku", 71, Rarity.UNCOMMON, mage.cards.s.SokkasHaiku.class)); cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 240, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 15514929397ad26545fd6d8de3429e3ee395476b Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 16:29:09 -0400 Subject: [PATCH 028/261] [TLA] Implement Tundra Tank --- Mage.Sets/src/mage/cards/t/TundraTank.java | 50 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 51 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TundraTank.java diff --git a/Mage.Sets/src/mage/cards/t/TundraTank.java b/Mage.Sets/src/mage/cards/t/TundraTank.java new file mode 100644 index 00000000000..4a354319b82 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TundraTank.java @@ -0,0 +1,50 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.CrewAbility; +import mage.abilities.keyword.FirebendingAbility; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TundraTank extends CardImpl { + + public TundraTank(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{B}"); + + this.subtype.add(SubType.VEHICLE); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Firebending 1 + this.addAbility(new FirebendingAbility(1)); + + // When this Vehicle enters, target creature you control gains indestructible until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility(new GainAbilityTargetEffect(IndestructibleAbility.getInstance())); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + + // Crew 1 + this.addAbility(new CrewAbility(1)); + } + + private TundraTank(final TundraTank card) { + super(card); + } + + @Override + public TundraTank copy() { + return new TundraTank(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 45c66b6bd26..549e4b0aaca 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -178,6 +178,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Toph, the First Metalbender", 353, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Toph, the First Metalbender", 362, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("True Ancestry", 199, Rarity.UNCOMMON, mage.cards.t.TrueAncestry.class)); + cards.add(new SetCardInfo("Tundra Tank", 121, Rarity.UNCOMMON, mage.cards.t.TundraTank.class)); cards.add(new SetCardInfo("Turtle-Duck", 200, Rarity.COMMON, mage.cards.t.TurtleDuck.class)); cards.add(new SetCardInfo("Ty Lee, Artful Acrobat", 158, Rarity.UNCOMMON, mage.cards.t.TyLeeArtfulAcrobat.class)); cards.add(new SetCardInfo("Uncle Iroh", 248, Rarity.UNCOMMON, mage.cards.u.UncleIroh.class)); -- 2.47.2 From 9f214bf0a3b9ca615eb028d57589c510955af1b3 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 16:35:09 -0400 Subject: [PATCH 029/261] [TLA] Implement Crescent Island Temple --- .../mage/cards/c/CrescentIslandTemple.java | 58 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 59 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CrescentIslandTemple.java diff --git a/Mage.Sets/src/mage/cards/c/CrescentIslandTemple.java b/Mage.Sets/src/mage/cards/c/CrescentIslandTemple.java new file mode 100644 index 00000000000..8349eeea9fa --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CrescentIslandTemple.java @@ -0,0 +1,58 @@ +package mage.cards.c; + +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +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.FilterControlledPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.game.permanent.token.MonkRedToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CrescentIslandTemple extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SHRINE); + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter); + private static final Hint hint = new ValueHint("Shrines you control", xValue); + private static final FilterPermanent filter2 = new FilterControlledPermanent(SubType.SHRINE, "another Shrine you control"); + + static { + filter.add(AnotherPredicate.instance); + } + + public CrescentIslandTemple(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.SHRINE); + + // When Crescent Island Temple enters, for each Shrine you control, create a 1/1 red Monk creature token with prowess. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new MonkRedToken(), xValue) + .setText("for each Shrine you control, create a 1/1 red Monk creature token with prowess")).addHint(hint)); + + // Whenever another Shrine you control enters, create a 1/1 red Monk creature token with prowess. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new CreateTokenEffect(new MonkRedToken()), filter2)); + } + + private CrescentIslandTemple(final CrescentIslandTemple card) { + super(card); + } + + @Override + public CrescentIslandTemple copy() { + return new CrescentIslandTemple(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 549e4b0aaca..a9e2bd10b7d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -53,6 +53,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Cat-Owl", 212, Rarity.COMMON, mage.cards.c.CatOwl.class)); cards.add(new SetCardInfo("Compassionate Healer", 13, Rarity.COMMON, mage.cards.c.CompassionateHealer.class)); cards.add(new SetCardInfo("Corrupt Court Official", 92, Rarity.COMMON, mage.cards.c.CorruptCourtOfficial.class)); + cards.add(new SetCardInfo("Crescent Island Temple", 129, Rarity.UNCOMMON, mage.cards.c.CrescentIslandTemple.class)); cards.add(new SetCardInfo("Cunning Maneuver", 130, Rarity.COMMON, mage.cards.c.CunningManeuver.class)); cards.add(new SetCardInfo("Cycle of Renewal", 170, Rarity.COMMON, mage.cards.c.CycleOfRenewal.class)); cards.add(new SetCardInfo("Dai Li Indoctrination", 93, Rarity.COMMON, mage.cards.d.DaiLiIndoctrination.class)); -- 2.47.2 From 8425601562738361d7be727333c2c7f954465ffd Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Oct 2025 16:46:44 -0400 Subject: [PATCH 030/261] [TLA] Implement Diligent Zookeeper --- .../src/mage/cards/d/DiligentZookeeper.java | 91 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 93 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/d/DiligentZookeeper.java diff --git a/Mage.Sets/src/mage/cards/d/DiligentZookeeper.java b/Mage.Sets/src/mage/cards/d/DiligentZookeeper.java new file mode 100644 index 00000000000..22ebabc3773 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DiligentZookeeper.java @@ -0,0 +1,91 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DiligentZookeeper extends CardImpl { + + public DiligentZookeeper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CITIZEN); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Each non-Human creature you control gets +1/+1 for each of its creature types, to a maximum of 10. + this.addAbility(new SimpleStaticAbility(new DiligentZookeeperEffect())); + } + + private DiligentZookeeper(final DiligentZookeeper card) { + super(card); + } + + @Override + public DiligentZookeeper copy() { + return new DiligentZookeeper(this); + } +} + +class DiligentZookeeperEffect extends ContinuousEffectImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + + static { + filter.add(Predicates.not(SubType.HUMAN.getPredicate())); + } + + DiligentZookeeperEffect() { + super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); + staticText = "each non-Human creature you control gets +1/+1 for each of its creature types, to a maximum of 10"; + } + + private DiligentZookeeperEffect(final DiligentZookeeperEffect effect) { + super(effect); + } + + @Override + public DiligentZookeeperEffect copy() { + return new DiligentZookeeperEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + if (permanent.isAllCreatureTypes(game)) { + permanent.addPower(10); + permanent.addToughness(10); + continue; + } + int types = Math.min( + 10, permanent + .getSubtype(game) + .stream() + .map(SubType::getSubTypeSet) + .filter(SubTypeSet.CreatureType::equals) + .mapToInt(x -> 1) + .sum() + ); + permanent.addPower(types); + permanent.addToughness(types); + continue; + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index a9e2bd10b7d..4c4e645eca0 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -58,6 +58,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Cycle of Renewal", 170, Rarity.COMMON, mage.cards.c.CycleOfRenewal.class)); cards.add(new SetCardInfo("Dai Li Indoctrination", 93, Rarity.COMMON, mage.cards.d.DaiLiIndoctrination.class)); cards.add(new SetCardInfo("Deserter's Disciple", 131, Rarity.COMMON, mage.cards.d.DesertersDisciple.class)); + cards.add(new SetCardInfo("Diligent Zookeeper", 171, Rarity.RARE, mage.cards.d.DiligentZookeeper.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Diligent Zookeeper", 327, Rarity.RARE, mage.cards.d.DiligentZookeeper.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dragonfly Swarm", 215, Rarity.UNCOMMON, mage.cards.d.DragonflySwarm.class)); cards.add(new SetCardInfo("Earth Kingdom Soldier", 216, Rarity.COMMON, mage.cards.e.EarthKingdomSoldier.class)); cards.add(new SetCardInfo("Earth Rumble", 174, Rarity.UNCOMMON, mage.cards.e.EarthRumble.class)); -- 2.47.2 From 531f2e3c38bdab365d842f7ec4c38f8ce28dad99 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 08:44:11 -0400 Subject: [PATCH 031/261] [TLA] update spoiler --- Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java | 2 +- Utils/mtg-cards-data.txt | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 4c4e645eca0..3016f03c94b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -12,7 +12,7 @@ import java.util.List; */ public final class AvatarTheLastAirbender extends ExpansionSet { - private static final List unfinished = Arrays.asList("Aang's Iceberg", "Avatar Aang", "Flexible Waterbender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "The Legend of Kuruk", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); + private static final List unfinished = Arrays.asList("Aang's Iceberg", "Avatar Aang", "Flexible Waterbender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Invasion Submersible", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "The Legend of Kuruk", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); private static final AvatarTheLastAirbender instance = new AvatarTheLastAirbender(); public static AvatarTheLastAirbender getInstance() { diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 9bea6e17ce7..b519b070586 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59791,6 +59791,7 @@ Giant Koi|Avatar: The Last Airbender|53|C|{4}{U}{U}|Creature - Fish|5|7|Waterben Gran-Gran|Avatar: The Last Airbender|54|U|{U}|Legendary Creature - Human Peasant Ally|1|2|Whenever Gran-Gran becomes tapped, draw a card, then discard a card.$Noncreature spells you cast cost {1} less to cast as long as there are three or more Lesson cards in your graveyard.| Honest Work|Avatar: The Last Airbender|55|U|{U}|Enchantment - Aura|||Enchant creature an opponent controls$When this Aura enters, tap enchanted creature and remove all counters from it.$Enchanted creature loses all abilities and is a Citizen with base power and toughness 1/1 and "{T}: Add {C}" named Humble Merchant.| Iguana Parrot|Avatar: The Last Airbender|56|C|{2}{U}|Creature - Lizard Bird Pirate|2|2|Flying, vigilance$Prowess| +Invasion Submersible|Avatar: The Last Airbender|57|U|{2}{U}|Artifact - Vehicle|0|0|When this Vehicle enters, return up to one other target nonland permanent to its owner's hand.$Exhaust -- Waterbend {3}: This Vehicle becomes an artifact creature. Put three +1/+1 counters on it.| It'll Quench Ya!|Avatar: The Last Airbender|58|C|{1}{U}|Instant - Lesson|||Counter target spell unless its controller pays {2}.| Katara, Bending Prodigy|Avatar: The Last Airbender|59|U|{2}{U}|Legendary Creature - Human Warrior Ally|2|3|At the beginning of your end step, if Katara is tapped, put a +1/+1 counter on her.$Waterbend {6}: Draw a card.| The Legend of Kuruk|Avatar: The Last Airbender|61|M|{2}{U}{U}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I, II -- Scry 2, then draw a card.$III -- Exile this Saga, then return it to the battlefield$transformed under your control.| @@ -59799,6 +59800,7 @@ Lost Days|Avatar: The Last Airbender|62|C|{4}{U}|Instant - Lesson|||The owner of Master Pakku|Avatar: The Last Airbender|63|U|{1}{U}|Legendary Creature - Human Advisor Ally|1|3|Prowess$Whenever Master Pakku becomes tapped, target player mills X cards, where X is the number of Lesson cards in your graveyard.| The Mechanist, Aerial Artisan|Avatar: The Last Airbender|64|R|{2}{U}|Legendary Creature - Human Artificer Ally|1|3|Whenever you cast a noncreature spell, create a Clue token.${T}: Until end of turn, target artifact token you control becomes a 3/1 Construct artifact creature with flying.| North Pole Patrol|Avatar: The Last Airbender|65|U|{2}{U}|Creature - Human Soldier Ally|2|3|{T}: Untap another target permanent you control.$Waterbend {3}, {T}: Tap target creature an opponent controls.| +Octopus Form|Avatar: The Last Airbender|66|C|{U}|Instant - Lesson|||Target creature you control gets +1/+1 and gains hexproof until end of turn. Untap it.| Otter-Penguin|Avatar: The Last Airbender|67|C|{1}{U}|Creature - Otter Bird|2|1|Whenever you draw your second card each turn, this creature gets +1/+2 until end of turn and can't be blocked this turn.| Rowdy Snowballers|Avatar: The Last Airbender|68|C|{2}{U}|Creature - Human Peasant Ally|2|2|When this creature enters, tap target creature an opponent controls and put a stun counter on it.| Secret of Bloodbending|Avatar: The Last Airbender|69|M|{U}{U}{U}{U}|Sorcery - Lesson|||As an additional cost to cast this spell, you may waterbend {10}.$You control target opponent during their next combat phase. If this spell's additional cost was paid, you control that player during their next turn instead.$Exile Secret of Bloodbending.| @@ -59820,6 +59822,7 @@ Cat-Gator|Avatar: The Last Airbender|91|U|{6}{B}|Creature - Fish Crocodile|3|2|L Corrupt Court Official|Avatar: The Last Airbender|92|C|{1}{B}|Creature - Human Advisor|1|1|When this creature enters, target opponent discards a card.| Dai Li Indoctrination|Avatar: The Last Airbender|93|C|{1}{B}|Sorcery - Lesson|||Choose one --$* Target opponent reveals their hand. You choose a nonland permanent card from it. That player discards that card.$* Earthbend 2.| Day of Black Sun|Avatar: The Last Airbender|94|R|{X}{B}{B}|Sorcery|||Each creature with mana value X or less loses all abilities until end of turn. Destroy those creatures.| +Deadly Precision|Avatar: The Last Airbender|95|C|{B}|Sorcery|||As an additional cost to cast this spell, pay {4} or sacrifice an artifact or creature.$Destroy target creature.| Epic Downfall|Avatar: The Last Airbender|96|U|{1}{B}|Sorcery|||Exile target creature with mana value 3 or greater.| The Fire Nation Drill|Avatar: The Last Airbender|98|R|{2}{B}{B}|Legendary Artifact - Vehicle|6|3|Trample$When The Fire Nation Drill enters, you may tap it. When you do, destroy target creature with power 4 or less.${1}: Permanents your opponents control lose hexproof and indestructible until end of turn.$Crew 2| Fire Nation Engineer|Avatar: The Last Airbender|99|U|{2}{B}|Creature - Human Artificer|2|3|Raid -- At the beginning of your end step, if you attacked this turn, put a +1/+1 counter on another target creature or Vehicle you control.| @@ -59832,12 +59835,14 @@ Ozai's Cruelty|Avatar: The Last Airbender|113|U|{2}{B}|Sorcery - Lesson|||Ozai's The Rise of Sozin|Avatar: The Last Airbender|117|M|{4}{B}{B}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I -- Destroy all creatures.$II -- Choose a card name. Search target opponent's graveyard, hand, and library for up to four cards with that name and exile them. Then that player shuffles.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| Fire Lord Sozin|Avatar: The Last Airbender|117|M||Legendary Creature - Human Noble|5|5|Menace, firebending 3$Whenever Fire Lord Sozin deals combat damage to a player, you may pay {X}. When you do, put any number of target creature cards with total mana value X or less from that player's graveyard onto the battlefield under your control.| Tundra Tank|Avatar: The Last Airbender|121|U|{2}{B}|Artifact - Vehicle|4|4|Firebending 1$When this Vehicle enters, target creature you control gains indestructible until end of turn.$Crew 1| +Bumi Bash|Avatar: The Last Airbender|125|C|{3}{R}|Sorcery|||Choose one --$* Bumi Bash deals damage equal to the number of lands you control to target creature.$* Destroy target land creature or nonbasic land.| The Cave of Two Lovers|Avatar: The Last Airbender|126|U|{3}{R}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I -- Create two 1/1 white Ally creature tokens.$II -- Search your library for a Mountain or Cave card, reveal it, put it into your hand,$then shuffle.$III -- Earthbend 3.| Crescent Island Temple|Avatar: The Last Airbender|129|U|{3}{R}|Legendary Enchantment - Shrine|||When Crescent Island Temple enters, for each Shrine you control, create a 1/1 red Monk creature token with prowess.$Whenever another Shrine you control enters, create a 1/1 red Monk creature token with prowess.| Cunning Maneuver|Avatar: The Last Airbender|130|C|{1}{R}|Instant|||Target creature gets +3/+1 until end of turn.$Create a Clue token.| Deserter's Disciple|Avatar: The Last Airbender|131|C|{1}{R}|Creature - Human Rebel Ally|2|2|{T}: Another target creature you control with power 2 or less can't be blocked this turn.| Fated Firepower|Avatar: The Last Airbender|132|M|{X}{R}{R}{R}|Enchantment|||Flash$This enchantment enters with X fire counters on it.$If a source you control would deal damage to an opponent or a permanent an opponent controls, it deals that much damage plus an amount of damage equal to the number of fire counters on this enchantment instead.| Fire Nation Attacks|Avatar: The Last Airbender|133|U|{4}{R}|Instant|||Create two 2/2 red Soldier creature tokens with firebending 1.$Flashback {8}{R}| +Fire Nation Cadets|Avatar: The Last Airbender|134|C|{R}|Creature - Human Soldier|1|2|This creature has firebending 2 as long as there's a Lesson card in your graveyard.${2}: This creature gets +1/+0 until end of turn.| Fire Sages|Avatar: The Last Airbender|136|U|{1}{R}|Creature - Human Cleric|2|2|Firebending 1${1}{R}{R}: Put a +1/+1 counter on this creature.| Firebending Student|Avatar: The Last Airbender|139|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| How to Start a Riot|Avatar: The Last Airbender|140|C|{2}{R}|Instant - Lesson|||Target creature gains menace until end of turn.$Creatures target player controls get +2/+0 until end of turn.| @@ -59866,6 +59871,7 @@ Flopsie, Bumi's Buddy|Avatar: The Last Airbender|179|U|{4}{G}{G}|Legendary Creat Haru, Hidden Talent|Avatar: The Last Airbender|182|U|{1}{G}|Legendary Creature - Human Peasant Ally|1|1|Whenever another Ally you control enters, earthbend 1.| Invasion Tactics|Avatar: The Last Airbender|183|U|{4}{G}|Enchantment|||When this enchantment enters, creatures you control get +2/+2 until end of turn.$Whenever one or more Allies you control deal combat damage to a player, draw a card.| Leaves from the Vine|Avatar: The Last Airbender|185|U|{1}{G}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I -- Mill three cards, then create a Food token.$II -- Put a +1/+1 counter on each of up to two target creatures you control.$III -- Draw a card if there's a creature or Lesson card in your graveyard.| +Origin of Metalbending|Avatar: The Last Airbender|187|C|{1}{G}|Instant - Lesson|||Choose one --$* Destroy target artifact or enchantment.$* Put a +1/+1 counter on target creature you control. It gains indestructible until end of turn.| Ostrich-Horse|Avatar: The Last Airbender|188|C|{2}{G}|Creature - Bird Horse|3|1|When this creature enters, mill three cards. You may put a land card from among them into your hand. If you don't, put a +1/+1 counter on this creature.| Pillar Launch|Avatar: The Last Airbender|189|C|{G}|Instant|||Target creature gets +2/+2 and gains reach until end of turn. Untap it.| Raucous Audience|Avatar: The Last Airbender|190|C|{1}{G}|Creature - Human Citizen|2|1|{T}: Add {G}. If you control a creature with power 4 or greater, add {G}{G} instead.| @@ -59890,6 +59896,7 @@ Dai Li Agents|Avatar: The Last Airbender|214|U|{3}{B}{G}|Creature - Human Soldie Dragonfly Swarm|Avatar: The Last Airbender|215|U|{1}{U}{R}|Creature - Dragon Insect|*|3|Flying, ward {1}$This creature's power is equal to the number of noncreature, nonland cards in your graveyard.$When this creature dies, if there's a Lesson card in your graveyard, draw a card.| Earth Kingdom Soldier|Avatar: The Last Airbender|216|C|{4}{G/W}|Creature - Human Soldier|3|4|Vigilance$When this creature enters, put a +1/+1 counter on each of up to two target creatures you control.| Earth King's Lieutenant|Avatar: The Last Airbender|217|R|{G}{W}|Creature - Human Soldier Ally|1|1|Trample$When this creature enters, put a +1/+1 counter on each other Ally creature you control.$Whenever another Ally you control enters, put a +1/+1 counter on this creature.| +Earth Rumble Wrestlers|Avatar: The Last Airbender|218|C|{3}{R/G}|Creature - Human Warrior Performer|3|4|Reach$This creature gets +1/+0 and has trample as long as you control a land creature or a land entered the battlefield under your control this under your control turn.| Earth Village Ruffians|Avatar: The Last Airbender|219|C|{2}{B/G}|Creature - Human Soldier Rogue|3|1|When this creature dies, earthbend 2.| Fire Lord Azula|Avatar: The Last Airbender|220|R|{1}{U}{B}{R}|Legendary Creature - Human Noble|4|4|Firebending 2$Whenever you cast a spell while Fire Lord Azula is attacking, copy that spell. You may choose new targets for the copy.| Fire Lord Zuko|Avatar: The Last Airbender|221|R|{R}{W}{B}|Legendary Creature - Human Noble Ally|2|4|Firebending X, where X is Fire Lord Zuko's power.$Whenever you cast a spell from exile and whenever a permanent you control enters from exile, put a +1/+1 counter on each creature you control.| @@ -59912,8 +59919,10 @@ Toph, the First Metalbender|Avatar: The Last Airbender|247|R|{1}{R}{G}{W}|Legend Uncle Iroh|Avatar: The Last Airbender|248|U|{1}{R/G}{R/G}|Legendary Creature - Human Noble Ally|4|2|Firebending 1$Lesson spells you cast cost {1} less to cast.| Vindictive Warden|Avatar: The Last Airbender|249|C|{2}{B/R}|Creature - Human Soldier|2|3|Menace$Firebending 1${3}: This creature deals 1 damage to each opponent.| White Lotus Reinforcements|Avatar: The Last Airbender|251|U|{1}{G}{W}|Creature - Human Soldier Ally|2|3|Vigilance$Other Allies you control get +1/+1.| +Zuko, Conflicted|Avatar: The Last Airbender|253|R|{B}{R}|Legendary Creature - Human Rogue|2|3|At the beginning of your first main phase, choose one that hasn't been chosen and you lose 2 life --$* Draw a card.$* Put a +1/+1 counter on Zuko.$* Add {R}.$* Exile Zuko, then return him to the battlefield under an opponent's control.| Barrels of Blasting Jelly|Avatar: The Last Airbender|254|C|{1}|Artifact|||{1}: Add one mana of any color. Activate only once each turn.${5}, {T}, Sacrifice this artifact: It deals 5 damage to target creature.| Bender's Waterskin|Avatar: The Last Airbender|255|C|{3}|Artifact|||Untap this artifact during each other player's untap step.${T}: Add one mana of any color.| +Fire Nation Warship|Avatar: The Last Airbender|256|U|{3}|Artifact - Vehicle|4|4|Reach$When this Vehicle dies, create a Clue token.$Crew 2| Planetarium of Wan Shi Tong|Avatar: The Last Airbender|259|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| Trusty Boomerang|Avatar: The Last Airbender|260|U|{1}|Artifact - Equipment|||Equipped creature has "{1}, {T}: Tap target creature. Return Trusty Boomerang to its owner's hand."$Equip {1}| White Lotus Tile|Avatar: The Last Airbender|262|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| -- 2.47.2 From a19dbf129b82541593f6caf52bdf0d4af0e1f03d Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 08:44:29 -0400 Subject: [PATCH 032/261] [TLE] update spoiler and reprints --- .../src/mage/sets/AvatarTheLastAirbenderEternal.java | 5 +++++ Utils/mtg-cards-data.txt | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 890d7f05de1..0c18fe3ff8b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -40,6 +40,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Arcane Signet", 315, Rarity.RARE, mage.cards.a.ArcaneSignet.class)); cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 130, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class)); cards.add(new SetCardInfo("Bribery", 10, Rarity.MYTHIC, mage.cards.b.Bribery.class)); + cards.add(new SetCardInfo("Brought Back", 1, Rarity.MYTHIC, mage.cards.b.BroughtBack.class)); cards.add(new SetCardInfo("Bumi, Eclectic Earthbender", 248, Rarity.RARE, mage.cards.b.BumiEclecticEarthbender.class)); cards.add(new SetCardInfo("Capital Guard", 234, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Capital Guard", 277, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); @@ -84,6 +85,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Loyal Fire Sage", 242, Rarity.UNCOMMON, mage.cards.l.LoyalFireSage.class)); cards.add(new SetCardInfo("Match the Odds", 253, Rarity.UNCOMMON, mage.cards.m.MatchTheOdds.class)); cards.add(new SetCardInfo("Mechanical Glider", 256, Rarity.COMMON, mage.cards.m.MechanicalGlider.class)); + cards.add(new SetCardInfo("Mirrorwing Dragon", 33, Rarity.MYTHIC, mage.cards.m.MirrorwingDragon.class)); cards.add(new SetCardInfo("Momo, Rambunctious Rascal", 217, Rarity.UNCOMMON, mage.cards.m.MomoRambunctiousRascal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Momo, Rambunctious Rascal", 270, Rarity.UNCOMMON, mage.cards.m.MomoRambunctiousRascal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 289, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); @@ -104,9 +106,12 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Plains", 302, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 303, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 304, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Prosperity", 17, Rarity.MYTHIC, mage.cards.p.Prosperity.class)); cards.add(new SetCardInfo("Purple Pentapus", 233, Rarity.COMMON, mage.cards.p.PurplePentapus.class)); cards.add(new SetCardInfo("Razor Rings", 272, Rarity.COMMON, mage.cards.r.RazorRings.class)); cards.add(new SetCardInfo("Release to Memory", 5, Rarity.MYTHIC, mage.cards.r.ReleaseToMemory.class)); + cards.add(new SetCardInfo("Rhys the Redeemed", 52, Rarity.MYTHIC, mage.cards.r.RhysTheRedeemed.class)); + cards.add(new SetCardInfo("Rites of Flourishing", 45, Rarity.MYTHIC, mage.cards.r.RitesOfFlourishing.class)); cards.add(new SetCardInfo("Roku's Mastery", 243, Rarity.UNCOMMON, mage.cards.r.RokusMastery.class)); cards.add(new SetCardInfo("Run Amok", 258, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Run Amok", 284, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index b519b070586..035c69f7556 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -60308,20 +60308,26 @@ Urban Retreat|Marvel's Spider-Man|283|R||Land|||This land enters tapped.${T}: Ad Spider-Sense|Marvel's Spider-Man|284|R|{1}{U}|Instant|||Web-slinging {U}$Counter target instant spell, sorcery spell, or triggered ability.| Radioactive Spider|Marvel's Spider-Man|285|R|{G}|Creature - Spider|1|1|Reach, deathtouch$Fateful Bite -- {2}, Sacrifice this creature: Search your library for a Spider Hero card, reveal it, put it into your hand, then shuffle. Activate only as a sorcery.| Gwenom, Remorseless|Marvel's Spider-Man|286|M|{3}{B}{B}|Legendary Creature - Symbiote Spider Hero|4|4|Deathtouch, lifelink$Whenever Gwenom attacks, until end of turn you may look at the top card of your library any time and you may play cards from the top of your library. If you cast a spell this way, pay life equal to its mana value rather than pay its mana cost.| +Brought Back|Avatar: The Last Airbender Eternal|1|M|{W}{W}|Instant|||Choose up to two target permanent cards in your graveyard that were put there from the battlefield this turn. Return them to the battlefield tapped.| Release to Memory|Avatar: The Last Airbender Eternal|5|M|{3}{W}|Instant|||Exile target opponent's graveyard. For each creature card exiled this way, create a 1/1 colorless Spirit creature token.| Agent of Treachery|Avatar: The Last Airbender Eternal|9|M|{5}{U}{U}|Creature - Human Rogue|2|3|When this creature enters, gain control of target permanent.$At the beginning of your end step, if you control three or more permanents you don't own, draw three cards.| Bribery|Avatar: The Last Airbender Eternal|10|M|{3}{U}{U}|Sorcery|||Search target opponent's library for a creature card and put that card onto the battlefield under your control. Then that player shuffles.| Force of Negation|Avatar: The Last Airbender Eternal|13|M|{1}{U}{U}|Instant|||If it's not your turn, you may exile a blue card from your hand rather than pay this spell's mana cost.$Counter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.| Mystic Remora|Avatar: The Last Airbender Eternal|16|M|{U}|Enchantment|||Cumulative upkeep {1}$Whenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}.| +Prosperity|Avatar: The Last Airbender Eternal|17|M|{X}{U}|Sorcery|||Each player draws X cards.| Cruel Tutor|Avatar: The Last Airbender Eternal|24|M|{2}{B}|Sorcery|||Search your library for a card, then shuffle and put that card on top. You lose 2 life.| +Mirrorwing Dragon|Avatar: The Last Airbender Eternal|33|M|{3}{R}{R}|Creature - Dragon|4|5|Flying$Whenever a player casts an instant or sorcery spell that targets only this creature, that player copies that spell for each other creature they control that the spell could target. Each copy targets a different one of those creatures.| The Great Henge|Avatar: The Last Airbender Eternal|41|M|{7}{G}{G}|Legendary Artifact|||This spell costs {X} less to cast, where X is the greatest power among creatures you control.${T}: Add {G}{G}. You gain 2 life.$Whenever a nontoken creature you control enters, put a +1/+1 counter on it and draw a card.| Heroic Intervention|Avatar: The Last Airbender Eternal|43|M|{1}{G}|Instant|||Permanents you control gain hexproof and indestructible until end of turn.| +Rites of Flourishing|Avatar: The Last Airbender Eternal|45|M|{2}{G}|Enchantment|||At the beginning of each player's draw step, that player draws an additional card.$Each player may play an additional land on each of their turns.| Eladamri's Call|Avatar: The Last Airbender Eternal|48|M|{G}{W}|Instant|||Search your library for a creature card, reveal that card, put it into your hand, then shuffle.| +Rhys the Redeemed|Avatar: The Last Airbender Eternal|52|M|{G/W}|Legendary Creature - Elf Warrior|1|1|{2}{G/W}, {T}: Create a 1/1 green and white Elf Warrior creature token.${4}{G/W}{G/W}, {T}: For each creature token you control, create a token that's a copy of that creature.| Dark Depths|Avatar: The Last Airbender Eternal|56|M||Legendary Snow Land|||Dark Depths enters with ten ice counters on it.${3}: Remove an ice counter from Dark Depths.$When Dark Depths has no ice counters on it, sacrifice it. If you do, create Marit Lage, a legendary 20/20 black Avatar creature token with flying and indestructible.| Valakut, the Molten Pinnacle|Avatar: The Last Airbender Eternal|61|M||Land|||This land enters tapped.$Whenever a Mountain you control enters, if you control at least five other Mountains, you may have this land deal 3 damage to any target.${T}: Add {R}.| Katara's Reversal|Avatar: The Last Airbender Eternal|63|R|{2}{U}{U}|Instant|||Counter up to four target spells and/or abilities.$Untap up to four target artifacts and/or creatures.| +Mai and Zuko|Avatar: The Last Airbender Eternal|68|R|{1}{U}{B}{R}|Legendary Creature - Human Noble Ally|3|5|Firebending 3$You may cast Ally spells and artifact spells as though they had flash.| Aang and Katara|Avatar: The Last Airbender Eternal|69|R|{3}{G}{W}{U}|Legendary Creature - Human Avatar Ally|5|5|Whenever Aang and Katara enter or attack, create X 1/1 white Ally creature tokens, where X is the number of tapped artifacts and/or creatures you control.| -Toph, Greatest Earthbender|Avatar: The Last Airbender Eternal|70|R|{2}{R}{G}|Legendary Creature - Human Warrior Ally|3|3|When Toph enters, earthbend X, where X is the amount of mana spent to cast her. Land creatures you control have double strike.| +Toph, Greatest Earthbender|Avatar: The Last Airbender Eternal|70|R|{2}{R}{G}|Legendary Creature - Human Warrior Ally|3|3|When Toph enters, earthbend X, where X is the amount of mana spent to cast her.$Land creatures you control have double strike.| Sokka and Suki|Avatar: The Last Airbender Eternal|71|R|{U}{R}{W}|Legendary Creature - Human Warrior Ally|3|3|Whenever Sokka and Suki or another Ally you control enters, attach up to one target Equipment you control to that creature.$Whenever an Equipment you control enters, create a 1/1 white Ally creature token.| Momo's Heist|Avatar: The Last Airbender Eternal|72|R|{2}{R}|Sorcery|||Gain control of target artifact. Untap it. It gains haste. At the beginning of the next end step, sacrifice it.| Uncle's Musings|Avatar: The Last Airbender Eternal|73|R|{2}{G}{G}|Sorcery|||Converge -- Return up to X permanent cards from your graveyard to your hand, where X is the number of colors of mana spent to cast this spell.$Exile Uncle's Musings.| -- 2.47.2 From 5d051f02ea4ce6bc481ebc063ce114cad9cd8061 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 08:46:03 -0400 Subject: [PATCH 033/261] [TLA] Implement Deadly Precision --- .../src/mage/cards/d/DeadlyPrecision.java | 42 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 43 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/d/DeadlyPrecision.java diff --git a/Mage.Sets/src/mage/cards/d/DeadlyPrecision.java b/Mage.Sets/src/mage/cards/d/DeadlyPrecision.java new file mode 100644 index 00000000000..e3ac37f7dc9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeadlyPrecision.java @@ -0,0 +1,42 @@ +package mage.cards.d; + +import mage.abilities.costs.OrCost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DeadlyPrecision extends CardImpl { + + public DeadlyPrecision(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}"); + + // As an additional cost to cast this spell, pay {4} or sacrifice an artifact or creature. + this.getSpellAbility().addCost(new OrCost( + "pay {4} or sacrifice an artifact or creature", new GenericManaCost(4), + new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE) + )); + + // Destroy target creature. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private DeadlyPrecision(final DeadlyPrecision card) { + super(card); + } + + @Override + public DeadlyPrecision copy() { + return new DeadlyPrecision(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 3016f03c94b..f42d7abc9e5 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -57,6 +57,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Cunning Maneuver", 130, Rarity.COMMON, mage.cards.c.CunningManeuver.class)); cards.add(new SetCardInfo("Cycle of Renewal", 170, Rarity.COMMON, mage.cards.c.CycleOfRenewal.class)); cards.add(new SetCardInfo("Dai Li Indoctrination", 93, Rarity.COMMON, mage.cards.d.DaiLiIndoctrination.class)); + cards.add(new SetCardInfo("Deadly Precision", 95, Rarity.COMMON, mage.cards.d.DeadlyPrecision.class)); cards.add(new SetCardInfo("Deserter's Disciple", 131, Rarity.COMMON, mage.cards.d.DesertersDisciple.class)); cards.add(new SetCardInfo("Diligent Zookeeper", 171, Rarity.RARE, mage.cards.d.DiligentZookeeper.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Diligent Zookeeper", 327, Rarity.RARE, mage.cards.d.DiligentZookeeper.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From c7fb5fd4958a174f31a02960565fe82256eea127 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 08:50:21 -0400 Subject: [PATCH 034/261] [TLA] Implement Octopus Form --- Mage.Sets/src/mage/cards/o/OctopusForm.java | 45 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 46 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/o/OctopusForm.java diff --git a/Mage.Sets/src/mage/cards/o/OctopusForm.java b/Mage.Sets/src/mage/cards/o/OctopusForm.java new file mode 100644 index 00000000000..c54d9353204 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OctopusForm.java @@ -0,0 +1,45 @@ +package mage.cards.o; + +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class OctopusForm extends CardImpl { + + public OctopusForm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); + + this.subtype.add(SubType.LESSON); + + // Target creature you control gets +1/+1 and gains hexproof until end of turn. Untap it. + this.getSpellAbility().addEffect(new BoostTargetEffect( + 1, 1, Duration.EndOfTurn + ).setText("target creature you control gets +1/+1")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + HexproofAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains hexproof until end of turn")); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + this.getSpellAbility().addEffect(new UntapTargetEffect("Untap it")); + } + + private OctopusForm(final OctopusForm card) { + super(card); + } + + @Override + public OctopusForm copy() { + return new OctopusForm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index f42d7abc9e5..c1d9c6e78f5 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -133,6 +133,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 290, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Mountain", 295, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("North Pole Patrol", 65, Rarity.UNCOMMON, mage.cards.n.NorthPolePatrol.class)); + cards.add(new SetCardInfo("Octopus Form", 66, Rarity.COMMON, mage.cards.o.OctopusForm.class)); cards.add(new SetCardInfo("Ostrich-Horse", 188, Rarity.COMMON, mage.cards.o.OstrichHorse.class)); cards.add(new SetCardInfo("Otter-Penguin", 67, Rarity.COMMON, mage.cards.o.OtterPenguin.class)); cards.add(new SetCardInfo("Ozai's Cruelty", 113, Rarity.UNCOMMON, mage.cards.o.OzaisCruelty.class)); -- 2.47.2 From 411eeab86829903e271bf274b7422453057e5841 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 08:53:36 -0400 Subject: [PATCH 035/261] [TLA] Implement Bumi Bash --- Mage.Sets/src/mage/cards/b/BumiBash.java | 56 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 57 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BumiBash.java diff --git a/Mage.Sets/src/mage/cards/b/BumiBash.java b/Mage.Sets/src/mage/cards/b/BumiBash.java new file mode 100644 index 00000000000..345c12521c6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BumiBash.java @@ -0,0 +1,56 @@ +package mage.cards.b; + +import mage.abilities.Mode; +import mage.abilities.dynamicvalue.common.LandsYouControlCount; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.hint.common.LandsYouControlHint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BumiBash extends CardImpl { + + private static final FilterPermanent filter = new FilterLandPermanent("land creature or nonbasic land"); + + static { + filter.add(Predicates.or( + CardType.CREATURE.getPredicate(), + Predicates.not(SuperType.BASIC.getPredicate()) + )); + } + + public BumiBash(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); + + // Choose one -- + // * Bumi Bash deals damage equal to the number of lands you control to target creature. + this.getSpellAbility().addEffect(new DamageTargetEffect(LandsYouControlCount.instance) + .setText("{this} deals damage equal to the number of lands you control to target creature")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addHint(LandsYouControlHint.instance); + + // * Destroy target land creature or nonbasic land. + this.getSpellAbility().addMode(new Mode(new DestroyTargetEffect()).addTarget(new TargetPermanent(filter))); + } + + private BumiBash(final BumiBash card) { + super(card); + } + + @Override + public BumiBash copy() { + return new BumiBash(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index c1d9c6e78f5..0f1fd1956b6 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -48,6 +48,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Barrels of Blasting Jelly", 254, Rarity.COMMON, mage.cards.b.BarrelsOfBlastingJelly.class)); cards.add(new SetCardInfo("Beetle-Headed Merchants", 86, Rarity.COMMON, mage.cards.b.BeetleHeadedMerchants.class)); cards.add(new SetCardInfo("Bender's Waterskin", 255, Rarity.COMMON, mage.cards.b.BendersWaterskin.class)); + cards.add(new SetCardInfo("Bumi Bash", 125, Rarity.COMMON, mage.cards.b.BumiBash.class)); cards.add(new SetCardInfo("Buzzard-Wasp Colony", 88, Rarity.UNCOMMON, mage.cards.b.BuzzardWaspColony.class)); cards.add(new SetCardInfo("Cat-Gator", 91, Rarity.UNCOMMON, mage.cards.c.CatGator.class)); cards.add(new SetCardInfo("Cat-Owl", 212, Rarity.COMMON, mage.cards.c.CatOwl.class)); -- 2.47.2 From 42a9cd8497cab4ba60ce3cb3d78717a123ed1ea7 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 08:58:26 -0400 Subject: [PATCH 036/261] [TLA] Implement Fire Nation Cadets --- .../src/mage/cards/f/FireNationCadets.java | 60 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 61 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FireNationCadets.java diff --git a/Mage.Sets/src/mage/cards/f/FireNationCadets.java b/Mage.Sets/src/mage/cards/f/FireNationCadets.java new file mode 100644 index 00000000000..f1eac9405e8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FireNationCadets.java @@ -0,0 +1,60 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.abilities.keyword.FirebendingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterCard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FireNationCadets extends CardImpl { + + private static final Condition condition = new CardsInControllerGraveyardCondition(1, new FilterCard(SubType.LESSON)); + private static final Hint hint = new ConditionHint(condition, "There's a Lesson card in your graveyard"); + + public FireNationCadets(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // This creature has firebending 2 as long as there's a Lesson card in your graveyard. + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new GainAbilitySourceEffect(new FirebendingAbility(2)), condition, + "{this} has firebending 2 as long as there's a Lesson card in your graveyard" + )).addHint(hint)); + + // {2}: This creature gets +1/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility( + new BoostSourceEffect(2, 0, Duration.EndOfTurn), new GenericManaCost(2) + )); + } + + private FireNationCadets(final FireNationCadets card) { + super(card); + } + + @Override + public FireNationCadets copy() { + return new FireNationCadets(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 0f1fd1956b6..008cf9310ba 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -82,6 +82,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Fire Lord Zuko", 360, Rarity.RARE, mage.cards.f.FireLordZuko.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation Attacks", 133, Rarity.UNCOMMON, mage.cards.f.FireNationAttacks.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation Attacks", 299, Rarity.UNCOMMON, mage.cards.f.FireNationAttacks.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fire Nation Cadets", 134, Rarity.COMMON, mage.cards.f.FireNationCadets.class)); cards.add(new SetCardInfo("Fire Nation Engineer", 99, Rarity.UNCOMMON, mage.cards.f.FireNationEngineer.class)); cards.add(new SetCardInfo("Fire Sages", 136, Rarity.UNCOMMON, mage.cards.f.FireSages.class)); cards.add(new SetCardInfo("Firebending Student", 139, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 55cc7dc36d36034a3dc7c4101e2e953494f846ce Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 08:59:10 -0400 Subject: [PATCH 037/261] [TLA] Implement Fire Nation Warship --- .../src/mage/cards/f/FireNationWarship.java | 46 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 47 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FireNationWarship.java diff --git a/Mage.Sets/src/mage/cards/f/FireNationWarship.java b/Mage.Sets/src/mage/cards/f/FireNationWarship.java new file mode 100644 index 00000000000..0fa1ef2e2a4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FireNationWarship.java @@ -0,0 +1,46 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.CrewAbility; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.ClueArtifactToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FireNationWarship extends CardImpl { + + public FireNationWarship(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + this.subtype.add(SubType.VEHICLE); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // When this Vehicle dies, create a Clue token. + this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new ClueArtifactToken()))); + + // Crew 2 + this.addAbility(new CrewAbility(2)); + } + + private FireNationWarship(final FireNationWarship card) { + super(card); + } + + @Override + public FireNationWarship copy() { + return new FireNationWarship(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 008cf9310ba..d86f62598cd 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -84,6 +84,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Fire Nation Attacks", 299, Rarity.UNCOMMON, mage.cards.f.FireNationAttacks.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation Cadets", 134, Rarity.COMMON, mage.cards.f.FireNationCadets.class)); cards.add(new SetCardInfo("Fire Nation Engineer", 99, Rarity.UNCOMMON, mage.cards.f.FireNationEngineer.class)); + cards.add(new SetCardInfo("Fire Nation Warship", 256, Rarity.UNCOMMON, mage.cards.f.FireNationWarship.class)); cards.add(new SetCardInfo("Fire Sages", 136, Rarity.UNCOMMON, mage.cards.f.FireSages.class)); cards.add(new SetCardInfo("Firebending Student", 139, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Firebending Student", 342, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 0b796ea2762ae306ed5be941f2811b46ddc60cfa Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 09:15:10 -0400 Subject: [PATCH 038/261] [TLA] Implement Toph, Earthbending Master --- .../mage/cards/t/TophEarthbendingMaster.java | 58 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + .../common/CountersControllerCount.java | 2 +- .../keyword/EarthbendTargetEffect.java | 32 +++++++--- 4 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/t/TophEarthbendingMaster.java diff --git a/Mage.Sets/src/mage/cards/t/TophEarthbendingMaster.java b/Mage.Sets/src/mage/cards/t/TophEarthbendingMaster.java new file mode 100644 index 00000000000..40e3ace50f1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TophEarthbendingMaster.java @@ -0,0 +1,58 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; +import mage.abilities.common.LandfallAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CountersControllerCount; +import mage.abilities.effects.common.counter.AddCountersPlayersEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TophEarthbendingMaster extends CardImpl { + + private static final DynamicValue xValue = new CountersControllerCount(CounterType.EXPERIENCE); + + public TophEarthbendingMaster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Landfall -- Whenever a land you control enters, you get an experience counter. + this.addAbility(new LandfallAbility(new AddCountersPlayersEffect( + CounterType.EXPERIENCE.createInstance(), TargetController.YOU + ))); + + // Whenever you attack, earthbend X, where X is the number of experience counters you have. + Ability ability = new AttacksWithCreaturesTriggeredAbility(new EarthbendTargetEffect(xValue), 1); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability); + } + + private TophEarthbendingMaster(final TophEarthbendingMaster card) { + super(card); + } + + @Override + public TophEarthbendingMaster copy() { + return new TophEarthbendingMaster(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 0c18fe3ff8b..c265cea16af 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -130,6 +130,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Thriving Heath", 262, Rarity.COMMON, mage.cards.t.ThrivingHeath.class)); cards.add(new SetCardInfo("Thriving Isle", 263, Rarity.COMMON, mage.cards.t.ThrivingIsle.class)); cards.add(new SetCardInfo("Thriving Moor", 264, Rarity.COMMON, mage.cards.t.ThrivingMoor.class)); + cards.add(new SetCardInfo("Toph, Earthbending Master", 145, Rarity.MYTHIC, mage.cards.t.TophEarthbendingMaster.class)); cards.add(new SetCardInfo("Tundra Wall", 220, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tundra Wall", 275, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Turtle-Seals", 226, Rarity.COMMON, mage.cards.t.TurtleSeals.class)); diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersControllerCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersControllerCount.java index c6d6a86826b..0d942a10de0 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersControllerCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/CountersControllerCount.java @@ -48,6 +48,6 @@ public class CountersControllerCount implements DynamicValue { @Override public String getMessage() { - return (counterType != null ? counterType.toString() + ' ' : "") + "counter on {this}'s controller"; + return "the number of " + counterType.getName() + " counters you have"; } } diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/EarthbendTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/EarthbendTargetEffect.java index 9982a5dc7fc..9ed6c95b839 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/EarthbendTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/EarthbendTargetEffect.java @@ -4,6 +4,8 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.Mode; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; @@ -25,9 +27,13 @@ import mage.util.CardUtil; */ public class EarthbendTargetEffect extends OneShotEffect { - private final int amount; + private final DynamicValue amount; public EarthbendTargetEffect(int amount) { + this(StaticValue.get(amount)); + } + + public EarthbendTargetEffect(DynamicValue amount) { super(Outcome.Benefit); this.amount = amount; } @@ -53,11 +59,12 @@ public class EarthbendTargetEffect extends OneShotEffect { .withAbility(HasteAbility.getInstance()), false, true, Duration.Custom ), source); - permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game); + int value = amount.calculate(game, source, this); + permanent.addCounters(CounterType.P1P1.createInstance(value), source, game); game.addDelayedTriggeredAbility(new EarthbendingDelayedTriggeredAbility(permanent, game), source); game.fireEvent(GameEvent.getEvent( GameEvent.EventType.EARTHBENDED, permanent.getId(), - source, source.getControllerId(), amount + source, source.getControllerId(), value )); return true; } @@ -67,10 +74,21 @@ public class EarthbendTargetEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - return "earthbend " + amount + ". (Target land you control becomes a 0/0 creature " + - "with haste that's still a land. Put " + CardUtil.numberToText(amount, "a") + - " +1/+1 counter" + (amount > 1 ? "s" : "") + " on it. " + - "When it dies or is exiled, return it to the battlefield tapped.)"; + StringBuilder sb = new StringBuilder("earthbend "); + sb.append(amount); + if (!(amount instanceof StaticValue)) { + sb.append(", where X is "); + sb.append(amount.getMessage()); + } + sb.append(". (Target land you control becomes a 0/0 creature with haste that's still a land. Put "); + String value = amount instanceof StaticValue + ? CardUtil.numberToText(((StaticValue) amount).getValue(), "a") + : amount.toString(); + sb.append(value); + sb.append(" +1/+1 counter"); + sb.append(("a".equals(value) ? "" : "s")); + sb.append(" on it. When it dies or is exiled, return it to the battlefield tapped.)"); + return sb.toString(); } } -- 2.47.2 From 48fa39256e7e8632e703b56c54bf17e7fb669243 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 12:01:37 -0400 Subject: [PATCH 039/261] [TLA] Implement Origin of Metalbending --- .../mage/cards/o/OriginOfMetalbending.java | 49 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 50 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/o/OriginOfMetalbending.java diff --git a/Mage.Sets/src/mage/cards/o/OriginOfMetalbending.java b/Mage.Sets/src/mage/cards/o/OriginOfMetalbending.java new file mode 100644 index 00000000000..9db58f9068a --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OriginOfMetalbending.java @@ -0,0 +1,49 @@ +package mage.cards.o; + +import mage.abilities.Mode; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class OriginOfMetalbending extends CardImpl { + + public OriginOfMetalbending(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); + + this.subtype.add(SubType.LESSON); + + // Choose one -- + // * Destroy target artifact or enchantment. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); + + // * Put a +1/+1 counter on target creature you control. It gains indestructible until end of turn. + this.getSpellAbility().addMode(new Mode(new AddCountersTargetEffect(CounterType.P1P1.createInstance())) + .addEffect(new GainAbilityTargetEffect(IndestructibleAbility.getInstance()) + .setText("It gains indestructible until end of turn")) + .addTarget(new TargetControlledCreaturePermanent())); + } + + private OriginOfMetalbending(final OriginOfMetalbending card) { + super(card); + } + + @Override + public OriginOfMetalbending copy() { + return new OriginOfMetalbending(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index d86f62598cd..1ed6f8ac599 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -137,6 +137,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 295, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("North Pole Patrol", 65, Rarity.UNCOMMON, mage.cards.n.NorthPolePatrol.class)); cards.add(new SetCardInfo("Octopus Form", 66, Rarity.COMMON, mage.cards.o.OctopusForm.class)); + cards.add(new SetCardInfo("Origin of Metalbending", 187, Rarity.COMMON, mage.cards.o.OriginOfMetalbending.class)); cards.add(new SetCardInfo("Ostrich-Horse", 188, Rarity.COMMON, mage.cards.o.OstrichHorse.class)); cards.add(new SetCardInfo("Otter-Penguin", 67, Rarity.COMMON, mage.cards.o.OtterPenguin.class)); cards.add(new SetCardInfo("Ozai's Cruelty", 113, Rarity.UNCOMMON, mage.cards.o.OzaisCruelty.class)); -- 2.47.2 From b7416356aa392e711f30ffa718705ec54f25f5cf Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 12:16:22 -0400 Subject: [PATCH 040/261] [TLA] Implement Northern Air Temple --- .../src/mage/cards/n/NorthernAirTemple.java | 62 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 63 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/n/NorthernAirTemple.java diff --git a/Mage.Sets/src/mage/cards/n/NorthernAirTemple.java b/Mage.Sets/src/mage/cards/n/NorthernAirTemple.java new file mode 100644 index 00000000000..6187b83987f --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NorthernAirTemple.java @@ -0,0 +1,62 @@ +package mage.cards.n; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +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.FilterControlledPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class NorthernAirTemple extends CardImpl { + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.SHRINE), null); + private static final Hint hint = new ValueHint("Shrines you control", xValue); + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SHRINE, "another Shrine you control"); + + static { + filter.add(AnotherPredicate.instance); + } + + public NorthernAirTemple(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.SHRINE); + + // When Northern Air Temple enters, each opponent loses X life and you gain X life, where X is the number of Shrines you control. + Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeOpponentsEffect(xValue) + .setText("each opponent loses X life")); + ability.addEffect(new GainLifeEffect(xValue).concatBy("and")); + this.addAbility(ability.addHint(hint)); + + // Whenever another Shrine you control enters, each opponent loses 1 life and you gain 1 life. + ability = new EntersBattlefieldAllTriggeredAbility(new LoseLifeOpponentsEffect(1), filter); + ability.addEffect(new GainLifeEffect(1).concatBy("and")); + this.addAbility(ability); + } + + private NorthernAirTemple(final NorthernAirTemple card) { + super(card); + } + + @Override + public NorthernAirTemple copy() { + return new NorthernAirTemple(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 1ed6f8ac599..8170c1ac29f 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -136,6 +136,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 290, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Mountain", 295, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("North Pole Patrol", 65, Rarity.UNCOMMON, mage.cards.n.NorthPolePatrol.class)); + cards.add(new SetCardInfo("Northern Air Temple", 111, Rarity.UNCOMMON, mage.cards.n.NorthernAirTemple.class)); cards.add(new SetCardInfo("Octopus Form", 66, Rarity.COMMON, mage.cards.o.OctopusForm.class)); cards.add(new SetCardInfo("Origin of Metalbending", 187, Rarity.COMMON, mage.cards.o.OriginOfMetalbending.class)); cards.add(new SetCardInfo("Ostrich-Horse", 188, Rarity.COMMON, mage.cards.o.OstrichHorse.class)); -- 2.47.2 From d4b8c75619c6f16a4920ad6f78ee496dd3a41c2f Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 12:29:05 -0400 Subject: [PATCH 041/261] [TLA] Implement Planetarium of Wan Shi Tong --- .../mage/cards/p/PlanetariumOfWanShiTong.java | 122 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + .../java/mage/abilities/TriggeredAbility.java | 2 + .../mage/abilities/TriggeredAbilityImpl.java | 6 + 4 files changed, 132 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/PlanetariumOfWanShiTong.java diff --git a/Mage.Sets/src/mage/cards/p/PlanetariumOfWanShiTong.java b/Mage.Sets/src/mage/cards/p/PlanetariumOfWanShiTong.java new file mode 100644 index 00000000000..0c6c9d526fe --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PlanetariumOfWanShiTong.java @@ -0,0 +1,122 @@ +package mage.cards.p; + +import mage.abilities.Ability; +import mage.abilities.TriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PlanetariumOfWanShiTong extends CardImpl { + + public PlanetariumOfWanShiTong(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); + + this.supertype.add(SuperType.LEGENDARY); + + // {1}, {T}: Scry 2. + Ability ability = new SimpleActivatedAbility(new ScryEffect(2), new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + + // Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn. + this.addAbility(new PlanetariumOfWanShiTongTriggeredAbility()); + } + + private PlanetariumOfWanShiTong(final PlanetariumOfWanShiTong card) { + super(card); + } + + @Override + public PlanetariumOfWanShiTong copy() { + return new PlanetariumOfWanShiTong(this); + } +} + +class PlanetariumOfWanShiTongTriggeredAbility extends TriggeredAbilityImpl { + + PlanetariumOfWanShiTongTriggeredAbility() { + super(Zone.BATTLEFIELD, new PlanetariumOfWanShiTongEffect()); + this.setTriggerPhrase("Whenever you scry or surveil, "); + this.setDoOnlyOnceEachTurn(true); + this.setOptional(false); + } + + private PlanetariumOfWanShiTongTriggeredAbility(final PlanetariumOfWanShiTongTriggeredAbility ability) { + super(ability); + } + + @Override + public PlanetariumOfWanShiTongTriggeredAbility copy() { + return new PlanetariumOfWanShiTongTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + switch (event.getType()) { + case SCRIED: + case SURVEILED: + return true; + default: + return false; + } + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return isControlledBy(event.getPlayerId()); + } +} + +class PlanetariumOfWanShiTongEffect extends OneShotEffect { + + PlanetariumOfWanShiTongEffect() { + super(Outcome.Benefit); + staticText = "look at the top card of your library. You may cast that card without paying its mana cost"; + } + + private PlanetariumOfWanShiTongEffect(final PlanetariumOfWanShiTongEffect effect) { + super(effect); + } + + @Override + public PlanetariumOfWanShiTongEffect copy() { + return new PlanetariumOfWanShiTongEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Card card = player.getLibrary().getFromTop(game); + if (card == null) { + return false; + } + player.lookAtCards("Top of library", card, game); + if (!CardUtil.castSpellWithAttributesForFree(player, source, game, card)) { + return false; + } + TriggeredAbility.setDidThisTurn(source, game); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 8170c1ac29f..4ea5571b2b1 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -147,6 +147,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Plains", 282, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 287, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Plains", 292, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Planetarium of Wan Shi Tong", 259, Rarity.MYTHIC, mage.cards.p.PlanetariumOfWanShiTong.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Planetarium of Wan Shi Tong", 385, Rarity.MYTHIC, mage.cards.p.PlanetariumOfWanShiTong.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Pretending Poxbearers", 237, Rarity.COMMON, mage.cards.p.PretendingPoxbearers.class)); cards.add(new SetCardInfo("Rabaroo Troop", 32, Rarity.COMMON, mage.cards.r.RabarooTroop.class)); cards.add(new SetCardInfo("Ran and Shaw", 150, Rarity.RARE, mage.cards.r.RanAndShaw.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbility.java b/Mage/src/main/java/mage/abilities/TriggeredAbility.java index 37785373766..7d0dd8401dc 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbility.java @@ -61,6 +61,8 @@ public interface TriggeredAbility extends Ability { */ int getRemainingTriggersLimitEachGame(Game game); + TriggeredAbility setOptional(boolean optional); + TriggeredAbility setDoOnlyOnceEachTurn(boolean doOnlyOnce); /** diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java index 171669368c5..fcef0db4a28 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java @@ -209,6 +209,12 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge return this; } + @Override + public TriggeredAbility setOptional(boolean optional) { + this.optional = optional; + return this; + } + @Override public TriggeredAbility withRuleTextReplacement(boolean replaceRuleText) { this.replaceRuleText = replaceRuleText; -- 2.47.2 From bcba45652f44e76693ebb1106a10fa88d8e2f5d5 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 31 Oct 2025 12:33:46 -0400 Subject: [PATCH 042/261] [TLA] Implement The Mechanist, Aerial Artisan --- .../cards/t/TheMechanistAerialArtisan.java | 74 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 76 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TheMechanistAerialArtisan.java diff --git a/Mage.Sets/src/mage/cards/t/TheMechanistAerialArtisan.java b/Mage.Sets/src/mage/cards/t/TheMechanistAerialArtisan.java new file mode 100644 index 00000000000..5b55075d372 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheMechanistAerialArtisan.java @@ -0,0 +1,74 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.permanent.token.ClueArtifactToken; +import mage.game.permanent.token.custom.CreatureToken; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheMechanistAerialArtisan extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledArtifactPermanent("artifact token you control"); + + static { + filter.add(TokenPredicate.TRUE); + } + + public TheMechanistAerialArtisan(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ARTIFICER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Whenever you cast a noncreature spell, create a Clue token. + this.addAbility(new SpellCastControllerTriggeredAbility( + new CreateTokenEffect(new ClueArtifactToken()), + StaticFilters.FILTER_SPELL_A_NON_CREATURE, false + )); + + // {T}: Until end of turn, target artifact token you control becomes a 3/1 Construct artifact creature with flying. + Ability ability = new SimpleActivatedAbility( + new BecomesCreatureTargetEffect( + new CreatureToken( + 3, 1, "3/1 Construct artifact creature with flying", SubType.CONSTRUCT + ).withAbility(FlyingAbility.getInstance()), false, false, Duration.EndOfTurn + ).withDurationRuleAtStart(true), new TapSourceCost() + ); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + private TheMechanistAerialArtisan(final TheMechanistAerialArtisan card) { + super(card); + } + + @Override + public TheMechanistAerialArtisan copy() { + return new TheMechanistAerialArtisan(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 4ea5571b2b1..6c46bcea8c5 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -181,6 +181,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Swamp", 289, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swamp", 294, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("The Cave of Two Lovers", 126, Rarity.UNCOMMON, mage.cards.t.TheCaveOfTwoLovers.class)); + cards.add(new SetCardInfo("The Mechanist, Aerial Artisan", 369, Rarity.RARE, mage.cards.t.TheMechanistAerialArtisan.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Mechanist, Aerial Artisan", 64, Rarity.RARE, mage.cards.t.TheMechanistAerialArtisan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Rise of Sozin", 117, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Rise of Sozin", 356, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tiger-Seal", 318, Rarity.RARE, mage.cards.t.TigerSeal.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 99bdfe3a1a011316793e367414e8b405e613e16e Mon Sep 17 00:00:00 2001 From: Steven Knipe Date: Fri, 31 Oct 2025 21:45:06 -0700 Subject: [PATCH 043/261] Convert UnsealTheNecropolis and AnotherChance to use OneShotNonTargetEffect --- Mage.Sets/src/mage/cards/a/AnotherChance.java | 37 +++++---------- .../src/mage/cards/u/UnsealTheNecropolis.java | 45 ++----------------- 2 files changed, 15 insertions(+), 67 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AnotherChance.java b/Mage.Sets/src/mage/cards/a/AnotherChance.java index fbbd9705b6c..943b1733290 100644 --- a/Mage.Sets/src/mage/cards/a/AnotherChance.java +++ b/Mage.Sets/src/mage/cards/a/AnotherChance.java @@ -2,17 +2,15 @@ package mage.cards.a; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.OneShotNonTargetEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; -import mage.target.TargetCard; import mage.target.common.TargetCardInYourGraveyard; import java.util.UUID; @@ -26,7 +24,9 @@ public final class AnotherChance extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}"); // You may mill two cards. Then return up to two creature cards from your graveyard to your hand. - this.getSpellAbility().addEffect(new AnotherChanceEffect()); + this.getSpellAbility().addEffect(new AnotherChanceMillEffect()); + this.getSpellAbility().addEffect(new OneShotNonTargetEffect(new ReturnFromGraveyardToHandTargetEffect().setText("Then return up to two creature cards from your graveyard to your hand."), + new TargetCardInYourGraveyard(0, 2, StaticFilters.FILTER_CARD_CREATURES_YOUR_GRAVEYARD, true)).withTargetDescription("up to two creature cards").concatBy("Then ")); } private AnotherChance(final AnotherChance card) { @@ -39,23 +39,20 @@ public final class AnotherChance extends CardImpl { } } -/** - * Inspired by {@link mage.cards.u.UnsealTheNecropolis} - */ -class AnotherChanceEffect extends OneShotEffect { +class AnotherChanceMillEffect extends OneShotEffect { - AnotherChanceEffect() { + AnotherChanceMillEffect() { super(Outcome.Benefit); - staticText = "You may mill two cards. Then return up to two creature cards from your graveyard to your hand"; + staticText = "You may mill two cards."; } - private AnotherChanceEffect(final AnotherChanceEffect effect) { + private AnotherChanceMillEffect(final AnotherChanceMillEffect effect) { super(effect); } @Override - public AnotherChanceEffect copy() { - return new AnotherChanceEffect(this); + public AnotherChanceMillEffect copy() { + return new AnotherChanceMillEffect(this); } @Override @@ -68,18 +65,6 @@ class AnotherChanceEffect extends OneShotEffect { if (player.chooseUse(outcome, "Mill two cards?", source, game)) { player.millCards(2, source, game); } - - // Make sure the mill has been processed. - game.processAction(); - - TargetCard target = new TargetCardInYourGraveyard( - 0, 2, StaticFilters.FILTER_CARD_CREATURES_YOUR_GRAVEYARD, true - ); - player.choose(outcome, target, source, game); - Cards cards = new CardsImpl(target.getTargets()); - if (!cards.isEmpty()) { - player.moveCards(cards, Zone.HAND, source, game); - } return true; } } diff --git a/Mage.Sets/src/mage/cards/u/UnsealTheNecropolis.java b/Mage.Sets/src/mage/cards/u/UnsealTheNecropolis.java index 90a77b78772..7f6dd20c4a3 100644 --- a/Mage.Sets/src/mage/cards/u/UnsealTheNecropolis.java +++ b/Mage.Sets/src/mage/cards/u/UnsealTheNecropolis.java @@ -1,20 +1,13 @@ package mage.cards.u; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.OneShotNonTargetEffect; import mage.abilities.effects.common.MillCardsEachPlayerEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetCard; import mage.target.common.TargetCardInYourGraveyard; import java.util.UUID; @@ -29,7 +22,8 @@ public final class UnsealTheNecropolis extends CardImpl { // Each player mills three cards. Then you return up to two creature cards from your graveyard to your hand. this.getSpellAbility().addEffect(new MillCardsEachPlayerEffect(3, TargetController.EACH_PLAYER)); - this.getSpellAbility().addEffect(new UnsealTheNecropolisEffect()); + this.getSpellAbility().addEffect(new OneShotNonTargetEffect(new ReturnFromGraveyardToHandTargetEffect().setText("Then you return up to two creature cards from your graveyard to your hand"), + new TargetCardInYourGraveyard(0, 2, StaticFilters.FILTER_CARD_CREATURES_YOUR_GRAVEYARD, true))); } private UnsealTheNecropolis(final UnsealTheNecropolis card) { @@ -41,34 +35,3 @@ public final class UnsealTheNecropolis extends CardImpl { return new UnsealTheNecropolis(this); } } - -class UnsealTheNecropolisEffect extends OneShotEffect { - - UnsealTheNecropolisEffect() { - super(Outcome.Benefit); - staticText = "Then you return up to two creature cards from your graveyard to your hand"; - } - - private UnsealTheNecropolisEffect(final UnsealTheNecropolisEffect effect) { - super(effect); - } - - @Override - public UnsealTheNecropolisEffect copy() { - return new UnsealTheNecropolisEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { - return false; - } - TargetCard target = new TargetCardInYourGraveyard( - 0, 2, StaticFilters.FILTER_CARD_CREATURES_YOUR_GRAVEYARD, true - ); - player.choose(outcome, target, source, game); - Cards cards = new CardsImpl(target.getTargets()); - return !cards.isEmpty() && player.moveCards(cards, Zone.HAND, source, game); - } -} -- 2.47.2 From 379cd5b7b73a6708c21f8a8ba8315fec570fbe0c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 1 Nov 2025 16:56:29 -0400 Subject: [PATCH 044/261] [TLA] update spoiler --- .../src/mage/sets/AvatarTheLastAirbender.java | 2 +- Utils/mtg-cards-data.txt | 27 ++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 6c46bcea8c5..f2b7e52430d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -12,7 +12,7 @@ import java.util.List; */ public final class AvatarTheLastAirbender extends ExpansionSet { - private static final List unfinished = Arrays.asList("Aang's Iceberg", "Avatar Aang", "Flexible Waterbender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Invasion Submersible", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "The Legend of Kuruk", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); + private static final List unfinished = Arrays.asList("Aang's Iceberg", "Aang, Swift Savior", "Avatar Aang", "Flexible Waterbender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Invasion Submersible", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "Spirit Water Revival", "The Legend of Kuruk", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); private static final AvatarTheLastAirbender instance = new AvatarTheLastAirbender(); public static AvatarTheLastAirbender getInstance() { diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 035c69f7556..02d9f4126a6 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59767,6 +59767,7 @@ Aang, the Last Airbender|Avatar: The Last Airbender|4|U|{3}{W}|Legendary Creatur Aang's Iceberg|Avatar: The Last Airbender|5|R|{2}{W}|Enchantment|||Flash$When this enchantment enters, exile up to one other target nonland permanent until this enchantment leaves the battlefield.$Waterbend {3}: Sacrifice this enchantment. If you do, scry 2.| Airbender Ascension|Avatar: The Last Airbender|6|R|{1}{W}|Enchantment|||When this enchantment enters, airbend up to one target creature.$Whenever a creature you control enters, put a quest counter on this enchantment.$At the beginning of your end step, if this enchantment has four or more quest counters on it, exile up to one target creature you control, then return it to the battlefield under its owner's control.| Airbending Lesson|Avatar: The Last Airbender|8|C|{2}{W}|Instant - Lesson|||Airbend target nonland permanent.$Draw a card.| +Appa, Loyal Sky Bison|Avatar: The Last Airbender|9|U|{4}{W}{W}|Legendary Creature - Bison Ally|4|4|Flying$Whenever Appa enters or attacks, choose one --$* Target creature you control gains flying until end of turn.$* Airbend another target nonland permanent you control..| Appa, Steadfast Guardian|Avatar: The Last Airbender|10|M|{2}{W}{W}|Legendary Creature - Bison Ally|3|4|Flash$Flying$When Appa enters, airbend any number of other target nonland permanents you control.$Whenever you cast a spell from exile, create a 1/1 white Ally creature token.| Avatar Enthusiasts|Avatar: The Last Airbender|11|C|{2}{W}|Creature - Human Peasant Ally|2|2|Whenever another Ally you control enters, put a +1/+1 counter on this creature.| Compassionate Healer|Avatar: The Last Airbender|13|C|{1}{W}|Creature - Human Cleric Ally|2|2|Whenever this creature becomes tapped, you gain 1 life and scry 1.| @@ -59774,6 +59775,8 @@ Fancy Footwork|Avatar: The Last Airbender|19|U|{2}{W}|Instant - Lesson|||Untap o Glider Kids|Avatar: The Last Airbender|21|C|{2}{W}|Creature - Human Pilot Ally|2|3|Flying$When this creature enters, scry 1.| Glider Staff|Avatar: The Last Airbender|22|U|{2}{W}|Artifact - Equipment|||When this Equipment enters, airbend up to one target creature.$Equipped creature gets +1/+1 and has flying.$Equip {2}| Jeong Jeong's Deserters|Avatar: The Last Airbender|25|C|{1}{W}|Creature - Human Rebel Ally|1|2|When this creature enters, put a +1/+1 counter on target creature.| +The Legend of Yangchen|Avatar: The Last Airbender|27|M|{3}{W}{W}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$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.$II -- You may have target opponent draw three cards. If you do, draw three cards.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| +Avatar Yangchen|Avatar: The Last Airbender|27|M||Legendary Creature - Avatar|4|5|Flying$Whenever you cast your second spell each turn, airbend up to one other target nonland permanent.| Master Piandao|Avatar: The Last Airbender|28|U|{4}{W}|Legendary Creature - Human Warrior Ally|4|4|First strike$Whenever Master Piandao attacks, look at the top four cards of your library. You may reveal an Ally, Equipment, or Lesson card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| Momo, Friendly Flier|Avatar: The Last Airbender|29|R|{W}|Legendary Creature - Lemur Bat Ally|1|1|Flying$The first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast.$Whenever another creature you control with flying enters, Momo gets +1/+1 until end of turn.| Momo, Playful Pet|Avatar: The Last Airbender|30|U|{W}|Legendary Creature - Lemur Bat Ally|1|1|Flying, vigilance$When Momo leaves the battlefield, choose one --$* Create a Food token.$* Put a +1/+1 counter on target creature you control.$* Scry 2.| @@ -59781,6 +59784,8 @@ Path to Redemption|Avatar: The Last Airbender|31|C|{1}{W}|Enchantment - Aura|||E Rabaroo Troop|Avatar: The Last Airbender|32|C|{3}{W}{W}|Creature - Rabbit Kangaroo|3|5|Landfall -- Whenever a land you control enters, this creature gains flying until end of turn and you gain 1 life.$Plainscycling {2}| Razor Rings|Avatar: The Last Airbender|33|C|{1}{W}|Instant|||Razor Rings deals 4 damage to target attacking or blocking creature. You gain life equal to the excess damage dealt this way.| Southern Air Temple|Avatar: The Last Airbender|36|U|{3}{W}|Legendary Enchantment - Shrine|||When Southern Air Temple enters, put X +1/+1 counters on each creature you control, where X is the number of Shrines you control.$Whenever another Shrine you control enters, put a +1/+1 counter on each creature you control.| +Suki, Courageous Rescuer|Avatar: The Last Airbender|37|R|{1}{W}{W}|Legendary Creature - Human Warrior Ally|2|4|Other creatures you control get +1/+0.$Whenever another permanent you control leaves the battlefield during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.| +United Front|Avatar: The Last Airbender|39|M|{X}{W}{W}|Sorcery|||Create X 1/1 white Ally creature tokens, then put a +1/+1 counter on each creature you control.| Water Tribe Rallier|Avatar: The Last Airbender|42|U|{1}{W}|Creature - Human Soldier Ally|2|2|Waterbend {5}: Look at the top four cards of your library. You may reveal a creature card with power 3 or less from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| Yip Yip!|Avatar: The Last Airbender|43|C|{W}|Instant - Lesson|||Target creature you control gets +2/+2 until end of turn. If that creature is an Ally, it also gains flying until end of turn.| First-Time Flyer|Avatar: The Last Airbender|49|C|{1}{U}|Creature - Human Pilot Ally|1|2|Flying$This creature gets +1/+1 as long as there's a Lesson card in your graveyard.| @@ -59806,6 +59811,8 @@ Rowdy Snowballers|Avatar: The Last Airbender|68|C|{2}{U}|Creature - Human Peasan Secret of Bloodbending|Avatar: The Last Airbender|69|M|{U}{U}{U}{U}|Sorcery - Lesson|||As an additional cost to cast this spell, you may waterbend {10}.$You control target opponent during their next combat phase. If this spell's additional cost was paid, you control that player during their next turn instead.$Exile Secret of Bloodbending.| Serpent of the Pass|Avatar: The Last Airbender|70|U|{5}{U}{U}|Creature - Serpent|6|5|If there are three or more Lesson cards in your graveyard, you may cast this spell as though it had flash.$This spell costs {1} less to cast for each noncreature, nonland card in your graveyard.| Sokka's Haiku|Avatar: The Last Airbender|71|U|{3}{U}{U}|Instant - Lesson|||Counter target spell.$Draw a card, then mill three cards.$Untap target land.| +The Spirit Oasis|Avatar: The Last Airbender|72|U|{2}{U}|Legendary Enchantment - Shrine|||When The Spirit Oasis enters, draw a card for each Shrine you control.$Whenever another Shrine you control enters, draw a card.| +Spirit Water Revival|Avatar: The Last Airbender|73|R|{1}{U}{U}|Sorcery|||As an additional cost to cast this spell, you may waterbend {6}.$Draw two cards. If this spell's additional cost was paid, instead shuffle your graveyard into your library, draw seven cards, and you have no maximum hand size for the rest of the game.$Exile Spirit Water Revival.| Teo, Spirited Glider|Avatar: The Last Airbender|74|U|{3}{U}|Legendary Creature - Human Pilot Ally|1|4|Flying$Whenever one or more creatures you control with flying attack, draw a card, then discard a card. When you discard a nonland card this way, put a +1/+1 counter on target creature you control.| Tiger-Seal|Avatar: The Last Airbender|75|R|{U}|Creature - Cat Seal|3|3|Vigilance$At the beginning of your upkeep, tap this creature.$Whenever you draw your second card each turn, untap this creature.| Ty Lee, Chi Blocker|Avatar: The Last Airbender|76|R|{2}{U}|Legendary Creature - Human Performer Ally|2|1|Flash$Prowess$When Ty Lee enters, tap up to one target creature. It doesn't untap during its controller's untap step for as long as you control Ty Lee.| @@ -59829,6 +59836,7 @@ Fire Nation Engineer|Avatar: The Last Airbender|99|U|{2}{B}|Creature - Human Art Foggy Swamp Visions|Avatar: The Last Airbender|102|R|{1}{B}{B}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Exile X target creature cards from graveyards. For each creature card exiled this way, create a token that's a copy of it. At the beginning of your next end step, sacrifice those tokens.| Heartless Act|Avatar: The Last Airbender|103|U|{1}{B}|Instant|||Choose one --$* Destroy target creature with no counters on it.$* Remove up to three counters from target creature.| Hog-Monkey|Avatar: The Last Airbender|104|C|{2}{B}|Creature - Boar Monkey|3|2|At the beginning of combat on your turn, target creature you control with a +1/+1 counter on it gains menace until end of turn.$Exhaust -- {5}: Put two +1/+1 counters on this creature.| +June, Bounty Hunter|Avatar: The Last Airbender|106|U|{1}{B}|Legendary Creature - Human Mercenary|2|2|June can't be blocked as long as you've drawn two or more cards this turn.${1}, Sacrifice another creature: Create a Clue token. Activate only during your turn.| Merchant of Many Hats|Avatar: The Last Airbender|110|C|{1}{B}|Creature - Human Peasant Ally|2|2|{2}{B}: Return this card from your graveyard to your hand.| Northern Air Temple|Avatar: The Last Airbender|111|U|{B}|Legendary Enchantment - Shrine|||When Northern Air Temple enters, each opponent loses X life and you gain X life, where X is the number of Shrines you control.$Whenever another Shrine you control enters, each opponent loses 1 life and you gain 1 life.| Ozai's Cruelty|Avatar: The Last Airbender|113|U|{2}{B}|Sorcery - Lesson|||Ozai's Cruelty deals 2 damage to target player. That player discards two cards.| @@ -59846,16 +59854,20 @@ Fire Nation Cadets|Avatar: The Last Airbender|134|C|{R}|Creature - Human Soldier Fire Sages|Avatar: The Last Airbender|136|U|{1}{R}|Creature - Human Cleric|2|2|Firebending 1${1}{R}{R}: Put a +1/+1 counter on this creature.| Firebending Student|Avatar: The Last Airbender|139|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| How to Start a Riot|Avatar: The Last Airbender|140|C|{2}{R}|Instant - Lesson|||Target creature gains menace until end of turn.$Creatures target player controls get +2/+0 until end of turn.| +Jet's Brainwashing|Avatar: The Last Airbender|143|U|{R}|Sorcery|||Kicker {3}$Target creature can't block this turn. If this spell was kicked, gain control of that creature until end of turn, untap it, and it gains haste until end of turn.$Create a Clue token.| The Last Agni Kai|Avatar: The Last Airbender|144|R|{1}{R}|Instant|||Target creature you control fights target creature an opponent controls. If the creature the opponent controls is dealt excess damage this way, add that much {R}.$Until end of turn, you don't lose unspent red mana as steps and phases end.| The Legend of Roku|Avatar: The Last Airbender|145|M|{2}{R}{R}|Enchantment - Saga|||(As this Saga enters and after your draw$step, add a lore counter.)$I -- Exile the top three cards of your library. Until the end of your next turn, you may play those cards.$II -- Add one mana of any color.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| Avatar Roku|Avatar: The Last Airbender|145|M||Legendary Creature - Avatar|4|4|Firebending 4${8}: Create a 4/4 red Dragon creature token with flying and firebending 4.| Lightning Strike|Avatar: The Last Airbender|146|C|{1}{R}|Instant|||Lightning Strike deals 3 damage to any target.| +Mai, Jaded Edge|Avatar: The Last Airbender|147|U|{1}{R}|Legendary Creature - Human Noble|1|3|Prowess$Exhaust -- {3}: Put a double strike counter on Mai.| Mongoose Lizard|Avatar: The Last Airbender|148|C|{4}{R}{R}|Creature - Mongoose Lizard|5|6|Menace$When this creature enters, it deals 1 damage to any target.$Mountaincycling {2}| +Price of Freedom|Avatar: The Last Airbender|149|U|{1}{R}|Sorcery - Lesson|||Destroy target artifact or land an opponent controls. Its controller may search their library for a basic land card, put it onto the battlefield tapped, then shuffle.$Draw a card.| Ran and Shaw|Avatar: The Last Airbender|150|R|{3}{R}{R}|Legendary Creature - Dragon|4|4|Flying, firebending 2$When Ran and Shaw enter, if you cast them and there are three or more Dragon and/or Lesson cards in your graveyard, create a token that's a copy of Ran and Shaw, except it's not legendary.${3}{R}: Dragons you control get +2/+0 until end of turn.| Redirect Lightning|Avatar: The Last Airbender|151|R|{R}|Instant - Lesson|||As an additional cost to cast this spell, pay 5 life or pay {2}.$Change the target of target spell or ability with a single target.| Rough Rhino Cavalry|Avatar: The Last Airbender|152|C|{4}{R}|Creature - Human Mercenary|5|5|Firebending 2$Exhaust -- {8}: Put two +1/+1 counters on this creature. It gains trample until end of turn.| Solstice Revelations|Avatar: The Last Airbender|153|U|{2}{R}|Instant - Lesson|||Exile cards from the top of your library until you exile a nonland card. You may cast that card without paying its mana cost if the spell's mana value is less than the number of Mountains you control. If you don't cast that card this way, put it into your hand.$Flashback {6}{R}| Sozin's Comet|Avatar: The Last Airbender|154|M|{3}{R}{R}|Sorcery|||Each creature you control gains firebending 5 until end of turn.$Foretell {2}{R}| +Treetop Freedom Fighters|Avatar: The Last Airbender|156|C|{2}{R}|Creature - Human Rebel Ally|2|1|Haste$When this creature enters, create a 1/1 white Ally creature token.| Ty Lee, Artful Acrobat|Avatar: The Last Airbender|158|U|{2}{R}|Legendary Creature - Human Performer|3|2|Prowess$Whenever Ty Lee attacks, you may pay {1}. When you do, target creature can't block this turn.| War Balloon|Avatar: The Last Airbender|159|U|{2}{R}|Artifact - Vehicle|4|3|Flying${1}: Put a fire counter on this Vehicle.$As long as this Vehicle has three or more fire counters on it, it's an artifact creature.$Crew 3| Yuyan Archers|Avatar: The Last Airbender|161|C|{1}{R}|Creature - Human Archer|3|1|Reach$When this creature enters, you may discard a card. If you do, draw a card.| @@ -59886,6 +59898,8 @@ Turtle-Duck|Avatar: The Last Airbender|200|C|{G}|Creature - Turtle Bird|0|4|{3}: Unlucky Cabbage Merchant|Avatar: The Last Airbender|201|U|{1}{G}|Creature - Human Citizen|2|2|When this creature enters, create a Food token.$Whenever you sacrifice a Food, you may search your library for a basic land card and put it onto the battlefield tapped. If you search your library this way, put this creature on the bottom of its owner's library, then shuffle.| Aang, at the Crossroads|Avatar: The Last Airbender|203|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| Aang, Destined Savior|Avatar: The Last Airbender|203|R||Legendary Creature - Avatar Ally|4|4|Flying$Land creatures you control have vigilance.$At the beginning of combat on your turn, earthbend 2.| +Aang, Swift Savior|Avatar: The Last Airbender|204|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| +Aang and La, Ocean's Fury|Avatar: The Last Airbender|204|R||Legendary Creature - Avatar Spirit Ally|5|5|Reach, trample$Whenever Aang and La attack, put a +1/+1 counter on each tapped creature you control.| Abandon Attachments|Avatar: The Last Airbender|205|C|{1}{U/R}|Instant - Lesson|||You may discard a card. If you do, draw two cards.| Avatar Aang|Avatar: The Last Airbender|207|M|{R}{G}{W}{U}|Legendary Creature - Human Avatar Ally|4|4|Flying, firebending 2$Whenever you waterbend, earthbend, firebend, or airbend, draw a card. Then if you've done all four this turn, transform Avatar Aang.| Aang, Master of Elements|Avatar: The Last Airbender|207|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| @@ -59896,14 +59910,16 @@ Dai Li Agents|Avatar: The Last Airbender|214|U|{3}{B}{G}|Creature - Human Soldie Dragonfly Swarm|Avatar: The Last Airbender|215|U|{1}{U}{R}|Creature - Dragon Insect|*|3|Flying, ward {1}$This creature's power is equal to the number of noncreature, nonland cards in your graveyard.$When this creature dies, if there's a Lesson card in your graveyard, draw a card.| Earth Kingdom Soldier|Avatar: The Last Airbender|216|C|{4}{G/W}|Creature - Human Soldier|3|4|Vigilance$When this creature enters, put a +1/+1 counter on each of up to two target creatures you control.| Earth King's Lieutenant|Avatar: The Last Airbender|217|R|{G}{W}|Creature - Human Soldier Ally|1|1|Trample$When this creature enters, put a +1/+1 counter on each other Ally creature you control.$Whenever another Ally you control enters, put a +1/+1 counter on this creature.| -Earth Rumble Wrestlers|Avatar: The Last Airbender|218|C|{3}{R/G}|Creature - Human Warrior Performer|3|4|Reach$This creature gets +1/+0 and has trample as long as you control a land creature or a land entered the battlefield under your control this under your control turn.| +Earth Rumble Wrestlers|Avatar: The Last Airbender|218|C|{3}{R/G}|Creature - Human Warrior Performer|3|4|Reach$This creature gets +1/+0 and has trample as long as you control a land creature or a land entered the battlefield under your control this turn.| Earth Village Ruffians|Avatar: The Last Airbender|219|C|{2}{B/G}|Creature - Human Soldier Rogue|3|1|When this creature dies, earthbend 2.| Fire Lord Azula|Avatar: The Last Airbender|220|R|{1}{U}{B}{R}|Legendary Creature - Human Noble|4|4|Firebending 2$Whenever you cast a spell while Fire Lord Azula is attacking, copy that spell. You may choose new targets for the copy.| Fire Lord Zuko|Avatar: The Last Airbender|221|R|{R}{W}{B}|Legendary Creature - Human Noble Ally|2|4|Firebending X, where X is Fire Lord Zuko's power.$Whenever you cast a spell from exile and whenever a permanent you control enters from exile, put a +1/+1 counter on each creature you control.| +Foggy Swamp Spirit Keeper|Avatar: The Last Airbender|222|U|{1}{U}{B}|Creature - Human Druid Ally|2|4|Lifelink$Whenever you draw your second card each turn, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."| Guru Pathik|Avatar: The Last Airbender|223|U|{2}{G/U}{G/U}|Legendary Creature - Human Monk Ally|2|4|When Guru Pathik enters, look at the top five cards of your library. You may reveal a Lesson, Saga, or Shrine card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.$Whenever you cast a Lesson, Saga, or Shrine spell, put a +1/+1 counter on another target creature you control.| Hama, the Bloodbender|Avatar: The Last Airbender|224|U|{2}{U/B}{U/B}{U/B}|Legendary Creature - Human Warlock|3|3|When Hama enters, target opponent mills three cards. Exile up to one noncreature, nonland card from that player's graveyard. For as long as you control Hama, you may cast the exiled card during your turn by waterbending {X} rather than paying its mana cost, where X is its mana value.| Hei Bai, Spirit of Balance|Avatar: The Last Airbender|225|U|{2}{W/B}{W/B}|Legendary Creature - Bear Spirit|3|3|Whenever Hei Bai enters or attacks, you may sacrifice another creature or artifact. If you do, put two +1/+1 counters on Hei Bai.$When Hei Bai leaves the battlefield, put its counters on target creature you control.| Iroh, Grand Lotus|Avatar: The Last Airbender|227|R|{3}{G}{U}{R}|Legendary Creature - Human Noble Ally|5|5|Firebending 2$During your turn, each non-Lesson instant and sorcery card in your graveyard has flashback. The flashback cost is equal to that card's mana cost.$During your turn, each Lesson card in your graveyard has flashback {1}.| +Jet, Freedom Fighter|Avatar: The Last Airbender|229|U|{2}{R/W}{R/W}{R/W}|Legendary Creature - Human Rebel Ally|3|1|When Jet enters, he deals damage equal to the number of creatures you control to target creature an opponent controls.$When Jet dies, put a +1/+1 counter on each of up to two target creatures.| Katara, the Fearless|Avatar: The Last Airbender|230|R|{G}{W}{U}|Legendary Creature - Human Warrior Ally|3|3|If a triggered ability of an Ally you control triggers, that ability triggers an additional time.| Katara, Water Tribe's Hope|Avatar: The Last Airbender|231|R|{2}{W}{U}{U}|Legendary Creature - Human Warrior Ally|3|3|Vigilance$When Katara enters, create a 1/1 white Ally creature token.$Waterbend {X}: Creatures you control have base power and toughness X/X until end of turn. X can't be 0. Activate only during your turn.| The Lion-Turtle|Avatar: The Last Airbender|232|R|{1}{G}{U}|Legendary Creature - Elder Cat Turtle|3|6|Vigilance, reach$When The Lion-Turtle enters, you gain 3 life.$The Lion-Turtle can't attack or block unless there are three or more Lesson cards in your graveyard.${T}: Add one mana of any color.| @@ -59919,6 +59935,7 @@ Toph, the First Metalbender|Avatar: The Last Airbender|247|R|{1}{R}{G}{W}|Legend Uncle Iroh|Avatar: The Last Airbender|248|U|{1}{R/G}{R/G}|Legendary Creature - Human Noble Ally|4|2|Firebending 1$Lesson spells you cast cost {1} less to cast.| Vindictive Warden|Avatar: The Last Airbender|249|C|{2}{B/R}|Creature - Human Soldier|2|3|Menace$Firebending 1${3}: This creature deals 1 damage to each opponent.| White Lotus Reinforcements|Avatar: The Last Airbender|251|U|{1}{G}{W}|Creature - Human Soldier Ally|2|3|Vigilance$Other Allies you control get +1/+1.| +Zhao, Ruthless Admiral|Avatar: The Last Airbender|252|U|{2}{B/R}{B/R}|Legendary Creature - Human Soldier|3|4|Firebending 2$Whenever you sacrifice another permanent, creatures you control get +1/+0 until end of turn.| Zuko, Conflicted|Avatar: The Last Airbender|253|R|{B}{R}|Legendary Creature - Human Rogue|2|3|At the beginning of your first main phase, choose one that hasn't been chosen and you lose 2 life --$* Draw a card.$* Put a +1/+1 counter on Zuko.$* Add {R}.$* Exile Zuko, then return him to the battlefield under an opponent's control.| Barrels of Blasting Jelly|Avatar: The Last Airbender|254|C|{1}|Artifact|||{1}: Add one mana of any color. Activate only once each turn.${5}, {T}, Sacrifice this artifact: It deals 5 damage to target creature.| Bender's Waterskin|Avatar: The Last Airbender|255|C|{3}|Artifact|||Untap this artifact during each other player's untap step.${T}: Add one mana of any color.| @@ -59944,6 +59961,8 @@ Swamp|Avatar: The Last Airbender|294|C||Basic Land - Swamp|||({T}: Add {B}.)| Mountain|Avatar: The Last Airbender|295|C||Basic Land - Mountain|||({T}: Add {R}.)| Forest|Avatar: The Last Airbender|296|C||Basic Land - Forest|||({T}: Add {G}.)| Fated Firepower|Avatar: The Last Airbender|297|M|{X}{R}{R}{R}|Enchantment|||Flash$This enchantment enters with X fire counters on it.$If a source you control would deal damage to an opponent or a permanent an opponent controls, it deals that much damage plus an amount of damage equal to the number of fire counters on this enchantment instead.| +Aang, Swift Savior|Avatar: The Last Airbender|298|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| +Aang and La, Ocean's Fury|Avatar: The Last Airbender|298|R||Legendary Creature - Avatar Spirit Ally|5|5|Reach, trample$Whenever Aang and La attack, put a +1/+1 counter on each tapped creature you control.| Fire Nation Attacks|Avatar: The Last Airbender|299|U|{4}{R}|Instant|||Create two 2/2 red Soldier creature tokens with firebending 1.$Flashback {8}{R}| Azula, Cunning Usurper|Avatar: The Last Airbender|303|R|{2}{U}{B}{B}|Legendary Creature - Human Noble Rogue|4|4|Firebending 2$When Azula enters, target opponent exiles a nontoken creature they control, then they exile a nonland card from their graveyard.$During your turn, you may cast cards exiled with Azula and you may cast them as though they had flash. Mana of any type can be spent to cast those spells.| Aang, at the Crossroads|Avatar: The Last Airbender|304|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| @@ -59979,6 +59998,8 @@ Firebending Student|Avatar: The Last Airbender|342|R|{1}{R}|Creature - Human Mon Redirect Lightning|Avatar: The Last Airbender|343|R|{R}|Instant - Lesson|||As an additional cost to cast this spell, pay 5 life or pay {2}.$Change the target of target spell or ability with a single target.| Aang, at the Crossroads|Avatar: The Last Airbender|346|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| Aang, Destined Savior|Avatar: The Last Airbender|346|R||Legendary Creature - Avatar Ally|4|4|Flying$Land creatures you control have vigilance.$At the beginning of combat on your turn, earthbend 2.| +Aang, Swift Savior|Avatar: The Last Airbender|347|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| +Aang and La, Ocean's Fury|Avatar: The Last Airbender|347|R||Legendary Creature - Avatar Spirit Ally|5|5|Reach, trample$Whenever Aang and La attack, put a +1/+1 counter on each tapped creature you control.| Bumi, Unleashed|Avatar: The Last Airbender|348|M|{3}{R}{G}|Legendary Creature - Human Noble Ally|5|4|Trample$When Bumi enters, earthbend 4.$Whenever Bumi deals combat damage to a player, untap all lands you control. After this phase, there is an additional combat phase. Only land creatures can attack during that combat phase.| Iroh, Grand Lotus|Avatar: The Last Airbender|349|R|{3}{G}{U}{R}|Legendary Creature - Human Noble Ally|5|5|Firebending 2$During your turn, each non-Lesson instant and sorcery card in your graveyard has flashback. The flashback cost is equal to that card's mana cost.$During your turn, each Lesson card in your graveyard has flashback {1}.| Katara, the Fearless|Avatar: The Last Airbender|350|R|{G}{W}{U}|Legendary Creature - Human Warrior Ally|3|3|If a triggered ability of an Ally you control triggers, that ability triggers an additional time.| @@ -59991,6 +60012,8 @@ The Rise of Sozin|Avatar: The Last Airbender|356|M|{4}{B}{B}|Enchantment - Saga| Fire Lord Sozin|Avatar: The Last Airbender|356|M||Legendary Creature - Human Noble|5|5|Menace, firebending 3$Whenever Fire Lord Sozin deals combat damage to a player, you may pay {X}. When you do, put any number of target creature cards with total mana value X or less from that player's graveyard onto the battlefield under your control.| The Legend of Roku|Avatar: The Last Airbender|357|M|{2}{R}{R}|Enchantment - Saga|||(As this Saga enters and after your draw$step, add a lore counter.)$I -- Exile the top three cards of your library. Until the end of your next turn, you may play those cards.$II -- Add one mana of any color.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| Avatar Roku|Avatar: The Last Airbender|357|M||Legendary Creature - Avatar|4|4|Firebending 4${8}: Create a 4/4 red Dragon creature token with flying and firebending 4.| +Aang, Swift Savior|Avatar: The Last Airbender|359|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| +Aang and La, Ocean's Fury|Avatar: The Last Airbender|359|R||Legendary Creature - Avatar Spirit Ally|5|5|Reach, trample$Whenever Aang and La attack, put a +1/+1 counter on each tapped creature you control.| Fire Lord Zuko|Avatar: The Last Airbender|360|R|{R}{W}{B}|Legendary Creature - Human Noble Ally|2|4|Firebending X, where X is Fire Lord Zuko's power.$Whenever you cast a spell from exile and whenever a permanent you control enters from exile, put a +1/+1 counter on each creature you control.| Katara, the Fearless|Avatar: The Last Airbender|361|R|{G}{W}{U}|Legendary Creature - Human Warrior Ally|3|3|If a triggered ability of an Ally you control triggers, that ability triggers an additional time.| Toph, the First Metalbender|Avatar: The Last Airbender|362|R|{1}{R}{G}{W}|Legendary Creature - Human Warrior Ally|3|3|Nontoken artifacts you control are lands in addition to their other types.$At the beginning of your end step, earthbend 2.| @@ -59999,10 +60022,12 @@ Aang, Master of Elements|Avatar: The Last Airbender|363|M||Legendary Creature - Airbender Ascension|Avatar: The Last Airbender|364|R|{1}{W}|Enchantment|||When this enchantment enters, airbend up to one target creature.$Whenever a creature you control enters, put a quest counter on this enchantment.$At the beginning of your end step, if this enchantment has four or more quest counters on it, exile up to one target creature you control, then return it to the battlefield under its owner's control.| Hakoda, Selfless Commander|Avatar: The Last Airbender|366|R|{3}{W}|Legendary Creature - Human Warrior Ally|3|5|Vigilance$You may look at the top card of your library any time.$You may cast Ally spells from the top of your library.$Sacrifice Hakoda: Creatures you control get +0/+5 and gain indestructible until end of turn.| The Mechanist, Aerial Artisan|Avatar: The Last Airbender|369|R|{2}{U}|Legendary Creature - Human Artificer Ally|1|3|Whenever you cast a noncreature spell, create a Clue token.${T}: Until end of turn, target artifact token you control becomes a 3/1 Construct artifact creature with flying.| +Spirit Water Revival|Avatar: The Last Airbender|370|R|{1}{U}{U}|Sorcery|||As an additional cost to cast this spell, you may waterbend {6}.$Draw two cards. If this spell's additional cost was paid, instead shuffle your graveyard into your library, draw seven cards, and you have no maximum hand size for the rest of the game.$Exile Spirit Water Revival.| Ty Lee, Chi Blocker|Avatar: The Last Airbender|371|R|{2}{U}|Legendary Creature - Human Performer Ally|2|1|Flash$Prowess$When Ty Lee enters, tap up to one target creature. It doesn't untap during its controller's untap step for as long as you control Ty Lee.| Boiling Rock Rioter|Avatar: The Last Airbender|372|R|{2}{B}|Creature - Human Rogue Ally|3|3|Firebending 1$Tap an untapped Ally you control: Exile target card from a graveyard.$Whenever this creature attacks, you may cast an Ally spell from among cards you own exiled with this creature.| Day of Black Sun|Avatar: The Last Airbender|373|R|{X}{B}{B}|Sorcery|||Each creature with mana value X or less loses all abilities until end of turn. Destroy those creatures.| Earth King's Lieutenant|Avatar: The Last Airbender|380|R|{G}{W}|Creature - Human Soldier Ally|1|1|Trample$When this creature enters, put a +1/+1 counter on each other Ally creature you control.$Whenever another Ally you control enters, put a +1/+1 counter on this creature.| +Iroh, Tea Master|Avatar: The Last Airbender|381|R|{1}{R}{W}|Legendary Creature - Human Citizen Ally|2|2|When Iroh enters, create a Food token.$At the beginning of combat on your turn, you may have target opponent gain control of target permanent you control. When you do, create a 1/1 white Ally creature token. Put a +1/+1 counter on that token for each permanent you own that your opponents control.| Sokka, Bold Boomeranger|Avatar: The Last Airbender|383|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.| Planetarium of Wan Shi Tong|Avatar: The Last Airbender|385|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| Secret Tunnel|Avatar: The Last Airbender|392|R||Land - Cave|||This land can't be blocked.${T}: Add {C}.${4}, {T}: Two target creatures you control that share a creature type can't be blocked this turn.| -- 2.47.2 From b915d63787d2930a23ed10cf28bd5300872b6718 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 1 Nov 2025 16:56:59 -0400 Subject: [PATCH 045/261] [TLE] update reprints --- Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java | 6 ++++++ Utils/mtg-cards-data.txt | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index c265cea16af..9603db89df8 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -39,6 +39,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Appa, Aang's Companion", 268, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Arcane Signet", 315, Rarity.RARE, mage.cards.a.ArcaneSignet.class)); cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 130, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class)); + cards.add(new SetCardInfo("Blasphemous Act", 26, Rarity.MYTHIC, mage.cards.b.BlasphemousAct.class)); cards.add(new SetCardInfo("Bribery", 10, Rarity.MYTHIC, mage.cards.b.Bribery.class)); cards.add(new SetCardInfo("Brought Back", 1, Rarity.MYTHIC, mage.cards.b.BroughtBack.class)); cards.add(new SetCardInfo("Bumi, Eclectic Earthbender", 248, Rarity.RARE, mage.cards.b.BumiEclecticEarthbender.class)); @@ -48,6 +49,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Dark Depths", 56, Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); cards.add(new SetCardInfo("Deny Entry", 222, Rarity.COMMON, mage.cards.d.DenyEntry.class)); cards.add(new SetCardInfo("Descendants' Path", 167, Rarity.RARE, mage.cards.d.DescendantsPath.class)); + cards.add(new SetCardInfo("Dockside Extortionist", 28, Rarity.MYTHIC, mage.cards.d.DocksideExtortionist.class)); cards.add(new SetCardInfo("Dragon Moose", 235, Rarity.COMMON, mage.cards.d.DragonMoose.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dragon Moose", 278, Rarity.COMMON, mage.cards.d.DragonMoose.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earthbending Student", 249, Rarity.UNCOMMON, mage.cards.e.EarthbendingStudent.class)); @@ -97,6 +99,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 295, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 296, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mystic Remora", 16, Rarity.MYTHIC, mage.cards.m.MysticRemora.class)); + cards.add(new SetCardInfo("Noxious Gearhulk", 25, Rarity.MYTHIC, mage.cards.n.NoxiousGearhulk.class)); cards.add(new SetCardInfo("Path to Redemption", 271, Rarity.COMMON, mage.cards.p.PathToRedemption.class)); cards.add(new SetCardInfo("Plains", 297, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 298, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); @@ -121,6 +124,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 219, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 274, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sol Ring", 316, Rarity.RARE, mage.cards.s.SolRing.class)); + cards.add(new SetCardInfo("Standstill", 19, Rarity.MYTHIC, mage.cards.s.Standstill.class)); + cards.add(new SetCardInfo("Sundial of the Infinite", 55, Rarity.MYTHIC, mage.cards.s.SundialOfTheInfinite.class)); cards.add(new SetCardInfo("Swiftfoot Boots", 317, Rarity.RARE, mage.cards.s.SwiftfootBoots.class)); cards.add(new SetCardInfo("The Cabbage Merchant", 134, Rarity.RARE, mage.cards.t.TheCabbageMerchant.class)); cards.add(new SetCardInfo("The Great Henge", 41, Rarity.MYTHIC, mage.cards.t.TheGreatHenge.class)); @@ -131,6 +136,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Thriving Isle", 263, Rarity.COMMON, mage.cards.t.ThrivingIsle.class)); cards.add(new SetCardInfo("Thriving Moor", 264, Rarity.COMMON, mage.cards.t.ThrivingMoor.class)); cards.add(new SetCardInfo("Toph, Earthbending Master", 145, Rarity.MYTHIC, mage.cards.t.TophEarthbendingMaster.class)); + cards.add(new SetCardInfo("Training Grounds", 20, Rarity.MYTHIC, mage.cards.t.TrainingGrounds.class)); cards.add(new SetCardInfo("Tundra Wall", 220, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tundra Wall", 275, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Turtle-Seals", 226, Rarity.COMMON, mage.cards.t.TurtleSeals.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 02d9f4126a6..1d3c6e9b4a8 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -60340,13 +60340,19 @@ Bribery|Avatar: The Last Airbender Eternal|10|M|{3}{U}{U}|Sorcery|||Search targe Force of Negation|Avatar: The Last Airbender Eternal|13|M|{1}{U}{U}|Instant|||If it's not your turn, you may exile a blue card from your hand rather than pay this spell's mana cost.$Counter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.| Mystic Remora|Avatar: The Last Airbender Eternal|16|M|{U}|Enchantment|||Cumulative upkeep {1}$Whenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}.| Prosperity|Avatar: The Last Airbender Eternal|17|M|{X}{U}|Sorcery|||Each player draws X cards.| +Standstill|Avatar: The Last Airbender Eternal|19|M|{1}{U}|Enchantment|||When a player casts a spell, sacrifice this enchantment. If you do, each of that player's opponents draws three cards.| +Training Grounds|Avatar: The Last Airbender Eternal|20|M|{U}|Enchantment|||Activated abilities of creatures you control cost {2} less to activate. This effect can't reduce the mana in that cost to less than one mana.| Cruel Tutor|Avatar: The Last Airbender Eternal|24|M|{2}{B}|Sorcery|||Search your library for a card, then shuffle and put that card on top. You lose 2 life.| +Noxious Gearhulk|Avatar: The Last Airbender Eternal|25|M|{4}{B}{B}|Artifact Creature - Construct|5|4|Menace$When this creature enters, you may destroy another target creature. If a creature is destroyed this way, you gain life equal to its toughness.| +Blasphemous Act|Avatar: The Last Airbender Eternal|26|M|{8}{R}|Sorcery|||This spell costs {1} less to cast for each creature on the battlefield.$Blasphemous Act deals 13 damage to each creature.| +Dockside Extortionist|Avatar: The Last Airbender Eternal|28|M|{1}{R}|Creature - Goblin Pirate|1|2|When this creature enters, create X Treasure tokens, where X is the number of artifacts and enchantments your opponents control.| Mirrorwing Dragon|Avatar: The Last Airbender Eternal|33|M|{3}{R}{R}|Creature - Dragon|4|5|Flying$Whenever a player casts an instant or sorcery spell that targets only this creature, that player copies that spell for each other creature they control that the spell could target. Each copy targets a different one of those creatures.| The Great Henge|Avatar: The Last Airbender Eternal|41|M|{7}{G}{G}|Legendary Artifact|||This spell costs {X} less to cast, where X is the greatest power among creatures you control.${T}: Add {G}{G}. You gain 2 life.$Whenever a nontoken creature you control enters, put a +1/+1 counter on it and draw a card.| Heroic Intervention|Avatar: The Last Airbender Eternal|43|M|{1}{G}|Instant|||Permanents you control gain hexproof and indestructible until end of turn.| Rites of Flourishing|Avatar: The Last Airbender Eternal|45|M|{2}{G}|Enchantment|||At the beginning of each player's draw step, that player draws an additional card.$Each player may play an additional land on each of their turns.| Eladamri's Call|Avatar: The Last Airbender Eternal|48|M|{G}{W}|Instant|||Search your library for a creature card, reveal that card, put it into your hand, then shuffle.| Rhys the Redeemed|Avatar: The Last Airbender Eternal|52|M|{G/W}|Legendary Creature - Elf Warrior|1|1|{2}{G/W}, {T}: Create a 1/1 green and white Elf Warrior creature token.${4}{G/W}{G/W}, {T}: For each creature token you control, create a token that's a copy of that creature.| +Sundial of the Infinite|Avatar: The Last Airbender Eternal|55|M|{2}|Artifact|||{1}, {T}: End the turn. Activate only during your turn.| Dark Depths|Avatar: The Last Airbender Eternal|56|M||Legendary Snow Land|||Dark Depths enters with ten ice counters on it.${3}: Remove an ice counter from Dark Depths.$When Dark Depths has no ice counters on it, sacrifice it. If you do, create Marit Lage, a legendary 20/20 black Avatar creature token with flying and indestructible.| Valakut, the Molten Pinnacle|Avatar: The Last Airbender Eternal|61|M||Land|||This land enters tapped.$Whenever a Mountain you control enters, if you control at least five other Mountains, you may have this land deal 3 damage to any target.${T}: Add {R}.| Katara's Reversal|Avatar: The Last Airbender Eternal|63|R|{2}{U}{U}|Instant|||Counter up to four target spells and/or abilities.$Untap up to four target artifacts and/or creatures.| -- 2.47.2 From 639944d796b45cc210125ffd19792209a3957594 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 1 Nov 2025 16:58:11 -0400 Subject: [PATCH 046/261] [TLA] Implement Mai, Jaded Edge --- Mage.Sets/src/mage/cards/m/MaiJadedEdge.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MaiJadedEdge.java diff --git a/Mage.Sets/src/mage/cards/m/MaiJadedEdge.java b/Mage.Sets/src/mage/cards/m/MaiJadedEdge.java new file mode 100644 index 00000000000..46a603d6ed9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MaiJadedEdge.java @@ -0,0 +1,48 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.ExhaustAbility; +import mage.abilities.keyword.ProwessAbility; +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 java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MaiJadedEdge extends CardImpl { + + public MaiJadedEdge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Prowess + this.addAbility(new ProwessAbility()); + + // Exhaust -- {3}: Put a double strike counter on Mai. + this.addAbility(new ExhaustAbility( + new AddCountersSourceEffect(CounterType.DOUBLE_STRIKE.createInstance()), new GenericManaCost(3) + )); + } + + private MaiJadedEdge(final MaiJadedEdge card) { + super(card); + } + + @Override + public MaiJadedEdge copy() { + return new MaiJadedEdge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index f2b7e52430d..3b3e1935abe 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -124,6 +124,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Leaves from the Vine", 185, Rarity.UNCOMMON, mage.cards.l.LeavesFromTheVine.class)); cards.add(new SetCardInfo("Lightning Strike", 146, Rarity.COMMON, mage.cards.l.LightningStrike.class)); cards.add(new SetCardInfo("Long Feng, Grand Secretariat", 233, Rarity.UNCOMMON, mage.cards.l.LongFengGrandSecretariat.class)); + cards.add(new SetCardInfo("Mai, Jaded Edge", 147, Rarity.UNCOMMON, mage.cards.m.MaiJadedEdge.class)); cards.add(new SetCardInfo("Master Pakku", 63, Rarity.UNCOMMON, mage.cards.m.MasterPakku.class)); cards.add(new SetCardInfo("Master Piandao", 28, Rarity.UNCOMMON, mage.cards.m.MasterPiandao.class)); cards.add(new SetCardInfo("Merchant of Many Hats", 110, Rarity.COMMON, mage.cards.m.MerchantOfManyHats.class)); -- 2.47.2 From 621e7cd454147ba842aa6603cf74582c32f51dd8 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 1 Nov 2025 16:59:32 -0400 Subject: [PATCH 047/261] [TLA] Implement United Front --- Mage.Sets/src/mage/cards/u/UnitedFront.java | 38 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 39 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/u/UnitedFront.java diff --git a/Mage.Sets/src/mage/cards/u/UnitedFront.java b/Mage.Sets/src/mage/cards/u/UnitedFront.java new file mode 100644 index 00000000000..11f63311ba4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UnitedFront.java @@ -0,0 +1,38 @@ +package mage.cards.u; + +import mage.abilities.dynamicvalue.common.GetXValue; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.permanent.token.AllyToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UnitedFront extends CardImpl { + + public UnitedFront(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{W}{W}"); + + // Create X 1/1 white Ally creature tokens, then put a +1/+1 counter on each creature you control. + this.getSpellAbility().addEffect(new CreateTokenEffect(new AllyToken(), GetXValue.instance)); + this.getSpellAbility().addEffect(new AddCountersAllEffect( + CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE + ).concatBy(", then")); + } + + private UnitedFront(final UnitedFront card) { + super(card); + } + + @Override + public UnitedFront copy() { + return new UnitedFront(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 3b3e1935abe..8690803e025 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -197,6 +197,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Turtle-Duck", 200, Rarity.COMMON, mage.cards.t.TurtleDuck.class)); cards.add(new SetCardInfo("Ty Lee, Artful Acrobat", 158, Rarity.UNCOMMON, mage.cards.t.TyLeeArtfulAcrobat.class)); cards.add(new SetCardInfo("Uncle Iroh", 248, Rarity.UNCOMMON, mage.cards.u.UncleIroh.class)); + cards.add(new SetCardInfo("United Front", 39, Rarity.MYTHIC, mage.cards.u.UnitedFront.class)); cards.add(new SetCardInfo("Vindictive Warden", 249, Rarity.COMMON, mage.cards.v.VindictiveWarden.class)); cards.add(new SetCardInfo("War Balloon", 159, Rarity.UNCOMMON, mage.cards.w.WarBalloon.class)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); -- 2.47.2 From 5e5b28151adf6f3b253b41dc1f1571723b3b4418 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 1 Nov 2025 17:00:19 -0400 Subject: [PATCH 048/261] [TLA] Implement Treetop Freedom Fighters --- .../mage/cards/t/TreetopFreedomFighters.java | 44 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 45 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TreetopFreedomFighters.java diff --git a/Mage.Sets/src/mage/cards/t/TreetopFreedomFighters.java b/Mage.Sets/src/mage/cards/t/TreetopFreedomFighters.java new file mode 100644 index 00000000000..3d1a1bffcf9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TreetopFreedomFighters.java @@ -0,0 +1,44 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.AllyToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TreetopFreedomFighters extends CardImpl { + + public TreetopFreedomFighters(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.REBEL); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // When this creature enters, create a 1/1 white Ally creature token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new AllyToken()))); + } + + private TreetopFreedomFighters(final TreetopFreedomFighters card) { + super(card); + } + + @Override + public TreetopFreedomFighters copy() { + return new TreetopFreedomFighters(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 8690803e025..0ddecdb293b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -192,6 +192,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Toph, the First Metalbender", 247, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Toph, the First Metalbender", 353, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Toph, the First Metalbender", 362, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Treetop Freedom Fighters", 156, Rarity.COMMON, mage.cards.t.TreetopFreedomFighters.class)); cards.add(new SetCardInfo("True Ancestry", 199, Rarity.UNCOMMON, mage.cards.t.TrueAncestry.class)); cards.add(new SetCardInfo("Tundra Tank", 121, Rarity.UNCOMMON, mage.cards.t.TundraTank.class)); cards.add(new SetCardInfo("Turtle-Duck", 200, Rarity.COMMON, mage.cards.t.TurtleDuck.class)); -- 2.47.2 From 654dda8f74070f3ec5bcdcee8d7b341ad4f041cb Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 1 Nov 2025 17:03:12 -0400 Subject: [PATCH 049/261] [TLA] Implement Suki, Courageous Rescuer --- .../mage/cards/s/SukiCourageousRescuer.java | 54 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 55 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SukiCourageousRescuer.java diff --git a/Mage.Sets/src/mage/cards/s/SukiCourageousRescuer.java b/Mage.Sets/src/mage/cards/s/SukiCourageousRescuer.java new file mode 100644 index 00000000000..ffbbf87e5f6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SukiCourageousRescuer.java @@ -0,0 +1,54 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.LeavesBattlefieldAllTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; +import mage.game.permanent.token.AllyToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SukiCourageousRescuer extends CardImpl { + + public SukiCourageousRescuer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Other creatures you control get +1/+0. + this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( + 1, 0, Duration.WhileOnBattlefield, true + ))); + + // Whenever another permanent you control leaves the battlefield during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn. + this.addAbility(new LeavesBattlefieldAllTriggeredAbility( + new CreateTokenEffect(new AllyToken()), StaticFilters.FILTER_CONTROLLED_ANOTHER_PERMANENT + ).withTriggerCondition(MyTurnCondition.instance).setTriggersLimitEachTurn(1)); + } + + private SukiCourageousRescuer(final SukiCourageousRescuer card) { + super(card); + } + + @Override + public SukiCourageousRescuer copy() { + return new SukiCourageousRescuer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 0ddecdb293b..88d27701b47 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -176,6 +176,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Sozin's Comet", 154, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sozin's Comet", 309, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sozin's Comet", 332, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Suki, Courageous Rescuer", 37, Rarity.RARE, mage.cards.s.SukiCourageousRescuer.class)); cards.add(new SetCardInfo("Suki, Kyoshi Warrior", 243, Rarity.UNCOMMON, mage.cards.s.SukiKyoshiWarrior.class)); cards.add(new SetCardInfo("Sun Warriors", 244, Rarity.UNCOMMON, mage.cards.s.SunWarriors.class)); cards.add(new SetCardInfo("Swamp", 284, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 064c10259081a6b824c518a9565c57dbf7c987f6 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Sun, 2 Nov 2025 00:42:12 +0400 Subject: [PATCH 050/261] GUI, game: improved stack's hint with targets list (added player name and sorted by it); --- Mage.Common/src/main/java/mage/view/CardView.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Mage.Common/src/main/java/mage/view/CardView.java b/Mage.Common/src/main/java/mage/view/CardView.java index 749488b8cf3..a1a41e0806a 100644 --- a/Mage.Common/src/main/java/mage/view/CardView.java +++ b/Mage.Common/src/main/java/mage/view/CardView.java @@ -27,6 +27,7 @@ import mage.counters.Counter; import mage.counters.CounterType; import mage.designations.Designation; import mage.filter.FilterMana; +import mage.game.ControllableOrOwnerable; import mage.game.Game; import mage.game.command.Dungeon; import mage.game.command.Emblem; @@ -764,7 +765,11 @@ public class CardView extends SimpleCardView { String info; MageObject targetObject = game.getObject(t); if (targetObject != null) { - info = targetObject.getIdName(); + Player player = null; + if (targetObject instanceof ControllableOrOwnerable) { + player = game.getPlayer(((ControllableOrOwnerable) targetObject).getControllerOrOwnerId()); + } + info = (player == null ? "" : player.getName() + ": ") + targetObject.getIdName(); } else { Player targetPlayer = game.getPlayer(t); if (targetPlayer != null) { -- 2.47.2 From a0bdfda91273bf24f74916c968589199a28d642c Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Sun, 2 Nov 2025 01:07:22 +0400 Subject: [PATCH 051/261] cheats: fixed AI naming, improved cheat commands compatibility: - added additional aliases for Human (me) and Computer (opponent, ai); - now same cheat command will be work in real, test, duel or multiplayer games (Computer/Human); - now same cheat command will be work in human only games; - fixed wrong/random AI opponent selection in multiplayer games; - fixed wrong opponent selection after first opponent's loose in multiplayer games; --- .../java/mage/client/table/TablesPanel.java | 8 +-- .../src/main/java/mage/utils/SystemUtil.java | 62 +++++++++++++++---- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java index 0cb2e6e4242..9030054dc6a 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java @@ -1700,7 +1700,7 @@ public class TablesPanel extends javax.swing.JPanel { MatchOptions options = new MatchOptions(gameName, gameType, multiPlayer); options.getPlayerTypes().add(PlayerType.HUMAN); options.getPlayerTypes().add(aiType); - for (int i=2 ; i < numPlayers ; i++) { + for (int i = 2; i < numPlayers; i++) { options.getPlayerTypes().add(aiType); } options.setDeckType("Variant Magic - Freeform Commander"); @@ -1719,9 +1719,9 @@ public class TablesPanel extends javax.swing.JPanel { table = SessionHandler.createTable(roomId, options); SessionHandler.joinTable(roomId, table.getTableId(), "Human", PlayerType.HUMAN, 1, testDeck, ""); - SessionHandler.joinTable(roomId, table.getTableId(), "Computer", aiType, 1, testDeck, ""); - for (int i=2 ; i < numPlayers ; i++) { - SessionHandler.joinTable(roomId, table.getTableId(), "Computer" + i, aiType, 1, testDeck, ""); + SessionHandler.joinTable(roomId, table.getTableId(), "Computer" + (multiPlayer ? " 2" : ""), aiType, 1, testDeck, ""); + for (int i = 2; i < numPlayers; i++) { + SessionHandler.joinTable(roomId, table.getTableId(), "Computer " + (i + 1), aiType, 1, testDeck, ""); } SessionHandler.startMatch(roomId, table.getTableId()); } catch (HeadlessException ex) { diff --git a/Mage.Common/src/main/java/mage/utils/SystemUtil.java b/Mage.Common/src/main/java/mage/utils/SystemUtil.java index c8144e49def..17124d7a084 100644 --- a/Mage.Common/src/main/java/mage/utils/SystemUtil.java +++ b/Mage.Common/src/main/java/mage/utils/SystemUtil.java @@ -601,14 +601,13 @@ public final class SystemUtil { continue; } - Optional playerOptional = findPlayer(game, command.player); - if (!playerOptional.isPresent()) { + Player player = findPlayer(game, command.player, feedbackPlayer); + if (player == null) { String mes = String.format("Unknown player: %s", line); errorsList.add(mes); logger.warn(mes); continue; } - Player player = playerOptional.get(); // SPECIAL token/emblem call (without SET name) if ("token".equalsIgnoreCase(command.zone)) { @@ -860,17 +859,54 @@ public final class SystemUtil { return false; } - /** - * Find player by name. - * - * @param game - * @param name - * @return - */ - private static Optional findPlayer(Game game, String name) { - return game.getPlayers().values().stream() - .filter(player -> player.getName().equals(name)).findFirst(); + private static Player findPlayer(Game game, String needName, Player feedbackPlayer) { + // real names + Player res = game.getPlayerList().stream() + .map(game::getPlayer) + .filter(Objects::nonNull) + .filter(player -> player.getName().equals(needName)) + .findFirst() + .orElse(null); + // test names - cheat commands will be compatible in both modes (quick test and normal) + if (res == null) { + switch (needName.toLowerCase(Locale.ENGLISH)) { + case "me": + case "human": + case "human 1": + res = feedbackPlayer; + break; + case "opponent": + case "opponent 1": + case "computer": + case "computer 1": // multiplayer game uses Computer 2+ naming + case "ai": + case "ai 1": + // try AI + res = game.getPlayerList().stream() + .map(game::getPlayer) + .filter(Objects::nonNull) + .filter(Player::isInGame) + .filter(Player::isComputer) + .findFirst() + .orElse(null); + if (res == null) { + // try opponent (human only games) + res = game.getOpponents(feedbackPlayer.getId(), true).stream() + .map(game::getPlayer) + .filter(Objects::nonNull) + .filter(Player::isInGame) + .findFirst() + .orElse(null); + } + break; + default: + // raise error message due unknown player name + break; + } + } + + return res; } public static String sanitize(String input) { -- 2.47.2 From 9ba96ddf11405d763a8a80254b3531b866d0d6f2 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Sat, 1 Nov 2025 20:00:03 -0400 Subject: [PATCH 052/261] Make Bebop and Rocksteady's discard optional. --- Mage.Sets/src/mage/cards/b/BebopAndRocksteady.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/b/BebopAndRocksteady.java b/Mage.Sets/src/mage/cards/b/BebopAndRocksteady.java index 198f5769582..2a9f7cfe058 100644 --- a/Mage.Sets/src/mage/cards/b/BebopAndRocksteady.java +++ b/Mage.Sets/src/mage/cards/b/BebopAndRocksteady.java @@ -32,7 +32,7 @@ public final class BebopAndRocksteady extends CardImpl { // Whenever Bebop & Rocksteady attacks or blocks, sacrifice a permanent unless you discard a card. this.addAbility(new AttacksOrBlocksTriggeredAbility(new DoIfCostPaid( null, new SacrificeControllerEffect(StaticFilters.FILTER_PERMANENT, 1, null), - new DiscardCardCost(), false), false + new DiscardCardCost(), true), false )); } -- 2.47.2 From ffb270eac71fabedc0083afd3195a48ce8b33235 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Sun, 2 Nov 2025 17:58:37 -0500 Subject: [PATCH 053/261] [TLA] Implement Bumi, Unleashed --- Mage.Sets/src/mage/cards/b/BumiUnleashed.java | 131 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 133 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BumiUnleashed.java diff --git a/Mage.Sets/src/mage/cards/b/BumiUnleashed.java b/Mage.Sets/src/mage/cards/b/BumiUnleashed.java new file mode 100644 index 00000000000..663f06b4641 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BumiUnleashed.java @@ -0,0 +1,131 @@ +package mage.cards.b; + +import java.util.UUID; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.UntapAllLandsControllerEffect; +import mage.abilities.effects.common.combat.CantAttackAllEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.constants.*; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.turn.TurnMod; +import mage.target.common.TargetControlledLandPermanent; + +/** + * + * @author Grath + */ +public final class BumiUnleashed extends CardImpl { + + public BumiUnleashed(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // When Bumi enters, earthbend 4. + Ability ability = new EntersBattlefieldTriggeredAbility(new EarthbendTargetEffect(4)); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability); + + // Whenever Bumi deals combat damage to a player, untap all lands you control. After this phase, there is an additional combat phase. Only land creatures can attack during that combat phase. + ability = new DealsCombatDamageToAPlayerTriggeredAbility(new UntapAllLandsControllerEffect(), false); + ability.addEffect(new BumiUnleashedEffect()); + this.addAbility(ability); + } + + private BumiUnleashed(final BumiUnleashed card) { + super(card); + } + + @Override + public BumiUnleashed copy() { + return new BumiUnleashed(this); + } +} + +//Based on LastNightTogetherEffect +class BumiUnleashedEffect extends OneShotEffect { + + BumiUnleashedEffect() { + super(Outcome.Benefit); + staticText = "After this main phase, there is an additional combat phase. Only land creatures can attack during that combat phase"; + } + + private BumiUnleashedEffect(final BumiUnleashedEffect effect) { + super(effect); + } + + @Override + public BumiUnleashedEffect copy() { + return new BumiUnleashedEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + // At the start of that combat, add a restriction effect preventing other creatures from attacking. + TurnMod combat = new TurnMod(game.getState().getActivePlayerId()).withExtraPhase(TurnPhase.COMBAT); + game.getState().getTurnMods().add(combat); + BumiUnleashedDelayedCantAttackAbility delayedTriggeredAbility = new BumiUnleashedDelayedCantAttackAbility(combat.getId()); + game.addDelayedTriggeredAbility(delayedTriggeredAbility, source); + return true; + } + +} + +class BumiUnleashedDelayedCantAttackAbility extends DelayedTriggeredAbility { + + private final UUID connectedTurnMod; + + BumiUnleashedDelayedCantAttackAbility(UUID connectedTurnMod) { + super(null, Duration.EndOfTurn); + FilterCreaturePermanent filterRestriction = new FilterCreaturePermanent(); + filterRestriction.add(Predicates.not(CardType.LAND.getPredicate())); + this.addEffect(new CantAttackAllEffect(Duration.EndOfCombat, filterRestriction)); + this.usesStack = false; // don't show this to the user + this.connectedTurnMod = connectedTurnMod; + } + + BumiUnleashedDelayedCantAttackAbility(BumiUnleashedDelayedCantAttackAbility ability) { + super(ability); + this.connectedTurnMod = ability.connectedTurnMod; + } + + @Override + public BumiUnleashedDelayedCantAttackAbility copy() { + return new BumiUnleashedDelayedCantAttackAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.PHASE_CHANGED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return (event.getType() == GameEvent.EventType.PHASE_CHANGED && this.connectedTurnMod.equals(event.getSourceId())); + } + + @Override + public String getRule() { + return "Only land creatures can attack during that combat phase"; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 88d27701b47..bb755470345 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -49,6 +49,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Beetle-Headed Merchants", 86, Rarity.COMMON, mage.cards.b.BeetleHeadedMerchants.class)); cards.add(new SetCardInfo("Bender's Waterskin", 255, Rarity.COMMON, mage.cards.b.BendersWaterskin.class)); cards.add(new SetCardInfo("Bumi Bash", 125, Rarity.COMMON, mage.cards.b.BumiBash.class)); + cards.add(new SetCardInfo("Bumi, Unleashed", 211, Rarity.MYTHIC, mage.cards.b.BumiUnleashed.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Bumi, Unleashed", 348, Rarity.MYTHIC, mage.cards.b.BumiUnleashed.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Buzzard-Wasp Colony", 88, Rarity.UNCOMMON, mage.cards.b.BuzzardWaspColony.class)); cards.add(new SetCardInfo("Cat-Gator", 91, Rarity.UNCOMMON, mage.cards.c.CatGator.class)); cards.add(new SetCardInfo("Cat-Owl", 212, Rarity.COMMON, mage.cards.c.CatOwl.class)); -- 2.47.2 From 852d1d435177b070d0c7b757132f312d1d64ddab Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:13:30 -0500 Subject: [PATCH 054/261] [TLA] update spoiler --- .../src/mage/sets/AvatarTheLastAirbender.java | 8 +++-- Utils/mtg-cards-data.txt | 35 +++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index bb755470345..689d81aa7f7 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -12,7 +12,7 @@ import java.util.List; */ public final class AvatarTheLastAirbender extends ExpansionSet { - private static final List unfinished = Arrays.asList("Aang's Iceberg", "Aang, Swift Savior", "Avatar Aang", "Flexible Waterbender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Invasion Submersible", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "Spirit Water Revival", "The Legend of Kuruk", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); + private static final List unfinished = Arrays.asList("Aang's Iceberg", "Aang, Swift Savior", "Avatar Aang", "Flexible Waterbender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Invasion Submersible", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "Spirit Water Revival", "The Legend of Kuruk", "The Unagi of Kyoshi Island", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); private static final AvatarTheLastAirbender instance = new AvatarTheLastAirbender(); public static AvatarTheLastAirbender getInstance() { @@ -178,7 +178,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Sozin's Comet", 154, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sozin's Comet", 309, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sozin's Comet", 332, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Suki, Courageous Rescuer", 37, Rarity.RARE, mage.cards.s.SukiCourageousRescuer.class)); + cards.add(new SetCardInfo("Suki, Courageous Rescuer", 368, Rarity.RARE, mage.cards.s.SukiCourageousRescuer.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Suki, Courageous Rescuer", 37, Rarity.RARE, mage.cards.s.SukiCourageousRescuer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Suki, Kyoshi Warrior", 243, Rarity.UNCOMMON, mage.cards.s.SukiKyoshiWarrior.class)); cards.add(new SetCardInfo("Sun Warriors", 244, Rarity.UNCOMMON, mage.cards.s.SunWarriors.class)); cards.add(new SetCardInfo("Swamp", 284, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); @@ -201,7 +202,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Turtle-Duck", 200, Rarity.COMMON, mage.cards.t.TurtleDuck.class)); cards.add(new SetCardInfo("Ty Lee, Artful Acrobat", 158, Rarity.UNCOMMON, mage.cards.t.TyLeeArtfulAcrobat.class)); cards.add(new SetCardInfo("Uncle Iroh", 248, Rarity.UNCOMMON, mage.cards.u.UncleIroh.class)); - cards.add(new SetCardInfo("United Front", 39, Rarity.MYTHIC, mage.cards.u.UnitedFront.class)); + cards.add(new SetCardInfo("United Front", 331, Rarity.MYTHIC, mage.cards.u.UnitedFront.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("United Front", 39, Rarity.MYTHIC, mage.cards.u.UnitedFront.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Vindictive Warden", 249, Rarity.COMMON, mage.cards.v.VindictiveWarden.class)); cards.add(new SetCardInfo("War Balloon", 159, Rarity.UNCOMMON, mage.cards.w.WarBalloon.class)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 1d3c6e9b4a8..444ff1c4e49 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59770,8 +59770,10 @@ Airbending Lesson|Avatar: The Last Airbender|8|C|{2}{W}|Instant - Lesson|||Airbe Appa, Loyal Sky Bison|Avatar: The Last Airbender|9|U|{4}{W}{W}|Legendary Creature - Bison Ally|4|4|Flying$Whenever Appa enters or attacks, choose one --$* Target creature you control gains flying until end of turn.$* Airbend another target nonland permanent you control..| Appa, Steadfast Guardian|Avatar: The Last Airbender|10|M|{2}{W}{W}|Legendary Creature - Bison Ally|3|4|Flash$Flying$When Appa enters, airbend any number of other target nonland permanents you control.$Whenever you cast a spell from exile, create a 1/1 white Ally creature token.| Avatar Enthusiasts|Avatar: The Last Airbender|11|C|{2}{W}|Creature - Human Peasant Ally|2|2|Whenever another Ally you control enters, put a +1/+1 counter on this creature.| +Avatar's Wrath|Avatar: The Last Airbender|12|R|{2}{W}{W}|Sorcery|||Choose up to one target creature, then airbend each other creature.$Until your next turn, your opponents can't cast spells from anywhere other than their hand.$Exile Avatar's Wrath.| Compassionate Healer|Avatar: The Last Airbender|13|C|{1}{W}|Creature - Human Cleric Ally|2|2|Whenever this creature becomes tapped, you gain 1 life and scry 1.| Fancy Footwork|Avatar: The Last Airbender|19|U|{2}{W}|Instant - Lesson|||Untap one or two target creatures. They each get +2/+2 until end of turn.| +Gather the White Lotus|Avatar: The Last Airbender|20|U|{4}{W}|Sorcery|||Create a 1/1 white Ally creature token for each Plains you control. Scry 2.| Glider Kids|Avatar: The Last Airbender|21|C|{2}{W}|Creature - Human Pilot Ally|2|3|Flying$When this creature enters, scry 1.| Glider Staff|Avatar: The Last Airbender|22|U|{2}{W}|Artifact - Equipment|||When this Equipment enters, airbend up to one target creature.$Equipped creature gets +1/+1 and has flying.$Equip {2}| Jeong Jeong's Deserters|Avatar: The Last Airbender|25|C|{1}{W}|Creature - Human Rebel Ally|1|2|When this creature enters, put a +1/+1 counter on target creature.| @@ -59816,6 +59818,7 @@ Spirit Water Revival|Avatar: The Last Airbender|73|R|{1}{U}{U}|Sorcery|||As an a Teo, Spirited Glider|Avatar: The Last Airbender|74|U|{3}{U}|Legendary Creature - Human Pilot Ally|1|4|Flying$Whenever one or more creatures you control with flying attack, draw a card, then discard a card. When you discard a nonland card this way, put a +1/+1 counter on target creature you control.| Tiger-Seal|Avatar: The Last Airbender|75|R|{U}|Creature - Cat Seal|3|3|Vigilance$At the beginning of your upkeep, tap this creature.$Whenever you draw your second card each turn, untap this creature.| Ty Lee, Chi Blocker|Avatar: The Last Airbender|76|R|{2}{U}|Legendary Creature - Human Performer Ally|2|1|Flash$Prowess$When Ty Lee enters, tap up to one target creature. It doesn't untap during its controller's untap step for as long as you control Ty Lee.| +The Unagi of Kyoshi Island|Avatar: The Last Airbender|77|R|{3}{U}{U}|Legendary Creature - Serpent|5|5|Flash$Ward--Waterbend {4}$Whenever an opponent draws their second card each turn, draw two cards.| Wan Shi Tong, Librarian|Avatar: The Last Airbender|78|M|{X}{U}{U}|Legendary Creature - Bird Spirit|1|1|Flash$Flying, vigilance$When Wan Shi Tong enters, put X +1/+1 counters on him. Then draw half X cards, rounded down.$Whenever an opponent searches their library, put a +1/+1 counter on Wan Shi Tong and draw a card.| Waterbending Lesson|Avatar: The Last Airbender|80|C|{3}{U}|Sorcery - Lesson|||Draw three cards. Then discard a card unless you waterbend {2}.| Watery Grasp|Avatar: The Last Airbender|82|C|{U}|Enchantment - Aura|||Enchant creature$Enchanted creature doesn't untap during its controller's untap step.$Waterbend {5}: Enchanted creature's owner shuffles it into their library.| @@ -59825,6 +59828,7 @@ Azula, On the Hunt|Avatar: The Last Airbender|85|U|{3}{B}|Legendary Creature - H Beetle-Headed Merchants|Avatar: The Last Airbender|86|C|{4}{B}|Creature - Human Citizen|5|4|Whenever this creature attacks, you may sacrifice another creature or artifact. If you do, draw a card and put a +1/+1 counter on this creature.| Boiling Rock Rioter|Avatar: The Last Airbender|87|R|{2}{B}|Creature - Human Rogue Ally|3|3|Firebending 1$Tap an untapped Ally you control: Exile target card from a graveyard.$Whenever this creature attacks, you may cast an Ally spell from among cards you own exiled with this creature.| Buzzard-Wasp Colony|Avatar: The Last Airbender|88|U|{3}{B}|Creature - Bird Insect|2|2|Flying$When this creature enters, you may sacrifice an artifact or creature. If you do, draw a card.$Whenever another creature you control dies, if it had counters on it, put its counters on this creature.| +Callous Inspector|Avatar: The Last Airbender|89|C|{B}|Creature - Human Soldier|1|1|Menace$When this creature dies, it deals 1 damage to you. Create a Clue token.| Cat-Gator|Avatar: The Last Airbender|91|U|{6}{B}|Creature - Fish Crocodile|3|2|Lifelink$When this creature enters, it deals damage equal to the number of Swamps you control to any target.| Corrupt Court Official|Avatar: The Last Airbender|92|C|{1}{B}|Creature - Human Advisor|1|1|When this creature enters, target opponent discards a card.| Dai Li Indoctrination|Avatar: The Last Airbender|93|C|{1}{B}|Sorcery - Lesson|||Choose one --$* Target opponent reveals their hand. You choose a nonland permanent card from it. That player discards that card.$* Earthbend 2.| @@ -59837,11 +59841,13 @@ Foggy Swamp Visions|Avatar: The Last Airbender|102|R|{1}{B}{B}|Sorcery|||As an a Heartless Act|Avatar: The Last Airbender|103|U|{1}{B}|Instant|||Choose one --$* Destroy target creature with no counters on it.$* Remove up to three counters from target creature.| Hog-Monkey|Avatar: The Last Airbender|104|C|{2}{B}|Creature - Boar Monkey|3|2|At the beginning of combat on your turn, target creature you control with a +1/+1 counter on it gains menace until end of turn.$Exhaust -- {5}: Put two +1/+1 counters on this creature.| June, Bounty Hunter|Avatar: The Last Airbender|106|U|{1}{B}|Legendary Creature - Human Mercenary|2|2|June can't be blocked as long as you've drawn two or more cards this turn.${1}, Sacrifice another creature: Create a Clue token. Activate only during your turn.| +Mai, Scornful Striker|Avatar: The Last Airbender|109|R|{1}{B}|Legendary Creature - Human Noble Ally|2|2|First strike$Whenever a player casts a noncreature spell, they lose 2 life.| Merchant of Many Hats|Avatar: The Last Airbender|110|C|{1}{B}|Creature - Human Peasant Ally|2|2|{2}{B}: Return this card from your graveyard to your hand.| Northern Air Temple|Avatar: The Last Airbender|111|U|{B}|Legendary Enchantment - Shrine|||When Northern Air Temple enters, each opponent loses X life and you gain X life, where X is the number of Shrines you control.$Whenever another Shrine you control enters, each opponent loses 1 life and you gain 1 life.| Ozai's Cruelty|Avatar: The Last Airbender|113|U|{2}{B}|Sorcery - Lesson|||Ozai's Cruelty deals 2 damage to target player. That player discards two cards.| The Rise of Sozin|Avatar: The Last Airbender|117|M|{4}{B}{B}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I -- Destroy all creatures.$II -- Choose a card name. Search target opponent's graveyard, hand, and library for up to four cards with that name and exile them. Then that player shuffles.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| Fire Lord Sozin|Avatar: The Last Airbender|117|M||Legendary Creature - Human Noble|5|5|Menace, firebending 3$Whenever Fire Lord Sozin deals combat damage to a player, you may pay {X}. When you do, put any number of target creature cards with total mana value X or less from that player's graveyard onto the battlefield under your control.| +Sold Out|Avatar: The Last Airbender|119|C|{3}{B}|Instant|||Exile target creature. If it was dealt damage this turn, create a Clue token.| Tundra Tank|Avatar: The Last Airbender|121|U|{2}{B}|Artifact - Vehicle|4|4|Firebending 1$When this Vehicle enters, target creature you control gains indestructible until end of turn.$Crew 1| Bumi Bash|Avatar: The Last Airbender|125|C|{3}{R}|Sorcery|||Choose one --$* Bumi Bash deals damage equal to the number of lands you control to target creature.$* Destroy target land creature or nonbasic land.| The Cave of Two Lovers|Avatar: The Last Airbender|126|U|{3}{R}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I -- Create two 1/1 white Ally creature tokens.$II -- Search your library for a Mountain or Cave card, reveal it, put it into your hand,$then shuffle.$III -- Earthbend 3.| @@ -59852,8 +59858,10 @@ Fated Firepower|Avatar: The Last Airbender|132|M|{X}{R}{R}{R}|Enchantment|||Flas Fire Nation Attacks|Avatar: The Last Airbender|133|U|{4}{R}|Instant|||Create two 2/2 red Soldier creature tokens with firebending 1.$Flashback {8}{R}| Fire Nation Cadets|Avatar: The Last Airbender|134|C|{R}|Creature - Human Soldier|1|2|This creature has firebending 2 as long as there's a Lesson card in your graveyard.${2}: This creature gets +1/+0 until end of turn.| Fire Sages|Avatar: The Last Airbender|136|U|{1}{R}|Creature - Human Cleric|2|2|Firebending 1${1}{R}{R}: Put a +1/+1 counter on this creature.| +Firebender Ascension|Avatar: The Last Airbender|137|R|{1}{R}|Enchantment|||When this enchantment enters, create a 2/2 red Soldier creature token with firebending 1.$Whenever a creature you control attacking causes a triggered ability of that creature to trigger, put a quest counter on this enchantment. Then if it has four or more quest counters on it, you may copy that ability. You may choose new targets for the copy.| Firebending Student|Avatar: The Last Airbender|139|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| How to Start a Riot|Avatar: The Last Airbender|140|C|{2}{R}|Instant - Lesson|||Target creature gains menace until end of turn.$Creatures target player controls get +2/+0 until end of turn.| +Jeong Jeong, the Deserter|Avatar: The Last Airbender|142|U|{2}{R}|Legendary Creature - Human Rebel Ally|2|3|Firebending 1$Exhaust -- {3}: Put a +1/+1 counter on Jeong Jeong. When you next cast a Lesson spell this turn, copy it and you may choose new targets for the copy.| Jet's Brainwashing|Avatar: The Last Airbender|143|U|{R}|Sorcery|||Kicker {3}$Target creature can't block this turn. If this spell was kicked, gain control of that creature until end of turn, untap it, and it gains haste until end of turn.$Create a Clue token.| The Last Agni Kai|Avatar: The Last Airbender|144|R|{1}{R}|Instant|||Target creature you control fights target creature an opponent controls. If the creature the opponent controls is dealt excess damage this way, add that much {R}.$Until end of turn, you don't lose unspent red mana as steps and phases end.| The Legend of Roku|Avatar: The Last Airbender|145|M|{2}{R}{R}|Enchantment - Saga|||(As this Saga enters and after your draw$step, add a lore counter.)$I -- Exile the top three cards of your library. Until the end of your next turn, you may play those cards.$II -- Add one mana of any color.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| @@ -59867,7 +59875,9 @@ Redirect Lightning|Avatar: The Last Airbender|151|R|{R}|Instant - Lesson|||As an Rough Rhino Cavalry|Avatar: The Last Airbender|152|C|{4}{R}|Creature - Human Mercenary|5|5|Firebending 2$Exhaust -- {8}: Put two +1/+1 counters on this creature. It gains trample until end of turn.| Solstice Revelations|Avatar: The Last Airbender|153|U|{2}{R}|Instant - Lesson|||Exile cards from the top of your library until you exile a nonland card. You may cast that card without paying its mana cost if the spell's mana value is less than the number of Mountains you control. If you don't cast that card this way, put it into your hand.$Flashback {6}{R}| Sozin's Comet|Avatar: The Last Airbender|154|M|{3}{R}{R}|Sorcery|||Each creature you control gains firebending 5 until end of turn.$Foretell {2}{R}| +Tiger-Dillo|Avatar: The Last Airbender|155|U|{1}{R}|Creature - Cat Armadillo|4|3|This creature can't attack or block unless you control another creature with power 4 or greater.| Treetop Freedom Fighters|Avatar: The Last Airbender|156|C|{2}{R}|Creature - Human Rebel Ally|2|1|Haste$When this creature enters, create a 1/1 white Ally creature token.| +Twin Blades|Avatar: The Last Airbender|157|U|{2}{R}|Artifact - Equipment|||Flash$When this Equipment enters, attach it to target creature you control. That creature gains double strike until end of turn.$Equipped creature gets +1/+1.$Equip {2}| Ty Lee, Artful Acrobat|Avatar: The Last Airbender|158|U|{2}{R}|Legendary Creature - Human Performer|3|2|Prowess$Whenever Ty Lee attacks, you may pay {1}. When you do, target creature can't block this turn.| War Balloon|Avatar: The Last Airbender|159|U|{2}{R}|Artifact - Vehicle|4|3|Flying${1}: Put a fire counter on this Vehicle.$As long as this Vehicle has three or more fire counters on it, it's an artifact creature.$Crew 3| Yuyan Archers|Avatar: The Last Airbender|161|C|{1}{R}|Creature - Human Archer|3|1|Reach$When this creature enters, you may discard a card. If you do, draw a card.| @@ -59877,8 +59887,10 @@ Badgermole|Avatar: The Last Airbender|166|C|{4}{G}|Creature - Badger Mole|4|4|Wh Badgermole Cub|Avatar: The Last Airbender|167|M|{1}{G}|Creature - Badger Mole|2|2|When this creature enters, earthbend 1.$Whenever you tap a creature for mana, add an additional {G}.| Cycle of Renewal|Avatar: The Last Airbender|170|C|{2}{G}|Instant - Lesson|||Sacrifice a land. Search your library for up to two basic land cards, put them onto the battlefield tapped, then shuffle.| Diligent Zookeeper|Avatar: The Last Airbender|171|R|{3}{G}|Creature - Human Citizen Ally|4|4|Each non-Human creature you control gets +1/+1 for each of its creature types, to a maximum of 10.| +Earth Kingdom General|Avatar: The Last Airbender|173|U|{3}{G}|Creature - Human Soldier Ally|2|2|When this creature enters, earthbend 2.$Whenever you put one or more +1/+1 counters on a creature, you may gain that much life. Do this only once each turn.| Earth Rumble|Avatar: The Last Airbender|174|U|{3}{G}|Sorcery|||Earthbend 2. When you do, up to one target creature you control fights target creature an opponent controls.| Earthbending Lesson|Avatar: The Last Airbender|176|C|{3}{G}|Sorcery - Lesson|||Earthbend 4.| +Elemental Teachings|Avatar: The Last Airbender|178|R|{4}{G}|Instant - Lesson|||Search your library for up to four land cards with different names and reveal them. An opponent chooses two of those cards. Put the chosen cards into your graveyard and the rest onto the battlefield tapped, then shuffle.| Flopsie, Bumi's Buddy|Avatar: The Last Airbender|179|U|{4}{G}{G}|Legendary Creature - Ape Goat|4|4|When Flopsie enters, put a +1/+1 counter on each creature you control.$Each creature you control with power 4 or greater can't be blocked by more than one creature.| Haru, Hidden Talent|Avatar: The Last Airbender|182|U|{1}{G}|Legendary Creature - Human Peasant Ally|1|1|Whenever another Ally you control enters, earthbend 1.| Invasion Tactics|Avatar: The Last Airbender|183|U|{4}{G}|Enchantment|||When this enchantment enters, creatures you control get +2/+2 until end of turn.$Whenever one or more Allies you control deal combat damage to a player, draw a card.| @@ -59891,6 +59903,7 @@ Rebellious Captives|Avatar: The Last Airbender|191|C|{1}{G}|Creature - Human Pea Rocky Rebuke|Avatar: The Last Airbender|193|C|{1}{G}|Instant|||Target creature you control deals damage equal to its power to target creature an opponent controls.| Saber-Tooth Moose-Lion|Avatar: The Last Airbender|194|C|{4}{G}{G}|Creature - Elk Cat|7|7|Reach$Forestcycling {2}| Seismic Sense|Avatar: The Last Airbender|195|U|{G}|Sorcery - Lesson|||Look at the top X cards of your library, where X is the number of lands you control. You may reveal a creature or land card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| +Shared Roots|Avatar: The Last Airbender|196|U|{1}{G}|Sorcery - Lesson|||Search your library for a basic land card, put it onto the battlefield tapped, then shuffle.| Sparring Dummy|Avatar: The Last Airbender|197|U|{1}{G}|Artifact Creature - Scarecrow|1|3|Defender${T}: Mill a card. You may put a land card milled this way into your hand. You gain 2 life if a Lesson card is milled this way.| Toph, the Blind Bandit|Avatar: The Last Airbender|198|U|{2}{G}|Legendary Creature - Human Warrior Ally|*|3|When Toph enters, earthbend 2.$Toph's power is equal to the number of +1/+1 counters on lands you control.| True Ancestry|Avatar: The Last Airbender|199|U|{1}{G}|Sorcery - Lesson|||Return up to one target permanent card from your graveyard to your hand.$Create a Clue token.| @@ -59904,6 +59917,7 @@ Abandon Attachments|Avatar: The Last Airbender|205|C|{1}{U/R}|Instant - Lesson|| Avatar Aang|Avatar: The Last Airbender|207|M|{R}{G}{W}{U}|Legendary Creature - Human Avatar Ally|4|4|Flying, firebending 2$Whenever you waterbend, earthbend, firebend, or airbend, draw a card. Then if you've done all four this turn, transform Avatar Aang.| Aang, Master of Elements|Avatar: The Last Airbender|207|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Azula, Cunning Usurper|Avatar: The Last Airbender|208|R|{2}{U}{B}{B}|Legendary Creature - Human Noble Rogue|4|4|Firebending 2$When Azula enters, target opponent exiles a nontoken creature they control, then they exile a nonland card from their graveyard.$During your turn, you may cast cards exiled with Azula and you may cast them as though they had flash. Mana of any type can be spent to cast those spells.| +Beifong's Bounty Hunters|Avatar: The Last Airbender|209|R|{2}{B}{G}|Creature - Human Mercenary|4|4|Whenever a nonland creature you control dies, earthbend X, where X is that creature's power.| Bumi, Unleashed|Avatar: The Last Airbender|211|M|{3}{R}{G}|Legendary Creature - Human Noble Ally|5|4|Trample$When Bumi enters, earthbend 4.$Whenever Bumi deals combat damage to a player, untap all lands you control. After this phase, there is an additional combat phase. Only land creatures can attack during that combat phase.| Cat-Owl|Avatar: The Last Airbender|212|C|{3}{W/U}|Creature - Cat Bird|3|3|Flying$Whenever this creature attacks, untap target artifact or creature.| Dai Li Agents|Avatar: The Last Airbender|214|U|{3}{B}{G}|Creature - Human Soldier|3|4|When this creature enters, earthbend 1, then earthbend 1.$Whenever this creature attacks, each opponent loses X life and you gain X life, where X is the number of creatures you control with +1/+1 counters on them.| @@ -59919,18 +59933,21 @@ Guru Pathik|Avatar: The Last Airbender|223|U|{2}{G/U}{G/U}|Legendary Creature - Hama, the Bloodbender|Avatar: The Last Airbender|224|U|{2}{U/B}{U/B}{U/B}|Legendary Creature - Human Warlock|3|3|When Hama enters, target opponent mills three cards. Exile up to one noncreature, nonland card from that player's graveyard. For as long as you control Hama, you may cast the exiled card during your turn by waterbending {X} rather than paying its mana cost, where X is its mana value.| Hei Bai, Spirit of Balance|Avatar: The Last Airbender|225|U|{2}{W/B}{W/B}|Legendary Creature - Bear Spirit|3|3|Whenever Hei Bai enters or attacks, you may sacrifice another creature or artifact. If you do, put two +1/+1 counters on Hei Bai.$When Hei Bai leaves the battlefield, put its counters on target creature you control.| Iroh, Grand Lotus|Avatar: The Last Airbender|227|R|{3}{G}{U}{R}|Legendary Creature - Human Noble Ally|5|5|Firebending 2$During your turn, each non-Lesson instant and sorcery card in your graveyard has flashback. The flashback cost is equal to that card's mana cost.$During your turn, each Lesson card in your graveyard has flashback {1}.| +Iroh, Tea Master|Avatar: The Last Airbender|228|R|{1}{R}{W}|Legendary Creature - Human Citizen Ally|2|2|When Iroh enters, create a Food token.$At the beginning of combat on your turn, you may have target opponent gain control of target permanent you control. When you do, create a 1/1 white Ally creature token. Put a +1/+1 counter on that token for each permanent you own that your opponents control.| Jet, Freedom Fighter|Avatar: The Last Airbender|229|U|{2}{R/W}{R/W}{R/W}|Legendary Creature - Human Rebel Ally|3|1|When Jet enters, he deals damage equal to the number of creatures you control to target creature an opponent controls.$When Jet dies, put a +1/+1 counter on each of up to two target creatures.| Katara, the Fearless|Avatar: The Last Airbender|230|R|{G}{W}{U}|Legendary Creature - Human Warrior Ally|3|3|If a triggered ability of an Ally you control triggers, that ability triggers an additional time.| Katara, Water Tribe's Hope|Avatar: The Last Airbender|231|R|{2}{W}{U}{U}|Legendary Creature - Human Warrior Ally|3|3|Vigilance$When Katara enters, create a 1/1 white Ally creature token.$Waterbend {X}: Creatures you control have base power and toughness X/X until end of turn. X can't be 0. Activate only during your turn.| The Lion-Turtle|Avatar: The Last Airbender|232|R|{1}{G}{U}|Legendary Creature - Elder Cat Turtle|3|6|Vigilance, reach$When The Lion-Turtle enters, you gain 3 life.$The Lion-Turtle can't attack or block unless there are three or more Lesson cards in your graveyard.${T}: Add one mana of any color.| Long Feng, Grand Secretariat|Avatar: The Last Airbender|233|U|{1}{B/G}{B/G}|Legendary Creature - Human Advisor|2|3|Whenever another creature you control or a land you control is put into a graveyard from the battlefield, put a +1/+1 counter on target creature you control.| Ozai, the Phoenix King|Avatar: The Last Airbender|235|M|{2}{B}{B}{R}{R}|Legendary Creature - Human Noble|7|7|Trample, firebending 4, haste$If you would lose unspent mana, that mana becomes red instead.$Ozai has flying and indestructible as long as you have six or more unspent mana.| +Platypus-Bear|Avatar: The Last Airbender|236|C|{1}{G/U}|Creature - Platypus Bear|2|3|Defender$When this creature enters, mill two cards.$As long as there is a Lesson card in your graveyard, this creature can attack as though it didn't have defender.| Pretending Poxbearers|Avatar: The Last Airbender|237|C|{1}{W/B}|Creature - Human Citizen Ally|2|1|When this creature dies, create a 1/1 white Ally creature token.| Sokka, Bold Boomeranger|Avatar: The Last Airbender|240|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.| Sokka, Lateral Strategist|Avatar: The Last Airbender|241|U|{1}{W/U}{W/U}|Legendary Creature - Human Warrior Ally|2|4|Vigilance$Whenever Sokka and at least one other creature attack, draw a card.| Sokka, Tenacious Tactician|Avatar: The Last Airbender|242|R|{1}{U}{R}{W}|Legendary Creature - Human Warrior Ally|3|3|Menace, prowess$Other Allies you control have menace and prowess.$Whenever you cast a noncreature spell, create a 1/1 white Ally creature token.| Suki, Kyoshi Warrior|Avatar: The Last Airbender|243|U|{2}{G/W}{G/W}|Legendary Creature - Human Warrior Ally|*|4|Suki's power is equal to the number of creatures you control.$Whenever Suki attacks, create a 1/1 white Ally creature token that's tapped and attacking.| Sun Warriors|Avatar: The Last Airbender|244|U|{2}{R}{W}|Creature - Human Warrior Ally|3|5|Firebending X, where X is the number of creatures you control.${5}: Create a 1/1 white Ally creature token.| +Tolls of War|Avatar: The Last Airbender|245|U|{W}{B}|Enchantment|||When this enchantment enters, create a Clue token.$Whenever you sacrifice a permanent during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.| Toph, the First Metalbender|Avatar: The Last Airbender|247|R|{1}{R}{G}{W}|Legendary Creature - Human Warrior Ally|3|3|Nontoken artifacts you control are lands in addition to their other types.$At the beginning of your end step, earthbend 2.| Uncle Iroh|Avatar: The Last Airbender|248|U|{1}{R/G}{R/G}|Legendary Creature - Human Noble Ally|4|2|Firebending 1$Lesson spells you cast cost {1} less to cast.| Vindictive Warden|Avatar: The Last Airbender|249|C|{2}{B/R}|Creature - Human Soldier|2|3|Menace$Firebending 1${3}: This creature deals 1 damage to each opponent.| @@ -59943,7 +59960,17 @@ Fire Nation Warship|Avatar: The Last Airbender|256|U|{3}|Artifact - Vehicle|4|4| Planetarium of Wan Shi Tong|Avatar: The Last Airbender|259|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| Trusty Boomerang|Avatar: The Last Airbender|260|U|{1}|Artifact - Equipment|||Equipped creature has "{1}, {T}: Tap target creature. Return Trusty Boomerang to its owner's hand."$Equip {1}| White Lotus Tile|Avatar: The Last Airbender|262|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| +Airship Engine Room|Avatar: The Last Airbender|265|C||Land|||This land enters tapped.${T}: Add {U} or {R}.${4}, {T}, Sacrifice this land: Draw a card.| +Boiling Rock Prison|Avatar: The Last Airbender|267|C||Land|||This land enters tapped.${T}: Add {B} or {R}.${4}, {T}, Sacrifice this land: Draw a card.| +Foggy Bottom Swamp|Avatar: The Last Airbender|269|C||Land|||This land enters tapped.${T}: Add {B} or {G}.${4}, {T}, Sacrifice this land: Draw a card.| +Kyoshi Village|Avatar: The Last Airbender|271|C||Land|||This land enters tapped.${T}: Add {G} or {W}.${4}, {T}, Sacrifice this land: Draw a card.| +Meditation Pools|Avatar: The Last Airbender|272|C||Land|||This land enters tapped.${T}: Add {G} or {U}.${4}, {T}, Sacrifice this land: Draw a card.| +Misty Palms Oasis|Avatar: The Last Airbender|273|C||Land|||This land enters tapped.${T}: Add {W} or {B}.${4}, {T}, Sacrifice this land: Draw a card.| +North Pole Gates|Avatar: The Last Airbender|274|C||Land|||This land enters tapped.${T}: Add {W} or {U}.${4}, {T}, Sacrifice this land: Draw a card.| +Omashu City|Avatar: The Last Airbender|275|C||Land|||This land enters tapped.${T}: Add {R} or {G}.${4}, {T}, Sacrifice this land: Draw a card.| Secret Tunnel|Avatar: The Last Airbender|278|R||Land - Cave|||This land can't be blocked.${T}: Add {C}.${4}, {T}: Two target creatures you control that share a creature type can't be blocked this turn.| +Serpent's Pass|Avatar: The Last Airbender|279|C||Land|||This land enters tapped.${T}: Add {U} or {B}.${4}, {T}, Sacrifice this land: Draw a card.| +Sun-Blessed Peak|Avatar: The Last Airbender|280|C||Land|||This land enters tapped.${T}: Add {R} or {W}.${4}, {T}, Sacrifice this land: Draw a card.| White Lotus Hideout|Avatar: The Last Airbender|281|U||Land|||{T}: Add {C}.${T}: Add one mana of any color. Spend this mana only to cast a Lesson or Shrine spell.${1}, {T}: Add one mana of any color.| Plains|Avatar: The Last Airbender|282|C||Basic Land - Plains|||({T}: Add {W}.)| Island|Avatar: The Last Airbender|283|C||Basic Land - Island|||({T}: Add {U}.)| @@ -59973,12 +60000,14 @@ Avatar Aang|Avatar: The Last Airbender|308|M|{R}{G}{W}{U}|Legendary Creature - H Aang, Master of Elements|Avatar: The Last Airbender|308|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Sozin's Comet|Avatar: The Last Airbender|309|M|{3}{R}{R}|Sorcery|||Each creature you control gains firebending 5 until end of turn.$Foretell {2}{R}| Ozai, the Phoenix King|Avatar: The Last Airbender|311|M|{2}{B}{B}{R}{R}|Legendary Creature - Human Noble|7|7|Trample, firebending 4, haste$If you would lose unspent mana, that mana becomes red instead.$Ozai has flying and indestructible as long as you have six or more unspent mana.| +Firebender Ascension|Avatar: The Last Airbender|312|R|{1}{R}|Enchantment|||When this enchantment enters, create a 2/2 red Soldier creature token with firebending 1.$Whenever a creature you control attacking causes a triggered ability of that creature to trigger, put a quest counter on this enchantment. Then if it has four or more quest counters on it, you may copy that ability. You may choose new targets for the copy.| Fire Lord Azula|Avatar: The Last Airbender|313|R|{1}{U}{B}{R}|Legendary Creature - Human Noble|4|4|Firebending 2$Whenever you cast a spell while Fire Lord Azula is attacking, copy that spell. You may choose new targets for the copy.| The Last Agni Kai|Avatar: The Last Airbender|314|R|{1}{R}|Instant|||Target creature you control fights target creature an opponent controls. If the creature the opponent controls is dealt excess damage this way, add that much {R}.$Until end of turn, you don't lose unspent red mana as steps and phases end.| Fire Lord Zuko|Avatar: The Last Airbender|315|R|{R}{W}{B}|Legendary Creature - Human Noble Ally|2|4|Firebending X, where X is Fire Lord Zuko's power.$Whenever you cast a spell from exile and whenever a permanent you control enters from exile, put a +1/+1 counter on each creature you control.| Appa, Steadfast Guardian|Avatar: The Last Airbender|316|M|{2}{W}{W}|Legendary Creature - Bison Ally|3|4|Flash$Flying$When Appa enters, airbend any number of other target nonland permanents you control.$Whenever you cast a spell from exile, create a 1/1 white Ally creature token.| Momo, Friendly Flier|Avatar: The Last Airbender|317|R|{W}|Legendary Creature - Lemur Bat Ally|1|1|Flying$The first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast.$Whenever another creature you control with flying enters, Momo gets +1/+1 until end of turn.| Tiger-Seal|Avatar: The Last Airbender|318|R|{U}|Creature - Cat Seal|3|3|Vigilance$At the beginning of your upkeep, tap this creature.$Whenever you draw your second card each turn, untap this creature.| +The Unagi of Kyoshi Island|Avatar: The Last Airbender|319|R|{3}{U}{U}|Legendary Creature - Serpent|5|5|Flash$Ward--Waterbend {4}$Whenever an opponent draws their second card each turn, draw two cards.| Wan Shi Tong, Librarian|Avatar: The Last Airbender|320|M|{X}{U}{U}|Legendary Creature - Bird Spirit|1|1|Flash$Flying, vigilance$When Wan Shi Tong enters, put X +1/+1 counters on him. Then draw half X cards, rounded down.$Whenever an opponent searches their library, put a +1/+1 counter on Wan Shi Tong and draw a card.| The Fire Nation Drill|Avatar: The Last Airbender|321|R|{2}{B}{B}|Legendary Artifact - Vehicle|6|3|Trample$When The Fire Nation Drill enters, you may tap it. When you do, destroy target creature with power 4 or less.${1}: Permanents your opponents control lose hexproof and indestructible until end of turn.$Crew 2| Ran and Shaw|Avatar: The Last Airbender|325|R|{3}{R}{R}|Legendary Creature - Dragon|4|4|Flying, firebending 2$When Ran and Shaw enter, if you cast them and there are three or more Dragon and/or Lesson cards in your graveyard, create a token that's a copy of Ran and Shaw, except it's not legendary.${3}{R}: Dragons you control get +2/+0 until end of turn.| @@ -59986,6 +60015,7 @@ Badgermole Cub|Avatar: The Last Airbender|326|M|{1}{G}|Creature - Badger Mole|2| Diligent Zookeeper|Avatar: The Last Airbender|327|R|{3}{G}|Creature - Human Citizen Ally|4|4|Each non-Human creature you control gets +1/+1 for each of its creature types, to a maximum of 10.| The Lion-Turtle|Avatar: The Last Airbender|328|R|{1}{G}{U}|Legendary Creature - Elder Cat Turtle|3|6|Vigilance, reach$When The Lion-Turtle enters, you gain 3 life.$The Lion-Turtle can't attack or block unless there are three or more Lesson cards in your graveyard.${T}: Add one mana of any color.| White Lotus Tile|Avatar: The Last Airbender|330|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| +United Front|Avatar: The Last Airbender|331|M|{X}{W}{W}|Sorcery|||Create X 1/1 white Ally creature tokens, then put a +1/+1 counter on each creature you control.| Sozin's Comet|Avatar: The Last Airbender|332|M|{3}{R}{R}|Sorcery|||Each creature you control gains firebending 5 until end of turn.$Foretell {2}{R}| Fire Lord Azula|Avatar: The Last Airbender|334|R|{1}{U}{B}{R}|Legendary Creature - Human Noble|4|4|Firebending 2$Whenever you cast a spell while Fire Lord Azula is attacking, copy that spell. You may choose new targets for the copy.| Ozai, the Phoenix King|Avatar: The Last Airbender|335|M|{2}{B}{B}{R}{R}|Legendary Creature - Human Noble|7|7|Trample, firebending 4, haste$If you would lose unspent mana, that mana becomes red instead.$Ozai has flying and indestructible as long as you have six or more unspent mana.| @@ -60006,6 +60036,8 @@ Katara, the Fearless|Avatar: The Last Airbender|350|R|{G}{W}{U}|Legendary Creatu Katara, Water Tribe's Hope|Avatar: The Last Airbender|351|R|{2}{W}{U}{U}|Legendary Creature - Human Warrior Ally|3|3|Vigilance$When Katara enters, create a 1/1 white Ally creature token.$Waterbend {X}: Creatures you control have base power and toughness X/X until end of turn. X can't be 0. Activate only during your turn.| Sokka, Tenacious Tactician|Avatar: The Last Airbender|352|R|{1}{U}{R}{W}|Legendary Creature - Human Warrior Ally|3|3|Menace, prowess$Other Allies you control have menace and prowess.$Whenever you cast a noncreature spell, create a 1/1 white Ally creature token.| Toph, the First Metalbender|Avatar: The Last Airbender|353|R|{1}{R}{G}{W}|Legendary Creature - Human Warrior Ally|3|3|Nontoken artifacts you control are lands in addition to their other types.$At the beginning of your end step, earthbend 2.| +The Legend of Yangchen|Avatar: The Last Airbender|354|M|{3}{W}{W}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$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.$II -- You may have target opponent draw three cards. If you do, draw three cards.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| +Avatar Yangchen|Avatar: The Last Airbender|354|M||Legendary Creature - Avatar|4|5|Flying$Whenever you cast your second spell each turn, airbend up to one other target nonland permanent.| The Legend of Kuruk|Avatar: The Last Airbender|355|M|{2}{U}{U}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I, II -- Scry 2, then draw a card.$III -- Exile this Saga, then return it to the battlefield$transformed under your control.| Avatar Kuruk|Avatar: The Last Airbender|355|M||Legendary Creature - Avatar|4|3|Whenever you cast a spell, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."$Exhaust -- Waterbend {20}: Take an extra turn after this one.| The Rise of Sozin|Avatar: The Last Airbender|356|M|{4}{B}{B}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I -- Destroy all creatures.$II -- Choose a card name. Search target opponent's graveyard, hand, and library for up to four cards with that name and exile them. Then that player shuffles.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| @@ -60021,11 +60053,14 @@ Avatar Aang|Avatar: The Last Airbender|363|M|{R}{G}{W}{U}|Legendary Creature - H Aang, Master of Elements|Avatar: The Last Airbender|363|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Airbender Ascension|Avatar: The Last Airbender|364|R|{1}{W}|Enchantment|||When this enchantment enters, airbend up to one target creature.$Whenever a creature you control enters, put a quest counter on this enchantment.$At the beginning of your end step, if this enchantment has four or more quest counters on it, exile up to one target creature you control, then return it to the battlefield under its owner's control.| Hakoda, Selfless Commander|Avatar: The Last Airbender|366|R|{3}{W}|Legendary Creature - Human Warrior Ally|3|5|Vigilance$You may look at the top card of your library any time.$You may cast Ally spells from the top of your library.$Sacrifice Hakoda: Creatures you control get +0/+5 and gain indestructible until end of turn.| +Suki, Courageous Rescuer|Avatar: The Last Airbender|368|R|{1}{W}{W}|Legendary Creature - Human Warrior Ally|2|4|Other creatures you control get +1/+0.$Whenever another permanent you control leaves the battlefield during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.| The Mechanist, Aerial Artisan|Avatar: The Last Airbender|369|R|{2}{U}|Legendary Creature - Human Artificer Ally|1|3|Whenever you cast a noncreature spell, create a Clue token.${T}: Until end of turn, target artifact token you control becomes a 3/1 Construct artifact creature with flying.| Spirit Water Revival|Avatar: The Last Airbender|370|R|{1}{U}{U}|Sorcery|||As an additional cost to cast this spell, you may waterbend {6}.$Draw two cards. If this spell's additional cost was paid, instead shuffle your graveyard into your library, draw seven cards, and you have no maximum hand size for the rest of the game.$Exile Spirit Water Revival.| Ty Lee, Chi Blocker|Avatar: The Last Airbender|371|R|{2}{U}|Legendary Creature - Human Performer Ally|2|1|Flash$Prowess$When Ty Lee enters, tap up to one target creature. It doesn't untap during its controller's untap step for as long as you control Ty Lee.| Boiling Rock Rioter|Avatar: The Last Airbender|372|R|{2}{B}|Creature - Human Rogue Ally|3|3|Firebending 1$Tap an untapped Ally you control: Exile target card from a graveyard.$Whenever this creature attacks, you may cast an Ally spell from among cards you own exiled with this creature.| Day of Black Sun|Avatar: The Last Airbender|373|R|{X}{B}{B}|Sorcery|||Each creature with mana value X or less loses all abilities until end of turn. Destroy those creatures.| +Mai, Scornful Striker|Avatar: The Last Airbender|374|R|{1}{B}|Legendary Creature - Human Noble Ally|2|2|First strike$Whenever a player casts a noncreature spell, they lose 2 life.| +Beifong's Bounty Hunters|Avatar: The Last Airbender|379|R|{2}{B}{G}|Creature - Human Mercenary|4|4|Whenever a nonland creature you control dies, earthbend X, where X is that creature's power.| Earth King's Lieutenant|Avatar: The Last Airbender|380|R|{G}{W}|Creature - Human Soldier Ally|1|1|Trample$When this creature enters, put a +1/+1 counter on each other Ally creature you control.$Whenever another Ally you control enters, put a +1/+1 counter on this creature.| Iroh, Tea Master|Avatar: The Last Airbender|381|R|{1}{R}{W}|Legendary Creature - Human Citizen Ally|2|2|When Iroh enters, create a Food token.$At the beginning of combat on your turn, you may have target opponent gain control of target permanent you control. When you do, create a 1/1 white Ally creature token. Put a +1/+1 counter on that token for each permanent you own that your opponents control.| Sokka, Bold Boomeranger|Avatar: The Last Airbender|383|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.| -- 2.47.2 From 76c6f4e2ec4b1f68771499741d852331c1dae3b7 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:14:43 -0500 Subject: [PATCH 055/261] [TLA] Implement North Pole Gates --- .../src/mage/cards/n/NorthPoleGates.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/n/NorthPoleGates.java diff --git a/Mage.Sets/src/mage/cards/n/NorthPoleGates.java b/Mage.Sets/src/mage/cards/n/NorthPoleGates.java new file mode 100644 index 00000000000..781b54b77c0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NorthPoleGates.java @@ -0,0 +1,48 @@ +package mage.cards.n; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class NorthPoleGates extends CardImpl { + + public NorthPoleGates(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {W} or {U}. + this.addAbility(new WhiteManaAbility()); + this.addAbility(new BlueManaAbility()); + + // {4}, {T}, Sacrifice this land: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + private NorthPoleGates(final NorthPoleGates card) { + super(card); + } + + @Override + public NorthPoleGates copy() { + return new NorthPoleGates(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 689d81aa7f7..52a9d49be0a 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -138,6 +138,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 285, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 290, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Mountain", 295, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("North Pole Gates", 274, Rarity.COMMON, mage.cards.n.NorthPoleGates.class)); cards.add(new SetCardInfo("North Pole Patrol", 65, Rarity.UNCOMMON, mage.cards.n.NorthPolePatrol.class)); cards.add(new SetCardInfo("Northern Air Temple", 111, Rarity.UNCOMMON, mage.cards.n.NorthernAirTemple.class)); cards.add(new SetCardInfo("Octopus Form", 66, Rarity.COMMON, mage.cards.o.OctopusForm.class)); -- 2.47.2 From 6766c7b45dd944f5d61eea210b0c852bfea60add Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:15:35 -0500 Subject: [PATCH 056/261] [TLA] Implement Misty Palms Oasis --- .../src/mage/cards/m/MistyPalmsOasis.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MistyPalmsOasis.java diff --git a/Mage.Sets/src/mage/cards/m/MistyPalmsOasis.java b/Mage.Sets/src/mage/cards/m/MistyPalmsOasis.java new file mode 100644 index 00000000000..50422cf804a --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MistyPalmsOasis.java @@ -0,0 +1,48 @@ +package mage.cards.m; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MistyPalmsOasis extends CardImpl { + + public MistyPalmsOasis(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {W} or {B}. + this.addAbility(new WhiteManaAbility()); + this.addAbility(new BlackManaAbility()); + + // {4}, {T}, Sacrifice this land: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + private MistyPalmsOasis(final MistyPalmsOasis card) { + super(card); + } + + @Override + public MistyPalmsOasis copy() { + return new MistyPalmsOasis(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 52a9d49be0a..b720f859f1e 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -130,6 +130,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Master Pakku", 63, Rarity.UNCOMMON, mage.cards.m.MasterPakku.class)); cards.add(new SetCardInfo("Master Piandao", 28, Rarity.UNCOMMON, mage.cards.m.MasterPiandao.class)); cards.add(new SetCardInfo("Merchant of Many Hats", 110, Rarity.COMMON, mage.cards.m.MerchantOfManyHats.class)); + cards.add(new SetCardInfo("Misty Palms Oasis", 273, Rarity.COMMON, mage.cards.m.MistyPalmsOasis.class)); cards.add(new SetCardInfo("Momo, Friendly Flier", 29, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Momo, Friendly Flier", 317, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Momo, Friendly Flier", 394, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 46fa105b7e8ada3c1f1b684eb4f8347c0cd5cbb2 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:16:43 -0500 Subject: [PATCH 057/261] [TLA] Implement Serpent's Pass --- Mage.Sets/src/mage/cards/s/SerpentsPass.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SerpentsPass.java diff --git a/Mage.Sets/src/mage/cards/s/SerpentsPass.java b/Mage.Sets/src/mage/cards/s/SerpentsPass.java new file mode 100644 index 00000000000..86def0461ef --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SerpentsPass.java @@ -0,0 +1,48 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.BlueManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SerpentsPass extends CardImpl { + + public SerpentsPass(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {U} or {B}. + this.addAbility(new BlueManaAbility()); + this.addAbility(new BlackManaAbility()); + + // {4}, {T}, Sacrifice this land: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + private SerpentsPass(final SerpentsPass card) { + super(card); + } + + @Override + public SerpentsPass copy() { + return new SerpentsPass(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b720f859f1e..e68a613d394 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -169,6 +169,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Saber-Tooth Moose-Lion", 194, Rarity.COMMON, mage.cards.s.SaberToothMooseLion.class)); cards.add(new SetCardInfo("Seismic Sense", 195, Rarity.UNCOMMON, mage.cards.s.SeismicSense.class)); cards.add(new SetCardInfo("Serpent of the Pass", 70, Rarity.UNCOMMON, mage.cards.s.SerpentOfThePass.class)); + cards.add(new SetCardInfo("Serpent's Pass", 279, Rarity.COMMON, mage.cards.s.SerpentsPass.class)); cards.add(new SetCardInfo("Sokka's Haiku", 71, Rarity.UNCOMMON, mage.cards.s.SokkasHaiku.class)); cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 240, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 383, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 717baabdc3d1d6b7d82a7434a4bb64e29a1ae34e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:17:30 -0500 Subject: [PATCH 058/261] [TLA] Implement Airship Engine Room --- .../src/mage/cards/a/AirshipEngineRoom.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AirshipEngineRoom.java diff --git a/Mage.Sets/src/mage/cards/a/AirshipEngineRoom.java b/Mage.Sets/src/mage/cards/a/AirshipEngineRoom.java new file mode 100644 index 00000000000..2c57ddaca7d --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AirshipEngineRoom.java @@ -0,0 +1,48 @@ +package mage.cards.a; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AirshipEngineRoom extends CardImpl { + + public AirshipEngineRoom(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {U} or {R}. + this.addAbility(new BlueManaAbility()); + this.addAbility(new RedManaAbility()); + + // {4}, {T}, Sacrifice this land: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + private AirshipEngineRoom(final AirshipEngineRoom card) { + super(card); + } + + @Override + public AirshipEngineRoom copy() { + return new AirshipEngineRoom(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index e68a613d394..efac43ed771 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -34,6 +34,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Aang, the Last Airbender", 4, Rarity.UNCOMMON, mage.cards.a.AangTheLastAirbender.class)); cards.add(new SetCardInfo("Abandon Attachments", 205, Rarity.COMMON, mage.cards.a.AbandonAttachments.class)); cards.add(new SetCardInfo("Airbending Lesson", 8, Rarity.COMMON, mage.cards.a.AirbendingLesson.class)); + cards.add(new SetCardInfo("Airship Engine Room", 265, Rarity.COMMON, mage.cards.a.AirshipEngineRoom.class)); cards.add(new SetCardInfo("Appa, Steadfast Guardian", 10, Rarity.MYTHIC, mage.cards.a.AppaSteadfastGuardian.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Appa, Steadfast Guardian", 316, Rarity.MYTHIC, mage.cards.a.AppaSteadfastGuardian.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Avatar Aang", 207, Rarity.MYTHIC, mage.cards.a.AvatarAang.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From d2918e69f4c13f15336aea9ce08659880c4904c3 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:18:30 -0500 Subject: [PATCH 059/261] [TLA] Implement Boiling Rock Prison --- .../src/mage/cards/b/BoilingRockPrison.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BoilingRockPrison.java diff --git a/Mage.Sets/src/mage/cards/b/BoilingRockPrison.java b/Mage.Sets/src/mage/cards/b/BoilingRockPrison.java new file mode 100644 index 00000000000..7947b1b9b76 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BoilingRockPrison.java @@ -0,0 +1,48 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BoilingRockPrison extends CardImpl { + + public BoilingRockPrison(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {B} or {R}. + this.addAbility(new BlackManaAbility()); + this.addAbility(new RedManaAbility()); + + // {4}, {T}, Sacrifice this land: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + private BoilingRockPrison(final BoilingRockPrison card) { + super(card); + } + + @Override + public BoilingRockPrison copy() { + return new BoilingRockPrison(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index efac43ed771..d5f12355860 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -49,6 +49,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Barrels of Blasting Jelly", 254, Rarity.COMMON, mage.cards.b.BarrelsOfBlastingJelly.class)); cards.add(new SetCardInfo("Beetle-Headed Merchants", 86, Rarity.COMMON, mage.cards.b.BeetleHeadedMerchants.class)); cards.add(new SetCardInfo("Bender's Waterskin", 255, Rarity.COMMON, mage.cards.b.BendersWaterskin.class)); + cards.add(new SetCardInfo("Boiling Rock Prison", 267, Rarity.COMMON, mage.cards.b.BoilingRockPrison.class)); cards.add(new SetCardInfo("Bumi Bash", 125, Rarity.COMMON, mage.cards.b.BumiBash.class)); cards.add(new SetCardInfo("Bumi, Unleashed", 211, Rarity.MYTHIC, mage.cards.b.BumiUnleashed.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bumi, Unleashed", 348, Rarity.MYTHIC, mage.cards.b.BumiUnleashed.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From f4d4e80ed1c5eb06414d9fc97d22c3b1ba4bbcc6 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:19:16 -0500 Subject: [PATCH 060/261] [TLA] Implement Foggy Bottom Swamp --- .../src/mage/cards/f/FoggyBottomSwamp.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FoggyBottomSwamp.java diff --git a/Mage.Sets/src/mage/cards/f/FoggyBottomSwamp.java b/Mage.Sets/src/mage/cards/f/FoggyBottomSwamp.java new file mode 100644 index 00000000000..f073c26d9c9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FoggyBottomSwamp.java @@ -0,0 +1,48 @@ +package mage.cards.f; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FoggyBottomSwamp extends CardImpl { + + public FoggyBottomSwamp(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {B} or {G}. + this.addAbility(new BlackManaAbility()); + this.addAbility(new GreenManaAbility()); + + // {4}, {T}, Sacrifice this land: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + private FoggyBottomSwamp(final FoggyBottomSwamp card) { + super(card); + } + + @Override + public FoggyBottomSwamp copy() { + return new FoggyBottomSwamp(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index d5f12355860..fc70d09e6f2 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -96,6 +96,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("First-Time Flyer", 49, Rarity.COMMON, mage.cards.f.FirstTimeFlyer.class)); cards.add(new SetCardInfo("Flexible Waterbender", 50, Rarity.COMMON, mage.cards.f.FlexibleWaterbender.class)); cards.add(new SetCardInfo("Flopsie, Bumi's Buddy", 179, Rarity.UNCOMMON, mage.cards.f.FlopsieBumisBuddy.class)); + cards.add(new SetCardInfo("Foggy Bottom Swamp", 269, Rarity.COMMON, mage.cards.f.FoggyBottomSwamp.class)); cards.add(new SetCardInfo("Forecasting Fortune Teller", 51, Rarity.COMMON, mage.cards.f.ForecastingFortuneTeller.class)); cards.add(new SetCardInfo("Forest", 286, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Forest", 291, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); -- 2.47.2 From fffead4da5d21c22be20f2ee19e33cd8e853092a Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:20:02 -0500 Subject: [PATCH 061/261] [TLA] Implement Omashu City --- Mage.Sets/src/mage/cards/o/OmashuCity.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/o/OmashuCity.java diff --git a/Mage.Sets/src/mage/cards/o/OmashuCity.java b/Mage.Sets/src/mage/cards/o/OmashuCity.java new file mode 100644 index 00000000000..eb1a89e64c8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OmashuCity.java @@ -0,0 +1,48 @@ +package mage.cards.o; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class OmashuCity extends CardImpl { + + public OmashuCity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {R} or {G}. + this.addAbility(new RedManaAbility()); + this.addAbility(new GreenManaAbility()); + + // {4}, {T}, Sacrifice this land: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + private OmashuCity(final OmashuCity card) { + super(card); + } + + @Override + public OmashuCity copy() { + return new OmashuCity(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index fc70d09e6f2..2cc9b7bd247 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -146,6 +146,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("North Pole Patrol", 65, Rarity.UNCOMMON, mage.cards.n.NorthPolePatrol.class)); cards.add(new SetCardInfo("Northern Air Temple", 111, Rarity.UNCOMMON, mage.cards.n.NorthernAirTemple.class)); cards.add(new SetCardInfo("Octopus Form", 66, Rarity.COMMON, mage.cards.o.OctopusForm.class)); + cards.add(new SetCardInfo("Omashu City", 275, Rarity.COMMON, mage.cards.o.OmashuCity.class)); cards.add(new SetCardInfo("Origin of Metalbending", 187, Rarity.COMMON, mage.cards.o.OriginOfMetalbending.class)); cards.add(new SetCardInfo("Ostrich-Horse", 188, Rarity.COMMON, mage.cards.o.OstrichHorse.class)); cards.add(new SetCardInfo("Otter-Penguin", 67, Rarity.COMMON, mage.cards.o.OtterPenguin.class)); -- 2.47.2 From 19274aa8f05e345f1466a3db22532506ac71b650 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:21:10 -0500 Subject: [PATCH 062/261] [TLA] Implement Sun-Blessed Peak --- .../src/mage/cards/s/SunBlessedPeak.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SunBlessedPeak.java diff --git a/Mage.Sets/src/mage/cards/s/SunBlessedPeak.java b/Mage.Sets/src/mage/cards/s/SunBlessedPeak.java new file mode 100644 index 00000000000..252a264483e --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SunBlessedPeak.java @@ -0,0 +1,48 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.RedManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SunBlessedPeak extends CardImpl { + + public SunBlessedPeak(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {R} or {W}. + this.addAbility(new RedManaAbility()); + this.addAbility(new WhiteManaAbility()); + + // {4}, {T}, Sacrifice this land: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + private SunBlessedPeak(final SunBlessedPeak card) { + super(card); + } + + @Override + public SunBlessedPeak copy() { + return new SunBlessedPeak(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 2cc9b7bd247..27bf4d40660 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -189,6 +189,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Suki, Courageous Rescuer", 37, Rarity.RARE, mage.cards.s.SukiCourageousRescuer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Suki, Kyoshi Warrior", 243, Rarity.UNCOMMON, mage.cards.s.SukiKyoshiWarrior.class)); cards.add(new SetCardInfo("Sun Warriors", 244, Rarity.UNCOMMON, mage.cards.s.SunWarriors.class)); + cards.add(new SetCardInfo("Sun-Blessed Peak", 280, Rarity.COMMON, mage.cards.s.SunBlessedPeak.class)); cards.add(new SetCardInfo("Swamp", 284, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Swamp", 289, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swamp", 294, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); -- 2.47.2 From dfc91bf8cffea19db4c2eef6a62a51c60bb91472 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:22:53 -0500 Subject: [PATCH 063/261] [TLA] Implement Kyoshi Village --- Mage.Sets/src/mage/cards/k/KyoshiVillage.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/k/KyoshiVillage.java diff --git a/Mage.Sets/src/mage/cards/k/KyoshiVillage.java b/Mage.Sets/src/mage/cards/k/KyoshiVillage.java new file mode 100644 index 00000000000..b81da4ec485 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KyoshiVillage.java @@ -0,0 +1,48 @@ +package mage.cards.k; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KyoshiVillage extends CardImpl { + + public KyoshiVillage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {G} or {W}. + this.addAbility(new GreenManaAbility()); + this.addAbility(new WhiteManaAbility()); + + // {4}, {T}, Sacrifice this land: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + private KyoshiVillage(final KyoshiVillage card) { + super(card); + } + + @Override + public KyoshiVillage copy() { + return new KyoshiVillage(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 27bf4d40660..b075b3ed799 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -126,6 +126,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Katara, the Fearless", 305, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, the Fearless", 350, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, the Fearless", 361, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Kyoshi Village", 271, Rarity.COMMON, mage.cards.k.KyoshiVillage.class)); cards.add(new SetCardInfo("Leaves from the Vine", 185, Rarity.UNCOMMON, mage.cards.l.LeavesFromTheVine.class)); cards.add(new SetCardInfo("Lightning Strike", 146, Rarity.COMMON, mage.cards.l.LightningStrike.class)); cards.add(new SetCardInfo("Long Feng, Grand Secretariat", 233, Rarity.UNCOMMON, mage.cards.l.LongFengGrandSecretariat.class)); -- 2.47.2 From 0fc84fca38b7aa91f207d6088b4e606389362e78 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:23:03 -0500 Subject: [PATCH 064/261] [TLA] Implement Meditation Pools --- .../src/mage/cards/m/MeditationPools.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MeditationPools.java diff --git a/Mage.Sets/src/mage/cards/m/MeditationPools.java b/Mage.Sets/src/mage/cards/m/MeditationPools.java new file mode 100644 index 00000000000..922f521ad82 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MeditationPools.java @@ -0,0 +1,48 @@ +package mage.cards.m; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MeditationPools extends CardImpl { + + public MeditationPools(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped. + this.addAbility(new EntersBattlefieldTappedAbility()); + + // {T}: Add {G} or {U}. + this.addAbility(new GreenManaAbility()); + this.addAbility(new BlueManaAbility()); + + // {4}, {T}, Sacrifice this land: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + private MeditationPools(final MeditationPools card) { + super(card); + } + + @Override + public MeditationPools copy() { + return new MeditationPools(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b075b3ed799..2d50e81819a 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -133,6 +133,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Mai, Jaded Edge", 147, Rarity.UNCOMMON, mage.cards.m.MaiJadedEdge.class)); cards.add(new SetCardInfo("Master Pakku", 63, Rarity.UNCOMMON, mage.cards.m.MasterPakku.class)); cards.add(new SetCardInfo("Master Piandao", 28, Rarity.UNCOMMON, mage.cards.m.MasterPiandao.class)); + cards.add(new SetCardInfo("Meditation Pools", 272, Rarity.COMMON, mage.cards.m.MeditationPools.class)); cards.add(new SetCardInfo("Merchant of Many Hats", 110, Rarity.COMMON, mage.cards.m.MerchantOfManyHats.class)); cards.add(new SetCardInfo("Misty Palms Oasis", 273, Rarity.COMMON, mage.cards.m.MistyPalmsOasis.class)); cards.add(new SetCardInfo("Momo, Friendly Flier", 29, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 44e6cf999ed4c4160060c75e01c45baaa1665f25 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:24:31 -0500 Subject: [PATCH 065/261] [TLA] Implement Mai, Scornful Striker --- .../src/mage/cards/m/MaiScornfulStriker.java | 50 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 52 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MaiScornfulStriker.java diff --git a/Mage.Sets/src/mage/cards/m/MaiScornfulStriker.java b/Mage.Sets/src/mage/cards/m/MaiScornfulStriker.java new file mode 100644 index 00000000000..6756b0556bb --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MaiScornfulStriker.java @@ -0,0 +1,50 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.common.SpellCastAllTriggeredAbility; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SetTargetPointer; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MaiScornfulStriker extends CardImpl { + + public MaiScornfulStriker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // Whenever a player casts a noncreature spell, they lose 2 life. + this.addAbility(new SpellCastAllTriggeredAbility( + new LoseLifeTargetEffect(2).setText("they lose 2 life"), + StaticFilters.FILTER_SPELL_A_NON_CREATURE, false, SetTargetPointer.PLAYER + )); + } + + private MaiScornfulStriker(final MaiScornfulStriker card) { + super(card); + } + + @Override + public MaiScornfulStriker copy() { + return new MaiScornfulStriker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 2d50e81819a..97ac180c2b2 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -131,6 +131,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Lightning Strike", 146, Rarity.COMMON, mage.cards.l.LightningStrike.class)); cards.add(new SetCardInfo("Long Feng, Grand Secretariat", 233, Rarity.UNCOMMON, mage.cards.l.LongFengGrandSecretariat.class)); cards.add(new SetCardInfo("Mai, Jaded Edge", 147, Rarity.UNCOMMON, mage.cards.m.MaiJadedEdge.class)); + cards.add(new SetCardInfo("Mai, Scornful Striker", 109, Rarity.RARE, mage.cards.m.MaiScornfulStriker.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mai, Scornful Striker", 374, Rarity.RARE, mage.cards.m.MaiScornfulStriker.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Master Pakku", 63, Rarity.UNCOMMON, mage.cards.m.MasterPakku.class)); cards.add(new SetCardInfo("Master Piandao", 28, Rarity.UNCOMMON, mage.cards.m.MasterPiandao.class)); cards.add(new SetCardInfo("Meditation Pools", 272, Rarity.COMMON, mage.cards.m.MeditationPools.class)); -- 2.47.2 From 08fc3bbdc1de0272f611a2b17d4e3391e49c8981 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:26:37 -0500 Subject: [PATCH 066/261] [TLA] Implement Tolls of War --- Mage.Sets/src/mage/cards/t/TollsOfWar.java | 41 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 42 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TollsOfWar.java diff --git a/Mage.Sets/src/mage/cards/t/TollsOfWar.java b/Mage.Sets/src/mage/cards/t/TollsOfWar.java new file mode 100644 index 00000000000..1e113a7cef3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TollsOfWar.java @@ -0,0 +1,41 @@ +package mage.cards.t; + +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SacrificePermanentTriggeredAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.game.permanent.token.AllyToken; +import mage.game.permanent.token.ClueArtifactToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TollsOfWar extends CardImpl { + + public TollsOfWar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{B}"); + + // When this enchantment enters, create a Clue token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ClueArtifactToken()))); + + // Whenever you sacrifice a permanent during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn. + this.addAbility(new SacrificePermanentTriggeredAbility( + new CreateTokenEffect(new AllyToken()), StaticFilters.FILTER_PERMANENT + ).withTriggerCondition(MyTurnCondition.instance).setTriggersLimitEachTurn(1)); + } + + private TollsOfWar(final TollsOfWar card) { + super(card); + } + + @Override + public TollsOfWar copy() { + return new TollsOfWar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 97ac180c2b2..18e88ec868a 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -204,6 +204,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("The Rise of Sozin", 356, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tiger-Seal", 318, Rarity.RARE, mage.cards.t.TigerSeal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tiger-Seal", 75, Rarity.RARE, mage.cards.t.TigerSeal.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Tolls of War", 245, Rarity.UNCOMMON, mage.cards.t.TollsOfWar.class)); cards.add(new SetCardInfo("Toph, the Blind Bandit", 198, Rarity.UNCOMMON, mage.cards.t.TophTheBlindBandit.class)); cards.add(new SetCardInfo("Toph, the First Metalbender", 247, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Toph, the First Metalbender", 353, Rarity.RARE, mage.cards.t.TophTheFirstMetalbender.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 6a36947e65bdf8bc02841423934f196f90556419 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:27:23 -0500 Subject: [PATCH 067/261] [TLA] Implement Shared Roots --- Mage.Sets/src/mage/cards/s/SharedRoots.java | 37 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 38 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SharedRoots.java diff --git a/Mage.Sets/src/mage/cards/s/SharedRoots.java b/Mage.Sets/src/mage/cards/s/SharedRoots.java new file mode 100644 index 00000000000..2680eed5bad --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SharedRoots.java @@ -0,0 +1,37 @@ +package mage.cards.s; + +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCardInLibrary; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SharedRoots extends CardImpl { + + public SharedRoots(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}"); + + this.subtype.add(SubType.LESSON); + + // Search your library for a basic land card, put it onto the battlefield tapped, then shuffle. + this.getSpellAbility().addEffect(new SearchLibraryPutInPlayEffect( + new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true + )); + } + + private SharedRoots(final SharedRoots card) { + super(card); + } + + @Override + public SharedRoots copy() { + return new SharedRoots(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 18e88ec868a..4e58c3d3eb8 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -178,6 +178,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Seismic Sense", 195, Rarity.UNCOMMON, mage.cards.s.SeismicSense.class)); cards.add(new SetCardInfo("Serpent of the Pass", 70, Rarity.UNCOMMON, mage.cards.s.SerpentOfThePass.class)); cards.add(new SetCardInfo("Serpent's Pass", 279, Rarity.COMMON, mage.cards.s.SerpentsPass.class)); + cards.add(new SetCardInfo("Shared Roots", 196, Rarity.UNCOMMON, mage.cards.s.SharedRoots.class)); cards.add(new SetCardInfo("Sokka's Haiku", 71, Rarity.UNCOMMON, mage.cards.s.SokkasHaiku.class)); cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 240, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Bold Boomeranger", 383, Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 3d6d30561d196fd83bcf675d4c8783d98dc15088 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:29:20 -0500 Subject: [PATCH 068/261] [TLA] Implement Twin Blades --- Mage.Sets/src/mage/cards/t/TwinBlades.java | 52 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 53 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TwinBlades.java diff --git a/Mage.Sets/src/mage/cards/t/TwinBlades.java b/Mage.Sets/src/mage/cards/t/TwinBlades.java new file mode 100644 index 00000000000..d62bff46f3e --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TwinBlades.java @@ -0,0 +1,52 @@ +package mage.cards.t; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAttachToTarget; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TwinBlades extends CardImpl { + + public TwinBlades(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{R}"); + + this.subtype.add(SubType.EQUIPMENT); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // When this Equipment enters, attach it to target creature you control. That creature gains double strike until end of turn. + Ability ability = new EntersBattlefieldAttachToTarget(); + ability.addEffect(new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance()) + .setText("That creature gains double strike until end of turn")); + this.addAbility(ability); + + // Equipped creature gets +1/+1. + this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(1, 1))); + + // Equip {2} + this.addAbility(new EquipAbility(2)); + } + + private TwinBlades(final TwinBlades card) { + super(card); + } + + @Override + public TwinBlades copy() { + return new TwinBlades(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 4e58c3d3eb8..a6c4bf9db8f 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -214,6 +214,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("True Ancestry", 199, Rarity.UNCOMMON, mage.cards.t.TrueAncestry.class)); cards.add(new SetCardInfo("Tundra Tank", 121, Rarity.UNCOMMON, mage.cards.t.TundraTank.class)); cards.add(new SetCardInfo("Turtle-Duck", 200, Rarity.COMMON, mage.cards.t.TurtleDuck.class)); + cards.add(new SetCardInfo("Twin Blades", 157, Rarity.UNCOMMON, mage.cards.t.TwinBlades.class)); cards.add(new SetCardInfo("Ty Lee, Artful Acrobat", 158, Rarity.UNCOMMON, mage.cards.t.TyLeeArtfulAcrobat.class)); cards.add(new SetCardInfo("Uncle Iroh", 248, Rarity.UNCOMMON, mage.cards.u.UncleIroh.class)); cards.add(new SetCardInfo("United Front", 331, Rarity.MYTHIC, mage.cards.u.UnitedFront.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 7caf775696604ddbb6bcfeb588a0ee43e3cdfb19 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:32:36 -0500 Subject: [PATCH 069/261] [TLA] Implement Tiger-Dillo --- Mage.Sets/src/mage/cards/t/TigerDillo.java | 59 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 60 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TigerDillo.java diff --git a/Mage.Sets/src/mage/cards/t/TigerDillo.java b/Mage.Sets/src/mage/cards/t/TigerDillo.java new file mode 100644 index 00000000000..7738560091a --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TigerDillo.java @@ -0,0 +1,59 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.effects.common.combat.CantAttackBlockUnlessConditionSourceEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.PowerPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TigerDillo extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + + static { + filter.add(AnotherPredicate.instance); + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + private static final Hint hint = new ConditionHint( + condition, "You control another creature with power 4 or greature" + ); + + public TigerDillo(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.CAT); + this.subtype.add(SubType.ARMADILLO); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // This creature can't attack or block unless you control another creature with power 4 or greater. + this.addAbility(new SimpleStaticAbility(new CantAttackBlockUnlessConditionSourceEffect(condition)).addHint(hint)); + } + + private TigerDillo(final TigerDillo card) { + super(card); + } + + @Override + public TigerDillo copy() { + return new TigerDillo(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index a6c4bf9db8f..9098ee11abd 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -203,6 +203,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("The Mechanist, Aerial Artisan", 64, Rarity.RARE, mage.cards.t.TheMechanistAerialArtisan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Rise of Sozin", 117, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Rise of Sozin", 356, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Tiger-Dillo", 155, Rarity.UNCOMMON, mage.cards.t.TigerDillo.class)); cards.add(new SetCardInfo("Tiger-Seal", 318, Rarity.RARE, mage.cards.t.TigerSeal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tiger-Seal", 75, Rarity.RARE, mage.cards.t.TigerSeal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tolls of War", 245, Rarity.UNCOMMON, mage.cards.t.TollsOfWar.class)); -- 2.47.2 From 5bf5bda8e5b8dc553afedeee2877c9d64e4d4965 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:35:52 -0500 Subject: [PATCH 070/261] [TLA] Implement Gather the White Lotus --- .../src/mage/cards/g/GatherTheWhiteLotus.java | 43 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 44 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/g/GatherTheWhiteLotus.java diff --git a/Mage.Sets/src/mage/cards/g/GatherTheWhiteLotus.java b/Mage.Sets/src/mage/cards/g/GatherTheWhiteLotus.java new file mode 100644 index 00000000000..f280c96fcb6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GatherTheWhiteLotus.java @@ -0,0 +1,43 @@ +package mage.cards.g; + +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.common.FilterControlledPermanent; +import mage.game.permanent.token.AllyToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GatherTheWhiteLotus extends CardImpl { + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.PLAINS)); + private static final Hint hint = new ValueHint("Plains you control", xValue); + + public GatherTheWhiteLotus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}"); + + // Create a 1/1 white Ally creature token for each Plains you control. Scry 2. + this.getSpellAbility().addEffect(new CreateTokenEffect(new AllyToken(), xValue)); + this.getSpellAbility().addEffect(new ScryEffect(2)); + this.getSpellAbility().addHint(hint); + } + + private GatherTheWhiteLotus(final GatherTheWhiteLotus card) { + super(card); + } + + @Override + public GatherTheWhiteLotus copy() { + return new GatherTheWhiteLotus(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 9098ee11abd..1cf39bf8a5b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -101,6 +101,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Forest", 286, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Forest", 291, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Forest", 296, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Gather the White Lotus", 20, Rarity.UNCOMMON, mage.cards.g.GatherTheWhiteLotus.class)); cards.add(new SetCardInfo("Geyser Leaper", 52, Rarity.COMMON, mage.cards.g.GeyserLeaper.class)); cards.add(new SetCardInfo("Giant Koi", 53, Rarity.COMMON, mage.cards.g.GiantKoi.class)); cards.add(new SetCardInfo("Glider Kids", 21, Rarity.COMMON, mage.cards.g.GliderKids.class)); -- 2.47.2 From 48ee8eefc322aab127770d494c16ed2b80f9b645 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:37:25 -0500 Subject: [PATCH 071/261] [TLE] update reprints --- Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java | 7 +++++++ Utils/mtg-cards-data.txt | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 9603db89df8..f61015853d6 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -40,11 +40,14 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Arcane Signet", 315, Rarity.RARE, mage.cards.a.ArcaneSignet.class)); cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 130, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class)); cards.add(new SetCardInfo("Blasphemous Act", 26, Rarity.MYTHIC, mage.cards.b.BlasphemousAct.class)); + cards.add(new SetCardInfo("Bloodchief Ascension", 23, Rarity.MYTHIC, mage.cards.b.BloodchiefAscension.class)); cards.add(new SetCardInfo("Bribery", 10, Rarity.MYTHIC, mage.cards.b.Bribery.class)); cards.add(new SetCardInfo("Brought Back", 1, Rarity.MYTHIC, mage.cards.b.BroughtBack.class)); cards.add(new SetCardInfo("Bumi, Eclectic Earthbender", 248, Rarity.RARE, mage.cards.b.BumiEclecticEarthbender.class)); cards.add(new SetCardInfo("Capital Guard", 234, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Capital Guard", 277, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Clone Legion", 12, Rarity.MYTHIC, mage.cards.c.CloneLegion.class)); + cards.add(new SetCardInfo("Clone", 11, Rarity.MYTHIC, mage.cards.c.Clone.class)); cards.add(new SetCardInfo("Cruel Tutor", 24, Rarity.MYTHIC, mage.cards.c.CruelTutor.class)); cards.add(new SetCardInfo("Dark Depths", 56, Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); cards.add(new SetCardInfo("Deny Entry", 222, Rarity.COMMON, mage.cards.d.DenyEntry.class)); @@ -72,8 +75,10 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Force of Negation", 13, Rarity.MYTHIC, mage.cards.f.ForceOfNegation.class)); cards.add(new SetCardInfo("Frog-Squirrels", 251, Rarity.COMMON, mage.cards.f.FrogSquirrels.class)); cards.add(new SetCardInfo("Gilacorn", 231, Rarity.COMMON, mage.cards.g.Gilacorn.class)); + cards.add(new SetCardInfo("Heartbeat of Spring", 42, Rarity.MYTHIC, mage.cards.h.HeartbeatOfSpring.class)); cards.add(new SetCardInfo("Heroic Intervention", 43, Rarity.MYTHIC, mage.cards.h.HeroicIntervention.class)); cards.add(new SetCardInfo("Hippo-Cows", 252, Rarity.COMMON, mage.cards.h.HippoCows.class)); + cards.add(new SetCardInfo("Imprisoned in the Moon", 14, Rarity.MYTHIC, mage.cards.i.ImprisonedInTheMoon.class)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 240, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 282, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); @@ -113,6 +118,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Purple Pentapus", 233, Rarity.COMMON, mage.cards.p.PurplePentapus.class)); cards.add(new SetCardInfo("Razor Rings", 272, Rarity.COMMON, mage.cards.r.RazorRings.class)); cards.add(new SetCardInfo("Release to Memory", 5, Rarity.MYTHIC, mage.cards.r.ReleaseToMemory.class)); + cards.add(new SetCardInfo("Return of the Wildspeaker", 44, Rarity.MYTHIC, mage.cards.r.ReturnOfTheWildspeaker.class)); cards.add(new SetCardInfo("Rhys the Redeemed", 52, Rarity.MYTHIC, mage.cards.r.RhysTheRedeemed.class)); cards.add(new SetCardInfo("Rites of Flourishing", 45, Rarity.MYTHIC, mage.cards.r.RitesOfFlourishing.class)); cards.add(new SetCardInfo("Roku's Mastery", 243, Rarity.UNCOMMON, mage.cards.r.RokusMastery.class)); @@ -127,6 +133,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Standstill", 19, Rarity.MYTHIC, mage.cards.s.Standstill.class)); cards.add(new SetCardInfo("Sundial of the Infinite", 55, Rarity.MYTHIC, mage.cards.s.SundialOfTheInfinite.class)); cards.add(new SetCardInfo("Swiftfoot Boots", 317, Rarity.RARE, mage.cards.s.SwiftfootBoots.class)); + cards.add(new SetCardInfo("Teferi's Protection", 7, Rarity.MYTHIC, mage.cards.t.TeferisProtection.class)); cards.add(new SetCardInfo("The Cabbage Merchant", 134, Rarity.RARE, mage.cards.t.TheCabbageMerchant.class)); cards.add(new SetCardInfo("The Great Henge", 41, Rarity.MYTHIC, mage.cards.t.TheGreatHenge.class)); cards.add(new SetCardInfo("The Terror of Serpent's Pass", 225, Rarity.RARE, mage.cards.t.TheTerrorOfSerpentsPass.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 444ff1c4e49..4d6db105bfb 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -60370,20 +60370,27 @@ Radioactive Spider|Marvel's Spider-Man|285|R|{G}|Creature - Spider|1|1|Reach, de Gwenom, Remorseless|Marvel's Spider-Man|286|M|{3}{B}{B}|Legendary Creature - Symbiote Spider Hero|4|4|Deathtouch, lifelink$Whenever Gwenom attacks, until end of turn you may look at the top card of your library any time and you may play cards from the top of your library. If you cast a spell this way, pay life equal to its mana value rather than pay its mana cost.| Brought Back|Avatar: The Last Airbender Eternal|1|M|{W}{W}|Instant|||Choose up to two target permanent cards in your graveyard that were put there from the battlefield this turn. Return them to the battlefield tapped.| Release to Memory|Avatar: The Last Airbender Eternal|5|M|{3}{W}|Instant|||Exile target opponent's graveyard. For each creature card exiled this way, create a 1/1 colorless Spirit creature token.| +Teferi's Protection|Avatar: The Last Airbender Eternal|7|M|{2}{W}|Instant|||Until your next turn, your life total can't change and you gain protection from everything. All permanents you control phase out.$Exile Teferi's Protection.| Agent of Treachery|Avatar: The Last Airbender Eternal|9|M|{5}{U}{U}|Creature - Human Rogue|2|3|When this creature enters, gain control of target permanent.$At the beginning of your end step, if you control three or more permanents you don't own, draw three cards.| Bribery|Avatar: The Last Airbender Eternal|10|M|{3}{U}{U}|Sorcery|||Search target opponent's library for a creature card and put that card onto the battlefield under your control. Then that player shuffles.| +Clone|Avatar: The Last Airbender Eternal|11|M|{3}{U}|Creature - Shapeshifter|0|0|You may have this creature enter as a copy of any creature on the battlefield.| +Clone Legion|Avatar: The Last Airbender Eternal|12|M|{7}{U}{U}|Sorcery|||For each creature target player controls, create a token that's a copy of that creature.| Force of Negation|Avatar: The Last Airbender Eternal|13|M|{1}{U}{U}|Instant|||If it's not your turn, you may exile a blue card from your hand rather than pay this spell's mana cost.$Counter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.| +Imprisoned in the Moon|Avatar: The Last Airbender Eternal|14|M|{2}{U}|Enchantment - Aura|||Enchant creature, land, or planeswalker$Enchanted permanent is a colorless land with "{T}: Add {C}" and loses all other card types and abilities.| Mystic Remora|Avatar: The Last Airbender Eternal|16|M|{U}|Enchantment|||Cumulative upkeep {1}$Whenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}.| Prosperity|Avatar: The Last Airbender Eternal|17|M|{X}{U}|Sorcery|||Each player draws X cards.| Standstill|Avatar: The Last Airbender Eternal|19|M|{1}{U}|Enchantment|||When a player casts a spell, sacrifice this enchantment. If you do, each of that player's opponents draws three cards.| Training Grounds|Avatar: The Last Airbender Eternal|20|M|{U}|Enchantment|||Activated abilities of creatures you control cost {2} less to activate. This effect can't reduce the mana in that cost to less than one mana.| +Bloodchief Ascension|Avatar: The Last Airbender Eternal|23|M|{B}|Enchantment|||At the beginning of each end step, if an opponent lost 2 or more life this turn, you may put a quest counter on this enchantment.$Whenever a card is put into an opponent's graveyard from anywhere, if this enchantment has three or more quest counters on it, you may have that player lose 2 life. If you do, you gain 2 life.| Cruel Tutor|Avatar: The Last Airbender Eternal|24|M|{2}{B}|Sorcery|||Search your library for a card, then shuffle and put that card on top. You lose 2 life.| Noxious Gearhulk|Avatar: The Last Airbender Eternal|25|M|{4}{B}{B}|Artifact Creature - Construct|5|4|Menace$When this creature enters, you may destroy another target creature. If a creature is destroyed this way, you gain life equal to its toughness.| Blasphemous Act|Avatar: The Last Airbender Eternal|26|M|{8}{R}|Sorcery|||This spell costs {1} less to cast for each creature on the battlefield.$Blasphemous Act deals 13 damage to each creature.| Dockside Extortionist|Avatar: The Last Airbender Eternal|28|M|{1}{R}|Creature - Goblin Pirate|1|2|When this creature enters, create X Treasure tokens, where X is the number of artifacts and enchantments your opponents control.| Mirrorwing Dragon|Avatar: The Last Airbender Eternal|33|M|{3}{R}{R}|Creature - Dragon|4|5|Flying$Whenever a player casts an instant or sorcery spell that targets only this creature, that player copies that spell for each other creature they control that the spell could target. Each copy targets a different one of those creatures.| The Great Henge|Avatar: The Last Airbender Eternal|41|M|{7}{G}{G}|Legendary Artifact|||This spell costs {X} less to cast, where X is the greatest power among creatures you control.${T}: Add {G}{G}. You gain 2 life.$Whenever a nontoken creature you control enters, put a +1/+1 counter on it and draw a card.| +Heartbeat of Spring|Avatar: The Last Airbender Eternal|42|M|{2}{G}|Enchantment|||Whenever a player taps a land for mana, that player adds one mana of any type that land produced.| Heroic Intervention|Avatar: The Last Airbender Eternal|43|M|{1}{G}|Instant|||Permanents you control gain hexproof and indestructible until end of turn.| +Return of the Wildspeaker|Avatar: The Last Airbender Eternal|44|M|{4}{G}|Instant|||Choose one --$* Draw cards equal to the greatest power among non-Human creatures you control.$* Non-Human creatures you control get +3/+3 until end of turn.| Rites of Flourishing|Avatar: The Last Airbender Eternal|45|M|{2}{G}|Enchantment|||At the beginning of each player's draw step, that player draws an additional card.$Each player may play an additional land on each of their turns.| Eladamri's Call|Avatar: The Last Airbender Eternal|48|M|{G}{W}|Instant|||Search your library for a creature card, reveal that card, put it into your hand, then shuffle.| Rhys the Redeemed|Avatar: The Last Airbender Eternal|52|M|{G/W}|Legendary Creature - Elf Warrior|1|1|{2}{G/W}, {T}: Create a 1/1 green and white Elf Warrior creature token.${4}{G/W}{G/W}, {T}: For each creature token you control, create a token that's a copy of that creature.| -- 2.47.2 From ff79d9503e7078be274e285f4e01575151b048ae Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:38:02 -0500 Subject: [PATCH 072/261] [SLC] update set --- .../src/mage/sets/SecretLairCountdown.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Mage.Sets/src/mage/sets/SecretLairCountdown.java b/Mage.Sets/src/mage/sets/SecretLairCountdown.java index 62c60ec020e..963489f2db8 100644 --- a/Mage.Sets/src/mage/sets/SecretLairCountdown.java +++ b/Mage.Sets/src/mage/sets/SecretLairCountdown.java @@ -19,36 +19,62 @@ public class SecretLairCountdown extends ExpansionSet { super("Secret Lair Countdown", "SLC", ExpansionSet.buildDate(2022, 11, 1), SetType.PROMOTIONAL); this.hasBasicLands = false; + cards.add(new SetCardInfo("Altar of the Brood", 1, Rarity.RARE, mage.cards.a.AltarOfTheBrood.class)); cards.add(new SetCardInfo("Arclight Phoenix", 2018, Rarity.MYTHIC, mage.cards.a.ArclightPhoenix.class)); cards.add(new SetCardInfo("Birthing Pod", 2011, Rarity.RARE, mage.cards.b.BirthingPod.class)); cards.add(new SetCardInfo("Bloodbraid Elf", 2009, Rarity.RARE, mage.cards.b.BloodbraidElf.class)); cards.add(new SetCardInfo("Bogardan Hellkite", 2006, Rarity.MYTHIC, mage.cards.b.BogardanHellkite.class)); + cards.add(new SetCardInfo("Brain Freeze", 2, Rarity.RARE, mage.cards.b.BrainFreeze.class)); cards.add(new SetCardInfo("Chrome Mox", 2003, Rarity.MYTHIC, mage.cards.c.ChromeMox.class, RETRO_ART)); + cards.add(new SetCardInfo("Crop Rotation", 3, Rarity.RARE, mage.cards.c.CropRotation.class)); cards.add(new SetCardInfo("Deathrite Shaman", 2012, Rarity.RARE, mage.cards.d.DeathriteShaman.class)); + cards.add(new SetCardInfo("Demonic Consultation", 4, Rarity.RARE, mage.cards.d.DemonicConsultation.class)); cards.add(new SetCardInfo("Dragonlord Ojutai", 2015, Rarity.MYTHIC, mage.cards.d.DragonlordOjutai.class)); + cards.add(new SetCardInfo("Eerie Ultimatum", 5, Rarity.RARE, mage.cards.e.EerieUltimatum.class)); cards.add(new SetCardInfo("Elite Spellbinder", 2021, Rarity.RARE, mage.cards.e.EliteSpellbinder.class)); cards.add(new SetCardInfo("Elspeth, Sun's Champion", 2013, Rarity.MYTHIC, mage.cards.e.ElspethSunsChampion.class, RETRO_ART)); cards.add(new SetCardInfo("Emry, Lurker of the Loch", 2019, Rarity.RARE, mage.cards.e.EmryLurkerOfTheLoch.class)); + cards.add(new SetCardInfo("Field of the Dead", 6, Rarity.RARE, mage.cards.f.FieldOfTheDead.class)); cards.add(new SetCardInfo("Genesis", 2002, Rarity.RARE, mage.cards.g.Genesis.class)); cards.add(new SetCardInfo("Glimpse of Nature", 2004, Rarity.RARE, mage.cards.g.GlimpseOfNature.class)); + cards.add(new SetCardInfo("Gray Merchant of Asphodel", 7, Rarity.RARE, mage.cards.g.GrayMerchantOfAsphodel.class)); cards.add(new SetCardInfo("Heritage Druid", 2008, Rarity.RARE, mage.cards.h.HeritageDruid.class)); + cards.add(new SetCardInfo("Hymn to Tourach", 8, Rarity.RARE, mage.cards.h.HymnToTourach.class)); + cards.add(new SetCardInfo("Isochron Scepter", 9, Rarity.RARE, mage.cards.i.IsochronScepter.class)); + cards.add(new SetCardInfo("Junji, the Midnight Sky", 10, Rarity.MYTHIC, mage.cards.j.JunjiTheMidnightSky.class)); + cards.add(new SetCardInfo("Krark-Clan Ironworks", 11, Rarity.RARE, mage.cards.k.KrarkClanIronworks.class)); cards.add(new SetCardInfo("Lightning Helix", 2005, Rarity.RARE, mage.cards.l.LightningHelix.class)); cards.add(new SetCardInfo("Lim-Dul's Vault", 1996, Rarity.RARE, mage.cards.l.LimDulsVault.class)); cards.add(new SetCardInfo("Lin Sivvi, Defiant Hero", 2000, Rarity.RARE, mage.cards.l.LinSivviDefiantHero.class)); + cards.add(new SetCardInfo("Llanowar Elves", 12, Rarity.RARE, mage.cards.l.LlanowarElves.class)); cards.add(new SetCardInfo("Lotus Field", 2023, Rarity.MYTHIC, mage.cards.l.LotusField.class)); cards.add(new SetCardInfo("Mishra's Factory", 1994, Rarity.RARE, mage.cards.m.MishrasFactory.class)); + cards.add(new SetCardInfo("Myrel, Shield of Argive", 13, Rarity.RARE, mage.cards.m.MyrelShieldOfArgive.class)); + cards.add(new SetCardInfo("Narset's Reversal", 14, Rarity.RARE, mage.cards.n.NarsetsReversal.class)); cards.add(new SetCardInfo("Nashi, Moon Sage's Scion", 2022, Rarity.MYTHIC, mage.cards.n.NashiMoonSagesScion.class)); cards.add(new SetCardInfo("Necropotence", 1995, Rarity.MYTHIC, mage.cards.n.Necropotence.class)); cards.add(new SetCardInfo("Nicol Bolas, God-Pharaoh", 2017, Rarity.MYTHIC, mage.cards.n.NicolBolasGodPharaoh.class)); + cards.add(new SetCardInfo("Ob Nixilis, the Fallen", 15, Rarity.MYTHIC, mage.cards.o.ObNixilisTheFallen.class)); + cards.add(new SetCardInfo("Phyrexian Altar", 16, Rarity.RARE, mage.cards.p.PhyrexianAltar.class)); cards.add(new SetCardInfo("Ponder", 2007, Rarity.RARE, mage.cards.p.Ponder.class)); + cards.add(new SetCardInfo("Questing Beast", 17, Rarity.MYTHIC, mage.cards.q.QuestingBeast.class)); + cards.add(new SetCardInfo("Retrofitter Foundry", 18, Rarity.RARE, mage.cards.r.RetrofitterFoundry.class)); cards.add(new SetCardInfo("Shark Typhoon", 2020, Rarity.RARE, mage.cards.s.SharkTyphoon.class)); cards.add(new SetCardInfo("Shivan Dragon", 1993, Rarity.RARE, mage.cards.s.ShivanDragon.class)); cards.add(new SetCardInfo("Siege Rhino", 2014, Rarity.RARE, mage.cards.s.SiegeRhino.class)); cards.add(new SetCardInfo("Smokestack", 1998, Rarity.RARE, mage.cards.s.Smokestack.class)); + cards.add(new SetCardInfo("Sol Ring", 19, Rarity.RARE, mage.cards.s.SolRing.class)); cards.add(new SetCardInfo("Squee, Goblin Nabob", 1999, Rarity.RARE, mage.cards.s.SqueeGoblinNabob.class)); cards.add(new SetCardInfo("Sun Titan", 2010, Rarity.MYTHIC, mage.cards.s.SunTitan.class)); + cards.add(new SetCardInfo("Temple of the False God", 20, Rarity.RARE, mage.cards.t.TempleOfTheFalseGod.class)); cards.add(new SetCardInfo("Thalia, Heretic Cathar", 2016, Rarity.RARE, mage.cards.t.ThaliaHereticCathar.class)); cards.add(new SetCardInfo("Tradewind Rider", 1997, Rarity.RARE, mage.cards.t.TradewindRider.class)); + cards.add(new SetCardInfo("Urza's Saga", 21, Rarity.RARE, mage.cards.u.UrzasSaga.class)); + cards.add(new SetCardInfo("Vesuva", 22, Rarity.RARE, mage.cards.v.Vesuva.class)); + cards.add(new SetCardInfo("Wasteland", 23, Rarity.RARE, mage.cards.w.Wasteland.class)); cards.add(new SetCardInfo("Wild Mongrel", 2001, Rarity.RARE, mage.cards.w.WildMongrel.class)); + cards.add(new SetCardInfo("Xantcha, Sleeper Agent", 24, Rarity.RARE, mage.cards.x.XantchaSleeperAgent.class)); + cards.add(new SetCardInfo("Yarok, the Desecrated", 25, Rarity.MYTHIC, mage.cards.y.YarokTheDesecrated.class)); + cards.add(new SetCardInfo("Zo-Zu the Punisher", 26, Rarity.RARE, mage.cards.z.ZoZuThePunisher.class)); } } -- 2.47.2 From a205bba84982fe9750435f130afbdf03d74880b7 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:39:43 -0500 Subject: [PATCH 073/261] [TLA] Implement Zhao, Ruthless Admiral --- .../src/mage/cards/z/ZhaoRuthlessAdmiral.java | 56 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 57 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/z/ZhaoRuthlessAdmiral.java diff --git a/Mage.Sets/src/mage/cards/z/ZhaoRuthlessAdmiral.java b/Mage.Sets/src/mage/cards/z/ZhaoRuthlessAdmiral.java new file mode 100644 index 00000000000..e002bedb33c --- /dev/null +++ b/Mage.Sets/src/mage/cards/z/ZhaoRuthlessAdmiral.java @@ -0,0 +1,56 @@ +package mage.cards.z; + +import mage.MageInt; +import mage.abilities.common.SacrificePermanentTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.FirebendingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ZhaoRuthlessAdmiral extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent("another permanent"); + + static { + filter.add(AnotherPredicate.instance); + } + + public ZhaoRuthlessAdmiral(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B/R}{B/R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Firebending 2 + this.addAbility(new FirebendingAbility(2)); + + // Whenever you sacrifice another permanent, creatures you control get +1/+0 until end of turn. + this.addAbility(new SacrificePermanentTriggeredAbility( + new BoostControlledEffect(1, 0, Duration.EndOfTurn), filter + )); + } + + private ZhaoRuthlessAdmiral(final ZhaoRuthlessAdmiral card) { + super(card); + } + + @Override + public ZhaoRuthlessAdmiral copy() { + return new ZhaoRuthlessAdmiral(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 1cf39bf8a5b..c83cf366cf5 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -231,6 +231,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Yue, the Moon Spirit", 338, Rarity.RARE, mage.cards.y.YueTheMoonSpirit.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Yue, the Moon Spirit", 83, Rarity.RARE, mage.cards.y.YueTheMoonSpirit.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Yuyan Archers", 161, Rarity.COMMON, mage.cards.y.YuyanArchers.class)); + cards.add(new SetCardInfo("Zhao, Ruthless Admiral", 252, Rarity.UNCOMMON, mage.cards.z.ZhaoRuthlessAdmiral.class)); cards.add(new SetCardInfo("Zuko's Exile", 3, Rarity.COMMON, mage.cards.z.ZukosExile.class)); cards.add(new SetCardInfo("Zuko, Exiled Prince", 163, Rarity.UNCOMMON, mage.cards.z.ZukoExiledPrince.class)); -- 2.47.2 From 698f1d4668acce7d4adefb71d5ff78162d54e3b8 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:41:42 -0500 Subject: [PATCH 074/261] [TLA] Implement The Unagi of Kyoshi Island --- .../mage/cards/t/TheUnagiOfKyoshiIsland.java | 52 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 54 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TheUnagiOfKyoshiIsland.java diff --git a/Mage.Sets/src/mage/cards/t/TheUnagiOfKyoshiIsland.java b/Mage.Sets/src/mage/cards/t/TheUnagiOfKyoshiIsland.java new file mode 100644 index 00000000000..0474f6d5631 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheUnagiOfKyoshiIsland.java @@ -0,0 +1,52 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.DrawNthCardTriggeredAbility; +import mage.abilities.costs.common.WaterbendCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.WardAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheUnagiOfKyoshiIsland extends CardImpl { + + public TheUnagiOfKyoshiIsland(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.SERPENT); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Ward--Waterbend {4} + this.addAbility(new WardAbility(new WaterbendCost(4))); + + // Whenever an opponent draws their second card each turn, draw two cards. + this.addAbility(new DrawNthCardTriggeredAbility( + new DrawCardSourceControllerEffect(2), + false, TargetController.OPPONENT, 2 + )); + } + + private TheUnagiOfKyoshiIsland(final TheUnagiOfKyoshiIsland card) { + super(card); + } + + @Override + public TheUnagiOfKyoshiIsland copy() { + return new TheUnagiOfKyoshiIsland(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index c83cf366cf5..fe4b5cd4177 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -204,6 +204,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("The Mechanist, Aerial Artisan", 64, Rarity.RARE, mage.cards.t.TheMechanistAerialArtisan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Rise of Sozin", 117, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Rise of Sozin", 356, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Unagi of Kyoshi Island", 319, Rarity.RARE, mage.cards.t.TheUnagiOfKyoshiIsland.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Unagi of Kyoshi Island", 77, Rarity.RARE, mage.cards.t.TheUnagiOfKyoshiIsland.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tiger-Dillo", 155, Rarity.UNCOMMON, mage.cards.t.TigerDillo.class)); cards.add(new SetCardInfo("Tiger-Seal", 318, Rarity.RARE, mage.cards.t.TigerSeal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tiger-Seal", 75, Rarity.RARE, mage.cards.t.TigerSeal.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 6e0d6dfc36fd0257a99c507cdb1ea237882a6a3c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:45:22 -0500 Subject: [PATCH 075/261] [TLA] Implement Callous Inspector --- .../src/mage/cards/c/CallousInspector.java | 47 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 48 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CallousInspector.java diff --git a/Mage.Sets/src/mage/cards/c/CallousInspector.java b/Mage.Sets/src/mage/cards/c/CallousInspector.java new file mode 100644 index 00000000000..0f092d36217 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CallousInspector.java @@ -0,0 +1,47 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DamageControllerEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.ClueArtifactToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CallousInspector extends CardImpl { + + public CallousInspector(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Menace + this.addAbility(new MenaceAbility()); + + // When this creature dies, it deals 1 damage to you. Create a Clue token. + Ability ability = new DiesSourceTriggeredAbility(new DamageControllerEffect(1, "it")); + ability.addEffect(new CreateTokenEffect(new ClueArtifactToken())); + this.addAbility(ability); + } + + private CallousInspector(final CallousInspector card) { + super(card); + } + + @Override + public CallousInspector copy() { + return new CallousInspector(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index fe4b5cd4177..3c428c82057 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -54,6 +54,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Bumi, Unleashed", 211, Rarity.MYTHIC, mage.cards.b.BumiUnleashed.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bumi, Unleashed", 348, Rarity.MYTHIC, mage.cards.b.BumiUnleashed.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Buzzard-Wasp Colony", 88, Rarity.UNCOMMON, mage.cards.b.BuzzardWaspColony.class)); + cards.add(new SetCardInfo("Callous Inspector", 89, Rarity.COMMON, mage.cards.c.CallousInspector.class)); cards.add(new SetCardInfo("Cat-Gator", 91, Rarity.UNCOMMON, mage.cards.c.CatGator.class)); cards.add(new SetCardInfo("Cat-Owl", 212, Rarity.COMMON, mage.cards.c.CatOwl.class)); cards.add(new SetCardInfo("Compassionate Healer", 13, Rarity.COMMON, mage.cards.c.CompassionateHealer.class)); -- 2.47.2 From 777bb176bf156958211f6318a6be3366f07c4bb0 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 18:52:34 -0500 Subject: [PATCH 076/261] [TLA] Implement Platypus-Bear --- Mage.Sets/src/mage/cards/p/PlatypusBear.java | 60 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + .../src/main/java/mage/constants/SubType.java | 1 + 3 files changed, 62 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/PlatypusBear.java diff --git a/Mage.Sets/src/mage/cards/p/PlatypusBear.java b/Mage.Sets/src/mage/cards/p/PlatypusBear.java new file mode 100644 index 00000000000..3bbe15feeb9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PlatypusBear.java @@ -0,0 +1,60 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.decorator.ConditionalAsThoughEffect; +import mage.abilities.effects.common.MillCardsControllerEffect; +import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderSourceEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterCard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PlatypusBear extends CardImpl { + + private static final Condition condition = new CardsInControllerGraveyardCondition(1, new FilterCard(SubType.LESSON)); + private static final Hint hint = new ConditionHint(condition, "There is a Lesson card in your graveyard"); + + public PlatypusBear(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G/U}"); + + this.subtype.add(SubType.PLATYPUS); + this.subtype.add(SubType.BEAR); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // When this creature enters, mill two cards. + this.addAbility(new EntersBattlefieldTriggeredAbility(new MillCardsControllerEffect(2))); + + // As long as there is a Lesson card in your graveyard, this creature can attack as though it didn't have defender. + this.addAbility(new SimpleStaticAbility(new ConditionalAsThoughEffect( + new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.WhileOnBattlefield), condition + ).setText("as long as there is a Lesson card in your graveyard, " + + "this creature can attack as though it didn't have defender")).addHint(hint)); + } + + private PlatypusBear(final PlatypusBear card) { + super(card); + } + + @Override + public PlatypusBear copy() { + return new PlatypusBear(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 3c428c82057..f199522d880 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -164,6 +164,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Plains", 292, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Planetarium of Wan Shi Tong", 259, Rarity.MYTHIC, mage.cards.p.PlanetariumOfWanShiTong.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Planetarium of Wan Shi Tong", 385, Rarity.MYTHIC, mage.cards.p.PlanetariumOfWanShiTong.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Platypus-Bear", 236, Rarity.COMMON, mage.cards.p.PlatypusBear.class)); cards.add(new SetCardInfo("Pretending Poxbearers", 237, Rarity.COMMON, mage.cards.p.PretendingPoxbearers.class)); cards.add(new SetCardInfo("Rabaroo Troop", 32, Rarity.COMMON, mage.cards.r.RabarooTroop.class)); cards.add(new SetCardInfo("Ran and Shaw", 150, Rarity.RARE, mage.cards.r.RanAndShaw.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 9c4e5d3c6a0..ac396d048b2 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -333,6 +333,7 @@ public enum SubType { PINCHER("Pincher", SubTypeSet.CreatureType), PIRATE("Pirate", SubTypeSet.CreatureType), PLANT("Plant", SubTypeSet.CreatureType), + PLATYPUS("Platypus", SubTypeSet.CreatureType), PORCUPINE("Porcupine", SubTypeSet.CreatureType), POSSUM("Possum", SubTypeSet.CreatureType), PRAETOR("Praetor", SubTypeSet.CreatureType), -- 2.47.2 From 1ec089710185ff6eb386c34969a5d79c3b7118f2 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 19:00:18 -0500 Subject: [PATCH 077/261] [TLA] Implement The Spirit Oasis --- .../src/mage/cards/t/TheSpiritOasis.java | 55 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 56 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TheSpiritOasis.java diff --git a/Mage.Sets/src/mage/cards/t/TheSpiritOasis.java b/Mage.Sets/src/mage/cards/t/TheSpiritOasis.java new file mode 100644 index 00000000000..750985f58ae --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheSpiritOasis.java @@ -0,0 +1,55 @@ +package mage.cards.t; + +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +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.FilterControlledPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheSpiritOasis extends CardImpl { + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.SHRINE)); + private static final Hint hint = new ValueHint("Shrines you control", xValue); + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SHRINE, "another Shrine you control"); + + static { + filter.add(AnotherPredicate.instance); + } + + public TheSpiritOasis(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.SHRINE); + + // When The Spirit Oasis enters, draw a card for each Shrine you control. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(xValue))); + + // Whenever another Shrine you control enters, draw a card. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)); + } + + private TheSpiritOasis(final TheSpiritOasis card) { + super(card); + } + + @Override + public TheSpiritOasis copy() { + return new TheSpiritOasis(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index f199522d880..49da9a05bff 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -206,6 +206,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("The Mechanist, Aerial Artisan", 64, Rarity.RARE, mage.cards.t.TheMechanistAerialArtisan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Rise of Sozin", 117, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Rise of Sozin", 356, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Spirit Oasis", 72, Rarity.UNCOMMON, mage.cards.t.TheSpiritOasis.class)); cards.add(new SetCardInfo("The Unagi of Kyoshi Island", 319, Rarity.RARE, mage.cards.t.TheUnagiOfKyoshiIsland.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Unagi of Kyoshi Island", 77, Rarity.RARE, mage.cards.t.TheUnagiOfKyoshiIsland.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tiger-Dillo", 155, Rarity.UNCOMMON, mage.cards.t.TigerDillo.class)); -- 2.47.2 From cbd6d110872cfc65f92561f94fc3ca7576094106 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 19:04:48 -0500 Subject: [PATCH 078/261] [TLA] Implement Earth King's Lieutenant --- .../mage/cards/e/EarthKingsLieutenant.java | 66 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 68 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EarthKingsLieutenant.java diff --git a/Mage.Sets/src/mage/cards/e/EarthKingsLieutenant.java b/Mage.Sets/src/mage/cards/e/EarthKingsLieutenant.java new file mode 100644 index 00000000000..49c957bad4e --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EarthKingsLieutenant.java @@ -0,0 +1,66 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EarthKingsLieutenant extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(SubType.ALLY); + private static final FilterPermanent filter2 = new FilterControlledPermanent(SubType.ALLY, "another Ally you control"); + + static { + filter.add(AnotherPredicate.instance); + filter2.add(AnotherPredicate.instance); + } + + public EarthKingsLieutenant(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // When this creature enters, put a +1/+1 counter on each other Ally creature you control. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter) + .setText("put a +1/+1 counter on each other Ally creature you control") + )); + + // Whenever another Ally you control enters, put a +1/+1 counter on this creature. + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter2 + )); + } + + private EarthKingsLieutenant(final EarthKingsLieutenant card) { + super(card); + } + + @Override + public EarthKingsLieutenant copy() { + return new EarthKingsLieutenant(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 49da9a05bff..620509e3de1 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -68,6 +68,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Diligent Zookeeper", 171, Rarity.RARE, mage.cards.d.DiligentZookeeper.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Diligent Zookeeper", 327, Rarity.RARE, mage.cards.d.DiligentZookeeper.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dragonfly Swarm", 215, Rarity.UNCOMMON, mage.cards.d.DragonflySwarm.class)); + cards.add(new SetCardInfo("Earth King's Lieutenant", 217, Rarity.RARE, mage.cards.e.EarthKingsLieutenant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Earth King's Lieutenant", 380, Rarity.RARE, mage.cards.e.EarthKingsLieutenant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earth Kingdom Soldier", 216, Rarity.COMMON, mage.cards.e.EarthKingdomSoldier.class)); cards.add(new SetCardInfo("Earth Rumble", 174, Rarity.UNCOMMON, mage.cards.e.EarthRumble.class)); cards.add(new SetCardInfo("Earth Village Ruffians", 219, Rarity.COMMON, mage.cards.e.EarthVillageRuffians.class)); -- 2.47.2 From 5ff8881d192fa5a48d6b19e667e3477ff84bbb78 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 19:10:52 -0500 Subject: [PATCH 079/261] [TLA] Implement The Lion Turtle --- Mage.Sets/src/mage/cards/t/TheLionTurtle.java | 71 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 73 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TheLionTurtle.java diff --git a/Mage.Sets/src/mage/cards/t/TheLionTurtle.java b/Mage.Sets/src/mage/cards/t/TheLionTurtle.java new file mode 100644 index 00000000000..543651f65dd --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheLionTurtle.java @@ -0,0 +1,71 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.combat.CantAttackBlockUnlessConditionSourceEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.abilities.keyword.ReachAbility; +import mage.abilities.keyword.VigilanceAbility; +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.filter.FilterCard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheLionTurtle extends CardImpl { + + private static final Condition condition = new CardsInControllerGraveyardCondition( + 3, new FilterCard(SubType.LESSON, "Lesson cards") + ); + private static final Hint hint = new ValueHint( + "Lesson cards in your graveyard", new CardsInControllerGraveyardCount(new FilterCard(SubType.LESSON)) + ); + + public TheLionTurtle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.ELDER); + this.subtype.add(SubType.CAT); + this.subtype.add(SubType.TURTLE); + this.power = new MageInt(3); + this.toughness = new MageInt(6); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // When The Lion-Turtle enters, you gain 3 life. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3))); + + // The Lion-Turtle can't attack or block unless there are three or more Lesson cards in your graveyard. + this.addAbility(new SimpleStaticAbility(new CantAttackBlockUnlessConditionSourceEffect(condition)).addHint(hint)); + + // {T}: Add one mana of any color. + this.addAbility(new AnyColorManaAbility()); + } + + private TheLionTurtle(final TheLionTurtle card) { + super(card); + } + + @Override + public TheLionTurtle copy() { + return new TheLionTurtle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 620509e3de1..03c71d87523 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -204,6 +204,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Swamp", 289, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swamp", 294, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("The Cave of Two Lovers", 126, Rarity.UNCOMMON, mage.cards.t.TheCaveOfTwoLovers.class)); + 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)); cards.add(new SetCardInfo("The Mechanist, Aerial Artisan", 64, Rarity.RARE, mage.cards.t.TheMechanistAerialArtisan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Rise of Sozin", 117, Rarity.MYTHIC, mage.cards.t.TheRiseOfSozin.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 64cde5ec1766599ea073f490b9f34473c616e893 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 19:50:09 -0500 Subject: [PATCH 080/261] [TLA] Implement Guru Pathik --- Mage.Sets/src/mage/cards/g/GuruPathik.java | 76 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 77 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/g/GuruPathik.java diff --git a/Mage.Sets/src/mage/cards/g/GuruPathik.java b/Mage.Sets/src/mage/cards/g/GuruPathik.java new file mode 100644 index 00000000000..2e4271ec413 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GuruPathik.java @@ -0,0 +1,76 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.PutCards; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.FilterSpell; +import mage.filter.StaticFilters; +import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GuruPathik extends CardImpl { + + private static final FilterCard filter = new FilterCard("a Lesson, Saga, or Shrine card"); + private static final FilterSpell filter2 = new FilterSpell("a Lesson, Saga, or Shrine spell"); + + static { + filter.add(Predicates.or( + SubType.LESSON.getPredicate(), + SubType.SAGA.getPredicate(), + SubType.SHRINE.getPredicate() + )); + filter2.add(Predicates.or( + SubType.LESSON.getPredicate(), + SubType.SAGA.getPredicate(), + SubType.SHRINE.getPredicate() + )); + } + + public GuruPathik(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G/U}{G/U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.MONK); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // When Guru Pathik enters, look at the top five cards of your library. You may reveal a Lesson, Saga, or Shrine card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. + this.addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect( + 5, 1, filter, PutCards.HAND, PutCards.BOTTOM_RANDOM + ))); + + // Whenever you cast a Lesson, Saga, or Shrine spell, put a +1/+1 counter on another target creature you control. + Ability ability = new SpellCastControllerTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance()), filter2, false + ); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + this.addAbility(ability); + } + + private GuruPathik(final GuruPathik card) { + super(card); + } + + @Override + public GuruPathik copy() { + return new GuruPathik(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 03c71d87523..1486f05228a 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -110,6 +110,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Glider Kids", 21, Rarity.COMMON, mage.cards.g.GliderKids.class)); cards.add(new SetCardInfo("Glider Staff", 22, Rarity.UNCOMMON, mage.cards.g.GliderStaff.class)); cards.add(new SetCardInfo("Gran-Gran", 54, Rarity.UNCOMMON, mage.cards.g.GranGran.class)); + cards.add(new SetCardInfo("Guru Pathik", 223, Rarity.UNCOMMON, mage.cards.g.GuruPathik.class)); cards.add(new SetCardInfo("Hakoda, Selfless Commander", 366, Rarity.RARE, mage.cards.h.HakodaSelflessCommander.class)); cards.add(new SetCardInfo("Haru, Hidden Talent", 182, Rarity.UNCOMMON, mage.cards.h.HaruHiddenTalent.class)); cards.add(new SetCardInfo("Heartless Act", 103, Rarity.UNCOMMON, mage.cards.h.HeartlessAct.class)); -- 2.47.2 From 269162bf321d875b98fb1a8d8f79b89a3cc29076 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 19:54:16 -0500 Subject: [PATCH 081/261] [TLA] Implement Invasion Submersible --- .../src/mage/cards/i/InvasionSubmersible.java | 61 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 62 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/InvasionSubmersible.java diff --git a/Mage.Sets/src/mage/cards/i/InvasionSubmersible.java b/Mage.Sets/src/mage/cards/i/InvasionSubmersible.java new file mode 100644 index 00000000000..801328452b9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InvasionSubmersible.java @@ -0,0 +1,61 @@ +package mage.cards.i; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.WaterbendCost; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.ExhaustAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.counters.CounterType; +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 InvasionSubmersible extends CardImpl { + + private static final FilterPermanent filter = new FilterNonlandPermanent("other target nonland permanent"); + + static { + filter.add(AnotherPredicate.instance); + } + + public InvasionSubmersible(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{U}"); + + this.subtype.add(SubType.VEHICLE); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // When this Vehicle enters, return up to one other target nonland permanent to its owner's hand. + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()); + ability.addTarget(new TargetPermanent(0, 1, filter)); + this.addAbility(ability); + + // Exhaust -- Waterbend {3}: This Vehicle becomes an artifact creature. Put three +1/+1 counters on it. + ability = new ExhaustAbility(new AddCardTypeSourceEffect(Duration.Custom, CardType.ARTIFACT, CardType.CREATURE), new WaterbendCost(3)); + ability.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)).setText("Put three +1/+1 counters on it")); + this.addAbility(ability); + } + + private InvasionSubmersible(final InvasionSubmersible card) { + super(card); + } + + @Override + public InvasionSubmersible copy() { + return new InvasionSubmersible(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 1486f05228a..106e4eed8f4 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -118,6 +118,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Hog-Monkey", 104, Rarity.COMMON, mage.cards.h.HogMonkey.class)); cards.add(new SetCardInfo("How to Start a Riot", 140, Rarity.COMMON, mage.cards.h.HowToStartARiot.class)); cards.add(new SetCardInfo("Iguana Parrot", 56, Rarity.COMMON, mage.cards.i.IguanaParrot.class)); + cards.add(new SetCardInfo("Invasion Submersible", 57, Rarity.UNCOMMON, mage.cards.i.InvasionSubmersible.class)); cards.add(new SetCardInfo("Invasion Tactics", 183, Rarity.UNCOMMON, mage.cards.i.InvasionTactics.class)); cards.add(new SetCardInfo("Island", 283, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Island", 288, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); -- 2.47.2 From 0168db7a57088f8b267d9e79975a81f7a1015517 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 3 Nov 2025 20:30:22 -0500 Subject: [PATCH 082/261] temporary verify fix --- Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 9bb9ed2c176..8916d75645e 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -170,14 +170,12 @@ public class VerifyCardDataTest { skipListAddName(SKIP_LIST_TYPE, "UNH", "Old Fogey"); // uses summon word as a joke card skipListAddName(SKIP_LIST_TYPE, "UND", "Old Fogey"); skipListAddName(SKIP_LIST_TYPE, "UST", "capital offense"); // uses "instant" instead "Instant" as a joke card - skipListAddName(SKIP_LIST_TYPE, "SPM", "Superior Foes of Spider-Man"); // temporary // subtype // skipListAddName(SKIP_LIST_SUBTYPE, set, cardName); skipListAddName(SKIP_LIST_SUBTYPE, "UGL", "Miss Demeanor"); // uses multiple types as a joke card: Lady, of, Proper, Etiquette skipListAddName(SKIP_LIST_SUBTYPE, "UGL", "Elvish Impersonators"); // subtype is "Elves" pun skipListAddName(SKIP_LIST_SUBTYPE, "UND", "Elvish Impersonators"); - skipListAddName(SKIP_LIST_SUBTYPE, "SPM", "Superior Foes of Spider-Man"); // temporary // number // skipListAddName(SKIP_LIST_NUMBER, set, cardName); @@ -185,7 +183,7 @@ public class VerifyCardDataTest { // rarity // skipListAddName(SKIP_LIST_RARITY, set, cardName); skipListAddName(SKIP_LIST_RARITY, "CMR", "The Prismatic Piper"); // Collation is not yet set up for CMR https://www.lethe.xyz/mtg/collation/cmr.html - skipListAddName(SKIP_LIST_RARITY, "SPM", "Gwenom, Remorseless"); // temporary + skipListAddName(SKIP_LIST_RARITY, "TLE", "Teferi's Protection"); // temporary // missing abilities // skipListAddName(SKIP_LIST_MISSING_ABILITIES, set, cardName); -- 2.47.2 From 10db510c35ffc5c92124ac9885dfbc0b9794a6bd Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 08:33:38 -0500 Subject: [PATCH 083/261] [TLE] update spoiler and reprints --- .../mage/sets/AvatarTheLastAirbenderEternal.java | 9 +++++++++ Utils/mtg-cards-data.txt | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index f61015853d6..ac0d88c9b4b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -39,6 +39,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Appa, Aang's Companion", 268, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Arcane Signet", 315, Rarity.RARE, mage.cards.a.ArcaneSignet.class)); cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 130, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class)); + cards.add(new SetCardInfo("Beastmaster Ascension", 39, Rarity.MYTHIC, mage.cards.b.BeastmasterAscension.class)); + cards.add(new SetCardInfo("Beastmaster's Magemark", 9999, Rarity.MYTHIC, mage.cards.b.BeastmastersMagemark.class)); cards.add(new SetCardInfo("Blasphemous Act", 26, Rarity.MYTHIC, mage.cards.b.BlasphemousAct.class)); cards.add(new SetCardInfo("Bloodchief Ascension", 23, Rarity.MYTHIC, mage.cards.b.BloodchiefAscension.class)); cards.add(new SetCardInfo("Bribery", 10, Rarity.MYTHIC, mage.cards.b.Bribery.class)); @@ -46,6 +48,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Bumi, Eclectic Earthbender", 248, Rarity.RARE, mage.cards.b.BumiEclecticEarthbender.class)); cards.add(new SetCardInfo("Capital Guard", 234, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Capital Guard", 277, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Cityscape Leveler", 53, Rarity.MYTHIC, mage.cards.c.CityscapeLeveler.class)); cards.add(new SetCardInfo("Clone Legion", 12, Rarity.MYTHIC, mage.cards.c.CloneLegion.class)); cards.add(new SetCardInfo("Clone", 11, Rarity.MYTHIC, mage.cards.c.Clone.class)); cards.add(new SetCardInfo("Cruel Tutor", 24, Rarity.MYTHIC, mage.cards.c.CruelTutor.class)); @@ -59,6 +62,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Eel-Hounds", 250, Rarity.UNCOMMON, mage.cards.e.EelHounds.class)); cards.add(new SetCardInfo("Eladamri's Call", 48, Rarity.MYTHIC, mage.cards.e.EladamrisCall.class)); cards.add(new SetCardInfo("Elephant-Rat", 228, Rarity.COMMON, mage.cards.e.ElephantRat.class)); + cards.add(new SetCardInfo("Empty City Ruse", 3, Rarity.MYTHIC, mage.cards.e.EmptyCityRuse.class)); cards.add(new SetCardInfo("Explore", 259, Rarity.COMMON, mage.cards.e.Explore.class)); cards.add(new SetCardInfo("Explosive Shot", 236, Rarity.COMMON, mage.cards.e.ExplosiveShot.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Explosive Shot", 279, Rarity.COMMON, mage.cards.e.ExplosiveShot.class, NON_FULL_USE_VARIOUS)); @@ -84,6 +88,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Heroic Healer", 269, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Waterbending Master", 93, Rarity.MYTHIC, mage.cards.k.KataraWaterbendingMaster.class)); + cards.add(new SetCardInfo("Koma, Cosmos Serpent", 51, Rarity.MYTHIC, mage.cards.k.KomaCosmosSerpent.class)); cards.add(new SetCardInfo("Komodo Rhino", 241, Rarity.COMMON, mage.cards.k.KomodoRhino.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Komodo Rhino", 283, Rarity.COMMON, mage.cards.k.KomodoRhino.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Kyoshi Warrior Guard", 216, Rarity.COMMON, mage.cards.k.KyoshiWarriorGuard.class)); @@ -118,13 +123,17 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Purple Pentapus", 233, Rarity.COMMON, mage.cards.p.PurplePentapus.class)); cards.add(new SetCardInfo("Razor Rings", 272, Rarity.COMMON, mage.cards.r.RazorRings.class)); cards.add(new SetCardInfo("Release to Memory", 5, Rarity.MYTHIC, mage.cards.r.ReleaseToMemory.class)); + cards.add(new SetCardInfo("Rending Volley", 34, Rarity.MYTHIC, mage.cards.r.RendingVolley.class)); cards.add(new SetCardInfo("Return of the Wildspeaker", 44, Rarity.MYTHIC, mage.cards.r.ReturnOfTheWildspeaker.class)); cards.add(new SetCardInfo("Rhys the Redeemed", 52, Rarity.MYTHIC, mage.cards.r.RhysTheRedeemed.class)); cards.add(new SetCardInfo("Rites of Flourishing", 45, Rarity.MYTHIC, mage.cards.r.RitesOfFlourishing.class)); cards.add(new SetCardInfo("Roku's Mastery", 243, Rarity.UNCOMMON, mage.cards.r.RokusMastery.class)); cards.add(new SetCardInfo("Run Amok", 258, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Run Amok", 284, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Scout's Warning", 6, Rarity.MYTHIC, mage.cards.s.ScoutsWarning.class)); + cards.add(new SetCardInfo("Searing Blood", 35, Rarity.MYTHIC, mage.cards.s.SearingBlood.class)); cards.add(new SetCardInfo("Seismic Tutelage", 254, Rarity.RARE, mage.cards.s.SeismicTutelage.class)); + cards.add(new SetCardInfo("Shattering Spree", 36, Rarity.MYTHIC, mage.cards.s.ShatteringSpree.class)); cards.add(new SetCardInfo("Sledding Otter-Penguin", 218, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sledding Otter-Penguin", 273, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 219, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 4d6db105bfb..9aee6029a0a 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -60369,7 +60369,9 @@ Spider-Sense|Marvel's Spider-Man|284|R|{1}{U}|Instant|||Web-slinging {U}$Counter Radioactive Spider|Marvel's Spider-Man|285|R|{G}|Creature - Spider|1|1|Reach, deathtouch$Fateful Bite -- {2}, Sacrifice this creature: Search your library for a Spider Hero card, reveal it, put it into your hand, then shuffle. Activate only as a sorcery.| Gwenom, Remorseless|Marvel's Spider-Man|286|M|{3}{B}{B}|Legendary Creature - Symbiote Spider Hero|4|4|Deathtouch, lifelink$Whenever Gwenom attacks, until end of turn you may look at the top card of your library any time and you may play cards from the top of your library. If you cast a spell this way, pay life equal to its mana value rather than pay its mana cost.| Brought Back|Avatar: The Last Airbender Eternal|1|M|{W}{W}|Instant|||Choose up to two target permanent cards in your graveyard that were put there from the battlefield this turn. Return them to the battlefield tapped.| +Empty City Ruse|Avatar: The Last Airbender Eternal|3|M|{W}|Sorcery|||Target opponent skips all combat phases of their next turn.| Release to Memory|Avatar: The Last Airbender Eternal|5|M|{3}{W}|Instant|||Exile target opponent's graveyard. For each creature card exiled this way, create a 1/1 colorless Spirit creature token.| +Scout's Warning|Avatar: The Last Airbender Eternal|6|M|{W}|Instant|||The next creature card you play this turn can be played as though it had flash.$Draw a card.| Teferi's Protection|Avatar: The Last Airbender Eternal|7|M|{2}{W}|Instant|||Until your next turn, your life total can't change and you gain protection from everything. All permanents you control phase out.$Exile Teferi's Protection.| Agent of Treachery|Avatar: The Last Airbender Eternal|9|M|{5}{U}{U}|Creature - Human Rogue|2|3|When this creature enters, gain control of target permanent.$At the beginning of your end step, if you control three or more permanents you don't own, draw three cards.| Bribery|Avatar: The Last Airbender Eternal|10|M|{3}{U}{U}|Sorcery|||Search target opponent's library for a creature card and put that card onto the battlefield under your control. Then that player shuffles.| @@ -60387,17 +60389,28 @@ Noxious Gearhulk|Avatar: The Last Airbender Eternal|25|M|{4}{B}{B}|Artifact Crea Blasphemous Act|Avatar: The Last Airbender Eternal|26|M|{8}{R}|Sorcery|||This spell costs {1} less to cast for each creature on the battlefield.$Blasphemous Act deals 13 damage to each creature.| Dockside Extortionist|Avatar: The Last Airbender Eternal|28|M|{1}{R}|Creature - Goblin Pirate|1|2|When this creature enters, create X Treasure tokens, where X is the number of artifacts and enchantments your opponents control.| Mirrorwing Dragon|Avatar: The Last Airbender Eternal|33|M|{3}{R}{R}|Creature - Dragon|4|5|Flying$Whenever a player casts an instant or sorcery spell that targets only this creature, that player copies that spell for each other creature they control that the spell could target. Each copy targets a different one of those creatures.| +Rending Volley|Avatar: The Last Airbender Eternal|34|M|{R}|Instant|||This spell can't be countered.$Rending Volley deals 4 damage to target white or blue creature.| +Searing Blood|Avatar: The Last Airbender Eternal|35|M|{R}{R}|Instant|||Searing Blood deals 2 damage to target creature. When that creature dies this turn, Searing Blood deals 3 damage to the creature's controller.| +Shattering Spree|Avatar: The Last Airbender Eternal|36|M|{R}|Sorcery|||Replicate {R}$Destroy target artifact.| +Beastmaster Ascension|Avatar: The Last Airbender Eternal|39|M|{2}{G}|Enchantment|||Whenever a creature you control attacks, you may put a quest counter on this enchantment.$As long as this enchantment has seven or more quest counters on it, creatures you control get +5/+5.| The Great Henge|Avatar: The Last Airbender Eternal|41|M|{7}{G}{G}|Legendary Artifact|||This spell costs {X} less to cast, where X is the greatest power among creatures you control.${T}: Add {G}{G}. You gain 2 life.$Whenever a nontoken creature you control enters, put a +1/+1 counter on it and draw a card.| Heartbeat of Spring|Avatar: The Last Airbender Eternal|42|M|{2}{G}|Enchantment|||Whenever a player taps a land for mana, that player adds one mana of any type that land produced.| Heroic Intervention|Avatar: The Last Airbender Eternal|43|M|{1}{G}|Instant|||Permanents you control gain hexproof and indestructible until end of turn.| Return of the Wildspeaker|Avatar: The Last Airbender Eternal|44|M|{4}{G}|Instant|||Choose one --$* Draw cards equal to the greatest power among non-Human creatures you control.$* Non-Human creatures you control get +3/+3 until end of turn.| Rites of Flourishing|Avatar: The Last Airbender Eternal|45|M|{2}{G}|Enchantment|||At the beginning of each player's draw step, that player draws an additional card.$Each player may play an additional land on each of their turns.| Eladamri's Call|Avatar: The Last Airbender Eternal|48|M|{G}{W}|Instant|||Search your library for a creature card, reveal that card, put it into your hand, then shuffle.| +Koma, Cosmos Serpent|Avatar: The Last Airbender Eternal|51|M|{3}{G}{G}{U}{U}|Legendary Creature - Serpent|6|6|This spell can't be countered.$At the beginning of each upkeep, create a 3/3 blue Serpent creature token named Koma's Coil.$Sacrifice another Serpent: Choose one --$* Tap target permanent. Its activated abilities can't be activated this turn.$* Koma gains indestructible until end of turn.| Rhys the Redeemed|Avatar: The Last Airbender Eternal|52|M|{G/W}|Legendary Creature - Elf Warrior|1|1|{2}{G/W}, {T}: Create a 1/1 green and white Elf Warrior creature token.${4}{G/W}{G/W}, {T}: For each creature token you control, create a token that's a copy of that creature.| +Cityscape Leveler|Avatar: The Last Airbender Eternal|53|M|{8}|Artifact Creature - Construct|8|8|Trample$When you cast this spell and whenever this creature attacks, destroy up to one target nonland permanent. Its controller creates a tapped Powerstone token.$Unearth {8}| Sundial of the Infinite|Avatar: The Last Airbender Eternal|55|M|{2}|Artifact|||{1}, {T}: End the turn. Activate only during your turn.| Dark Depths|Avatar: The Last Airbender Eternal|56|M||Legendary Snow Land|||Dark Depths enters with ten ice counters on it.${3}: Remove an ice counter from Dark Depths.$When Dark Depths has no ice counters on it, sacrifice it. If you do, create Marit Lage, a legendary 20/20 black Avatar creature token with flying and indestructible.| Valakut, the Molten Pinnacle|Avatar: The Last Airbender Eternal|61|M||Land|||This land enters tapped.$Whenever a Mountain you control enters, if you control at least five other Mountains, you may have this land deal 3 damage to any target.${T}: Add {R}.| +Appa, the Vigilant|Avatar: The Last Airbender Eternal|62|R|{5}{W}{W}|Legendary Creature - Bison Ally|6|6|Flying, vigilance$Whenever Appa or another Ally you control enters, creatures you control get +1/+1 and gain flying and vigilance until end of turn.| Katara's Reversal|Avatar: The Last Airbender Eternal|63|R|{2}{U}{U}|Instant|||Counter up to four target spells and/or abilities.$Untap up to four target artifacts and/or creatures.| +Fire Nation Turret|Avatar: The Last Airbender Eternal|64|R|{2}{R}|Artifact|||At the beginning of combat on your turn, up to one target creature gets +2/+0 and gains firebending 2 until end of turn.${R}: Put a charge counter on this artifact.$Remove fifty charge counters from this artifact: It deals 50 damage to any target.| +Swampbenders|Avatar: The Last Airbender Eternal|65|R|{4}{G}{G}|Creature - Human Druid Ally|*|*|Swampbenders's power and toughness are each equal to the number of Swamps on the battlefield. Lands you control are Swamps in addition to their other types.| +Sokka's Charge|Avatar: The Last Airbender Eternal|66|R|{3}{W}|Enchantment|||During your turn, Allies you control have double strike and lifelink.| +Earthshape|Avatar: The Last Airbender Eternal|67|R|{2}{W}|Instant|||Earthbend 3. Then each creature you control with power less than or equal to that land's power gains hexproof and indestructible until end of turn. You gain hexproof until end of turn.| Mai and Zuko|Avatar: The Last Airbender Eternal|68|R|{1}{U}{B}{R}|Legendary Creature - Human Noble Ally|3|5|Firebending 3$You may cast Ally spells and artifact spells as though they had flash.| Aang and Katara|Avatar: The Last Airbender Eternal|69|R|{3}{G}{W}{U}|Legendary Creature - Human Avatar Ally|5|5|Whenever Aang and Katara enter or attack, create X 1/1 white Ally creature tokens, where X is the number of tapped artifacts and/or creatures you control.| Toph, Greatest Earthbender|Avatar: The Last Airbender Eternal|70|R|{2}{R}{G}|Legendary Creature - Human Warrior Ally|3|3|When Toph enters, earthbend X, where X is the amount of mana spent to cast her.$Land creatures you control have double strike.| @@ -60517,6 +60530,7 @@ Plains|Avatar: The Last Airbender Eternal|304|C||Basic Land - Plains|||({T}: Add Arcane Signet|Avatar: The Last Airbender Eternal|315|R|{2}|Artifact|||{T}: Add one mana of any color in your commander's color identity.| Sol Ring|Avatar: The Last Airbender Eternal|316|R|{1}|Artifact|||{T}: Add {C}{C}.| Swiftfoot Boots|Avatar: The Last Airbender Eternal|317|R|{2}|Artifact - Equipment|||Equipped creature has hexproof and haste.$Equip {1}| +Beastmaster's Magemark|Avatar: The Last Airbender Eternal|9999|M|{2}{G}|Enchantment - Aura|||Enchant creature$Creatures you control that are enchanted get +1/+1.$Whenever a creature you control that's enchanted becomes blocked, it gets +1/+1 until end of turn for each creature blocking it.| Eirdu, Carrier of Dawn|Lorwyn Eclipsed|13|M|{3}{W}{W}|Legendary Creature - Elemental God|5|5|Flying, lifelink$Creature spells you cast have convoke.$At the beginning of your first main phase, you may pay {B}. If you do, transform Eirdu.| Isilu, Carrier of Twilight|Lorwyn Eclipsed|13|M||Legendary Creature - Elemental God|5|5|Flying, lifelink$Each other nontoken creature you control has persist.$At the beginning of your first main phase, you may pay {W}. If you do, transform Isilu.| Morningtide's Light|Lorwyn Eclipsed|27|M|{3}{W}|Sorcery|||Exile any number of target creatures. At the beginning of the next end step, return those cards to the battlefield tapped under their owners' control.$Until your next turn, prevent all damage that would be dealt to you.$Exile Morningtide's Light.| -- 2.47.2 From a0f0c0f6bea47849f2f2541a5e63b106f7d045b5 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 08:33:54 -0500 Subject: [PATCH 084/261] [TLA] update spoiler --- Utils/mtg-cards-data.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 9aee6029a0a..016e7eb96f0 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59772,6 +59772,8 @@ Appa, Steadfast Guardian|Avatar: The Last Airbender|10|M|{2}{W}{W}|Legendary Cre Avatar Enthusiasts|Avatar: The Last Airbender|11|C|{2}{W}|Creature - Human Peasant Ally|2|2|Whenever another Ally you control enters, put a +1/+1 counter on this creature.| Avatar's Wrath|Avatar: The Last Airbender|12|R|{2}{W}{W}|Sorcery|||Choose up to one target creature, then airbend each other creature.$Until your next turn, your opponents can't cast spells from anywhere other than their hand.$Exile Avatar's Wrath.| Compassionate Healer|Avatar: The Last Airbender|13|C|{1}{W}|Creature - Human Cleric Ally|2|2|Whenever this creature becomes tapped, you gain 1 life and scry 1.| +Earth Kingdom Jailer|Avatar: The Last Airbender|16|U|{2}{W}|Creature - Human Soldier Ally|3|3|When this creature enters, exile up to one target artifact, creature, or enchantment an opponent controls with mana value 3 or greater until this creature leaves the battlefield.| +Enter the Avatar State|Avatar: The Last Airbender|18|U|{W}|Instant - Lesson|||Until end of turn, target creature you control becomes an Avatar in addition to its other types and gains flying, first strike, lifelink, and hexproof.| Fancy Footwork|Avatar: The Last Airbender|19|U|{2}{W}|Instant - Lesson|||Untap one or two target creatures. They each get +2/+2 until end of turn.| Gather the White Lotus|Avatar: The Last Airbender|20|U|{4}{W}|Sorcery|||Create a 1/1 white Ally creature token for each Plains you control. Scry 2.| Glider Kids|Avatar: The Last Airbender|21|C|{2}{W}|Creature - Human Pilot Ally|2|3|Flying$When this creature enters, scry 1.| @@ -59883,10 +59885,13 @@ War Balloon|Avatar: The Last Airbender|159|U|{2}{R}|Artifact - Vehicle|4|3|Flyin Yuyan Archers|Avatar: The Last Airbender|161|C|{1}{R}|Creature - Human Archer|3|1|Reach$When this creature enters, you may discard a card. If you do, draw a card.| Zuko, Exiled Prince|Avatar: The Last Airbender|163|U|{3}{R}|Legendary Creature - Human Noble|4|3|Firebending 3${3}: Exile the top card of your library. You may play that card this turn.| Allies at Last|Avatar: The Last Airbender|164|U|{2}{G}|Instant|||Affinity for Allies$Up to two target creatures you control each deal damage equal to their power to target creature an opponent controls.| +Avatar Destiny|Avatar: The Last Airbender|165|R|{2}{G}{G}|Enchantment - Aura|||Enchant creature you control$Enchanted creature gets +1/+1 for each creature card in your graveyard and is an Avatar in addition to its other types.$When enchanted creature dies, mill cards equal to its power. Return this card to its owner's hand and up to one creature card milled this way to the battlefield under your control.| Badgermole|Avatar: The Last Airbender|166|C|{4}{G}|Creature - Badger Mole|4|4|When this creature enters, earthbend 2.$Creatures you control with +1/+1 counters on them have trample.| Badgermole Cub|Avatar: The Last Airbender|167|M|{1}{G}|Creature - Badger Mole|2|2|When this creature enters, earthbend 1.$Whenever you tap a creature for mana, add an additional {G}.| +Bumi, King of Three Trials|Avatar: The Last Airbender|169|U|{5}{G}|Legendary Creature - Human Noble Ally|4|4|When Bumi enters, choose up to X, where X is the number of Lesson cards in your graveyard --$* Put three +1/+1 counters on Bumi.$* Target player scries 3.$* Earthbend 3.| Cycle of Renewal|Avatar: The Last Airbender|170|C|{2}{G}|Instant - Lesson|||Sacrifice a land. Search your library for up to two basic land cards, put them onto the battlefield tapped, then shuffle.| Diligent Zookeeper|Avatar: The Last Airbender|171|R|{3}{G}|Creature - Human Citizen Ally|4|4|Each non-Human creature you control gets +1/+1 for each of its creature types, to a maximum of 10.| +The Earth King|Avatar: The Last Airbender|172|R|{3}{G}|Legendary Creature - Human Noble Ally|2|2|When The Earth King enters, create a 4/4 green Bear creature token.$Whenever one or more creatures you control with power 4 or greater attack, search your library for up to that many basic land cards, put them onto the battlefield tapped, then shuffle.| Earth Kingdom General|Avatar: The Last Airbender|173|U|{3}{G}|Creature - Human Soldier Ally|2|2|When this creature enters, earthbend 2.$Whenever you put one or more +1/+1 counters on a creature, you may gain that much life. Do this only once each turn.| Earth Rumble|Avatar: The Last Airbender|174|U|{3}{G}|Sorcery|||Earthbend 2. When you do, up to one target creature you control fights target creature an opponent controls.| Earthbending Lesson|Avatar: The Last Airbender|176|C|{3}{G}|Sorcery - Lesson|||Earthbend 4.| @@ -59918,8 +59923,10 @@ Avatar Aang|Avatar: The Last Airbender|207|M|{R}{G}{W}{U}|Legendary Creature - H Aang, Master of Elements|Avatar: The Last Airbender|207|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Azula, Cunning Usurper|Avatar: The Last Airbender|208|R|{2}{U}{B}{B}|Legendary Creature - Human Noble Rogue|4|4|Firebending 2$When Azula enters, target opponent exiles a nontoken creature they control, then they exile a nonland card from their graveyard.$During your turn, you may cast cards exiled with Azula and you may cast them as though they had flash. Mana of any type can be spent to cast those spells.| Beifong's Bounty Hunters|Avatar: The Last Airbender|209|R|{2}{B}{G}|Creature - Human Mercenary|4|4|Whenever a nonland creature you control dies, earthbend X, where X is that creature's power.| +Bitter Work|Avatar: The Last Airbender|210|U|{1}{R}{G}|Enchantment|||Whenever you attack a player with one or more creatures with power 4 or greater, draw a card.$Exhaust -- {4}: Earthbend 4. Activate only during your turn.| Bumi, Unleashed|Avatar: The Last Airbender|211|M|{3}{R}{G}|Legendary Creature - Human Noble Ally|5|4|Trample$When Bumi enters, earthbend 4.$Whenever Bumi deals combat damage to a player, untap all lands you control. After this phase, there is an additional combat phase. Only land creatures can attack during that combat phase.| Cat-Owl|Avatar: The Last Airbender|212|C|{3}{W/U}|Creature - Cat Bird|3|3|Flying$Whenever this creature attacks, untap target artifact or creature.| +Cruel Administrator|Avatar: The Last Airbender|213|U|{3}{B}{R}|Creature - Human Soldier|5|4|Raid -- This creature enters with a +1/+1 counter on it if you attacked this turn.$Whenever this creature attacks, create a 2/2 red Soldier creature token with firebending 1.| Dai Li Agents|Avatar: The Last Airbender|214|U|{3}{B}{G}|Creature - Human Soldier|3|4|When this creature enters, earthbend 1, then earthbend 1.$Whenever this creature attacks, each opponent loses X life and you gain X life, where X is the number of creatures you control with +1/+1 counters on them.| Dragonfly Swarm|Avatar: The Last Airbender|215|U|{1}{U}{R}|Creature - Dragon Insect|*|3|Flying, ward {1}$This creature's power is equal to the number of noncreature, nonland cards in your graveyard.$When this creature dies, if there's a Lesson card in your graveyard, draw a card.| Earth Kingdom Soldier|Avatar: The Last Airbender|216|C|{4}{G/W}|Creature - Human Soldier|3|4|Vigilance$When this creature enters, put a +1/+1 counter on each of up to two target creatures you control.| @@ -59962,7 +59969,9 @@ Trusty Boomerang|Avatar: The Last Airbender|260|U|{1}|Artifact - Equipment|||Equ White Lotus Tile|Avatar: The Last Airbender|262|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| Airship Engine Room|Avatar: The Last Airbender|265|C||Land|||This land enters tapped.${T}: Add {U} or {R}.${4}, {T}, Sacrifice this land: Draw a card.| Boiling Rock Prison|Avatar: The Last Airbender|267|C||Land|||This land enters tapped.${T}: Add {B} or {R}.${4}, {T}, Sacrifice this land: Draw a card.| +Fire Nation Palace|Avatar: The Last Airbender|268|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {R}.${1}{R}, {T}: Target creature you control gains firebending 4 until end of turn.| Foggy Bottom Swamp|Avatar: The Last Airbender|269|C||Land|||This land enters tapped.${T}: Add {B} or {G}.${4}, {T}, Sacrifice this land: Draw a card.| +Jasmine Dragon Tea Shop|Avatar: The Last Airbender|270|R||Land|||{T}: Add {C}.${T}: Add one mana of any color. Spend this mana only to cast an Ally spell or activate an ability of an Ally source.${5}, {T}: Create a 1/1 white Ally creature token.| Kyoshi Village|Avatar: The Last Airbender|271|C||Land|||This land enters tapped.${T}: Add {G} or {W}.${4}, {T}, Sacrifice this land: Draw a card.| Meditation Pools|Avatar: The Last Airbender|272|C||Land|||This land enters tapped.${T}: Add {G} or {U}.${4}, {T}, Sacrifice this land: Draw a card.| Misty Palms Oasis|Avatar: The Last Airbender|273|C||Land|||This land enters tapped.${T}: Add {W} or {B}.${4}, {T}, Sacrifice this land: Draw a card.| @@ -60017,6 +60026,7 @@ The Lion-Turtle|Avatar: The Last Airbender|328|R|{1}{G}{U}|Legendary Creature - White Lotus Tile|Avatar: The Last Airbender|330|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| United Front|Avatar: The Last Airbender|331|M|{X}{W}{W}|Sorcery|||Create X 1/1 white Ally creature tokens, then put a +1/+1 counter on each creature you control.| Sozin's Comet|Avatar: The Last Airbender|332|M|{3}{R}{R}|Sorcery|||Each creature you control gains firebending 5 until end of turn.$Foretell {2}{R}| +Avatar Destiny|Avatar: The Last Airbender|333|R|{2}{G}{G}|Enchantment - Aura|||Enchant creature you control$Enchanted creature gets +1/+1 for each creature card in your graveyard and is an Avatar in addition to its other types.$When enchanted creature dies, mill cards equal to its power. Return this card to its owner's hand and up to one creature card milled this way to the battlefield under your control.| Fire Lord Azula|Avatar: The Last Airbender|334|R|{1}{U}{B}{R}|Legendary Creature - Human Noble|4|4|Firebending 2$Whenever you cast a spell while Fire Lord Azula is attacking, copy that spell. You may choose new targets for the copy.| Ozai, the Phoenix King|Avatar: The Last Airbender|335|M|{2}{B}{B}{R}{R}|Legendary Creature - Human Noble|7|7|Trample, firebending 4, haste$If you would lose unspent mana, that mana becomes red instead.$Ozai has flying and indestructible as long as you have six or more unspent mana.| Aang's Iceberg|Avatar: The Last Airbender|336|R|{2}{W}|Enchantment|||Flash$When this enchantment enters, exile up to one other target nonland permanent until this enchantment leaves the battlefield.$Waterbend {3}: Sacrifice this enchantment. If you do, scry 2.| @@ -60026,6 +60036,7 @@ Foggy Swamp Visions|Avatar: The Last Airbender|339|R|{1}{B}{B}|Sorcery|||As an a Fated Firepower|Avatar: The Last Airbender|341|M|{X}{R}{R}{R}|Enchantment|||Flash$This enchantment enters with X fire counters on it.$If a source you control would deal damage to an opponent or a permanent an opponent controls, it deals that much damage plus an amount of damage equal to the number of fire counters on this enchantment instead.| Firebending Student|Avatar: The Last Airbender|342|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| Redirect Lightning|Avatar: The Last Airbender|343|R|{R}|Instant - Lesson|||As an additional cost to cast this spell, pay 5 life or pay {2}.$Change the target of target spell or ability with a single target.| +The Earth King|Avatar: The Last Airbender|344|R|{3}{G}|Legendary Creature - Human Noble Ally|2|2|When The Earth King enters, create a 4/4 green Bear creature token.$Whenever one or more creatures you control with power 4 or greater attack, search your library for up to that many basic land cards, put them onto the battlefield tapped, then shuffle.| Aang, at the Crossroads|Avatar: The Last Airbender|346|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| Aang, Destined Savior|Avatar: The Last Airbender|346|R||Legendary Creature - Avatar Ally|4|4|Flying$Land creatures you control have vigilance.$At the beginning of combat on your turn, earthbend 2.| Aang, Swift Savior|Avatar: The Last Airbender|347|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| @@ -60052,6 +60063,7 @@ Toph, the First Metalbender|Avatar: The Last Airbender|362|R|{1}{R}{G}{W}|Legend Avatar Aang|Avatar: The Last Airbender|363|M|{R}{G}{W}{U}|Legendary Creature - Human Avatar Ally|4|4|Flying, firebending 2$Whenever you waterbend, earthbend, firebend, or airbend, draw a card. Then if you've done all four this turn, transform Avatar Aang.| Aang, Master of Elements|Avatar: The Last Airbender|363|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Airbender Ascension|Avatar: The Last Airbender|364|R|{1}{W}|Enchantment|||When this enchantment enters, airbend up to one target creature.$Whenever a creature you control enters, put a quest counter on this enchantment.$At the beginning of your end step, if this enchantment has four or more quest counters on it, exile up to one target creature you control, then return it to the battlefield under its owner's control.| +Avatar's Wrath|Avatar: The Last Airbender|365|R|{2}{W}{W}|Sorcery|||Choose up to one target creature, then airbend each other creature.$Until your next turn, your opponents can't cast spells from anywhere other than their hand.$Exile Avatar's Wrath.| Hakoda, Selfless Commander|Avatar: The Last Airbender|366|R|{3}{W}|Legendary Creature - Human Warrior Ally|3|5|Vigilance$You may look at the top card of your library any time.$You may cast Ally spells from the top of your library.$Sacrifice Hakoda: Creatures you control get +0/+5 and gain indestructible until end of turn.| Suki, Courageous Rescuer|Avatar: The Last Airbender|368|R|{1}{W}{W}|Legendary Creature - Human Warrior Ally|2|4|Other creatures you control get +1/+0.$Whenever another permanent you control leaves the battlefield during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.| The Mechanist, Aerial Artisan|Avatar: The Last Airbender|369|R|{2}{U}|Legendary Creature - Human Artificer Ally|1|3|Whenever you cast a noncreature spell, create a Clue token.${T}: Until end of turn, target artifact token you control becomes a 3/1 Construct artifact creature with flying.| @@ -60065,6 +60077,8 @@ Earth King's Lieutenant|Avatar: The Last Airbender|380|R|{G}{W}|Creature - Human Iroh, Tea Master|Avatar: The Last Airbender|381|R|{1}{R}{W}|Legendary Creature - Human Citizen Ally|2|2|When Iroh enters, create a Food token.$At the beginning of combat on your turn, you may have target opponent gain control of target permanent you control. When you do, create a 1/1 white Ally creature token. Put a +1/+1 counter on that token for each permanent you own that your opponents control.| Sokka, Bold Boomeranger|Avatar: The Last Airbender|383|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.| Planetarium of Wan Shi Tong|Avatar: The Last Airbender|385|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| +Fire Nation Palace|Avatar: The Last Airbender|389|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {R}.${1}{R}, {T}: Target creature you control gains firebending 4 until end of turn.| +Jasmine Dragon Tea Shop|Avatar: The Last Airbender|390|R||Land|||{T}: Add {C}.${T}: Add one mana of any color. Spend this mana only to cast an Ally spell or activate an ability of an Ally source.${5}, {T}: Create a 1/1 white Ally creature token.| Secret Tunnel|Avatar: The Last Airbender|392|R||Land - Cave|||This land can't be blocked.${T}: Add {C}.${4}, {T}: Two target creatures you control that share a creature type can't be blocked this turn.| Firebending Student|Avatar: The Last Airbender|393|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| Momo, Friendly Flier|Avatar: The Last Airbender|394|R|{W}|Legendary Creature - Lemur Bat Ally|1|1|Flying$The first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast.$Whenever another creature you control with flying enters, Momo gets +1/+1 until end of turn.| -- 2.47.2 From 793c8d1daa906a3f8ce4f9f28f499df2af1347be Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 08:38:42 -0500 Subject: [PATCH 085/261] [TLA] Implement Fire Nation Palace --- .../src/mage/cards/f/FireNationPalace.java | 65 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 67 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FireNationPalace.java diff --git a/Mage.Sets/src/mage/cards/f/FireNationPalace.java b/Mage.Sets/src/mage/cards/f/FireNationPalace.java new file mode 100644 index 00000000000..39f263df364 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FireNationPalace.java @@ -0,0 +1,65 @@ +package mage.cards.f; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedUnlessAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.abilities.keyword.FirebendingAbility; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledLandPermanent; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FireNationPalace extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledLandPermanent("you control a basic land"); + + static { + filter.add(SuperType.BASIC.getPredicate()); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + private static final Hint hint = new ConditionHint(condition); + + public FireNationPalace(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped unless you control a basic land. + this.addAbility(new EntersBattlefieldTappedUnlessAbility(condition)); + + // {T}: Add {R}. + this.addAbility(new RedManaAbility()); + + // {1}{R}, {T}: Target creature you control gains firebending 4 until end of turn. + Ability ability = new SimpleActivatedAbility( + new GainAbilityTargetEffect(new FirebendingAbility(4)), new ManaCostsImpl<>("{1}{R}") + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + private FireNationPalace(final FireNationPalace card) { + super(card); + } + + @Override + public FireNationPalace copy() { + return new FireNationPalace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 106e4eed8f4..8ccf56fed74 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -91,6 +91,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Fire Nation Attacks", 299, Rarity.UNCOMMON, mage.cards.f.FireNationAttacks.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation Cadets", 134, Rarity.COMMON, mage.cards.f.FireNationCadets.class)); cards.add(new SetCardInfo("Fire Nation Engineer", 99, Rarity.UNCOMMON, mage.cards.f.FireNationEngineer.class)); + cards.add(new SetCardInfo("Fire Nation Palace", 268, Rarity.RARE, mage.cards.f.FireNationPalace.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fire Nation Palace", 389, Rarity.RARE, mage.cards.f.FireNationPalace.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation Warship", 256, Rarity.UNCOMMON, mage.cards.f.FireNationWarship.class)); cards.add(new SetCardInfo("Fire Sages", 136, Rarity.UNCOMMON, mage.cards.f.FireSages.class)); cards.add(new SetCardInfo("Firebending Student", 139, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 171ea63bc0e5737025589094c23686429cff2215 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 08:40:52 -0500 Subject: [PATCH 086/261] [TLA] Implement Cruel Administrator --- .../src/mage/cards/c/CruelAdministrator.java | 54 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 55 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CruelAdministrator.java diff --git a/Mage.Sets/src/mage/cards/c/CruelAdministrator.java b/Mage.Sets/src/mage/cards/c/CruelAdministrator.java new file mode 100644 index 00000000000..f91b2c39df5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CruelAdministrator.java @@ -0,0 +1,54 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.condition.common.RaidCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.hint.common.RaidHint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.game.permanent.token.SoldierFirebendingToken; +import mage.watchers.common.PlayerAttackedWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CruelAdministrator extends CardImpl { + + public CruelAdministrator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Raid -- This creature enters with a +1/+1 counter on it if you attacked this turn. + this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), RaidCondition.instance, "" + ), "with a +1/+1 counter on it if you attacked this turn") + .setAbilityWord(AbilityWord.RAID) + .addHint(RaidHint.instance), new PlayerAttackedWatcher()); + + // Whenever this creature attacks, create a 2/2 red Soldier creature token with firebending 1. + this.addAbility(new AttacksTriggeredAbility(new CreateTokenEffect(new SoldierFirebendingToken()))); + } + + private CruelAdministrator(final CruelAdministrator card) { + super(card); + } + + @Override + public CruelAdministrator copy() { + return new CruelAdministrator(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 8ccf56fed74..48387f3f255 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -60,6 +60,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Compassionate Healer", 13, Rarity.COMMON, mage.cards.c.CompassionateHealer.class)); cards.add(new SetCardInfo("Corrupt Court Official", 92, Rarity.COMMON, mage.cards.c.CorruptCourtOfficial.class)); cards.add(new SetCardInfo("Crescent Island Temple", 129, Rarity.UNCOMMON, mage.cards.c.CrescentIslandTemple.class)); + cards.add(new SetCardInfo("Cruel Administrator", 213, Rarity.UNCOMMON, mage.cards.c.CruelAdministrator.class)); cards.add(new SetCardInfo("Cunning Maneuver", 130, Rarity.COMMON, mage.cards.c.CunningManeuver.class)); cards.add(new SetCardInfo("Cycle of Renewal", 170, Rarity.COMMON, mage.cards.c.CycleOfRenewal.class)); cards.add(new SetCardInfo("Dai Li Indoctrination", 93, Rarity.COMMON, mage.cards.d.DaiLiIndoctrination.class)); -- 2.47.2 From da6ba92ba232a211121b5fc8f73bb1c01730dd6d Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 08:44:08 -0500 Subject: [PATCH 087/261] [TLA] Implement Earth Kingdom Jailer --- .../src/mage/cards/e/EarthKingdomJailer.java | 62 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 63 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EarthKingdomJailer.java diff --git a/Mage.Sets/src/mage/cards/e/EarthKingdomJailer.java b/Mage.Sets/src/mage/cards/e/EarthKingdomJailer.java new file mode 100644 index 00000000000..9c1ad504098 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EarthKingdomJailer.java @@ -0,0 +1,62 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.ExileUntilSourceLeavesEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ManaValuePredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EarthKingdomJailer extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent( + "artifact, creature, or enchantment an opponent controls with mana value 3 or greater" + ); + + static { + filter.add(Predicates.or( + CardType.ARTIFACT.getPredicate(), + CardType.CREATURE.getPredicate(), + CardType.ENCHANTMENT.getPredicate() + )); + filter.add(TargetController.OPPONENT.getControllerPredicate()); + filter.add(new ManaValuePredicate(ComparisonType.MORE_THAN, 2)); + } + + public EarthKingdomJailer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When this creature enters, exile up to one target artifact, creature, or enchantment an opponent controls with mana value 3 or greater until this creature leaves the battlefield. + Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect()); + ability.addTarget(new TargetPermanent(0, 1, filter)); + this.addAbility(ability); + } + + private EarthKingdomJailer(final EarthKingdomJailer card) { + super(card); + } + + @Override + public EarthKingdomJailer copy() { + return new EarthKingdomJailer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 48387f3f255..2d158041eec 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -71,6 +71,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Dragonfly Swarm", 215, Rarity.UNCOMMON, mage.cards.d.DragonflySwarm.class)); cards.add(new SetCardInfo("Earth King's Lieutenant", 217, Rarity.RARE, mage.cards.e.EarthKingsLieutenant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earth King's Lieutenant", 380, Rarity.RARE, mage.cards.e.EarthKingsLieutenant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Earth Kingdom Jailer", 16, Rarity.UNCOMMON, mage.cards.e.EarthKingdomJailer.class)); cards.add(new SetCardInfo("Earth Kingdom Soldier", 216, Rarity.COMMON, mage.cards.e.EarthKingdomSoldier.class)); cards.add(new SetCardInfo("Earth Rumble", 174, Rarity.UNCOMMON, mage.cards.e.EarthRumble.class)); cards.add(new SetCardInfo("Earth Village Ruffians", 219, Rarity.COMMON, mage.cards.e.EarthVillageRuffians.class)); -- 2.47.2 From 6e5116b673c153ce7dd2333bca0382174e5ff4fb Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 08:47:08 -0500 Subject: [PATCH 088/261] [TLA] Implement Enter the Avatar State --- .../src/mage/cards/e/EnterTheAvatarState.java | 46 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 47 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EnterTheAvatarState.java diff --git a/Mage.Sets/src/mage/cards/e/EnterTheAvatarState.java b/Mage.Sets/src/mage/cards/e/EnterTheAvatarState.java new file mode 100644 index 00000000000..552e117162c --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EnterTheAvatarState.java @@ -0,0 +1,46 @@ +package mage.cards.e; + +import mage.abilities.effects.common.continuous.AddCardSubTypeTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HexproofAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EnterTheAvatarState extends CardImpl { + + public EnterTheAvatarState(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); + + this.subtype.add(SubType.LESSON); + + // Until end of turn, target creature you control becomes an Avatar in addition to its other types and gains flying, first strike, lifelink, and hexproof. + this.getSpellAbility().addEffect(new AddCardSubTypeTargetEffect(SubType.AVATAR, Duration.EndOfTurn) + .setText("until end of turn, target creature you control becomes an Avatar in addition to its other types")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(FlyingAbility.getInstance()).setText("and gains flying")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance()).setText(", first strike")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(LifelinkAbility.getInstance()).setText(", lifelink")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HexproofAbility.getInstance()).setText(", and hexproof")); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + } + + private EnterTheAvatarState(final EnterTheAvatarState card) { + super(card); + } + + @Override + public EnterTheAvatarState copy() { + return new EnterTheAvatarState(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 2d158041eec..2ddcb869884 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -76,6 +76,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Earth Rumble", 174, Rarity.UNCOMMON, mage.cards.e.EarthRumble.class)); cards.add(new SetCardInfo("Earth Village Ruffians", 219, Rarity.COMMON, mage.cards.e.EarthVillageRuffians.class)); cards.add(new SetCardInfo("Earthbending Lesson", 176, Rarity.COMMON, mage.cards.e.EarthbendingLesson.class)); + cards.add(new SetCardInfo("Enter the Avatar State", 18, Rarity.UNCOMMON, mage.cards.e.EnterTheAvatarState.class)); cards.add(new SetCardInfo("Epic Downfall", 96, Rarity.UNCOMMON, mage.cards.e.EpicDownfall.class)); cards.add(new SetCardInfo("Fancy Footwork", 19, Rarity.UNCOMMON, mage.cards.f.FancyFootwork.class)); cards.add(new SetCardInfo("Fated Firepower", 132, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From f0ba075d561772a5d0a609e9e6d43e726b22a209 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 09:11:19 -0500 Subject: [PATCH 089/261] [TLA] update spoiler --- Utils/mtg-cards-data.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 016e7eb96f0..0e7e11ec94f 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59792,6 +59792,7 @@ Suki, Courageous Rescuer|Avatar: The Last Airbender|37|R|{1}{W}{W}|Legendary Cre United Front|Avatar: The Last Airbender|39|M|{X}{W}{W}|Sorcery|||Create X 1/1 white Ally creature tokens, then put a +1/+1 counter on each creature you control.| Water Tribe Rallier|Avatar: The Last Airbender|42|U|{1}{W}|Creature - Human Soldier Ally|2|2|Waterbend {5}: Look at the top four cards of your library. You may reveal a creature card with power 3 or less from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| Yip Yip!|Avatar: The Last Airbender|43|C|{W}|Instant - Lesson|||Target creature you control gets +2/+2 until end of turn. If that creature is an Ally, it also gains flying until end of turn.| +Boomerang Basics|Avatar: The Last Airbender|46|U|{U}|Sorcery - Lesson|||Return target nonland permanent to its owner's hand. If you controlled that permanent, draw a card.| First-Time Flyer|Avatar: The Last Airbender|49|C|{1}{U}|Creature - Human Pilot Ally|1|2|Flying$This creature gets +1/+1 as long as there's a Lesson card in your graveyard.| Flexible Waterbender|Avatar: The Last Airbender|50|C|{3}{U}|Creature - Human Warrior Ally|2|5|Vigilance$Waterbend {3}: This creature has base power and toughness 5/2 until end of turn.| Forecasting Fortune Teller|Avatar: The Last Airbender|51|C|{1}{U}|Creature - Human Advisor Ally|1|3|When this creature enters, create a Clue token.| @@ -59839,6 +59840,7 @@ Deadly Precision|Avatar: The Last Airbender|95|C|{B}|Sorcery|||As an additional Epic Downfall|Avatar: The Last Airbender|96|U|{1}{B}|Sorcery|||Exile target creature with mana value 3 or greater.| The Fire Nation Drill|Avatar: The Last Airbender|98|R|{2}{B}{B}|Legendary Artifact - Vehicle|6|3|Trample$When The Fire Nation Drill enters, you may tap it. When you do, destroy target creature with power 4 or less.${1}: Permanents your opponents control lose hexproof and indestructible until end of turn.$Crew 2| Fire Nation Engineer|Avatar: The Last Airbender|99|U|{2}{B}|Creature - Human Artificer|2|3|Raid -- At the beginning of your end step, if you attacked this turn, put a +1/+1 counter on another target creature or Vehicle you control.| +Fire Navy Trebuchet|Avatar: The Last Airbender|100|U|{2}{B}|Artifact Creature - Wall|0|4|Defender, reach$Whenever you attack, create a 2/1 colorless Construct artifact creature token with flying named Ballistic Boulder that's tapped and attacking. Sacrifice that token at the beginning of the next end step.| Foggy Swamp Visions|Avatar: The Last Airbender|102|R|{1}{B}{B}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Exile X target creature cards from graveyards. For each creature card exiled this way, create a token that's a copy of it. At the beginning of your next end step, sacrifice those tokens.| Heartless Act|Avatar: The Last Airbender|103|U|{1}{B}|Instant|||Choose one --$* Destroy target creature with no counters on it.$* Remove up to three counters from target creature.| Hog-Monkey|Avatar: The Last Airbender|104|C|{2}{B}|Creature - Boar Monkey|3|2|At the beginning of combat on your turn, target creature you control with a +1/+1 counter on it gains menace until end of turn.$Exhaust -- {5}: Put two +1/+1 counters on this creature.| @@ -59847,6 +59849,7 @@ Mai, Scornful Striker|Avatar: The Last Airbender|109|R|{1}{B}|Legendary Creature Merchant of Many Hats|Avatar: The Last Airbender|110|C|{1}{B}|Creature - Human Peasant Ally|2|2|{2}{B}: Return this card from your graveyard to your hand.| Northern Air Temple|Avatar: The Last Airbender|111|U|{B}|Legendary Enchantment - Shrine|||When Northern Air Temple enters, each opponent loses X life and you gain X life, where X is the number of Shrines you control.$Whenever another Shrine you control enters, each opponent loses 1 life and you gain 1 life.| Ozai's Cruelty|Avatar: The Last Airbender|113|U|{2}{B}|Sorcery - Lesson|||Ozai's Cruelty deals 2 damage to target player. That player discards two cards.| +Raven Eagle|Avatar: The Last Airbender|116|R|{2}{B}|Creature - Bird Assassin|2|3|Flying$Whenever this creature enters or attacks, exile up to one target card from a graveyard. If a creature card is exiled this way, create a Clue token.$Whenever you draw your second card each turn, each opponent loses 1 life and you gain 1 life.| The Rise of Sozin|Avatar: The Last Airbender|117|M|{4}{B}{B}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I -- Destroy all creatures.$II -- Choose a card name. Search target opponent's graveyard, hand, and library for up to four cards with that name and exile them. Then that player shuffles.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| Fire Lord Sozin|Avatar: The Last Airbender|117|M||Legendary Creature - Human Noble|5|5|Menace, firebending 3$Whenever Fire Lord Sozin deals combat damage to a player, you may pay {X}. When you do, put any number of target creature cards with total mana value X or less from that player's graveyard onto the battlefield under your control.| Sold Out|Avatar: The Last Airbender|119|C|{3}{B}|Instant|||Exile target creature. If it was dealt damage this turn, create a Clue token.| @@ -59863,6 +59866,7 @@ Fire Sages|Avatar: The Last Airbender|136|U|{1}{R}|Creature - Human Cleric|2|2|F Firebender Ascension|Avatar: The Last Airbender|137|R|{1}{R}|Enchantment|||When this enchantment enters, create a 2/2 red Soldier creature token with firebending 1.$Whenever a creature you control attacking causes a triggered ability of that creature to trigger, put a quest counter on this enchantment. Then if it has four or more quest counters on it, you may copy that ability. You may choose new targets for the copy.| Firebending Student|Avatar: The Last Airbender|139|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| How to Start a Riot|Avatar: The Last Airbender|140|C|{2}{R}|Instant - Lesson|||Target creature gains menace until end of turn.$Creatures target player controls get +2/+0 until end of turn.| +Iroh's Demonstration|Avatar: The Last Airbender|141|U|{1}{R}|Sorcery - Lesson|||Choose one --$* Iroh's Demonstration deals 1 damage to each creature your opponents control.$* Iroh's Demonstration deals 4 damage to target creature.| Jeong Jeong, the Deserter|Avatar: The Last Airbender|142|U|{2}{R}|Legendary Creature - Human Rebel Ally|2|3|Firebending 1$Exhaust -- {3}: Put a +1/+1 counter on Jeong Jeong. When you next cast a Lesson spell this turn, copy it and you may choose new targets for the copy.| Jet's Brainwashing|Avatar: The Last Airbender|143|U|{R}|Sorcery|||Kicker {3}$Target creature can't block this turn. If this spell was kicked, gain control of that creature until end of turn, untap it, and it gains haste until end of turn.$Create a Clue token.| The Last Agni Kai|Avatar: The Last Airbender|144|R|{1}{R}|Instant|||Target creature you control fights target creature an opponent controls. If the creature the opponent controls is dealt excess damage this way, add that much {R}.$Until end of turn, you don't lose unspent red mana as steps and phases end.| @@ -59888,6 +59892,7 @@ Allies at Last|Avatar: The Last Airbender|164|U|{2}{G}|Instant|||Affinity for Al Avatar Destiny|Avatar: The Last Airbender|165|R|{2}{G}{G}|Enchantment - Aura|||Enchant creature you control$Enchanted creature gets +1/+1 for each creature card in your graveyard and is an Avatar in addition to its other types.$When enchanted creature dies, mill cards equal to its power. Return this card to its owner's hand and up to one creature card milled this way to the battlefield under your control.| Badgermole|Avatar: The Last Airbender|166|C|{4}{G}|Creature - Badger Mole|4|4|When this creature enters, earthbend 2.$Creatures you control with +1/+1 counters on them have trample.| Badgermole Cub|Avatar: The Last Airbender|167|M|{1}{G}|Creature - Badger Mole|2|2|When this creature enters, earthbend 1.$Whenever you tap a creature for mana, add an additional {G}.| +The Boulder, Ready to Rumble|Avatar: The Last Airbender|168|U|{3}{G}|Legendary Creature - Human Warrior Performer|4|4|Whenever The Boulder attacks, earthbend X, where X is the number of creatures you control with power 4 or greater.| Bumi, King of Three Trials|Avatar: The Last Airbender|169|U|{5}{G}|Legendary Creature - Human Noble Ally|4|4|When Bumi enters, choose up to X, where X is the number of Lesson cards in your graveyard --$* Put three +1/+1 counters on Bumi.$* Target player scries 3.$* Earthbend 3.| Cycle of Renewal|Avatar: The Last Airbender|170|C|{2}{G}|Instant - Lesson|||Sacrifice a land. Search your library for up to two basic land cards, put them onto the battlefield tapped, then shuffle.| Diligent Zookeeper|Avatar: The Last Airbender|171|R|{3}{G}|Creature - Human Citizen Ally|4|4|Each non-Human creature you control gets +1/+1 for each of its creature types, to a maximum of 10.| @@ -60019,6 +60024,7 @@ Tiger-Seal|Avatar: The Last Airbender|318|R|{U}|Creature - Cat Seal|3|3|Vigilanc The Unagi of Kyoshi Island|Avatar: The Last Airbender|319|R|{3}{U}{U}|Legendary Creature - Serpent|5|5|Flash$Ward--Waterbend {4}$Whenever an opponent draws their second card each turn, draw two cards.| Wan Shi Tong, Librarian|Avatar: The Last Airbender|320|M|{X}{U}{U}|Legendary Creature - Bird Spirit|1|1|Flash$Flying, vigilance$When Wan Shi Tong enters, put X +1/+1 counters on him. Then draw half X cards, rounded down.$Whenever an opponent searches their library, put a +1/+1 counter on Wan Shi Tong and draw a card.| The Fire Nation Drill|Avatar: The Last Airbender|321|R|{2}{B}{B}|Legendary Artifact - Vehicle|6|3|Trample$When The Fire Nation Drill enters, you may tap it. When you do, destroy target creature with power 4 or less.${1}: Permanents your opponents control lose hexproof and indestructible until end of turn.$Crew 2| +Raven Eagle|Avatar: The Last Airbender|324|R|{2}{B}|Creature - Bird Assassin|2|3|Flying$Whenever this creature enters or attacks, exile up to one target card from a graveyard. If a creature card is exiled this way, create a Clue token.$Whenever you draw your second card each turn, each opponent loses 1 life and you gain 1 life.| Ran and Shaw|Avatar: The Last Airbender|325|R|{3}{R}{R}|Legendary Creature - Dragon|4|4|Flying, firebending 2$When Ran and Shaw enter, if you cast them and there are three or more Dragon and/or Lesson cards in your graveyard, create a token that's a copy of Ran and Shaw, except it's not legendary.${3}{R}: Dragons you control get +2/+0 until end of turn.| Badgermole Cub|Avatar: The Last Airbender|326|M|{1}{G}|Creature - Badger Mole|2|2|When this creature enters, earthbend 1.$Whenever you tap a creature for mana, add an additional {G}.| Diligent Zookeeper|Avatar: The Last Airbender|327|R|{3}{G}|Creature - Human Citizen Ally|4|4|Each non-Human creature you control gets +1/+1 for each of its creature types, to a maximum of 10.| -- 2.47.2 From c473b7a189f388ace7f21005649b20175fded183 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 09:27:24 -0500 Subject: [PATCH 090/261] [TLE] Implement Avatar Roku, Firebender --- .../mage/cards/a/AvatarRokuFirebender.java | 108 ++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 109 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AvatarRokuFirebender.java diff --git a/Mage.Sets/src/mage/cards/a/AvatarRokuFirebender.java b/Mage.Sets/src/mage/cards/a/AvatarRokuFirebender.java new file mode 100644 index 00000000000..00c7e62e87b --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AvatarRokuFirebender.java @@ -0,0 +1,108 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AvatarRokuFirebender extends CardImpl { + + public AvatarRokuFirebender(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.AVATAR); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Whenever a player attacks, add six {R}. Until end of combat, you don't lose this mana as steps end. + this.addAbility(new AvatarRokuFirebenderTriggeredAbility()); + + // {R}{R}{R}: Target creature gets +3/+0 until end of turn. + Ability ability = new SimpleActivatedAbility( + new BoostTargetEffect(3, 0), new ManaCostsImpl<>("{R}{R}{R}") + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + private AvatarRokuFirebender(final AvatarRokuFirebender card) { + super(card); + } + + @Override + public AvatarRokuFirebender copy() { + return new AvatarRokuFirebender(this); + } +} + +class AvatarRokuFirebenderTriggeredAbility extends TriggeredAbilityImpl { + + AvatarRokuFirebenderTriggeredAbility() { + super(Zone.BATTLEFIELD, new AvatarRokuFirebenderEffect()); + setTriggerPhrase("Whenever a player attacks, "); + } + + private AvatarRokuFirebenderTriggeredAbility(final AvatarRokuFirebenderTriggeredAbility ability) { + super(ability); + } + + @Override + public AvatarRokuFirebenderTriggeredAbility copy() { + return new AvatarRokuFirebenderTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return !game.getCombat().getAttackers().isEmpty(); + } +} + +class AvatarRokuFirebenderEffect extends OneShotEffect { + + AvatarRokuFirebenderEffect() { + super(Outcome.Benefit); + staticText = "add six {R}. Until end of combat, you don't lose this mana as steps end"; + } + + private AvatarRokuFirebenderEffect(final AvatarRokuFirebenderEffect effect) { + super(effect); + } + + @Override + public AvatarRokuFirebenderEffect copy() { + return new AvatarRokuFirebenderEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + player.getManaPool().addMana(Mana.RedMana(6), game, source, Duration.EndOfCombat); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index ac0d88c9b4b..e84b7810289 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -39,6 +39,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Appa, Aang's Companion", 268, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Arcane Signet", 315, Rarity.RARE, mage.cards.a.ArcaneSignet.class)); cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 130, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class)); + cards.add(new SetCardInfo("Avatar Roku, Firebender", 112, Rarity.MYTHIC, mage.cards.a.AvatarRokuFirebender.class)); cards.add(new SetCardInfo("Beastmaster Ascension", 39, Rarity.MYTHIC, mage.cards.b.BeastmasterAscension.class)); cards.add(new SetCardInfo("Beastmaster's Magemark", 9999, Rarity.MYTHIC, mage.cards.b.BeastmastersMagemark.class)); cards.add(new SetCardInfo("Blasphemous Act", 26, Rarity.MYTHIC, mage.cards.b.BlasphemousAct.class)); -- 2.47.2 From 63b01b10d79da65e9e11fd9fa2234e8ba64f6ce9 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 09:19:48 -0500 Subject: [PATCH 091/261] [TLE] Implement Iroh's Demonstration --- .../src/mage/cards/i/IrohsDemonstration.java | 41 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 42 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/IrohsDemonstration.java diff --git a/Mage.Sets/src/mage/cards/i/IrohsDemonstration.java b/Mage.Sets/src/mage/cards/i/IrohsDemonstration.java new file mode 100644 index 00000000000..b9c39d21f6c --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IrohsDemonstration.java @@ -0,0 +1,41 @@ +package mage.cards.i; + +import mage.abilities.Mode; +import mage.abilities.effects.common.DamageAllEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class IrohsDemonstration extends CardImpl { + + public IrohsDemonstration(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}"); + + this.subtype.add(SubType.LESSON); + + // Choose one -- + // * Iroh's Demonstration deals 1 damage to each creature your opponents control. + this.getSpellAbility().addEffect(new DamageAllEffect(1, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + + // * Iroh's Demonstration deals 4 damage to target creature. + this.getSpellAbility().addMode(new Mode(new DamageTargetEffect(4)).addTarget(new TargetCreaturePermanent())); + } + + private IrohsDemonstration(final IrohsDemonstration card) { + super(card); + } + + @Override + public IrohsDemonstration copy() { + return new IrohsDemonstration(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 2ddcb869884..2501d1f6f81 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -125,6 +125,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Iguana Parrot", 56, Rarity.COMMON, mage.cards.i.IguanaParrot.class)); cards.add(new SetCardInfo("Invasion Submersible", 57, Rarity.UNCOMMON, mage.cards.i.InvasionSubmersible.class)); cards.add(new SetCardInfo("Invasion Tactics", 183, Rarity.UNCOMMON, mage.cards.i.InvasionTactics.class)); + cards.add(new SetCardInfo("Iroh's Demonstration", 141, Rarity.UNCOMMON, mage.cards.i.IrohsDemonstration.class)); cards.add(new SetCardInfo("Island", 283, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Island", 288, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Island", 293, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); -- 2.47.2 From f880a683f9bb3f45410bfb95a600478996b0410e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 09:19:52 -0500 Subject: [PATCH 092/261] [TLA] Implement The Boulder, Ready to Rumble --- .../mage/cards/t/TheBoulderReadyToRumble.java | 62 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 63 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TheBoulderReadyToRumble.java diff --git a/Mage.Sets/src/mage/cards/t/TheBoulderReadyToRumble.java b/Mage.Sets/src/mage/cards/t/TheBoulderReadyToRumble.java new file mode 100644 index 00000000000..1d84e42f907 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheBoulderReadyToRumble.java @@ -0,0 +1,62 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheBoulderReadyToRumble extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("creatures you control with power 4 or greater"); + + static { + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + } + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter); + private static final Hint hint = new ValueHint("Creatures you control with power 4 or greater", xValue); + + public TheBoulderReadyToRumble(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.subtype.add(SubType.PERFORMER); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Whenever The Boulder attacks, earthbend X, where X is the number of creatures you control with power 4 or greater. + Ability ability = new AttacksTriggeredAbility(new EarthbendTargetEffect(xValue)); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability.addHint(hint)); + } + + private TheBoulderReadyToRumble(final TheBoulderReadyToRumble card) { + super(card); + } + + @Override + public TheBoulderReadyToRumble copy() { + return new TheBoulderReadyToRumble(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 2501d1f6f81..f8c75ee79d5 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -211,6 +211,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Swamp", 284, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Swamp", 289, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swamp", 294, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("The Boulder, Ready to Rumble", 168, Rarity.UNCOMMON, mage.cards.t.TheBoulderReadyToRumble.class)); cards.add(new SetCardInfo("The Cave of Two Lovers", 126, Rarity.UNCOMMON, mage.cards.t.TheCaveOfTwoLovers.class)); 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)); -- 2.47.2 From ddb7e133c63b70db9a10b59680775b75c4ad2a81 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 09:24:09 -0500 Subject: [PATCH 093/261] [TLA] Implement Sold Out --- Mage.Sets/src/mage/cards/s/SoldOut.java | 72 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 73 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SoldOut.java diff --git a/Mage.Sets/src/mage/cards/s/SoldOut.java b/Mage.Sets/src/mage/cards/s/SoldOut.java new file mode 100644 index 00000000000..1e70d5ac73b --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SoldOut.java @@ -0,0 +1,72 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Controllable; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.ClueArtifactToken; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SoldOut extends CardImpl { + + public SoldOut(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}"); + + // Exile target creature. If it was dealt damage this turn, create a Clue token. + this.getSpellAbility().addEffect(new SoldOutEffect()); + } + + private SoldOut(final SoldOut card) { + super(card); + } + + @Override + public SoldOut copy() { + return new SoldOut(this); + } +} + +class SoldOutEffect extends OneShotEffect { + + SoldOutEffect() { + super(Outcome.Benefit); + staticText = "exile target creature. If it was dealt damage this turn, create a Clue token"; + } + + private SoldOutEffect(final SoldOutEffect effect) { + super(effect); + } + + @Override + public SoldOutEffect copy() { + return new SoldOutEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent == null) { + return false; + } + boolean flag = permanent.getDamage() > 0; + Optional.ofNullable(source) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .ifPresent(player -> player.moveCards(permanent, Zone.EXILED, source, game)); + if (flag) { + new ClueArtifactToken().putOntoBattlefield(1, game, source); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index f8c75ee79d5..4c23ff0138d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -198,6 +198,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Sokka, Lateral Strategist", 241, Rarity.UNCOMMON, mage.cards.s.SokkaLateralStrategist.class)); cards.add(new SetCardInfo("Sokka, Tenacious Tactician", 242, Rarity.RARE, mage.cards.s.SokkaTenaciousTactician.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Tenacious Tactician", 352, Rarity.RARE, mage.cards.s.SokkaTenaciousTactician.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sold Out", 119, Rarity.COMMON, mage.cards.s.SoldOut.class)); cards.add(new SetCardInfo("Solstice Revelations", 153, Rarity.UNCOMMON, mage.cards.s.SolsticeRevelations.class)); cards.add(new SetCardInfo("Southern Air Temple", 36, Rarity.UNCOMMON, mage.cards.s.SouthernAirTemple.class)); cards.add(new SetCardInfo("Sozin's Comet", 154, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From a13c339df247d40bade1218071f5480d9b6aa73d Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 09:26:58 -0500 Subject: [PATCH 094/261] [TLA] Implement Appa, Loyal Sky Bison --- .../src/mage/cards/a/AppaLoyalSkyBison.java | 55 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 56 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AppaLoyalSkyBison.java diff --git a/Mage.Sets/src/mage/cards/a/AppaLoyalSkyBison.java b/Mage.Sets/src/mage/cards/a/AppaLoyalSkyBison.java new file mode 100644 index 00000000000..1be12ec9283 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AppaLoyalSkyBison.java @@ -0,0 +1,55 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +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.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetNonlandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AppaLoyalSkyBison extends CardImpl { + + public AppaLoyalSkyBison(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.BISON); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever Appa enters or attacks, choose one -- + // * Target creature you control gains flying until end of turn. + Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new GainAbilityTargetEffect(FlyingAbility.getInstance())); + ability.addTarget(new TargetControlledCreaturePermanent()); + + // * Airbend another target nonland permanent you control.. + ability.addMode(new Mode(new AirbendTargetEffect()).addTarget(new TargetNonlandPermanent())); + this.addAbility(ability); + } + + private AppaLoyalSkyBison(final AppaLoyalSkyBison card) { + super(card); + } + + @Override + public AppaLoyalSkyBison copy() { + return new AppaLoyalSkyBison(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 4c23ff0138d..6ae9b070f71 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -35,6 +35,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Abandon Attachments", 205, Rarity.COMMON, mage.cards.a.AbandonAttachments.class)); cards.add(new SetCardInfo("Airbending Lesson", 8, Rarity.COMMON, mage.cards.a.AirbendingLesson.class)); cards.add(new SetCardInfo("Airship Engine Room", 265, Rarity.COMMON, mage.cards.a.AirshipEngineRoom.class)); + cards.add(new SetCardInfo("Appa, Loyal Sky Bison", 9, Rarity.UNCOMMON, mage.cards.a.AppaLoyalSkyBison.class)); cards.add(new SetCardInfo("Appa, Steadfast Guardian", 10, Rarity.MYTHIC, mage.cards.a.AppaSteadfastGuardian.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Appa, Steadfast Guardian", 316, Rarity.MYTHIC, mage.cards.a.AppaSteadfastGuardian.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Avatar Aang", 207, Rarity.MYTHIC, mage.cards.a.AvatarAang.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From ac7f33a156849e61d4d75675af5913e936e4c179 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 09:36:28 -0500 Subject: [PATCH 095/261] [TLA] Implement Earth Rumble Wrestlers --- .../mage/cards/e/EarthRumbleWrestlers.java | 78 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 79 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EarthRumbleWrestlers.java diff --git a/Mage.Sets/src/mage/cards/e/EarthRumbleWrestlers.java b/Mage.Sets/src/mage/cards/e/EarthRumbleWrestlers.java new file mode 100644 index 00000000000..996a25299b1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EarthRumbleWrestlers.java @@ -0,0 +1,78 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.LandfallCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.abilities.keyword.ReachAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledLandPermanent; +import mage.watchers.common.LandfallWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EarthRumbleWrestlers extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledLandPermanent(); + + static { + filter.add(CardType.CREATURE.getPredicate()); + } + + private static final Condition condition = new CompoundCondition( + "you control a land creature or a land entered the battlefield under your control this turn", + new PermanentsOnTheBattlefieldCondition(filter), LandfallCondition.instance + ); + private static final Hint hint = new ConditionHint(condition); + + public EarthRumbleWrestlers(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R/G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.subtype.add(SubType.PERFORMER); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // This creature gets +1/+0 and has trample as long as you control a land creature or a land entered the battlefield under your control this turn. + Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( + new BoostSourceEffect(1, 0, Duration.WhileOnBattlefield), + condition, "{this} gets +1/+0" + )); + ability.addEffect(new ConditionalContinuousEffect( + new GainAbilitySourceEffect(TrampleAbility.getInstance()), + condition, "and has trample as long as you control a land creature " + + "or a land entered the battlefield under your control this turn" + )); + this.addAbility(ability.addHint(hint), new LandfallWatcher()); + } + + private EarthRumbleWrestlers(final EarthRumbleWrestlers card) { + super(card); + } + + @Override + public EarthRumbleWrestlers copy() { + return new EarthRumbleWrestlers(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 6ae9b070f71..7675c04298d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -75,6 +75,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Earth Kingdom Jailer", 16, Rarity.UNCOMMON, mage.cards.e.EarthKingdomJailer.class)); cards.add(new SetCardInfo("Earth Kingdom Soldier", 216, Rarity.COMMON, mage.cards.e.EarthKingdomSoldier.class)); cards.add(new SetCardInfo("Earth Rumble", 174, Rarity.UNCOMMON, mage.cards.e.EarthRumble.class)); + cards.add(new SetCardInfo("Earth Rumble Wrestlers", 218, Rarity.COMMON, mage.cards.e.EarthRumbleWrestlers.class)); cards.add(new SetCardInfo("Earth Village Ruffians", 219, Rarity.COMMON, mage.cards.e.EarthVillageRuffians.class)); cards.add(new SetCardInfo("Earthbending Lesson", 176, Rarity.COMMON, mage.cards.e.EarthbendingLesson.class)); cards.add(new SetCardInfo("Enter the Avatar State", 18, Rarity.UNCOMMON, mage.cards.e.EnterTheAvatarState.class)); -- 2.47.2 From 34ddd612b38ce4904d49468a7608ee46c3a20c5b Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 09:45:00 -0500 Subject: [PATCH 096/261] [TLA] Implement Airbender Ascension --- .../src/mage/cards/a/AirbenderAscension.java | 59 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 61 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AirbenderAscension.java diff --git a/Mage.Sets/src/mage/cards/a/AirbenderAscension.java b/Mage.Sets/src/mage/cards/a/AirbenderAscension.java new file mode 100644 index 00000000000..cf862437492 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AirbenderAscension.java @@ -0,0 +1,59 @@ +package mage.cards.a; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.effects.common.ExileThenReturnTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.keyword.AirbendTargetEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AirbenderAscension extends CardImpl { + + private static final Condition condition = new SourceHasCounterCondition(CounterType.QUEST, 4); + + public AirbenderAscension(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); + + // When this enchantment enters, airbend up to one target creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new AirbendTargetEffect()); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + this.addAbility(ability); + + // Whenever a creature you control enters, put a quest counter on this enchantment. + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new AddCountersSourceEffect(CounterType.QUEST.createInstance()), + StaticFilters.FILTER_CONTROLLED_CREATURE + )); + + // At the beginning of your end step, if this enchantment has four or more quest counters on it, exile up to one target creature you control, then return it to the battlefield under its owner's control. + ability = new BeginningOfEndStepTriggeredAbility( + new ExileThenReturnTargetEffect(false, false) + ).withInterveningIf(condition); + ability.addTarget(new TargetControlledCreaturePermanent(0, 1)); + this.addAbility(ability); + } + + private AirbenderAscension(final AirbenderAscension card) { + super(card); + } + + @Override + public AirbenderAscension copy() { + return new AirbenderAscension(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 7675c04298d..e46db4e974b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -33,6 +33,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Aang, Master of Elements", 363, Rarity.MYTHIC, mage.cards.a.AangMasterOfElements.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, the Last Airbender", 4, Rarity.UNCOMMON, mage.cards.a.AangTheLastAirbender.class)); cards.add(new SetCardInfo("Abandon Attachments", 205, Rarity.COMMON, mage.cards.a.AbandonAttachments.class)); + cards.add(new SetCardInfo("Airbender Ascension", 364, Rarity.RARE, mage.cards.a.AirbenderAscension.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Airbender Ascension", 6, Rarity.RARE, mage.cards.a.AirbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Airbending Lesson", 8, Rarity.COMMON, mage.cards.a.AirbendingLesson.class)); cards.add(new SetCardInfo("Airship Engine Room", 265, Rarity.COMMON, mage.cards.a.AirshipEngineRoom.class)); cards.add(new SetCardInfo("Appa, Loyal Sky Bison", 9, Rarity.UNCOMMON, mage.cards.a.AppaLoyalSkyBison.class)); -- 2.47.2 From 4c0270a5d5ecd1e60d06cd8b08c386cda7df829e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 09:53:44 -0500 Subject: [PATCH 097/261] [TLA] Implement Dai Li Agents --- Mage.Sets/src/mage/cards/d/DaiLiAgents.java | 71 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 73 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/d/DaiLiAgents.java diff --git a/Mage.Sets/src/mage/cards/d/DaiLiAgents.java b/Mage.Sets/src/mage/cards/d/DaiLiAgents.java new file mode 100644 index 00000000000..fda6379c4cb --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DaiLiAgents.java @@ -0,0 +1,71 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.target.common.TargetControlledLandPermanent; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DaiLiAgents extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("creatures you control with +1/+1 counters on them"); + + static { + filter.add(CounterType.P1P1.getPredicate()); + } + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter); + private static final Hint hint = new ValueHint("Creatures you control with +1/+1 counters on them", xValue); + + public DaiLiAgents(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // When this creature enters, earthbend 1, then earthbend 1. + Ability ability = new EntersBattlefieldTriggeredAbility(new EarthbendTargetEffect(1).setText("earhbend 1")); + ability.addEffect(new EarthbendTargetEffect(1) + .setTargetPointer(new SecondTargetPointer()) + .concatBy(", then")); + ability.addTarget(new TargetControlledLandPermanent().withChooseHint("first target")); + ability.addTarget(new TargetControlledLandPermanent().withChooseHint("second target")); + this.addAbility(ability.addHint(hint)); + + // Whenever this creature attacks, each opponent loses X life and you gain X life, where X is the number of creatures you control with +1/+1 counters on them. + ability = new AttacksTriggeredAbility(new LoseLifeOpponentsEffect(xValue).setText("each opponent loses X life")); + ability.addEffect(new GainLifeEffect(xValue).concatBy("and")); + this.addAbility(ability); + } + + private DaiLiAgents(final DaiLiAgents card) { + super(card); + } + + @Override + public DaiLiAgents copy() { + return new DaiLiAgents(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index e46db4e974b..cd29aa8fcc3 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -66,6 +66,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Cruel Administrator", 213, Rarity.UNCOMMON, mage.cards.c.CruelAdministrator.class)); cards.add(new SetCardInfo("Cunning Maneuver", 130, Rarity.COMMON, mage.cards.c.CunningManeuver.class)); cards.add(new SetCardInfo("Cycle of Renewal", 170, Rarity.COMMON, mage.cards.c.CycleOfRenewal.class)); + cards.add(new SetCardInfo("Dai Li Agents", 214, Rarity.UNCOMMON, mage.cards.d.DaiLiAgents.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Dai Li Agents", 306, Rarity.UNCOMMON, mage.cards.d.DaiLiAgents.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dai Li Indoctrination", 93, Rarity.COMMON, mage.cards.d.DaiLiIndoctrination.class)); cards.add(new SetCardInfo("Deadly Precision", 95, Rarity.COMMON, mage.cards.d.DeadlyPrecision.class)); cards.add(new SetCardInfo("Deserter's Disciple", 131, Rarity.COMMON, mage.cards.d.DesertersDisciple.class)); -- 2.47.2 From dcf1ab14d7a8f38f81f77d42b41345de0ca3b6ea Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 09:58:53 -0500 Subject: [PATCH 098/261] [TLA] Implement Yip Yip! --- Mage.Sets/src/mage/cards/y/YipYip.java | 71 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 72 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/y/YipYip.java diff --git a/Mage.Sets/src/mage/cards/y/YipYip.java b/Mage.Sets/src/mage/cards/y/YipYip.java new file mode 100644 index 00000000000..1eb242e208e --- /dev/null +++ b/Mage.Sets/src/mage/cards/y/YipYip.java @@ -0,0 +1,71 @@ +package mage.cards.y; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FlyingAbility; +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.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class YipYip extends CardImpl { + + public YipYip(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); + + this.subtype.add(SubType.LESSON); + + // Target creature you control gets +2/+2 until end of turn. If that creature is an Ally, it also gains flying until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2)); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + this.getSpellAbility().addEffect(new YipYipEffect()); + } + + private YipYip(final YipYip card) { + super(card); + } + + @Override + public YipYip copy() { + return new YipYip(this); + } +} + +class YipYipEffect extends OneShotEffect { + + YipYipEffect() { + super(Outcome.Benefit); + staticText = "If that creature is an Ally, it also gains flying until end of turn"; + } + + private YipYipEffect(final YipYipEffect effect) { + super(effect); + } + + @Override + public YipYipEffect copy() { + return new YipYipEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Optional.ofNullable(getTargetPointer().getFirst(game, source)) + .map(game::getPermanent) + .filter(permanent -> permanent.hasSubtype(SubType.ALLY, game)) + .ifPresent(permanent -> game.addEffect(new GainAbilityTargetEffect(FlyingAbility.getInstance()) + .setTargetPointer(new FixedTarget(permanent, game)), source)); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index cd29aa8fcc3..13ff3df913d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -253,6 +253,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("White Lotus Reinforcements", 251, Rarity.UNCOMMON, mage.cards.w.WhiteLotusReinforcements.class)); cards.add(new SetCardInfo("White Lotus Tile", 262, Rarity.MYTHIC, mage.cards.w.WhiteLotusTile.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("White Lotus Tile", 330, Rarity.MYTHIC, mage.cards.w.WhiteLotusTile.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Yip Yip!", 43, Rarity.COMMON, mage.cards.y.YipYip.class)); cards.add(new SetCardInfo("Yue, the Moon Spirit", 338, Rarity.RARE, mage.cards.y.YueTheMoonSpirit.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Yue, the Moon Spirit", 83, Rarity.RARE, mage.cards.y.YueTheMoonSpirit.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Yuyan Archers", 161, Rarity.COMMON, mage.cards.y.YuyanArchers.class)); -- 2.47.2 From c3f359c5e83c0715fefd0033d2c334b117d5986c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 10:08:03 -0500 Subject: [PATCH 099/261] [TLA] Implement Jet's Brainwashing --- .../src/mage/cards/j/JetsBrainwashing.java | 56 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 57 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/j/JetsBrainwashing.java diff --git a/Mage.Sets/src/mage/cards/j/JetsBrainwashing.java b/Mage.Sets/src/mage/cards/j/JetsBrainwashing.java new file mode 100644 index 00000000000..5c303a6e71d --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JetsBrainwashing.java @@ -0,0 +1,56 @@ +package mage.cards.j; + +import mage.abilities.condition.common.KickedCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.AddContinuousEffectToGame; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.combat.CantBlockTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.KickerAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.game.permanent.token.ClueArtifactToken; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JetsBrainwashing extends CardImpl { + + public JetsBrainwashing(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}"); + + // Kicker {3} + this.addAbility(new KickerAbility("{3}")); + + // Target creature can't block this turn. If this spell was kicked, gain control of that creature until end of turn, untap it, and it gains haste until end of turn. + this.getSpellAbility().addEffect(new CantBlockTargetEffect(Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new AddContinuousEffectToGame( + new GainControlTargetEffect(Duration.EndOfTurn), + new GainAbilityTargetEffect(HasteAbility.getInstance()) + ), KickedCondition.ONCE, "If this spell was kicked, gain control of that creature " + + "until end of turn, untap it, and it gains haste until end of turn" + ).addEffect(new UntapTargetEffect())); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Create a Clue token. + this.getSpellAbility().addEffect(new CreateTokenEffect(new ClueArtifactToken()).concatBy("
")); + } + + private JetsBrainwashing(final JetsBrainwashing card) { + super(card); + } + + @Override + public JetsBrainwashing copy() { + return new JetsBrainwashing(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 13ff3df913d..897a18e6200 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -137,6 +137,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Island", 293, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("It'll Quench Ya!", 58, Rarity.COMMON, mage.cards.i.ItllQuenchYa.class)); cards.add(new SetCardInfo("Jeong Jeong's Deserters", 25, Rarity.COMMON, mage.cards.j.JeongJeongsDeserters.class)); + cards.add(new SetCardInfo("Jet's Brainwashing", 143, Rarity.UNCOMMON, mage.cards.j.JetsBrainwashing.class)); cards.add(new SetCardInfo("Katara, Bending Prodigy", 59, Rarity.UNCOMMON, mage.cards.k.KataraBendingProdigy.class)); cards.add(new SetCardInfo("Katara, Water Tribe's Hope", 231, Rarity.RARE, mage.cards.k.KataraWaterTribesHope.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Water Tribe's Hope", 351, Rarity.RARE, mage.cards.k.KataraWaterTribesHope.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From d968fb9f70d0f127914b4f1bb068dfd0585b2561 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 12:38:20 -0500 Subject: [PATCH 100/261] [TLA] Implement Boomerang Basics --- .../src/mage/cards/b/BoomerangBasics.java | 74 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 75 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BoomerangBasics.java diff --git a/Mage.Sets/src/mage/cards/b/BoomerangBasics.java b/Mage.Sets/src/mage/cards/b/BoomerangBasics.java new file mode 100644 index 00000000000..29594aa5e7b --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BoomerangBasics.java @@ -0,0 +1,74 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetNonlandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BoomerangBasics extends CardImpl { + + public BoomerangBasics(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}"); + + this.subtype.add(SubType.LESSON); + + // Return target nonland permanent to its owner's hand. If you controlled that permanent, draw a card. + this.getSpellAbility().addEffect(new BoomerangBasicsEffect()); + this.getSpellAbility().addTarget(new TargetNonlandPermanent()); + } + + private BoomerangBasics(final BoomerangBasics card) { + super(card); + } + + @Override + public BoomerangBasics copy() { + return new BoomerangBasics(this); + } +} + +class BoomerangBasicsEffect extends OneShotEffect { + + BoomerangBasicsEffect() { + super(Outcome.Benefit); + staticText = "return target nonland permanent to its owner's hand. If you controlled that permanent, draw a card"; + } + + private BoomerangBasicsEffect(final BoomerangBasicsEffect effect) { + super(effect); + } + + @Override + public BoomerangBasicsEffect copy() { + return new BoomerangBasicsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (player == null || permanent == null) { + return false; + } + boolean flag = permanent.isControlledBy(player.getId()); + player.moveCards(permanent, Zone.HAND, source, game); + if (flag) { + game.processAction(); + player.drawCards(1, source, game); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 897a18e6200..817337a9aaa 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -53,6 +53,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Beetle-Headed Merchants", 86, Rarity.COMMON, mage.cards.b.BeetleHeadedMerchants.class)); cards.add(new SetCardInfo("Bender's Waterskin", 255, Rarity.COMMON, mage.cards.b.BendersWaterskin.class)); cards.add(new SetCardInfo("Boiling Rock Prison", 267, Rarity.COMMON, mage.cards.b.BoilingRockPrison.class)); + cards.add(new SetCardInfo("Boomerang Basics", 46, Rarity.UNCOMMON, mage.cards.b.BoomerangBasics.class)); cards.add(new SetCardInfo("Bumi Bash", 125, Rarity.COMMON, mage.cards.b.BumiBash.class)); cards.add(new SetCardInfo("Bumi, Unleashed", 211, Rarity.MYTHIC, mage.cards.b.BumiUnleashed.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bumi, Unleashed", 348, Rarity.MYTHIC, mage.cards.b.BumiUnleashed.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 143efd64cb0678af39e67d109ded4335d2735a47 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 12:38:56 -0500 Subject: [PATCH 101/261] [TLA] update spoiler --- .../src/mage/sets/AvatarTheLastAirbender.java | 2 +- Utils/mtg-cards-data.txt | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 817337a9aaa..813f2586113 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -79,8 +79,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Earth King's Lieutenant", 380, Rarity.RARE, mage.cards.e.EarthKingsLieutenant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earth Kingdom Jailer", 16, Rarity.UNCOMMON, mage.cards.e.EarthKingdomJailer.class)); cards.add(new SetCardInfo("Earth Kingdom Soldier", 216, Rarity.COMMON, mage.cards.e.EarthKingdomSoldier.class)); - cards.add(new SetCardInfo("Earth Rumble", 174, Rarity.UNCOMMON, mage.cards.e.EarthRumble.class)); cards.add(new SetCardInfo("Earth Rumble Wrestlers", 218, Rarity.COMMON, mage.cards.e.EarthRumbleWrestlers.class)); + cards.add(new SetCardInfo("Earth Rumble", 174, Rarity.UNCOMMON, mage.cards.e.EarthRumble.class)); cards.add(new SetCardInfo("Earth Village Ruffians", 219, Rarity.COMMON, mage.cards.e.EarthVillageRuffians.class)); cards.add(new SetCardInfo("Earthbending Lesson", 176, Rarity.COMMON, mage.cards.e.EarthbendingLesson.class)); cards.add(new SetCardInfo("Enter the Avatar State", 18, Rarity.UNCOMMON, mage.cards.e.EnterTheAvatarState.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 0e7e11ec94f..8b54d5634e5 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59772,7 +59772,9 @@ Appa, Steadfast Guardian|Avatar: The Last Airbender|10|M|{2}{W}{W}|Legendary Cre Avatar Enthusiasts|Avatar: The Last Airbender|11|C|{2}{W}|Creature - Human Peasant Ally|2|2|Whenever another Ally you control enters, put a +1/+1 counter on this creature.| Avatar's Wrath|Avatar: The Last Airbender|12|R|{2}{W}{W}|Sorcery|||Choose up to one target creature, then airbend each other creature.$Until your next turn, your opponents can't cast spells from anywhere other than their hand.$Exile Avatar's Wrath.| Compassionate Healer|Avatar: The Last Airbender|13|C|{1}{W}|Creature - Human Cleric Ally|2|2|Whenever this creature becomes tapped, you gain 1 life and scry 1.| +Destined Confrontation|Avatar: The Last Airbender|15|U|{2}{W}{W}|Sorcery|||Each player chooses any number of creatures they control with total power 4 or less, then sacrifices all other creatures they control.| Earth Kingdom Jailer|Avatar: The Last Airbender|16|U|{2}{W}|Creature - Human Soldier Ally|3|3|When this creature enters, exile up to one target artifact, creature, or enchantment an opponent controls with mana value 3 or greater until this creature leaves the battlefield.| +Earth Kingdom Protectors|Avatar: The Last Airbender|17|U|{W}|Creature - Human Soldier Ally|1|1|Vigilance$Sacrifice this creature: Another target Ally you control gains indestructible until end of turn.| Enter the Avatar State|Avatar: The Last Airbender|18|U|{W}|Instant - Lesson|||Until end of turn, target creature you control becomes an Avatar in addition to its other types and gains flying, first strike, lifelink, and hexproof.| Fancy Footwork|Avatar: The Last Airbender|19|U|{2}{W}|Instant - Lesson|||Untap one or two target creatures. They each get +2/+2 until end of turn.| Gather the White Lotus|Avatar: The Last Airbender|20|U|{4}{W}|Sorcery|||Create a 1/1 white Ally creature token for each Plains you control. Scry 2.| @@ -59787,12 +59789,14 @@ Momo, Playful Pet|Avatar: The Last Airbender|30|U|{W}|Legendary Creature - Lemur Path to Redemption|Avatar: The Last Airbender|31|C|{1}{W}|Enchantment - Aura|||Enchant creature$Enchanted creature can't attack or block.${5}, Sacrifice this Aura: Exile enchanted creature. Create a 1/1 white Ally creature token. Activate only during your turn.| Rabaroo Troop|Avatar: The Last Airbender|32|C|{3}{W}{W}|Creature - Rabbit Kangaroo|3|5|Landfall -- Whenever a land you control enters, this creature gains flying until end of turn and you gain 1 life.$Plainscycling {2}| Razor Rings|Avatar: The Last Airbender|33|C|{1}{W}|Instant|||Razor Rings deals 4 damage to target attacking or blocking creature. You gain life equal to the excess damage dealt this way.| +Sandbenders' Storm|Avatar: The Last Airbender|34|C|{3}{W}|Instant|||Choose one--$* Destroy target creature with power 4 or greater.$* Earthbend 3.| Southern Air Temple|Avatar: The Last Airbender|36|U|{3}{W}|Legendary Enchantment - Shrine|||When Southern Air Temple enters, put X +1/+1 counters on each creature you control, where X is the number of Shrines you control.$Whenever another Shrine you control enters, put a +1/+1 counter on each creature you control.| Suki, Courageous Rescuer|Avatar: The Last Airbender|37|R|{1}{W}{W}|Legendary Creature - Human Warrior Ally|2|4|Other creatures you control get +1/+0.$Whenever another permanent you control leaves the battlefield during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.| United Front|Avatar: The Last Airbender|39|M|{X}{W}{W}|Sorcery|||Create X 1/1 white Ally creature tokens, then put a +1/+1 counter on each creature you control.| Water Tribe Rallier|Avatar: The Last Airbender|42|U|{1}{W}|Creature - Human Soldier Ally|2|2|Waterbend {5}: Look at the top four cards of your library. You may reveal a creature card with power 3 or less from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| Yip Yip!|Avatar: The Last Airbender|43|C|{W}|Instant - Lesson|||Target creature you control gets +2/+2 until end of turn. If that creature is an Ally, it also gains flying until end of turn.| Boomerang Basics|Avatar: The Last Airbender|46|U|{U}|Sorcery - Lesson|||Return target nonland permanent to its owner's hand. If you controlled that permanent, draw a card.| +Ember Island Production|Avatar: The Last Airbender|48|U|{3}{U}{U}|Sorcery|||Choose one--$* Create a token that's a copy of target creature you control, except it's not legendary and it's a 4/4 Hero in addition to its other types.$* Create a token that's a copy of target creature an opponent controls, except it's not legendary and it's a 2/2 Coward in addition to its other types.| First-Time Flyer|Avatar: The Last Airbender|49|C|{1}{U}|Creature - Human Pilot Ally|1|2|Flying$This creature gets +1/+1 as long as there's a Lesson card in your graveyard.| Flexible Waterbender|Avatar: The Last Airbender|50|C|{3}{U}|Creature - Human Warrior Ally|2|5|Vigilance$Waterbend {3}: This creature has base power and toughness 5/2 until end of turn.| Forecasting Fortune Teller|Avatar: The Last Airbender|51|C|{1}{U}|Creature - Human Advisor Ally|1|3|When this creature enters, create a Clue token.| @@ -59838,6 +59842,7 @@ Dai Li Indoctrination|Avatar: The Last Airbender|93|C|{1}{B}|Sorcery - Lesson||| Day of Black Sun|Avatar: The Last Airbender|94|R|{X}{B}{B}|Sorcery|||Each creature with mana value X or less loses all abilities until end of turn. Destroy those creatures.| Deadly Precision|Avatar: The Last Airbender|95|C|{B}|Sorcery|||As an additional cost to cast this spell, pay {4} or sacrifice an artifact or creature.$Destroy target creature.| Epic Downfall|Avatar: The Last Airbender|96|U|{1}{B}|Sorcery|||Exile target creature with mana value 3 or greater.| +Fatal Fissure|Avatar: The Last Airbender|97|U|{1}{B}|Instant|||Choose target creature. When that creature dies this turn, you earthbend 4.| The Fire Nation Drill|Avatar: The Last Airbender|98|R|{2}{B}{B}|Legendary Artifact - Vehicle|6|3|Trample$When The Fire Nation Drill enters, you may tap it. When you do, destroy target creature with power 4 or less.${1}: Permanents your opponents control lose hexproof and indestructible until end of turn.$Crew 2| Fire Nation Engineer|Avatar: The Last Airbender|99|U|{2}{B}|Creature - Human Artificer|2|3|Raid -- At the beginning of your end step, if you attacked this turn, put a +1/+1 counter on another target creature or Vehicle you control.| Fire Navy Trebuchet|Avatar: The Last Airbender|100|U|{2}{B}|Artifact Creature - Wall|0|4|Defender, reach$Whenever you attack, create a 2/1 colorless Construct artifact creature token with flying named Ballistic Boulder that's tapped and attacking. Sacrifice that token at the beginning of the next end step.| @@ -59854,14 +59859,18 @@ The Rise of Sozin|Avatar: The Last Airbender|117|M|{4}{B}{B}|Enchantment - Saga| Fire Lord Sozin|Avatar: The Last Airbender|117|M||Legendary Creature - Human Noble|5|5|Menace, firebending 3$Whenever Fire Lord Sozin deals combat damage to a player, you may pay {X}. When you do, put any number of target creature cards with total mana value X or less from that player's graveyard onto the battlefield under your control.| Sold Out|Avatar: The Last Airbender|119|C|{3}{B}|Instant|||Exile target creature. If it was dealt damage this turn, create a Clue token.| Tundra Tank|Avatar: The Last Airbender|121|U|{2}{B}|Artifact - Vehicle|4|4|Firebending 1$When this Vehicle enters, target creature you control gains indestructible until end of turn.$Crew 1| +Wolfbat|Avatar: The Last Airbender|122|U|{2}{B}|Creature - Wolf Bat|2|2|Flying$Whenever you draw your second card each turn, you may pay {B}. If you do, return this card from your graveyard to the battlefield with a finality counter on it.| Bumi Bash|Avatar: The Last Airbender|125|C|{3}{R}|Sorcery|||Choose one --$* Bumi Bash deals damage equal to the number of lands you control to target creature.$* Destroy target land creature or nonbasic land.| The Cave of Two Lovers|Avatar: The Last Airbender|126|U|{3}{R}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I -- Create two 1/1 white Ally creature tokens.$II -- Search your library for a Mountain or Cave card, reveal it, put it into your hand,$then shuffle.$III -- Earthbend 3.| +Combustion Man|Avatar: The Last Airbender|127|U|{3}{R}{R}|Legendary Creature - Human Assassin|4|6|Whenever Combustion Man attacks, destroy target permanent unless its controller has Combustion Man deal damage to them equal to his power.| +Combustion Technique|Avatar: The Last Airbender|128|U|{1}{R}|Instant - Lesson|||Combustion Technique deals damage equal to 2 plus the number of Lesson cards in your graveyard to target creature. If that creature would die this turn, exile it instead.| Crescent Island Temple|Avatar: The Last Airbender|129|U|{3}{R}|Legendary Enchantment - Shrine|||When Crescent Island Temple enters, for each Shrine you control, create a 1/1 red Monk creature token with prowess.$Whenever another Shrine you control enters, create a 1/1 red Monk creature token with prowess.| Cunning Maneuver|Avatar: The Last Airbender|130|C|{1}{R}|Instant|||Target creature gets +3/+1 until end of turn.$Create a Clue token.| Deserter's Disciple|Avatar: The Last Airbender|131|C|{1}{R}|Creature - Human Rebel Ally|2|2|{T}: Another target creature you control with power 2 or less can't be blocked this turn.| Fated Firepower|Avatar: The Last Airbender|132|M|{X}{R}{R}{R}|Enchantment|||Flash$This enchantment enters with X fire counters on it.$If a source you control would deal damage to an opponent or a permanent an opponent controls, it deals that much damage plus an amount of damage equal to the number of fire counters on this enchantment instead.| Fire Nation Attacks|Avatar: The Last Airbender|133|U|{4}{R}|Instant|||Create two 2/2 red Soldier creature tokens with firebending 1.$Flashback {8}{R}| Fire Nation Cadets|Avatar: The Last Airbender|134|C|{R}|Creature - Human Soldier|1|2|This creature has firebending 2 as long as there's a Lesson card in your graveyard.${2}: This creature gets +1/+0 until end of turn.| +Fire Nation Raider|Avatar: The Last Airbender|135|C|{3}{R}|Creature - Human Soldier|4|2|Raid -- When this creature enters, if you attacked this turn, create a Clue token.| Fire Sages|Avatar: The Last Airbender|136|U|{1}{R}|Creature - Human Cleric|2|2|Firebending 1${1}{R}{R}: Put a +1/+1 counter on this creature.| Firebender Ascension|Avatar: The Last Airbender|137|R|{1}{R}|Enchantment|||When this enchantment enters, create a 2/2 red Soldier creature token with firebending 1.$Whenever a creature you control attacking causes a triggered ability of that creature to trigger, put a quest counter on this enchantment. Then if it has four or more quest counters on it, you may copy that ability. You may choose new targets for the copy.| Firebending Student|Avatar: The Last Airbender|139|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| @@ -59899,11 +59908,13 @@ Diligent Zookeeper|Avatar: The Last Airbender|171|R|{3}{G}|Creature - Human Citi The Earth King|Avatar: The Last Airbender|172|R|{3}{G}|Legendary Creature - Human Noble Ally|2|2|When The Earth King enters, create a 4/4 green Bear creature token.$Whenever one or more creatures you control with power 4 or greater attack, search your library for up to that many basic land cards, put them onto the battlefield tapped, then shuffle.| Earth Kingdom General|Avatar: The Last Airbender|173|U|{3}{G}|Creature - Human Soldier Ally|2|2|When this creature enters, earthbend 2.$Whenever you put one or more +1/+1 counters on a creature, you may gain that much life. Do this only once each turn.| Earth Rumble|Avatar: The Last Airbender|174|U|{3}{G}|Sorcery|||Earthbend 2. When you do, up to one target creature you control fights target creature an opponent controls.| +Earthbender Ascension|Avatar: The Last Airbender|175|R|{2}{G}|Enchantment|||When this enchantment enters, earthbend 2. Then search your library for a basic land card, put it onto the battlefield tapped, then shuffle.$Landfall -- Whenever a land you control enters, put a quest counter on this enchantment. When you do, if it has four or more quest counters on it, put a +1/+1 counter on target creature you control. It gains trample until end of turn.| Earthbending Lesson|Avatar: The Last Airbender|176|C|{3}{G}|Sorcery - Lesson|||Earthbend 4.| Elemental Teachings|Avatar: The Last Airbender|178|R|{4}{G}|Instant - Lesson|||Search your library for up to four land cards with different names and reveal them. An opponent chooses two of those cards. Put the chosen cards into your graveyard and the rest onto the battlefield tapped, then shuffle.| Flopsie, Bumi's Buddy|Avatar: The Last Airbender|179|U|{4}{G}{G}|Legendary Creature - Ape Goat|4|4|When Flopsie enters, put a +1/+1 counter on each creature you control.$Each creature you control with power 4 or greater can't be blocked by more than one creature.| Haru, Hidden Talent|Avatar: The Last Airbender|182|U|{1}{G}|Legendary Creature - Human Peasant Ally|1|1|Whenever another Ally you control enters, earthbend 1.| Invasion Tactics|Avatar: The Last Airbender|183|U|{4}{G}|Enchantment|||When this enchantment enters, creatures you control get +2/+2 until end of turn.$Whenever one or more Allies you control deal combat damage to a player, draw a card.| +Kyoshi Island Plaza|Avatar: The Last Airbender|184|U|{3}{G}|Legendary Enchantment - Shrine|||When Kyoshi Island Plaza enters, search your library for up to X basic land cards, where X is the number of Shrines you control. Put those cards onto the battlefield tapped, then shuffle.$Whenever another Shrine you control enters, search your library for a basic land card, put it onto the battlefield tapped, then shuffle.| Leaves from the Vine|Avatar: The Last Airbender|185|U|{1}{G}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I -- Mill three cards, then create a Food token.$II -- Put a +1/+1 counter on each of up to two target creatures you control.$III -- Draw a card if there's a creature or Lesson card in your graveyard.| Origin of Metalbending|Avatar: The Last Airbender|187|C|{1}{G}|Instant - Lesson|||Choose one --$* Destroy target artifact or enchantment.$* Put a +1/+1 counter on target creature you control. It gains indestructible until end of turn.| Ostrich-Horse|Avatar: The Last Airbender|188|C|{2}{G}|Creature - Bird Horse|3|1|When this creature enters, mill three cards. You may put a land card from among them into your hand. If you don't, put a +1/+1 counter on this creature.| @@ -60005,11 +60016,13 @@ Fated Firepower|Avatar: The Last Airbender|297|M|{X}{R}{R}{R}|Enchantment|||Flas Aang, Swift Savior|Avatar: The Last Airbender|298|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| Aang and La, Ocean's Fury|Avatar: The Last Airbender|298|R||Legendary Creature - Avatar Spirit Ally|5|5|Reach, trample$Whenever Aang and La attack, put a +1/+1 counter on each tapped creature you control.| Fire Nation Attacks|Avatar: The Last Airbender|299|U|{4}{R}|Instant|||Create two 2/2 red Soldier creature tokens with firebending 1.$Flashback {8}{R}| +Combustion Technique|Avatar: The Last Airbender|301|U|{1}{R}|Instant - Lesson|||Combustion Technique deals damage equal to 2 plus the number of Lesson cards in your graveyard to target creature. If that creature would die this turn, exile it instead.| Azula, Cunning Usurper|Avatar: The Last Airbender|303|R|{2}{U}{B}{B}|Legendary Creature - Human Noble Rogue|4|4|Firebending 2$When Azula enters, target opponent exiles a nontoken creature they control, then they exile a nonland card from their graveyard.$During your turn, you may cast cards exiled with Azula and you may cast them as though they had flash. Mana of any type can be spent to cast those spells.| Aang, at the Crossroads|Avatar: The Last Airbender|304|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| Aang, Destined Savior|Avatar: The Last Airbender|304|R||Legendary Creature - Avatar Ally|4|4|Flying$Land creatures you control have vigilance.$At the beginning of combat on your turn, earthbend 2.| Katara, the Fearless|Avatar: The Last Airbender|305|R|{G}{W}{U}|Legendary Creature - Human Warrior Ally|3|3|If a triggered ability of an Ally you control triggers, that ability triggers an additional time.| Dai Li Agents|Avatar: The Last Airbender|306|U|{3}{B}{G}|Creature - Human Soldier|3|4|When this creature enters, earthbend 1, then earthbend 1.$Whenever this creature attacks, each opponent loses X life and you gain X life, where X is the number of creatures you control with +1/+1 counters on them.| +Earthbender Ascension|Avatar: The Last Airbender|307|R|{2}{G}|Enchantment|||When this enchantment enters, earthbend 2. Then search your library for a basic land card, put it onto the battlefield tapped, then shuffle.$Landfall -- Whenever a land you control enters, put a quest counter on this enchantment. When you do, if it has four or more quest counters on it, put a +1/+1 counter on target creature you control. It gains trample until end of turn.| Avatar Aang|Avatar: The Last Airbender|308|M|{R}{G}{W}{U}|Legendary Creature - Human Avatar Ally|4|4|Flying, firebending 2$Whenever you waterbend, earthbend, firebend, or airbend, draw a card. Then if you've done all four this turn, transform Avatar Aang.| Aang, Master of Elements|Avatar: The Last Airbender|308|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Sozin's Comet|Avatar: The Last Airbender|309|M|{3}{R}{R}|Sorcery|||Each creature you control gains firebending 5 until end of turn.$Foretell {2}{R}| @@ -60078,6 +60091,7 @@ Ty Lee, Chi Blocker|Avatar: The Last Airbender|371|R|{2}{U}|Legendary Creature - Boiling Rock Rioter|Avatar: The Last Airbender|372|R|{2}{B}|Creature - Human Rogue Ally|3|3|Firebending 1$Tap an untapped Ally you control: Exile target card from a graveyard.$Whenever this creature attacks, you may cast an Ally spell from among cards you own exiled with this creature.| Day of Black Sun|Avatar: The Last Airbender|373|R|{X}{B}{B}|Sorcery|||Each creature with mana value X or less loses all abilities until end of turn. Destroy those creatures.| Mai, Scornful Striker|Avatar: The Last Airbender|374|R|{1}{B}|Legendary Creature - Human Noble Ally|2|2|First strike$Whenever a player casts a noncreature spell, they lose 2 life.| +Elemental Teachings|Avatar: The Last Airbender|378|R|{4}{G}|Instant - Lesson|||Search your library for up to four land cards with different names and reveal them. An opponent chooses two of those cards. Put the chosen cards into your graveyard and the rest onto the battlefield tapped, then shuffle.| Beifong's Bounty Hunters|Avatar: The Last Airbender|379|R|{2}{B}{G}|Creature - Human Mercenary|4|4|Whenever a nonland creature you control dies, earthbend X, where X is that creature's power.| Earth King's Lieutenant|Avatar: The Last Airbender|380|R|{G}{W}|Creature - Human Soldier Ally|1|1|Trample$When this creature enters, put a +1/+1 counter on each other Ally creature you control.$Whenever another Ally you control enters, put a +1/+1 counter on this creature.| Iroh, Tea Master|Avatar: The Last Airbender|381|R|{1}{R}{W}|Legendary Creature - Human Citizen Ally|2|2|When Iroh enters, create a Food token.$At the beginning of combat on your turn, you may have target opponent gain control of target permanent you control. When you do, create a 1/1 white Ally creature token. Put a +1/+1 counter on that token for each permanent you own that your opponents control.| -- 2.47.2 From dc07b24ed3963dfd0427673d13f4cafbf1fdee61 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 12:40:16 -0500 Subject: [PATCH 102/261] [TLA] Implement Fire Nation Raider --- .../src/mage/cards/f/FireNationRaider.java | 46 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 47 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FireNationRaider.java diff --git a/Mage.Sets/src/mage/cards/f/FireNationRaider.java b/Mage.Sets/src/mage/cards/f/FireNationRaider.java new file mode 100644 index 00000000000..eeb93a34232 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FireNationRaider.java @@ -0,0 +1,46 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.common.RaidCondition; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.hint.common.RaidHint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.ClueArtifactToken; +import mage.watchers.common.PlayerAttackedWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FireNationRaider extends CardImpl { + + public FireNationRaider(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // Raid -- When this creature enters, if you attacked this turn, create a Clue token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ClueArtifactToken())) + .withInterveningIf(RaidCondition.instance) + .setAbilityWord(AbilityWord.RAID) + .addHint(RaidHint.instance), new PlayerAttackedWatcher()); + } + + private FireNationRaider(final FireNationRaider card) { + super(card); + } + + @Override + public FireNationRaider copy() { + return new FireNationRaider(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 813f2586113..b85a5a6e456 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -103,6 +103,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Fire Nation Engineer", 99, Rarity.UNCOMMON, mage.cards.f.FireNationEngineer.class)); cards.add(new SetCardInfo("Fire Nation Palace", 268, Rarity.RARE, mage.cards.f.FireNationPalace.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation Palace", 389, Rarity.RARE, mage.cards.f.FireNationPalace.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fire Nation Raider", 135, Rarity.COMMON, mage.cards.f.FireNationRaider.class)); cards.add(new SetCardInfo("Fire Nation Warship", 256, Rarity.UNCOMMON, mage.cards.f.FireNationWarship.class)); cards.add(new SetCardInfo("Fire Sages", 136, Rarity.UNCOMMON, mage.cards.f.FireSages.class)); cards.add(new SetCardInfo("Firebending Student", 139, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 6b482f2afcaea37cd75e5126523f4964cfcab913 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 12:52:02 -0500 Subject: [PATCH 103/261] [TLA] Implement Earthbender Ascension --- .../mage/cards/e/EarthbenderAscension.java | 95 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + .../delayed/ReflexiveTriggeredAbility.java | 11 +-- 3 files changed, 100 insertions(+), 8 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/e/EarthbenderAscension.java diff --git a/Mage.Sets/src/mage/cards/e/EarthbenderAscension.java b/Mage.Sets/src/mage/cards/e/EarthbenderAscension.java new file mode 100644 index 00000000000..d68fd37a8f9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EarthbenderAscension.java @@ -0,0 +1,95 @@ +package mage.cards.e; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.LandfallAbility; +import mage.abilities.common.delayed.ReflexiveTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EarthbenderAscension extends CardImpl { + + public EarthbenderAscension(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); + + // When this enchantment enters, earthbend 2. Then search your library for a basic land card, put it onto the battlefield tapped, then shuffle. + Ability ability = new EntersBattlefieldTriggeredAbility(new EarthbendTargetEffect(2)); + ability.addEffect(new SearchLibraryPutInPlayEffect( + new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true + ).concatBy("Then")); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability); + + // Landfall -- Whenever a land you control enters, put a quest counter on this enchantment. When you do, if it has four or more quest counters on it, put a +1/+1 counter on target creature you control. It gains trample until end of turn. + this.addAbility(new LandfallAbility(new EarthbenderAscensionEffect())); + } + + private EarthbenderAscension(final EarthbenderAscension card) { + super(card); + } + + @Override + public EarthbenderAscension copy() { + return new EarthbenderAscension(this); + } +} + +class EarthbenderAscensionEffect extends OneShotEffect { + + private static final Condition condition = new SourceHasCounterCondition(CounterType.QUEST, ComparisonType.MORE_THAN, 3); + + EarthbenderAscensionEffect() { + super(Outcome.Benefit); + staticText = "put a quest counter on {this}. When you do, if it has four or more quest counters on it, " + + "put a +1/+1 counter on target creature you control. It gains trample until end of turn"; + } + + private EarthbenderAscensionEffect(final EarthbenderAscensionEffect effect) { + super(effect); + } + + @Override + public EarthbenderAscensionEffect copy() { + return new EarthbenderAscensionEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null || !permanent.addCounters(CounterType.QUEST.createInstance(), source, game)) { + return false; + } + ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false, "When you do, " + + "if it has four or more quest counters on it, put a +1/+1 counter on target creature you control. " + + "It gains trample until end of turn", condition + ); + ability.addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance())); + ability.addTarget(new TargetControlledCreaturePermanent()); + game.fireReflexiveTriggeredAbility(ability, source); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b85a5a6e456..7b47ffe41d8 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -82,6 +82,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Earth Rumble Wrestlers", 218, Rarity.COMMON, mage.cards.e.EarthRumbleWrestlers.class)); cards.add(new SetCardInfo("Earth Rumble", 174, Rarity.UNCOMMON, mage.cards.e.EarthRumble.class)); cards.add(new SetCardInfo("Earth Village Ruffians", 219, Rarity.COMMON, mage.cards.e.EarthVillageRuffians.class)); + cards.add(new SetCardInfo("Earthbender Ascension", 175, Rarity.RARE, mage.cards.e.EarthbenderAscension.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Earthbender Ascension", 307, Rarity.RARE, mage.cards.e.EarthbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earthbending Lesson", 176, Rarity.COMMON, mage.cards.e.EarthbendingLesson.class)); cards.add(new SetCardInfo("Enter the Avatar State", 18, Rarity.UNCOMMON, mage.cards.e.EnterTheAvatarState.class)); cards.add(new SetCardInfo("Epic Downfall", 96, Rarity.UNCOMMON, mage.cards.e.EpicDownfall.class)); diff --git a/Mage/src/main/java/mage/abilities/common/delayed/ReflexiveTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/ReflexiveTriggeredAbility.java index 2c4cc9afc07..a6d0387fc46 100644 --- a/Mage/src/main/java/mage/abilities/common/delayed/ReflexiveTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/delayed/ReflexiveTriggeredAbility.java @@ -14,7 +14,6 @@ import mage.util.CardUtil; public class ReflexiveTriggeredAbility extends DelayedTriggeredAbility { private final String text; - private final Condition condition; public ReflexiveTriggeredAbility(Effect effect, boolean optional) { this(effect, optional, null); @@ -27,13 +26,14 @@ public class ReflexiveTriggeredAbility extends DelayedTriggeredAbility { public ReflexiveTriggeredAbility(Effect effect, boolean optional, String text, Condition condition) { super(effect, Duration.EndOfTurn, true, optional); this.text = text; - this.condition = condition; + if (condition != null) { + this.withInterveningIf(condition); + } } protected ReflexiveTriggeredAbility(final ReflexiveTriggeredAbility ability) { super(ability); this.text = ability.text; - this.condition = ability.condition; } @Override @@ -55,11 +55,6 @@ public class ReflexiveTriggeredAbility extends DelayedTriggeredAbility { return CardUtil.getTextWithFirstCharUpperCase(text) + '.'; } - @Override - public boolean checkInterveningIfClause(Game game) { - return condition == null || condition.apply(game, this); - } - @Override public ReflexiveTriggeredAbility setTriggerPhrase(String triggerPhrase) { super.setTriggerPhrase(triggerPhrase); -- 2.47.2 From d4635eb0608e7e74fc29d1cb57749e13c5e6dd73 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 4 Nov 2025 13:01:09 -0500 Subject: [PATCH 104/261] [TLA] Implement Sandbenders' Storm --- .../src/mage/cards/s/SandbendersStorm.java | 50 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 51 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SandbendersStorm.java diff --git a/Mage.Sets/src/mage/cards/s/SandbendersStorm.java b/Mage.Sets/src/mage/cards/s/SandbendersStorm.java new file mode 100644 index 00000000000..3326fa727bc --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SandbendersStorm.java @@ -0,0 +1,50 @@ +package mage.cards.s; + +import mage.abilities.Mode; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SandbendersStorm extends CardImpl { + + private static final FilterPermanent filter = new FilterCreaturePermanent("creature with power 4 or greater"); + + static { + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + } + + public SandbendersStorm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}"); + + // Choose one-- + // * Destroy target creature with power 4 or greater. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); + + // * Earthbend 3. + this.getSpellAbility().addMode(new Mode(new EarthbendTargetEffect(3)) + .addTarget(new TargetControlledLandPermanent())); + } + + private SandbendersStorm(final SandbendersStorm card) { + super(card); + } + + @Override + public SandbendersStorm copy() { + return new SandbendersStorm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 7b47ffe41d8..b3d50a18d7a 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -199,6 +199,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Rough Rhino Cavalry", 152, Rarity.COMMON, mage.cards.r.RoughRhinoCavalry.class)); cards.add(new SetCardInfo("Rowdy Snowballers", 68, Rarity.COMMON, mage.cards.r.RowdySnowballers.class)); cards.add(new SetCardInfo("Saber-Tooth Moose-Lion", 194, Rarity.COMMON, mage.cards.s.SaberToothMooseLion.class)); + cards.add(new SetCardInfo("Sandbenders' Storm", 34, Rarity.COMMON, mage.cards.s.SandbendersStorm.class)); cards.add(new SetCardInfo("Seismic Sense", 195, Rarity.UNCOMMON, mage.cards.s.SeismicSense.class)); cards.add(new SetCardInfo("Serpent of the Pass", 70, Rarity.UNCOMMON, mage.cards.s.SerpentOfThePass.class)); cards.add(new SetCardInfo("Serpent's Pass", 279, Rarity.COMMON, mage.cards.s.SerpentsPass.class)); -- 2.47.2 From 9d1d27c9a56068208f414a10d0bbe9d6cab3a9f3 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:08:16 -0500 Subject: [PATCH 105/261] [TLA] update spoiler --- .../src/mage/sets/AvatarTheLastAirbender.java | 2 +- Utils/mtg-cards-data.txt | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b3d50a18d7a..14d8bf3a0e2 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -12,7 +12,7 @@ import java.util.List; */ public final class AvatarTheLastAirbender extends ExpansionSet { - private static final List unfinished = Arrays.asList("Aang's Iceberg", "Aang, Swift Savior", "Avatar Aang", "Flexible Waterbender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Invasion Submersible", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "Spirit Water Revival", "The Legend of Kuruk", "The Unagi of Kyoshi Island", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); + private static final List unfinished = Arrays.asList("Aang's Iceberg", "Aang, Swift Savior", "Avatar Aang", "Benevolent River Spirit", "Crashing Wave", "Flexible Waterbender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Invasion Submersible", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "Spirit Water Revival", "The Legend of Kuruk", "The Unagi of Kyoshi Island", "Waterbender Ascension", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); private static final AvatarTheLastAirbender instance = new AvatarTheLastAirbender(); public static AvatarTheLastAirbender getInstance() { diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 8b54d5634e5..566debe0a9b 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59780,7 +59780,9 @@ Fancy Footwork|Avatar: The Last Airbender|19|U|{2}{W}|Instant - Lesson|||Untap o Gather the White Lotus|Avatar: The Last Airbender|20|U|{4}{W}|Sorcery|||Create a 1/1 white Ally creature token for each Plains you control. Scry 2.| Glider Kids|Avatar: The Last Airbender|21|C|{2}{W}|Creature - Human Pilot Ally|2|3|Flying$When this creature enters, scry 1.| Glider Staff|Avatar: The Last Airbender|22|U|{2}{W}|Artifact - Equipment|||When this Equipment enters, airbend up to one target creature.$Equipped creature gets +1/+1 and has flying.$Equip {2}| +Invasion Reinforcements|Avatar: The Last Airbender|24|U|{1}{W}|Creature - Human Warrior Ally|1|1|Flash$When this creature enters, create a 1/1 white Ally creature token.| Jeong Jeong's Deserters|Avatar: The Last Airbender|25|C|{1}{W}|Creature - Human Rebel Ally|1|2|When this creature enters, put a +1/+1 counter on target creature.| +Kyoshi Warriors|Avatar: The Last Airbender|26|C|{3}{W}|Creature - Human Warrior Ally|3|3|When this creature enters, create a 1/1 white Ally creature token.| The Legend of Yangchen|Avatar: The Last Airbender|27|M|{3}{W}{W}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$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.$II -- You may have target opponent draw three cards. If you do, draw three cards.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| Avatar Yangchen|Avatar: The Last Airbender|27|M||Legendary Creature - Avatar|4|5|Flying$Whenever you cast your second spell each turn, airbend up to one other target nonland permanent.| Master Piandao|Avatar: The Last Airbender|28|U|{4}{W}|Legendary Creature - Human Warrior Ally|4|4|First strike$Whenever Master Piandao attacks, look at the top four cards of your library. You may reveal an Ally, Equipment, or Lesson card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| @@ -59795,7 +59797,9 @@ Suki, Courageous Rescuer|Avatar: The Last Airbender|37|R|{1}{W}{W}|Legendary Cre United Front|Avatar: The Last Airbender|39|M|{X}{W}{W}|Sorcery|||Create X 1/1 white Ally creature tokens, then put a +1/+1 counter on each creature you control.| Water Tribe Rallier|Avatar: The Last Airbender|42|U|{1}{W}|Creature - Human Soldier Ally|2|2|Waterbend {5}: Look at the top four cards of your library. You may reveal a creature card with power 3 or less from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| Yip Yip!|Avatar: The Last Airbender|43|C|{W}|Instant - Lesson|||Target creature you control gets +2/+2 until end of turn. If that creature is an Ally, it also gains flying until end of turn.| +Benevolent River Spirit|Avatar: The Last Airbender|45|U|{U}{U}|Creature - Spirit|4|5|As an additional cost to cast this spell, waterbend {5}.$Flying, ward {2}$When this creature enters, scry 2.| Boomerang Basics|Avatar: The Last Airbender|46|U|{U}|Sorcery - Lesson|||Return target nonland permanent to its owner's hand. If you controlled that permanent, draw a card.| +Crashing Wave|Avatar: The Last Airbender|47|U|{U}{U}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Tap up to X target creatures, then distribute three stun counters among tapped creatures your opponents control.| Ember Island Production|Avatar: The Last Airbender|48|U|{3}{U}{U}|Sorcery|||Choose one--$* Create a token that's a copy of target creature you control, except it's not legendary and it's a 4/4 Hero in addition to its other types.$* Create a token that's a copy of target creature an opponent controls, except it's not legendary and it's a 2/2 Coward in addition to its other types.| First-Time Flyer|Avatar: The Last Airbender|49|C|{1}{U}|Creature - Human Pilot Ally|1|2|Flying$This creature gets +1/+1 as long as there's a Lesson card in your graveyard.| Flexible Waterbender|Avatar: The Last Airbender|50|C|{3}{U}|Creature - Human Warrior Ally|2|5|Vigilance$Waterbend {3}: This creature has base power and toughness 5/2 until end of turn.| @@ -59808,6 +59812,7 @@ Iguana Parrot|Avatar: The Last Airbender|56|C|{2}{U}|Creature - Lizard Bird Pira Invasion Submersible|Avatar: The Last Airbender|57|U|{2}{U}|Artifact - Vehicle|0|0|When this Vehicle enters, return up to one other target nonland permanent to its owner's hand.$Exhaust -- Waterbend {3}: This Vehicle becomes an artifact creature. Put three +1/+1 counters on it.| It'll Quench Ya!|Avatar: The Last Airbender|58|C|{1}{U}|Instant - Lesson|||Counter target spell unless its controller pays {2}.| Katara, Bending Prodigy|Avatar: The Last Airbender|59|U|{2}{U}|Legendary Creature - Human Warrior Ally|2|3|At the beginning of your end step, if Katara is tapped, put a +1/+1 counter on her.$Waterbend {6}: Draw a card.| +Knowledge Seeker|Avatar: The Last Airbender|60|U|{1}{U}|Creature - Fox Spirit|2|1|Vigilance$Whenever you draw your second card each turn, put a +1/+1 counter on this creature.$When this creature dies, create a Clue token.| The Legend of Kuruk|Avatar: The Last Airbender|61|M|{2}{U}{U}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I, II -- Scry 2, then draw a card.$III -- Exile this Saga, then return it to the battlefield$transformed under your control.| Avatar Kuruk|Avatar: The Last Airbender|61|M||Legendary Creature - Avatar|4|3|Whenever you cast a spell, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."$Exhaust -- Waterbend {20}: Take an extra turn after this one.| Lost Days|Avatar: The Last Airbender|62|C|{4}{U}|Instant - Lesson|||The owner of target creature or enchantment puts it into their library second from the top or on the bottom. You create a Clue token.| @@ -59827,6 +59832,7 @@ Tiger-Seal|Avatar: The Last Airbender|75|R|{U}|Creature - Cat Seal|3|3|Vigilance Ty Lee, Chi Blocker|Avatar: The Last Airbender|76|R|{2}{U}|Legendary Creature - Human Performer Ally|2|1|Flash$Prowess$When Ty Lee enters, tap up to one target creature. It doesn't untap during its controller's untap step for as long as you control Ty Lee.| The Unagi of Kyoshi Island|Avatar: The Last Airbender|77|R|{3}{U}{U}|Legendary Creature - Serpent|5|5|Flash$Ward--Waterbend {4}$Whenever an opponent draws their second card each turn, draw two cards.| Wan Shi Tong, Librarian|Avatar: The Last Airbender|78|M|{X}{U}{U}|Legendary Creature - Bird Spirit|1|1|Flash$Flying, vigilance$When Wan Shi Tong enters, put X +1/+1 counters on him. Then draw half X cards, rounded down.$Whenever an opponent searches their library, put a +1/+1 counter on Wan Shi Tong and draw a card.| +Waterbender Ascension|Avatar: The Last Airbender|79|R|{1}{U}|Enchantment|||Whenever a creature you control deals combat damage to a player, put a quest counter on this enchantment. Then if it has four or more quest counters on it, draw a card.$Waterbend {4}: Target creature can't be blocked this turn.| Waterbending Lesson|Avatar: The Last Airbender|80|C|{3}{U}|Sorcery - Lesson|||Draw three cards. Then discard a card unless you waterbend {2}.| Watery Grasp|Avatar: The Last Airbender|82|C|{U}|Enchantment - Aura|||Enchant creature$Enchanted creature doesn't untap during its controller's untap step.$Waterbend {5}: Enchanted creature's owner shuffles it into their library.| Yue, the Moon Spirit|Avatar: The Last Airbender|83|R|{3}{U}|Legendary Creature - Spirit Ally|3|3|Flying, vigilance$Waterbend {5}, {T}: You may cast a noncreature spell from your hand without paying its mana cost.| @@ -59846,6 +59852,7 @@ Fatal Fissure|Avatar: The Last Airbender|97|U|{1}{B}|Instant|||Choose target cre The Fire Nation Drill|Avatar: The Last Airbender|98|R|{2}{B}{B}|Legendary Artifact - Vehicle|6|3|Trample$When The Fire Nation Drill enters, you may tap it. When you do, destroy target creature with power 4 or less.${1}: Permanents your opponents control lose hexproof and indestructible until end of turn.$Crew 2| Fire Nation Engineer|Avatar: The Last Airbender|99|U|{2}{B}|Creature - Human Artificer|2|3|Raid -- At the beginning of your end step, if you attacked this turn, put a +1/+1 counter on another target creature or Vehicle you control.| Fire Navy Trebuchet|Avatar: The Last Airbender|100|U|{2}{B}|Artifact Creature - Wall|0|4|Defender, reach$Whenever you attack, create a 2/1 colorless Construct artifact creature token with flying named Ballistic Boulder that's tapped and attacking. Sacrifice that token at the beginning of the next end step.| +Foggy Swamp Hunters|Avatar: The Last Airbender|101|C|{3}{B}|Creature - Human Ranger Ally|3|4|As long as you've drawn two or more cards this turn, this creature has lifelink and menace.| Foggy Swamp Visions|Avatar: The Last Airbender|102|R|{1}{B}{B}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Exile X target creature cards from graveyards. For each creature card exiled this way, create a token that's a copy of it. At the beginning of your next end step, sacrifice those tokens.| Heartless Act|Avatar: The Last Airbender|103|U|{1}{B}|Instant|||Choose one --$* Destroy target creature with no counters on it.$* Remove up to three counters from target creature.| Hog-Monkey|Avatar: The Last Airbender|104|C|{2}{B}|Creature - Boar Monkey|3|2|At the beginning of combat on your turn, target creature you control with a +1/+1 counter on it gains menace until end of turn.$Exhaust -- {5}: Put two +1/+1 counters on this creature.| @@ -59853,11 +59860,13 @@ June, Bounty Hunter|Avatar: The Last Airbender|106|U|{1}{B}|Legendary Creature - Mai, Scornful Striker|Avatar: The Last Airbender|109|R|{1}{B}|Legendary Creature - Human Noble Ally|2|2|First strike$Whenever a player casts a noncreature spell, they lose 2 life.| Merchant of Many Hats|Avatar: The Last Airbender|110|C|{1}{B}|Creature - Human Peasant Ally|2|2|{2}{B}: Return this card from your graveyard to your hand.| Northern Air Temple|Avatar: The Last Airbender|111|U|{B}|Legendary Enchantment - Shrine|||When Northern Air Temple enters, each opponent loses X life and you gain X life, where X is the number of Shrines you control.$Whenever another Shrine you control enters, each opponent loses 1 life and you gain 1 life.| +Obsessive Pursuit|Avatar: The Last Airbender|112|R|{1}{B}|Enchantment|||When this enchantment enters and at the beginning of your upkeep, you lose 1 life and create a Clue token.$Whenever you attack, put X +1/+1 counters on target attacking creature, where X is the number of permanents you've sacrificed this turn. If X is three or greater, that creature gains lifelink until end of turn.| Ozai's Cruelty|Avatar: The Last Airbender|113|U|{2}{B}|Sorcery - Lesson|||Ozai's Cruelty deals 2 damage to target player. That player discards two cards.| Raven Eagle|Avatar: The Last Airbender|116|R|{2}{B}|Creature - Bird Assassin|2|3|Flying$Whenever this creature enters or attacks, exile up to one target card from a graveyard. If a creature card is exiled this way, create a Clue token.$Whenever you draw your second card each turn, each opponent loses 1 life and you gain 1 life.| The Rise of Sozin|Avatar: The Last Airbender|117|M|{4}{B}{B}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I -- Destroy all creatures.$II -- Choose a card name. Search target opponent's graveyard, hand, and library for up to four cards with that name and exile them. Then that player shuffles.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| Fire Lord Sozin|Avatar: The Last Airbender|117|M||Legendary Creature - Human Noble|5|5|Menace, firebending 3$Whenever Fire Lord Sozin deals combat damage to a player, you may pay {X}. When you do, put any number of target creature cards with total mana value X or less from that player's graveyard onto the battlefield under your control.| Sold Out|Avatar: The Last Airbender|119|C|{3}{B}|Instant|||Exile target creature. If it was dealt damage this turn, create a Clue token.| +Swampsnare Trap|Avatar: The Last Airbender|120|C|{2}{B}|Enchantment - Aura|||This spell costs {1} less to cast if it targets a creature with flying.$Enchant creature$Enchanted creature gets -5/-3.| Tundra Tank|Avatar: The Last Airbender|121|U|{2}{B}|Artifact - Vehicle|4|4|Firebending 1$When this Vehicle enters, target creature you control gains indestructible until end of turn.$Crew 1| Wolfbat|Avatar: The Last Airbender|122|U|{2}{B}|Creature - Wolf Bat|2|2|Flying$Whenever you draw your second card each turn, you may pay {B}. If you do, return this card from your graveyard to the battlefield with a finality counter on it.| Bumi Bash|Avatar: The Last Airbender|125|C|{3}{R}|Sorcery|||Choose one --$* Bumi Bash deals damage equal to the number of lands you control to target creature.$* Destroy target land creature or nonbasic land.| @@ -59912,6 +59921,7 @@ Earthbender Ascension|Avatar: The Last Airbender|175|R|{2}{G}|Enchantment|||When Earthbending Lesson|Avatar: The Last Airbender|176|C|{3}{G}|Sorcery - Lesson|||Earthbend 4.| Elemental Teachings|Avatar: The Last Airbender|178|R|{4}{G}|Instant - Lesson|||Search your library for up to four land cards with different names and reveal them. An opponent chooses two of those cards. Put the chosen cards into your graveyard and the rest onto the battlefield tapped, then shuffle.| Flopsie, Bumi's Buddy|Avatar: The Last Airbender|179|U|{4}{G}{G}|Legendary Creature - Ape Goat|4|4|When Flopsie enters, put a +1/+1 counter on each creature you control.$Each creature you control with power 4 or greater can't be blocked by more than one creature.| +Great Divide Guide|Avatar: The Last Airbender|181|R|{1}{G}|Creature - Human Scout Ally|2|3|Each land and Ally you control has 66 : Add one mana of any color."| Haru, Hidden Talent|Avatar: The Last Airbender|182|U|{1}{G}|Legendary Creature - Human Peasant Ally|1|1|Whenever another Ally you control enters, earthbend 1.| Invasion Tactics|Avatar: The Last Airbender|183|U|{4}{G}|Enchantment|||When this enchantment enters, creatures you control get +2/+2 until end of turn.$Whenever one or more Allies you control deal combat damage to a player, draw a card.| Kyoshi Island Plaza|Avatar: The Last Airbender|184|U|{3}{G}|Legendary Enchantment - Shrine|||When Kyoshi Island Plaza enters, search your library for up to X basic land cards, where X is the number of Shrines you control. Put those cards onto the battlefield tapped, then shuffle.$Whenever another Shrine you control enters, search your library for a basic land card, put it onto the battlefield tapped, then shuffle.| @@ -59921,6 +59931,7 @@ Ostrich-Horse|Avatar: The Last Airbender|188|C|{2}{G}|Creature - Bird Horse|3|1| Pillar Launch|Avatar: The Last Airbender|189|C|{G}|Instant|||Target creature gets +2/+2 and gains reach until end of turn. Untap it.| Raucous Audience|Avatar: The Last Airbender|190|C|{1}{G}|Creature - Human Citizen|2|1|{T}: Add {G}. If you control a creature with power 4 or greater, add {G}{G} instead.| Rebellious Captives|Avatar: The Last Airbender|191|C|{1}{G}|Creature - Human Peasant Ally|2|2|Exhaust -- {6}: Put two +1/+1 counters on this creature, then earthbend 2.| +Rockalanche|Avatar: The Last Airbender|192|U|{2}{G}|Sorcery - Lesson|||Earthbend X, where X is the number of Forests you control.$Flashback {5}{G}| Rocky Rebuke|Avatar: The Last Airbender|193|C|{1}{G}|Instant|||Target creature you control deals damage equal to its power to target creature an opponent controls.| Saber-Tooth Moose-Lion|Avatar: The Last Airbender|194|C|{4}{G}{G}|Creature - Elk Cat|7|7|Reach$Forestcycling {2}| Seismic Sense|Avatar: The Last Airbender|195|U|{G}|Sorcery - Lesson|||Look at the top X cards of your library, where X is the number of lands you control. You may reveal a creature or land card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| @@ -59930,6 +59941,7 @@ Toph, the Blind Bandit|Avatar: The Last Airbender|198|U|{2}{G}|Legendary Creatur True Ancestry|Avatar: The Last Airbender|199|U|{1}{G}|Sorcery - Lesson|||Return up to one target permanent card from your graveyard to your hand.$Create a Clue token.| Turtle-Duck|Avatar: The Last Airbender|200|C|{G}|Creature - Turtle Bird|0|4|{3}: Until end of turn, this creature has base power 4 and gains trample.| Unlucky Cabbage Merchant|Avatar: The Last Airbender|201|U|{1}{G}|Creature - Human Citizen|2|2|When this creature enters, create a Food token.$Whenever you sacrifice a Food, you may search your library for a basic land card and put it onto the battlefield tapped. If you search your library this way, put this creature on the bottom of its owner's library, then shuffle.| +Walltop Sentries|Avatar: The Last Airbender|202|C|{2}{G}|Creature - Human Soldier Ally|2|3|Reach, deathtouch$When this creature dies, if there's a Lesson card in your graveyard, you gain 2 life.| Aang, at the Crossroads|Avatar: The Last Airbender|203|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| Aang, Destined Savior|Avatar: The Last Airbender|203|R||Legendary Creature - Avatar Ally|4|4|Flying$Land creatures you control have vigilance.$At the beginning of combat on your turn, earthbend 2.| Aang, Swift Savior|Avatar: The Last Airbender|204|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| @@ -59962,9 +59974,11 @@ Katara, the Fearless|Avatar: The Last Airbender|230|R|{G}{W}{U}|Legendary Creatu Katara, Water Tribe's Hope|Avatar: The Last Airbender|231|R|{2}{W}{U}{U}|Legendary Creature - Human Warrior Ally|3|3|Vigilance$When Katara enters, create a 1/1 white Ally creature token.$Waterbend {X}: Creatures you control have base power and toughness X/X until end of turn. X can't be 0. Activate only during your turn.| The Lion-Turtle|Avatar: The Last Airbender|232|R|{1}{G}{U}|Legendary Creature - Elder Cat Turtle|3|6|Vigilance, reach$When The Lion-Turtle enters, you gain 3 life.$The Lion-Turtle can't attack or block unless there are three or more Lesson cards in your graveyard.${T}: Add one mana of any color.| Long Feng, Grand Secretariat|Avatar: The Last Airbender|233|U|{1}{B/G}{B/G}|Legendary Creature - Human Advisor|2|3|Whenever another creature you control or a land you control is put into a graveyard from the battlefield, put a +1/+1 counter on target creature you control.| +Messenger Hawk|Avatar: The Last Airbender|234|C|{2}{U/B}|Creature - Bird Scout|1|2|Flying$When this creature enters, create a Clue token.$This creature gets +2/+0 as long as you've drawn two or more cards this turn.| Ozai, the Phoenix King|Avatar: The Last Airbender|235|M|{2}{B}{B}{R}{R}|Legendary Creature - Human Noble|7|7|Trample, firebending 4, haste$If you would lose unspent mana, that mana becomes red instead.$Ozai has flying and indestructible as long as you have six or more unspent mana.| Platypus-Bear|Avatar: The Last Airbender|236|C|{1}{G/U}|Creature - Platypus Bear|2|3|Defender$When this creature enters, mill two cards.$As long as there is a Lesson card in your graveyard, this creature can attack as though it didn't have defender.| Pretending Poxbearers|Avatar: The Last Airbender|237|C|{1}{W/B}|Creature - Human Citizen Ally|2|1|When this creature dies, create a 1/1 white Ally creature token.| +Professor Zei, Anthropologist|Avatar: The Last Airbender|238|U|{U/R}{U/R}|Legendary Creature - Human Advisor Ally|0|3|{T}, Discard a card: Draw a card.${1}, {T}, Sacrifice Professor Zei: Return target instant or sorcery card from your graveyard to your hand. Activate only during your turn.| Sokka, Bold Boomeranger|Avatar: The Last Airbender|240|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.| Sokka, Lateral Strategist|Avatar: The Last Airbender|241|U|{1}{W/U}{W/U}|Legendary Creature - Human Warrior Ally|2|4|Vigilance$Whenever Sokka and at least one other creature attack, draw a card.| Sokka, Tenacious Tactician|Avatar: The Last Airbender|242|R|{1}{U}{R}{W}|Legendary Creature - Human Warrior Ally|3|3|Menace, prowess$Other Allies you control have menace and prowess.$Whenever you cast a noncreature spell, create a 1/1 white Ally creature token.| @@ -59983,6 +59997,7 @@ Fire Nation Warship|Avatar: The Last Airbender|256|U|{3}|Artifact - Vehicle|4|4| Planetarium of Wan Shi Tong|Avatar: The Last Airbender|259|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| Trusty Boomerang|Avatar: The Last Airbender|260|U|{1}|Artifact - Equipment|||Equipped creature has "{1}, {T}: Tap target creature. Return Trusty Boomerang to its owner's hand."$Equip {1}| White Lotus Tile|Avatar: The Last Airbender|262|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| +Agna Qel'a|Avatar: The Last Airbender|264|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {U}.${2}{U}, {T}: Draw a card, then discard a card.| Airship Engine Room|Avatar: The Last Airbender|265|C||Land|||This land enters tapped.${T}: Add {U} or {R}.${4}, {T}, Sacrifice this land: Draw a card.| Boiling Rock Prison|Avatar: The Last Airbender|267|C||Land|||This land enters tapped.${T}: Add {B} or {R}.${4}, {T}, Sacrifice this land: Draw a card.| Fire Nation Palace|Avatar: The Last Airbender|268|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {R}.${1}{R}, {T}: Target creature you control gains firebending 4 until end of turn.| @@ -60016,6 +60031,7 @@ Fated Firepower|Avatar: The Last Airbender|297|M|{X}{R}{R}{R}|Enchantment|||Flas Aang, Swift Savior|Avatar: The Last Airbender|298|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| Aang and La, Ocean's Fury|Avatar: The Last Airbender|298|R||Legendary Creature - Avatar Spirit Ally|5|5|Reach, trample$Whenever Aang and La attack, put a +1/+1 counter on each tapped creature you control.| Fire Nation Attacks|Avatar: The Last Airbender|299|U|{4}{R}|Instant|||Create two 2/2 red Soldier creature tokens with firebending 1.$Flashback {8}{R}| +Crashing Wave|Avatar: The Last Airbender|300|U|{U}{U}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Tap up to X target creatures, then distribute three stun counters among tapped creatures your opponents control.| Combustion Technique|Avatar: The Last Airbender|301|U|{1}{R}|Instant - Lesson|||Combustion Technique deals damage equal to 2 plus the number of Lesson cards in your graveyard to target creature. If that creature would die this turn, exile it instead.| Azula, Cunning Usurper|Avatar: The Last Airbender|303|R|{2}{U}{B}{B}|Legendary Creature - Human Noble Rogue|4|4|Firebending 2$When Azula enters, target opponent exiles a nontoken creature they control, then they exile a nonland card from their graveyard.$During your turn, you may cast cards exiled with Azula and you may cast them as though they had flash. Mana of any type can be spent to cast those spells.| Aang, at the Crossroads|Avatar: The Last Airbender|304|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| @@ -60026,6 +60042,7 @@ Earthbender Ascension|Avatar: The Last Airbender|307|R|{2}{G}|Enchantment|||When Avatar Aang|Avatar: The Last Airbender|308|M|{R}{G}{W}{U}|Legendary Creature - Human Avatar Ally|4|4|Flying, firebending 2$Whenever you waterbend, earthbend, firebend, or airbend, draw a card. Then if you've done all four this turn, transform Avatar Aang.| Aang, Master of Elements|Avatar: The Last Airbender|308|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Sozin's Comet|Avatar: The Last Airbender|309|M|{3}{R}{R}|Sorcery|||Each creature you control gains firebending 5 until end of turn.$Foretell {2}{R}| +Waterbender Ascension|Avatar: The Last Airbender|310|R|{1}{U}|Enchantment|||Whenever a creature you control deals combat damage to a player, put a quest counter on this enchantment. Then if it has four or more quest counters on it, draw a card.$Waterbend {4}: Target creature can't be blocked this turn.| Ozai, the Phoenix King|Avatar: The Last Airbender|311|M|{2}{B}{B}{R}{R}|Legendary Creature - Human Noble|7|7|Trample, firebending 4, haste$If you would lose unspent mana, that mana becomes red instead.$Ozai has flying and indestructible as long as you have six or more unspent mana.| Firebender Ascension|Avatar: The Last Airbender|312|R|{1}{R}|Enchantment|||When this enchantment enters, create a 2/2 red Soldier creature token with firebending 1.$Whenever a creature you control attacking causes a triggered ability of that creature to trigger, put a quest counter on this enchantment. Then if it has four or more quest counters on it, you may copy that ability. You may choose new targets for the copy.| Fire Lord Azula|Avatar: The Last Airbender|313|R|{1}{U}{B}{R}|Legendary Creature - Human Noble|4|4|Firebending 2$Whenever you cast a spell while Fire Lord Azula is attacking, copy that spell. You may choose new targets for the copy.| @@ -60052,10 +60069,12 @@ Aang's Iceberg|Avatar: The Last Airbender|336|R|{2}{W}|Enchantment|||Flash$When Secret of Bloodbending|Avatar: The Last Airbender|337|M|{U}{U}{U}{U}|Sorcery - Lesson|||As an additional cost to cast this spell, you may waterbend {10}.$You control target opponent during their next combat phase. If this spell's additional cost was paid, you control that player during their next turn instead.$Exile Secret of Bloodbending.| Yue, the Moon Spirit|Avatar: The Last Airbender|338|R|{3}{U}|Legendary Creature - Spirit Ally|3|3|Flying, vigilance$Waterbend {5}, {T}: You may cast a noncreature spell from your hand without paying its mana cost.| Foggy Swamp Visions|Avatar: The Last Airbender|339|R|{1}{B}{B}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Exile X target creature cards from graveyards. For each creature card exiled this way, create a token that's a copy of it. At the beginning of your next end step, sacrifice those tokens.| +Obsessive Pursuit|Avatar: The Last Airbender|340|R|{1}{B}|Enchantment|||When this enchantment enters and at the beginning of your upkeep, you lose 1 life and create a Clue token.$Whenever you attack, put X +1/+1 counters on target attacking creature, where X is the number of permanents you've sacrificed this turn. If X is three or greater, that creature gains lifelink until end of turn.| Fated Firepower|Avatar: The Last Airbender|341|M|{X}{R}{R}{R}|Enchantment|||Flash$This enchantment enters with X fire counters on it.$If a source you control would deal damage to an opponent or a permanent an opponent controls, it deals that much damage plus an amount of damage equal to the number of fire counters on this enchantment instead.| Firebending Student|Avatar: The Last Airbender|342|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| Redirect Lightning|Avatar: The Last Airbender|343|R|{R}|Instant - Lesson|||As an additional cost to cast this spell, pay 5 life or pay {2}.$Change the target of target spell or ability with a single target.| The Earth King|Avatar: The Last Airbender|344|R|{3}{G}|Legendary Creature - Human Noble Ally|2|2|When The Earth King enters, create a 4/4 green Bear creature token.$Whenever one or more creatures you control with power 4 or greater attack, search your library for up to that many basic land cards, put them onto the battlefield tapped, then shuffle.| +Great Divide Guide|Avatar: The Last Airbender|345|R|{1}{G}|Creature - Human Scout Ally|2|3|Each land and Ally you control has 66 : Add one mana of any color."| Aang, at the Crossroads|Avatar: The Last Airbender|346|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| Aang, Destined Savior|Avatar: The Last Airbender|346|R||Legendary Creature - Avatar Ally|4|4|Flying$Land creatures you control have vigilance.$At the beginning of combat on your turn, earthbend 2.| Aang, Swift Savior|Avatar: The Last Airbender|347|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| @@ -60097,6 +60116,7 @@ Earth King's Lieutenant|Avatar: The Last Airbender|380|R|{G}{W}|Creature - Human Iroh, Tea Master|Avatar: The Last Airbender|381|R|{1}{R}{W}|Legendary Creature - Human Citizen Ally|2|2|When Iroh enters, create a Food token.$At the beginning of combat on your turn, you may have target opponent gain control of target permanent you control. When you do, create a 1/1 white Ally creature token. Put a +1/+1 counter on that token for each permanent you own that your opponents control.| Sokka, Bold Boomeranger|Avatar: The Last Airbender|383|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.| Planetarium of Wan Shi Tong|Avatar: The Last Airbender|385|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| +Agna Qel'a|Avatar: The Last Airbender|387|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {U}.${2}{U}, {T}: Draw a card, then discard a card.| Fire Nation Palace|Avatar: The Last Airbender|389|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {R}.${1}{R}, {T}: Target creature you control gains firebending 4 until end of turn.| Jasmine Dragon Tea Shop|Avatar: The Last Airbender|390|R||Land|||{T}: Add {C}.${T}: Add one mana of any color. Spend this mana only to cast an Ally spell or activate an ability of an Ally source.${5}, {T}: Create a 1/1 white Ally creature token.| Secret Tunnel|Avatar: The Last Airbender|392|R||Land - Cave|||This land can't be blocked.${T}: Add {C}.${4}, {T}: Two target creatures you control that share a creature type can't be blocked this turn.| -- 2.47.2 From 35eeb2cb2de3a46b7f3f816b056f59c426c06c51 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:10:10 -0500 Subject: [PATCH 106/261] [TLA] Implement Swampsnare Trap --- .../src/mage/cards/s/SwampsnareTrap.java | 57 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 58 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SwampsnareTrap.java diff --git a/Mage.Sets/src/mage/cards/s/SwampsnareTrap.java b/Mage.Sets/src/mage/cards/s/SwampsnareTrap.java new file mode 100644 index 00000000000..7b89640e7a9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SwampsnareTrap.java @@ -0,0 +1,57 @@ +package mage.cards.s; + +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceTargetsPermanentCondition; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SwampsnareTrap extends CardImpl { + + private static final Condition condition = new SourceTargetsPermanentCondition(StaticFilters.FILTER_CREATURE_FLYING); + + public SwampsnareTrap(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); + + this.subtype.add(SubType.AURA); + + // This spell costs {1} less to cast if it targets a creature with flying. + this.addAbility(new SimpleStaticAbility( + Zone.ALL, new SpellCostReductionSourceEffect(1, condition).setCanWorksOnStackOnly(true) + ).setRuleAtTheTop(true)); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + this.addAbility(new EnchantAbility(auraTarget)); + + // Enchanted creature gets -5/-3. + this.addAbility(new SimpleStaticAbility(new BoostEnchantedEffect(-5, -3))); + } + + private SwampsnareTrap(final SwampsnareTrap card) { + super(card); + } + + @Override + public SwampsnareTrap copy() { + return new SwampsnareTrap(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 14d8bf3a0e2..46d6f4d2d8e 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -224,6 +224,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Swamp", 284, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Swamp", 289, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swamp", 294, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Swampsnare Trap", 120, Rarity.COMMON, mage.cards.s.SwampsnareTrap.class)); cards.add(new SetCardInfo("The Boulder, Ready to Rumble", 168, Rarity.UNCOMMON, mage.cards.t.TheBoulderReadyToRumble.class)); cards.add(new SetCardInfo("The Cave of Two Lovers", 126, Rarity.UNCOMMON, mage.cards.t.TheCaveOfTwoLovers.class)); cards.add(new SetCardInfo("The Lion-Turtle", 232, Rarity.RARE, mage.cards.t.TheLionTurtle.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From d8b32308e80aca3d04d8ac85fd42709ba252fc61 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:11:20 -0500 Subject: [PATCH 107/261] [TLA] Implement Kyoshi Warriors --- .../src/mage/cards/k/KyoshiWarriors.java | 40 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 41 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/k/KyoshiWarriors.java diff --git a/Mage.Sets/src/mage/cards/k/KyoshiWarriors.java b/Mage.Sets/src/mage/cards/k/KyoshiWarriors.java new file mode 100644 index 00000000000..979844a52c5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KyoshiWarriors.java @@ -0,0 +1,40 @@ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.AllyToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KyoshiWarriors extends CardImpl { + + public KyoshiWarriors(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When this creature enters, create a 1/1 white Ally creature token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new AllyToken()))); + } + + private KyoshiWarriors(final KyoshiWarriors card) { + super(card); + } + + @Override + public KyoshiWarriors copy() { + return new KyoshiWarriors(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 46d6f4d2d8e..f8bd1b5fea2 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -150,6 +150,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Katara, the Fearless", 350, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, the Fearless", 361, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Kyoshi Village", 271, Rarity.COMMON, mage.cards.k.KyoshiVillage.class)); + cards.add(new SetCardInfo("Kyoshi Warriors", 26, Rarity.COMMON, mage.cards.k.KyoshiWarriors.class)); cards.add(new SetCardInfo("Leaves from the Vine", 185, Rarity.UNCOMMON, mage.cards.l.LeavesFromTheVine.class)); cards.add(new SetCardInfo("Lightning Strike", 146, Rarity.COMMON, mage.cards.l.LightningStrike.class)); cards.add(new SetCardInfo("Long Feng, Grand Secretariat", 233, Rarity.UNCOMMON, mage.cards.l.LongFengGrandSecretariat.class)); -- 2.47.2 From c9e4b33e4cf250ab707129b48c9cd233968b064a Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:12:00 -0500 Subject: [PATCH 108/261] [TLA] Implement Invasion Reinforcements --- .../mage/cards/i/InvasionReinforcements.java | 44 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 45 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/InvasionReinforcements.java diff --git a/Mage.Sets/src/mage/cards/i/InvasionReinforcements.java b/Mage.Sets/src/mage/cards/i/InvasionReinforcements.java new file mode 100644 index 00000000000..905223017d8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InvasionReinforcements.java @@ -0,0 +1,44 @@ +package mage.cards.i; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.AllyToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class InvasionReinforcements extends CardImpl { + + public InvasionReinforcements(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WARRIOR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // When this creature enters, create a 1/1 white Ally creature token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new AllyToken()))); + } + + private InvasionReinforcements(final InvasionReinforcements card) { + super(card); + } + + @Override + public InvasionReinforcements copy() { + return new InvasionReinforcements(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index f8bd1b5fea2..8c981277be1 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -133,6 +133,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Hog-Monkey", 104, Rarity.COMMON, mage.cards.h.HogMonkey.class)); cards.add(new SetCardInfo("How to Start a Riot", 140, Rarity.COMMON, mage.cards.h.HowToStartARiot.class)); cards.add(new SetCardInfo("Iguana Parrot", 56, Rarity.COMMON, mage.cards.i.IguanaParrot.class)); + cards.add(new SetCardInfo("Invasion Reinforcements", 24, Rarity.UNCOMMON, mage.cards.i.InvasionReinforcements.class)); cards.add(new SetCardInfo("Invasion Submersible", 57, Rarity.UNCOMMON, mage.cards.i.InvasionSubmersible.class)); cards.add(new SetCardInfo("Invasion Tactics", 183, Rarity.UNCOMMON, mage.cards.i.InvasionTactics.class)); cards.add(new SetCardInfo("Iroh's Demonstration", 141, Rarity.UNCOMMON, mage.cards.i.IrohsDemonstration.class)); -- 2.47.2 From 835d4ae465856d65b9e20567a894826eecd4fd7d Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:14:18 -0500 Subject: [PATCH 109/261] [TLA] Implement Great Divide Guide --- .../src/mage/cards/g/GreatDivideGuide.java | 54 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 56 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/g/GreatDivideGuide.java diff --git a/Mage.Sets/src/mage/cards/g/GreatDivideGuide.java b/Mage.Sets/src/mage/cards/g/GreatDivideGuide.java new file mode 100644 index 00000000000..ea4dda96d9a --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GreatDivideGuide.java @@ -0,0 +1,54 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.mana.AnyColorManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GreatDivideGuide extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("each land and Ally"); + + static { + filter.add(Predicates.or( + CardType.LAND.getPredicate(), + SubType.ALLY.getPredicate() + )); + } + + public GreatDivideGuide(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SCOUT); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Each land and Ally you control has "{T} : Add one mana of any color." + this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( + new AnyColorManaAbility(), Duration.WhileOnBattlefield, filter + ))); + } + + private GreatDivideGuide(final GreatDivideGuide card) { + super(card); + } + + @Override + public GreatDivideGuide copy() { + return new GreatDivideGuide(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 8c981277be1..1d3291b7e59 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -125,6 +125,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Glider Kids", 21, Rarity.COMMON, mage.cards.g.GliderKids.class)); cards.add(new SetCardInfo("Glider Staff", 22, Rarity.UNCOMMON, mage.cards.g.GliderStaff.class)); cards.add(new SetCardInfo("Gran-Gran", 54, Rarity.UNCOMMON, mage.cards.g.GranGran.class)); + cards.add(new SetCardInfo("Great Divide Guide", 181, Rarity.RARE, mage.cards.g.GreatDivideGuide.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Great Divide Guide", 345, Rarity.RARE, mage.cards.g.GreatDivideGuide.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Guru Pathik", 223, Rarity.UNCOMMON, mage.cards.g.GuruPathik.class)); cards.add(new SetCardInfo("Hakoda, Selfless Commander", 366, Rarity.RARE, mage.cards.h.HakodaSelflessCommander.class)); cards.add(new SetCardInfo("Haru, Hidden Talent", 182, Rarity.UNCOMMON, mage.cards.h.HaruHiddenTalent.class)); -- 2.47.2 From 6e0dc4f5f659eeb3d45d389585314112a36b392b Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:17:45 -0500 Subject: [PATCH 110/261] [TLA] Implement Professor Zei, Anthropologist --- .../cards/p/ProfessorZeiAnthropologist.java | 62 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 63 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/ProfessorZeiAnthropologist.java diff --git a/Mage.Sets/src/mage/cards/p/ProfessorZeiAnthropologist.java b/Mage.Sets/src/mage/cards/p/ProfessorZeiAnthropologist.java new file mode 100644 index 00000000000..c4afed6a3db --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/ProfessorZeiAnthropologist.java @@ -0,0 +1,62 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +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.target.common.TargetCardInYourGraveyard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ProfessorZeiAnthropologist extends CardImpl { + + public ProfessorZeiAnthropologist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U/R}{U/R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ADVISOR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(0); + this.toughness = new MageInt(3); + + // {T}, Discard a card: Draw a card. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new TapSourceCost()); + ability.addCost(new DiscardCardCost()); + this.addAbility(ability); + + // {1}, {T}, Sacrifice Professor Zei: Return target instant or sorcery card from your graveyard to your hand. Activate only during your turn. + ability = new ActivateIfConditionActivatedAbility( + new ReturnFromGraveyardToHandTargetEffect(), new GenericManaCost(1), MyTurnCondition.instance + ); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD)); + this.addAbility(ability); + } + + private ProfessorZeiAnthropologist(final ProfessorZeiAnthropologist card) { + super(card); + } + + @Override + public ProfessorZeiAnthropologist copy() { + return new ProfessorZeiAnthropologist(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 1d3291b7e59..4beb650cf09 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -191,6 +191,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Planetarium of Wan Shi Tong", 385, Rarity.MYTHIC, mage.cards.p.PlanetariumOfWanShiTong.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Platypus-Bear", 236, Rarity.COMMON, mage.cards.p.PlatypusBear.class)); cards.add(new SetCardInfo("Pretending Poxbearers", 237, Rarity.COMMON, mage.cards.p.PretendingPoxbearers.class)); + cards.add(new SetCardInfo("Professor Zei, Anthropologist", 238, Rarity.UNCOMMON, mage.cards.p.ProfessorZeiAnthropologist.class)); cards.add(new SetCardInfo("Rabaroo Troop", 32, Rarity.COMMON, mage.cards.r.RabarooTroop.class)); cards.add(new SetCardInfo("Ran and Shaw", 150, Rarity.RARE, mage.cards.r.RanAndShaw.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ran and Shaw", 325, Rarity.RARE, mage.cards.r.RanAndShaw.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 9c630578f10deb0492425aad2b039f9f1e242911 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:19:24 -0500 Subject: [PATCH 111/261] [TLA] Implement Rockalanche --- Mage.Sets/src/mage/cards/r/Rockalanche.java | 51 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 52 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/r/Rockalanche.java diff --git a/Mage.Sets/src/mage/cards/r/Rockalanche.java b/Mage.Sets/src/mage/cards/r/Rockalanche.java new file mode 100644 index 00000000000..ef35c89bfce --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/Rockalanche.java @@ -0,0 +1,51 @@ +package mage.cards.r; + +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.abilities.keyword.FlashbackAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.common.FilterControlledPermanent; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Rockalanche extends CardImpl { + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( + new FilterControlledPermanent(SubType.FOREST, "Forests you control"), null + ); + private static final Hint hint = new ValueHint("Forests you control", xValue); + + public Rockalanche(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); + + this.subtype.add(SubType.LESSON); + + // Earthbend X, where X is the number of Forests you control. + this.getSpellAbility().addEffect(new EarthbendTargetEffect(xValue)); + this.getSpellAbility().addTarget(new TargetControlledLandPermanent()); + this.getSpellAbility().addHint(hint); + + // Flashback {5}{G} + this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{5}{G}"))); + } + + private Rockalanche(final Rockalanche card) { + super(card); + } + + @Override + public Rockalanche copy() { + return new Rockalanche(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 4beb650cf09..972e46c28cf 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -200,6 +200,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Rebellious Captives", 191, Rarity.COMMON, mage.cards.r.RebelliousCaptives.class)); cards.add(new SetCardInfo("Redirect Lightning", 151, Rarity.RARE, mage.cards.r.RedirectLightning.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Redirect Lightning", 343, Rarity.RARE, mage.cards.r.RedirectLightning.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Rockalanche", 192, Rarity.UNCOMMON, mage.cards.r.Rockalanche.class)); cards.add(new SetCardInfo("Rocky Rebuke", 193, Rarity.COMMON, mage.cards.r.RockyRebuke.class)); cards.add(new SetCardInfo("Rough Rhino Cavalry", 152, Rarity.COMMON, mage.cards.r.RoughRhinoCavalry.class)); cards.add(new SetCardInfo("Rowdy Snowballers", 68, Rarity.COMMON, mage.cards.r.RowdySnowballers.class)); -- 2.47.2 From e4fcca82dd581b78093218088cc1f2fca3c1bcce Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:20:15 -0500 Subject: [PATCH 112/261] [TLA] Implement Benevolent River Spirit --- .../mage/cards/b/BenevolentRiverSpirit.java | 50 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 51 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BenevolentRiverSpirit.java diff --git a/Mage.Sets/src/mage/cards/b/BenevolentRiverSpirit.java b/Mage.Sets/src/mage/cards/b/BenevolentRiverSpirit.java new file mode 100644 index 00000000000..25038e78824 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BenevolentRiverSpirit.java @@ -0,0 +1,50 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.WaterbendCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.keyword.ScryEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.WardAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BenevolentRiverSpirit extends CardImpl { + + public BenevolentRiverSpirit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{U}"); + + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(4); + this.toughness = new MageInt(5); + + // As an additional cost to cast this spell, waterbend {5}. + this.getSpellAbility().addCost(new WaterbendCost(5)); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Ward {2} + this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}"))); + + // When this creature enters, scry 2. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(2))); + } + + private BenevolentRiverSpirit(final BenevolentRiverSpirit card) { + super(card); + } + + @Override + public BenevolentRiverSpirit copy() { + return new BenevolentRiverSpirit(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 972e46c28cf..7b4167d2c92 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -52,6 +52,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Barrels of Blasting Jelly", 254, Rarity.COMMON, mage.cards.b.BarrelsOfBlastingJelly.class)); cards.add(new SetCardInfo("Beetle-Headed Merchants", 86, Rarity.COMMON, mage.cards.b.BeetleHeadedMerchants.class)); cards.add(new SetCardInfo("Bender's Waterskin", 255, Rarity.COMMON, mage.cards.b.BendersWaterskin.class)); + cards.add(new SetCardInfo("Benevolent River Spirit", 45, Rarity.UNCOMMON, mage.cards.b.BenevolentRiverSpirit.class)); cards.add(new SetCardInfo("Boiling Rock Prison", 267, Rarity.COMMON, mage.cards.b.BoilingRockPrison.class)); cards.add(new SetCardInfo("Boomerang Basics", 46, Rarity.UNCOMMON, mage.cards.b.BoomerangBasics.class)); cards.add(new SetCardInfo("Bumi Bash", 125, Rarity.COMMON, mage.cards.b.BumiBash.class)); -- 2.47.2 From a50095e784a9d47db41ab716ea95deca6b20ea5c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:22:35 -0500 Subject: [PATCH 113/261] [TLA] Implement Wolfbat --- Mage.Sets/src/mage/cards/w/Wolfbat.java | 54 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 55 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/w/Wolfbat.java diff --git a/Mage.Sets/src/mage/cards/w/Wolfbat.java b/Mage.Sets/src/mage/cards/w/Wolfbat.java new file mode 100644 index 00000000000..3afcc12e14e --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/Wolfbat.java @@ -0,0 +1,54 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.common.DrawNthCardTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldWithCounterEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Wolfbat extends CardImpl { + + public Wolfbat(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.WOLF); + this.subtype.add(SubType.BAT); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever you draw your second card each turn, you may pay {B}. If you do, return this card from your graveyard to the battlefield with a finality counter on it. + this.addAbility(new DrawNthCardTriggeredAbility( + Zone.GRAVEYARD, + new DoIfCostPaid( + new ReturnSourceFromGraveyardToBattlefieldWithCounterEffect( + CounterType.FINALITY.createInstance(), false + ), new ManaCostsImpl<>("{B}") + ), false, TargetController.YOU, 2 + )); + } + + private Wolfbat(final Wolfbat card) { + super(card); + } + + @Override + public Wolfbat copy() { + return new Wolfbat(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 7b4167d2c92..ed36e93054f 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -267,6 +267,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("White Lotus Reinforcements", 251, Rarity.UNCOMMON, mage.cards.w.WhiteLotusReinforcements.class)); cards.add(new SetCardInfo("White Lotus Tile", 262, Rarity.MYTHIC, mage.cards.w.WhiteLotusTile.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("White Lotus Tile", 330, Rarity.MYTHIC, mage.cards.w.WhiteLotusTile.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Wolfbat", 122, Rarity.UNCOMMON, mage.cards.w.Wolfbat.class)); cards.add(new SetCardInfo("Yip Yip!", 43, Rarity.COMMON, mage.cards.y.YipYip.class)); cards.add(new SetCardInfo("Yue, the Moon Spirit", 338, Rarity.RARE, mage.cards.y.YueTheMoonSpirit.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Yue, the Moon Spirit", 83, Rarity.RARE, mage.cards.y.YueTheMoonSpirit.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 1c5634248597be77860d1689d7e05ec4a98f4a0b Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:23:51 -0500 Subject: [PATCH 114/261] [TLA] Implement Knowledge Seeker --- .../src/mage/cards/k/KnowledgeSeeker.java | 49 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 50 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/k/KnowledgeSeeker.java diff --git a/Mage.Sets/src/mage/cards/k/KnowledgeSeeker.java b/Mage.Sets/src/mage/cards/k/KnowledgeSeeker.java new file mode 100644 index 00000000000..130bd0f3a19 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KnowledgeSeeker.java @@ -0,0 +1,49 @@ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.common.DrawNthCardTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.game.permanent.token.ClueArtifactToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KnowledgeSeeker extends CardImpl { + + public KnowledgeSeeker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.FOX); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Whenever you draw your second card each turn, put a +1/+1 counter on this creature. + this.addAbility(new DrawNthCardTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()))); + + // When this creature dies, create a Clue token. + this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new ClueArtifactToken()))); + } + + private KnowledgeSeeker(final KnowledgeSeeker card) { + super(card); + } + + @Override + public KnowledgeSeeker copy() { + return new KnowledgeSeeker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index ed36e93054f..cbe66dee69b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -153,6 +153,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Katara, the Fearless", 305, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, the Fearless", 350, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, the Fearless", 361, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Knowledge Seeker", 60, Rarity.UNCOMMON, mage.cards.k.KnowledgeSeeker.class)); cards.add(new SetCardInfo("Kyoshi Village", 271, Rarity.COMMON, mage.cards.k.KyoshiVillage.class)); cards.add(new SetCardInfo("Kyoshi Warriors", 26, Rarity.COMMON, mage.cards.k.KyoshiWarriors.class)); cards.add(new SetCardInfo("Leaves from the Vine", 185, Rarity.UNCOMMON, mage.cards.l.LeavesFromTheVine.class)); -- 2.47.2 From 08130d98b11da6fa2b1b014341ed06ac78577d8c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:42:35 -0500 Subject: [PATCH 115/261] fix verify failure --- Mage.Sets/src/mage/cards/s/SoldOut.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Mage.Sets/src/mage/cards/s/SoldOut.java b/Mage.Sets/src/mage/cards/s/SoldOut.java index 1e70d5ac73b..eac68b43645 100644 --- a/Mage.Sets/src/mage/cards/s/SoldOut.java +++ b/Mage.Sets/src/mage/cards/s/SoldOut.java @@ -11,6 +11,7 @@ import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.ClueArtifactToken; +import mage.target.common.TargetCreaturePermanent; import java.util.Optional; import java.util.UUID; @@ -25,6 +26,7 @@ public final class SoldOut extends CardImpl { // Exile target creature. If it was dealt damage this turn, create a Clue token. this.getSpellAbility().addEffect(new SoldOutEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } private SoldOut(final SoldOut card) { -- 2.47.2 From 49aab3a855f82c121f845c9dc0b8a0e11b1f58b7 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:49:13 -0500 Subject: [PATCH 116/261] [TLE] update spoiler and reprints --- .../sets/AvatarTheLastAirbenderEternal.java | 12 ++++++- Utils/mtg-cards-data.txt | 33 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index e84b7810289..0291ebf154a 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -12,7 +12,7 @@ import java.util.List; */ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { - private static final List unfinished = Arrays.asList("Water Whip"); + private static final List unfinished = Arrays.asList("Waterbender's Restoration", "Water Whip"); private static final AvatarTheLastAirbenderEternal instance = new AvatarTheLastAirbenderEternal(); @@ -42,6 +42,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Avatar Roku, Firebender", 112, Rarity.MYTHIC, mage.cards.a.AvatarRokuFirebender.class)); cards.add(new SetCardInfo("Beastmaster Ascension", 39, Rarity.MYTHIC, mage.cards.b.BeastmasterAscension.class)); cards.add(new SetCardInfo("Beastmaster's Magemark", 9999, Rarity.MYTHIC, mage.cards.b.BeastmastersMagemark.class)); + cards.add(new SetCardInfo("Black Sun's Zenith", 22, Rarity.MYTHIC, mage.cards.b.BlackSunsZenith.class)); cards.add(new SetCardInfo("Blasphemous Act", 26, Rarity.MYTHIC, mage.cards.b.BlasphemousAct.class)); cards.add(new SetCardInfo("Bloodchief Ascension", 23, Rarity.MYTHIC, mage.cards.b.BloodchiefAscension.class)); cards.add(new SetCardInfo("Bribery", 10, Rarity.MYTHIC, mage.cards.b.Bribery.class)); @@ -49,6 +50,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Bumi, Eclectic Earthbender", 248, Rarity.RARE, mage.cards.b.BumiEclecticEarthbender.class)); cards.add(new SetCardInfo("Capital Guard", 234, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Capital Guard", 277, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Captain Sisay", 47, Rarity.MYTHIC, mage.cards.c.CaptainSisay.class)); cards.add(new SetCardInfo("Cityscape Leveler", 53, Rarity.MYTHIC, mage.cards.c.CityscapeLeveler.class)); cards.add(new SetCardInfo("Clone Legion", 12, Rarity.MYTHIC, mage.cards.c.CloneLegion.class)); cards.add(new SetCardInfo("Clone", 11, Rarity.MYTHIC, mage.cards.c.Clone.class)); @@ -56,9 +58,11 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Dark Depths", 56, Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); cards.add(new SetCardInfo("Deny Entry", 222, Rarity.COMMON, mage.cards.d.DenyEntry.class)); cards.add(new SetCardInfo("Descendants' Path", 167, Rarity.RARE, mage.cards.d.DescendantsPath.class)); + cards.add(new SetCardInfo("Diaochan, Artful Beauty", 27, Rarity.MYTHIC, mage.cards.d.DiaochanArtfulBeauty.class)); cards.add(new SetCardInfo("Dockside Extortionist", 28, Rarity.MYTHIC, mage.cards.d.DocksideExtortionist.class)); cards.add(new SetCardInfo("Dragon Moose", 235, Rarity.COMMON, mage.cards.d.DragonMoose.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dragon Moose", 278, Rarity.COMMON, mage.cards.d.DragonMoose.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Drannith Magistrate", 2, Rarity.MYTHIC, mage.cards.d.DrannithMagistrate.class)); cards.add(new SetCardInfo("Earthbending Student", 249, Rarity.UNCOMMON, mage.cards.e.EarthbendingStudent.class)); cards.add(new SetCardInfo("Eel-Hounds", 250, Rarity.UNCOMMON, mage.cards.e.EelHounds.class)); cards.add(new SetCardInfo("Eladamri's Call", 48, Rarity.MYTHIC, mage.cards.e.EladamrisCall.class)); @@ -67,6 +71,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Explore", 259, Rarity.COMMON, mage.cards.e.Explore.class)); cards.add(new SetCardInfo("Explosive Shot", 236, Rarity.COMMON, mage.cards.e.ExplosiveShot.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Explosive Shot", 279, Rarity.COMMON, mage.cards.e.ExplosiveShot.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fabled Passage", 57, Rarity.MYTHIC, mage.cards.f.FabledPassage.class)); cards.add(new SetCardInfo("Feed the Swarm", 257, Rarity.COMMON, mage.cards.f.FeedTheSwarm.class)); cards.add(new SetCardInfo("Fiery Confluence", 165, Rarity.RARE, mage.cards.f.FieryConfluence.class)); cards.add(new SetCardInfo("Fire Nation Ambushers", 229, Rarity.COMMON, mage.cards.f.FireNationAmbushers.class)); @@ -84,6 +89,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Heroic Intervention", 43, Rarity.MYTHIC, mage.cards.h.HeroicIntervention.class)); cards.add(new SetCardInfo("Hippo-Cows", 252, Rarity.COMMON, mage.cards.h.HippoCows.class)); cards.add(new SetCardInfo("Imprisoned in the Moon", 14, Rarity.MYTHIC, mage.cards.i.ImprisonedInTheMoon.class)); + cards.add(new SetCardInfo("Insurrection", 31, Rarity.MYTHIC, mage.cards.i.Insurrection.class)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 240, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 282, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); @@ -131,6 +137,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Roku's Mastery", 243, Rarity.UNCOMMON, mage.cards.r.RokusMastery.class)); cards.add(new SetCardInfo("Run Amok", 258, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Run Amok", 284, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sakashima of a Thousand Faces", 18, Rarity.MYTHIC, mage.cards.s.SakashimaOfAThousandFaces.class)); cards.add(new SetCardInfo("Scout's Warning", 6, Rarity.MYTHIC, mage.cards.s.ScoutsWarning.class)); cards.add(new SetCardInfo("Searing Blood", 35, Rarity.MYTHIC, mage.cards.s.SearingBlood.class)); cards.add(new SetCardInfo("Seismic Tutelage", 254, Rarity.RARE, mage.cards.s.SeismicTutelage.class)); @@ -143,10 +150,12 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Standstill", 19, Rarity.MYTHIC, mage.cards.s.Standstill.class)); cards.add(new SetCardInfo("Sundial of the Infinite", 55, Rarity.MYTHIC, mage.cards.s.SundialOfTheInfinite.class)); cards.add(new SetCardInfo("Swiftfoot Boots", 317, Rarity.RARE, mage.cards.s.SwiftfootBoots.class)); + cards.add(new SetCardInfo("Taunting Challenge", 46, Rarity.MYTHIC, mage.cards.t.TauntingChallenge.class)); cards.add(new SetCardInfo("Teferi's Protection", 7, Rarity.MYTHIC, mage.cards.t.TeferisProtection.class)); cards.add(new SetCardInfo("The Cabbage Merchant", 134, Rarity.RARE, mage.cards.t.TheCabbageMerchant.class)); cards.add(new SetCardInfo("The Great Henge", 41, Rarity.MYTHIC, mage.cards.t.TheGreatHenge.class)); cards.add(new SetCardInfo("The Terror of Serpent's Pass", 225, Rarity.RARE, mage.cards.t.TheTerrorOfSerpentsPass.class)); + cards.add(new SetCardInfo("Three Dreams", 8, Rarity.MYTHIC, mage.cards.t.ThreeDreams.class)); cards.add(new SetCardInfo("Thriving Bluff", 260, Rarity.COMMON, mage.cards.t.ThrivingBluff.class)); cards.add(new SetCardInfo("Thriving Grove", 261, Rarity.COMMON, mage.cards.t.ThrivingGrove.class)); cards.add(new SetCardInfo("Thriving Heath", 262, Rarity.COMMON, mage.cards.t.ThrivingHeath.class)); @@ -158,6 +167,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Tundra Wall", 275, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Turtle-Seals", 226, Rarity.COMMON, mage.cards.t.TurtleSeals.class)); cards.add(new SetCardInfo("Valakut, the Molten Pinnacle", 61, Rarity.MYTHIC, mage.cards.v.ValakutTheMoltenPinnacle.class)); + cards.add(new SetCardInfo("Visions of Beyond", 21, Rarity.MYTHIC, mage.cards.v.VisionsOfBeyond.class)); cards.add(new SetCardInfo("Warship Scout", 244, Rarity.COMMON, mage.cards.w.WarshipScout.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Warship Scout", 285, Rarity.COMMON, mage.cards.w.WarshipScout.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Water Whip", 227, Rarity.RARE, mage.cards.w.WaterWhip.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 566debe0a9b..759344d986f 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -60423,10 +60423,12 @@ Spider-Sense|Marvel's Spider-Man|284|R|{1}{U}|Instant|||Web-slinging {U}$Counter Radioactive Spider|Marvel's Spider-Man|285|R|{G}|Creature - Spider|1|1|Reach, deathtouch$Fateful Bite -- {2}, Sacrifice this creature: Search your library for a Spider Hero card, reveal it, put it into your hand, then shuffle. Activate only as a sorcery.| Gwenom, Remorseless|Marvel's Spider-Man|286|M|{3}{B}{B}|Legendary Creature - Symbiote Spider Hero|4|4|Deathtouch, lifelink$Whenever Gwenom attacks, until end of turn you may look at the top card of your library any time and you may play cards from the top of your library. If you cast a spell this way, pay life equal to its mana value rather than pay its mana cost.| Brought Back|Avatar: The Last Airbender Eternal|1|M|{W}{W}|Instant|||Choose up to two target permanent cards in your graveyard that were put there from the battlefield this turn. Return them to the battlefield tapped.| +Drannith Magistrate|Avatar: The Last Airbender Eternal|2|M|{1}{W}|Creature - Human Wizard|1|3|Your opponents can't cast spells from anywhere other than their hands.| Empty City Ruse|Avatar: The Last Airbender Eternal|3|M|{W}|Sorcery|||Target opponent skips all combat phases of their next turn.| Release to Memory|Avatar: The Last Airbender Eternal|5|M|{3}{W}|Instant|||Exile target opponent's graveyard. For each creature card exiled this way, create a 1/1 colorless Spirit creature token.| Scout's Warning|Avatar: The Last Airbender Eternal|6|M|{W}|Instant|||The next creature card you play this turn can be played as though it had flash.$Draw a card.| Teferi's Protection|Avatar: The Last Airbender Eternal|7|M|{2}{W}|Instant|||Until your next turn, your life total can't change and you gain protection from everything. All permanents you control phase out.$Exile Teferi's Protection.| +Three Dreams|Avatar: The Last Airbender Eternal|8|M|{4}{W}|Sorcery|||Search your library for up to three Aura cards with different names, reveal them, put them into your hand, then shuffle.| Agent of Treachery|Avatar: The Last Airbender Eternal|9|M|{5}{U}{U}|Creature - Human Rogue|2|3|When this creature enters, gain control of target permanent.$At the beginning of your end step, if you control three or more permanents you don't own, draw three cards.| Bribery|Avatar: The Last Airbender Eternal|10|M|{3}{U}{U}|Sorcery|||Search target opponent's library for a creature card and put that card onto the battlefield under your control. Then that player shuffles.| Clone|Avatar: The Last Airbender Eternal|11|M|{3}{U}|Creature - Shapeshifter|0|0|You may have this creature enter as a copy of any creature on the battlefield.| @@ -60435,13 +60437,18 @@ Force of Negation|Avatar: The Last Airbender Eternal|13|M|{1}{U}{U}|Instant|||If Imprisoned in the Moon|Avatar: The Last Airbender Eternal|14|M|{2}{U}|Enchantment - Aura|||Enchant creature, land, or planeswalker$Enchanted permanent is a colorless land with "{T}: Add {C}" and loses all other card types and abilities.| Mystic Remora|Avatar: The Last Airbender Eternal|16|M|{U}|Enchantment|||Cumulative upkeep {1}$Whenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}.| Prosperity|Avatar: The Last Airbender Eternal|17|M|{X}{U}|Sorcery|||Each player draws X cards.| +Sakashima of a Thousand Faces|Avatar: The Last Airbender Eternal|18|M|{3}{U}|Legendary Creature - Human Rogue|3|1|You may have Sakashima enter as a copy of another creature you control, except it has Sakashima's other abilities.$The "legend rule" doesn't apply to permanents you control.$Partner| Standstill|Avatar: The Last Airbender Eternal|19|M|{1}{U}|Enchantment|||When a player casts a spell, sacrifice this enchantment. If you do, each of that player's opponents draws three cards.| Training Grounds|Avatar: The Last Airbender Eternal|20|M|{U}|Enchantment|||Activated abilities of creatures you control cost {2} less to activate. This effect can't reduce the mana in that cost to less than one mana.| +Visions of Beyond|Avatar: The Last Airbender Eternal|21|M|{U}|Instant|||Draw a card. If a graveyard has twenty or more cards in it, draw three cards instead.| +Black Sun's Zenith|Avatar: The Last Airbender Eternal|22|M|{X}{B}{B}|Sorcery|||Put X -1/-1 counters on each creature. Shuffle Black Sun's Zenith into its owner's library.| Bloodchief Ascension|Avatar: The Last Airbender Eternal|23|M|{B}|Enchantment|||At the beginning of each end step, if an opponent lost 2 or more life this turn, you may put a quest counter on this enchantment.$Whenever a card is put into an opponent's graveyard from anywhere, if this enchantment has three or more quest counters on it, you may have that player lose 2 life. If you do, you gain 2 life.| Cruel Tutor|Avatar: The Last Airbender Eternal|24|M|{2}{B}|Sorcery|||Search your library for a card, then shuffle and put that card on top. You lose 2 life.| Noxious Gearhulk|Avatar: The Last Airbender Eternal|25|M|{4}{B}{B}|Artifact Creature - Construct|5|4|Menace$When this creature enters, you may destroy another target creature. If a creature is destroyed this way, you gain life equal to its toughness.| Blasphemous Act|Avatar: The Last Airbender Eternal|26|M|{8}{R}|Sorcery|||This spell costs {1} less to cast for each creature on the battlefield.$Blasphemous Act deals 13 damage to each creature.| +Diaochan, Artful Beauty|Avatar: The Last Airbender Eternal|27|M|{3}{R}|Legendary Creature - Human Advisor|1|1|{T}: Destroy target creature of your choice, then destroy target creature of an opponent's choice. Activate only during your turn, before attackers are declared.| Dockside Extortionist|Avatar: The Last Airbender Eternal|28|M|{1}{R}|Creature - Goblin Pirate|1|2|When this creature enters, create X Treasure tokens, where X is the number of artifacts and enchantments your opponents control.| +Insurrection|Avatar: The Last Airbender Eternal|31|M|{5}{R}{R}{R}|Sorcery|||Untap all creatures and gain control of them until end of turn. They gain haste until end of turn.| Mirrorwing Dragon|Avatar: The Last Airbender Eternal|33|M|{3}{R}{R}|Creature - Dragon|4|5|Flying$Whenever a player casts an instant or sorcery spell that targets only this creature, that player copies that spell for each other creature they control that the spell could target. Each copy targets a different one of those creatures.| Rending Volley|Avatar: The Last Airbender Eternal|34|M|{R}|Instant|||This spell can't be countered.$Rending Volley deals 4 damage to target white or blue creature.| Searing Blood|Avatar: The Last Airbender Eternal|35|M|{R}{R}|Instant|||Searing Blood deals 2 damage to target creature. When that creature dies this turn, Searing Blood deals 3 damage to the creature's controller.| @@ -60452,12 +60459,15 @@ Heartbeat of Spring|Avatar: The Last Airbender Eternal|42|M|{2}{G}|Enchantment|| Heroic Intervention|Avatar: The Last Airbender Eternal|43|M|{1}{G}|Instant|||Permanents you control gain hexproof and indestructible until end of turn.| Return of the Wildspeaker|Avatar: The Last Airbender Eternal|44|M|{4}{G}|Instant|||Choose one --$* Draw cards equal to the greatest power among non-Human creatures you control.$* Non-Human creatures you control get +3/+3 until end of turn.| Rites of Flourishing|Avatar: The Last Airbender Eternal|45|M|{2}{G}|Enchantment|||At the beginning of each player's draw step, that player draws an additional card.$Each player may play an additional land on each of their turns.| +Taunting Challenge|Avatar: The Last Airbender Eternal|46|M|{1}{G}{G}|Sorcery|||All creatures able to block target creature this turn do so.| +Captain Sisay|Avatar: The Last Airbender Eternal|47|M|{2}{G}{W}|Legendary Creature - Human Soldier|2|2|{T}: Search your library for a legendary card, reveal that card, put it into your hand, then shuffle.| Eladamri's Call|Avatar: The Last Airbender Eternal|48|M|{G}{W}|Instant|||Search your library for a creature card, reveal that card, put it into your hand, then shuffle.| Koma, Cosmos Serpent|Avatar: The Last Airbender Eternal|51|M|{3}{G}{G}{U}{U}|Legendary Creature - Serpent|6|6|This spell can't be countered.$At the beginning of each upkeep, create a 3/3 blue Serpent creature token named Koma's Coil.$Sacrifice another Serpent: Choose one --$* Tap target permanent. Its activated abilities can't be activated this turn.$* Koma gains indestructible until end of turn.| Rhys the Redeemed|Avatar: The Last Airbender Eternal|52|M|{G/W}|Legendary Creature - Elf Warrior|1|1|{2}{G/W}, {T}: Create a 1/1 green and white Elf Warrior creature token.${4}{G/W}{G/W}, {T}: For each creature token you control, create a token that's a copy of that creature.| Cityscape Leveler|Avatar: The Last Airbender Eternal|53|M|{8}|Artifact Creature - Construct|8|8|Trample$When you cast this spell and whenever this creature attacks, destroy up to one target nonland permanent. Its controller creates a tapped Powerstone token.$Unearth {8}| Sundial of the Infinite|Avatar: The Last Airbender Eternal|55|M|{2}|Artifact|||{1}, {T}: End the turn. Activate only during your turn.| Dark Depths|Avatar: The Last Airbender Eternal|56|M||Legendary Snow Land|||Dark Depths enters with ten ice counters on it.${3}: Remove an ice counter from Dark Depths.$When Dark Depths has no ice counters on it, sacrifice it. If you do, create Marit Lage, a legendary 20/20 black Avatar creature token with flying and indestructible.| +Fabled Passage|Avatar: The Last Airbender Eternal|57|M||Land|||{T}, Sacrifice this land: Search your library for a basic land card, put it onto the battlefield tapped, then shuffle. Then if you control four or more lands, untap that land.| Valakut, the Molten Pinnacle|Avatar: The Last Airbender Eternal|61|M||Land|||This land enters tapped.$Whenever a Mountain you control enters, if you control at least five other Mountains, you may have this land deal 3 damage to any target.${T}: Add {R}.| Appa, the Vigilant|Avatar: The Last Airbender Eternal|62|R|{5}{W}{W}|Legendary Creature - Bison Ally|6|6|Flying, vigilance$Whenever Appa or another Ally you control enters, creatures you control get +1/+1 and gain flying and vigilance until end of turn.| Katara's Reversal|Avatar: The Last Airbender Eternal|63|R|{2}{U}{U}|Instant|||Counter up to four target spells and/or abilities.$Untap up to four target artifacts and/or creatures.| @@ -60472,9 +60482,32 @@ Sokka and Suki|Avatar: The Last Airbender Eternal|71|R|{U}{R}{W}|Legendary Creat Momo's Heist|Avatar: The Last Airbender Eternal|72|R|{2}{R}|Sorcery|||Gain control of target artifact. Untap it. It gains haste. At the beginning of the next end step, sacrifice it.| Uncle's Musings|Avatar: The Last Airbender Eternal|73|R|{2}{G}{G}|Sorcery|||Converge -- Return up to X permanent cards from your graveyard to your hand, where X is the number of colors of mana spent to cast this spell.$Exile Uncle's Musings.| Aang, Airbending Master|Avatar: The Last Airbender Eternal|74|M|{4}{W}|Legendary Creature - Human Avatar Ally|4|4|When Aang enters, airbend another target creature.$Whenever one or more creatures you control leave the battlefield without dying, you get an experience counter.$At the beginning of your upkeep, create a 1/1 white Ally creature token for each experience counter you have.| +Air Nomad Student|Avatar: The Last Airbender Eternal|75|U|{3}{W}|Creature - Human Monk|2|2|Flying$At the beginning of your end step, if this creature didn't attack this turn, put a +1/+1 counter on it.| +The Duke, Rebel Sentry|Avatar: The Last Airbender Eternal|76|U|{W}|Legendary Creature - Human Rebel Ally|0|1|The Duke enters with a +1/+1 counter on him.${T}, Remove a counter from The Duke: Put a +1/+1 counter on another target creature you control. It gains hexproof until end of turn.| +Inspired Insurgent|Avatar: The Last Airbender Eternal|77|C|{1}{W}|Creature - Human Peasant Ally|2|2|| +Jet, Rebel Leader|Avatar: The Last Airbender Eternal|78|R|{3}{W}|Legendary Creature - Human Rebel Ally|3|4|Whenever Jet attacks, look at the top five cards of your library. You may put a creature card with mana value 3 or less from among them onto the battlefield tapped and attacking. Put the rest on the bottom of your library in a random order.| +Kindly Customer|Avatar: The Last Airbender Eternal|79|C|{1}{W}|Creature - Human Citizen|1|1|When this creature enters, draw a card.| +Koala-Sheep|Avatar: The Last Airbender Eternal|80|C|{2}{W}|Creature - Bear Sheep|3|2|When this creature enters, you gain 3 life.| +Monk Gyatso|Avatar: The Last Airbender Eternal|81|R|{3}{W}|Legendary Creature - Human Monk|3|3|Whenever another creature you control becomes the target of a spell or ability, you may airbend that creature.| +Pipsqueak, Rebel Strongarm|Avatar: The Last Airbender Eternal|82|U|{2}{W}|Legendary Creature - Human Rebel Ally|4|4|Pipsqueak can't attack alone unless he has a +1/+1 counter on him.| Sokka, Swordmaster|Avatar: The Last Airbender Eternal|83|M|{2}{W}|Legendary Creature - Human Warrior Ally|3|3|Vigilance$Equipment spells you cast cost {1} less to cast for each Ally you control.$At the beginning of combat on your turn, attach up to one target Equipment you control to Sokka.| +Sokka's Sword Training|Avatar: The Last Airbender Eternal|84|C|{1}{W}|Instant - Lesson|||Target creature gets +2/+2 until end of turn.$Create a Clue token.| +Suki, Kyoshi Captain|Avatar: The Last Airbender Eternal|85|R|{2}{W}|Legendary Creature - Human Warrior Ally|3|3|Other Warriors you control get +1/+1.${3}{W}: Attacking Warriors you control gain double strike until end of turn.| +Tale of Momo|Avatar: The Last Airbender Eternal|86|R|{2}{W}|Sorcery|||This spell costs {2} less to cast if a creature left the battlefield under your control this turn.$Search your library and/or graveyard for an Ally creature card, reveal it, and put it into your hand. If you search your library this way, shuffle.| +That's Rough Buddy|Avatar: The Last Airbender Eternal|87|U|{1}{W}|Instant - Lesson|||Put a +1/+1 counter on target creature. Put two +1/+1 counters on that creature instead if a creature left the battlefield under your control this turn.$Draw a card.| +Toucan-Puffin|Avatar: The Last Airbender Eternal|88|C|{2}{W}|Creature - Bird|2|2|Flying$When this creature enters, target creature you control gets +2/+0 until end of turn.| +Baboon Spirit|Avatar: The Last Airbender Eternal|89|R|{2}{U}|Creature - Monkey Spirit|2|4|Whenever another nontoken Spirit you control enters, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."${3}{U}: Exile another target creature you control. Return it to the battlefield under its owner's control at the beginning of the next end step.| +The Blue Spirit|Avatar: The Last Airbender Eternal|90|R|{3}{U}|Legendary Creature - Human Rogue Ally|2|4|You may cast the first creature spell you cast each turn as though it had flash.$Whenever a nontoken creature you control enters during combat, draw a card.| +Chakra Meditation|Avatar: The Last Airbender Eternal|91|R|{2}{U}|Enchantment|||When this enchantment enters, return up to one target instant or sorcery card from your graveyard to your hand.$Whenever you cast an instant or sorcery spell, draw a card. Then discard a card unless there are three or more Lesson cards in your graveyard.| +Dutiful Knowledge Seeker|Avatar: The Last Airbender Eternal|92|U|{2}{U}|Creature - Fox Spirit|2|2|Whenever one or more cards are put into a library from anywhere, put a +1/+1 counter on this creature.${3}: Put target card from a graveyard on the bottom of its owner's library.| Katara, Waterbending Master|Avatar: The Last Airbender Eternal|93|M|{1}{U}|Legendary Creature - Human Warrior Ally|1|3|Whenever you cast a spell during an opponent's turn, you get an experience counter.$Whenever Katara attacks, you may draw a card for each experience counter you have. If you do, discard a card.| +Nightmares and Daydreams|Avatar: The Last Airbender Eternal|94|R|{2}{U}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after IV.)$I, II, III -- Until your next turn, whenever you cast an instant or sorcery spell, target player mills cards equal to that spell's mana value.$IV -- Draw a card. If a graveyard has twenty or more cards in it, draw three cards instead.| +Princess Yue|Avatar: The Last Airbender Eternal|95|U|{2}{U}|Legendary Creature - Human Noble Ally|3|2|When Princess Yue dies, if she was a nonland creature, return this card to the battlefield tapped under your control. She's a land named Moon. She gains "{T}: Add {C}."${T}: Scry 2.| +Tui and La, Moon and Ocean|Avatar: The Last Airbender Eternal|96|R|{3}{U}|Legendary Creature - Fish Spirit|3|3|Whenever Tui and La become tapped, draw a card.$Whenever Tui and La become untapped, put a +1/+1 counter on them.| +Unagi's Spray|Avatar: The Last Airbender Eternal|97|C|{U}|Instant|||Target creature gets -4/-0 until end of turn. If you control a Fish, Octopus, Otter, Seal, Serpent, or Whale, draw a card.| Wan Shi Tong, All-Knowing|Avatar: The Last Airbender Eternal|98|M|{3}{U}{U}|Legendary Creature - Bird Spirit|4|4|Flying$When Wan Shi Tong enters, target nonland permanent's owner puts it into their library second from the top or on the bottom.$Whenever one or more cards are put into a library from anywhere, create two 1/1 colorless Spirit creature tokens with "This token can't block or be blocked by non-Spirit creatures."| +Waterbender's Restoration|Avatar: The Last Airbender Eternal|99|R|{U}{U}|Instant - Lesson|||As an additional cost to cast this spell, waterbend {X}.$Exile X target creatures you control. Return those cards to the battlefield under their owner's control at the beginning of the next end step.| +Whirlwind Technique|Avatar: The Last Airbender Eternal|100|U|{4}{U}{U}|Instant - Lesson|||Target player draws two cards, then discards a card.$Airbend up to two target creatures.| Azula, Ruthless Firebender|Avatar: The Last Airbender Eternal|101|M|{2}{B}|Legendary Creature - Human Noble|3|3|Firebending 1$Whenever Azula attacks, you may discard a card. Then you get an experience counter for each player who discarded a card this turn.${2}{B}: Until end of turn, Azula gets +1/+1 for each experience counter you have and gains menace.| Fire Lord Ozai|Avatar: The Last Airbender Eternal|104|M|{3}{B}|Legendary Creature - Human Noble|4|4|Whenever Fire Lord Ozai attacks, you may sacrifice another creature. If you do, add an amount of {R} equal to the sacrificed creature's power. Until end of combat, you don't lose this mana as steps end.${6}: Exile the top card of each opponent's library. Until end of turn, you may play one of those cards without paying its mana cost.| Avatar Roku, Firebender|Avatar: The Last Airbender Eternal|112|M|{3}{R}{R}{R}|Legendary Creature - Human Avatar|6|6|Whenever a player attacks, add six {R}. Until end of combat, you don't lose this mana as steps end.${R}{R}{R}: Target creature gets +3/+0 until end of turn.| -- 2.47.2 From 52dbd9614732ebbce7dcd47a2fa5c0e794c13316 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:51:23 -0500 Subject: [PATCH 117/261] [TLE] Implement Toucan-Puffin --- Mage.Sets/src/mage/cards/t/ToucanPuffin.java | 45 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 46 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/ToucanPuffin.java diff --git a/Mage.Sets/src/mage/cards/t/ToucanPuffin.java b/Mage.Sets/src/mage/cards/t/ToucanPuffin.java new file mode 100644 index 00000000000..f3b285f6c41 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ToucanPuffin.java @@ -0,0 +1,45 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ToucanPuffin extends CardImpl { + + public ToucanPuffin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.BIRD); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When this creature enters, target creature you control gets +2/+0 until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(2, 0)); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + private ToucanPuffin(final ToucanPuffin card) { + super(card); + } + + @Override + public ToucanPuffin copy() { + return new ToucanPuffin(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 0291ebf154a..fe55d937053 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -162,6 +162,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Thriving Isle", 263, Rarity.COMMON, mage.cards.t.ThrivingIsle.class)); cards.add(new SetCardInfo("Thriving Moor", 264, Rarity.COMMON, mage.cards.t.ThrivingMoor.class)); cards.add(new SetCardInfo("Toph, Earthbending Master", 145, Rarity.MYTHIC, mage.cards.t.TophEarthbendingMaster.class)); + cards.add(new SetCardInfo("Toucan-Puffin", 88, Rarity.COMMON, mage.cards.t.ToucanPuffin.class)); cards.add(new SetCardInfo("Training Grounds", 20, Rarity.MYTHIC, mage.cards.t.TrainingGrounds.class)); cards.add(new SetCardInfo("Tundra Wall", 220, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tundra Wall", 275, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 6e3d278fc86fc4503e62311ca3117ce0a3859b14 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:52:23 -0500 Subject: [PATCH 118/261] [TLE] Implement Sokka's Sword Training --- .../src/mage/cards/s/SokkasSwordTraining.java | 40 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 41 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SokkasSwordTraining.java diff --git a/Mage.Sets/src/mage/cards/s/SokkasSwordTraining.java b/Mage.Sets/src/mage/cards/s/SokkasSwordTraining.java new file mode 100644 index 00000000000..d88a1297cfa --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SokkasSwordTraining.java @@ -0,0 +1,40 @@ +package mage.cards.s; + +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.ClueArtifactToken; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SokkasSwordTraining extends CardImpl { + + public SokkasSwordTraining(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); + + this.subtype.add(SubType.LESSON); + + // Target creature gets +2/+2 until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Create a Clue token. + this.getSpellAbility().addEffect(new CreateTokenEffect(new ClueArtifactToken()).concatBy("
")); + } + + private SokkasSwordTraining(final SokkasSwordTraining card) { + super(card); + } + + @Override + public SokkasSwordTraining copy() { + return new SokkasSwordTraining(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index fe55d937053..ca7dedf34ea 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -144,6 +144,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Shattering Spree", 36, Rarity.MYTHIC, mage.cards.s.ShatteringSpree.class)); cards.add(new SetCardInfo("Sledding Otter-Penguin", 218, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sledding Otter-Penguin", 273, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sokka's Sword Training", 84, Rarity.COMMON, mage.cards.s.SokkasSwordTraining.class)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 219, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 274, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sol Ring", 316, Rarity.RARE, mage.cards.s.SolRing.class)); -- 2.47.2 From e43cef514ba1d8942cf52bcae2532853d6dd059d Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 12:53:03 -0500 Subject: [PATCH 119/261] [TLE] Implement Kindly Customer --- .../src/mage/cards/k/KindlyCustomer.java | 38 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 39 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/k/KindlyCustomer.java diff --git a/Mage.Sets/src/mage/cards/k/KindlyCustomer.java b/Mage.Sets/src/mage/cards/k/KindlyCustomer.java new file mode 100644 index 00000000000..20d5ed750ca --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KindlyCustomer.java @@ -0,0 +1,38 @@ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KindlyCustomer extends CardImpl { + + public KindlyCustomer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CITIZEN); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When this creature enters, draw a card. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1))); + } + + private KindlyCustomer(final KindlyCustomer card) { + super(card); + } + + @Override + public KindlyCustomer copy() { + return new KindlyCustomer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index ca7dedf34ea..fae0c4c13df 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -95,6 +95,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Heroic Healer", 269, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Waterbending Master", 93, Rarity.MYTHIC, mage.cards.k.KataraWaterbendingMaster.class)); + cards.add(new SetCardInfo("Kindly Customer", 79, Rarity.COMMON, mage.cards.k.KindlyCustomer.class)); cards.add(new SetCardInfo("Koma, Cosmos Serpent", 51, Rarity.MYTHIC, mage.cards.k.KomaCosmosSerpent.class)); cards.add(new SetCardInfo("Komodo Rhino", 241, Rarity.COMMON, mage.cards.k.KomodoRhino.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Komodo Rhino", 283, Rarity.COMMON, mage.cards.k.KomodoRhino.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From b05f749be4f73be244bd11785d0327204a9e7a0b Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 19:07:58 -0500 Subject: [PATCH 120/261] [TLE] update spoiler and reprints --- .../sets/AvatarTheLastAirbenderEternal.java | 37 ++++++++- Utils/mtg-cards-data.txt | 76 +++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index fae0c4c13df..3ec58b1b73a 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -12,7 +12,7 @@ import java.util.List; */ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { - private static final List unfinished = Arrays.asList("Waterbender's Restoration", "Water Whip"); + private static final List unfinished = Arrays.asList("Katara, Seeking Revenge", "Ruthless Waterbender", "Waterbender's Restoration", "Water Whip"); private static final AvatarTheLastAirbenderEternal instance = new AvatarTheLastAirbenderEternal(); @@ -33,6 +33,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Aang, Airbending Master", 74, Rarity.MYTHIC, mage.cards.a.AangAirbendingMaster.class)); cards.add(new SetCardInfo("Aardvark Sloth", 212, Rarity.COMMON, mage.cards.a.AardvarkSloth.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aardvark Sloth", 267, Rarity.COMMON, mage.cards.a.AardvarkSloth.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Acrobatic Leap", 151, Rarity.COMMON, mage.cards.a.AcrobaticLeap.class)); cards.add(new SetCardInfo("Agent of Treachery", 9, Rarity.MYTHIC, mage.cards.a.AgentOfTreachery.class)); cards.add(new SetCardInfo("Allied Teamwork", 213, Rarity.RARE, mage.cards.a.AlliedTeamwork.class)); cards.add(new SetCardInfo("Appa, Aang's Companion", 214, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS)); @@ -40,39 +41,56 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Arcane Signet", 315, Rarity.RARE, mage.cards.a.ArcaneSignet.class)); cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 130, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class)); cards.add(new SetCardInfo("Avatar Roku, Firebender", 112, Rarity.MYTHIC, mage.cards.a.AvatarRokuFirebender.class)); + cards.add(new SetCardInfo("Bastion of Remembrance", 160, Rarity.UNCOMMON, mage.cards.b.BastionOfRemembrance.class)); cards.add(new SetCardInfo("Beastmaster Ascension", 39, Rarity.MYTHIC, mage.cards.b.BeastmasterAscension.class)); cards.add(new SetCardInfo("Beastmaster's Magemark", 9999, Rarity.MYTHIC, mage.cards.b.BeastmastersMagemark.class)); cards.add(new SetCardInfo("Black Sun's Zenith", 22, Rarity.MYTHIC, mage.cards.b.BlackSunsZenith.class)); cards.add(new SetCardInfo("Blasphemous Act", 26, Rarity.MYTHIC, mage.cards.b.BlasphemousAct.class)); cards.add(new SetCardInfo("Bloodchief Ascension", 23, Rarity.MYTHIC, mage.cards.b.BloodchiefAscension.class)); + cards.add(new SetCardInfo("Bolt Bend", 163, Rarity.UNCOMMON, mage.cards.b.BoltBend.class)); + cards.add(new SetCardInfo("Brainstorm", 155, Rarity.COMMON, mage.cards.b.Brainstorm.class)); cards.add(new SetCardInfo("Bribery", 10, Rarity.MYTHIC, mage.cards.b.Bribery.class)); cards.add(new SetCardInfo("Brought Back", 1, Rarity.MYTHIC, mage.cards.b.BroughtBack.class)); cards.add(new SetCardInfo("Bumi, Eclectic Earthbender", 248, Rarity.RARE, mage.cards.b.BumiEclecticEarthbender.class)); cards.add(new SetCardInfo("Capital Guard", 234, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Capital Guard", 277, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Captain Sisay", 47, Rarity.MYTHIC, mage.cards.c.CaptainSisay.class)); + cards.add(new SetCardInfo("Cathartic Reunion", 164, Rarity.COMMON, mage.cards.c.CatharticReunion.class)); cards.add(new SetCardInfo("Cityscape Leveler", 53, Rarity.MYTHIC, mage.cards.c.CityscapeLeveler.class)); cards.add(new SetCardInfo("Clone Legion", 12, Rarity.MYTHIC, mage.cards.c.CloneLegion.class)); cards.add(new SetCardInfo("Clone", 11, Rarity.MYTHIC, mage.cards.c.Clone.class)); + cards.add(new SetCardInfo("Cloudshift", 152, Rarity.COMMON, mage.cards.c.Cloudshift.class)); + cards.add(new SetCardInfo("Coastal Piracy", 156, Rarity.UNCOMMON, mage.cards.c.CoastalPiracy.class)); + cards.add(new SetCardInfo("Consider", 157, Rarity.COMMON, mage.cards.c.Consider.class)); cards.add(new SetCardInfo("Cruel Tutor", 24, Rarity.MYTHIC, mage.cards.c.CruelTutor.class)); + cards.add(new SetCardInfo("Dark Deal", 161, Rarity.UNCOMMON, mage.cards.d.DarkDeal.class)); cards.add(new SetCardInfo("Dark Depths", 56, Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); + cards.add(new SetCardInfo("Deadly Rollick", 309, Rarity.RARE, mage.cards.d.DeadlyRollick.class)); + cards.add(new SetCardInfo("Deflecting Swat", 311, Rarity.RARE, mage.cards.d.DeflectingSwat.class)); cards.add(new SetCardInfo("Deny Entry", 222, Rarity.COMMON, mage.cards.d.DenyEntry.class)); cards.add(new SetCardInfo("Descendants' Path", 167, Rarity.RARE, mage.cards.d.DescendantsPath.class)); cards.add(new SetCardInfo("Diaochan, Artful Beauty", 27, Rarity.MYTHIC, mage.cards.d.DiaochanArtfulBeauty.class)); + cards.add(new SetCardInfo("Diresight", 162, Rarity.COMMON, mage.cards.d.Diresight.class)); cards.add(new SetCardInfo("Dockside Extortionist", 28, Rarity.MYTHIC, mage.cards.d.DocksideExtortionist.class)); cards.add(new SetCardInfo("Dragon Moose", 235, Rarity.COMMON, mage.cards.d.DragonMoose.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dragon Moose", 278, Rarity.COMMON, mage.cards.d.DragonMoose.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Dramatic Reversal", 158, Rarity.COMMON, mage.cards.d.DramaticReversal.class)); cards.add(new SetCardInfo("Drannith Magistrate", 2, Rarity.MYTHIC, mage.cards.d.DrannithMagistrate.class)); + cards.add(new SetCardInfo("Duelist's Heritage", 153, Rarity.RARE, mage.cards.d.DuelistsHeritage.class)); cards.add(new SetCardInfo("Earthbending Student", 249, Rarity.UNCOMMON, mage.cards.e.EarthbendingStudent.class)); cards.add(new SetCardInfo("Eel-Hounds", 250, Rarity.UNCOMMON, mage.cards.e.EelHounds.class)); cards.add(new SetCardInfo("Eladamri's Call", 48, Rarity.MYTHIC, mage.cards.e.EladamrisCall.class)); + cards.add(new SetCardInfo("Elemental Bond", 40, Rarity.MYTHIC, mage.cards.e.ElementalBond.class)); cards.add(new SetCardInfo("Elephant-Rat", 228, Rarity.COMMON, mage.cards.e.ElephantRat.class)); cards.add(new SetCardInfo("Empty City Ruse", 3, Rarity.MYTHIC, mage.cards.e.EmptyCityRuse.class)); + cards.add(new SetCardInfo("Enlightened Tutor", 305, Rarity.RARE, mage.cards.e.EnlightenedTutor.class)); + cards.add(new SetCardInfo("Entomb", 310, Rarity.RARE, mage.cards.e.Entomb.class)); cards.add(new SetCardInfo("Explore", 259, Rarity.COMMON, mage.cards.e.Explore.class)); cards.add(new SetCardInfo("Explosive Shot", 236, Rarity.COMMON, mage.cards.e.ExplosiveShot.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Explosive Shot", 279, Rarity.COMMON, mage.cards.e.ExplosiveShot.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fabled Passage", 57, Rarity.MYTHIC, mage.cards.f.FabledPassage.class)); cards.add(new SetCardInfo("Feed the Swarm", 257, Rarity.COMMON, mage.cards.f.FeedTheSwarm.class)); + cards.add(new SetCardInfo("Fierce Guardianship", 307, Rarity.RARE, mage.cards.f.FierceGuardianship.class)); cards.add(new SetCardInfo("Fiery Confluence", 165, Rarity.RARE, mage.cards.f.FieryConfluence.class)); cards.add(new SetCardInfo("Fire Nation Ambushers", 229, Rarity.COMMON, mage.cards.f.FireNationAmbushers.class)); cards.add(new SetCardInfo("Fire Nation Archers", 237, Rarity.RARE, mage.cards.f.FireNationArchers.class)); @@ -81,15 +99,21 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Fire Nation Soldier", 280, Rarity.COMMON, mage.cards.f.FireNationSoldier.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation's Conquest", 239, Rarity.UNCOMMON, mage.cards.f.FireNationsConquest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation's Conquest", 281, Rarity.UNCOMMON, mage.cards.f.FireNationsConquest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fists of Flame", 166, Rarity.COMMON, mage.cards.f.FistsOfFlame.class)); + cards.add(new SetCardInfo("Flawless Maneuver", 306, Rarity.RARE, mage.cards.f.FlawlessManeuver.class)); cards.add(new SetCardInfo("Flying Dolphin-Fish", 223, Rarity.COMMON, mage.cards.f.FlyingDolphinFish.class)); cards.add(new SetCardInfo("Force of Negation", 13, Rarity.MYTHIC, mage.cards.f.ForceOfNegation.class)); + cards.add(new SetCardInfo("Frantic Search", 159, Rarity.COMMON, mage.cards.f.FranticSearch.class)); cards.add(new SetCardInfo("Frog-Squirrels", 251, Rarity.COMMON, mage.cards.f.FrogSquirrels.class)); + cards.add(new SetCardInfo("Gamble", 312, Rarity.RARE, mage.cards.g.Gamble.class)); cards.add(new SetCardInfo("Gilacorn", 231, Rarity.COMMON, mage.cards.g.Gilacorn.class)); cards.add(new SetCardInfo("Heartbeat of Spring", 42, Rarity.MYTHIC, mage.cards.h.HeartbeatOfSpring.class)); cards.add(new SetCardInfo("Heroic Intervention", 43, Rarity.MYTHIC, mage.cards.h.HeroicIntervention.class)); cards.add(new SetCardInfo("Hippo-Cows", 252, Rarity.COMMON, mage.cards.h.HippoCows.class)); cards.add(new SetCardInfo("Imprisoned in the Moon", 14, Rarity.MYTHIC, mage.cards.i.ImprisonedInTheMoon.class)); + cards.add(new SetCardInfo("Inspiring Call", 168, Rarity.UNCOMMON, mage.cards.i.InspiringCall.class)); cards.add(new SetCardInfo("Insurrection", 31, Rarity.MYTHIC, mage.cards.i.Insurrection.class)); + cards.add(new SetCardInfo("Intruder Alarm", 15, Rarity.MYTHIC, mage.cards.i.IntruderAlarm.class)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 240, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 282, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); @@ -103,8 +127,10 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Lion Vulture", 232, Rarity.RARE, mage.cards.l.LionVulture.class)); cards.add(new SetCardInfo("Lost in the Spirit World", 224, Rarity.UNCOMMON, mage.cards.l.LostInTheSpiritWorld.class)); cards.add(new SetCardInfo("Loyal Fire Sage", 242, Rarity.UNCOMMON, mage.cards.l.LoyalFireSage.class)); + cards.add(new SetCardInfo("Many Partings", 169, Rarity.COMMON, mage.cards.m.ManyPartings.class)); cards.add(new SetCardInfo("Match the Odds", 253, Rarity.UNCOMMON, mage.cards.m.MatchTheOdds.class)); cards.add(new SetCardInfo("Mechanical Glider", 256, Rarity.COMMON, mage.cards.m.MechanicalGlider.class)); + cards.add(new SetCardInfo("Meteorite", 54, Rarity.MYTHIC, mage.cards.m.Meteorite.class)); cards.add(new SetCardInfo("Mirrorwing Dragon", 33, Rarity.MYTHIC, mage.cards.m.MirrorwingDragon.class)); cards.add(new SetCardInfo("Momo, Rambunctious Rascal", 217, Rarity.UNCOMMON, mage.cards.m.MomoRambunctiousRascal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Momo, Rambunctious Rascal", 270, Rarity.UNCOMMON, mage.cards.m.MomoRambunctiousRascal.class, NON_FULL_USE_VARIOUS)); @@ -117,7 +143,9 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 295, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 296, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mystic Remora", 16, Rarity.MYTHIC, mage.cards.m.MysticRemora.class)); + cards.add(new SetCardInfo("Mystical Tutor", 308, Rarity.RARE, mage.cards.m.MysticalTutor.class)); cards.add(new SetCardInfo("Noxious Gearhulk", 25, Rarity.MYTHIC, mage.cards.n.NoxiousGearhulk.class)); + cards.add(new SetCardInfo("Obscuring Haze", 313, Rarity.RARE, mage.cards.o.ObscuringHaze.class)); cards.add(new SetCardInfo("Path to Redemption", 271, Rarity.COMMON, mage.cards.p.PathToRedemption.class)); cards.add(new SetCardInfo("Plains", 297, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 298, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); @@ -150,7 +178,9 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 274, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sol Ring", 316, Rarity.RARE, mage.cards.s.SolRing.class)); cards.add(new SetCardInfo("Standstill", 19, Rarity.MYTHIC, mage.cards.s.Standstill.class)); + cards.add(new SetCardInfo("Sunbaked Canyon", 58, Rarity.MYTHIC, mage.cards.s.SunbakedCanyon.class)); cards.add(new SetCardInfo("Sundial of the Infinite", 55, Rarity.MYTHIC, mage.cards.s.SundialOfTheInfinite.class)); + cards.add(new SetCardInfo("Suspicious Bookcase", 170, Rarity.UNCOMMON, mage.cards.s.SuspiciousBookcase.class)); cards.add(new SetCardInfo("Swiftfoot Boots", 317, Rarity.RARE, mage.cards.s.SwiftfootBoots.class)); cards.add(new SetCardInfo("Taunting Challenge", 46, Rarity.MYTHIC, mage.cards.t.TauntingChallenge.class)); cards.add(new SetCardInfo("Teferi's Protection", 7, Rarity.MYTHIC, mage.cards.t.TeferisProtection.class)); @@ -166,16 +196,21 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Toph, Earthbending Master", 145, Rarity.MYTHIC, mage.cards.t.TophEarthbendingMaster.class)); cards.add(new SetCardInfo("Toucan-Puffin", 88, Rarity.COMMON, mage.cards.t.ToucanPuffin.class)); cards.add(new SetCardInfo("Training Grounds", 20, Rarity.MYTHIC, mage.cards.t.TrainingGrounds.class)); + cards.add(new SetCardInfo("Treetop Village", 60, Rarity.MYTHIC, mage.cards.t.TreetopVillage.class)); cards.add(new SetCardInfo("Tundra Wall", 220, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tundra Wall", 275, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Turtle-Seals", 226, Rarity.COMMON, mage.cards.t.TurtleSeals.class)); cards.add(new SetCardInfo("Valakut, the Molten Pinnacle", 61, Rarity.MYTHIC, mage.cards.v.ValakutTheMoltenPinnacle.class)); + cards.add(new SetCardInfo("Valorous Stance", 154, Rarity.UNCOMMON, mage.cards.v.ValorousStance.class)); cards.add(new SetCardInfo("Visions of Beyond", 21, Rarity.MYTHIC, mage.cards.v.VisionsOfBeyond.class)); + cards.add(new SetCardInfo("Volcanic Torrent", 37, Rarity.MYTHIC, mage.cards.v.VolcanicTorrent.class)); cards.add(new SetCardInfo("Warship Scout", 244, Rarity.COMMON, mage.cards.w.WarshipScout.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Warship Scout", 285, Rarity.COMMON, mage.cards.w.WarshipScout.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Warstorm Surge", 38, Rarity.MYTHIC, mage.cards.w.WarstormSurge.class)); cards.add(new SetCardInfo("Water Whip", 227, Rarity.RARE, mage.cards.w.WaterWhip.class)); cards.add(new SetCardInfo("Wolf Cove Villager", 221, Rarity.COMMON, mage.cards.w.WolfCoveVillager.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Wolf Cove Villager", 276, Rarity.COMMON, mage.cards.w.WolfCoveVillager.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Worldly Tutor", 314, Rarity.RARE, mage.cards.w.WorldlyTutor.class)); cards.add(new SetCardInfo("Zhao, the Seething Flame", 245, Rarity.UNCOMMON, mage.cards.z.ZhaoTheSeethingFlame.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Zhao, the Seething Flame", 286, Rarity.UNCOMMON, mage.cards.z.ZhaoTheSeethingFlame.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Zuko's Offense", 247, Rarity.COMMON, mage.cards.z.ZukosOffense.class, NON_FULL_USE_VARIOUS)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 759344d986f..23dca0a4c22 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -60435,6 +60435,7 @@ Clone|Avatar: The Last Airbender Eternal|11|M|{3}{U}|Creature - Shapeshifter|0|0 Clone Legion|Avatar: The Last Airbender Eternal|12|M|{7}{U}{U}|Sorcery|||For each creature target player controls, create a token that's a copy of that creature.| Force of Negation|Avatar: The Last Airbender Eternal|13|M|{1}{U}{U}|Instant|||If it's not your turn, you may exile a blue card from your hand rather than pay this spell's mana cost.$Counter target noncreature spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.| Imprisoned in the Moon|Avatar: The Last Airbender Eternal|14|M|{2}{U}|Enchantment - Aura|||Enchant creature, land, or planeswalker$Enchanted permanent is a colorless land with "{T}: Add {C}" and loses all other card types and abilities.| +Intruder Alarm|Avatar: The Last Airbender Eternal|15|M|{2}{U}|Enchantment|||Creatures don't untap during their controllers' untap steps.$Whenever a creature enters, untap all creatures.| Mystic Remora|Avatar: The Last Airbender Eternal|16|M|{U}|Enchantment|||Cumulative upkeep {1}$Whenever an opponent casts a noncreature spell, you may draw a card unless that player pays {4}.| Prosperity|Avatar: The Last Airbender Eternal|17|M|{X}{U}|Sorcery|||Each player draws X cards.| Sakashima of a Thousand Faces|Avatar: The Last Airbender Eternal|18|M|{3}{U}|Legendary Creature - Human Rogue|3|1|You may have Sakashima enter as a copy of another creature you control, except it has Sakashima's other abilities.$The "legend rule" doesn't apply to permanents you control.$Partner| @@ -60453,7 +60454,10 @@ Mirrorwing Dragon|Avatar: The Last Airbender Eternal|33|M|{3}{R}{R}|Creature - D Rending Volley|Avatar: The Last Airbender Eternal|34|M|{R}|Instant|||This spell can't be countered.$Rending Volley deals 4 damage to target white or blue creature.| Searing Blood|Avatar: The Last Airbender Eternal|35|M|{R}{R}|Instant|||Searing Blood deals 2 damage to target creature. When that creature dies this turn, Searing Blood deals 3 damage to the creature's controller.| Shattering Spree|Avatar: The Last Airbender Eternal|36|M|{R}|Sorcery|||Replicate {R}$Destroy target artifact.| +Volcanic Torrent|Avatar: The Last Airbender Eternal|37|M|{4}{R}|Sorcery|||Cascade$Volcanic Torrent deals X damage to each creature and planeswalker your opponents control, where X is the number of spells you've cast this turn.| +Warstorm Surge|Avatar: The Last Airbender Eternal|38|M|{5}{R}|Enchantment|||Whenever a creature you control enters, it deals damage equal to its power to any target.| Beastmaster Ascension|Avatar: The Last Airbender Eternal|39|M|{2}{G}|Enchantment|||Whenever a creature you control attacks, you may put a quest counter on this enchantment.$As long as this enchantment has seven or more quest counters on it, creatures you control get +5/+5.| +Elemental Bond|Avatar: The Last Airbender Eternal|40|M|{2}{G}|Enchantment|||Whenever a creature you control with power 3 or greater enters, draw a card.| The Great Henge|Avatar: The Last Airbender Eternal|41|M|{7}{G}{G}|Legendary Artifact|||This spell costs {X} less to cast, where X is the greatest power among creatures you control.${T}: Add {G}{G}. You gain 2 life.$Whenever a nontoken creature you control enters, put a +1/+1 counter on it and draw a card.| Heartbeat of Spring|Avatar: The Last Airbender Eternal|42|M|{2}{G}|Enchantment|||Whenever a player taps a land for mana, that player adds one mana of any type that land produced.| Heroic Intervention|Avatar: The Last Airbender Eternal|43|M|{1}{G}|Instant|||Permanents you control gain hexproof and indestructible until end of turn.| @@ -60465,9 +60469,12 @@ Eladamri's Call|Avatar: The Last Airbender Eternal|48|M|{G}{W}|Instant|||Search Koma, Cosmos Serpent|Avatar: The Last Airbender Eternal|51|M|{3}{G}{G}{U}{U}|Legendary Creature - Serpent|6|6|This spell can't be countered.$At the beginning of each upkeep, create a 3/3 blue Serpent creature token named Koma's Coil.$Sacrifice another Serpent: Choose one --$* Tap target permanent. Its activated abilities can't be activated this turn.$* Koma gains indestructible until end of turn.| Rhys the Redeemed|Avatar: The Last Airbender Eternal|52|M|{G/W}|Legendary Creature - Elf Warrior|1|1|{2}{G/W}, {T}: Create a 1/1 green and white Elf Warrior creature token.${4}{G/W}{G/W}, {T}: For each creature token you control, create a token that's a copy of that creature.| Cityscape Leveler|Avatar: The Last Airbender Eternal|53|M|{8}|Artifact Creature - Construct|8|8|Trample$When you cast this spell and whenever this creature attacks, destroy up to one target nonland permanent. Its controller creates a tapped Powerstone token.$Unearth {8}| +Meteorite|Avatar: The Last Airbender Eternal|54|M|{5}|Artifact|||When this artifact enters, it deals 2 damage to any target.${T}: Add one mana of any color.| Sundial of the Infinite|Avatar: The Last Airbender Eternal|55|M|{2}|Artifact|||{1}, {T}: End the turn. Activate only during your turn.| Dark Depths|Avatar: The Last Airbender Eternal|56|M||Legendary Snow Land|||Dark Depths enters with ten ice counters on it.${3}: Remove an ice counter from Dark Depths.$When Dark Depths has no ice counters on it, sacrifice it. If you do, create Marit Lage, a legendary 20/20 black Avatar creature token with flying and indestructible.| Fabled Passage|Avatar: The Last Airbender Eternal|57|M||Land|||{T}, Sacrifice this land: Search your library for a basic land card, put it onto the battlefield tapped, then shuffle. Then if you control four or more lands, untap that land.| +Sunbaked Canyon|Avatar: The Last Airbender Eternal|58|M||Land|||{T}, Pay 1 life: Add {R} or {W}.${1}, {T}, Sacrifice this land: Draw a card.| +Treetop Village|Avatar: The Last Airbender Eternal|60|M||Land|||This land enters tapped.${T}: Add {G}.${1}{G}: This land becomes a 3/3 green Ape creature with trample until end of turn. It's still a land.| Valakut, the Molten Pinnacle|Avatar: The Last Airbender Eternal|61|M||Land|||This land enters tapped.$Whenever a Mountain you control enters, if you control at least five other Mountains, you may have this land deal 3 damage to any target.${T}: Add {R}.| Appa, the Vigilant|Avatar: The Last Airbender Eternal|62|R|{5}{W}{W}|Legendary Creature - Bison Ally|6|6|Flying, vigilance$Whenever Appa or another Ally you control enters, creatures you control get +1/+1 and gain flying and vigilance until end of turn.| Katara's Reversal|Avatar: The Last Airbender Eternal|63|R|{2}{U}{U}|Instant|||Counter up to four target spells and/or abilities.$Untap up to four target artifacts and/or creatures.| @@ -60509,16 +60516,75 @@ Wan Shi Tong, All-Knowing|Avatar: The Last Airbender Eternal|98|M|{3}{U}{U}|Lege Waterbender's Restoration|Avatar: The Last Airbender Eternal|99|R|{U}{U}|Instant - Lesson|||As an additional cost to cast this spell, waterbend {X}.$Exile X target creatures you control. Return those cards to the battlefield under their owner's control at the beginning of the next end step.| Whirlwind Technique|Avatar: The Last Airbender Eternal|100|U|{4}{U}{U}|Instant - Lesson|||Target player draws two cards, then discards a card.$Airbend up to two target creatures.| Azula, Ruthless Firebender|Avatar: The Last Airbender Eternal|101|M|{2}{B}|Legendary Creature - Human Noble|3|3|Firebending 1$Whenever Azula attacks, you may discard a card. Then you get an experience counter for each player who discarded a card this turn.${2}{B}: Until end of turn, Azula gets +1/+1 for each experience counter you have and gains menace.| +Dai Li Censor|Avatar: The Last Airbender Eternal|102|C|{1}{B}|Creature - Human Soldier Advisor|2|1|{1}, Sacrifice another creature: This creature gets +2/+2 until end of turn. Activate only once each turn.| +Desperate Plea|Avatar: The Last Airbender Eternal|103|R|{1}{B}|Sorcery - Lesson|||As an additional cost to cast this spell, sacrifice a creature.$Choose one or both --$* Return target creature card from your graveyard to the battlefield if its power is less than or equal to the sacrificed creature's power.$* Destroy target creature.| Fire Lord Ozai|Avatar: The Last Airbender Eternal|104|M|{3}{B}|Legendary Creature - Human Noble|4|4|Whenever Fire Lord Ozai attacks, you may sacrifice another creature. If you do, add an amount of {R} equal to the sacrificed creature's power. Until end of combat, you don't lose this mana as steps end.${6}: Exile the top card of each opponent's library. Until end of turn, you may play one of those cards without paying its mana cost.| +Fire Nation Occupation|Avatar: The Last Airbender Eternal|105|R|{2}{B}|Enchantment|||When this enchantment enters, create a 2/2 red Soldier creature token with firebending 1.$Whenever you cast a spell during an opponent's turn, create a 2/2 red Soldier creature token with firebending 1.| +Fire Nation Salvagers|Avatar: The Last Airbender Eternal|106|R|{3}{B}{B}|Creature - Human Soldier|3|3|Menace$When this creature enters, put a +1/+1 counter on target creature or Vehicle you control.$Whenever one or more creatures you control with counters on them deal combat damage to a player, put target creature or Vehicle card from that player's graveyard onto the battlefield under your control.| +Giant Fly|Avatar: The Last Airbender Eternal|107|C|{2}{B}|Creature - Insect|2|2|Flying$Whenever you sacrifice another permanent, this creature gets +1/+0 until end of turn.| +Lo and Li, Royal Advisors|Avatar: The Last Airbender Eternal|108|R|{2}{B}{B}|Legendary Creature - Human Advisor|3|3|Whenever an opponent discards a card or mills one or more cards, put a +1/+1 counter on each Advisor you control.${2}{U/B}: Target player mills four cards.| +Nyla, Shirshu Sleuth|Avatar: The Last Airbender Eternal|109|R|{4}{B}|Legendary Creature - Mole Beast|4|5|When Nyla enters, exile up to one target creature card from your graveyard. If you do, you lose X life and create X Clue tokens, where X is that card's mana value.$At the beginning of your end step, if you control no Clues, return target card exiled with Nyla to its owner's hand.| +Ruthless Waterbender|Avatar: The Last Airbender Eternal|110|U|{1}{B}|Creature - Human Soldier Ally|1|3|Waterbend {2}: This creature gets +1/+1 until end of turn. Activate only during your turn.| +Scarring Memories|Avatar: The Last Airbender Eternal|111|U|{3}{B}|Sorcery - Lesson|||You may cast this spell as though it had flash if you control an attacking legendary creature.$Target opponent sacrifices a creature of their choice, discards a card, and loses 3 life.| Avatar Roku, Firebender|Avatar: The Last Airbender Eternal|112|M|{3}{R}{R}{R}|Legendary Creature - Human Avatar|6|6|Whenever a player attacks, add six {R}. Until end of combat, you don't lose this mana as steps end.${R}{R}{R}: Target creature gets +3/+0 until end of turn.| +Chong and Lily, Nomads|Avatar: The Last Airbender Eternal|113|R|{3}{R}|Legendary Creature - Human Bard Ally|3|3|Whenever one or more Bards you control attack, choose one --$* Put a lore counter on each of any number of target Sagas you control.$* Creatures you control get +1/+0 until end of turn for each lore counter among Sagas you control.| +Deer-Dog|Avatar: The Last Airbender Eternal|114|C|{1}{R}|Creature - Elk Dog|1|3|First strike| Fang, Roku's Companion|Avatar: The Last Airbender Eternal|115|R|{3}{R}{R}|Legendary Creature - Dragon|4|4|Flying$Whenever Fang attacks, another target legendary creature you control gets +X/+0 until end of turn, where X is Fang's power.$When Fang dies, if he wasn't a Spirit, return this card to the battlefield under your control. He's a Spirit in addition to his other types.| +Founding of Omashu|Avatar: The Last Airbender Eternal|116|U|{2}{R}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I -- Create two 1/1 white Ally creature tokens.$II -- You may discard a card. If you do,$draw a card.$III -- Creatures you control get +1/+0 until end of turn.| +Frantic Confrontation|Avatar: The Last Airbender Eternal|117|U|{X}{R}|Instant|||Target creature you control gets +X/+0 and gains first strike and trample until end of turn.| +Freedom Fighter Recruit|Avatar: The Last Airbender Eternal|118|C|{1}{R}|Creature - Human Rebel Ally|*|2|Freedom Fighter Recruit's power is equal to the number of creatures you control.| +Iroh, Dragon of the West|Avatar: The Last Airbender Eternal|119|R|{2}{R}{R}|Legendary Creature - Human Noble Ally|4|4|Haste$Mentor$At the beginning of combat on your turn, each creature you control with a counter on it gains firebending 2 until end of turn.| +Longshot, Rebel Bowman|Avatar: The Last Airbender Eternal|120|U|{3}{R}|Legendary Creature - Human Rebel Ally|3|3|Reach$Noncreature spells you cast cost {1} less to cast.$Whenever you cast a noncreature spell, Longshot deals 2 damage to each opponent.| +Lost in Memories|Avatar: The Last Airbender Eternal|121|R|{1}{R}|Enchantment - Aura|||Flash$Enchant creature you control$Enchanted creature gets +1/+1 and has "Whenever this creature deals combat damage to a player, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost."| +Moku, Meandering Drummer|Avatar: The Last Airbender Eternal|122|U|{1}{R}|Legendary Creature - Human Bard Ally|2|2|Whenever you cast a noncreature spell, you may pay {1}. If you do, Moku gets +2/+1 and creatures you control gain haste until end of turn.| +Overwhelming Victory|Avatar: The Last Airbender Eternal|123|R|{4}{R}|Instant - Lesson|||Overwhelming Victory deals 5 damage to target creature. Each creature you control gains trample and gets +X/+0 until end of turn, where X is the amount of excess damage dealt this way.| +Reckless Blaze|Avatar: The Last Airbender Eternal|124|R|{3}{R}{R}|Sorcery - Lesson|||Reckless Blaze deals 5 damage to each creature. Whenever a creature you control dealt damage this way dies this turn, add {R}.| +Smellerbee, Rebel Fighter|Avatar: The Last Airbender Eternal|125|R|{3}{R}|Legendary Creature - Human Rebel Ally|3|3|First strike$Other creatures you control have haste.$Whenever Smellerbee attacks, you may discard your hand. If you do, draw cards equal to the number of attacking creatures.| +Storm of Memories|Avatar: The Last Airbender Eternal|126|R|{2}{R}{R}{R}|Sorcery|||Storm$Exile an instant or sorcery card with mana value 3 or less from your graveyard at random. You may cast it without paying its mana cost. If that spell would be put into a graveyard, exile it instead.| Zuko, Firebending Master|Avatar: The Last Airbender Eternal|127|M|{1}{R}|Legendary Creature - Human Noble Ally|2|2|First strike$Firebending X, where X is the number of experience counters you have.$Whenever you cast a spell during combat, you get an experience counter.| +Animal Attendant|Avatar: The Last Airbender Eternal|128|U|{1}{G}|Creature - Human Citizen|2|2|{T}: Add one mana of any color. If that mana is spent to cast a non-Human creature spell, that creature enters with an additional +1/+1 counter on it.| +The Art of Tea|Avatar: The Last Airbender Eternal|129|C|{1}{G}|Instant - Lesson|||Put a +1/+1 counter on up to one target creature you control. Create a Food token.| Avatar Kyoshi, Earthbender|Avatar: The Last Airbender Eternal|130|M|{5}{G}{G}{G}|Legendary Creature - Human Avatar|6|6|During your turn, Avatar Kyoshi has hexproof.$At the beginning of combat on your turn, earthbend 8, then untap that land.| +Bison Whistle|Avatar: The Last Airbender Eternal|131|R|{1}{G}|Artifact|||{1}, {T}: Look at the top card of your library. If it's a Bison card, you may put it onto the battlefield. If it's a creature card, you may reveal it and put it into your hand. Otherwise, you may put it into your$graveyard.| +Bosco, Just a Bear|Avatar: The Last Airbender Eternal|132|U|{4}{G}|Legendary Creature - Bear|4|4|When Bosco enters, create a Food token for each legendary creature you control.${2}{G}, Sacrifice a Food: Put two +1/+1 counters on Bosco. He gains trample until end of turn.| +Bumi's Feast Lecture|Avatar: The Last Airbender Eternal|133|U|{1}{G}|Sorcery - Lesson|||Create a Food token. Then earthbend X, where X is twice the number of Foods you control.| The Cabbage Merchant|Avatar: The Last Airbender Eternal|134|R|{2}{G}|Legendary Creature - Human Citizen|2|2|Whenever an opponent casts a noncreature spell, create a Food token.$Whenever a creature deals combat damage to you, sacrifice a Food token.$Tap two untapped Foods you control: Add one mana of any color.| +Cracked Earth Technique|Avatar: The Last Airbender Eternal|135|U|{4}{G}|Sorcery - Lesson|||Earthbend 3, then earthbend 3. You gain 3 life.| +Creeping Crystal Coating|Avatar: The Last Airbender Eternal|136|U|{2}{G}|Enchantment - Aura|||Flash$Enchant creature$Enchanted creature gets +0/+3 and has "Whenever this creature attacks, create a Food token."| +Crystalline Armor|Avatar: The Last Airbender Eternal|137|R|{3}{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +1/+1 for each land you control and has trample.| +Elephant-Mandrill|Avatar: The Last Airbender Eternal|138|U|{2}{G}|Creature - Elephant Monkey|3|2|Reach$When this creature enters, each player creates a Food token.$At the beginning of combat on your turn, this creature gets +1/+1 until end of turn for each artifact your opponents control.| Hei Bai, Forest Guardian|Avatar: The Last Airbender Eternal|139|M|{3}{G}|Legendary Creature - Bear Spirit|4|4|When Hei Bai enters, reveal cards from the top of your library until you reveal a Shrine card. You may put that card onto the battlefield. Then shuffle.${W}{U}{B}{R}{G}, {T}: For each legendary enchantment you control, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."| +Kyoshi Warrior Exemplars|Avatar: The Last Airbender Eternal|140|U|{3}{G}|Creature - Human Warrior Ally|4|3|Whenever this creature attacks, if you control eight or more lands, creatures you control get +2/+2 until end of turn.| +Master's Guidance|Avatar: The Last Airbender Eternal|141|R|{2}{G}|Enchantment|||Whenever you attack with two or more legendary creatures, put a +1/+1 counter on each of up to two target attacking creatures.$At the beginning of your end step, if you control a creature with power 4 or greater, draw a card.| +Solid Ground|Avatar: The Last Airbender Eternal|142|U|{3}{G}|Enchantment|||When this enchantment enters, earthbend 3.$If one or more +1/+1 counters would be put on a permanent you control, that many plus one +1/+1 counters are put on it instead.| +Tale of Katara and Toph|Avatar: The Last Airbender Eternal|143|R|{2}{G}|Enchantment|||Creatures you control have "Whenever this creature becomes tapped for the first time during each of your turns, put a +1/+1 counter on it."| +Tectonic Split|Avatar: The Last Airbender Eternal|144|R|{4}{G}{G}|Enchantment|||As an additional cost to cast this spell, sacrifice half the lands you control, rounded up.$Hexproof$Lands you control have "{T}: Add three mana of any one color."| Toph, Earthbending Master|Avatar: The Last Airbender Eternal|145|M|{3}{G}|Legendary Creature - Human Warrior Ally|2|4|Landfall -- Whenever a land you control enters, you get an experience counter.$Whenever you attack, earthbend X, where X is the number of experience counters you have.| +Aang, A Lot to Learn|Avatar: The Last Airbender Eternal|146|U|{2}{G/W}|Legendary Creature - Human Avatar Ally|3|2|Aang has vigilance as long as there's a Lesson card in your graveyard.$Whenever another creature you control dies, put a +1/+1 counter on Aang.| +Hook Swords|Avatar: The Last Airbender Eternal|147|U|{2}{R/W}|Artifact - Equipment|||When this Equipment enters, create a 1/1 white Ally creature token, then attach this Equipment to it.$During your turn, equipped creature gets +1/+1 and has first strike.$Equip {3}| +Katara, Seeking Revenge|Avatar: The Last Airbender Eternal|148|U|{3}{U/B}|Legendary Creature - Human Warrior Ally|3|3|As an additional cost to cast this spell, you may waterbend {2}.$When Katara enters, draw a card, then discard a card unless her additional cost was paid.$Katara gets +1/+1 for each Lesson card in your graveyard.| +Stand United|Avatar: The Last Airbender Eternal|149|C|{1}{G/W}|Instant|||Target creature gets +2/+2 until end of turn. If it's an Ally, scry 2.| +Zuko, Seeking Honor|Avatar: The Last Airbender Eternal|150|U|{2}{B/R}|Legendary Creature - Human Noble|2|2|Firebending 1$Whenever you cast a noncreature spell, Zuko gains first strike until end of turn.$Whenever Zuko deals combat damage to a player, put a +1/+1 counter on him.| +Acrobatic Leap|Avatar: The Last Airbender Eternal|151|C|{W}|Instant|||Target creature gets +1/+3 and gains flying until end of turn. Untap it.| +Cloudshift|Avatar: The Last Airbender Eternal|152|C|{W}|Instant|||Exile target creature you control, then return that card to the battlefield under your control.| +Duelist's Heritage|Avatar: The Last Airbender Eternal|153|R|{2}{W}|Enchantment|||Whenever one or more creatures attack, you may have target attacking creature gain double strike until end of turn.| +Valorous Stance|Avatar: The Last Airbender Eternal|154|U|{1}{W}|Instant|||Choose one --$* Target creature gains indestructible until end of turn.$* Destroy target creature with toughness 4 or greater.| +Brainstorm|Avatar: The Last Airbender Eternal|155|C|{U}|Instant|||Draw three cards, then put two cards from your hand on top of your library in any order.| +Coastal Piracy|Avatar: The Last Airbender Eternal|156|U|{2}{U}{U}|Enchantment|||Whenever a creature you control deals combat damage to an opponent, you may draw a card.| +Consider|Avatar: The Last Airbender Eternal|157|C|{U}|Instant|||Surveil 1.$Draw a card.| +Dramatic Reversal|Avatar: The Last Airbender Eternal|158|C|{1}{U}|Instant|||Untap all nonland permanents you control.| +Frantic Search|Avatar: The Last Airbender Eternal|159|C|{2}{U}|Instant|||Draw two cards, then discard two cards. Untap up to three lands.| +Bastion of Remembrance|Avatar: The Last Airbender Eternal|160|U|{2}{B}|Enchantment|||When this enchantment enters, create a 1/1 white Human Soldier creature token.$Whenever a creature you control dies, each opponent loses 1 life and you gain 1 life.| +Dark Deal|Avatar: The Last Airbender Eternal|161|U|{2}{B}|Sorcery|||Each player discards all the cards in their hand, then draws that many cards minus one.| +Diresight|Avatar: The Last Airbender Eternal|162|C|{2}{B}|Sorcery|||Surveil 2, then draw two cards. You lose 2 life.| +Bolt Bend|Avatar: The Last Airbender Eternal|163|U|{3}{R}|Instant|||This spell costs {3} less to cast if you control a creature with power 4 or greater.$Change the target of target spell or ability with a single target.| +Cathartic Reunion|Avatar: The Last Airbender Eternal|164|C|{1}{R}|Sorcery|||As an additional cost to cast this spell, discard two cards.$Draw three cards.| Fiery Confluence|Avatar: The Last Airbender Eternal|165|R|{2}{R}{R}|Sorcery|||Choose three. You may choose the same mode more than once.$* Fiery Confluence deals 1 damage to each creature.$* Fiery Confluence deals 2 damage to each opponent.$* Destroy target artifact.| +Fists of Flame|Avatar: The Last Airbender Eternal|166|C|{1}{R}|Instant|||Draw a card. Until end of turn, target creature gains trample and gets +1/+0 for each card you've drawn this turn.| Descendants' Path|Avatar: The Last Airbender Eternal|167|R|{2}{G}|Enchantment|||At the beginning of your upkeep, reveal the top card of your library. If it's a creature card that shares a creature type with a creature you control, you may cast it without paying its mana cost. If you don't cast it, put it on the bottom of your library.| +Inspiring Call|Avatar: The Last Airbender Eternal|168|U|{2}{G}|Instant|||Draw a card for each creature you control with a +1/+1 counter on it. Those creatures gain indestructible until end of turn.| +Many Partings|Avatar: The Last Airbender Eternal|169|C|{G}|Sorcery|||Search your library for a basic land card, reveal it, put it into your hand, then shuffle. Create a Food token.| +Suspicious Bookcase|Avatar: The Last Airbender Eternal|170|U|{2}|Artifact Creature - Wall|0|4|Defender${3}, {T}: Target creature can't be blocked this turn.| Aang, Air Nomad|Avatar: The Last Airbender Eternal|210|R|{3}{W}{W}|Legendary Creature - Human Avatar Ally|5|4|Flying$Vigilance$Other creatures you control have vigilance.| Aang's Defense|Avatar: The Last Airbender Eternal|211|C|{W}|Instant|||Target blocking creature you control gets +2/+2 until end of turn.$Draw a card.| Aardvark Sloth|Avatar: The Last Airbender Eternal|212|C|{3}{W}|Creature - Sloth Beast|3|3|Lifelink| @@ -60614,6 +60680,16 @@ Plains|Avatar: The Last Airbender Eternal|301|C||Basic Land - Plains|||({T}: Add Plains|Avatar: The Last Airbender Eternal|302|C||Basic Land - Plains|||({T}: Add {W}.)| Plains|Avatar: The Last Airbender Eternal|303|C||Basic Land - Plains|||({T}: Add {W}.)| Plains|Avatar: The Last Airbender Eternal|304|C||Basic Land - Plains|||({T}: Add {W}.)| +Enlightened Tutor|Avatar: The Last Airbender Eternal|305|R|{W}|Instant|||Search your library for an artifact or enchantment card, reveal it, then shuffle and put that card on top.| +Flawless Maneuver|Avatar: The Last Airbender Eternal|306|R|{2}{W}|Instant|||If you control a commander, you may cast this spell without paying its mana cost.$Creatures you control gain indestructible until end of turn.| +Fierce Guardianship|Avatar: The Last Airbender Eternal|307|R|{2}{U}|Instant|||If you control a commander, you may cast this spell without paying its mana cost.$Counter target noncreature spell.| +Mystical Tutor|Avatar: The Last Airbender Eternal|308|R|{U}|Instant|||Search your library for an instant or sorcery card, reveal it, then shuffle and put that card on top.| +Deadly Rollick|Avatar: The Last Airbender Eternal|309|R|{3}{B}|Instant|||If you control a commander, you may cast this spell without paying its mana cost.$Exile target creature.| +Entomb|Avatar: The Last Airbender Eternal|310|R|{B}|Instant|||Search your library for a card, put that card into your graveyard, then shuffle.| +Deflecting Swat|Avatar: The Last Airbender Eternal|311|R|{2}{R}|Instant|||If you control a commander, you may cast this spell without paying its mana cost.$You may choose new targets for target spell or ability.| +Gamble|Avatar: The Last Airbender Eternal|312|R|{R}|Sorcery|||Search your library for a card, put that card into your hand, discard a card at random, then shuffle.| +Obscuring Haze|Avatar: The Last Airbender Eternal|313|R|{2}{G}|Instant|||If you control a commander, you may cast this spell without paying its mana cost.$Prevent all damage that would be dealt this turn by creatures your opponents control.| +Worldly Tutor|Avatar: The Last Airbender Eternal|314|R|{G}|Instant|||Search your library for a creature card, reveal it, then shuffle and put the card on top.| Arcane Signet|Avatar: The Last Airbender Eternal|315|R|{2}|Artifact|||{T}: Add one mana of any color in your commander's color identity.| Sol Ring|Avatar: The Last Airbender Eternal|316|R|{1}|Artifact|||{T}: Add {C}{C}.| Swiftfoot Boots|Avatar: The Last Airbender Eternal|317|R|{2}|Artifact - Equipment|||Equipped creature has hexproof and haste.$Equip {1}| -- 2.47.2 From fbf6fe6ae6c1ec2105c11f5e9fabc10885890ed0 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 19:08:18 -0500 Subject: [PATCH 121/261] [TLA] update spoiler --- Utils/mtg-cards-data.txt | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 23dca0a4c22..42a7285ef00 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59766,6 +59766,7 @@ Zuko's Exile|Avatar: The Last Airbender|3|C|{5}|Instant - Lesson|||Exile target Aang, the Last Airbender|Avatar: The Last Airbender|4|U|{3}{W}|Legendary Creature - Human Avatar Ally|3|2|Flying$When Aang enters, airbend up to one other target nonland permanent.$Whenever you cast a Lesson spell, Aang gains lifelink until end of turn.| Aang's Iceberg|Avatar: The Last Airbender|5|R|{2}{W}|Enchantment|||Flash$When this enchantment enters, exile up to one other target nonland permanent until this enchantment leaves the battlefield.$Waterbend {3}: Sacrifice this enchantment. If you do, scry 2.| Airbender Ascension|Avatar: The Last Airbender|6|R|{1}{W}|Enchantment|||When this enchantment enters, airbend up to one target creature.$Whenever a creature you control enters, put a quest counter on this enchantment.$At the beginning of your end step, if this enchantment has four or more quest counters on it, exile up to one target creature you control, then return it to the battlefield under its owner's control.| +Airbender's Reversal|Avatar: The Last Airbender|7|U|{1}{W}|Instant - Lesson|||Choose one --$* Destroy target attacking creature.$* Airbend target creature you control.| Airbending Lesson|Avatar: The Last Airbender|8|C|{2}{W}|Instant - Lesson|||Airbend target nonland permanent.$Draw a card.| Appa, Loyal Sky Bison|Avatar: The Last Airbender|9|U|{4}{W}{W}|Legendary Creature - Bison Ally|4|4|Flying$Whenever Appa enters or attacks, choose one --$* Target creature you control gains flying until end of turn.$* Airbend another target nonland permanent you control..| Appa, Steadfast Guardian|Avatar: The Last Airbender|10|M|{2}{W}{W}|Legendary Creature - Bison Ally|3|4|Flash$Flying$When Appa enters, airbend any number of other target nonland permanents you control.$Whenever you cast a spell from exile, create a 1/1 white Ally creature token.| @@ -59856,6 +59857,7 @@ Foggy Swamp Hunters|Avatar: The Last Airbender|101|C|{3}{B}|Creature - Human Ran Foggy Swamp Visions|Avatar: The Last Airbender|102|R|{1}{B}{B}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Exile X target creature cards from graveyards. For each creature card exiled this way, create a token that's a copy of it. At the beginning of your next end step, sacrifice those tokens.| Heartless Act|Avatar: The Last Airbender|103|U|{1}{B}|Instant|||Choose one --$* Destroy target creature with no counters on it.$* Remove up to three counters from target creature.| Hog-Monkey|Avatar: The Last Airbender|104|C|{2}{B}|Creature - Boar Monkey|3|2|At the beginning of combat on your turn, target creature you control with a +1/+1 counter on it gains menace until end of turn.$Exhaust -- {5}: Put two +1/+1 counters on this creature.| +Joo Dee, One of Many|Avatar: The Last Airbender|105|U|{1}{B}|Creature - Human Advisor|2|2|{B}, {T}: Surveil 1. Create a token that's a copy of this creature, then sacrifice an artifact or creature. Activate only as a sorcery.| June, Bounty Hunter|Avatar: The Last Airbender|106|U|{1}{B}|Legendary Creature - Human Mercenary|2|2|June can't be blocked as long as you've drawn two or more cards this turn.${1}, Sacrifice another creature: Create a Clue token. Activate only during your turn.| Mai, Scornful Striker|Avatar: The Last Airbender|109|R|{1}{B}|Legendary Creature - Human Noble Ally|2|2|First strike$Whenever a player casts a noncreature spell, they lose 2 life.| Merchant of Many Hats|Avatar: The Last Airbender|110|C|{1}{B}|Creature - Human Peasant Ally|2|2|{2}{B}: Return this card from your graveyard to your hand.| @@ -59905,6 +59907,7 @@ Twin Blades|Avatar: The Last Airbender|157|U|{2}{R}|Artifact - Equipment|||Flash Ty Lee, Artful Acrobat|Avatar: The Last Airbender|158|U|{2}{R}|Legendary Creature - Human Performer|3|2|Prowess$Whenever Ty Lee attacks, you may pay {1}. When you do, target creature can't block this turn.| War Balloon|Avatar: The Last Airbender|159|U|{2}{R}|Artifact - Vehicle|4|3|Flying${1}: Put a fire counter on this Vehicle.$As long as this Vehicle has three or more fire counters on it, it's an artifact creature.$Crew 3| Yuyan Archers|Avatar: The Last Airbender|161|C|{1}{R}|Creature - Human Archer|3|1|Reach$When this creature enters, you may discard a card. If you do, draw a card.| +Zhao, the Moon Slayer|Avatar: The Last Airbender|162|R|{1}{R}|Legendary Creature - Human Soldier|2|2|Menace$Nonbasic lands enter tapped.${7}: Put a conqueror counter on Zhao.$As long as Zhao has a conqueror counter on him, nonbasic lands are Mountains.| Zuko, Exiled Prince|Avatar: The Last Airbender|163|U|{3}{R}|Legendary Creature - Human Noble|4|3|Firebending 3${3}: Exile the top card of your library. You may play that card this turn.| Allies at Last|Avatar: The Last Airbender|164|U|{2}{G}|Instant|||Affinity for Allies$Up to two target creatures you control each deal damage equal to their power to target creature an opponent controls.| Avatar Destiny|Avatar: The Last Airbender|165|R|{2}{G}{G}|Enchantment - Aura|||Enchant creature you control$Enchanted creature gets +1/+1 for each creature card in your graveyard and is an Avatar in addition to its other types.$When enchanted creature dies, mill cards equal to its power. Return this card to its owner's hand and up to one creature card milled this way to the battlefield under your control.| @@ -59919,13 +59922,16 @@ Earth Kingdom General|Avatar: The Last Airbender|173|U|{3}{G}|Creature - Human S Earth Rumble|Avatar: The Last Airbender|174|U|{3}{G}|Sorcery|||Earthbend 2. When you do, up to one target creature you control fights target creature an opponent controls.| Earthbender Ascension|Avatar: The Last Airbender|175|R|{2}{G}|Enchantment|||When this enchantment enters, earthbend 2. Then search your library for a basic land card, put it onto the battlefield tapped, then shuffle.$Landfall -- Whenever a land you control enters, put a quest counter on this enchantment. When you do, if it has four or more quest counters on it, put a +1/+1 counter on target creature you control. It gains trample until end of turn.| Earthbending Lesson|Avatar: The Last Airbender|176|C|{3}{G}|Sorcery - Lesson|||Earthbend 4.| +Earthen Ally|Avatar: The Last Airbender|177|R|{G}|Creature - Human Soldier Ally|0|2|This creature gets +1/+0 for each color among Allies you control.${2}{W}{U}{B}{R}{G}: Earthbend 5.| Elemental Teachings|Avatar: The Last Airbender|178|R|{4}{G}|Instant - Lesson|||Search your library for up to four land cards with different names and reveal them. An opponent chooses two of those cards. Put the chosen cards into your graveyard and the rest onto the battlefield tapped, then shuffle.| Flopsie, Bumi's Buddy|Avatar: The Last Airbender|179|U|{4}{G}{G}|Legendary Creature - Ape Goat|4|4|When Flopsie enters, put a +1/+1 counter on each creature you control.$Each creature you control with power 4 or greater can't be blocked by more than one creature.| -Great Divide Guide|Avatar: The Last Airbender|181|R|{1}{G}|Creature - Human Scout Ally|2|3|Each land and Ally you control has 66 : Add one mana of any color."| +Great Divide Guide|Avatar: The Last Airbender|181|R|{1}{G}|Creature - Human Scout Ally|2|3|Each land and Ally you control has "{T}: Add one mana of any color."| Haru, Hidden Talent|Avatar: The Last Airbender|182|U|{1}{G}|Legendary Creature - Human Peasant Ally|1|1|Whenever another Ally you control enters, earthbend 1.| Invasion Tactics|Avatar: The Last Airbender|183|U|{4}{G}|Enchantment|||When this enchantment enters, creatures you control get +2/+2 until end of turn.$Whenever one or more Allies you control deal combat damage to a player, draw a card.| Kyoshi Island Plaza|Avatar: The Last Airbender|184|U|{3}{G}|Legendary Enchantment - Shrine|||When Kyoshi Island Plaza enters, search your library for up to X basic land cards, where X is the number of Shrines you control. Put those cards onto the battlefield tapped, then shuffle.$Whenever another Shrine you control enters, search your library for a basic land card, put it onto the battlefield tapped, then shuffle.| Leaves from the Vine|Avatar: The Last Airbender|185|U|{1}{G}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I -- Mill three cards, then create a Food token.$II -- Put a +1/+1 counter on each of up to two target creatures you control.$III -- Draw a card if there's a creature or Lesson card in your graveyard.| +The Legend of Kyoshi|Avatar: The Last Airbender|186|M|{4}{G}{G}|Enchantment - Saga|||(As this Saga enters and after your draw$step, add a lore counter.)$I -- Draw cards equal to the greatest power among creatures you control.$II -- Earthbend X, where X is the number of cards in your hand. That land becomes an Island in addition to its other types.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| +Avatar Kyoshi|Avatar: The Last Airbender|186|M||Legendary Creature - Avatar|5|4|Lands you control have trample and hexproof.${T}: Add X mana of any one color, where X is the greatest power among creatures you control.| Origin of Metalbending|Avatar: The Last Airbender|187|C|{1}{G}|Instant - Lesson|||Choose one --$* Destroy target artifact or enchantment.$* Put a +1/+1 counter on target creature you control. It gains indestructible until end of turn.| Ostrich-Horse|Avatar: The Last Airbender|188|C|{2}{G}|Creature - Bird Horse|3|1|When this creature enters, mill three cards. You may put a land card from among them into your hand. If you don't, put a +1/+1 counter on this creature.| Pillar Launch|Avatar: The Last Airbender|189|C|{G}|Instant|||Target creature gets +2/+2 and gains reach until end of turn. Untap it.| @@ -59967,6 +59973,7 @@ Foggy Swamp Spirit Keeper|Avatar: The Last Airbender|222|U|{1}{U}{B}|Creature - Guru Pathik|Avatar: The Last Airbender|223|U|{2}{G/U}{G/U}|Legendary Creature - Human Monk Ally|2|4|When Guru Pathik enters, look at the top five cards of your library. You may reveal a Lesson, Saga, or Shrine card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.$Whenever you cast a Lesson, Saga, or Shrine spell, put a +1/+1 counter on another target creature you control.| Hama, the Bloodbender|Avatar: The Last Airbender|224|U|{2}{U/B}{U/B}{U/B}|Legendary Creature - Human Warlock|3|3|When Hama enters, target opponent mills three cards. Exile up to one noncreature, nonland card from that player's graveyard. For as long as you control Hama, you may cast the exiled card during your turn by waterbending {X} rather than paying its mana cost, where X is its mana value.| Hei Bai, Spirit of Balance|Avatar: The Last Airbender|225|U|{2}{W/B}{W/B}|Legendary Creature - Bear Spirit|3|3|Whenever Hei Bai enters or attacks, you may sacrifice another creature or artifact. If you do, put two +1/+1 counters on Hei Bai.$When Hei Bai leaves the battlefield, put its counters on target creature you control.| +Hermitic Herbalist|Avatar: The Last Airbender|226|U|{G}{U}|Creature - Human Druid Ally|2|3|{T}: Add one mana of any color.${T}: Add two mana in any combination of colors. Spend this mana only to cast Lesson spells.| Iroh, Grand Lotus|Avatar: The Last Airbender|227|R|{3}{G}{U}{R}|Legendary Creature - Human Noble Ally|5|5|Firebending 2$During your turn, each non-Lesson instant and sorcery card in your graveyard has flashback. The flashback cost is equal to that card's mana cost.$During your turn, each Lesson card in your graveyard has flashback {1}.| Iroh, Tea Master|Avatar: The Last Airbender|228|R|{1}{R}{W}|Legendary Creature - Human Citizen Ally|2|2|When Iroh enters, create a Food token.$At the beginning of combat on your turn, you may have target opponent gain control of target permanent you control. When you do, create a 1/1 white Ally creature token. Put a +1/+1 counter on that token for each permanent you own that your opponents control.| Jet, Freedom Fighter|Avatar: The Last Airbender|229|U|{2}{R/W}{R/W}{R/W}|Legendary Creature - Human Rebel Ally|3|1|When Jet enters, he deals damage equal to the number of creatures you control to target creature an opponent controls.$When Jet dies, put a +1/+1 counter on each of up to two target creatures.| @@ -59994,11 +60001,14 @@ Zuko, Conflicted|Avatar: The Last Airbender|253|R|{B}{R}|Legendary Creature - Hu Barrels of Blasting Jelly|Avatar: The Last Airbender|254|C|{1}|Artifact|||{1}: Add one mana of any color. Activate only once each turn.${5}, {T}, Sacrifice this artifact: It deals 5 damage to target creature.| Bender's Waterskin|Avatar: The Last Airbender|255|C|{3}|Artifact|||Untap this artifact during each other player's untap step.${T}: Add one mana of any color.| Fire Nation Warship|Avatar: The Last Airbender|256|U|{3}|Artifact - Vehicle|4|4|Reach$When this Vehicle dies, create a Clue token.$Crew 2| +Kyoshi Battle Fan|Avatar: The Last Airbender|257|C|{2}|Artifact - Equipment|||When this Equipment enters, create a 1/1 white Ally creature token, then attach this Equipment to it.$Equipped creature gets +1/+0.$Equip {2}| Planetarium of Wan Shi Tong|Avatar: The Last Airbender|259|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| Trusty Boomerang|Avatar: The Last Airbender|260|U|{1}|Artifact - Equipment|||Equipped creature has "{1}, {T}: Tap target creature. Return Trusty Boomerang to its owner's hand."$Equip {1}| +The Walls of Ba Sing Se|Avatar: The Last Airbender|261|M|{8}|Legendary Artifact Creature - Wall|0|30|Defender$Other permanents you control have indestructible.| White Lotus Tile|Avatar: The Last Airbender|262|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| Agna Qel'a|Avatar: The Last Airbender|264|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {U}.${2}{U}, {T}: Draw a card, then discard a card.| Airship Engine Room|Avatar: The Last Airbender|265|C||Land|||This land enters tapped.${T}: Add {U} or {R}.${4}, {T}, Sacrifice this land: Draw a card.| +Ba Sing Se|Avatar: The Last Airbender|266|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {G}.${2}{G}, {T}: Earthbend 2. Activate only as a sorcery.| Boiling Rock Prison|Avatar: The Last Airbender|267|C||Land|||This land enters tapped.${T}: Add {B} or {R}.${4}, {T}, Sacrifice this land: Draw a card.| Fire Nation Palace|Avatar: The Last Airbender|268|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {R}.${1}{R}, {T}: Target creature you control gains firebending 4 until end of turn.| Foggy Bottom Swamp|Avatar: The Last Airbender|269|C||Land|||This land enters tapped.${T}: Add {B} or {G}.${4}, {T}, Sacrifice this land: Draw a card.| @@ -60059,6 +60069,7 @@ Ran and Shaw|Avatar: The Last Airbender|325|R|{3}{R}{R}|Legendary Creature - Dra Badgermole Cub|Avatar: The Last Airbender|326|M|{1}{G}|Creature - Badger Mole|2|2|When this creature enters, earthbend 1.$Whenever you tap a creature for mana, add an additional {G}.| Diligent Zookeeper|Avatar: The Last Airbender|327|R|{3}{G}|Creature - Human Citizen Ally|4|4|Each non-Human creature you control gets +1/+1 for each of its creature types, to a maximum of 10.| The Lion-Turtle|Avatar: The Last Airbender|328|R|{1}{G}{U}|Legendary Creature - Elder Cat Turtle|3|6|Vigilance, reach$When The Lion-Turtle enters, you gain 3 life.$The Lion-Turtle can't attack or block unless there are three or more Lesson cards in your graveyard.${T}: Add one mana of any color.| +The Walls of Ba Sing Se|Avatar: The Last Airbender|329|M|{8}|Legendary Artifact Creature - Wall|0|30|Defender$Other permanents you control have indestructible.| White Lotus Tile|Avatar: The Last Airbender|330|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| United Front|Avatar: The Last Airbender|331|M|{X}{W}{W}|Sorcery|||Create X 1/1 white Ally creature tokens, then put a +1/+1 counter on each creature you control.| Sozin's Comet|Avatar: The Last Airbender|332|M|{3}{R}{R}|Sorcery|||Each creature you control gains firebending 5 until end of turn.$Foretell {2}{R}| @@ -60074,7 +60085,7 @@ Fated Firepower|Avatar: The Last Airbender|341|M|{X}{R}{R}{R}|Enchantment|||Flas Firebending Student|Avatar: The Last Airbender|342|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| Redirect Lightning|Avatar: The Last Airbender|343|R|{R}|Instant - Lesson|||As an additional cost to cast this spell, pay 5 life or pay {2}.$Change the target of target spell or ability with a single target.| The Earth King|Avatar: The Last Airbender|344|R|{3}{G}|Legendary Creature - Human Noble Ally|2|2|When The Earth King enters, create a 4/4 green Bear creature token.$Whenever one or more creatures you control with power 4 or greater attack, search your library for up to that many basic land cards, put them onto the battlefield tapped, then shuffle.| -Great Divide Guide|Avatar: The Last Airbender|345|R|{1}{G}|Creature - Human Scout Ally|2|3|Each land and Ally you control has 66 : Add one mana of any color."| +Great Divide Guide|Avatar: The Last Airbender|345|R|{1}{G}|Creature - Human Scout Ally|2|3|Each land and Ally you control has "{T}: Add one mana of any color."| Aang, at the Crossroads|Avatar: The Last Airbender|346|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| Aang, Destined Savior|Avatar: The Last Airbender|346|R||Legendary Creature - Avatar Ally|4|4|Flying$Land creatures you control have vigilance.$At the beginning of combat on your turn, earthbend 2.| Aang, Swift Savior|Avatar: The Last Airbender|347|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| @@ -60093,6 +60104,8 @@ The Rise of Sozin|Avatar: The Last Airbender|356|M|{4}{B}{B}|Enchantment - Saga| Fire Lord Sozin|Avatar: The Last Airbender|356|M||Legendary Creature - Human Noble|5|5|Menace, firebending 3$Whenever Fire Lord Sozin deals combat damage to a player, you may pay {X}. When you do, put any number of target creature cards with total mana value X or less from that player's graveyard onto the battlefield under your control.| The Legend of Roku|Avatar: The Last Airbender|357|M|{2}{R}{R}|Enchantment - Saga|||(As this Saga enters and after your draw$step, add a lore counter.)$I -- Exile the top three cards of your library. Until the end of your next turn, you may play those cards.$II -- Add one mana of any color.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| Avatar Roku|Avatar: The Last Airbender|357|M||Legendary Creature - Avatar|4|4|Firebending 4${8}: Create a 4/4 red Dragon creature token with flying and firebending 4.| +The Legend of Kyoshi|Avatar: The Last Airbender|358|M|{4}{G}{G}|Enchantment - Saga|||(As this Saga enters and after your draw$step, add a lore counter.)$I -- Draw cards equal to the greatest power among creatures you control.$II -- Earthbend X, where X is the number of cards in your hand. That land becomes an Island in addition to its other types.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| +Avatar Kyoshi|Avatar: The Last Airbender|358|M||Legendary Creature - Avatar|5|4|Lands you control have trample and hexproof.${T}: Add X mana of any one color, where X is the greatest power among creatures you control.| Aang, Swift Savior|Avatar: The Last Airbender|359|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| Aang and La, Ocean's Fury|Avatar: The Last Airbender|359|R||Legendary Creature - Avatar Spirit Ally|5|5|Reach, trample$Whenever Aang and La attack, put a +1/+1 counter on each tapped creature you control.| Fire Lord Zuko|Avatar: The Last Airbender|360|R|{R}{W}{B}|Legendary Creature - Human Noble Ally|2|4|Firebending X, where X is Fire Lord Zuko's power.$Whenever you cast a spell from exile and whenever a permanent you control enters from exile, put a +1/+1 counter on each creature you control.| @@ -60110,6 +60123,7 @@ Ty Lee, Chi Blocker|Avatar: The Last Airbender|371|R|{2}{U}|Legendary Creature - Boiling Rock Rioter|Avatar: The Last Airbender|372|R|{2}{B}|Creature - Human Rogue Ally|3|3|Firebending 1$Tap an untapped Ally you control: Exile target card from a graveyard.$Whenever this creature attacks, you may cast an Ally spell from among cards you own exiled with this creature.| Day of Black Sun|Avatar: The Last Airbender|373|R|{X}{B}{B}|Sorcery|||Each creature with mana value X or less loses all abilities until end of turn. Destroy those creatures.| Mai, Scornful Striker|Avatar: The Last Airbender|374|R|{1}{B}|Legendary Creature - Human Noble Ally|2|2|First strike$Whenever a player casts a noncreature spell, they lose 2 life.| +Earthen Ally|Avatar: The Last Airbender|377|R|{G}|Creature - Human Soldier Ally|0|2|This creature gets +1/+0 for each color among Allies you control.${2}{W}{U}{B}{R}{G}: Earthbend 5.| Elemental Teachings|Avatar: The Last Airbender|378|R|{4}{G}|Instant - Lesson|||Search your library for up to four land cards with different names and reveal them. An opponent chooses two of those cards. Put the chosen cards into your graveyard and the rest onto the battlefield tapped, then shuffle.| Beifong's Bounty Hunters|Avatar: The Last Airbender|379|R|{2}{B}{G}|Creature - Human Mercenary|4|4|Whenever a nonland creature you control dies, earthbend X, where X is that creature's power.| Earth King's Lieutenant|Avatar: The Last Airbender|380|R|{G}{W}|Creature - Human Soldier Ally|1|1|Trample$When this creature enters, put a +1/+1 counter on each other Ally creature you control.$Whenever another Ally you control enters, put a +1/+1 counter on this creature.| @@ -60117,6 +60131,7 @@ Iroh, Tea Master|Avatar: The Last Airbender|381|R|{1}{R}{W}|Legendary Creature - Sokka, Bold Boomeranger|Avatar: The Last Airbender|383|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.| Planetarium of Wan Shi Tong|Avatar: The Last Airbender|385|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| Agna Qel'a|Avatar: The Last Airbender|387|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {U}.${2}{U}, {T}: Draw a card, then discard a card.| +Ba Sing Se|Avatar: The Last Airbender|388|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {G}.${2}{G}, {T}: Earthbend 2. Activate only as a sorcery.| Fire Nation Palace|Avatar: The Last Airbender|389|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {R}.${1}{R}, {T}: Target creature you control gains firebending 4 until end of turn.| Jasmine Dragon Tea Shop|Avatar: The Last Airbender|390|R||Land|||{T}: Add {C}.${T}: Add one mana of any color. Spend this mana only to cast an Ally spell or activate an ability of an Ally source.${5}, {T}: Create a 1/1 white Ally creature token.| Secret Tunnel|Avatar: The Last Airbender|392|R||Land - Cave|||This land can't be blocked.${T}: Add {C}.${4}, {T}: Two target creatures you control that share a creature type can't be blocked this turn.| -- 2.47.2 From b77d6cd8fda7695c137a9a7ea02f55966c55b294 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 19:10:01 -0500 Subject: [PATCH 122/261] [TLA] Implement Kyoshi Battle Fan --- .../src/mage/cards/k/KyoshiBattleFan.java | 44 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 45 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/k/KyoshiBattleFan.java diff --git a/Mage.Sets/src/mage/cards/k/KyoshiBattleFan.java b/Mage.Sets/src/mage/cards/k/KyoshiBattleFan.java new file mode 100644 index 00000000000..624d4a13c56 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KyoshiBattleFan.java @@ -0,0 +1,44 @@ +package mage.cards.k; + +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.CreateTokenAttachSourceEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.AllyToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KyoshiBattleFan extends CardImpl { + + public KyoshiBattleFan(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + this.subtype.add(SubType.EQUIPMENT); + + // When this Equipment enters, create a 1/1 white Ally creature token, then attach this Equipment to it. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenAttachSourceEffect(new AllyToken()))); + + // Equipped creature gets +1/+0. + this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(1, 0))); + + // Equip {2} + this.addAbility(new EquipAbility(2)); + } + + private KyoshiBattleFan(final KyoshiBattleFan card) { + super(card); + } + + @Override + public KyoshiBattleFan copy() { + return new KyoshiBattleFan(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index cbe66dee69b..24ab25dbecc 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -154,6 +154,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Katara, the Fearless", 350, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, the Fearless", 361, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Knowledge Seeker", 60, Rarity.UNCOMMON, mage.cards.k.KnowledgeSeeker.class)); + cards.add(new SetCardInfo("Kyoshi Battle Fan", 257, Rarity.COMMON, mage.cards.k.KyoshiBattleFan.class)); cards.add(new SetCardInfo("Kyoshi Village", 271, Rarity.COMMON, mage.cards.k.KyoshiVillage.class)); cards.add(new SetCardInfo("Kyoshi Warriors", 26, Rarity.COMMON, mage.cards.k.KyoshiWarriors.class)); cards.add(new SetCardInfo("Leaves from the Vine", 185, Rarity.UNCOMMON, mage.cards.l.LeavesFromTheVine.class)); -- 2.47.2 From 69c018fd3f094f9eb3ef4e2b8c4821f228ad1e6f Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 19:11:01 -0500 Subject: [PATCH 123/261] [TLA] Implement The Walls of Ba Sing Se --- .../src/mage/cards/t/TheWallsOfBaSingSe.java | 49 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 51 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TheWallsOfBaSingSe.java diff --git a/Mage.Sets/src/mage/cards/t/TheWallsOfBaSingSe.java b/Mage.Sets/src/mage/cards/t/TheWallsOfBaSingSe.java new file mode 100644 index 00000000000..81469195cc6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheWallsOfBaSingSe.java @@ -0,0 +1,49 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheWallsOfBaSingSe extends CardImpl { + + public TheWallsOfBaSingSe(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{8}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.WALL); + this.power = new MageInt(0); + this.toughness = new MageInt(30); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // Other permanents you control have indestructible. + this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( + IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield, + StaticFilters.FILTER_PERMANENTS, true + ))); + } + + private TheWallsOfBaSingSe(final TheWallsOfBaSingSe card) { + super(card); + } + + @Override + public TheWallsOfBaSingSe copy() { + return new TheWallsOfBaSingSe(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 24ab25dbecc..36ab2678ee3 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -245,6 +245,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("The Spirit Oasis", 72, Rarity.UNCOMMON, mage.cards.t.TheSpiritOasis.class)); cards.add(new SetCardInfo("The Unagi of Kyoshi Island", 319, Rarity.RARE, mage.cards.t.TheUnagiOfKyoshiIsland.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Unagi of Kyoshi Island", 77, Rarity.RARE, mage.cards.t.TheUnagiOfKyoshiIsland.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Walls of Ba Sing Se", 261, Rarity.MYTHIC, mage.cards.t.TheWallsOfBaSingSe.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Walls of Ba Sing Se", 329, Rarity.MYTHIC, mage.cards.t.TheWallsOfBaSingSe.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tiger-Dillo", 155, Rarity.UNCOMMON, mage.cards.t.TigerDillo.class)); cards.add(new SetCardInfo("Tiger-Seal", 318, Rarity.RARE, mage.cards.t.TigerSeal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tiger-Seal", 75, Rarity.RARE, mage.cards.t.TigerSeal.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From cc9a7bafc3d676991daff5fe36d327b8fab95def Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 5 Nov 2025 19:12:20 -0500 Subject: [PATCH 124/261] [TLA] Implement Airbender's Reversal --- .../src/mage/cards/a/AirbendersReversal.java | 43 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 44 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AirbendersReversal.java diff --git a/Mage.Sets/src/mage/cards/a/AirbendersReversal.java b/Mage.Sets/src/mage/cards/a/AirbendersReversal.java new file mode 100644 index 00000000000..4175a1b20b4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AirbendersReversal.java @@ -0,0 +1,43 @@ +package mage.cards.a; + +import mage.abilities.Mode; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.keyword.AirbendTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetAttackingCreature; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AirbendersReversal extends CardImpl { + + public AirbendersReversal(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); + + this.subtype.add(SubType.LESSON); + + // Choose one -- + // * Destroy target attacking creature. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetAttackingCreature()); + + // * Airbend target creature you control. + this.getSpellAbility().addMode(new Mode(new AirbendTargetEffect()) + .addTarget(new TargetControlledCreaturePermanent())); + } + + private AirbendersReversal(final AirbendersReversal card) { + super(card); + } + + @Override + public AirbendersReversal copy() { + return new AirbendersReversal(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 36ab2678ee3..a4a643b9d89 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -35,6 +35,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Abandon Attachments", 205, Rarity.COMMON, mage.cards.a.AbandonAttachments.class)); cards.add(new SetCardInfo("Airbender Ascension", 364, Rarity.RARE, mage.cards.a.AirbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Airbender Ascension", 6, Rarity.RARE, mage.cards.a.AirbenderAscension.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Airbender's Reversal", 7, Rarity.UNCOMMON, mage.cards.a.AirbendersReversal.class)); cards.add(new SetCardInfo("Airbending Lesson", 8, Rarity.COMMON, mage.cards.a.AirbendingLesson.class)); cards.add(new SetCardInfo("Airship Engine Room", 265, Rarity.COMMON, mage.cards.a.AirshipEngineRoom.class)); cards.add(new SetCardInfo("Appa, Loyal Sky Bison", 9, Rarity.UNCOMMON, mage.cards.a.AppaLoyalSkyBison.class)); -- 2.47.2 From d41d9693b4721fb19b379ceb7d4422ef27e4695e Mon Sep 17 00:00:00 2001 From: Steven Knipe Date: Wed, 5 Nov 2025 21:25:19 -0800 Subject: [PATCH 125/261] Fix AzorsElocutors missing first ability --- Mage.Sets/src/mage/cards/a/AzorsElocutors.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/a/AzorsElocutors.java b/Mage.Sets/src/mage/cards/a/AzorsElocutors.java index 633d1c6f776..302d55090ac 100644 --- a/Mage.Sets/src/mage/cards/a/AzorsElocutors.java +++ b/Mage.Sets/src/mage/cards/a/AzorsElocutors.java @@ -44,6 +44,7 @@ public final class AzorsElocutors extends CardImpl { new WinGameSourceControllerEffect(), condition, "Then if {this} has five or more filibuster counters on it, you win the game" )); + this.addAbility(ability); // Whenever a source deals damage to you, remove a filibuster counter from Azor's Elocutors. this.addAbility(new AzorsElocutorsTriggeredAbility()); -- 2.47.2 From 93ebabf443ad10161abd913a8bf92ee25d5a4411 Mon Sep 17 00:00:00 2001 From: Steven Knipe Date: Wed, 5 Nov 2025 21:30:05 -0800 Subject: [PATCH 126/261] Fix IntPlusDynamicValue not modifying getMessage as well --- .../mage/abilities/dynamicvalue/IntPlusDynamicValue.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/IntPlusDynamicValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/IntPlusDynamicValue.java index 3742630a3ec..0b0d5ee9dbd 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/IntPlusDynamicValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/IntPlusDynamicValue.java @@ -36,14 +36,12 @@ public class IntPlusDynamicValue implements DynamicValue { @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(baseValue).append(" plus "); - return sb.append(value.toString()).toString(); + return baseValue + " plus " + value.toString(); } @Override public String getMessage() { - return value.getMessage(); + return baseValue + " plus " + value.getMessage(); } @Override -- 2.47.2 From 4494bdddbb7d92239593c0069fc707ac7436da25 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Fri, 7 Nov 2025 16:38:01 -0500 Subject: [PATCH 127/261] [TLA] Fix Fire Lord Azula. --- Mage.Sets/src/mage/cards/f/FireLordAzula.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Mage.Sets/src/mage/cards/f/FireLordAzula.java b/Mage.Sets/src/mage/cards/f/FireLordAzula.java index 4505fa07faa..fe4c32e9447 100644 --- a/Mage.Sets/src/mage/cards/f/FireLordAzula.java +++ b/Mage.Sets/src/mage/cards/f/FireLordAzula.java @@ -11,6 +11,8 @@ import mage.constants.SetTargetPointer; import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; import java.util.UUID; @@ -32,10 +34,7 @@ public final class FireLordAzula extends CardImpl { this.addAbility(new FirebendingAbility(2)); // Whenever you cast a spell while Fire Lord Azula is attacking, copy that spell. You may choose new targets for the copy. - this.addAbility(new SpellCastControllerTriggeredAbility( - new CopyStackObjectEffect("that spell"), - StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL - )); + this.addAbility(new FireLordAzulaAbility()); } private FireLordAzula(final FireLordAzula card) { @@ -47,3 +46,16 @@ public final class FireLordAzula extends CardImpl { return new FireLordAzula(this); } } + +class FireLordAzulaAbility extends SpellCastControllerTriggeredAbility { + + public FireLordAzulaAbility() { + super(new CopyStackObjectEffect("that spell"), StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL); + setTriggerPhrase("Whenever you cast a spell while Fire Lord Azula is attacking, "); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return game.getCombat().getAttackers().contains(getSourceId()) && super.checkTrigger(event, game); + } +} \ No newline at end of file -- 2.47.2 From a502ee94d5cc5c65854f0e925b7e10a5063dbd48 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Fri, 7 Nov 2025 18:40:45 -0500 Subject: [PATCH 128/261] [TLA] Implement Firebender Ascension Also implemented an OptionalOneShotEffect for ease of stapling together a mandatory effect and an optional effect on the same ability. --- .../src/mage/cards/f/FirebenderAscension.java | 133 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + .../decorator/OptionalOneShotEffect.java | 85 +++++++++++ 3 files changed, 220 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FirebenderAscension.java create mode 100644 Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java diff --git a/Mage.Sets/src/mage/cards/f/FirebenderAscension.java b/Mage.Sets/src/mage/cards/f/FirebenderAscension.java new file mode 100644 index 00000000000..cb6ef523762 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FirebenderAscension.java @@ -0,0 +1,133 @@ +package mage.cards.f; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.TriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.decorator.OptionalOneShotEffect; +import mage.abilities.effects.common.CopyStackObjectEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.DefenderAttackedEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.SoldierFirebendingToken; +import mage.game.stack.StackObject; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author Grath + */ +public final class FirebenderAscension extends CardImpl { + + public FirebenderAscension(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); + + // When this enchantment enters, create a 2/2 red Soldier creature token with firebending 1. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SoldierFirebendingToken()))); + + // Whenever a creature you control attacking causes a triggered ability of that creature to trigger, put a quest + // counter on this enchantment. Then if it has four or more quest counters on it, you may copy that ability. You + // may choose new targets for the copy. + this.addAbility(new FirebenderAscensionTriggeredAbility()); + } + + private FirebenderAscension(final FirebenderAscension card) { + super(card); + } + + @Override + public FirebenderAscension copy() { + return new FirebenderAscension(this); + } +} + +class FirebenderAscensionTriggeredAbility extends TriggeredAbilityImpl { + + private static final Condition condition = new SourceHasCounterCondition(CounterType.QUEST, 4); + + FirebenderAscensionTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.QUEST.createInstance(), true), false); + addEffect(new ConditionalOneShotEffect(new OptionalOneShotEffect(new CopyStackObjectEffect(), + "You may copy that ability. You may choose new targets for the copy."), condition, + "Then if it has four or more quest counters on it, you may copy that ability. You may choose new targets for the copy.")); + setTriggerPhrase("Whenever a creature you control attacking causes a triggered ability of that creature to trigger, "); + } + + private FirebenderAscensionTriggeredAbility(final FirebenderAscensionTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRIGGERED_ABILITY; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + StackObject stackObject = game.getStack().getStackObject(event.getTargetId()); + Permanent permanent = game.getPermanent(event.getSourceId()); + if (stackObject == null || permanent == null || !permanent.isCreature(game)) { + return false; // only creatures + } + if (this.getControllerId() != permanent.getControllerId()) { + return false; // only your creatures + } + Ability stackAbility = stackObject.getStackAbility(); + if (!stackAbility.isTriggeredAbility()) { + return false; + } + GameEvent triggerEvent = ((TriggeredAbility) stackAbility).getTriggerEvent(); + GameEvent.EventType eventType = triggerEvent.getType(); + if (triggerEvent == null || (eventType != GameEvent.EventType.ATTACKER_DECLARED && + eventType != GameEvent.EventType.DECLARED_ATTACKERS && + eventType != GameEvent.EventType.DEFENDER_ATTACKED)) { + return false; // only attacking triggers + } + switch (triggerEvent.getType()) { + case ATTACKER_DECLARED: + if (triggerEvent.getSourceId() != permanent.getId()) { + return false; + } // only triggered abilities of that creature + break; + case DECLARED_ATTACKERS: + if (game + .getCombat() + .getAttackers() + .stream() + .noneMatch(permanent.getId()::equals)) { + return false; + } // only if the creature was one of the attackers that were declared + // This might give some false positives? + break; + case DEFENDER_ATTACKED: + if (((DefenderAttackedEvent) triggerEvent) + .getAttackers(game) + .stream() + .noneMatch(permanent::equals)) { + return false; + } // only if the creature was one of the attackers that were declared + // This might give some false positives? + } + getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game)); + return true; + } + + @Override + public FirebenderAscensionTriggeredAbility copy() { + return new FirebenderAscensionTriggeredAbility(this); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index a4a643b9d89..749609032a9 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -110,6 +110,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Fire Nation Raider", 135, Rarity.COMMON, mage.cards.f.FireNationRaider.class)); cards.add(new SetCardInfo("Fire Nation Warship", 256, Rarity.UNCOMMON, mage.cards.f.FireNationWarship.class)); cards.add(new SetCardInfo("Fire Sages", 136, Rarity.UNCOMMON, mage.cards.f.FireSages.class)); + cards.add(new SetCardInfo("Firebender Ascension", 137, Rarity.RARE, mage.cards.f.FirebenderAscension.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Firebender Ascension", 312, Rarity.RARE, mage.cards.f.FirebenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Firebending Student", 139, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Firebending Student", 342, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Firebending Student", 393, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java b/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java new file mode 100644 index 00000000000..c4d59047de3 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java @@ -0,0 +1,85 @@ +package mage.abilities.decorator; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.Effects; +import mage.abilities.effects.OneShotEffect; +import mage.game.Game; +import mage.players.Player; +import mage.target.targetpointer.TargetPointer; +import mage.util.CardUtil; + +/** + * Adds condition to {@link OneShotEffect}. Acts as decorator. + * + * @author Grath + */ +public class OptionalOneShotEffect extends OneShotEffect { + + private final Effects effects = new Effects(); + + public OptionalOneShotEffect(OneShotEffect effect, String text) { + super(effect.getOutcome()); + if (effect != null) { + this.effects.add(effect); + } + this.staticText = text; + } + + protected OptionalOneShotEffect(final OptionalOneShotEffect effect) { + super(effect); + this.effects.addAll(effect.effects.copy()); + } + + @Override + public boolean apply(Game game, Ability source) { + // nothing to do - no problem + if (effects.isEmpty()) { + return true; + } + Player player = game.getPlayer(source.getControllerId()); + if (player != null && player.chooseUse(outcome, staticText, source, game)) { + effects.setTargetPointer(this.getTargetPointer().copy()); + effects.forEach(effect -> effect.apply(game, source)); + return true; + } + return false; + } + + public OptionalOneShotEffect addEffect(OneShotEffect effect) { + this.effects.add(effect); + return this; + } + + @Override + public void setValue(String key, Object value) { + super.setValue(key, value); + this.effects.setValue(key, value); + } + + @Override + public OptionalOneShotEffect copy() { + return new OptionalOneShotEffect(this); + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + return "you may " + CardUtil.getTextWithFirstCharLowerCase(effects.getText(mode)); + } + + @Override + public OptionalOneShotEffect setTargetPointer(TargetPointer targetPointer) { + effects.setTargetPointer(targetPointer); + super.setTargetPointer(targetPointer); + return this; + } + + @Override + public OptionalOneShotEffect withTargetDescription(String target) { + effects.forEach(effect -> effect.withTargetDescription(target)); + return this; + } +} -- 2.47.2 From 9c4bd210d708aee0439fb2026873ba07d20e8aa1 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Fri, 7 Nov 2025 20:19:19 -0500 Subject: [PATCH 129/261] [EOE] Fix Planetary Annihilation It was never allowing people with 6 or fewer lands to save their lands. --- Mage.Sets/src/mage/cards/p/PlanetaryAnnihilation.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/p/PlanetaryAnnihilation.java b/Mage.Sets/src/mage/cards/p/PlanetaryAnnihilation.java index 20b327efd38..cf140ece939 100644 --- a/Mage.Sets/src/mage/cards/p/PlanetaryAnnihilation.java +++ b/Mage.Sets/src/mage/cards/p/PlanetaryAnnihilation.java @@ -66,6 +66,7 @@ class PlanetaryAnnihilationEffect extends OneShotEffect { if (player == null || game.getBattlefield().count( StaticFilters.FILTER_CONTROLLED_PERMANENT_LANDS, playerId, source, game ) <= 6) { + toSave.addAll(game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CONTROLLED_PERMANENT_LANDS, playerId, game)); continue; } TargetPermanent target = new TargetPermanent( -- 2.47.2 From b69fb2f4cd624822ac7150ea0ee727285b821812 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Fri, 7 Nov 2025 20:48:57 -0500 Subject: [PATCH 130/261] [TLE] Implement Zuko, Firebending Master --- .../mage/cards/z/ZukoFirebendingMaster.java | 68 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 69 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/z/ZukoFirebendingMaster.java diff --git a/Mage.Sets/src/mage/cards/z/ZukoFirebendingMaster.java b/Mage.Sets/src/mage/cards/z/ZukoFirebendingMaster.java new file mode 100644 index 00000000000..7f277b96c69 --- /dev/null +++ b/Mage.Sets/src/mage/cards/z/ZukoFirebendingMaster.java @@ -0,0 +1,68 @@ +package mage.cards.z; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CountersControllerCount; +import mage.abilities.effects.common.counter.AddCountersPlayersEffect; +import mage.constants.*; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FirebendingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author anonymous + */ +public final class ZukoFirebendingMaster extends CardImpl { + + private static final DynamicValue xValue = new CountersControllerCount(CounterType.EXPERIENCE); + + public ZukoFirebendingMaster(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // Firebending X where X is the number of experience counters you have. + this.addAbility(new FirebendingAbility(xValue)); + + // Whenever you cast a spell during combat, you get an experience counter. + this.addAbility(new ZukoFirebendingMasterAbility()); + } + + private ZukoFirebendingMaster(final ZukoFirebendingMaster card) { + super(card); + } + + @Override + public ZukoFirebendingMaster copy() { + return new ZukoFirebendingMaster(this); + } +} + +class ZukoFirebendingMasterAbility extends SpellCastControllerTriggeredAbility { + + public ZukoFirebendingMasterAbility() { + super(new AddCountersPlayersEffect(CounterType.EXPERIENCE.createInstance(), TargetController.YOU), StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL); + setTriggerPhrase("Whenever you cast a spell during combat, "); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return game.getTurnPhaseType() == TurnPhase.COMBAT && super.checkTrigger(event, game); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 3ec58b1b73a..1708ee26a47 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -217,6 +217,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Zuko's Offense", 288, Rarity.COMMON, mage.cards.z.ZukosOffense.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Zuko, Avatar Hunter", 246, Rarity.RARE, mage.cards.z.ZukoAvatarHunter.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Zuko, Avatar Hunter", 287, Rarity.RARE, mage.cards.z.ZukoAvatarHunter.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Zuko, Firebending Master", 127, Rarity.MYTHIC, mage.cards.z.ZukoFirebendingMaster.class)); cards.removeIf(setCardInfo -> unfinished.contains(setCardInfo.getName())); } -- 2.47.2 From 3a92c32e48f47ec04335dc7bf48e85561c0becde Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Fri, 7 Nov 2025 21:34:48 -0500 Subject: [PATCH 131/261] [TLE] Implement Azula, Ruthless Firebender --- .../mage/cards/a/AzulaRuthlessFirebender.java | 93 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 94 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AzulaRuthlessFirebender.java diff --git a/Mage.Sets/src/mage/cards/a/AzulaRuthlessFirebender.java b/Mage.Sets/src/mage/cards/a/AzulaRuthlessFirebender.java new file mode 100644 index 00000000000..f52e7430ef0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AzulaRuthlessFirebender.java @@ -0,0 +1,93 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.OptionalOneShotEffect; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.SourceControllerCountersCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.counter.AddCountersPlayersEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.constants.*; +import mage.abilities.keyword.FirebendingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.counters.CounterType; +import mage.game.Game; +import mage.watchers.common.DiscardedCardWatcher; + +/** + * + * @author anonymous + */ +public final class AzulaRuthlessFirebender extends CardImpl { + + public AzulaRuthlessFirebender(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.NOBLE); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Firebending 1 + this.addAbility(new FirebendingAbility(1)); + + // Whenever Azula attacks, you may discard a card. Then you get an experience counter for each player who discarded a card this turn. + Ability ability = new AttacksTriggeredAbility(new OptionalOneShotEffect(new DiscardControllerEffect(1), "You may discard a card")); + ability.addEffect(new AddCountersPlayersEffect(CounterType.EXPERIENCE.createInstance(), AzulaRuthlessFirebenderValue.instance, TargetController.YOU).setText("Then you get an experience counter for each player who discarded a card this turn.")); + this.addAbility(ability, new DiscardedCardWatcher()); + + // {2}{B}: Until end of turn, Azula gets +1/+1 for each experience counter you have and gains menace. + ability = new SimpleActivatedAbility(new BoostSourceEffect(SourceControllerCountersCount.EXPERIENCE, SourceControllerCountersCount.EXPERIENCE, Duration.EndOfTurn), new ManaCostsImpl<>("{2}{B}")); + ability.addEffect(new GainAbilitySourceEffect(new MenaceAbility(), Duration.EndOfTurn).setText("and gains menace")); + this.addAbility(ability); + } + + private AzulaRuthlessFirebender(final AzulaRuthlessFirebender card) { + super(card); + } + + @Override + public AzulaRuthlessFirebender copy() { + return new AzulaRuthlessFirebender(this); + } +} + +enum AzulaRuthlessFirebenderValue implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + int playersDiscardedThisTurn = 0; + for (UUID playerId : game.getState().getPlayersInRange(sourceAbility.getControllerId(), game)) { + if (DiscardedCardWatcher.checkPlayerDiscarded(playerId, game)) { + playersDiscardedThisTurn += 1; + } + } + return playersDiscardedThisTurn; + } + + @Override + public AzulaRuthlessFirebenderValue copy() { + return this; + } + + @Override + public String getMessage() { + return "for each player who discarded a card this turn"; + } + + @Override + public String toString() { + return "X"; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 1708ee26a47..70a1218ba62 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -41,6 +41,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Arcane Signet", 315, Rarity.RARE, mage.cards.a.ArcaneSignet.class)); cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 130, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class)); cards.add(new SetCardInfo("Avatar Roku, Firebender", 112, Rarity.MYTHIC, mage.cards.a.AvatarRokuFirebender.class)); + cards.add(new SetCardInfo("Azula, Ruthless Firebender", 101, Rarity.MYTHIC, mage.cards.a.AzulaRuthlessFirebender.class)); cards.add(new SetCardInfo("Bastion of Remembrance", 160, Rarity.UNCOMMON, mage.cards.b.BastionOfRemembrance.class)); cards.add(new SetCardInfo("Beastmaster Ascension", 39, Rarity.MYTHIC, mage.cards.b.BeastmasterAscension.class)); cards.add(new SetCardInfo("Beastmaster's Magemark", 9999, Rarity.MYTHIC, mage.cards.b.BeastmastersMagemark.class)); -- 2.47.2 From a17635564ae8eafb769317a8bf0ecc130e6a852d Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Fri, 7 Nov 2025 21:50:20 -0500 Subject: [PATCH 132/261] [TLE] Implement Iroh, Dragon of the West --- .../src/mage/cards/i/IrohDragonOfTheWest.java | 59 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 60 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/IrohDragonOfTheWest.java diff --git a/Mage.Sets/src/mage/cards/i/IrohDragonOfTheWest.java b/Mage.Sets/src/mage/cards/i/IrohDragonOfTheWest.java new file mode 100644 index 00000000000..d18ed8d6e99 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IrohDragonOfTheWest.java @@ -0,0 +1,59 @@ +package mage.cards.i; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.FirebendingAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.MentorAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.CounterAnyPredicate; + +/** + * + * @author anonymous + */ +public final class IrohDragonOfTheWest extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(CounterAnyPredicate.instance); + } + + public IrohDragonOfTheWest(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Mentor + this.addAbility(new MentorAbility()); + + // At the beginning of combat on your turn, each creature you control with a counter on it gains firebending 2 until end of turn. + this.addAbility(new BeginningOfCombatTriggeredAbility(new GainAbilityControlledEffect(new FirebendingAbility(2), Duration.EndOfTurn, filter))); + } + + private IrohDragonOfTheWest(final IrohDragonOfTheWest card) { + super(card); + } + + @Override + public IrohDragonOfTheWest copy() { + return new IrohDragonOfTheWest(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 70a1218ba62..eee1f3e1654 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -115,6 +115,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Inspiring Call", 168, Rarity.UNCOMMON, mage.cards.i.InspiringCall.class)); cards.add(new SetCardInfo("Insurrection", 31, Rarity.MYTHIC, mage.cards.i.Insurrection.class)); cards.add(new SetCardInfo("Intruder Alarm", 15, Rarity.MYTHIC, mage.cards.i.IntruderAlarm.class)); + cards.add(new SetCardInfo("Iroh, Dragon of the West", 119, Rarity.RARE, mage.cards.i.IrohDragonOfTheWest.class)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 240, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 282, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 90815541f9af0df1834a69b2c4ab9e6e3cbe91ca Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Fri, 7 Nov 2025 22:22:33 -0500 Subject: [PATCH 133/261] [TLA] Implement Ozai, the Phoenix King --- .../src/mage/cards/o/OzaiThePhoenixKing.java | 123 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 3 + Mage/src/main/java/mage/players/ManaPool.java | 18 +++ 3 files changed, 144 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/o/OzaiThePhoenixKing.java diff --git a/Mage.Sets/src/mage/cards/o/OzaiThePhoenixKing.java b/Mage.Sets/src/mage/cards/o/OzaiThePhoenixKing.java new file mode 100644 index 00000000000..4ef9e353d15 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OzaiThePhoenixKing.java @@ -0,0 +1,123 @@ +package mage.cards.o; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.keyword.*; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.ManaPool; +import mage.players.Player; + +/** + * + * @author anonymous + */ +public final class OzaiThePhoenixKing extends CardImpl { + + public OzaiThePhoenixKing(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}{R}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.power = new MageInt(7); + this.toughness = new MageInt(7); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Firebending 4 + this.addAbility(new FirebendingAbility(4)); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // If you would lose unspent mana, that mana becomes red instead. + this.addAbility(new SimpleStaticAbility(new OzaiThePhoenixKingManaEffect())); + + // Ozai has flying and indestructible as long as you have six or more unspent mana. + this.addAbility(new SimpleStaticAbility(new OzaiThePhoenixKingBoostEffect())); + } + + private OzaiThePhoenixKing(final OzaiThePhoenixKing card) { + super(card); + } + + @Override + public OzaiThePhoenixKing copy() { + return new OzaiThePhoenixKing(this); + } +} + +class OzaiThePhoenixKingManaEffect extends ContinuousEffectImpl { + + OzaiThePhoenixKingManaEffect() { + super(Duration.WhileOnBattlefield, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit); + staticText = "if you would lose unspent mana, that mana becomes red instead"; + } + + private OzaiThePhoenixKingManaEffect(final OzaiThePhoenixKingManaEffect effect) { + super(effect); + } + + @Override + public OzaiThePhoenixKingManaEffect copy() { + return new OzaiThePhoenixKingManaEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + player.getManaPool().setManaBecomesRed(true); + } + return true; + } +} + +class OzaiThePhoenixKingBoostEffect extends ContinuousEffectImpl { + + OzaiThePhoenixKingBoostEffect() { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + staticText = "{this} has flying and indestructible as long as you have six or more unspent mana"; + } + + private OzaiThePhoenixKingBoostEffect(final OzaiThePhoenixKingBoostEffect effect) { + super(effect); + } + + @Override + public OzaiThePhoenixKingBoostEffect copy() { + return new OzaiThePhoenixKingBoostEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent creature = game.getPermanent(source.getSourceId()); + if (controller == null || creature == null) { + return false; + } + ManaPool pool = controller.getManaPool(); + int blackMana = pool.getBlack(); + int whiteMana = pool.getWhite(); + int blueMana = pool.getBlue(); + int greenMana = pool.getGreen(); + int redMana = pool.getRed(); + int colorlessMana = pool.getColorless(); + int manaPoolTotal = blackMana + whiteMana + blueMana + greenMana + redMana + colorlessMana; + if (manaPoolTotal >= 6) { + creature.addAbility(FlyingAbility.getInstance(), source.getSourceId(), game); + creature.addAbility(IndestructibleAbility.getInstance(), source.getSourceId(), game); + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 749609032a9..b248e86e798 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -188,6 +188,9 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Ostrich-Horse", 188, Rarity.COMMON, mage.cards.o.OstrichHorse.class)); cards.add(new SetCardInfo("Otter-Penguin", 67, Rarity.COMMON, mage.cards.o.OtterPenguin.class)); cards.add(new SetCardInfo("Ozai's Cruelty", 113, Rarity.UNCOMMON, mage.cards.o.OzaisCruelty.class)); + cards.add(new SetCardInfo("Ozai, the Phoenix King", 235, Rarity.MYTHIC, mage.cards.o.OzaiThePhoenixKing.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ozai, the Phoenix King", 311, Rarity.MYTHIC, mage.cards.o.OzaiThePhoenixKing.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ozai, the Phoenix King", 335, Rarity.MYTHIC, mage.cards.o.OzaiThePhoenixKing.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Path to Redemption", 31, Rarity.COMMON, mage.cards.p.PathToRedemption.class)); cards.add(new SetCardInfo("Pillar Launch", 189, Rarity.COMMON, mage.cards.p.PillarLaunch.class)); cards.add(new SetCardInfo("Plains", 282, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/players/ManaPool.java b/Mage/src/main/java/mage/players/ManaPool.java index 1311c7408fa..ae06cef17e3 100644 --- a/Mage/src/main/java/mage/players/ManaPool.java +++ b/Mage/src/main/java/mage/players/ManaPool.java @@ -42,6 +42,7 @@ public class ManaPool implements Serializable { // empty mana pool effects private final Set doNotEmptyManaTypes = new HashSet<>(); // keep some colors private boolean manaBecomesBlack = false; // replace all pool by black + private boolean manaBecomesRed = false; // replace all pool by red private boolean manaBecomesColorless = false; // replace all pool by colorless private static final class ConditionalManaInfo { @@ -76,6 +77,7 @@ public class ManaPool implements Serializable { } this.doNotEmptyManaTypes.addAll(pool.doNotEmptyManaTypes); this.manaBecomesBlack = pool.manaBecomesBlack; + this.manaBecomesRed = pool.manaBecomesRed; this.manaBecomesColorless = pool.manaBecomesColorless; } @@ -236,6 +238,7 @@ public class ManaPool implements Serializable { public void clearEmptyManaPoolRules() { doNotEmptyManaTypes.clear(); this.manaBecomesBlack = false; + this.manaBecomesRed = false; this.manaBecomesColorless = false; } @@ -247,6 +250,10 @@ public class ManaPool implements Serializable { this.manaBecomesBlack = manaBecomesBlack; } + public void setManaBecomesRed(boolean manaBecomesRed) { + this.manaBecomesRed = manaBecomesRed; + } + public void setManaBecomesColorless(boolean manaBecomesColorless) { this.manaBecomesColorless = manaBecomesColorless; } @@ -267,6 +274,9 @@ public class ManaPool implements Serializable { if (manaBecomesBlack) { continue; } + if (manaBecomesRed) { + continue; + } if (manaBecomesColorless) { continue; } @@ -315,12 +325,20 @@ public class ManaPool implements Serializable { return 0; } } + + // TODO: This should be reimplemented as replacement effects instead, so you can choose which applies. if (manaBecomesBlack) { int amount = toEmpty.get(manaType); toEmpty.clear(manaType); toEmpty.add(ManaType.BLACK, amount); return 0; } + if (manaBecomesRed) { + int amount = toEmpty.get(manaType); + toEmpty.clear(manaType); + toEmpty.add(ManaType.RED, amount); + return 0; + } if (manaBecomesColorless) { int amount = toEmpty.get(manaType); toEmpty.clear(manaType); -- 2.47.2 From 0d21b67057030d1bb76b0e91eece3f9801eb65b6 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 09:33:53 -0500 Subject: [PATCH 134/261] [TLA] update spoiler --- .../src/mage/sets/AvatarTheLastAirbender.java | 5 ++- Utils/mtg-cards-data.txt | 43 +++++++++++++++++-- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b248e86e798..7911c405b3b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -12,7 +12,7 @@ import java.util.List; */ public final class AvatarTheLastAirbender extends ExpansionSet { - private static final List unfinished = Arrays.asList("Aang's Iceberg", "Aang, Swift Savior", "Avatar Aang", "Benevolent River Spirit", "Crashing Wave", "Flexible Waterbender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Invasion Submersible", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Secret of Bloodbending", "Spirit Water Revival", "The Legend of Kuruk", "The Unagi of Kyoshi Island", "Waterbender Ascension", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); + private static final List unfinished = Arrays.asList("Aang's Iceberg", "Aang, Swift Savior", "Avatar Aang", "Benevolent River Spirit", "Crashing Wave", "Flexible Waterbender", "Foggy Swamp Vinebender", "Foggy Swamp Visions", "Geyser Leaper", "Giant Koi", "Hama, the Bloodbender", "Invasion Submersible", "Katara, Bending Prodigy", "Katara, Water Tribe's Hope", "North Pole Patrol", "Ruinous Waterbending", "Secret of Bloodbending", "Spirit Water Revival", "The Legend of Kuruk", "The Unagi of Kyoshi Island", "Waterbender Ascension", "Waterbending Lesson", "Water Tribe Rallier", "Watery Grasp", "Yue, the Moon Spirit"); private static final AvatarTheLastAirbender instance = new AvatarTheLastAirbender(); public static AvatarTheLastAirbender getInstance() { @@ -132,7 +132,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Great Divide Guide", 181, Rarity.RARE, mage.cards.g.GreatDivideGuide.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Great Divide Guide", 345, Rarity.RARE, mage.cards.g.GreatDivideGuide.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Guru Pathik", 223, Rarity.UNCOMMON, mage.cards.g.GuruPathik.class)); - cards.add(new SetCardInfo("Hakoda, Selfless Commander", 366, Rarity.RARE, mage.cards.h.HakodaSelflessCommander.class)); + cards.add(new SetCardInfo("Hakoda, Selfless Commander", 23, Rarity.RARE, mage.cards.h.HakodaSelflessCommander.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Hakoda, Selfless Commander", 366, Rarity.RARE, mage.cards.h.HakodaSelflessCommander.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Haru, Hidden Talent", 182, Rarity.UNCOMMON, mage.cards.h.HaruHiddenTalent.class)); cards.add(new SetCardInfo("Heartless Act", 103, Rarity.UNCOMMON, mage.cards.h.HeartlessAct.class)); cards.add(new SetCardInfo("Hei Bai, Spirit of Balance", 225, Rarity.UNCOMMON, mage.cards.h.HeiBaiSpiritOfBalance.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 42a7285ef00..b8180d97822 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59768,11 +59768,12 @@ Aang's Iceberg|Avatar: The Last Airbender|5|R|{2}{W}|Enchantment|||Flash$When th Airbender Ascension|Avatar: The Last Airbender|6|R|{1}{W}|Enchantment|||When this enchantment enters, airbend up to one target creature.$Whenever a creature you control enters, put a quest counter on this enchantment.$At the beginning of your end step, if this enchantment has four or more quest counters on it, exile up to one target creature you control, then return it to the battlefield under its owner's control.| Airbender's Reversal|Avatar: The Last Airbender|7|U|{1}{W}|Instant - Lesson|||Choose one --$* Destroy target attacking creature.$* Airbend target creature you control.| Airbending Lesson|Avatar: The Last Airbender|8|C|{2}{W}|Instant - Lesson|||Airbend target nonland permanent.$Draw a card.| -Appa, Loyal Sky Bison|Avatar: The Last Airbender|9|U|{4}{W}{W}|Legendary Creature - Bison Ally|4|4|Flying$Whenever Appa enters or attacks, choose one --$* Target creature you control gains flying until end of turn.$* Airbend another target nonland permanent you control..| +Appa, Loyal Sky Bison|Avatar: The Last Airbender|9|U|{4}{W}{W}|Legendary Creature - Bison Ally|4|4|Flying$Whenever Appa enters or attacks, choose one --$* Target creature you control gains flying until end of turn.$* Airbend another target nonland permanent you control.| Appa, Steadfast Guardian|Avatar: The Last Airbender|10|M|{2}{W}{W}|Legendary Creature - Bison Ally|3|4|Flash$Flying$When Appa enters, airbend any number of other target nonland permanents you control.$Whenever you cast a spell from exile, create a 1/1 white Ally creature token.| Avatar Enthusiasts|Avatar: The Last Airbender|11|C|{2}{W}|Creature - Human Peasant Ally|2|2|Whenever another Ally you control enters, put a +1/+1 counter on this creature.| -Avatar's Wrath|Avatar: The Last Airbender|12|R|{2}{W}{W}|Sorcery|||Choose up to one target creature, then airbend each other creature.$Until your next turn, your opponents can't cast spells from anywhere other than their hand.$Exile Avatar's Wrath.| +Avatar's Wrath|Avatar: The Last Airbender|12|R|{2}{W}{W}|Sorcery|||Choose up to one target creature, then airbend all other creatures.$Until your next turn, your opponents can't cast spells from anywhere other than their hand.$Exile Avatar's Wrath.| Compassionate Healer|Avatar: The Last Airbender|13|C|{1}{W}|Creature - Human Cleric Ally|2|2|Whenever this creature becomes tapped, you gain 1 life and scry 1.| +Curious Farm Animals|Avatar: The Last Airbender|14|C|{W}|Creature - Boar Elk Bird Ox|1|1|When this creature dies, you gain 3 life.${2}, Sacrifice this creature: Destroy up to one target artifact or enchantment.| Destined Confrontation|Avatar: The Last Airbender|15|U|{2}{W}{W}|Sorcery|||Each player chooses any number of creatures they control with total power 4 or less, then sacrifices all other creatures they control.| Earth Kingdom Jailer|Avatar: The Last Airbender|16|U|{2}{W}|Creature - Human Soldier Ally|3|3|When this creature enters, exile up to one target artifact, creature, or enchantment an opponent controls with mana value 3 or greater until this creature leaves the battlefield.| Earth Kingdom Protectors|Avatar: The Last Airbender|17|U|{W}|Creature - Human Soldier Ally|1|1|Vigilance$Sacrifice this creature: Another target Ally you control gains indestructible until end of turn.| @@ -59781,6 +59782,7 @@ Fancy Footwork|Avatar: The Last Airbender|19|U|{2}{W}|Instant - Lesson|||Untap o Gather the White Lotus|Avatar: The Last Airbender|20|U|{4}{W}|Sorcery|||Create a 1/1 white Ally creature token for each Plains you control. Scry 2.| Glider Kids|Avatar: The Last Airbender|21|C|{2}{W}|Creature - Human Pilot Ally|2|3|Flying$When this creature enters, scry 1.| Glider Staff|Avatar: The Last Airbender|22|U|{2}{W}|Artifact - Equipment|||When this Equipment enters, airbend up to one target creature.$Equipped creature gets +1/+1 and has flying.$Equip {2}| +Hakoda, Selfless Commander|Avatar: The Last Airbender|23|R|{3}{W}|Legendary Creature - Human Warrior Ally|3|5|Vigilance$You may look at the top card of your library any time.$You may cast Ally spells from the top of your library.$Sacrifice Hakoda: Creatures you control get +0/+5 and gain indestructible until end of turn.| Invasion Reinforcements|Avatar: The Last Airbender|24|U|{1}{W}|Creature - Human Warrior Ally|1|1|Flash$When this creature enters, create a 1/1 white Ally creature token.| Jeong Jeong's Deserters|Avatar: The Last Airbender|25|C|{1}{W}|Creature - Human Rebel Ally|1|2|When this creature enters, put a +1/+1 counter on target creature.| Kyoshi Warriors|Avatar: The Last Airbender|26|C|{3}{W}|Creature - Human Warrior Ally|3|3|When this creature enters, create a 1/1 white Ally creature token.| @@ -59793,11 +59795,16 @@ Path to Redemption|Avatar: The Last Airbender|31|C|{1}{W}|Enchantment - Aura|||E Rabaroo Troop|Avatar: The Last Airbender|32|C|{3}{W}{W}|Creature - Rabbit Kangaroo|3|5|Landfall -- Whenever a land you control enters, this creature gains flying until end of turn and you gain 1 life.$Plainscycling {2}| Razor Rings|Avatar: The Last Airbender|33|C|{1}{W}|Instant|||Razor Rings deals 4 damage to target attacking or blocking creature. You gain life equal to the excess damage dealt this way.| Sandbenders' Storm|Avatar: The Last Airbender|34|C|{3}{W}|Instant|||Choose one--$* Destroy target creature with power 4 or greater.$* Earthbend 3.| +South Pole Voyager|Avatar: The Last Airbender|35|R|{1}{W}|Creature - Human Scout Ally|2|2|Whenever this creature or another Ally you control enters, you gain 1 life. If this is the second time this ability has resolved this turn, draw a card.| Southern Air Temple|Avatar: The Last Airbender|36|U|{3}{W}|Legendary Enchantment - Shrine|||When Southern Air Temple enters, put X +1/+1 counters on each creature you control, where X is the number of Shrines you control.$Whenever another Shrine you control enters, put a +1/+1 counter on each creature you control.| Suki, Courageous Rescuer|Avatar: The Last Airbender|37|R|{1}{W}{W}|Legendary Creature - Human Warrior Ally|2|4|Other creatures you control get +1/+0.$Whenever another permanent you control leaves the battlefield during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.| +Team Avatar|Avatar: The Last Airbender|38|U|{2}{W}|Enchantment|||Whenever a creature you control attacks alone, it gets +X/+X until end of turn, where X is the number of creatures you control.${2}{W}, Discard this card: It deals damage equal to the number of creatures you control to target creature.| United Front|Avatar: The Last Airbender|39|M|{X}{W}{W}|Sorcery|||Create X 1/1 white Ally creature tokens, then put a +1/+1 counter on each creature you control.| +Vengeful Villagers|Avatar: The Last Airbender|40|U|{3}{W}|Creature - Human Citizen|3|3|Whenever this creature attacks, choose target creature an opponent controls. Tap it, then you may sacrifice an artifact or creature. If you do, put a stun counter on the chosen creature.| +Water Tribe Captain|Avatar: The Last Airbender|41|C|{2}{W}|Creature - Human Soldier Ally|3|3|{5}: Creatures you control get +1/+1 until end of turn.| Water Tribe Rallier|Avatar: The Last Airbender|42|U|{1}{W}|Creature - Human Soldier Ally|2|2|Waterbend {5}: Look at the top four cards of your library. You may reveal a creature card with power 3 or less from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| Yip Yip!|Avatar: The Last Airbender|43|C|{W}|Instant - Lesson|||Target creature you control gets +2/+2 until end of turn. If that creature is an Ally, it also gains flying until end of turn.| +Accumulate Wisdom|Avatar: The Last Airbender|44|U|{1}{U}|Instant - Lesson|||Look at the top three cards of your library. Put one of those cards into your hand and the rest on the bottom of your library in any order. Put each of those cards into your hand instead if there are three or more Lesson cards in your graveyard.| Benevolent River Spirit|Avatar: The Last Airbender|45|U|{U}{U}|Creature - Spirit|4|5|As an additional cost to cast this spell, waterbend {5}.$Flying, ward {2}$When this creature enters, scry 2.| Boomerang Basics|Avatar: The Last Airbender|46|U|{U}|Sorcery - Lesson|||Return target nonland permanent to its owner's hand. If you controlled that permanent, draw a card.| Crashing Wave|Avatar: The Last Airbender|47|U|{U}{U}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Tap up to X target creatures, then distribute three stun counters among tapped creatures your opponents control.| @@ -59835,6 +59842,7 @@ The Unagi of Kyoshi Island|Avatar: The Last Airbender|77|R|{3}{U}{U}|Legendary C Wan Shi Tong, Librarian|Avatar: The Last Airbender|78|M|{X}{U}{U}|Legendary Creature - Bird Spirit|1|1|Flash$Flying, vigilance$When Wan Shi Tong enters, put X +1/+1 counters on him. Then draw half X cards, rounded down.$Whenever an opponent searches their library, put a +1/+1 counter on Wan Shi Tong and draw a card.| Waterbender Ascension|Avatar: The Last Airbender|79|R|{1}{U}|Enchantment|||Whenever a creature you control deals combat damage to a player, put a quest counter on this enchantment. Then if it has four or more quest counters on it, draw a card.$Waterbend {4}: Target creature can't be blocked this turn.| Waterbending Lesson|Avatar: The Last Airbender|80|C|{3}{U}|Sorcery - Lesson|||Draw three cards. Then discard a card unless you waterbend {2}.| +Waterbending Scroll|Avatar: The Last Airbender|81|U|{1}{U}|Artifact|||{6}, {T}: Draw a card. This ability costs {1} less to activate for each Island you control.| Watery Grasp|Avatar: The Last Airbender|82|C|{U}|Enchantment - Aura|||Enchant creature$Enchanted creature doesn't untap during its controller's untap step.$Waterbend {5}: Enchanted creature's owner shuffles it into their library.| Yue, the Moon Spirit|Avatar: The Last Airbender|83|R|{3}{U}|Legendary Creature - Spirit Ally|3|3|Flying, vigilance$Waterbend {5}, {T}: You may cast a noncreature spell from your hand without paying its mana cost.| Azula Always Lies|Avatar: The Last Airbender|84|C|{1}{B}|Instant - Lesson|||Choose one or both --$* Target creature gets -1/-1 until end of turn.$* Put a +1/+1 counter on target creature.| @@ -59843,6 +59851,7 @@ Beetle-Headed Merchants|Avatar: The Last Airbender|86|C|{4}{B}|Creature - Human Boiling Rock Rioter|Avatar: The Last Airbender|87|R|{2}{B}|Creature - Human Rogue Ally|3|3|Firebending 1$Tap an untapped Ally you control: Exile target card from a graveyard.$Whenever this creature attacks, you may cast an Ally spell from among cards you own exiled with this creature.| Buzzard-Wasp Colony|Avatar: The Last Airbender|88|U|{3}{B}|Creature - Bird Insect|2|2|Flying$When this creature enters, you may sacrifice an artifact or creature. If you do, draw a card.$Whenever another creature you control dies, if it had counters on it, put its counters on this creature.| Callous Inspector|Avatar: The Last Airbender|89|C|{B}|Creature - Human Soldier|1|1|Menace$When this creature dies, it deals 1 damage to you. Create a Clue token.| +Canyon Crawler|Avatar: The Last Airbender|90|C|{4}{B}{B}|Creature - Spider Beast|6|6|Deathtouch$When this creature enters, create a Food token.$Swampcycling {2}| Cat-Gator|Avatar: The Last Airbender|91|U|{6}{B}|Creature - Fish Crocodile|3|2|Lifelink$When this creature enters, it deals damage equal to the number of Swamps you control to any target.| Corrupt Court Official|Avatar: The Last Airbender|92|C|{1}{B}|Creature - Human Advisor|1|1|When this creature enters, target opponent discards a card.| Dai Li Indoctrination|Avatar: The Last Airbender|93|C|{1}{B}|Sorcery - Lesson|||Choose one --$* Target opponent reveals their hand. You choose a nonland permanent card from it. That player discards that card.$* Earthbend 2.| @@ -59859,18 +59868,25 @@ Heartless Act|Avatar: The Last Airbender|103|U|{1}{B}|Instant|||Choose one --$* Hog-Monkey|Avatar: The Last Airbender|104|C|{2}{B}|Creature - Boar Monkey|3|2|At the beginning of combat on your turn, target creature you control with a +1/+1 counter on it gains menace until end of turn.$Exhaust -- {5}: Put two +1/+1 counters on this creature.| Joo Dee, One of Many|Avatar: The Last Airbender|105|U|{1}{B}|Creature - Human Advisor|2|2|{B}, {T}: Surveil 1. Create a token that's a copy of this creature, then sacrifice an artifact or creature. Activate only as a sorcery.| June, Bounty Hunter|Avatar: The Last Airbender|106|U|{1}{B}|Legendary Creature - Human Mercenary|2|2|June can't be blocked as long as you've drawn two or more cards this turn.${1}, Sacrifice another creature: Create a Clue token. Activate only during your turn.| +Koh, the Face Stealer|Avatar: The Last Airbender|107|M|{4}{B}{B}|Legendary Creature - Shapeshifter Spirit|6|6|When Koh enters, exile up to one other target creature.$Whenever another nontoken creature dies, you may exile it.$Pay 1 life: Choose a creature card exiled with Koh.$Koh has all activated and triggered abilities of the last chosen card.| +Lo and Li, Twin Tutors|Avatar: The Last Airbender|108|U|{4}{B}|Legendary Creature - Human Advisor|2|2|When Lo and Li enter, search your library for a Lesson or Noble card, reveal it, put it into your hand, then shuffle.$Noble creatures you control and Lesson spells you control have lifelink.| Mai, Scornful Striker|Avatar: The Last Airbender|109|R|{1}{B}|Legendary Creature - Human Noble Ally|2|2|First strike$Whenever a player casts a noncreature spell, they lose 2 life.| Merchant of Many Hats|Avatar: The Last Airbender|110|C|{1}{B}|Creature - Human Peasant Ally|2|2|{2}{B}: Return this card from your graveyard to your hand.| Northern Air Temple|Avatar: The Last Airbender|111|U|{B}|Legendary Enchantment - Shrine|||When Northern Air Temple enters, each opponent loses X life and you gain X life, where X is the number of Shrines you control.$Whenever another Shrine you control enters, each opponent loses 1 life and you gain 1 life.| Obsessive Pursuit|Avatar: The Last Airbender|112|R|{1}{B}|Enchantment|||When this enchantment enters and at the beginning of your upkeep, you lose 1 life and create a Clue token.$Whenever you attack, put X +1/+1 counters on target attacking creature, where X is the number of permanents you've sacrificed this turn. If X is three or greater, that creature gains lifelink until end of turn.| Ozai's Cruelty|Avatar: The Last Airbender|113|U|{2}{B}|Sorcery - Lesson|||Ozai's Cruelty deals 2 damage to target player. That player discards two cards.| +Phoenix Fleet Airship|Avatar: The Last Airbender|114|M|{2}{B}{B}|Artifact - Vehicle|4|4|Flying$At the beginning of your end step, if you sacrificed a permanent this turn, create a token that's a copy of this Vehicle.$As long as you control eight or more permanents named Phoenix Fleet Airship, this Vehicle is an artifact creature.$Crew 1| +Pirate Peddlers|Avatar: The Last Airbender|115|C|{2}{B}|Creature - Human Pirate|2|2|Deathtouch$Whenever you sacrifice another permanent, put a +1/+1 counter on this creature.| Raven Eagle|Avatar: The Last Airbender|116|R|{2}{B}|Creature - Bird Assassin|2|3|Flying$Whenever this creature enters or attacks, exile up to one target card from a graveyard. If a creature card is exiled this way, create a Clue token.$Whenever you draw your second card each turn, each opponent loses 1 life and you gain 1 life.| The Rise of Sozin|Avatar: The Last Airbender|117|M|{4}{B}{B}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I -- Destroy all creatures.$II -- Choose a card name. Search target opponent's graveyard, hand, and library for up to four cards with that name and exile them. Then that player shuffles.$III -- Exile this Saga, then return it to the battlefield transformed under your control.| Fire Lord Sozin|Avatar: The Last Airbender|117|M||Legendary Creature - Human Noble|5|5|Menace, firebending 3$Whenever Fire Lord Sozin deals combat damage to a player, you may pay {X}. When you do, put any number of target creature cards with total mana value X or less from that player's graveyard onto the battlefield under your control.| +Ruinous Waterbending|Avatar: The Last Airbender|118|U|{1}{B}{B}|Sorcery - Lesson|||As an additional cost to cast this spell, you may waterbend {4}.$All creatures get -2/-2 until end of turn. If this spell's additional cost was paid, whenever a creature dies this turn, you gain 1 life.| Sold Out|Avatar: The Last Airbender|119|C|{3}{B}|Instant|||Exile target creature. If it was dealt damage this turn, create a Clue token.| Swampsnare Trap|Avatar: The Last Airbender|120|C|{2}{B}|Enchantment - Aura|||This spell costs {1} less to cast if it targets a creature with flying.$Enchant creature$Enchanted creature gets -5/-3.| Tundra Tank|Avatar: The Last Airbender|121|U|{2}{B}|Artifact - Vehicle|4|4|Firebending 1$When this Vehicle enters, target creature you control gains indestructible until end of turn.$Crew 1| Wolfbat|Avatar: The Last Airbender|122|U|{2}{B}|Creature - Wolf Bat|2|2|Flying$Whenever you draw your second card each turn, you may pay {B}. If you do, return this card from your graveyard to the battlefield with a finality counter on it.| +Zuko's Conviction|Avatar: The Last Airbender|123|U|{B}|Instant|||Kicker {4}$Return target creature card from your graveyard to your hand. If this spell was kicked, instead put that card onto the battlefield tapped.| +Boar-q-pine|Avatar: The Last Airbender|124|C|{2}{R}|Creature - Boar Porcupine|2|2|Whenever you cast a noncreature spell, put a +1/+1 counter on this creature.| Bumi Bash|Avatar: The Last Airbender|125|C|{3}{R}|Sorcery|||Choose one --$* Bumi Bash deals damage equal to the number of lands you control to target creature.$* Destroy target land creature or nonbasic land.| The Cave of Two Lovers|Avatar: The Last Airbender|126|U|{3}{R}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I -- Create two 1/1 white Ally creature tokens.$II -- Search your library for a Mountain or Cave card, reveal it, put it into your hand,$then shuffle.$III -- Earthbend 3.| Combustion Man|Avatar: The Last Airbender|127|U|{3}{R}{R}|Legendary Creature - Human Assassin|4|6|Whenever Combustion Man attacks, destroy target permanent unless its controller has Combustion Man deal damage to them equal to his power.| @@ -59884,6 +59900,7 @@ Fire Nation Cadets|Avatar: The Last Airbender|134|C|{R}|Creature - Human Soldier Fire Nation Raider|Avatar: The Last Airbender|135|C|{3}{R}|Creature - Human Soldier|4|2|Raid -- When this creature enters, if you attacked this turn, create a Clue token.| Fire Sages|Avatar: The Last Airbender|136|U|{1}{R}|Creature - Human Cleric|2|2|Firebending 1${1}{R}{R}: Put a +1/+1 counter on this creature.| Firebender Ascension|Avatar: The Last Airbender|137|R|{1}{R}|Enchantment|||When this enchantment enters, create a 2/2 red Soldier creature token with firebending 1.$Whenever a creature you control attacking causes a triggered ability of that creature to trigger, put a quest counter on this enchantment. Then if it has four or more quest counters on it, you may copy that ability. You may choose new targets for the copy.| +Firebending Lesson|Avatar: The Last Airbender|138|C|{R}|Instant - Lesson|||Kicker {4}$Firebending Lesson deals 2 damage to target creature. If this spell was kicked, it deals 5 damage to that creature instead.| Firebending Student|Avatar: The Last Airbender|139|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| How to Start a Riot|Avatar: The Last Airbender|140|C|{2}{R}|Instant - Lesson|||Target creature gains menace until end of turn.$Creatures target player controls get +2/+0 until end of turn.| Iroh's Demonstration|Avatar: The Last Airbender|141|U|{1}{R}|Sorcery - Lesson|||Choose one --$* Iroh's Demonstration deals 1 damage to each creature your opponents control.$* Iroh's Demonstration deals 4 damage to target creature.| @@ -59906,6 +59923,7 @@ Treetop Freedom Fighters|Avatar: The Last Airbender|156|C|{2}{R}|Creature - Huma Twin Blades|Avatar: The Last Airbender|157|U|{2}{R}|Artifact - Equipment|||Flash$When this Equipment enters, attach it to target creature you control. That creature gains double strike until end of turn.$Equipped creature gets +1/+1.$Equip {2}| Ty Lee, Artful Acrobat|Avatar: The Last Airbender|158|U|{2}{R}|Legendary Creature - Human Performer|3|2|Prowess$Whenever Ty Lee attacks, you may pay {1}. When you do, target creature can't block this turn.| War Balloon|Avatar: The Last Airbender|159|U|{2}{R}|Artifact - Vehicle|4|3|Flying${1}: Put a fire counter on this Vehicle.$As long as this Vehicle has three or more fire counters on it, it's an artifact creature.$Crew 3| +Wartime Protestors|Avatar: The Last Airbender|160|R|{3}{R}|Creature - Human Rebel Ally|4|4|Haste$Whenever another Ally you control enters, put a +1/+1 counter on that creature and it gains haste until end of turn.| Yuyan Archers|Avatar: The Last Airbender|161|C|{1}{R}|Creature - Human Archer|3|1|Reach$When this creature enters, you may discard a card. If you do, draw a card.| Zhao, the Moon Slayer|Avatar: The Last Airbender|162|R|{1}{R}|Legendary Creature - Human Soldier|2|2|Menace$Nonbasic lands enter tapped.${7}: Put a conqueror counter on Zhao.$As long as Zhao has a conqueror counter on him, nonbasic lands are Mountains.| Zuko, Exiled Prince|Avatar: The Last Airbender|163|U|{3}{R}|Legendary Creature - Human Noble|4|3|Firebending 3${3}: Exile the top card of your library. You may play that card this turn.| @@ -59925,6 +59943,7 @@ Earthbending Lesson|Avatar: The Last Airbender|176|C|{3}{G}|Sorcery - Lesson|||E Earthen Ally|Avatar: The Last Airbender|177|R|{G}|Creature - Human Soldier Ally|0|2|This creature gets +1/+0 for each color among Allies you control.${2}{W}{U}{B}{R}{G}: Earthbend 5.| Elemental Teachings|Avatar: The Last Airbender|178|R|{4}{G}|Instant - Lesson|||Search your library for up to four land cards with different names and reveal them. An opponent chooses two of those cards. Put the chosen cards into your graveyard and the rest onto the battlefield tapped, then shuffle.| Flopsie, Bumi's Buddy|Avatar: The Last Airbender|179|U|{4}{G}{G}|Legendary Creature - Ape Goat|4|4|When Flopsie enters, put a +1/+1 counter on each creature you control.$Each creature you control with power 4 or greater can't be blocked by more than one creature.| +Foggy Swamp Vinebender|Avatar: The Last Airbender|180|C|{3}{G}|Creature - Human Plant Ally|4|3|This creature can't be blocked by creatures with power 2 or less.$Waterbend {5}: Put a +1/+1 counter on this creature. Activate only during your turn.| Great Divide Guide|Avatar: The Last Airbender|181|R|{1}{G}|Creature - Human Scout Ally|2|3|Each land and Ally you control has "{T}: Add one mana of any color."| Haru, Hidden Talent|Avatar: The Last Airbender|182|U|{1}{G}|Legendary Creature - Human Peasant Ally|1|1|Whenever another Ally you control enters, earthbend 1.| Invasion Tactics|Avatar: The Last Airbender|183|U|{4}{G}|Enchantment|||When this enchantment enters, creatures you control get +2/+2 until end of turn.$Whenever one or more Allies you control deal combat damage to a player, draw a card.| @@ -59953,6 +59972,7 @@ Aang, Destined Savior|Avatar: The Last Airbender|203|R||Legendary Creature - Ava Aang, Swift Savior|Avatar: The Last Airbender|204|R|{1}{W}{U}|Legendary Creature - Human Avatar Ally|2|3|Flash$Flying$When Aang enters, airbend up to one other target creature or spell.$Waterbend {8}: Transform Aang.| Aang and La, Ocean's Fury|Avatar: The Last Airbender|204|R||Legendary Creature - Avatar Spirit Ally|5|5|Reach, trample$Whenever Aang and La attack, put a +1/+1 counter on each tapped creature you control.| Abandon Attachments|Avatar: The Last Airbender|205|C|{1}{U/R}|Instant - Lesson|||You may discard a card. If you do, draw two cards.| +Air Nomad Legacy|Avatar: The Last Airbender|206|U|{W}{U}|Enchantment|||When this enchantment enters, create a Clue token.$Creatures you control with flying get +1/+1.| Avatar Aang|Avatar: The Last Airbender|207|M|{R}{G}{W}{U}|Legendary Creature - Human Avatar Ally|4|4|Flying, firebending 2$Whenever you waterbend, earthbend, firebend, or airbend, draw a card. Then if you've done all four this turn, transform Avatar Aang.| Aang, Master of Elements|Avatar: The Last Airbender|207|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Azula, Cunning Usurper|Avatar: The Last Airbender|208|R|{2}{U}{B}{B}|Legendary Creature - Human Noble Rogue|4|4|Firebending 2$When Azula enters, target opponent exiles a nontoken creature they control, then they exile a nonland card from their graveyard.$During your turn, you may cast cards exiled with Azula and you may cast them as though they had flash. Mana of any type can be spent to cast those spells.| @@ -59986,15 +60006,18 @@ Ozai, the Phoenix King|Avatar: The Last Airbender|235|M|{2}{B}{B}{R}{R}|Legendar Platypus-Bear|Avatar: The Last Airbender|236|C|{1}{G/U}|Creature - Platypus Bear|2|3|Defender$When this creature enters, mill two cards.$As long as there is a Lesson card in your graveyard, this creature can attack as though it didn't have defender.| Pretending Poxbearers|Avatar: The Last Airbender|237|C|{1}{W/B}|Creature - Human Citizen Ally|2|1|When this creature dies, create a 1/1 white Ally creature token.| Professor Zei, Anthropologist|Avatar: The Last Airbender|238|U|{U/R}{U/R}|Legendary Creature - Human Advisor Ally|0|3|{T}, Discard a card: Draw a card.${1}, {T}, Sacrifice Professor Zei: Return target instant or sorcery card from your graveyard to your hand. Activate only during your turn.| +Sandbender Scavengers|Avatar: The Last Airbender|239|R|{W}{B}|Creature - Human Rogue|1|1|Whenever you sacrifice another permanent, put a +1/+1 counter on this creature.$When this creature dies, you may exile it. When you do, return target creature card with mana value less than or equal to this creature's power from your graveyard to the battlefield.| Sokka, Bold Boomeranger|Avatar: The Last Airbender|240|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.| Sokka, Lateral Strategist|Avatar: The Last Airbender|241|U|{1}{W/U}{W/U}|Legendary Creature - Human Warrior Ally|2|4|Vigilance$Whenever Sokka and at least one other creature attack, draw a card.| Sokka, Tenacious Tactician|Avatar: The Last Airbender|242|R|{1}{U}{R}{W}|Legendary Creature - Human Warrior Ally|3|3|Menace, prowess$Other Allies you control have menace and prowess.$Whenever you cast a noncreature spell, create a 1/1 white Ally creature token.| Suki, Kyoshi Warrior|Avatar: The Last Airbender|243|U|{2}{G/W}{G/W}|Legendary Creature - Human Warrior Ally|*|4|Suki's power is equal to the number of creatures you control.$Whenever Suki attacks, create a 1/1 white Ally creature token that's tapped and attacking.| Sun Warriors|Avatar: The Last Airbender|244|U|{2}{R}{W}|Creature - Human Warrior Ally|3|5|Firebending X, where X is the number of creatures you control.${5}: Create a 1/1 white Ally creature token.| Tolls of War|Avatar: The Last Airbender|245|U|{W}{B}|Enchantment|||When this enchantment enters, create a Clue token.$Whenever you sacrifice a permanent during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.| +Toph, Hardheaded Teacher|Avatar: The Last Airbender|246|R|{2}{R}{G}|Legendary Creature - Human Warrior Ally|3|4|When Toph enters, you may discard a card. If you do, return target instant or sorcery card from your graveyard to your hand.$Whenever you cast a spell, earthbend 1. If that spell is a Lesson, put an additional +1/+1 counter on that land.| Toph, the First Metalbender|Avatar: The Last Airbender|247|R|{1}{R}{G}{W}|Legendary Creature - Human Warrior Ally|3|3|Nontoken artifacts you control are lands in addition to their other types.$At the beginning of your end step, earthbend 2.| Uncle Iroh|Avatar: The Last Airbender|248|U|{1}{R/G}{R/G}|Legendary Creature - Human Noble Ally|4|2|Firebending 1$Lesson spells you cast cost {1} less to cast.| Vindictive Warden|Avatar: The Last Airbender|249|C|{2}{B/R}|Creature - Human Soldier|2|3|Menace$Firebending 1${3}: This creature deals 1 damage to each opponent.| +Wandering Musicians|Avatar: The Last Airbender|250|C|{3}{R/W}|Creature - Human Bard Ally|2|5|Whenever this creature attacks, creatures you control get +1/+0 until end of turn.| White Lotus Reinforcements|Avatar: The Last Airbender|251|U|{1}{G}{W}|Creature - Human Soldier Ally|2|3|Vigilance$Other Allies you control get +1/+1.| Zhao, Ruthless Admiral|Avatar: The Last Airbender|252|U|{2}{B/R}{B/R}|Legendary Creature - Human Soldier|3|4|Firebending 2$Whenever you sacrifice another permanent, creatures you control get +1/+0 until end of turn.| Zuko, Conflicted|Avatar: The Last Airbender|253|R|{B}{R}|Legendary Creature - Human Rogue|2|3|At the beginning of your first main phase, choose one that hasn't been chosen and you lose 2 life --$* Draw a card.$* Put a +1/+1 counter on Zuko.$* Add {R}.$* Exile Zuko, then return him to the battlefield under an opponent's control.| @@ -60002,10 +60025,12 @@ Barrels of Blasting Jelly|Avatar: The Last Airbender|254|C|{1}|Artifact|||{1}: A Bender's Waterskin|Avatar: The Last Airbender|255|C|{3}|Artifact|||Untap this artifact during each other player's untap step.${T}: Add one mana of any color.| Fire Nation Warship|Avatar: The Last Airbender|256|U|{3}|Artifact - Vehicle|4|4|Reach$When this Vehicle dies, create a Clue token.$Crew 2| Kyoshi Battle Fan|Avatar: The Last Airbender|257|C|{2}|Artifact - Equipment|||When this Equipment enters, create a 1/1 white Ally creature token, then attach this Equipment to it.$Equipped creature gets +1/+0.$Equip {2}| +Meteor Sword|Avatar: The Last Airbender|258|U|{7}|Artifact - Equipment|||When this Equipment enters, destroy target permanent.$Equipped creature gets +3/+3.$Equip {3}| Planetarium of Wan Shi Tong|Avatar: The Last Airbender|259|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| Trusty Boomerang|Avatar: The Last Airbender|260|U|{1}|Artifact - Equipment|||Equipped creature has "{1}, {T}: Tap target creature. Return Trusty Boomerang to its owner's hand."$Equip {1}| The Walls of Ba Sing Se|Avatar: The Last Airbender|261|M|{8}|Legendary Artifact Creature - Wall|0|30|Defender$Other permanents you control have indestructible.| White Lotus Tile|Avatar: The Last Airbender|262|M|{4}|Artifact|||This artifact enters tapped.${T}: Add X mana of any one color, where X is the greatest number of creatures you control that have a creature type in common.| +Abandoned Air Temple|Avatar: The Last Airbender|263|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {W}.${3}{W}, {T}: Put a +1/+1 counter on each creature you control.| Agna Qel'a|Avatar: The Last Airbender|264|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {U}.${2}{U}, {T}: Draw a card, then discard a card.| Airship Engine Room|Avatar: The Last Airbender|265|C||Land|||This land enters tapped.${T}: Add {U} or {R}.${4}, {T}, Sacrifice this land: Draw a card.| Ba Sing Se|Avatar: The Last Airbender|266|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {G}.${2}{G}, {T}: Earthbend 2. Activate only as a sorcery.| @@ -60018,6 +60043,8 @@ Meditation Pools|Avatar: The Last Airbender|272|C||Land|||This land enters tappe Misty Palms Oasis|Avatar: The Last Airbender|273|C||Land|||This land enters tapped.${T}: Add {W} or {B}.${4}, {T}, Sacrifice this land: Draw a card.| North Pole Gates|Avatar: The Last Airbender|274|C||Land|||This land enters tapped.${T}: Add {W} or {U}.${4}, {T}, Sacrifice this land: Draw a card.| Omashu City|Avatar: The Last Airbender|275|C||Land|||This land enters tapped.${T}: Add {R} or {G}.${4}, {T}, Sacrifice this land: Draw a card.| +Realm of Koh|Avatar: The Last Airbender|276|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {B}.${3}{B}, {T}: Create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."| +Rumble Arena|Avatar: The Last Airbender|277|C||Land|||Vigilance$When this land enters, scry 1.${T}: Add {C}.${1}, {T}: Add one mana of any color.| Secret Tunnel|Avatar: The Last Airbender|278|R||Land - Cave|||This land can't be blocked.${T}: Add {C}.${4}, {T}: Two target creatures you control that share a creature type can't be blocked this turn.| Serpent's Pass|Avatar: The Last Airbender|279|C||Land|||This land enters tapped.${T}: Add {U} or {B}.${4}, {T}, Sacrifice this land: Draw a card.| Sun-Blessed Peak|Avatar: The Last Airbender|280|C||Land|||This land enters tapped.${T}: Add {R} or {W}.${4}, {T}, Sacrifice this land: Draw a card.| @@ -60043,6 +60070,7 @@ Aang and La, Ocean's Fury|Avatar: The Last Airbender|298|R||Legendary Creature - Fire Nation Attacks|Avatar: The Last Airbender|299|U|{4}{R}|Instant|||Create two 2/2 red Soldier creature tokens with firebending 1.$Flashback {8}{R}| Crashing Wave|Avatar: The Last Airbender|300|U|{U}{U}|Sorcery|||As an additional cost to cast this spell, waterbend {X}.$Tap up to X target creatures, then distribute three stun counters among tapped creatures your opponents control.| Combustion Technique|Avatar: The Last Airbender|301|U|{1}{R}|Instant - Lesson|||Combustion Technique deals damage equal to 2 plus the number of Lesson cards in your graveyard to target creature. If that creature would die this turn, exile it instead.| +Zuko, Conflicted|Avatar: The Last Airbender|302|R|{B}{R}|Legendary Creature - Human Rogue|2|3|At the beginning of your first main phase, choose one that hasn't been chosen and you lose 2 life --$* Draw a card.$* Put a +1/+1 counter on Zuko.$* Add {R}.$* Exile Zuko, then return him to the battlefield under an opponent's control.| Azula, Cunning Usurper|Avatar: The Last Airbender|303|R|{2}{U}{B}{B}|Legendary Creature - Human Noble Rogue|4|4|Firebending 2$When Azula enters, target opponent exiles a nontoken creature they control, then they exile a nonland card from their graveyard.$During your turn, you may cast cards exiled with Azula and you may cast them as though they had flash. Mana of any type can be spent to cast those spells.| Aang, at the Crossroads|Avatar: The Last Airbender|304|R|{2}{G}{W}{U}|Legendary Creature - Human Avatar Ally|3|3|Flying$When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order.$When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep.| Aang, Destined Savior|Avatar: The Last Airbender|304|R||Legendary Creature - Avatar Ally|4|4|Flying$Land creatures you control have vigilance.$At the beginning of combat on your turn, earthbend 2.| @@ -60064,6 +60092,8 @@ Tiger-Seal|Avatar: The Last Airbender|318|R|{U}|Creature - Cat Seal|3|3|Vigilanc The Unagi of Kyoshi Island|Avatar: The Last Airbender|319|R|{3}{U}{U}|Legendary Creature - Serpent|5|5|Flash$Ward--Waterbend {4}$Whenever an opponent draws their second card each turn, draw two cards.| Wan Shi Tong, Librarian|Avatar: The Last Airbender|320|M|{X}{U}{U}|Legendary Creature - Bird Spirit|1|1|Flash$Flying, vigilance$When Wan Shi Tong enters, put X +1/+1 counters on him. Then draw half X cards, rounded down.$Whenever an opponent searches their library, put a +1/+1 counter on Wan Shi Tong and draw a card.| The Fire Nation Drill|Avatar: The Last Airbender|321|R|{2}{B}{B}|Legendary Artifact - Vehicle|6|3|Trample$When The Fire Nation Drill enters, you may tap it. When you do, destroy target creature with power 4 or less.${1}: Permanents your opponents control lose hexproof and indestructible until end of turn.$Crew 2| +Koh, the Face Stealer|Avatar: The Last Airbender|322|M|{4}{B}{B}|Legendary Creature - Shapeshifter Spirit|6|6|When Koh enters, exile up to one other target creature.$Whenever another nontoken creature dies, you may exile it.$Pay 1 life: Choose a creature card exiled with Koh.$Koh has all activated and triggered abilities of the last chosen card.| +Phoenix Fleet Airship|Avatar: The Last Airbender|323|M|{2}{B}{B}|Artifact - Vehicle|4|4|Flying$At the beginning of your end step, if you sacrificed a permanent this turn, create a token that's a copy of this Vehicle.$As long as you control eight or more permanents named Phoenix Fleet Airship, this Vehicle is an artifact creature.$Crew 1| Raven Eagle|Avatar: The Last Airbender|324|R|{2}{B}|Creature - Bird Assassin|2|3|Flying$Whenever this creature enters or attacks, exile up to one target card from a graveyard. If a creature card is exiled this way, create a Clue token.$Whenever you draw your second card each turn, each opponent loses 1 life and you gain 1 life.| Ran and Shaw|Avatar: The Last Airbender|325|R|{3}{R}{R}|Legendary Creature - Dragon|4|4|Flying, firebending 2$When Ran and Shaw enter, if you cast them and there are three or more Dragon and/or Lesson cards in your graveyard, create a token that's a copy of Ran and Shaw, except it's not legendary.${3}{R}: Dragons you control get +2/+0 until end of turn.| Badgermole Cub|Avatar: The Last Airbender|326|M|{1}{G}|Creature - Badger Mole|2|2|When this creature enters, earthbend 1.$Whenever you tap a creature for mana, add an additional {G}.| @@ -60114,8 +60144,9 @@ Toph, the First Metalbender|Avatar: The Last Airbender|362|R|{1}{R}{G}{W}|Legend Avatar Aang|Avatar: The Last Airbender|363|M|{R}{G}{W}{U}|Legendary Creature - Human Avatar Ally|4|4|Flying, firebending 2$Whenever you waterbend, earthbend, firebend, or airbend, draw a card. Then if you've done all four this turn, transform Avatar Aang.| Aang, Master of Elements|Avatar: The Last Airbender|363|M||Legendary Creature - Avatar Ally|6|6|Flying$Spells you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| Airbender Ascension|Avatar: The Last Airbender|364|R|{1}{W}|Enchantment|||When this enchantment enters, airbend up to one target creature.$Whenever a creature you control enters, put a quest counter on this enchantment.$At the beginning of your end step, if this enchantment has four or more quest counters on it, exile up to one target creature you control, then return it to the battlefield under its owner's control.| -Avatar's Wrath|Avatar: The Last Airbender|365|R|{2}{W}{W}|Sorcery|||Choose up to one target creature, then airbend each other creature.$Until your next turn, your opponents can't cast spells from anywhere other than their hand.$Exile Avatar's Wrath.| +Avatar's Wrath|Avatar: The Last Airbender|365|R|{2}{W}{W}|Sorcery|||Choose up to one target creature, then airbend all other creatures.$Until your next turn, your opponents can't cast spells from anywhere other than their hand.$Exile Avatar's Wrath.| Hakoda, Selfless Commander|Avatar: The Last Airbender|366|R|{3}{W}|Legendary Creature - Human Warrior Ally|3|5|Vigilance$You may look at the top card of your library any time.$You may cast Ally spells from the top of your library.$Sacrifice Hakoda: Creatures you control get +0/+5 and gain indestructible until end of turn.| +South Pole Voyager|Avatar: The Last Airbender|367|R|{1}{W}|Creature - Human Scout Ally|2|2|Whenever this creature or another Ally you control enters, you gain 1 life. If this is the second time this ability has resolved this turn, draw a card.| Suki, Courageous Rescuer|Avatar: The Last Airbender|368|R|{1}{W}{W}|Legendary Creature - Human Warrior Ally|2|4|Other creatures you control get +1/+0.$Whenever another permanent you control leaves the battlefield during your turn, create a 1/1 white Ally creature token. This ability triggers only once each turn.| The Mechanist, Aerial Artisan|Avatar: The Last Airbender|369|R|{2}{U}|Legendary Creature - Human Artificer Ally|1|3|Whenever you cast a noncreature spell, create a Clue token.${T}: Until end of turn, target artifact token you control becomes a 3/1 Construct artifact creature with flying.| Spirit Water Revival|Avatar: The Last Airbender|370|R|{1}{U}{U}|Sorcery|||As an additional cost to cast this spell, you may waterbend {6}.$Draw two cards. If this spell's additional cost was paid, instead shuffle your graveyard into your library, draw seven cards, and you have no maximum hand size for the rest of the game.$Exile Spirit Water Revival.| @@ -60123,17 +60154,23 @@ Ty Lee, Chi Blocker|Avatar: The Last Airbender|371|R|{2}{U}|Legendary Creature - Boiling Rock Rioter|Avatar: The Last Airbender|372|R|{2}{B}|Creature - Human Rogue Ally|3|3|Firebending 1$Tap an untapped Ally you control: Exile target card from a graveyard.$Whenever this creature attacks, you may cast an Ally spell from among cards you own exiled with this creature.| Day of Black Sun|Avatar: The Last Airbender|373|R|{X}{B}{B}|Sorcery|||Each creature with mana value X or less loses all abilities until end of turn. Destroy those creatures.| Mai, Scornful Striker|Avatar: The Last Airbender|374|R|{1}{B}|Legendary Creature - Human Noble Ally|2|2|First strike$Whenever a player casts a noncreature spell, they lose 2 life.| +Wartime Protestors|Avatar: The Last Airbender|375|R|{3}{R}|Creature - Human Rebel Ally|4|4|Haste$Whenever another Ally you control enters, put a +1/+1 counter on that creature and it gains haste until end of turn.| +Zhao, the Moon Slayer|Avatar: The Last Airbender|376|R|{1}{R}|Legendary Creature - Human Soldier|2|2|Menace$Nonbasic lands enter tapped.${7}: Put a conqueror counter on Zhao.$As long as Zhao has a conqueror counter on him, nonbasic lands are Mountains.| Earthen Ally|Avatar: The Last Airbender|377|R|{G}|Creature - Human Soldier Ally|0|2|This creature gets +1/+0 for each color among Allies you control.${2}{W}{U}{B}{R}{G}: Earthbend 5.| Elemental Teachings|Avatar: The Last Airbender|378|R|{4}{G}|Instant - Lesson|||Search your library for up to four land cards with different names and reveal them. An opponent chooses two of those cards. Put the chosen cards into your graveyard and the rest onto the battlefield tapped, then shuffle.| Beifong's Bounty Hunters|Avatar: The Last Airbender|379|R|{2}{B}{G}|Creature - Human Mercenary|4|4|Whenever a nonland creature you control dies, earthbend X, where X is that creature's power.| Earth King's Lieutenant|Avatar: The Last Airbender|380|R|{G}{W}|Creature - Human Soldier Ally|1|1|Trample$When this creature enters, put a +1/+1 counter on each other Ally creature you control.$Whenever another Ally you control enters, put a +1/+1 counter on this creature.| Iroh, Tea Master|Avatar: The Last Airbender|381|R|{1}{R}{W}|Legendary Creature - Human Citizen Ally|2|2|When Iroh enters, create a Food token.$At the beginning of combat on your turn, you may have target opponent gain control of target permanent you control. When you do, create a 1/1 white Ally creature token. Put a +1/+1 counter on that token for each permanent you own that your opponents control.| +Sandbender Scavengers|Avatar: The Last Airbender|382|R|{W}{B}|Creature - Human Rogue|1|1|Whenever you sacrifice another permanent, put a +1/+1 counter on this creature.$When this creature dies, you may exile it. When you do, return target creature card with mana value less than or equal to this creature's power from your graveyard to the battlefield.| Sokka, Bold Boomeranger|Avatar: The Last Airbender|383|R|{U}{R}|Legendary Creature - Human Warrior Ally|1|1|When Sokka enters, discard up to two cards, then draw that many cards.$Whenever you cast an artifact or Lesson spell, put a +1/+1 counter on Sokka.| +Toph, Hardheaded Teacher|Avatar: The Last Airbender|384|R|{2}{R}{G}|Legendary Creature - Human Warrior Ally|3|4|When Toph enters, you may discard a card. If you do, return target instant or sorcery card from your graveyard to your hand.$Whenever you cast a spell, earthbend 1. If that spell is a Lesson, put an additional +1/+1 counter on that land.| Planetarium of Wan Shi Tong|Avatar: The Last Airbender|385|M|{6}|Legendary Artifact|||{1}, {T}: Scry 2.$Whenever you scry or surveil, look at the top card of your library. You may cast that card without paying its mana cost. Do this only once each turn.| +Abandoned Air Temple|Avatar: The Last Airbender|386|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {W}.${3}{W}, {T}: Put a +1/+1 counter on each creature you control.| Agna Qel'a|Avatar: The Last Airbender|387|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {U}.${2}{U}, {T}: Draw a card, then discard a card.| Ba Sing Se|Avatar: The Last Airbender|388|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {G}.${2}{G}, {T}: Earthbend 2. Activate only as a sorcery.| Fire Nation Palace|Avatar: The Last Airbender|389|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {R}.${1}{R}, {T}: Target creature you control gains firebending 4 until end of turn.| Jasmine Dragon Tea Shop|Avatar: The Last Airbender|390|R||Land|||{T}: Add {C}.${T}: Add one mana of any color. Spend this mana only to cast an Ally spell or activate an ability of an Ally source.${5}, {T}: Create a 1/1 white Ally creature token.| +Realm of Koh|Avatar: The Last Airbender|391|R||Land|||This land enters tapped unless you control a basic land.${T}: Add {B}.${3}{B}, {T}: Create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."| Secret Tunnel|Avatar: The Last Airbender|392|R||Land - Cave|||This land can't be blocked.${T}: Add {C}.${4}, {T}: Two target creatures you control that share a creature type can't be blocked this turn.| Firebending Student|Avatar: The Last Airbender|393|R|{1}{R}|Creature - Human Monk|1|2|Prowess$Firebending X, where X is this creature's power.| Momo, Friendly Flier|Avatar: The Last Airbender|394|R|{W}|Legendary Creature - Lemur Bat Ally|1|1|Flying$The first non-Lemur creature spell with flying you cast during each of your turns costs {1} less to cast.$Whenever another creature you control with flying enters, Momo gets +1/+1 until end of turn.| -- 2.47.2 From 6e6812189720c57520be478a14e867b62aca70df Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 09:34:11 -0500 Subject: [PATCH 135/261] [TLE] update spoiler and reprints --- .../sets/AvatarTheLastAirbenderEternal.java | 35 +++++++++---- Utils/mtg-cards-data.txt | 51 +++++++++++++++++-- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index eee1f3e1654..2a1f684425f 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -30,7 +30,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Aang's Defense", 266, Rarity.COMMON, mage.cards.a.AangsDefense.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, Air Nomad", 210, Rarity.RARE, mage.cards.a.AangAirNomad.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, Air Nomad", 265, Rarity.RARE, mage.cards.a.AangAirNomad.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Aang, Airbending Master", 74, Rarity.MYTHIC, mage.cards.a.AangAirbendingMaster.class)); + cards.add(new SetCardInfo("Aang, Airbending Master", 171, Rarity.MYTHIC, mage.cards.a.AangAirbendingMaster.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, Airbending Master", 74, Rarity.MYTHIC, mage.cards.a.AangAirbendingMaster.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aardvark Sloth", 212, Rarity.COMMON, mage.cards.a.AardvarkSloth.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aardvark Sloth", 267, Rarity.COMMON, mage.cards.a.AardvarkSloth.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Acrobatic Leap", 151, Rarity.COMMON, mage.cards.a.AcrobaticLeap.class)); @@ -39,12 +40,14 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Appa, Aang's Companion", 214, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Appa, Aang's Companion", 268, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Arcane Signet", 315, Rarity.RARE, mage.cards.a.ArcaneSignet.class)); - cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 130, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class)); - cards.add(new SetCardInfo("Avatar Roku, Firebender", 112, Rarity.MYTHIC, mage.cards.a.AvatarRokuFirebender.class)); - cards.add(new SetCardInfo("Azula, Ruthless Firebender", 101, Rarity.MYTHIC, mage.cards.a.AzulaRuthlessFirebender.class)); + cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 130, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Avatar Kyoshi, Earthbender", 201, Rarity.MYTHIC, mage.cards.a.AvatarKyoshiEarthbender.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Avatar Roku, Firebender", 112, Rarity.MYTHIC, mage.cards.a.AvatarRokuFirebender.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Avatar Roku, Firebender", 191, Rarity.MYTHIC, mage.cards.a.AvatarRokuFirebender.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Azula, Ruthless Firebender", 101, Rarity.MYTHIC, mage.cards.a.AzulaRuthlessFirebender.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Azula, Ruthless Firebender", 184, Rarity.MYTHIC, mage.cards.a.AzulaRuthlessFirebender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bastion of Remembrance", 160, Rarity.UNCOMMON, mage.cards.b.BastionOfRemembrance.class)); cards.add(new SetCardInfo("Beastmaster Ascension", 39, Rarity.MYTHIC, mage.cards.b.BeastmasterAscension.class)); - cards.add(new SetCardInfo("Beastmaster's Magemark", 9999, Rarity.MYTHIC, mage.cards.b.BeastmastersMagemark.class)); cards.add(new SetCardInfo("Black Sun's Zenith", 22, Rarity.MYTHIC, mage.cards.b.BlackSunsZenith.class)); cards.add(new SetCardInfo("Blasphemous Act", 26, Rarity.MYTHIC, mage.cards.b.BlasphemousAct.class)); cards.add(new SetCardInfo("Bloodchief Ascension", 23, Rarity.MYTHIC, mage.cards.b.BloodchiefAscension.class)); @@ -91,6 +94,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Explosive Shot", 279, Rarity.COMMON, mage.cards.e.ExplosiveShot.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fabled Passage", 57, Rarity.MYTHIC, mage.cards.f.FabledPassage.class)); cards.add(new SetCardInfo("Feed the Swarm", 257, Rarity.COMMON, mage.cards.f.FeedTheSwarm.class)); + cards.add(new SetCardInfo("Fervor", 29, Rarity.MYTHIC, mage.cards.f.Fervor.class)); + cards.add(new SetCardInfo("Fevered Visions", 49, Rarity.RARE, mage.cards.f.FeveredVisions.class)); cards.add(new SetCardInfo("Fierce Guardianship", 307, Rarity.RARE, mage.cards.f.FierceGuardianship.class)); cards.add(new SetCardInfo("Fiery Confluence", 165, Rarity.RARE, mage.cards.f.FieryConfluence.class)); cards.add(new SetCardInfo("Fire Nation Ambushers", 229, Rarity.COMMON, mage.cards.f.FireNationAmbushers.class)); @@ -111,22 +116,28 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Heartbeat of Spring", 42, Rarity.MYTHIC, mage.cards.h.HeartbeatOfSpring.class)); cards.add(new SetCardInfo("Heroic Intervention", 43, Rarity.MYTHIC, mage.cards.h.HeroicIntervention.class)); cards.add(new SetCardInfo("Hippo-Cows", 252, Rarity.COMMON, mage.cards.h.HippoCows.class)); + cards.add(new SetCardInfo("Humble Defector", 30, Rarity.MYTHIC, mage.cards.h.HumbleDefector.class)); cards.add(new SetCardInfo("Imprisoned in the Moon", 14, Rarity.MYTHIC, mage.cards.i.ImprisonedInTheMoon.class)); cards.add(new SetCardInfo("Inspiring Call", 168, Rarity.UNCOMMON, mage.cards.i.InspiringCall.class)); cards.add(new SetCardInfo("Insurrection", 31, Rarity.MYTHIC, mage.cards.i.Insurrection.class)); cards.add(new SetCardInfo("Intruder Alarm", 15, Rarity.MYTHIC, mage.cards.i.IntruderAlarm.class)); - cards.add(new SetCardInfo("Iroh, Dragon of the West", 119, Rarity.RARE, mage.cards.i.IrohDragonOfTheWest.class)); + cards.add(new SetCardInfo("Iroh, Dragon of the West", 119, Rarity.RARE, mage.cards.i.IrohDragonOfTheWest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Iroh, Dragon of the West", 194, Rarity.RARE, mage.cards.i.IrohDragonOfTheWest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 240, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 282, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Join the Dance", 50, Rarity.UNCOMMON, mage.cards.j.JoinTheDance.class)); cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Heroic Healer", 269, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Katara, Waterbending Master", 93, Rarity.MYTHIC, mage.cards.k.KataraWaterbendingMaster.class)); + cards.add(new SetCardInfo("Katara, Waterbending Master", 180, Rarity.MYTHIC, mage.cards.k.KataraWaterbendingMaster.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Katara, Waterbending Master", 93, Rarity.MYTHIC, mage.cards.k.KataraWaterbendingMaster.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Kindly Customer", 79, Rarity.COMMON, mage.cards.k.KindlyCustomer.class)); cards.add(new SetCardInfo("Koma, Cosmos Serpent", 51, Rarity.MYTHIC, mage.cards.k.KomaCosmosSerpent.class)); cards.add(new SetCardInfo("Komodo Rhino", 241, Rarity.COMMON, mage.cards.k.KomodoRhino.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Komodo Rhino", 283, Rarity.COMMON, mage.cards.k.KomodoRhino.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Kyoshi Warrior Guard", 216, Rarity.COMMON, mage.cards.k.KyoshiWarriorGuard.class)); + cards.add(new SetCardInfo("Lightning Bolt", 32, Rarity.MYTHIC, mage.cards.l.LightningBolt.class)); cards.add(new SetCardInfo("Lion Vulture", 232, Rarity.RARE, mage.cards.l.LionVulture.class)); + cards.add(new SetCardInfo("Lita, Mechanical Engineer", 4, Rarity.MYTHIC, mage.cards.l.LitaMechanicalEngineer.class)); cards.add(new SetCardInfo("Lost in the Spirit World", 224, Rarity.UNCOMMON, mage.cards.l.LostInTheSpiritWorld.class)); cards.add(new SetCardInfo("Loyal Fire Sage", 242, Rarity.UNCOMMON, mage.cards.l.LoyalFireSage.class)); cards.add(new SetCardInfo("Many Partings", 169, Rarity.COMMON, mage.cards.m.ManyPartings.class)); @@ -184,9 +195,11 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Sundial of the Infinite", 55, Rarity.MYTHIC, mage.cards.s.SundialOfTheInfinite.class)); cards.add(new SetCardInfo("Suspicious Bookcase", 170, Rarity.UNCOMMON, mage.cards.s.SuspiciousBookcase.class)); cards.add(new SetCardInfo("Swiftfoot Boots", 317, Rarity.RARE, mage.cards.s.SwiftfootBoots.class)); + cards.add(new SetCardInfo("Tarnished Citadel", 59, Rarity.MYTHIC, mage.cards.t.TarnishedCitadel.class)); cards.add(new SetCardInfo("Taunting Challenge", 46, Rarity.MYTHIC, mage.cards.t.TauntingChallenge.class)); cards.add(new SetCardInfo("Teferi's Protection", 7, Rarity.MYTHIC, mage.cards.t.TeferisProtection.class)); - cards.add(new SetCardInfo("The Cabbage Merchant", 134, Rarity.RARE, mage.cards.t.TheCabbageMerchant.class)); + cards.add(new SetCardInfo("The Cabbage Merchant", 134, Rarity.RARE, mage.cards.t.TheCabbageMerchant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Cabbage Merchant", 203, Rarity.RARE, mage.cards.t.TheCabbageMerchant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Great Henge", 41, Rarity.MYTHIC, mage.cards.t.TheGreatHenge.class)); cards.add(new SetCardInfo("The Terror of Serpent's Pass", 225, Rarity.RARE, mage.cards.t.TheTerrorOfSerpentsPass.class)); cards.add(new SetCardInfo("Three Dreams", 8, Rarity.MYTHIC, mage.cards.t.ThreeDreams.class)); @@ -195,7 +208,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Thriving Heath", 262, Rarity.COMMON, mage.cards.t.ThrivingHeath.class)); cards.add(new SetCardInfo("Thriving Isle", 263, Rarity.COMMON, mage.cards.t.ThrivingIsle.class)); cards.add(new SetCardInfo("Thriving Moor", 264, Rarity.COMMON, mage.cards.t.ThrivingMoor.class)); - cards.add(new SetCardInfo("Toph, Earthbending Master", 145, Rarity.MYTHIC, mage.cards.t.TophEarthbendingMaster.class)); + cards.add(new SetCardInfo("Toph, Earthbending Master", 145, Rarity.MYTHIC, mage.cards.t.TophEarthbendingMaster.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Toph, Earthbending Master", 209, Rarity.MYTHIC, mage.cards.t.TophEarthbendingMaster.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Toucan-Puffin", 88, Rarity.COMMON, mage.cards.t.ToucanPuffin.class)); cards.add(new SetCardInfo("Training Grounds", 20, Rarity.MYTHIC, mage.cards.t.TrainingGrounds.class)); cards.add(new SetCardInfo("Treetop Village", 60, Rarity.MYTHIC, mage.cards.t.TreetopVillage.class)); @@ -219,7 +233,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Zuko's Offense", 288, Rarity.COMMON, mage.cards.z.ZukosOffense.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Zuko, Avatar Hunter", 246, Rarity.RARE, mage.cards.z.ZukoAvatarHunter.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Zuko, Avatar Hunter", 287, Rarity.RARE, mage.cards.z.ZukoAvatarHunter.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Zuko, Firebending Master", 127, Rarity.MYTHIC, mage.cards.z.ZukoFirebendingMaster.class)); + cards.add(new SetCardInfo("Zuko, Firebending Master", 127, Rarity.MYTHIC, mage.cards.z.ZukoFirebendingMaster.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Zuko, Firebending Master", 200, Rarity.MYTHIC, mage.cards.z.ZukoFirebendingMaster.class, NON_FULL_USE_VARIOUS)); cards.removeIf(setCardInfo -> unfinished.contains(setCardInfo.getName())); } diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index b8180d97822..0a34c5276c5 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -60477,6 +60477,7 @@ Gwenom, Remorseless|Marvel's Spider-Man|286|M|{3}{B}{B}|Legendary Creature - Sym Brought Back|Avatar: The Last Airbender Eternal|1|M|{W}{W}|Instant|||Choose up to two target permanent cards in your graveyard that were put there from the battlefield this turn. Return them to the battlefield tapped.| Drannith Magistrate|Avatar: The Last Airbender Eternal|2|M|{1}{W}|Creature - Human Wizard|1|3|Your opponents can't cast spells from anywhere other than their hands.| Empty City Ruse|Avatar: The Last Airbender Eternal|3|M|{W}|Sorcery|||Target opponent skips all combat phases of their next turn.| +Lita, Mechanical Engineer|Avatar: The Last Airbender Eternal|4|M|{2}{W}|Legendary Artifact Creature - Artificer|3|3|Vigilance$At the beginning of your end step, untap each other artifact creature you control.${3}{W}, {T}: Create a 5/5 colorless Vehicle artifact token named Zeppelin with flying and crew 3.| Release to Memory|Avatar: The Last Airbender Eternal|5|M|{3}{W}|Instant|||Exile target opponent's graveyard. For each creature card exiled this way, create a 1/1 colorless Spirit creature token.| Scout's Warning|Avatar: The Last Airbender Eternal|6|M|{W}|Instant|||The next creature card you play this turn can be played as though it had flash.$Draw a card.| Teferi's Protection|Avatar: The Last Airbender Eternal|7|M|{2}{W}|Instant|||Until your next turn, your life total can't change and you gain protection from everything. All permanents you control phase out.$Exile Teferi's Protection.| @@ -60501,7 +60502,10 @@ Noxious Gearhulk|Avatar: The Last Airbender Eternal|25|M|{4}{B}{B}|Artifact Crea Blasphemous Act|Avatar: The Last Airbender Eternal|26|M|{8}{R}|Sorcery|||This spell costs {1} less to cast for each creature on the battlefield.$Blasphemous Act deals 13 damage to each creature.| Diaochan, Artful Beauty|Avatar: The Last Airbender Eternal|27|M|{3}{R}|Legendary Creature - Human Advisor|1|1|{T}: Destroy target creature of your choice, then destroy target creature of an opponent's choice. Activate only during your turn, before attackers are declared.| Dockside Extortionist|Avatar: The Last Airbender Eternal|28|M|{1}{R}|Creature - Goblin Pirate|1|2|When this creature enters, create X Treasure tokens, where X is the number of artifacts and enchantments your opponents control.| +Fervor|Avatar: The Last Airbender Eternal|29|M|{2}{R}|Enchantment|||Creatures you control have haste.| +Humble Defector|Avatar: The Last Airbender Eternal|30|M|{1}{R}|Creature - Human Rogue|2|1|{T}: Draw two cards. Target opponent gains control of this creature. Activate only during your turn.| Insurrection|Avatar: The Last Airbender Eternal|31|M|{5}{R}{R}{R}|Sorcery|||Untap all creatures and gain control of them until end of turn. They gain haste until end of turn.| +Lightning Bolt|Avatar: The Last Airbender Eternal|32|M|{R}|Instant|||Lightning Bolt deals 3 damage to any target.| Mirrorwing Dragon|Avatar: The Last Airbender Eternal|33|M|{3}{R}{R}|Creature - Dragon|4|5|Flying$Whenever a player casts an instant or sorcery spell that targets only this creature, that player copies that spell for each other creature they control that the spell could target. Each copy targets a different one of those creatures.| Rending Volley|Avatar: The Last Airbender Eternal|34|M|{R}|Instant|||This spell can't be countered.$Rending Volley deals 4 damage to target white or blue creature.| Searing Blood|Avatar: The Last Airbender Eternal|35|M|{R}{R}|Instant|||Searing Blood deals 2 damage to target creature. When that creature dies this turn, Searing Blood deals 3 damage to the creature's controller.| @@ -60518,6 +60522,8 @@ Rites of Flourishing|Avatar: The Last Airbender Eternal|45|M|{2}{G}|Enchantment| Taunting Challenge|Avatar: The Last Airbender Eternal|46|M|{1}{G}{G}|Sorcery|||All creatures able to block target creature this turn do so.| Captain Sisay|Avatar: The Last Airbender Eternal|47|M|{2}{G}{W}|Legendary Creature - Human Soldier|2|2|{T}: Search your library for a legendary card, reveal that card, put it into your hand, then shuffle.| Eladamri's Call|Avatar: The Last Airbender Eternal|48|M|{G}{W}|Instant|||Search your library for a creature card, reveal that card, put it into your hand, then shuffle.| +Fevered Visions|Avatar: The Last Airbender Eternal|49|R|{1}{U}{R}|Enchantment|||At the beginning of each player's end step, that player draws a card. If the player is your opponent and has four or more cards in hand, this enchantment deals 2 damage to that player.| +Join the Dance|Avatar: The Last Airbender Eternal|50|U|{G}{W}|Sorcery|||Create two 1/1 white Human creature tokens.$Flashback {3}{G}{W}| Koma, Cosmos Serpent|Avatar: The Last Airbender Eternal|51|M|{3}{G}{G}{U}{U}|Legendary Creature - Serpent|6|6|This spell can't be countered.$At the beginning of each upkeep, create a 3/3 blue Serpent creature token named Koma's Coil.$Sacrifice another Serpent: Choose one --$* Tap target permanent. Its activated abilities can't be activated this turn.$* Koma gains indestructible until end of turn.| Rhys the Redeemed|Avatar: The Last Airbender Eternal|52|M|{G/W}|Legendary Creature - Elf Warrior|1|1|{2}{G/W}, {T}: Create a 1/1 green and white Elf Warrior creature token.${4}{G/W}{G/W}, {T}: For each creature token you control, create a token that's a copy of that creature.| Cityscape Leveler|Avatar: The Last Airbender Eternal|53|M|{8}|Artifact Creature - Construct|8|8|Trample$When you cast this spell and whenever this creature attacks, destroy up to one target nonland permanent. Its controller creates a tapped Powerstone token.$Unearth {8}| @@ -60526,6 +60532,7 @@ Sundial of the Infinite|Avatar: The Last Airbender Eternal|55|M|{2}|Artifact|||{ Dark Depths|Avatar: The Last Airbender Eternal|56|M||Legendary Snow Land|||Dark Depths enters with ten ice counters on it.${3}: Remove an ice counter from Dark Depths.$When Dark Depths has no ice counters on it, sacrifice it. If you do, create Marit Lage, a legendary 20/20 black Avatar creature token with flying and indestructible.| Fabled Passage|Avatar: The Last Airbender Eternal|57|M||Land|||{T}, Sacrifice this land: Search your library for a basic land card, put it onto the battlefield tapped, then shuffle. Then if you control four or more lands, untap that land.| Sunbaked Canyon|Avatar: The Last Airbender Eternal|58|M||Land|||{T}, Pay 1 life: Add {R} or {W}.${1}, {T}, Sacrifice this land: Draw a card.| +Tarnished Citadel|Avatar: The Last Airbender Eternal|59|M||Land|||{T}: Add {C}.${T}: Add one mana of any color. This land deals 3 damage to you.| Treetop Village|Avatar: The Last Airbender Eternal|60|M||Land|||This land enters tapped.${T}: Add {G}.${1}{G}: This land becomes a 3/3 green Ape creature with trample until end of turn. It's still a land.| Valakut, the Molten Pinnacle|Avatar: The Last Airbender Eternal|61|M||Land|||This land enters tapped.$Whenever a Mountain you control enters, if you control at least five other Mountains, you may have this land deal 3 damage to any target.${T}: Add {R}.| Appa, the Vigilant|Avatar: The Last Airbender Eternal|62|R|{5}{W}{W}|Legendary Creature - Bison Ally|6|6|Flying, vigilance$Whenever Appa or another Ally you control enters, creatures you control get +1/+1 and gain flying and vigilance until end of turn.| @@ -60543,7 +60550,7 @@ Uncle's Musings|Avatar: The Last Airbender Eternal|73|R|{2}{G}{G}|Sorcery|||Conv Aang, Airbending Master|Avatar: The Last Airbender Eternal|74|M|{4}{W}|Legendary Creature - Human Avatar Ally|4|4|When Aang enters, airbend another target creature.$Whenever one or more creatures you control leave the battlefield without dying, you get an experience counter.$At the beginning of your upkeep, create a 1/1 white Ally creature token for each experience counter you have.| Air Nomad Student|Avatar: The Last Airbender Eternal|75|U|{3}{W}|Creature - Human Monk|2|2|Flying$At the beginning of your end step, if this creature didn't attack this turn, put a +1/+1 counter on it.| The Duke, Rebel Sentry|Avatar: The Last Airbender Eternal|76|U|{W}|Legendary Creature - Human Rebel Ally|0|1|The Duke enters with a +1/+1 counter on him.${T}, Remove a counter from The Duke: Put a +1/+1 counter on another target creature you control. It gains hexproof until end of turn.| -Inspired Insurgent|Avatar: The Last Airbender Eternal|77|C|{1}{W}|Creature - Human Peasant Ally|2|2|| +Inspired Insurgent|Avatar: The Last Airbender Eternal|77|C|{1}{W}|Creature - Human Peasant Ally|2|2|{1}, Sacrifice this creature: Destroy target artifact or enchantment.| Jet, Rebel Leader|Avatar: The Last Airbender Eternal|78|R|{3}{W}|Legendary Creature - Human Rebel Ally|3|4|Whenever Jet attacks, look at the top five cards of your library. You may put a creature card with mana value 3 or less from among them onto the battlefield tapped and attacking. Put the rest on the bottom of your library in a random order.| Kindly Customer|Avatar: The Last Airbender Eternal|79|C|{1}{W}|Creature - Human Citizen|1|1|When this creature enters, draw a card.| Koala-Sheep|Avatar: The Last Airbender Eternal|80|C|{2}{W}|Creature - Bear Sheep|3|2|When this creature enters, you gain 3 life.| @@ -60597,7 +60604,7 @@ Zuko, Firebending Master|Avatar: The Last Airbender Eternal|127|M|{1}{R}|Legenda Animal Attendant|Avatar: The Last Airbender Eternal|128|U|{1}{G}|Creature - Human Citizen|2|2|{T}: Add one mana of any color. If that mana is spent to cast a non-Human creature spell, that creature enters with an additional +1/+1 counter on it.| The Art of Tea|Avatar: The Last Airbender Eternal|129|C|{1}{G}|Instant - Lesson|||Put a +1/+1 counter on up to one target creature you control. Create a Food token.| Avatar Kyoshi, Earthbender|Avatar: The Last Airbender Eternal|130|M|{5}{G}{G}{G}|Legendary Creature - Human Avatar|6|6|During your turn, Avatar Kyoshi has hexproof.$At the beginning of combat on your turn, earthbend 8, then untap that land.| -Bison Whistle|Avatar: The Last Airbender Eternal|131|R|{1}{G}|Artifact|||{1}, {T}: Look at the top card of your library. If it's a Bison card, you may put it onto the battlefield. If it's a creature card, you may reveal it and put it into your hand. Otherwise, you may put it into your$graveyard.| +Bison Whistle|Avatar: The Last Airbender Eternal|131|R|{1}{G}|Artifact|||{1}, {T}: Look at the top card of your library. If it's a Bison card, you may put it onto the battlefield. If it's a creature card, you may reveal it and put it into your hand. Otherwise, you may put it into your graveyard.| Bosco, Just a Bear|Avatar: The Last Airbender Eternal|132|U|{4}{G}|Legendary Creature - Bear|4|4|When Bosco enters, create a Food token for each legendary creature you control.${2}{G}, Sacrifice a Food: Put two +1/+1 counters on Bosco. He gains trample until end of turn.| Bumi's Feast Lecture|Avatar: The Last Airbender Eternal|133|U|{1}{G}|Sorcery - Lesson|||Create a Food token. Then earthbend X, where X is twice the number of Foods you control.| The Cabbage Merchant|Avatar: The Last Airbender Eternal|134|R|{2}{G}|Legendary Creature - Human Citizen|2|2|Whenever an opponent casts a noncreature spell, create a Food token.$Whenever a creature deals combat damage to you, sacrifice a Food token.$Tap two untapped Foods you control: Add one mana of any color.| @@ -60637,6 +60644,45 @@ Descendants' Path|Avatar: The Last Airbender Eternal|167|R|{2}{G}|Enchantment||| Inspiring Call|Avatar: The Last Airbender Eternal|168|U|{2}{G}|Instant|||Draw a card for each creature you control with a +1/+1 counter on it. Those creatures gain indestructible until end of turn.| Many Partings|Avatar: The Last Airbender Eternal|169|C|{G}|Sorcery|||Search your library for a basic land card, reveal it, put it into your hand, then shuffle. Create a Food token.| Suspicious Bookcase|Avatar: The Last Airbender Eternal|170|U|{2}|Artifact Creature - Wall|0|4|Defender${3}, {T}: Target creature can't be blocked this turn.| +Aang, Airbending Master|Avatar: The Last Airbender Eternal|171|M|{4}{W}|Legendary Creature - Human Avatar Ally|4|4|When Aang enters, airbend another target creature.$Whenever one or more creatures you control leave the battlefield without dying, you get an experience counter.$At the beginning of your upkeep, create a 1/1 white Ally creature token for each experience counter you have.| +Jet, Rebel Leader|Avatar: The Last Airbender Eternal|172|R|{3}{W}|Legendary Creature - Human Rebel Ally|3|4|Whenever Jet attacks, look at the top five cards of your library. You may put a creature card with mana value 3 or less from among them onto the battlefield tapped and attacking. Put the rest on the bottom of your library in a random order.| +Monk Gyatso|Avatar: The Last Airbender Eternal|173|R|{3}{W}|Legendary Creature - Human Monk|3|3|Whenever another creature you control becomes the target of a spell or ability, you may airbend that creature.| +Sokka, Swordmaster|Avatar: The Last Airbender Eternal|174|M|{2}{W}|Legendary Creature - Human Warrior Ally|3|3|Vigilance$Equipment spells you cast cost {1} less to cast for each Ally you control.$At the beginning of combat on your turn, attach up to one target Equipment you control to Sokka.| +Suki, Kyoshi Captain|Avatar: The Last Airbender Eternal|175|R|{2}{W}|Legendary Creature - Human Warrior Ally|3|3|Other Warriors you control get +1/+1.${3}{W}: Attacking Warriors you control gain double strike until end of turn.| +Tale of Momo|Avatar: The Last Airbender Eternal|176|R|{2}{W}|Sorcery|||This spell costs {2} less to cast if a creature left the battlefield under your control this turn.$Search your library and/or graveyard for an Ally creature card, reveal it, and put it into your hand. If you search your library this way, shuffle.| +Baboon Spirit|Avatar: The Last Airbender Eternal|177|R|{2}{U}|Creature - Monkey Spirit|2|4|Whenever another nontoken Spirit you control enters, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."${3}{U}: Exile another target creature you control. Return it to the battlefield under its owner's control at the beginning of the next end step.| +The Blue Spirit|Avatar: The Last Airbender Eternal|178|R|{3}{U}|Legendary Creature - Human Rogue Ally|2|4|You may cast the first creature spell you cast each turn as though it had flash.$Whenever a nontoken creature you control enters during combat, draw a card.| +Chakra Meditation|Avatar: The Last Airbender Eternal|179|R|{2}{U}|Enchantment|||When this enchantment enters, return up to one target instant or sorcery card from your graveyard to your hand.$Whenever you cast an instant or sorcery spell, draw a card. Then discard a card unless there are three or more Lesson cards in your graveyard.| +Katara, Waterbending Master|Avatar: The Last Airbender Eternal|180|M|{1}{U}|Legendary Creature - Human Warrior Ally|1|3|Whenever you cast a spell during an opponent's turn, you get an experience counter.$Whenever Katara attacks, you may draw a card for each experience counter you have. If you do, discard a card.| +Tui and La, Moon and Ocean|Avatar: The Last Airbender Eternal|181|R|{3}{U}|Legendary Creature - Fish Spirit|3|3|Whenever Tui and La become tapped, draw a card.$Whenever Tui and La become untapped, put a +1/+1 counter on them.| +Wan Shi Tong, All-Knowing|Avatar: The Last Airbender Eternal|182|M|{3}{U}{U}|Legendary Creature - Bird Spirit|4|4|Flying$When Wan Shi Tong enters, target nonland permanent's owner puts it into their library second from the top or on the bottom.$Whenever one or more cards are put into a library from anywhere, create two 1/1 colorless Spirit creature tokens with "This token can't block or be blocked by non-Spirit creatures."| +Waterbender's Restoration|Avatar: The Last Airbender Eternal|183|R|{U}{U}|Instant - Lesson|||As an additional cost to cast this spell, waterbend {X}.$Exile X target creatures you control. Return those cards to the battlefield under their owner's control at the beginning of the next end step.| +Azula, Ruthless Firebender|Avatar: The Last Airbender Eternal|184|M|{2}{B}|Legendary Creature - Human Noble|3|3|Firebending 1$Whenever Azula attacks, you may discard a card. Then you get an experience counter for each player who discarded a card this turn.${2}{B}: Until end of turn, Azula gets +1/+1 for each experience counter you have and gains menace.| +Desperate Plea|Avatar: The Last Airbender Eternal|185|R|{1}{B}|Sorcery - Lesson|||As an additional cost to cast this spell, sacrifice a creature.$Choose one or both --$* Return target creature card from your graveyard to the battlefield if its power is less than or equal to the sacrificed creature's power.$* Destroy target creature.| +Fire Lord Ozai|Avatar: The Last Airbender Eternal|186|M|{3}{B}|Legendary Creature - Human Noble|4|4|Whenever Fire Lord Ozai attacks, you may sacrifice another creature. If you do, add an amount of {R} equal to the sacrificed creature's power. Until end of combat, you don't lose this mana as steps end.${6}: Exile the top card of each opponent's library. Until end of turn, you may play one of those cards without paying its mana cost.| +Fire Nation Occupation|Avatar: The Last Airbender Eternal|187|R|{2}{B}|Enchantment|||When this enchantment enters, create a 2/2 red Soldier creature token with firebending 1.$Whenever you cast a spell during an opponent's turn, create a 2/2 red Soldier creature token with firebending 1.| +Fire Nation Salvagers|Avatar: The Last Airbender Eternal|188|R|{3}{B}{B}|Creature - Human Soldier|3|3|Menace$When this creature enters, put a +1/+1 counter on target creature or Vehicle you control.$Whenever one or more creatures you control with counters on them deal combat damage to a player, put target creature or Vehicle card from that player's graveyard onto the battlefield under your control.| +Lo and Li, Royal Advisors|Avatar: The Last Airbender Eternal|189|R|{2}{B}{B}|Legendary Creature - Human Advisor|3|3|Whenever an opponent discards a card or mills one or more cards, put a +1/+1 counter on each Advisor you control.${2}{U/B}: Target player mills four cards.| +Nyla, Shirshu Sleuth|Avatar: The Last Airbender Eternal|190|R|{4}{B}|Legendary Creature - Mole Beast|4|5|When Nyla enters, exile up to one target creature card from your graveyard. If you do, you lose X life and create X Clue tokens, where X is that card's mana value.$At the beginning of your end step, if you control no Clues, return target card exiled with Nyla to its owner's hand.| +Avatar Roku, Firebender|Avatar: The Last Airbender Eternal|191|M|{3}{R}{R}{R}|Legendary Creature - Human Avatar|6|6|Whenever a player attacks, add six {R}. Until end of combat, you don't lose this mana as steps end.${R}{R}{R}: Target creature gets +3/+0 until end of turn.| +Chong and Lily, Nomads|Avatar: The Last Airbender Eternal|192|R|{3}{R}|Legendary Creature - Human Bard Ally|3|3|Whenever one or more Bards you control attack, choose one --$* Put a lore counter on each of any number of target Sagas you control.$* Creatures you control get +1/+0 until end of turn for each lore counter among Sagas you control.| +Fang, Roku's Companion|Avatar: The Last Airbender Eternal|193|R|{3}{R}{R}|Legendary Creature - Dragon|4|4|Flying$Whenever Fang attacks, another target legendary creature you control gets +X/+0 until end of turn, where X is Fang's power.$When Fang dies, if he wasn't a Spirit, return this card to the battlefield under your control. He's a Spirit in addition to his other types.| +Iroh, Dragon of the West|Avatar: The Last Airbender Eternal|194|R|{2}{R}{R}|Legendary Creature - Human Noble Ally|4|4|Haste$Mentor$At the beginning of combat on your turn, each creature you control with a counter on it gains firebending 2 until end of turn.| +Lost in Memories|Avatar: The Last Airbender Eternal|195|R|{1}{R}|Enchantment - Aura|||Flash$Enchant creature you control$Enchanted creature gets +1/+1 and has "Whenever this creature deals combat damage to a player, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost."| +Overwhelming Victory|Avatar: The Last Airbender Eternal|196|R|{4}{R}|Instant - Lesson|||Overwhelming Victory deals 5 damage to target creature. Each creature you control gains trample and gets +X/+0 until end of turn, where X is the amount of excess damage dealt this way.| +Reckless Blaze|Avatar: The Last Airbender Eternal|197|R|{3}{R}{R}|Sorcery - Lesson|||Reckless Blaze deals 5 damage to each creature. Whenever a creature you control dealt damage this way dies this turn, add {R}.| +Smellerbee, Rebel Fighter|Avatar: The Last Airbender Eternal|198|R|{3}{R}|Legendary Creature - Human Rebel Ally|3|3|First strike$Other creatures you control have haste.$Whenever Smellerbee attacks, you may discard your hand. If you do, draw cards equal to the number of attacking creatures.| +Storm of Memories|Avatar: The Last Airbender Eternal|199|R|{2}{R}{R}{R}|Sorcery|||Storm$Exile an instant or sorcery card with mana value 3 or less from your graveyard at random. You may cast it without paying its mana cost. If that spell would be put into a graveyard, exile it instead.| +Zuko, Firebending Master|Avatar: The Last Airbender Eternal|200|M|{1}{R}|Legendary Creature - Human Noble Ally|2|2|First strike$Firebending X, where X is the number of experience counters you have.$Whenever you cast a spell during combat, you get an experience counter.| +Avatar Kyoshi, Earthbender|Avatar: The Last Airbender Eternal|201|M|{5}{G}{G}{G}|Legendary Creature - Human Avatar|6|6|During your turn, Avatar Kyoshi has hexproof.$At the beginning of combat on your turn, earthbend 8, then untap that land.| +Bison Whistle|Avatar: The Last Airbender Eternal|202|R|{1}{G}|Artifact|||{1}, {T}: Look at the top card of your library. If it's a Bison card, you may put it onto the battlefield. If it's a creature card, you may reveal it and put it into your hand. Otherwise, you may put it into your graveyard.| +The Cabbage Merchant|Avatar: The Last Airbender Eternal|203|R|{2}{G}|Legendary Creature - Human Citizen|2|2|Whenever an opponent casts a noncreature spell, create a Food token.$Whenever a creature deals combat damage to you, sacrifice a Food token.$Tap two untapped Foods you control: Add one mana of any color.| +Crystalline Armor|Avatar: The Last Airbender Eternal|204|R|{3}{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +1/+1 for each land you control and has trample.| +Hei Bai, Forest Guardian|Avatar: The Last Airbender Eternal|205|M|{3}{G}|Legendary Creature - Bear Spirit|4|4|When Hei Bai enters, reveal cards from the top of your library until you reveal a Shrine card. You may put that card onto the battlefield. Then shuffle.${W}{U}{B}{R}{G}, {T}: For each legendary enchantment you control, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures."| +Master's Guidance|Avatar: The Last Airbender Eternal|206|R|{2}{G}|Enchantment|||Whenever you attack with two or more legendary creatures, put a +1/+1 counter on each of up to two target attacking creatures.$At the beginning of your end step, if you control a creature with power 4 or greater, draw a card.| +Tale of Katara and Toph|Avatar: The Last Airbender Eternal|207|R|{2}{G}|Enchantment|||Creatures you control have "Whenever this creature becomes tapped for the first time during each of your turns, put a +1/+1 counter on it."| +Tectonic Split|Avatar: The Last Airbender Eternal|208|R|{4}{G}{G}|Enchantment|||As an additional cost to cast this spell, sacrifice half the lands you control, rounded up.$Hexproof$Lands you control have "{T}: Add three mana of any one color."| +Toph, Earthbending Master|Avatar: The Last Airbender Eternal|209|M|{3}{G}|Legendary Creature - Human Warrior Ally|2|4|Landfall -- Whenever a land you control enters, you get an experience counter.$Whenever you attack, earthbend X, where X is the number of experience counters you have.| Aang, Air Nomad|Avatar: The Last Airbender Eternal|210|R|{3}{W}{W}|Legendary Creature - Human Avatar Ally|5|4|Flying$Vigilance$Other creatures you control have vigilance.| Aang's Defense|Avatar: The Last Airbender Eternal|211|C|{W}|Instant|||Target blocking creature you control gets +2/+2 until end of turn.$Draw a card.| Aardvark Sloth|Avatar: The Last Airbender Eternal|212|C|{3}{W}|Creature - Sloth Beast|3|3|Lifelink| @@ -60745,7 +60791,6 @@ Worldly Tutor|Avatar: The Last Airbender Eternal|314|R|{G}|Instant|||Search your Arcane Signet|Avatar: The Last Airbender Eternal|315|R|{2}|Artifact|||{T}: Add one mana of any color in your commander's color identity.| Sol Ring|Avatar: The Last Airbender Eternal|316|R|{1}|Artifact|||{T}: Add {C}{C}.| Swiftfoot Boots|Avatar: The Last Airbender Eternal|317|R|{2}|Artifact - Equipment|||Equipped creature has hexproof and haste.$Equip {1}| -Beastmaster's Magemark|Avatar: The Last Airbender Eternal|9999|M|{2}{G}|Enchantment - Aura|||Enchant creature$Creatures you control that are enchanted get +1/+1.$Whenever a creature you control that's enchanted becomes blocked, it gets +1/+1 until end of turn for each creature blocking it.| Eirdu, Carrier of Dawn|Lorwyn Eclipsed|13|M|{3}{W}{W}|Legendary Creature - Elemental God|5|5|Flying, lifelink$Creature spells you cast have convoke.$At the beginning of your first main phase, you may pay {B}. If you do, transform Eirdu.| Isilu, Carrier of Twilight|Lorwyn Eclipsed|13|M||Legendary Creature - Elemental God|5|5|Flying, lifelink$Each other nontoken creature you control has persist.$At the beginning of your first main phase, you may pay {W}. If you do, transform Isilu.| Morningtide's Light|Lorwyn Eclipsed|27|M|{3}{W}|Sorcery|||Exile any number of target creatures. At the beginning of the next end step, return those cards to the battlefield tapped under their owners' control.$Until your next turn, prevent all damage that would be dealt to you.$Exile Morningtide's Light.| -- 2.47.2 From aac1aa55cc79d9f3d16418c02ed83f8c500a50ca Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 09:54:48 -0500 Subject: [PATCH 136/261] fix verify errors --- Mage.Sets/src/mage/cards/f/FireLordAzula.java | 21 +++--------- .../mage/cards/z/ZukoFirebendingMaster.java | 33 +++++++------------ 2 files changed, 17 insertions(+), 37 deletions(-) diff --git a/Mage.Sets/src/mage/cards/f/FireLordAzula.java b/Mage.Sets/src/mage/cards/f/FireLordAzula.java index fe4c32e9447..4ad6e69e5c8 100644 --- a/Mage.Sets/src/mage/cards/f/FireLordAzula.java +++ b/Mage.Sets/src/mage/cards/f/FireLordAzula.java @@ -2,6 +2,7 @@ package mage.cards.f; import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.condition.common.SourceAttackingCondition; import mage.abilities.effects.common.CopyStackObjectEffect; import mage.abilities.keyword.FirebendingAbility; import mage.cards.CardImpl; @@ -11,8 +12,6 @@ import mage.constants.SetTargetPointer; import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.events.GameEvent; import java.util.UUID; @@ -34,7 +33,10 @@ public final class FireLordAzula extends CardImpl { this.addAbility(new FirebendingAbility(2)); // Whenever you cast a spell while Fire Lord Azula is attacking, copy that spell. You may choose new targets for the copy. - this.addAbility(new FireLordAzulaAbility()); + this.addAbility(new SpellCastControllerTriggeredAbility( + new CopyStackObjectEffect("that spell"), + StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL + ).withTriggerCondition(SourceAttackingCondition.instance)); } private FireLordAzula(final FireLordAzula card) { @@ -46,16 +48,3 @@ public final class FireLordAzula extends CardImpl { return new FireLordAzula(this); } } - -class FireLordAzulaAbility extends SpellCastControllerTriggeredAbility { - - public FireLordAzulaAbility() { - super(new CopyStackObjectEffect("that spell"), StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL); - setTriggerPhrase("Whenever you cast a spell while Fire Lord Azula is attacking, "); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return game.getCombat().getAttackers().contains(getSourceId()) && super.checkTrigger(event, game); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/z/ZukoFirebendingMaster.java b/Mage.Sets/src/mage/cards/z/ZukoFirebendingMaster.java index 7f277b96c69..38020b147b4 100644 --- a/Mage.Sets/src/mage/cards/z/ZukoFirebendingMaster.java +++ b/Mage.Sets/src/mage/cards/z/ZukoFirebendingMaster.java @@ -1,32 +1,33 @@ package mage.cards.z; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.IsPhaseCondition; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CountersControllerCount; import mage.abilities.effects.common.counter.AddCountersPlayersEffect; -import mage.constants.*; -import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FirebendingAbility; +import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.counters.CounterType; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.events.GameEvent; + +import java.util.UUID; /** - * * @author anonymous */ public final class ZukoFirebendingMaster extends CardImpl { private static final DynamicValue xValue = new CountersControllerCount(CounterType.EXPERIENCE); + private static final Condition condition = new IsPhaseCondition(TurnPhase.COMBAT); public ZukoFirebendingMaster(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.NOBLE); @@ -41,7 +42,10 @@ public final class ZukoFirebendingMaster extends CardImpl { this.addAbility(new FirebendingAbility(xValue)); // Whenever you cast a spell during combat, you get an experience counter. - this.addAbility(new ZukoFirebendingMasterAbility()); + this.addAbility(new SpellCastControllerTriggeredAbility( + new AddCountersPlayersEffect(CounterType.EXPERIENCE.createInstance(), TargetController.YOU), + StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL + ).withTriggerCondition(condition)); } private ZukoFirebendingMaster(final ZukoFirebendingMaster card) { @@ -53,16 +57,3 @@ public final class ZukoFirebendingMaster extends CardImpl { return new ZukoFirebendingMaster(this); } } - -class ZukoFirebendingMasterAbility extends SpellCastControllerTriggeredAbility { - - public ZukoFirebendingMasterAbility() { - super(new AddCountersPlayersEffect(CounterType.EXPERIENCE.createInstance(), TargetController.YOU), StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL); - setTriggerPhrase("Whenever you cast a spell during combat, "); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return game.getTurnPhaseType() == TurnPhase.COMBAT && super.checkTrigger(event, game); - } -} \ No newline at end of file -- 2.47.2 From 2b288cfd00880849afcd303cc47bae2b33c90519 Mon Sep 17 00:00:00 2001 From: ReSech Date: Tue, 7 Oct 2025 12:26:55 +1100 Subject: [PATCH 137/261] Add SLD Reprint and Tokens --- .../plugins/card/dl/sources/ScryfallImageSupportTokens.java | 3 +++ Mage.Sets/src/mage/sets/SecretLairDrop.java | 1 + Mage/src/main/resources/tokens-database.txt | 3 +++ 3 files changed, 7 insertions(+) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java index 8a28fe7808c..17e0094521f 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java @@ -817,10 +817,13 @@ public class ScryfallImageSupportTokens { // SLD put("SLD/Angel", "https://api.scryfall.com/cards/sld/1340?format=image"); + put("SLD/Blood", "https://api.scryfall.com/cards/sld/2180?format=image"); put("SLD/Cat/1", "https://api.scryfall.com/cards/sld/1517?format=image"); put("SLD/Cat/2", "https://api.scryfall.com/cards/sld/27?format=image"); put("SLD/Cat/3", "https://api.scryfall.com/cards/sld/28?format=image"); put("SLD/Clue", "https://api.scryfall.com/cards/sld/348/en?format=image"); + put("SLD/Cordyceps Infected/1", "https://api.scryfall.com/cards/sld/2201?format=image"); + put("SLD/Cordyceps Infected/2", "https://api.scryfall.com/cards/sld/2206?format=image"); put("SLD/Dog", "https://api.scryfall.com/cards/sld/1516?format=image"); put("SLD/Egg", "https://api.scryfall.com/cards/sld/1398?format=image"); put("SLD/Faerie Rogue/1", "https://api.scryfall.com/cards/sld/13/en?format=image"); diff --git a/Mage.Sets/src/mage/sets/SecretLairDrop.java b/Mage.Sets/src/mage/sets/SecretLairDrop.java index 9c46db38472..2eccd5fbec1 100644 --- a/Mage.Sets/src/mage/sets/SecretLairDrop.java +++ b/Mage.Sets/src/mage/sets/SecretLairDrop.java @@ -897,6 +897,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Deadeye Navigator", 902, Rarity.RARE, mage.cards.d.DeadeyeNavigator.class)); cards.add(new SetCardInfo("The Locust God", 903, Rarity.MYTHIC, mage.cards.t.TheLocustGod.class)); cards.add(new SetCardInfo("The Scorpion God", 904, Rarity.MYTHIC, mage.cards.t.TheScorpionGod.class)); + cards.add(new SetCardInfo("Cryptic Command", 905, Rarity.RARE, mage.cards.c.CrypticCommand.class, FULL_ART)); cards.add(new SetCardInfo("Ignoble Hierarch", 906, Rarity.RARE, mage.cards.i.IgnobleHierarch.class, FULL_ART)); cards.add(new SetCardInfo("Seedborn Muse", 907, Rarity.RARE, mage.cards.s.SeedbornMuse.class)); cards.add(new SetCardInfo("Arcane Signet", 908, Rarity.RARE, mage.cards.a.ArcaneSignet.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/resources/tokens-database.txt b/Mage/src/main/resources/tokens-database.txt index 9e2a5a813ee..fa695370dd3 100644 --- a/Mage/src/main/resources/tokens-database.txt +++ b/Mage/src/main/resources/tokens-database.txt @@ -1515,10 +1515,13 @@ # SLD |Generate|TOK:SLD|Angel|||AngelToken| +|Generate|TOK:SLD|Blood|||BloodToken| |Generate|TOK:SLD|Cat|1||GreenCatToken| |Generate|TOK:SLD|Cat|2||CatToken2| |Generate|TOK:SLD|Cat|3||CatToken2| |Generate|TOK:SLD|Clue|||ClueArtifactToken| +|Generate|TOK:SLD|Cordyceps Infected|1||CordycepsInfectedToken| +|Generate|TOK:SLD|Cordyceps Infected|2||CordycepsInfectedToken| |Generate|TOK:SLD|Dog|||WhiteDogToken| |Generate|TOK:SLD|Egg|||AtlaPalaniToken| |Generate|TOK:SLD|Faerie Rogue|1||FaerieRogueToken| -- 2.47.2 From 67660374cb632aac28ee58f32793011374f4895e Mon Sep 17 00:00:00 2001 From: ReSech Date: Tue, 7 Oct 2025 12:52:11 +1100 Subject: [PATCH 138/261] Fix 2214 Back Image Download --- .../mage/plugins/card/dl/sources/ScryfallImageSupportCards.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java index 0955335f669..c4c7a7121d4 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java @@ -717,6 +717,7 @@ public class ScryfallImageSupportCards { put("SLD/Sol Ring/1512b", "https://api.scryfall.com/cards/sld/1512/en?format=image&face=back"); put("SLD/Steely Resolve/1326b", "https://api.scryfall.com/cards/sld/1326/en?format=image&face=back"); put("SLD/Stitch in Time/382b", "https://api.scryfall.com/cards/sld/382/en?format=image&face=back"); + put("SLD/Teferi's Ageless Insight/2214b", "https://api.scryfall.com/cards/sld/2214/en?format=image&face=back"); put("SLD/Terror/750b", "https://api.scryfall.com/cards/sld/750/en?format=image&face=back"); put("SLD/Tuvasa the Sunlit/1328b", "https://api.scryfall.com/cards/sld/1328/en?format=image&face=back"); put("SLD/Ulamog, the Ceaseless Hunger/1122b", "https://api.scryfall.com/cards/sld/1122/en?format=image&face=back"); -- 2.47.2 From 7e34363954dd3c4ef20e32c6cd103131e10a7f98 Mon Sep 17 00:00:00 2001 From: ReSech Date: Sun, 9 Nov 2025 06:58:25 +1100 Subject: [PATCH 139/261] Move cards from PMEI to LMAR and add missing PURL Reprints (#14008) * Add new PURL reprints * Move LMAR cards to dedicated set, remove from PMEI --- .../dl/sources/ScryfallImageSupportCards.java | 1 + .../mage/sets/MarvelLegendsSeriesInserts.java | 29 +++++++++++++++++++ .../sets/MediaAndCollaborationPromos.java | 5 ---- .../src/mage/sets/URLConventionPromos.java | 2 ++ 4 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/MarvelLegendsSeriesInserts.java diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java index c4c7a7121d4..d53f1280640 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java @@ -611,6 +611,7 @@ public class ScryfallImageSupportCards { add("EOS"); // Edge of Eternities: Stellar Sights add("SPM"); // Marvel's Spider-Man add("SPE"); // Marvel's Spider-Man Eternal + add("LMAR"); // Marvel Legends Series Inserts add("MAR"); // Marvel Universe add("TLA"); // Avatar: The Last Airbender add("TLE"); // Avatar: The Last Airbender Eternal diff --git a/Mage.Sets/src/mage/sets/MarvelLegendsSeriesInserts.java b/Mage.Sets/src/mage/sets/MarvelLegendsSeriesInserts.java new file mode 100644 index 00000000000..7a4ebe5eb0c --- /dev/null +++ b/Mage.Sets/src/mage/sets/MarvelLegendsSeriesInserts.java @@ -0,0 +1,29 @@ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * https://scryfall.com/sets/lmar + */ +public class MarvelLegendsSeriesInserts extends ExpansionSet { + + private static final MarvelLegendsSeriesInserts instance = new MarvelLegendsSeriesInserts(); + + public static MarvelLegendsSeriesInserts getInstance() { + return instance; + } + + private MarvelLegendsSeriesInserts() { + super("Marvel Legends Series Inserts", "LMAR", ExpansionSet.buildDate(2025, 9, 30), SetType.PROMOTIONAL); + this.hasBoosters = false; + this.hasBasicLands = false; + + cards.add(new SetCardInfo("Anti-Venom, Horrifying Healer", 1, Rarity.MYTHIC, mage.cards.a.AntiVenomHorrifyingHealer.class)); + cards.add(new SetCardInfo("Huntmaster of the Fells", 3, Rarity.RARE, mage.cards.h.HuntmasterOfTheFells.class)); + cards.add(new SetCardInfo("Iron Spider, Stark Upgrade", 4, Rarity.RARE, mage.cards.i.IronSpiderStarkUpgrade.class)); + cards.add(new SetCardInfo("Ravager of the Fells", 3, Rarity.RARE, mage.cards.r.RavagerOfTheFells.class)); + cards.add(new SetCardInfo("Spectacular Spider-Man", 2, Rarity.RARE, mage.cards.s.SpectacularSpiderMan.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/MediaAndCollaborationPromos.java b/Mage.Sets/src/mage/sets/MediaAndCollaborationPromos.java index 1436aaf5098..823f67ae669 100644 --- a/Mage.Sets/src/mage/sets/MediaAndCollaborationPromos.java +++ b/Mage.Sets/src/mage/sets/MediaAndCollaborationPromos.java @@ -24,7 +24,6 @@ public class MediaAndCollaborationPromos extends ExpansionSet { cards.add(new SetCardInfo("Ajani, Mentor of Heroes", "2024-3", Rarity.MYTHIC, mage.cards.a.AjaniMentorOfHeroes.class)); cards.add(new SetCardInfo("Ancestral Mask", "2025-2", Rarity.RARE, mage.cards.a.AncestralMask.class)); - cards.add(new SetCardInfo("Anti-Venom, Horrifying Healer", "2025-15", Rarity.MYTHIC, mage.cards.a.AntiVenomHorrifyingHealer.class)); cards.add(new SetCardInfo("Archangel", "2000-4", Rarity.RARE, mage.cards.a.Archangel.class, RETRO_ART)); cards.add(new SetCardInfo("Ascendant Evincar", "2000-7", Rarity.RARE, mage.cards.a.AscendantEvincar.class, RETRO_ART)); cards.add(new SetCardInfo("Avalanche Riders", "2023-5", Rarity.RARE, mage.cards.a.AvalancheRiders.class)); @@ -54,9 +53,7 @@ public class MediaAndCollaborationPromos extends ExpansionSet { cards.add(new SetCardInfo("Gush", "2024-4", Rarity.RARE, mage.cards.g.Gush.class)); cards.add(new SetCardInfo("Harald, King of Skemfar", "2021-3", Rarity.RARE, mage.cards.h.HaraldKingOfSkemfar.class)); cards.add(new SetCardInfo("Heliod's Pilgrim", "2020-6", Rarity.RARE, mage.cards.h.HeliodsPilgrim.class)); - cards.add(new SetCardInfo("Huntmaster of the Fells", "2025-17", Rarity.RARE, mage.cards.h.HuntmasterOfTheFells.class)); cards.add(new SetCardInfo("Hypnotic Sprite", "2019-5", Rarity.RARE, mage.cards.h.HypnoticSprite.class)); - cards.add(new SetCardInfo("Iron Spider, Stark Upgrade", "2025-18", Rarity.RARE, mage.cards.i.IronSpiderStarkUpgrade.class)); cards.add(new SetCardInfo("Jace Beleren", "2009-1", Rarity.MYTHIC, mage.cards.j.JaceBeleren.class)); cards.add(new SetCardInfo("Jace, Memory Adept", "2024-2", Rarity.MYTHIC, mage.cards.j.JaceMemoryAdept.class)); cards.add(new SetCardInfo("Jamuraan Lion", "1996-3", Rarity.COMMON, mage.cards.j.JamuraanLion.class, RETRO_ART)); @@ -73,7 +70,6 @@ public class MediaAndCollaborationPromos extends ExpansionSet { cards.add(new SetCardInfo("Phantasmal Dragon", "2011-1", Rarity.UNCOMMON, mage.cards.p.PhantasmalDragon.class)); cards.add(new SetCardInfo("Phyrexian Rager", "2000-5", Rarity.COMMON, mage.cards.p.PhyrexianRager.class, RETRO_ART)); cards.add(new SetCardInfo("Pyromancer's Gauntlet", "2023-6", Rarity.RARE, mage.cards.p.PyromancersGauntlet.class, RETRO_ART)); - cards.add(new SetCardInfo("Ravager of the Fells", "2025-17", Rarity.RARE, mage.cards.r.RavagerOfTheFells.class)); cards.add(new SetCardInfo("Ruin Crab", "2023-4", Rarity.RARE, mage.cards.r.RuinCrab.class, RETRO_ART)); cards.add(new SetCardInfo("Sandbar Crocodile", "1996-1", Rarity.COMMON, mage.cards.s.SandbarCrocodile.class, RETRO_ART)); cards.add(new SetCardInfo("Scent of Cinder", "1999-1", Rarity.COMMON, mage.cards.s.ScentOfCinder.class, RETRO_ART)); @@ -85,7 +81,6 @@ public class MediaAndCollaborationPromos extends ExpansionSet { cards.add(new SetCardInfo("Shrieking Drake", "1997-2", Rarity.COMMON, mage.cards.s.ShriekingDrake.class, RETRO_ART)); cards.add(new SetCardInfo("Silver Drake", "2000-2", Rarity.COMMON, mage.cards.s.SilverDrake.class, RETRO_ART)); cards.add(new SetCardInfo("Snuff Out", "2024-1", Rarity.RARE, mage.cards.s.SnuffOut.class)); - cards.add(new SetCardInfo("Spectacular Spider-Man", "2025-16", Rarity.RARE, mage.cards.s.SpectacularSpiderMan.class)); cards.add(new SetCardInfo("Spined Wurm", "2001-1", Rarity.COMMON, mage.cards.s.SpinedWurm.class, RETRO_ART)); cards.add(new SetCardInfo("Sprite Dragon", "2020-5", Rarity.RARE, mage.cards.s.SpriteDragon.class)); cards.add(new SetCardInfo("Staggering Insight", "2020-3", Rarity.RARE, mage.cards.s.StaggeringInsight.class)); diff --git a/Mage.Sets/src/mage/sets/URLConventionPromos.java b/Mage.Sets/src/mage/sets/URLConventionPromos.java index 155a5718d2f..da73a7cee08 100644 --- a/Mage.Sets/src/mage/sets/URLConventionPromos.java +++ b/Mage.Sets/src/mage/sets/URLConventionPromos.java @@ -29,7 +29,9 @@ public class URLConventionPromos extends ExpansionSet { cards.add(new SetCardInfo("Kor Skyfisher", 23, Rarity.RARE, mage.cards.k.KorSkyfisher.class)); cards.add(new SetCardInfo("Merfolk Mesmerist", 4, Rarity.RARE, mage.cards.m.MerfolkMesmerist.class)); cards.add(new SetCardInfo("Shepherd of the Lost", "34*", Rarity.UNCOMMON, mage.cards.s.ShepherdOfTheLost.class)); + cards.add(new SetCardInfo("Sokka, Bold Boomeranger", "2025-4", Rarity.RARE, mage.cards.s.SokkaBoldBoomeranger.class)); cards.add(new SetCardInfo("Stealer of Secrets", 7, Rarity.RARE, mage.cards.s.StealerOfSecrets.class)); cards.add(new SetCardInfo("Steward of Valeron", 1, Rarity.RARE, mage.cards.s.StewardOfValeron.class)); + cards.add(new SetCardInfo("Unbreakable Formation", "2025-5", Rarity.RARE, mage.cards.u.UnbreakableFormation.class)); } } -- 2.47.2 From 1327fe2b99d73b8e42815f1f4ca444bace2a6023 Mon Sep 17 00:00:00 2001 From: Tuomas-Matti Soikkeli Date: Sat, 8 Nov 2025 21:59:45 +0200 Subject: [PATCH 140/261] gui: cover scale style option for background images (#14049) --- .../mage/plugins/theme/ThemePluginImpl.java | 2 +- .../main/java/mage/components/ImagePanel.java | 24 +++++++++++++++++++ .../java/mage/components/ImagePanelStyle.java | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/plugins/theme/ThemePluginImpl.java b/Mage.Client/src/main/java/org/mage/plugins/theme/ThemePluginImpl.java index 34631c40516..dbcc8e01760 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/theme/ThemePluginImpl.java +++ b/Mage.Client/src/main/java/org/mage/plugins/theme/ThemePluginImpl.java @@ -82,7 +82,7 @@ public class ThemePluginImpl implements ThemePlugin { } if (ui.containsKey("gamePanel") && ui.containsKey("jLayeredPane")) { - ImagePanel bgPanel = new ImagePanel(backgroundImage, ImagePanelStyle.TILED); + ImagePanel bgPanel = new ImagePanel(backgroundImage, ImagePanelStyle.COVER); // TODO: research - is all components used? And why it make transparent? unsetOpaque(ui.get("splitChatAndLogs")); diff --git a/Mage.Common/src/main/java/mage/components/ImagePanel.java b/Mage.Common/src/main/java/mage/components/ImagePanel.java index 0699e6d0cb4..dc1c317efb8 100644 --- a/Mage.Common/src/main/java/mage/components/ImagePanel.java +++ b/Mage.Common/src/main/java/mage/components/ImagePanel.java @@ -78,6 +78,9 @@ public class ImagePanel extends JPanel { case ACTUAL: drawActual(g); break; + case COVER: + drawCover(g); + break; } } @@ -99,4 +102,25 @@ public class ImagePanel extends JPanel { float y = (d.height - image.getHeight(null)) * alignmentY; g.drawImage(image, (int) x, (int) y, this); } + + private void drawCover(Graphics g) { + Dimension d = getSize(); + int imageWidth = image.getWidth(null); + int imageHeight = image.getHeight(null); + + // Calculate scale to cover the entire panel while maintaining aspect ratio + double scaleX = (double) d.width / imageWidth; + double scaleY = (double) d.height / imageHeight; + double scale = Math.max(scaleX, scaleY); + + // Calculate the scaled dimensions + int scaledWidth = (int) (imageWidth * scale); + int scaledHeight = (int) (imageHeight * scale); + + // Center the image + int x = (d.width - scaledWidth) / 2; + int y = (d.height - scaledHeight) / 2; + + g.drawImage(image, x, y, scaledWidth, scaledHeight, null); + } } diff --git a/Mage.Common/src/main/java/mage/components/ImagePanelStyle.java b/Mage.Common/src/main/java/mage/components/ImagePanelStyle.java index 01e1b4557bc..7e1a17839d1 100644 --- a/Mage.Common/src/main/java/mage/components/ImagePanelStyle.java +++ b/Mage.Common/src/main/java/mage/components/ImagePanelStyle.java @@ -4,5 +4,5 @@ package mage.components; * Created by IGOUDT on 7-3-2017. */ public enum ImagePanelStyle { - TILED, SCALED, ACTUAL + TILED, SCALED, ACTUAL, COVER } -- 2.47.2 From d2559333e8caf5137a56ef07ef5253555e4ba24c Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sat, 8 Nov 2025 14:40:21 -0500 Subject: [PATCH 141/261] fix Koth of the Hammer --- Mage.Sets/src/mage/cards/k/KothOfTheHammer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/k/KothOfTheHammer.java b/Mage.Sets/src/mage/cards/k/KothOfTheHammer.java index 82dbe08f976..01280ba2caa 100644 --- a/Mage.Sets/src/mage/cards/k/KothOfTheHammer.java +++ b/Mage.Sets/src/mage/cards/k/KothOfTheHammer.java @@ -29,8 +29,8 @@ import java.util.UUID; */ public final class KothOfTheHammer extends CardImpl { - static final FilterPermanent filter = new FilterPermanent(SubType.MOUNTAIN, "Mountain"); - static final FilterPermanent filterCount = new FilterControlledPermanent("Mountain you control"); + private static final FilterPermanent filter = new FilterPermanent(SubType.MOUNTAIN, "Mountain"); + private static final FilterPermanent filterCount = new FilterControlledPermanent(SubType.MOUNTAIN, "Mountain you control"); public KothOfTheHammer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{R}{R}"); -- 2.47.2 From 39a8945589c9d521d6ba9d659007125c4de4ed47 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sat, 8 Nov 2025 14:43:03 -0500 Subject: [PATCH 142/261] fix Sandman, Shifting Scoundrel --- Mage.Sets/src/mage/cards/s/SandmanShiftingScoundrel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/s/SandmanShiftingScoundrel.java b/Mage.Sets/src/mage/cards/s/SandmanShiftingScoundrel.java index ff40e6a5215..9d4c489c2a4 100644 --- a/Mage.Sets/src/mage/cards/s/SandmanShiftingScoundrel.java +++ b/Mage.Sets/src/mage/cards/s/SandmanShiftingScoundrel.java @@ -43,7 +43,7 @@ public final class SandmanShiftingScoundrel extends CardImpl { this.addAbility(new DauntAbility()); // {3}{G}{G}: Return this card and target land card from your graveyard to the battlefield tapped. - Ability ability = new SimpleActivatedAbility( + Ability ability = new SimpleActivatedAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(true) .setText("return this card"), new ManaCostsImpl<>("{3}{G}{G}") -- 2.47.2 From 8ac800b08bd12174b0bb04472f0c1d23602fb5c3 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sat, 8 Nov 2025 14:43:19 -0500 Subject: [PATCH 143/261] fix Shadow of the Goblin --- Mage.Sets/src/mage/cards/s/ShadowOfTheGoblin.java | 7 +++---- .../mage/test/cards/single/spm/ShadowOfTheGoblinTest.java | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/ShadowOfTheGoblin.java b/Mage.Sets/src/mage/cards/s/ShadowOfTheGoblin.java index 822dbe8d30f..ca66c633325 100644 --- a/Mage.Sets/src/mage/cards/s/ShadowOfTheGoblin.java +++ b/Mage.Sets/src/mage/cards/s/ShadowOfTheGoblin.java @@ -28,10 +28,9 @@ public final class ShadowOfTheGoblin extends CardImpl { // Unreliable Visions -- At the beginning of your first main phase, discard a card. If you do, draw a card. - this.addAbility(new BeginningOfFirstMainTriggeredAbility( - new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new DiscardCardCost()), false) - .withFlavorWord("Unreliable Visions") - ); + this.addAbility(new BeginningOfFirstMainTriggeredAbility(new DoIfCostPaid( + new DrawCardSourceControllerEffect(1), null, new DiscardCardCost(), false + ), false).withFlavorWord("Unreliable Visions")); // Undying Vengeance -- Whenever you play a land or cast a spell from anywhere other than your hand, this enchantment deals 1 damage to each opponent. this.addAbility(new ShadowOfTheGoblinTriggeredAbility(new DamagePlayersEffect(1, TargetController.OPPONENT)) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/spm/ShadowOfTheGoblinTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/spm/ShadowOfTheGoblinTest.java index 50312827c11..07ff6ec1e9d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/spm/ShadowOfTheGoblinTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/spm/ShadowOfTheGoblinTest.java @@ -61,7 +61,7 @@ public class ShadowOfTheGoblinTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Mountain"); addCard(Zone.HAND, playerA, partyThrasher); - setChoice(playerA, false); // shadow trigger + setChoice(playerA, "Mountain"); // shadow trigger waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain"); @@ -120,4 +120,4 @@ public class ShadowOfTheGoblinTest extends CardTestPlayerBase { assertLife(playerB, 20 - 1 - 1); // land + spell from library } -} \ No newline at end of file +} -- 2.47.2 From a03e9710909ca24a43c710b007d348388860e86d Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sat, 8 Nov 2025 14:49:33 -0500 Subject: [PATCH 144/261] fix Spider-Punk --- Mage.Sets/src/mage/cards/s/SpiderPunk.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/SpiderPunk.java b/Mage.Sets/src/mage/cards/s/SpiderPunk.java index 5c9245b121d..034d7423238 100644 --- a/Mage.Sets/src/mage/cards/s/SpiderPunk.java +++ b/Mage.Sets/src/mage/cards/s/SpiderPunk.java @@ -15,6 +15,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.events.EntersTheBattlefieldEvent; @@ -34,7 +35,7 @@ import java.util.UUID; */ public final class SpiderPunk extends CardImpl { - static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.SPIDER, "Spiders you control"); + static final FilterPermanent filter = new FilterPermanent(SubType.SPIDER, "Spiders you control"); public SpiderPunk(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); @@ -125,7 +126,7 @@ class SpiderPunkRiotETBEffect extends ReplacementEffectImpl { return creature != null && creature.getId() != source.getSourceId() && creature.isControlledBy(source.getControllerId()) - && creature.isCreature(game) + && SpiderPunk.filter.match(creature, source.getControllerId(), source, game) && !(creature instanceof PermanentToken); } @@ -154,4 +155,4 @@ class SpiderPunkRiotETBEffect extends ReplacementEffectImpl { public SpiderPunkRiotETBEffect copy() { return new SpiderPunkRiotETBEffect(this); } -} \ No newline at end of file +} -- 2.47.2 From 1c95a93af204502ef76763ffda9eb89fff9eb625 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sat, 8 Nov 2025 14:56:19 -0500 Subject: [PATCH 145/261] fix Carnage, Crimson Chaos (closes #14056) --- Mage.Sets/src/mage/cards/c/CarnageCrimsonChaos.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/c/CarnageCrimsonChaos.java b/Mage.Sets/src/mage/cards/c/CarnageCrimsonChaos.java index 12860badb5b..44520925e69 100644 --- a/Mage.Sets/src/mage/cards/c/CarnageCrimsonChaos.java +++ b/Mage.Sets/src/mage/cards/c/CarnageCrimsonChaos.java @@ -16,6 +16,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -32,7 +33,7 @@ import java.util.UUID; */ public final class CarnageCrimsonChaos extends CardImpl { - private static final FilterCard filter = new FilterCard("creature card with mana value 3 or less"); + private static final FilterCard filter = new FilterCreatureCard("creature card with mana value 3 or less"); static { filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, 3)); -- 2.47.2 From 80fdc8f88b408d3c0fcce825b90a36712c68447a Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 14:46:35 -0500 Subject: [PATCH 146/261] [TLA] Implement Abandoned Air Temple --- .../src/mage/cards/a/AbandonedAirTemple.java | 50 +++++++++++++++++++ .../src/mage/cards/f/FireNationPalace.java | 20 ++------ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + .../common/YouControlABasicLandCondition.java | 38 ++++++++++++++ 4 files changed, 93 insertions(+), 17 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/a/AbandonedAirTemple.java create mode 100644 Mage/src/main/java/mage/abilities/condition/common/YouControlABasicLandCondition.java diff --git a/Mage.Sets/src/mage/cards/a/AbandonedAirTemple.java b/Mage.Sets/src/mage/cards/a/AbandonedAirTemple.java new file mode 100644 index 00000000000..118806cf04a --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AbandonedAirTemple.java @@ -0,0 +1,50 @@ +package mage.cards.a; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedUnlessAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.YouControlABasicLandCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AbandonedAirTemple extends CardImpl { + + public AbandonedAirTemple(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped unless you control a basic land. + this.addAbility(new EntersBattlefieldTappedUnlessAbility(YouControlABasicLandCondition.instance) + .addHint(YouControlABasicLandCondition.getHint())); + + // {T}: Add {W}. + this.addAbility(new WhiteManaAbility()); + + // {3}{W}, {T}: Put a +1/+1 counter on each creature you control. + Ability ability = new SimpleActivatedAbility(new AddCountersAllEffect( + CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE + ), new ManaCostsImpl<>("{3}{W}")); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + private AbandonedAirTemple(final AbandonedAirTemple card) { + super(card); + } + + @Override + public AbandonedAirTemple copy() { + return new AbandonedAirTemple(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FireNationPalace.java b/Mage.Sets/src/mage/cards/f/FireNationPalace.java index 39f263df364..e7aaee487fe 100644 --- a/Mage.Sets/src/mage/cards/f/FireNationPalace.java +++ b/Mage.Sets/src/mage/cards/f/FireNationPalace.java @@ -3,21 +3,15 @@ package mage.cards.f; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedUnlessAbility; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.condition.common.YouControlABasicLandCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; import mage.abilities.keyword.FirebendingAbility; import mage.abilities.mana.RedManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SuperType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledLandPermanent; import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -27,20 +21,12 @@ import java.util.UUID; */ public final class FireNationPalace extends CardImpl { - private static final FilterPermanent filter = new FilterControlledLandPermanent("you control a basic land"); - - static { - filter.add(SuperType.BASIC.getPredicate()); - } - - private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); - private static final Hint hint = new ConditionHint(condition); - public FireNationPalace(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // This land enters tapped unless you control a basic land. - this.addAbility(new EntersBattlefieldTappedUnlessAbility(condition)); + this.addAbility(new EntersBattlefieldTappedUnlessAbility(YouControlABasicLandCondition.instance) + .addHint(YouControlABasicLandCondition.getHint())); // {T}: Add {R}. this.addAbility(new RedManaAbility()); diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 7911c405b3b..b3b2ad5c7b7 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -33,6 +33,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Aang, Master of Elements", 363, Rarity.MYTHIC, mage.cards.a.AangMasterOfElements.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, the Last Airbender", 4, Rarity.UNCOMMON, mage.cards.a.AangTheLastAirbender.class)); cards.add(new SetCardInfo("Abandon Attachments", 205, Rarity.COMMON, mage.cards.a.AbandonAttachments.class)); + cards.add(new SetCardInfo("Abandoned Air Temple", 263, Rarity.RARE, mage.cards.a.AbandonedAirTemple.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Abandoned Air Temple", 386, Rarity.RARE, mage.cards.a.AbandonedAirTemple.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Airbender Ascension", 364, Rarity.RARE, mage.cards.a.AirbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Airbender Ascension", 6, Rarity.RARE, mage.cards.a.AirbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Airbender's Reversal", 7, Rarity.UNCOMMON, mage.cards.a.AirbendersReversal.class)); diff --git a/Mage/src/main/java/mage/abilities/condition/common/YouControlABasicLandCondition.java b/Mage/src/main/java/mage/abilities/condition/common/YouControlABasicLandCondition.java new file mode 100644 index 00000000000..1bde708b141 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/YouControlABasicLandCondition.java @@ -0,0 +1,38 @@ +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledLandPermanent; +import mage.game.Game; + +/** + * @author TheElk801 + */ +public enum YouControlABasicLandCondition implements Condition { + instance; + private static final Hint hint = new ConditionHint(instance); + + public static Hint getHint() { + return hint; + } + + private static final FilterPermanent filter = new FilterControlledLandPermanent(); + + static { + filter.add(SuperType.BASIC.getPredicate()); + } + + @Override + public boolean apply(Game game, Ability source) { + return game.getBattlefield().contains(filter, source.getControllerId(), source, game, 1); + } + + @Override + public String toString() { + return "you control a basic land"; + } +} -- 2.47.2 From 7a71bf70aad2dc2fe15c575ab3d20f6bbc69154e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 14:47:48 -0500 Subject: [PATCH 147/261] [TLA] Implement Agna Qel'a --- Mage.Sets/src/mage/cards/a/AgnaQela.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 50 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AgnaQela.java diff --git a/Mage.Sets/src/mage/cards/a/AgnaQela.java b/Mage.Sets/src/mage/cards/a/AgnaQela.java new file mode 100644 index 00000000000..2af54ef1ce0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AgnaQela.java @@ -0,0 +1,48 @@ +package mage.cards.a; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedUnlessAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.YouControlABasicLandCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.abilities.mana.BlueManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AgnaQela extends CardImpl { + + public AgnaQela(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped unless you control a basic land. + this.addAbility(new EntersBattlefieldTappedUnlessAbility(YouControlABasicLandCondition.instance) + .addHint(YouControlABasicLandCondition.getHint())); + + // {T}: Add {U}. + this.addAbility(new BlueManaAbility()); + + // {2}{U}, {T}: Draw a card, then discard a card. + Ability ability = new SimpleActivatedAbility( + new DrawDiscardControllerEffect(1, 1), new ManaCostsImpl<>("{2}{U}") + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + private AgnaQela(final AgnaQela card) { + super(card); + } + + @Override + public AgnaQela copy() { + return new AgnaQela(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b3b2ad5c7b7..87bef3718ba 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -35,6 +35,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Abandon Attachments", 205, Rarity.COMMON, mage.cards.a.AbandonAttachments.class)); cards.add(new SetCardInfo("Abandoned Air Temple", 263, Rarity.RARE, mage.cards.a.AbandonedAirTemple.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Abandoned Air Temple", 386, Rarity.RARE, mage.cards.a.AbandonedAirTemple.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Agna Qel'a", 264, Rarity.RARE, mage.cards.a.AgnaQela.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Agna Qel'a", 387, Rarity.RARE, mage.cards.a.AgnaQela.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Airbender Ascension", 364, Rarity.RARE, mage.cards.a.AirbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Airbender Ascension", 6, Rarity.RARE, mage.cards.a.AirbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Airbender's Reversal", 7, Rarity.UNCOMMON, mage.cards.a.AirbendersReversal.class)); -- 2.47.2 From 401b70e61658ec184719516a82eb508a66970d9f Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 14:49:22 -0500 Subject: [PATCH 148/261] [TLA] Implement Ba Sing Se --- Mage.Sets/src/mage/cards/b/BaSingSe.java | 50 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 52 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BaSingSe.java diff --git a/Mage.Sets/src/mage/cards/b/BaSingSe.java b/Mage.Sets/src/mage/cards/b/BaSingSe.java new file mode 100644 index 00000000000..19becb63efa --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BaSingSe.java @@ -0,0 +1,50 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.EntersBattlefieldTappedUnlessAbility; +import mage.abilities.condition.common.YouControlABasicLandCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.abilities.mana.GreenManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BaSingSe extends CardImpl { + + public BaSingSe(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped unless you control a basic land. + this.addAbility(new EntersBattlefieldTappedUnlessAbility(YouControlABasicLandCondition.instance) + .addHint(YouControlABasicLandCondition.getHint())); + + // {T}: Add {G}. + this.addAbility(new GreenManaAbility()); + + // {2}{G}, {T}: Earthbend 2. Activate only as a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility( + new EarthbendTargetEffect(2), new ManaCostsImpl<>("{2}{G}") + ); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability); + } + + private BaSingSe(final BaSingSe card) { + super(card); + } + + @Override + public BaSingSe copy() { + return new BaSingSe(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 87bef3718ba..f308af0fb74 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -51,6 +51,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Avatar Enthusiasts", 11, Rarity.COMMON, mage.cards.a.AvatarEnthusiasts.class)); cards.add(new SetCardInfo("Azula Always Lies", 84, Rarity.COMMON, mage.cards.a.AzulaAlwaysLies.class)); cards.add(new SetCardInfo("Azula, On the Hunt", 85, Rarity.UNCOMMON, mage.cards.a.AzulaOnTheHunt.class)); + cards.add(new SetCardInfo("Ba Sing Se", 266, Rarity.RARE, mage.cards.b.BaSingSe.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ba Sing Se", 388, Rarity.RARE, mage.cards.b.BaSingSe.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Badgermole Cub", 167, Rarity.MYTHIC, mage.cards.b.BadgermoleCub.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Badgermole Cub", 326, Rarity.MYTHIC, mage.cards.b.BadgermoleCub.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Badgermole", 166, Rarity.COMMON, mage.cards.b.Badgermole.class)); -- 2.47.2 From e996131ea9ac12201c1114626226cc70ff6962c1 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 14:55:14 -0500 Subject: [PATCH 149/261] [TLA] Implement Air Nomad Legacy --- .../src/mage/cards/a/AirNomadLegacy.java | 41 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 42 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AirNomadLegacy.java diff --git a/Mage.Sets/src/mage/cards/a/AirNomadLegacy.java b/Mage.Sets/src/mage/cards/a/AirNomadLegacy.java new file mode 100644 index 00000000000..3ad0a54cfb3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AirNomadLegacy.java @@ -0,0 +1,41 @@ +package mage.cards.a; + +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.StaticFilters; +import mage.game.permanent.token.ClueArtifactToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AirNomadLegacy extends CardImpl { + + public AirNomadLegacy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{U}"); + + // When this enchantment enters, create a Clue token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ClueArtifactToken()))); + + // Creatures you control with flying get +1/+1. + this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( + 1, 1, Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURE_FLYING + ).setText("creatures you control with flying get +1/+1"))); + } + + private AirNomadLegacy(final AirNomadLegacy card) { + super(card); + } + + @Override + public AirNomadLegacy copy() { + return new AirNomadLegacy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index f308af0fb74..1df58a1bdae 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -37,6 +37,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Abandoned Air Temple", 386, Rarity.RARE, mage.cards.a.AbandonedAirTemple.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Agna Qel'a", 264, Rarity.RARE, mage.cards.a.AgnaQela.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Agna Qel'a", 387, Rarity.RARE, mage.cards.a.AgnaQela.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Air Nomad Legacy", 206, Rarity.UNCOMMON, mage.cards.a.AirNomadLegacy.class)); cards.add(new SetCardInfo("Airbender Ascension", 364, Rarity.RARE, mage.cards.a.AirbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Airbender Ascension", 6, Rarity.RARE, mage.cards.a.AirbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Airbender's Reversal", 7, Rarity.UNCOMMON, mage.cards.a.AirbendersReversal.class)); -- 2.47.2 From 6a5fb5dd51fb262eb967075924b7fbf225b63865 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 14:57:43 -0500 Subject: [PATCH 150/261] [TLA] Implement Boar-q-pine --- Mage.Sets/src/mage/cards/b/BoarQPine.java | 43 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 44 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BoarQPine.java diff --git a/Mage.Sets/src/mage/cards/b/BoarQPine.java b/Mage.Sets/src/mage/cards/b/BoarQPine.java new file mode 100644 index 00000000000..fa7588a24df --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BoarQPine.java @@ -0,0 +1,43 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BoarQPine extends CardImpl { + + public BoarQPine(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.BOAR); + this.subtype.add(SubType.PORCUPINE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever you cast a noncreature spell, put a +1/+1 counter on this creature. + this.addAbility(new SpellCastControllerTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), + StaticFilters.FILTER_SPELL_A_NON_CREATURE, false + )); + } + + private BoarQPine(final BoarQPine card) { + super(card); + } + + @Override + public BoarQPine copy() { + return new BoarQPine(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 1df58a1bdae..adc727520f6 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -61,6 +61,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Beetle-Headed Merchants", 86, Rarity.COMMON, mage.cards.b.BeetleHeadedMerchants.class)); cards.add(new SetCardInfo("Bender's Waterskin", 255, Rarity.COMMON, mage.cards.b.BendersWaterskin.class)); cards.add(new SetCardInfo("Benevolent River Spirit", 45, Rarity.UNCOMMON, mage.cards.b.BenevolentRiverSpirit.class)); + cards.add(new SetCardInfo("Boar-q-pine", 124, Rarity.COMMON, mage.cards.b.BoarQPine.class)); cards.add(new SetCardInfo("Boiling Rock Prison", 267, Rarity.COMMON, mage.cards.b.BoilingRockPrison.class)); cards.add(new SetCardInfo("Boomerang Basics", 46, Rarity.UNCOMMON, mage.cards.b.BoomerangBasics.class)); cards.add(new SetCardInfo("Bumi Bash", 125, Rarity.COMMON, mage.cards.b.BumiBash.class)); -- 2.47.2 From 71f642acc4166f18e7a17d300e692c8fe1283457 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 14:58:48 -0500 Subject: [PATCH 151/261] [TLA] Implement Canyon Crawler --- Mage.Sets/src/mage/cards/c/CanyonCrawler.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CanyonCrawler.java diff --git a/Mage.Sets/src/mage/cards/c/CanyonCrawler.java b/Mage.Sets/src/mage/cards/c/CanyonCrawler.java new file mode 100644 index 00000000000..64bced505f2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CanyonCrawler.java @@ -0,0 +1,48 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.SwampcyclingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.FoodToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CanyonCrawler extends CardImpl { + + public CanyonCrawler(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); + + this.subtype.add(SubType.SPIDER); + this.subtype.add(SubType.BEAST); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // When this creature enters, create a Food token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new FoodToken()))); + + // Swampcycling {2} + this.addAbility(new SwampcyclingAbility(new ManaCostsImpl<>("{2}"))); + } + + private CanyonCrawler(final CanyonCrawler card) { + super(card); + } + + @Override + public CanyonCrawler copy() { + return new CanyonCrawler(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index adc727520f6..9ae8a794599 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -69,6 +69,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Bumi, Unleashed", 348, Rarity.MYTHIC, mage.cards.b.BumiUnleashed.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Buzzard-Wasp Colony", 88, Rarity.UNCOMMON, mage.cards.b.BuzzardWaspColony.class)); cards.add(new SetCardInfo("Callous Inspector", 89, Rarity.COMMON, mage.cards.c.CallousInspector.class)); + cards.add(new SetCardInfo("Canyon Crawler", 90, Rarity.COMMON, mage.cards.c.CanyonCrawler.class)); cards.add(new SetCardInfo("Cat-Gator", 91, Rarity.UNCOMMON, mage.cards.c.CatGator.class)); cards.add(new SetCardInfo("Cat-Owl", 212, Rarity.COMMON, mage.cards.c.CatOwl.class)); cards.add(new SetCardInfo("Compassionate Healer", 13, Rarity.COMMON, mage.cards.c.CompassionateHealer.class)); -- 2.47.2 From 504d8d375fbcb15fb53c0ed2e2b0b7f0670e34a7 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:00:50 -0500 Subject: [PATCH 152/261] [TLA] Implement Curious Farm Animals --- .../src/mage/cards/c/CuriousFarmAnimals.java | 53 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 54 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CuriousFarmAnimals.java diff --git a/Mage.Sets/src/mage/cards/c/CuriousFarmAnimals.java b/Mage.Sets/src/mage/cards/c/CuriousFarmAnimals.java new file mode 100644 index 00000000000..22c98506229 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CuriousFarmAnimals.java @@ -0,0 +1,53 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CuriousFarmAnimals extends CardImpl { + + public CuriousFarmAnimals(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); + + this.subtype.add(SubType.BOAR); + this.subtype.add(SubType.ELK); + this.subtype.add(SubType.BIRD); + this.subtype.add(SubType.OX); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When this creature dies, you gain 3 life. + this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(3))); + + // {2}, Sacrifice this creature: Destroy up to one target artifact or enchantment. + Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new GenericManaCost(2)); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); + this.addAbility(ability); + } + + private CuriousFarmAnimals(final CuriousFarmAnimals card) { + super(card); + } + + @Override + public CuriousFarmAnimals copy() { + return new CuriousFarmAnimals(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 9ae8a794599..f8ff362914f 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -77,6 +77,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Crescent Island Temple", 129, Rarity.UNCOMMON, mage.cards.c.CrescentIslandTemple.class)); cards.add(new SetCardInfo("Cruel Administrator", 213, Rarity.UNCOMMON, mage.cards.c.CruelAdministrator.class)); cards.add(new SetCardInfo("Cunning Maneuver", 130, Rarity.COMMON, mage.cards.c.CunningManeuver.class)); + cards.add(new SetCardInfo("Curious Farm Animals", 14, Rarity.COMMON, mage.cards.c.CuriousFarmAnimals.class)); cards.add(new SetCardInfo("Cycle of Renewal", 170, Rarity.COMMON, mage.cards.c.CycleOfRenewal.class)); cards.add(new SetCardInfo("Dai Li Agents", 214, Rarity.UNCOMMON, mage.cards.d.DaiLiAgents.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dai Li Agents", 306, Rarity.UNCOMMON, mage.cards.d.DaiLiAgents.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From b69a4c16168254e626f58bfe05e41e9f485e9005 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:02:29 -0500 Subject: [PATCH 153/261] [TLA] Implement Earth Kingdom Protectors --- .../mage/cards/e/EarthKingdomProtectors.java | 61 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 62 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EarthKingdomProtectors.java diff --git a/Mage.Sets/src/mage/cards/e/EarthKingdomProtectors.java b/Mage.Sets/src/mage/cards/e/EarthKingdomProtectors.java new file mode 100644 index 00000000000..d68b0b91fb8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EarthKingdomProtectors.java @@ -0,0 +1,61 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EarthKingdomProtectors extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledPermanent(SubType.ALLY, "another target Ally you control"); + + static { + filter.add(AnotherPredicate.instance); + } + + public EarthKingdomProtectors(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Sacrifice this creature: Another target Ally you control gains indestructible until end of turn. + Ability ability = new SimpleActivatedAbility( + new GainAbilityTargetEffect(IndestructibleAbility.getInstance()), new SacrificeSourceCost() + ); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + private EarthKingdomProtectors(final EarthKingdomProtectors card) { + super(card); + } + + @Override + public EarthKingdomProtectors copy() { + return new EarthKingdomProtectors(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index f8ff362914f..65f840afb6b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -90,6 +90,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Earth King's Lieutenant", 217, Rarity.RARE, mage.cards.e.EarthKingsLieutenant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earth King's Lieutenant", 380, Rarity.RARE, mage.cards.e.EarthKingsLieutenant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earth Kingdom Jailer", 16, Rarity.UNCOMMON, mage.cards.e.EarthKingdomJailer.class)); + cards.add(new SetCardInfo("Earth Kingdom Protectors", 17, Rarity.UNCOMMON, mage.cards.e.EarthKingdomProtectors.class)); cards.add(new SetCardInfo("Earth Kingdom Soldier", 216, Rarity.COMMON, mage.cards.e.EarthKingdomSoldier.class)); cards.add(new SetCardInfo("Earth Rumble Wrestlers", 218, Rarity.COMMON, mage.cards.e.EarthRumbleWrestlers.class)); cards.add(new SetCardInfo("Earth Rumble", 174, Rarity.UNCOMMON, mage.cards.e.EarthRumble.class)); -- 2.47.2 From da4c97acbed6089b684ee2baf19db269eee50a4d Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:06:11 -0500 Subject: [PATCH 154/261] [TLA] Implement Firebending Lesson --- .../src/mage/cards/f/FirebendingLesson.java | 45 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 46 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FirebendingLesson.java diff --git a/Mage.Sets/src/mage/cards/f/FirebendingLesson.java b/Mage.Sets/src/mage/cards/f/FirebendingLesson.java new file mode 100644 index 00000000000..495e9c46ab9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FirebendingLesson.java @@ -0,0 +1,45 @@ +package mage.cards.f; + +import mage.abilities.condition.common.KickedCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.KickerAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FirebendingLesson extends CardImpl { + + public FirebendingLesson(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); + + this.subtype.add(SubType.LESSON); + + // Kicker {4} + this.addAbility(new KickerAbility("{4}")); + + // Firebending Lesson deals 2 damage to target creature. If this spell was kicked, it deals 5 damage to that creature instead. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new DamageTargetEffect(5), new DamageTargetEffect(2), + KickedCondition.ONCE, "{this} deals 2 damage to target creature. " + + "If this spell was kicked, it deals 5 damage to that creature instead" + )); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private FirebendingLesson(final FirebendingLesson card) { + super(card); + } + + @Override + public FirebendingLesson copy() { + return new FirebendingLesson(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 65f840afb6b..924dd4712ea 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -123,6 +123,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Fire Sages", 136, Rarity.UNCOMMON, mage.cards.f.FireSages.class)); cards.add(new SetCardInfo("Firebender Ascension", 137, Rarity.RARE, mage.cards.f.FirebenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Firebender Ascension", 312, Rarity.RARE, mage.cards.f.FirebenderAscension.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Firebending Lesson", 138, Rarity.COMMON, mage.cards.f.FirebendingLesson.class)); cards.add(new SetCardInfo("Firebending Student", 139, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Firebending Student", 342, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Firebending Student", 393, Rarity.RARE, mage.cards.f.FirebendingStudent.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From f744712d928c3ecf9cd359448180256e365f62e9 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:09:04 -0500 Subject: [PATCH 155/261] [TLA] Implement Foggy Swamp Vinebender --- .../mage/cards/f/FoggySwampVinebender.java | 49 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 50 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FoggySwampVinebender.java diff --git a/Mage.Sets/src/mage/cards/f/FoggySwampVinebender.java b/Mage.Sets/src/mage/cards/f/FoggySwampVinebender.java new file mode 100644 index 00000000000..a34af151b15 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FoggySwampVinebender.java @@ -0,0 +1,49 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.common.WaterbendCost; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.DauntAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FoggySwampVinebender extends CardImpl { + + public FoggySwampVinebender(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.PLANT); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // This creature can't be blocked by creatures with power 2 or less. + this.addAbility(new DauntAbility()); + + // Waterbend {5}: Put a +1/+1 counter on this creature. Activate only during your turn. + this.addAbility(new ActivateIfConditionActivatedAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), + new WaterbendCost(5), MyTurnCondition.instance + )); + } + + private FoggySwampVinebender(final FoggySwampVinebender card) { + super(card); + } + + @Override + public FoggySwampVinebender copy() { + return new FoggySwampVinebender(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 924dd4712ea..b591bcb6c1b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -131,6 +131,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Flexible Waterbender", 50, Rarity.COMMON, mage.cards.f.FlexibleWaterbender.class)); cards.add(new SetCardInfo("Flopsie, Bumi's Buddy", 179, Rarity.UNCOMMON, mage.cards.f.FlopsieBumisBuddy.class)); cards.add(new SetCardInfo("Foggy Bottom Swamp", 269, Rarity.COMMON, mage.cards.f.FoggyBottomSwamp.class)); + cards.add(new SetCardInfo("Foggy Swamp Vinebender", 180, Rarity.COMMON, mage.cards.f.FoggySwampVinebender.class)); cards.add(new SetCardInfo("Forecasting Fortune Teller", 51, Rarity.COMMON, mage.cards.f.ForecastingFortuneTeller.class)); cards.add(new SetCardInfo("Forest", 286, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Forest", 291, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); -- 2.47.2 From 6a2bc8f2eede1694d44e44288dc10c2695fc86aa Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:12:12 -0500 Subject: [PATCH 156/261] [TLA] Implement Joo Dee, One of Many --- .../src/mage/cards/j/JooDeeOneOfMany.java | 52 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 53 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/j/JooDeeOneOfMany.java diff --git a/Mage.Sets/src/mage/cards/j/JooDeeOneOfMany.java b/Mage.Sets/src/mage/cards/j/JooDeeOneOfMany.java new file mode 100644 index 00000000000..1736af86532 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JooDeeOneOfMany.java @@ -0,0 +1,52 @@ +package mage.cards.j; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.CreateTokenCopySourceEffect; +import mage.abilities.effects.common.SacrificeControllerEffect; +import mage.abilities.effects.keyword.SurveilEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JooDeeOneOfMany extends CardImpl { + + public JooDeeOneOfMany(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ADVISOR); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {B}, {T}: Surveil 1. Create a token that's a copy of this creature, then sacrifice an artifact or creature. Activate only as a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility( + new SurveilEffect(1, false), new ManaCostsImpl<>("{B}") + ); + ability.addCost(new TapSourceCost()); + ability.addEffect(new CreateTokenCopySourceEffect()); + ability.addEffect(new SacrificeControllerEffect( + StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE, 1, ", then" + )); + this.addAbility(ability); + } + + private JooDeeOneOfMany(final JooDeeOneOfMany card) { + super(card); + } + + @Override + public JooDeeOneOfMany copy() { + return new JooDeeOneOfMany(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b591bcb6c1b..e50d0beb900 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -163,6 +163,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("It'll Quench Ya!", 58, Rarity.COMMON, mage.cards.i.ItllQuenchYa.class)); cards.add(new SetCardInfo("Jeong Jeong's Deserters", 25, Rarity.COMMON, mage.cards.j.JeongJeongsDeserters.class)); cards.add(new SetCardInfo("Jet's Brainwashing", 143, Rarity.UNCOMMON, mage.cards.j.JetsBrainwashing.class)); + cards.add(new SetCardInfo("Joo Dee, One of Many", 105, Rarity.UNCOMMON, mage.cards.j.JooDeeOneOfMany.class)); cards.add(new SetCardInfo("Katara, Bending Prodigy", 59, Rarity.UNCOMMON, mage.cards.k.KataraBendingProdigy.class)); cards.add(new SetCardInfo("Katara, Water Tribe's Hope", 231, Rarity.RARE, mage.cards.k.KataraWaterTribesHope.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Water Tribe's Hope", 351, Rarity.RARE, mage.cards.k.KataraWaterTribesHope.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From cff73aa9f89854481b561b9e52f4a8915e911e62 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:13:43 -0500 Subject: [PATCH 157/261] [TLA] Implement Meteor Sword --- Mage.Sets/src/mage/cards/m/MeteorSword.java | 47 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 48 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MeteorSword.java diff --git a/Mage.Sets/src/mage/cards/m/MeteorSword.java b/Mage.Sets/src/mage/cards/m/MeteorSword.java new file mode 100644 index 00000000000..86f5114ff80 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MeteorSword.java @@ -0,0 +1,47 @@ +package mage.cards.m; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MeteorSword extends CardImpl { + + public MeteorSword(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{7}"); + + this.subtype.add(SubType.EQUIPMENT); + + // When this Equipment enters, destroy target permanent. + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); + ability.addTarget(new TargetPermanent()); + this.addAbility(ability); + + // Equipped creature gets +3/+3. + this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(3, 3))); + + // Equip {3} + this.addAbility(new EquipAbility(3)); + } + + private MeteorSword(final MeteorSword card) { + super(card); + } + + @Override + public MeteorSword copy() { + return new MeteorSword(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index e50d0beb900..4cd1b3eff14 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -185,6 +185,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Master Piandao", 28, Rarity.UNCOMMON, mage.cards.m.MasterPiandao.class)); cards.add(new SetCardInfo("Meditation Pools", 272, Rarity.COMMON, mage.cards.m.MeditationPools.class)); cards.add(new SetCardInfo("Merchant of Many Hats", 110, Rarity.COMMON, mage.cards.m.MerchantOfManyHats.class)); + cards.add(new SetCardInfo("Meteor Sword", 258, Rarity.UNCOMMON, mage.cards.m.MeteorSword.class)); cards.add(new SetCardInfo("Misty Palms Oasis", 273, Rarity.COMMON, mage.cards.m.MistyPalmsOasis.class)); cards.add(new SetCardInfo("Momo, Friendly Flier", 29, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Momo, Friendly Flier", 317, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From a986cdf31eb1a51fc93a6f12b6c40147e4fadfc9 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:16:10 -0500 Subject: [PATCH 158/261] [TLA] Implement Rumble Arena --- Mage.Sets/src/mage/cards/r/RumbleArena.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/r/RumbleArena.java diff --git a/Mage.Sets/src/mage/cards/r/RumbleArena.java b/Mage.Sets/src/mage/cards/r/RumbleArena.java new file mode 100644 index 00000000000..47dd8997ea4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RumbleArena.java @@ -0,0 +1,48 @@ +package mage.cards.r; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.keyword.ScryEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RumbleArena extends CardImpl { + + public RumbleArena(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // When this land enters, scry 1. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(1))); + + // {T}: Add {C}. + this.addAbility(new ColorlessManaAbility()); + + // {1}, {T}: Add one mana of any color. + Ability ability = new AnyColorManaAbility(new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + private RumbleArena(final RumbleArena card) { + super(card); + } + + @Override + public RumbleArena copy() { + return new RumbleArena(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 4cd1b3eff14..e8420299b1d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -229,6 +229,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Rocky Rebuke", 193, Rarity.COMMON, mage.cards.r.RockyRebuke.class)); cards.add(new SetCardInfo("Rough Rhino Cavalry", 152, Rarity.COMMON, mage.cards.r.RoughRhinoCavalry.class)); cards.add(new SetCardInfo("Rowdy Snowballers", 68, Rarity.COMMON, mage.cards.r.RowdySnowballers.class)); + cards.add(new SetCardInfo("Rumble Arena", 277, Rarity.COMMON, mage.cards.r.RumbleArena.class)); cards.add(new SetCardInfo("Saber-Tooth Moose-Lion", 194, Rarity.COMMON, mage.cards.s.SaberToothMooseLion.class)); cards.add(new SetCardInfo("Sandbenders' Storm", 34, Rarity.COMMON, mage.cards.s.SandbendersStorm.class)); cards.add(new SetCardInfo("Seismic Sense", 195, Rarity.UNCOMMON, mage.cards.s.SeismicSense.class)); -- 2.47.2 From 67004140ffd1d1f3372e8887c890e637edc8ce89 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:19:15 -0500 Subject: [PATCH 159/261] [TLA] Implement South Pole Voyager --- .../src/mage/cards/s/SouthPoleVoyager.java | 47 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SouthPoleVoyager.java diff --git a/Mage.Sets/src/mage/cards/s/SouthPoleVoyager.java b/Mage.Sets/src/mage/cards/s/SouthPoleVoyager.java new file mode 100644 index 00000000000..4101ea86db8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SouthPoleVoyager.java @@ -0,0 +1,47 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.IfAbilityHasResolvedXTimesEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SouthPoleVoyager extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent(SubType.ALLY, "Ally"); + + public SouthPoleVoyager(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SCOUT); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever this creature or another Ally you control enters, you gain 1 life. If this is the second time this ability has resolved this turn, draw a card. + Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(new GainLifeEffect(1), filter, false, true); + ability.addEffect(new IfAbilityHasResolvedXTimesEffect(2, new DrawCardSourceControllerEffect(1))); + this.addAbility(ability); + } + + private SouthPoleVoyager(final SouthPoleVoyager card) { + super(card); + } + + @Override + public SouthPoleVoyager copy() { + return new SouthPoleVoyager(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index e8420299b1d..5fb05d1daf1 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -244,6 +244,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Sokka, Tenacious Tactician", 352, Rarity.RARE, mage.cards.s.SokkaTenaciousTactician.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sold Out", 119, Rarity.COMMON, mage.cards.s.SoldOut.class)); cards.add(new SetCardInfo("Solstice Revelations", 153, Rarity.UNCOMMON, mage.cards.s.SolsticeRevelations.class)); + cards.add(new SetCardInfo("South Pole Voyager", 35, Rarity.RARE, mage.cards.s.SouthPoleVoyager.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("South Pole Voyager", 367, Rarity.RARE, mage.cards.s.SouthPoleVoyager.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Southern Air Temple", 36, Rarity.UNCOMMON, mage.cards.s.SouthernAirTemple.class)); cards.add(new SetCardInfo("Sozin's Comet", 154, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sozin's Comet", 309, Rarity.MYTHIC, mage.cards.s.SozinsComet.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 3c75bd4889003af08206740d7298a582eaf2de18 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:19:53 -0500 Subject: [PATCH 160/261] [TLA] Implement Wandering Musicians --- .../src/mage/cards/w/WanderingMusicians.java | 40 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 41 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/w/WanderingMusicians.java diff --git a/Mage.Sets/src/mage/cards/w/WanderingMusicians.java b/Mage.Sets/src/mage/cards/w/WanderingMusicians.java new file mode 100644 index 00000000000..2402e267f45 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WanderingMusicians.java @@ -0,0 +1,40 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WanderingMusicians extends CardImpl { + + public WanderingMusicians(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R/W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.BARD); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(5); + + // Whenever this creature attacks, creatures you control get +1/+0 until end of turn. + this.addAbility(new AttacksTriggeredAbility(new BoostControlledEffect(1, 0, Duration.EndOfTurn))); + } + + private WanderingMusicians(final WanderingMusicians card) { + super(card); + } + + @Override + public WanderingMusicians copy() { + return new WanderingMusicians(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 5fb05d1daf1..b064c1d4e9f 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -290,6 +290,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("United Front", 331, Rarity.MYTHIC, mage.cards.u.UnitedFront.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("United Front", 39, Rarity.MYTHIC, mage.cards.u.UnitedFront.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Vindictive Warden", 249, Rarity.COMMON, mage.cards.v.VindictiveWarden.class)); + cards.add(new SetCardInfo("Wandering Musicians", 250, Rarity.COMMON, mage.cards.w.WanderingMusicians.class)); cards.add(new SetCardInfo("War Balloon", 159, Rarity.UNCOMMON, mage.cards.w.WarBalloon.class)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); cards.add(new SetCardInfo("Watery Grasp", 82, Rarity.COMMON, mage.cards.w.WateryGrasp.class)); -- 2.47.2 From 1bd39630793e1e6d0ab3e0e5e694a94e11ca9f7b Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:20:47 -0500 Subject: [PATCH 161/261] [TLA] Implement Water Tribe Captain --- .../src/mage/cards/w/WaterTribeCaptain.java | 43 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 44 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/w/WaterTribeCaptain.java diff --git a/Mage.Sets/src/mage/cards/w/WaterTribeCaptain.java b/Mage.Sets/src/mage/cards/w/WaterTribeCaptain.java new file mode 100644 index 00000000000..617bd68b59e --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WaterTribeCaptain.java @@ -0,0 +1,43 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WaterTribeCaptain extends CardImpl { + + public WaterTribeCaptain(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // {5}: Creatures you control get +1/+1 until end of turn. + this.addAbility(new SimpleActivatedAbility( + new BoostControlledEffect(1, 1, Duration.EndOfTurn), new GenericManaCost(5) + )); + } + + private WaterTribeCaptain(final WaterTribeCaptain card) { + super(card); + } + + @Override + public WaterTribeCaptain copy() { + return new WaterTribeCaptain(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b064c1d4e9f..6531068aa6e 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -292,6 +292,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Vindictive Warden", 249, Rarity.COMMON, mage.cards.v.VindictiveWarden.class)); cards.add(new SetCardInfo("Wandering Musicians", 250, Rarity.COMMON, mage.cards.w.WanderingMusicians.class)); cards.add(new SetCardInfo("War Balloon", 159, Rarity.UNCOMMON, mage.cards.w.WarBalloon.class)); + cards.add(new SetCardInfo("Water Tribe Captain", 41, Rarity.COMMON, mage.cards.w.WaterTribeCaptain.class)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); cards.add(new SetCardInfo("Watery Grasp", 82, Rarity.COMMON, mage.cards.w.WateryGrasp.class)); cards.add(new SetCardInfo("White Lotus Reinforcements", 251, Rarity.UNCOMMON, mage.cards.w.WhiteLotusReinforcements.class)); -- 2.47.2 From f0d1fb8fa4102ebcebfcda17fb5e489d7c315c38 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:22:26 -0500 Subject: [PATCH 162/261] [TLA] Implement Water Tribe Rallier --- .../src/mage/cards/w/WaterTribeRallier.java | 53 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 54 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/w/WaterTribeRallier.java diff --git a/Mage.Sets/src/mage/cards/w/WaterTribeRallier.java b/Mage.Sets/src/mage/cards/w/WaterTribeRallier.java new file mode 100644 index 00000000000..5c3d881a71b --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WaterTribeRallier.java @@ -0,0 +1,53 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.WaterbendCost; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.PutCards; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.PowerPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WaterTribeRallier extends CardImpl { + + private static final FilterCard filter = new FilterCreatureCard("creature card with power 3 or less"); + + static { + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 4)); + } + + public WaterTribeRallier(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Waterbend {5}: Look at the top four cards of your library. You may reveal a creature card with power 3 or less from among them and put it into your hand. Put the rest on the bottom of your library in a random order. + this.addAbility(new SimpleActivatedAbility(new LookLibraryAndPickControllerEffect( + 4, 1, filter, PutCards.HAND, PutCards.BOTTOM_RANDOM + ), new WaterbendCost(5))); + } + + private WaterTribeRallier(final WaterTribeRallier card) { + super(card); + } + + @Override + public WaterTribeRallier copy() { + return new WaterTribeRallier(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 6531068aa6e..85d6c481289 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -293,6 +293,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Wandering Musicians", 250, Rarity.COMMON, mage.cards.w.WanderingMusicians.class)); cards.add(new SetCardInfo("War Balloon", 159, Rarity.UNCOMMON, mage.cards.w.WarBalloon.class)); cards.add(new SetCardInfo("Water Tribe Captain", 41, Rarity.COMMON, mage.cards.w.WaterTribeCaptain.class)); + cards.add(new SetCardInfo("Water Tribe Rallier", 42, Rarity.UNCOMMON, mage.cards.w.WaterTribeRallier.class)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); cards.add(new SetCardInfo("Watery Grasp", 82, Rarity.COMMON, mage.cards.w.WateryGrasp.class)); cards.add(new SetCardInfo("White Lotus Reinforcements", 251, Rarity.UNCOMMON, mage.cards.w.WhiteLotusReinforcements.class)); -- 2.47.2 From 70327c70c72dec916c7a918a90e1ef0401d87bae Mon Sep 17 00:00:00 2001 From: theelk801 Date: Sat, 8 Nov 2025 15:24:22 -0500 Subject: [PATCH 163/261] [TLA] Implement Zuko's Conviction --- .../src/mage/cards/z/ZukosConviction.java | 42 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 43 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/z/ZukosConviction.java diff --git a/Mage.Sets/src/mage/cards/z/ZukosConviction.java b/Mage.Sets/src/mage/cards/z/ZukosConviction.java new file mode 100644 index 00000000000..f0ed6978e52 --- /dev/null +++ b/Mage.Sets/src/mage/cards/z/ZukosConviction.java @@ -0,0 +1,42 @@ +package mage.cards.z; + +import mage.abilities.condition.common.KickedCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.abilities.keyword.KickerAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ZukosConviction extends CardImpl { + + public ZukosConviction(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}"); + + // Kicker {4} + this.addAbility(new KickerAbility("{4}")); + + // Return target creature card from your graveyard to your hand. If this spell was kicked, instead put that card onto the battlefield tapped. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new ReturnFromGraveyardToBattlefieldTargetEffect(true), + new ReturnFromGraveyardToHandTargetEffect(), + KickedCondition.ONCE, "return target creature card from your graveyard to your hand. " + + "If this spell was kicked, instead put that card onto the battlefield tapped" + )); + } + + private ZukosConviction(final ZukosConviction card) { + super(card); + } + + @Override + public ZukosConviction copy() { + return new ZukosConviction(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 85d6c481289..702862826a6 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -305,6 +305,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Yue, the Moon Spirit", 83, Rarity.RARE, mage.cards.y.YueTheMoonSpirit.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Yuyan Archers", 161, Rarity.COMMON, mage.cards.y.YuyanArchers.class)); cards.add(new SetCardInfo("Zhao, Ruthless Admiral", 252, Rarity.UNCOMMON, mage.cards.z.ZhaoRuthlessAdmiral.class)); + cards.add(new SetCardInfo("Zuko's Conviction", 123, Rarity.UNCOMMON, mage.cards.z.ZukosConviction.class)); cards.add(new SetCardInfo("Zuko's Exile", 3, Rarity.COMMON, mage.cards.z.ZukosExile.class)); cards.add(new SetCardInfo("Zuko, Exiled Prince", 163, Rarity.UNCOMMON, mage.cards.z.ZukoExiledPrince.class)); -- 2.47.2 From eb69df162338ac40bc8ba88b2c3eff9ca82819fc Mon Sep 17 00:00:00 2001 From: ReSech Date: Sun, 9 Nov 2025 07:26:13 +1100 Subject: [PATCH 164/261] FULL_ART Card and Check Fixes (#14004) * Fix SLD Lands and SLC Full Art * Update FULL_ART cards in SPM * Update FULL_ART in SLD * More SLD FULL_ART * update test_checkWrongFullArtAndRetro --- Mage.Sets/src/mage/sets/MarvelsSpiderMan.java | 16 +- .../src/mage/sets/SecretLairCountdown.java | 2 +- Mage.Sets/src/mage/sets/SecretLairDrop.java | 382 +++++++++--------- .../java/mage/verify/VerifyCardDataTest.java | 22 +- 4 files changed, 213 insertions(+), 209 deletions(-) diff --git a/Mage.Sets/src/mage/sets/MarvelsSpiderMan.java b/Mage.Sets/src/mage/sets/MarvelsSpiderMan.java index 6479f72823e..ae7b50e8bc2 100644 --- a/Mage.Sets/src/mage/sets/MarvelsSpiderMan.java +++ b/Mage.Sets/src/mage/sets/MarvelsSpiderMan.java @@ -40,14 +40,14 @@ public final class MarvelsSpiderMan extends ExpansionSet { cards.add(new SetCardInfo("Aunt May", 3, Rarity.UNCOMMON, mage.cards.a.AuntMay.class)); cards.add(new SetCardInfo("Bagel and Schmear", 161, Rarity.COMMON, mage.cards.b.BagelAndSchmear.class)); cards.add(new SetCardInfo("Beetle, Legacy Criminal", 26, Rarity.COMMON, mage.cards.b.BeetleLegacyCriminal.class)); - cards.add(new SetCardInfo("Behold the Sinister Six!", 221, Rarity.MYTHIC, mage.cards.b.BeholdTheSinisterSix.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Behold the Sinister Six!", 221, Rarity.MYTHIC, mage.cards.b.BeholdTheSinisterSix.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Behold the Sinister Six!", 51, Rarity.MYTHIC, mage.cards.b.BeholdTheSinisterSix.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Biorganic Carapace", 124, Rarity.RARE, mage.cards.b.BiorganicCarapace.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Biorganic Carapace", 269, Rarity.RARE, mage.cards.b.BiorganicCarapace.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Black Cat, Cunning Thief", 222, Rarity.RARE, mage.cards.b.BlackCatCunningThief.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Black Cat, Cunning Thief", 222, Rarity.RARE, mage.cards.b.BlackCatCunningThief.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Black Cat, Cunning Thief", 52, Rarity.RARE, mage.cards.b.BlackCatCunningThief.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Carnage, Crimson Chaos", 125, Rarity.RARE, mage.cards.c.CarnageCrimsonChaos.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Carnage, Crimson Chaos", 227, Rarity.RARE, mage.cards.c.CarnageCrimsonChaos.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Carnage, Crimson Chaos", 227, Rarity.RARE, mage.cards.c.CarnageCrimsonChaos.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Chameleon, Master of Disguise", 27, Rarity.UNCOMMON, mage.cards.c.ChameleonMasterOfDisguise.class)); cards.add(new SetCardInfo("Cheering Crowd", 126, Rarity.RARE, mage.cards.c.CheeringCrowd.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Cheering Crowd", 270, Rarity.RARE, mage.cards.c.CheeringCrowd.class, NON_FULL_USE_VARIOUS)); @@ -64,7 +64,7 @@ public final class MarvelsSpiderMan extends ExpansionSet { cards.add(new SetCardInfo("Doc Ock's Tentacles", 277, Rarity.RARE, mage.cards.d.DocOcksTentacles.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Doc Ock, Sinister Scientist", 29, Rarity.COMMON, mage.cards.d.DocOckSinisterScientist.class)); cards.add(new SetCardInfo("Doctor Octopus, Master Planner", 128, Rarity.MYTHIC, mage.cards.d.DoctorOctopusMasterPlanner.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Doctor Octopus, Master Planner", 228, Rarity.MYTHIC, mage.cards.d.DoctorOctopusMasterPlanner.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Doctor Octopus, Master Planner", 228, Rarity.MYTHIC, mage.cards.d.DoctorOctopusMasterPlanner.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Eddie Brock", 224, Rarity.MYTHIC, mage.cards.e.EddieBrock.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Eddie Brock", 233, Rarity.MYTHIC, mage.cards.e.EddieBrock.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Eddie Brock", 55, Rarity.MYTHIC, mage.cards.e.EddieBrock.class, NON_FULL_USE_VARIOUS)); @@ -124,7 +124,7 @@ public final class MarvelsSpiderMan extends ExpansionSet { cards.add(new SetCardInfo("Lurking Lizards", 107, Rarity.COMMON, mage.cards.l.LurkingLizards.class)); cards.add(new SetCardInfo("Madame Web, Clairvoyant", 36, Rarity.UNCOMMON, mage.cards.m.MadameWebClairvoyant.class)); cards.add(new SetCardInfo("Mary Jane Watson", 134, Rarity.RARE, mage.cards.m.MaryJaneWatson.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mary Jane Watson", 229, Rarity.RARE, mage.cards.m.MaryJaneWatson.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mary Jane Watson", 229, Rarity.RARE, mage.cards.m.MaryJaneWatson.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Masked Meower", 82, Rarity.COMMON, mage.cards.m.MaskedMeower.class)); cards.add(new SetCardInfo("Maximum Carnage", 225, Rarity.RARE, mage.cards.m.MaximumCarnage.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Maximum Carnage", 83, Rarity.RARE, mage.cards.m.MaximumCarnage.class, NON_FULL_USE_VARIOUS)); @@ -248,7 +248,7 @@ public final class MarvelsSpiderMan extends ExpansionSet { cards.add(new SetCardInfo("Spider-Verse", 263, Rarity.MYTHIC, mage.cards.s.SpiderVerse.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Spider-Verse", 93, Rarity.MYTHIC, mage.cards.s.SpiderVerse.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Spider-Woman, Stunning Savior", 152, Rarity.RARE, mage.cards.s.SpiderWomanStunningSavior.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Spider-Woman, Stunning Savior", 230, Rarity.RARE, mage.cards.s.SpiderWomanStunningSavior.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Spider-Woman, Stunning Savior", 230, Rarity.RARE, mage.cards.s.SpiderWomanStunningSavior.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Spiders-Man, Heroic Horde", 117, Rarity.UNCOMMON, mage.cards.s.SpidersManHeroicHorde.class)); cards.add(new SetCardInfo("Spinneret and Spiderling", 264, Rarity.RARE, mage.cards.s.SpinneretAndSpiderling.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Spinneret and Spiderling", 94, Rarity.RARE, mage.cards.s.SpinneretAndSpiderling.class, NON_FULL_USE_VARIOUS)); @@ -276,12 +276,12 @@ public final class MarvelsSpiderMan extends ExpansionSet { cards.add(new SetCardInfo("The Clone Saga", 28, Rarity.RARE, mage.cards.t.TheCloneSaga.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Death of Gwen Stacy", 223, Rarity.RARE, mage.cards.t.TheDeathOfGwenStacy.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("The Death of Gwen Stacy", 54, Rarity.RARE, mage.cards.t.TheDeathOfGwenStacy.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("The Soul Stone", 242, Rarity.MYTHIC, mage.cards.t.TheSoulStone.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Soul Stone", 242, Rarity.MYTHIC, mage.cards.t.TheSoulStone.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("The Soul Stone", 243, Rarity.MYTHIC, mage.cards.t.TheSoulStone.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Soul Stone", 66, Rarity.MYTHIC, mage.cards.t.TheSoulStone.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Spot's Portal", 68, Rarity.UNCOMMON, mage.cards.t.TheSpotsPortal.class)); cards.add(new SetCardInfo("The Spot, Living Portal", 153, Rarity.RARE, mage.cards.t.TheSpotLivingPortal.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("The Spot, Living Portal", 231, Rarity.RARE, mage.cards.t.TheSpotLivingPortal.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Spot, Living Portal", 231, Rarity.RARE, mage.cards.t.TheSpotLivingPortal.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Thwip!", 20, Rarity.COMMON, mage.cards.t.Thwip.class)); cards.add(new SetCardInfo("Tombstone, Career Criminal", 70, Rarity.UNCOMMON, mage.cards.t.TombstoneCareerCriminal.class)); cards.add(new SetCardInfo("Ultimate Green Goblin", 157, Rarity.RARE, mage.cards.u.UltimateGreenGoblin.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage.Sets/src/mage/sets/SecretLairCountdown.java b/Mage.Sets/src/mage/sets/SecretLairCountdown.java index 963489f2db8..bf9c227fbce 100644 --- a/Mage.Sets/src/mage/sets/SecretLairCountdown.java +++ b/Mage.Sets/src/mage/sets/SecretLairCountdown.java @@ -59,7 +59,7 @@ public class SecretLairCountdown extends ExpansionSet { cards.add(new SetCardInfo("Ponder", 2007, Rarity.RARE, mage.cards.p.Ponder.class)); cards.add(new SetCardInfo("Questing Beast", 17, Rarity.MYTHIC, mage.cards.q.QuestingBeast.class)); cards.add(new SetCardInfo("Retrofitter Foundry", 18, Rarity.RARE, mage.cards.r.RetrofitterFoundry.class)); - cards.add(new SetCardInfo("Shark Typhoon", 2020, Rarity.RARE, mage.cards.s.SharkTyphoon.class)); + cards.add(new SetCardInfo("Shark Typhoon", 2020, Rarity.RARE, mage.cards.s.SharkTyphoon.class, FULL_ART)); cards.add(new SetCardInfo("Shivan Dragon", 1993, Rarity.RARE, mage.cards.s.ShivanDragon.class)); cards.add(new SetCardInfo("Siege Rhino", 2014, Rarity.RARE, mage.cards.s.SiegeRhino.class)); cards.add(new SetCardInfo("Smokestack", 1998, Rarity.RARE, mage.cards.s.Smokestack.class)); diff --git a/Mage.Sets/src/mage/sets/SecretLairDrop.java b/Mage.Sets/src/mage/sets/SecretLairDrop.java index 2eccd5fbec1..3b9da5294b5 100644 --- a/Mage.Sets/src/mage/sets/SecretLairDrop.java +++ b/Mage.Sets/src/mage/sets/SecretLairDrop.java @@ -367,7 +367,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 362, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Forest", 363, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swords to Plowshares", 364, Rarity.RARE, mage.cards.s.SwordsToPlowshares.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Grim Tutor", 365, Rarity.MYTHIC, mage.cards.g.GrimTutor.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Grim Tutor", 365, Rarity.MYTHIC, mage.cards.g.GrimTutor.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Blood Moon", 366, Rarity.RARE, mage.cards.b.BloodMoon.class)); cards.add(new SetCardInfo("Cut // Ribbons", 367, Rarity.RARE, mage.cards.c.CutRibbons.class)); cards.add(new SetCardInfo("Teferi's Puzzle Box", 368, Rarity.RARE, mage.cards.t.TeferisPuzzleBox.class)); @@ -744,23 +744,23 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Mountain Goat", 737, Rarity.RARE, mage.cards.m.MountainGoat.class)); cards.add(new SetCardInfo("Woodland Cemetery", 738, Rarity.RARE, mage.cards.w.WoodlandCemetery.class)); cards.add(new SetCardInfo("Isolated Chapel", 739, Rarity.RARE, mage.cards.i.IsolatedChapel.class)); - cards.add(new SetCardInfo("Colossal Dreadmaw", 740, Rarity.RARE, mage.cards.c.ColossalDreadmaw.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Colossal Dreadmaw", "740*", Rarity.RARE, mage.cards.c.ColossalDreadmaw.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Colossal Dreadmaw", 740, Rarity.RARE, mage.cards.c.ColossalDreadmaw.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Colossal Dreadmaw", "740*", Rarity.RARE, mage.cards.c.ColossalDreadmaw.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Chaos Warp", 741, Rarity.RARE, mage.cards.c.ChaosWarp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Chaos Warp", "741*", Rarity.RARE, mage.cards.c.ChaosWarp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Command Tower", 744, Rarity.RARE, mage.cards.c.CommandTower.class, FULL_ART_USE_VARIOUS)); - cards.add(new SetCardInfo("Ajani Goldmane", 745, Rarity.MYTHIC, mage.cards.a.AjaniGoldmane.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ajani Goldmane", "745b", Rarity.MYTHIC, mage.cards.a.AjaniGoldmane.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Jace Beleren", 746, Rarity.MYTHIC, mage.cards.j.JaceBeleren.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Jace Beleren", "746b", Rarity.MYTHIC, mage.cards.j.JaceBeleren.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Liliana Vess", 747, Rarity.MYTHIC, mage.cards.l.LilianaVess.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Liliana Vess", "747b", Rarity.MYTHIC, mage.cards.l.LilianaVess.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Chandra Nalaar", 748, Rarity.MYTHIC, mage.cards.c.ChandraNalaar.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Chandra Nalaar", "748b", Rarity.MYTHIC, mage.cards.c.ChandraNalaar.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Garruk Wildspeaker", 749, Rarity.MYTHIC, mage.cards.g.GarrukWildspeaker.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Garruk Wildspeaker", "749b", Rarity.MYTHIC, mage.cards.g.GarrukWildspeaker.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Terror", 750, Rarity.RARE, mage.cards.t.Terror.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Terror", "750b", Rarity.RARE, mage.cards.t.Terror.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ajani Goldmane", 745, Rarity.MYTHIC, mage.cards.a.AjaniGoldmane.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Ajani Goldmane", "745b", Rarity.MYTHIC, mage.cards.a.AjaniGoldmane.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Jace Beleren", 746, Rarity.MYTHIC, mage.cards.j.JaceBeleren.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Jace Beleren", "746b", Rarity.MYTHIC, mage.cards.j.JaceBeleren.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Liliana Vess", 747, Rarity.MYTHIC, mage.cards.l.LilianaVess.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Liliana Vess", "747b", Rarity.MYTHIC, mage.cards.l.LilianaVess.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Chandra Nalaar", 748, Rarity.MYTHIC, mage.cards.c.ChandraNalaar.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Chandra Nalaar", "748b", Rarity.MYTHIC, mage.cards.c.ChandraNalaar.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Garruk Wildspeaker", 749, Rarity.MYTHIC, mage.cards.g.GarrukWildspeaker.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Garruk Wildspeaker", "749b", Rarity.MYTHIC, mage.cards.g.GarrukWildspeaker.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Terror", 750, Rarity.RARE, mage.cards.t.Terror.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Terror", "750b", Rarity.RARE, mage.cards.t.Terror.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Relentless Rats", 752, Rarity.RARE, mage.cards.r.RelentlessRats.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Relentless Rats", 754, Rarity.RARE, mage.cards.r.RelentlessRats.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Relentless Rats", 755, Rarity.RARE, mage.cards.r.RelentlessRats.class, NON_FULL_USE_VARIOUS)); @@ -801,10 +801,10 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Wastes", "795*", Rarity.RARE, mage.cards.w.Wastes.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Mana Vault", "796*", Rarity.MYTHIC, mage.cards.m.ManaVault.class)); cards.add(new SetCardInfo("Seraph Sanctuary", 797, Rarity.RARE, mage.cards.s.SeraphSanctuary.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Coveted Jewel", 799, Rarity.RARE, mage.cards.c.CovetedJewel.class)); + cards.add(new SetCardInfo("Coveted Jewel", 799, Rarity.RARE, mage.cards.c.CovetedJewel.class, FULL_ART)); cards.add(new SetCardInfo("Llanowar Elves", 800, Rarity.RARE, mage.cards.l.LlanowarElves.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Spiteful Prankster", 801, Rarity.RARE, mage.cards.s.SpitefulPrankster.class)); - cards.add(new SetCardInfo("Haystack", 802, Rarity.RARE, mage.cards.h.Haystack.class)); + cards.add(new SetCardInfo("Haystack", 802, Rarity.RARE, mage.cards.h.Haystack.class, FULL_ART)); cards.add(new SetCardInfo("Sonic Screwdriver", 803, Rarity.RARE, mage.cards.s.SonicScrewdriver.class)); cards.add(new SetCardInfo("Beloved Princess", 804, Rarity.RARE, mage.cards.b.BelovedPrincess.class)); cards.add(new SetCardInfo("Elvish Mystic", 805, Rarity.RARE, mage.cards.e.ElvishMystic.class, NON_FULL_USE_VARIOUS)); @@ -878,10 +878,10 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Minsc & Boo, Timeless Heroes", 879, Rarity.MYTHIC, mage.cards.m.MinscBooTimelessHeroes.class)); cards.add(new SetCardInfo("Stuffy Doll", 880, Rarity.RARE, mage.cards.s.StuffyDoll.class)); cards.add(new SetCardInfo("Silence", 881, Rarity.RARE, mage.cards.s.Silence.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Winds of Abandon", 882, Rarity.RARE, mage.cards.w.WindsOfAbandon.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Culling the Weak", 883, Rarity.RARE, mage.cards.c.CullingTheWeak.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Fatal Push", 884, Rarity.RARE, mage.cards.f.FatalPush.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Young Wolf", 885, Rarity.RARE, mage.cards.y.YoungWolf.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Winds of Abandon", 882, Rarity.RARE, mage.cards.w.WindsOfAbandon.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Culling the Weak", 883, Rarity.RARE, mage.cards.c.CullingTheWeak.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Fatal Push", 884, Rarity.RARE, mage.cards.f.FatalPush.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Young Wolf", 885, Rarity.RARE, mage.cards.y.YoungWolf.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Solve the Equation", 886, Rarity.RARE, mage.cards.s.SolveTheEquation.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Enduring Ideal", 887, Rarity.RARE, mage.cards.e.EnduringIdeal.class)); cards.add(new SetCardInfo("Plains", 888, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); @@ -895,7 +895,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("The Scarab God", 900, Rarity.MYTHIC, mage.cards.t.TheScarabGod.class, FULL_ART)); cards.add(new SetCardInfo("Lightning Bolt", 901, Rarity.RARE, mage.cards.l.LightningBolt.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Deadeye Navigator", 902, Rarity.RARE, mage.cards.d.DeadeyeNavigator.class)); - cards.add(new SetCardInfo("The Locust God", 903, Rarity.MYTHIC, mage.cards.t.TheLocustGod.class)); + cards.add(new SetCardInfo("The Locust God", 903, Rarity.MYTHIC, mage.cards.t.TheLocustGod.class, FULL_ART)); cards.add(new SetCardInfo("The Scorpion God", 904, Rarity.MYTHIC, mage.cards.t.TheScorpionGod.class)); cards.add(new SetCardInfo("Cryptic Command", 905, Rarity.RARE, mage.cards.c.CrypticCommand.class, FULL_ART)); cards.add(new SetCardInfo("Ignoble Hierarch", 906, Rarity.RARE, mage.cards.i.IgnobleHierarch.class, FULL_ART)); @@ -1025,12 +1025,12 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Doomsday", 1115, Rarity.RARE, mage.cards.d.Doomsday.class)); cards.add(new SetCardInfo("Plaguecrafter", 1116, Rarity.RARE, mage.cards.p.Plaguecrafter.class)); cards.add(new SetCardInfo("Thoughtseize", 1117, Rarity.RARE, mage.cards.t.Thoughtseize.class)); - cards.add(new SetCardInfo("Ulamog, the Ceaseless Hunger", 1122, Rarity.MYTHIC, mage.cards.u.UlamogTheCeaselessHunger.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ulamog, the Ceaseless Hunger", "1122b", Rarity.MYTHIC, mage.cards.u.UlamogTheCeaselessHunger.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Etali, Primal Storm", 1123, Rarity.RARE, mage.cards.e.EtaliPrimalStorm.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Etali, Primal Storm", "1123b", Rarity.RARE, mage.cards.e.EtaliPrimalStorm.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ghalta, Primal Hunger", 1124, Rarity.RARE, mage.cards.g.GhaltaPrimalHunger.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ghalta, Primal Hunger", "1124b", Rarity.RARE, mage.cards.g.GhaltaPrimalHunger.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ulamog, the Ceaseless Hunger", 1122, Rarity.MYTHIC, mage.cards.u.UlamogTheCeaselessHunger.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Ulamog, the Ceaseless Hunger", "1122b", Rarity.MYTHIC, mage.cards.u.UlamogTheCeaselessHunger.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Etali, Primal Storm", 1123, Rarity.RARE, mage.cards.e.EtaliPrimalStorm.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Etali, Primal Storm", "1123b", Rarity.RARE, mage.cards.e.EtaliPrimalStorm.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Ghalta, Primal Hunger", 1124, Rarity.RARE, mage.cards.g.GhaltaPrimalHunger.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Ghalta, Primal Hunger", "1124b", Rarity.RARE, mage.cards.g.GhaltaPrimalHunger.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Serra Ascendant", 1125, Rarity.RARE, mage.cards.s.SerraAscendant.class)); cards.add(new SetCardInfo("Rapid Hybridization", 1126, Rarity.RARE, mage.cards.r.RapidHybridization.class)); cards.add(new SetCardInfo("Demonic Consultation", 1127, Rarity.RARE, mage.cards.d.DemonicConsultation.class)); @@ -1221,16 +1221,16 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Shared Summons", 1308, Rarity.RARE, mage.cards.s.SharedSummons.class)); cards.add(new SetCardInfo("Sylvan Offering", 1309, Rarity.RARE, mage.cards.s.SylvanOffering.class)); cards.add(new SetCardInfo("Sliver Legion", 1310, Rarity.MYTHIC, mage.cards.s.SliverLegion.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Goblin Lackey", 1311, Rarity.RARE, mage.cards.g.GoblinLackey.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Goblin Lackey", "1311*", Rarity.RARE, mage.cards.g.GoblinLackey.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Goblin Matron", 1312, Rarity.RARE, mage.cards.g.GoblinMatron.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Goblin Matron", "1312*", Rarity.RARE, mage.cards.g.GoblinMatron.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Goblin Recruiter", 1313, Rarity.RARE, mage.cards.g.GoblinRecruiter.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Goblin Recruiter", "1313*", Rarity.RARE, mage.cards.g.GoblinRecruiter.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Muxus, Goblin Grandee", 1314, Rarity.RARE, mage.cards.m.MuxusGoblinGrandee.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Muxus, Goblin Grandee", "1314*", Rarity.RARE, mage.cards.m.MuxusGoblinGrandee.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Shattergang Brothers", 1315, Rarity.MYTHIC, mage.cards.s.ShattergangBrothers.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Shattergang Brothers", "1315*", Rarity.MYTHIC, mage.cards.s.ShattergangBrothers.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Goblin Lackey", 1311, Rarity.RARE, mage.cards.g.GoblinLackey.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Goblin Lackey", "1311*", Rarity.RARE, mage.cards.g.GoblinLackey.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Goblin Matron", 1312, Rarity.RARE, mage.cards.g.GoblinMatron.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Goblin Matron", "1312*", Rarity.RARE, mage.cards.g.GoblinMatron.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Goblin Recruiter", 1313, Rarity.RARE, mage.cards.g.GoblinRecruiter.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Goblin Recruiter", "1313*", Rarity.RARE, mage.cards.g.GoblinRecruiter.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Muxus, Goblin Grandee", 1314, Rarity.RARE, mage.cards.m.MuxusGoblinGrandee.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Muxus, Goblin Grandee", "1314*", Rarity.RARE, mage.cards.m.MuxusGoblinGrandee.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Shattergang Brothers", 1315, Rarity.MYTHIC, mage.cards.s.ShattergangBrothers.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Shattergang Brothers", "1315*", Rarity.MYTHIC, mage.cards.s.ShattergangBrothers.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Nirkana Revenant", 1316, Rarity.MYTHIC, mage.cards.n.NirkanaRevenant.class)); cards.add(new SetCardInfo("Arbor Elf", 1317, Rarity.RARE, mage.cards.a.ArborElf.class)); cards.add(new SetCardInfo("Terastodon", 1318, Rarity.RARE, mage.cards.t.Terastodon.class)); @@ -1248,11 +1248,11 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Estrid, the Masked", "1327b", Rarity.MYTHIC, mage.cards.e.EstridTheMasked.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Tuvasa the Sunlit", 1328, Rarity.MYTHIC, mage.cards.t.TuvasaTheSunlit.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Tuvasa the Sunlit", "1328b", Rarity.MYTHIC, mage.cards.t.TuvasaTheSunlit.class, FULL_ART_USE_VARIOUS)); - cards.add(new SetCardInfo("Gargos, Vicious Watcher", 1329, Rarity.RARE, mage.cards.g.GargosViciousWatcher.class)); - cards.add(new SetCardInfo("Primordial Hydra", 1330, Rarity.MYTHIC, mage.cards.p.PrimordialHydra.class)); - cards.add(new SetCardInfo("Unbound Flourishing", 1331, Rarity.MYTHIC, mage.cards.u.UnboundFlourishing.class)); - cards.add(new SetCardInfo("Hydroid Krasis", 1332, Rarity.RARE, mage.cards.h.HydroidKrasis.class)); - cards.add(new SetCardInfo("Zaxara, the Exemplary", 1333, Rarity.MYTHIC, mage.cards.z.ZaxaraTheExemplary.class)); + cards.add(new SetCardInfo("Gargos, Vicious Watcher", 1329, Rarity.RARE, mage.cards.g.GargosViciousWatcher.class, FULL_ART)); + cards.add(new SetCardInfo("Primordial Hydra", 1330, Rarity.MYTHIC, mage.cards.p.PrimordialHydra.class, FULL_ART)); + cards.add(new SetCardInfo("Unbound Flourishing", 1331, Rarity.MYTHIC, mage.cards.u.UnboundFlourishing.class, FULL_ART)); + cards.add(new SetCardInfo("Hydroid Krasis", 1332, Rarity.RARE, mage.cards.h.HydroidKrasis.class, FULL_ART)); + cards.add(new SetCardInfo("Zaxara, the Exemplary", 1333, Rarity.MYTHIC, mage.cards.z.ZaxaraTheExemplary.class, FULL_ART)); cards.add(new SetCardInfo("Gisela, the Broken Blade", 1335, Rarity.MYTHIC, mage.cards.g.GiselaTheBrokenBlade.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Brisela, Voice of Nightmares", "1336b", Rarity.MYTHIC, mage.cards.b.BriselaVoiceOfNightmares.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bruna, the Fading Light", 1336, Rarity.RARE, mage.cards.b.BrunaTheFadingLight.class, NON_FULL_USE_VARIOUS)); @@ -1284,10 +1284,10 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 1365, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 1366, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 1367, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Rewind", 1368, Rarity.RARE, mage.cards.r.Rewind.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Food Chain", 1369, Rarity.MYTHIC, mage.cards.f.FoodChain.class)); - cards.add(new SetCardInfo("Rampant Growth", 1370, Rarity.RARE, mage.cards.r.RampantGrowth.class)); - cards.add(new SetCardInfo("The First Sliver", 1371, Rarity.MYTHIC, mage.cards.t.TheFirstSliver.class)); + cards.add(new SetCardInfo("Rewind", 1368, Rarity.RARE, mage.cards.r.Rewind.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Food Chain", 1369, Rarity.MYTHIC, mage.cards.f.FoodChain.class, FULL_ART)); + cards.add(new SetCardInfo("Rampant Growth", 1370, Rarity.RARE, mage.cards.r.RampantGrowth.class, FULL_ART)); + cards.add(new SetCardInfo("The First Sliver", 1371, Rarity.MYTHIC, mage.cards.t.TheFirstSliver.class, FULL_ART)); cards.add(new SetCardInfo("Concealed Courtyard", 1372, Rarity.RARE, mage.cards.c.ConcealedCourtyard.class)); cards.add(new SetCardInfo("Spirebluff Canal", 1373, Rarity.RARE, mage.cards.s.SpirebluffCanal.class)); cards.add(new SetCardInfo("Blooming Marsh", 1374, Rarity.RARE, mage.cards.b.BloomingMarsh.class)); @@ -1306,16 +1306,16 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Gisela, the Broken Blade", 1387, Rarity.MYTHIC, mage.cards.g.GiselaTheBrokenBlade.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Brisela, Voice of Nightmares", "1388b", Rarity.MYTHIC, mage.cards.b.BriselaVoiceOfNightmares.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bruna, the Fading Light", 1388, Rarity.RARE, mage.cards.b.BrunaTheFadingLight.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Etali, Primal Storm", 1389, Rarity.RARE, mage.cards.e.EtaliPrimalStorm.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Etali, Primal Storm", "1389*", Rarity.RARE, mage.cards.e.EtaliPrimalStorm.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Rampaging Ferocidon", 1390, Rarity.RARE, mage.cards.r.RampagingFerocidon.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Rampaging Ferocidon", "1390*", Rarity.RARE, mage.cards.r.RampagingFerocidon.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Polyraptor", 1391, Rarity.MYTHIC, mage.cards.p.Polyraptor.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Polyraptor", "1391*", Rarity.MYTHIC, mage.cards.p.Polyraptor.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Wayward Swordtooth", 1392, Rarity.RARE, mage.cards.w.WaywardSwordtooth.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Wayward Swordtooth", "1392*", Rarity.RARE, mage.cards.w.WaywardSwordtooth.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Regisaur Alpha", 1393, Rarity.RARE, mage.cards.r.RegisaurAlpha.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Regisaur Alpha", "1393*", Rarity.RARE, mage.cards.r.RegisaurAlpha.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Etali, Primal Storm", 1389, Rarity.RARE, mage.cards.e.EtaliPrimalStorm.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Etali, Primal Storm", "1389*", Rarity.RARE, mage.cards.e.EtaliPrimalStorm.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Rampaging Ferocidon", 1390, Rarity.RARE, mage.cards.r.RampagingFerocidon.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Rampaging Ferocidon", "1390*", Rarity.RARE, mage.cards.r.RampagingFerocidon.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Polyraptor", 1391, Rarity.MYTHIC, mage.cards.p.Polyraptor.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Polyraptor", "1391*", Rarity.MYTHIC, mage.cards.p.Polyraptor.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Wayward Swordtooth", 1392, Rarity.RARE, mage.cards.w.WaywardSwordtooth.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Wayward Swordtooth", "1392*", Rarity.RARE, mage.cards.w.WaywardSwordtooth.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Regisaur Alpha", 1393, Rarity.RARE, mage.cards.r.RegisaurAlpha.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Regisaur Alpha", "1393*", Rarity.RARE, mage.cards.r.RegisaurAlpha.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Laboratory Maniac", 1394, Rarity.RARE, mage.cards.l.LaboratoryManiac.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Laboratory Maniac", "1394*", Rarity.RARE, mage.cards.l.LaboratoryManiac.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tasha's Hideous Laughter", 1395, Rarity.RARE, mage.cards.t.TashasHideousLaughter.class, NON_FULL_USE_VARIOUS)); @@ -1344,11 +1344,11 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Kumena, Tyrant of Orazca", "1412*", Rarity.MYTHIC, mage.cards.k.KumenaTyrantOfOrazca.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Vona, Butcher of Magan", 1413, Rarity.MYTHIC, mage.cards.v.VonaButcherOfMagan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Vona, Butcher of Magan", "1413*", Rarity.MYTHIC, mage.cards.v.VonaButcherOfMagan.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Eldritch Evolution", 1414, Rarity.RARE, mage.cards.e.EldritchEvolution.class)); - cards.add(new SetCardInfo("Giant Adephage", 1415, Rarity.MYTHIC, mage.cards.g.GiantAdephage.class)); - cards.add(new SetCardInfo("Noxious Revival", 1416, Rarity.RARE, mage.cards.n.NoxiousRevival.class)); - cards.add(new SetCardInfo("Grist, the Hunger Tide", 1417, Rarity.MYTHIC, mage.cards.g.GristTheHungerTide.class)); - cards.add(new SetCardInfo("Mazirek, Kraul Death Priest", 1418, Rarity.RARE, mage.cards.m.MazirekKraulDeathPriest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Eldritch Evolution", 1414, Rarity.RARE, mage.cards.e.EldritchEvolution.class, FULL_ART)); + cards.add(new SetCardInfo("Giant Adephage", 1415, Rarity.MYTHIC, mage.cards.g.GiantAdephage.class, FULL_ART)); + cards.add(new SetCardInfo("Noxious Revival", 1416, Rarity.RARE, mage.cards.n.NoxiousRevival.class, FULL_ART)); + cards.add(new SetCardInfo("Grist, the Hunger Tide", 1417, Rarity.MYTHIC, mage.cards.g.GristTheHungerTide.class, FULL_ART)); + cards.add(new SetCardInfo("Mazirek, Kraul Death Priest", 1418, Rarity.RARE, mage.cards.m.MazirekKraulDeathPriest.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Karn, Scion of Urza", 1419, Rarity.MYTHIC, mage.cards.k.KarnScionOfUrza.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Karn, Scion of Urza", "1419*", Rarity.MYTHIC, mage.cards.k.KarnScionOfUrza.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Chandra, Flame's Catalyst", 1420, Rarity.MYTHIC, mage.cards.c.ChandraFlamesCatalyst.class, NON_FULL_USE_VARIOUS)); @@ -1382,26 +1382,26 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Brion Stoutarm", 1450, Rarity.RARE, mage.cards.b.BrionStoutarm.class)); cards.add(new SetCardInfo("Samut, Voice of Dissent", 1451, Rarity.MYTHIC, mage.cards.s.SamutVoiceOfDissent.class)); cards.add(new SetCardInfo("Marchesa, the Black Rose", 1452, Rarity.RARE, mage.cards.m.MarchesaTheBlackRose.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ajani Goldmane", 1453, Rarity.MYTHIC, mage.cards.a.AjaniGoldmane.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ajani Goldmane", "1453b", Rarity.MYTHIC, mage.cards.a.AjaniGoldmane.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Jace Beleren", 1454, Rarity.MYTHIC, mage.cards.j.JaceBeleren.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Jace Beleren", "1454b", Rarity.MYTHIC, mage.cards.j.JaceBeleren.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Liliana Vess", 1455, Rarity.MYTHIC, mage.cards.l.LilianaVess.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Liliana Vess", "1455b", Rarity.MYTHIC, mage.cards.l.LilianaVess.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Chandra Nalaar", 1456, Rarity.MYTHIC, mage.cards.c.ChandraNalaar.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Chandra Nalaar", "1456b", Rarity.MYTHIC, mage.cards.c.ChandraNalaar.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Garruk Wildspeaker", 1457, Rarity.MYTHIC, mage.cards.g.GarrukWildspeaker.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Garruk Wildspeaker", "1457b", Rarity.MYTHIC, mage.cards.g.GarrukWildspeaker.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Death Baron", 1458, Rarity.RARE, mage.cards.d.DeathBaron.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Death Baron", "1458b", Rarity.RARE, mage.cards.d.DeathBaron.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Noxious Ghoul", 1459, Rarity.RARE, mage.cards.n.NoxiousGhoul.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Noxious Ghoul", "1459b", Rarity.RARE, mage.cards.n.NoxiousGhoul.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Zombie Master", 1460, Rarity.RARE, mage.cards.z.ZombieMaster.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Zombie Master", "1460b", Rarity.RARE, mage.cards.z.ZombieMaster.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Grimgrin, Corpse-Born", 1461, Rarity.MYTHIC, mage.cards.g.GrimgrinCorpseBorn.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Grimgrin, Corpse-Born", "1461b", Rarity.MYTHIC, mage.cards.g.GrimgrinCorpseBorn.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Unholy Grotto", 1462, Rarity.RARE, mage.cards.u.UnholyGrotto.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Unholy Grotto", "1462b", Rarity.RARE, mage.cards.u.UnholyGrotto.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ajani Goldmane", 1453, Rarity.MYTHIC, mage.cards.a.AjaniGoldmane.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Ajani Goldmane", "1453b", Rarity.MYTHIC, mage.cards.a.AjaniGoldmane.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Jace Beleren", 1454, Rarity.MYTHIC, mage.cards.j.JaceBeleren.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Jace Beleren", "1454b", Rarity.MYTHIC, mage.cards.j.JaceBeleren.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Liliana Vess", 1455, Rarity.MYTHIC, mage.cards.l.LilianaVess.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Liliana Vess", "1455b", Rarity.MYTHIC, mage.cards.l.LilianaVess.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Chandra Nalaar", 1456, Rarity.MYTHIC, mage.cards.c.ChandraNalaar.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Chandra Nalaar", "1456b", Rarity.MYTHIC, mage.cards.c.ChandraNalaar.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Garruk Wildspeaker", 1457, Rarity.MYTHIC, mage.cards.g.GarrukWildspeaker.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Garruk Wildspeaker", "1457b", Rarity.MYTHIC, mage.cards.g.GarrukWildspeaker.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Death Baron", 1458, Rarity.RARE, mage.cards.d.DeathBaron.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Death Baron", "1458b", Rarity.RARE, mage.cards.d.DeathBaron.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Noxious Ghoul", 1459, Rarity.RARE, mage.cards.n.NoxiousGhoul.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Noxious Ghoul", "1459b", Rarity.RARE, mage.cards.n.NoxiousGhoul.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Zombie Master", 1460, Rarity.RARE, mage.cards.z.ZombieMaster.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Zombie Master", "1460b", Rarity.RARE, mage.cards.z.ZombieMaster.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Grimgrin, Corpse-Born", 1461, Rarity.MYTHIC, mage.cards.g.GrimgrinCorpseBorn.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Grimgrin, Corpse-Born", "1461b", Rarity.MYTHIC, mage.cards.g.GrimgrinCorpseBorn.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Unholy Grotto", 1462, Rarity.RARE, mage.cards.u.UnholyGrotto.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Unholy Grotto", "1462b", Rarity.RARE, mage.cards.u.UnholyGrotto.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Giver of Runes", 1463, Rarity.RARE, mage.cards.g.GiverOfRunes.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Giver of Runes", "1463*", Rarity.RARE, mage.cards.g.GiverOfRunes.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Distant Melody", 1464, Rarity.RARE, mage.cards.d.DistantMelody.class, NON_FULL_USE_VARIOUS)); @@ -1460,14 +1460,14 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Thought Vessel", "1495*", Rarity.RARE, mage.cards.t.ThoughtVessel.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Command Tower", 1496, Rarity.RARE, mage.cards.c.CommandTower.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Command Tower", "1496*", Rarity.RARE, mage.cards.c.CommandTower.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Beacon of Tomorrows", 1497, Rarity.RARE, mage.cards.b.BeaconOfTomorrows.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Beacon of Tomorrows", "1497*", Rarity.RARE, mage.cards.b.BeaconOfTomorrows.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Nexus of Fate", 1498, Rarity.MYTHIC, mage.cards.n.NexusOfFate.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Nexus of Fate", "1498*", Rarity.MYTHIC, mage.cards.n.NexusOfFate.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Time Reversal", 1499, Rarity.MYTHIC, mage.cards.t.TimeReversal.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Time Reversal", "1499*", Rarity.MYTHIC, mage.cards.t.TimeReversal.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Time Stop", 1500, Rarity.RARE, mage.cards.t.TimeStop.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Time Stop", "1500*", Rarity.RARE, mage.cards.t.TimeStop.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Beacon of Tomorrows", 1497, Rarity.RARE, mage.cards.b.BeaconOfTomorrows.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Beacon of Tomorrows", "1497*", Rarity.RARE, mage.cards.b.BeaconOfTomorrows.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Nexus of Fate", 1498, Rarity.MYTHIC, mage.cards.n.NexusOfFate.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Nexus of Fate", "1498*", Rarity.MYTHIC, mage.cards.n.NexusOfFate.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Time Reversal", 1499, Rarity.MYTHIC, mage.cards.t.TimeReversal.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Time Reversal", "1499*", Rarity.MYTHIC, mage.cards.t.TimeReversal.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Time Stop", 1500, Rarity.RARE, mage.cards.t.TimeStop.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Time Stop", "1500*", Rarity.RARE, mage.cards.t.TimeStop.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Lara Croft, Tomb Raider", 1501, Rarity.MYTHIC, mage.cards.l.LaraCroftTombRaider.class)); cards.add(new SetCardInfo("Search for Azcanta", 1502, Rarity.RARE, mage.cards.s.SearchForAzcanta.class)); cards.add(new SetCardInfo("Azcanta, the Sunken Ruin", 1502, Rarity.RARE, mage.cards.a.AzcantaTheSunkenRuin.class)); @@ -1488,16 +1488,16 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Plains", 1513, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Mountain", 1514, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Forest", 1515, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); - cards.add(new SetCardInfo("Wall of Omens", 1518, Rarity.RARE, mage.cards.w.WallOfOmens.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Wall of Omens", "1518*", Rarity.RARE, mage.cards.w.WallOfOmens.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Circular Logic", 1519, Rarity.RARE, mage.cards.c.CircularLogic.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Circular Logic", "1519*", Rarity.RARE, mage.cards.c.CircularLogic.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Scheming Symmetry", 1520, Rarity.RARE, mage.cards.s.SchemingSymmetry.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Scheming Symmetry", "1520*", Rarity.RARE, mage.cards.s.SchemingSymmetry.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Price of Progress", 1521, Rarity.RARE, mage.cards.p.PriceOfProgress.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Price of Progress", "1521*", Rarity.RARE, mage.cards.p.PriceOfProgress.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Eternal Witness", 1522, Rarity.RARE, mage.cards.e.EternalWitness.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Eternal Witness", "1522*", Rarity.RARE, mage.cards.e.EternalWitness.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Wall of Omens", 1518, Rarity.RARE, mage.cards.w.WallOfOmens.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Wall of Omens", "1518*", Rarity.RARE, mage.cards.w.WallOfOmens.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Circular Logic", 1519, Rarity.RARE, mage.cards.c.CircularLogic.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Circular Logic", "1519*", Rarity.RARE, mage.cards.c.CircularLogic.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Scheming Symmetry", 1520, Rarity.RARE, mage.cards.s.SchemingSymmetry.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Scheming Symmetry", "1520*", Rarity.RARE, mage.cards.s.SchemingSymmetry.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Price of Progress", 1521, Rarity.RARE, mage.cards.p.PriceOfProgress.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Price of Progress", "1521*", Rarity.RARE, mage.cards.p.PriceOfProgress.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Eternal Witness", 1522, Rarity.RARE, mage.cards.e.EternalWitness.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Eternal Witness", "1522*", Rarity.RARE, mage.cards.e.EternalWitness.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Inspiring Overseer", 1523, Rarity.RARE, mage.cards.i.InspiringOverseer.class)); cards.add(new SetCardInfo("Consider", 1524, Rarity.RARE, mage.cards.c.Consider.class)); cards.add(new SetCardInfo("Price of Glory", 1525, Rarity.RARE, mage.cards.p.PriceOfGlory.class)); @@ -1517,14 +1517,14 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Reflecting Pool", "1535*", Rarity.RARE, mage.cards.r.ReflectingPool.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Reliquary Tower", 1536, Rarity.RARE, mage.cards.r.ReliquaryTower.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Reliquary Tower", "1536*", Rarity.RARE, mage.cards.r.ReliquaryTower.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Sakashima of a Thousand Faces", 1541, Rarity.MYTHIC, mage.cards.s.SakashimaOfAThousandFaces.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Sakashima of a Thousand Faces", "1541b", Rarity.MYTHIC, mage.cards.s.SakashimaOfAThousandFaces.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Yargle, Glutton of Urborg", 1542, Rarity.RARE, mage.cards.y.YargleGluttonOfUrborg.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Yargle, Glutton of Urborg", "1542b", Rarity.RARE, mage.cards.y.YargleGluttonOfUrborg.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Krark, the Thumbless", 1543, Rarity.RARE, mage.cards.k.KrarkTheThumbless.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Krark, the Thumbless", "1543b", Rarity.RARE, mage.cards.k.KrarkTheThumbless.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Adrix and Nev, Twincasters", 1544, Rarity.MYTHIC, mage.cards.a.AdrixAndNevTwincasters.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Adrix and Nev, Twincasters", "1544b", Rarity.MYTHIC, mage.cards.a.AdrixAndNevTwincasters.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sakashima of a Thousand Faces", 1541, Rarity.MYTHIC, mage.cards.s.SakashimaOfAThousandFaces.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Sakashima of a Thousand Faces", "1541b", Rarity.MYTHIC, mage.cards.s.SakashimaOfAThousandFaces.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Yargle, Glutton of Urborg", 1542, Rarity.RARE, mage.cards.y.YargleGluttonOfUrborg.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Yargle, Glutton of Urborg", "1542b", Rarity.RARE, mage.cards.y.YargleGluttonOfUrborg.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Krark, the Thumbless", 1543, Rarity.RARE, mage.cards.k.KrarkTheThumbless.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Krark, the Thumbless", "1543b", Rarity.RARE, mage.cards.k.KrarkTheThumbless.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Adrix and Nev, Twincasters", 1544, Rarity.MYTHIC, mage.cards.a.AdrixAndNevTwincasters.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Adrix and Nev, Twincasters", "1544b", Rarity.MYTHIC, mage.cards.a.AdrixAndNevTwincasters.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Arcane Denial", 1545, Rarity.RARE, mage.cards.a.ArcaneDenial.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Arcane Denial", "1545*", Rarity.RARE, mage.cards.a.ArcaneDenial.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Nightscape Familiar", 1546, Rarity.RARE, mage.cards.n.NightscapeFamiliar.class, NON_FULL_USE_VARIOUS)); @@ -1562,21 +1562,21 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Anowon, the Ruin Thief", "1568*", Rarity.MYTHIC, mage.cards.a.AnowonTheRuinThief.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Grenzo, Dungeon Warden", 1569, Rarity.RARE, mage.cards.g.GrenzoDungeonWarden.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Grenzo, Dungeon Warden", "1569*", Rarity.RARE, mage.cards.g.GrenzoDungeonWarden.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Blade of Selves", 1570, Rarity.RARE, mage.cards.b.BladeOfSelves.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Conqueror's Flail", 1571, Rarity.RARE, mage.cards.c.ConquerorsFlail.class)); - cards.add(new SetCardInfo("Darksteel Plate", 1572, Rarity.RARE, mage.cards.d.DarksteelPlate.class)); - cards.add(new SetCardInfo("Deathrender", 1573, Rarity.RARE, mage.cards.d.Deathrender.class)); - cards.add(new SetCardInfo("Whispersilk Cloak", 1574, Rarity.RARE, mage.cards.w.WhispersilkCloak.class)); - cards.add(new SetCardInfo("Reconnaissance", 1575, Rarity.RARE, mage.cards.r.Reconnaissance.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Reconnaissance", "1575*", Rarity.RARE, mage.cards.r.Reconnaissance.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Jace, Wielder of Mysteries", 1576, Rarity.RARE, mage.cards.j.JaceWielderOfMysteries.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Jace, Wielder of Mysteries", "1576*", Rarity.RARE, mage.cards.j.JaceWielderOfMysteries.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Black Market", 1577, Rarity.RARE, mage.cards.b.BlackMarket.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Black Market", "1577*", Rarity.RARE, mage.cards.b.BlackMarket.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Dire Undercurrents", 1578, Rarity.RARE, mage.cards.d.DireUndercurrents.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Dire Undercurrents", "1578*", Rarity.RARE, mage.cards.d.DireUndercurrents.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Obeka, Brute Chronologist", 1579, Rarity.MYTHIC, mage.cards.o.ObekaBruteChronologist.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Obeka, Brute Chronologist", "1579*", Rarity.MYTHIC, mage.cards.o.ObekaBruteChronologist.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Blade of Selves", 1570, Rarity.RARE, mage.cards.b.BladeOfSelves.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Conqueror's Flail", 1571, Rarity.RARE, mage.cards.c.ConquerorsFlail.class, FULL_ART)); + cards.add(new SetCardInfo("Darksteel Plate", 1572, Rarity.RARE, mage.cards.d.DarksteelPlate.class, FULL_ART)); + cards.add(new SetCardInfo("Deathrender", 1573, Rarity.RARE, mage.cards.d.Deathrender.class, FULL_ART)); + cards.add(new SetCardInfo("Whispersilk Cloak", 1574, Rarity.RARE, mage.cards.w.WhispersilkCloak.class, FULL_ART)); + cards.add(new SetCardInfo("Reconnaissance", 1575, Rarity.RARE, mage.cards.r.Reconnaissance.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Reconnaissance", "1575*", Rarity.RARE, mage.cards.r.Reconnaissance.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Jace, Wielder of Mysteries", 1576, Rarity.RARE, mage.cards.j.JaceWielderOfMysteries.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Jace, Wielder of Mysteries", "1576*", Rarity.RARE, mage.cards.j.JaceWielderOfMysteries.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Black Market", 1577, Rarity.RARE, mage.cards.b.BlackMarket.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Black Market", "1577*", Rarity.RARE, mage.cards.b.BlackMarket.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Dire Undercurrents", 1578, Rarity.RARE, mage.cards.d.DireUndercurrents.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Dire Undercurrents", "1578*", Rarity.RARE, mage.cards.d.DireUndercurrents.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Obeka, Brute Chronologist", 1579, Rarity.MYTHIC, mage.cards.o.ObekaBruteChronologist.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Obeka, Brute Chronologist", "1579*", Rarity.MYTHIC, mage.cards.o.ObekaBruteChronologist.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Rose Noble", 1580, Rarity.RARE, mage.cards.r.RoseNoble.class)); cards.add(new SetCardInfo("The Meep", 1581, Rarity.RARE, mage.cards.t.TheMeep.class)); // cards.add(new SetCardInfo("The Celestial Toymaker", 1582, Rarity.RARE, mage.cards.t.TheCelestialToymaker.class)); @@ -1655,14 +1655,14 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Anger", "1637*", Rarity.RARE, mage.cards.a.Anger.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Lightning Bolt", 1638, Rarity.RARE, mage.cards.l.LightningBolt.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Lightning Bolt", "1638*", Rarity.RARE, mage.cards.l.LightningBolt.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Inalla, Archmage Ritualist", 1639, Rarity.MYTHIC, mage.cards.i.InallaArchmageRitualist.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Inalla, Archmage Ritualist", "1639*", Rarity.MYTHIC, mage.cards.i.InallaArchmageRitualist.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Aether Vial", 1640, Rarity.RARE, mage.cards.a.AetherVial.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Aether Vial", "1640*", Rarity.RARE, mage.cards.a.AetherVial.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Arcane Signet", 1641, Rarity.RARE, mage.cards.a.ArcaneSignet.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Arcane Signet", "1641*", Rarity.RARE, mage.cards.a.ArcaneSignet.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Sword of the Animist", 1642, Rarity.RARE, mage.cards.s.SwordOfTheAnimist.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Sword of the Animist", "1642*", Rarity.RARE, mage.cards.s.SwordOfTheAnimist.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Inalla, Archmage Ritualist", 1639, Rarity.MYTHIC, mage.cards.i.InallaArchmageRitualist.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Inalla, Archmage Ritualist", "1639*", Rarity.MYTHIC, mage.cards.i.InallaArchmageRitualist.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Aether Vial", 1640, Rarity.RARE, mage.cards.a.AetherVial.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Aether Vial", "1640*", Rarity.RARE, mage.cards.a.AetherVial.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Arcane Signet", 1641, Rarity.RARE, mage.cards.a.ArcaneSignet.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Arcane Signet", "1641*", Rarity.RARE, mage.cards.a.ArcaneSignet.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Sword of the Animist", 1642, Rarity.RARE, mage.cards.s.SwordOfTheAnimist.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Sword of the Animist", "1642*", Rarity.RARE, mage.cards.s.SwordOfTheAnimist.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Gravebreaker Lamia", 1643, Rarity.RARE, mage.cards.g.GravebreakerLamia.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Gravebreaker Lamia", "1643*", Rarity.RARE, mage.cards.g.GravebreakerLamia.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aura Shards", 1644, Rarity.RARE, mage.cards.a.AuraShards.class, NON_FULL_USE_VARIOUS)); @@ -1671,16 +1671,16 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Fiend Artisan", "1645*", Rarity.MYTHIC, mage.cards.f.FiendArtisan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Karador, Ghost Chieftain", 1646, Rarity.MYTHIC, mage.cards.k.KaradorGhostChieftain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Karador, Ghost Chieftain", "1646*", Rarity.MYTHIC, mage.cards.k.KaradorGhostChieftain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 1647, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 1648, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 1649, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 1650, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 1651, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 1652, Rarity.LAND, mage.cards.basiclands.Plains.class, RETRO_ART_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 1653, Rarity.LAND, mage.cards.basiclands.Island.class, RETRO_ART_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 1654, Rarity.LAND, mage.cards.basiclands.Swamp.class, RETRO_ART_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 1655, Rarity.LAND, mage.cards.basiclands.Mountain.class, RETRO_ART_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 1656, Rarity.LAND, mage.cards.basiclands.Forest.class, RETRO_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 1647, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Island", 1648, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 1649, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 1650, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Forest", 1651, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Plains", 1652, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Island", 1653, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 1654, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 1655, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Forest", 1656, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Consecrated Sphinx", 1657, Rarity.MYTHIC, mage.cards.c.ConsecratedSphinx.class, RETRO_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Chaotic Goo", 1658, Rarity.RARE, mage.cards.c.ChaoticGoo.class, RETRO_ART)); cards.add(new SetCardInfo("Kiki-Jiki, Mirror Breaker", 1659, Rarity.MYTHIC, mage.cards.k.KikiJikiMirrorBreaker.class, RETRO_ART)); @@ -1726,21 +1726,21 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Kiora, Behemoth Beckoner", 1700, Rarity.RARE, mage.cards.k.KioraBehemothBeckoner.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tezzeret, Master of the Bridge", 1701, Rarity.MYTHIC, mage.cards.t.TezzeretMasterOfTheBridge.class)); cards.add(new SetCardInfo("Vraska, Golgari Queen", 1702, Rarity.MYTHIC, mage.cards.v.VraskaGolgariQueen.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Jaxis, the Troublemaker", 1703, Rarity.RARE, mage.cards.j.JaxisTheTroublemaker.class)); - cards.add(new SetCardInfo("Coffin Queen", 1704, Rarity.RARE, mage.cards.c.CoffinQueen.class)); - cards.add(new SetCardInfo("Goblin King", 1705, Rarity.RARE, mage.cards.g.GoblinKing.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Professional Face-Breaker", 1706, Rarity.RARE, mage.cards.p.ProfessionalFaceBreaker.class)); - cards.add(new SetCardInfo("Rankle, Master of Pranks", 1707, Rarity.MYTHIC, mage.cards.r.RankleMasterOfPranks.class)); + cards.add(new SetCardInfo("Jaxis, the Troublemaker", 1703, Rarity.RARE, mage.cards.j.JaxisTheTroublemaker.class, FULL_ART)); + cards.add(new SetCardInfo("Coffin Queen", 1704, Rarity.RARE, mage.cards.c.CoffinQueen.class, FULL_ART)); + cards.add(new SetCardInfo("Goblin King", 1705, Rarity.RARE, mage.cards.g.GoblinKing.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Professional Face-Breaker", 1706, Rarity.RARE, mage.cards.p.ProfessionalFaceBreaker.class, FULL_ART)); + cards.add(new SetCardInfo("Rankle, Master of Pranks", 1707, Rarity.MYTHIC, mage.cards.r.RankleMasterOfPranks.class, FULL_ART)); cards.add(new SetCardInfo("Soul Warden", 1708, Rarity.RARE, mage.cards.s.SoulWarden.class)); cards.add(new SetCardInfo("Shivan Dragon", 1709, Rarity.RARE, mage.cards.s.ShivanDragon.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Elves of Deep Shadow", 1710, Rarity.RARE, mage.cards.e.ElvesOfDeepShadow.class)); cards.add(new SetCardInfo("Good-Fortune Unicorn", 1711, Rarity.RARE, mage.cards.g.GoodFortuneUnicorn.class)); cards.add(new SetCardInfo("Coat of Arms", 1712, Rarity.RARE, mage.cards.c.CoatOfArms.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Dictate of Erebos", 1713, Rarity.RARE, mage.cards.d.DictateOfErebos.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Fecundity", 1714, Rarity.RARE, mage.cards.f.Fecundity.class)); - cards.add(new SetCardInfo("Mayhem Devil", 1715, Rarity.RARE, mage.cards.m.MayhemDevil.class)); - cards.add(new SetCardInfo("Moldervine Reclamation", 1716, Rarity.RARE, mage.cards.m.MoldervineReclamation.class)); - cards.add(new SetCardInfo("Prossh, Skyraider of Kher", 1717, Rarity.MYTHIC, mage.cards.p.ProsshSkyraiderOfKher.class)); + cards.add(new SetCardInfo("Dictate of Erebos", 1713, Rarity.RARE, mage.cards.d.DictateOfErebos.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Fecundity", 1714, Rarity.RARE, mage.cards.f.Fecundity.class, FULL_ART)); + cards.add(new SetCardInfo("Mayhem Devil", 1715, Rarity.RARE, mage.cards.m.MayhemDevil.class, FULL_ART)); + cards.add(new SetCardInfo("Moldervine Reclamation", 1716, Rarity.RARE, mage.cards.m.MoldervineReclamation.class, FULL_ART)); + cards.add(new SetCardInfo("Prossh, Skyraider of Kher", 1717, Rarity.MYTHIC, mage.cards.p.ProsshSkyraiderOfKher.class, FULL_ART)); cards.add(new SetCardInfo("Back to Basics", 1718, Rarity.RARE, mage.cards.b.BackToBasics.class)); cards.add(new SetCardInfo("Preordain", 1719, Rarity.RARE, mage.cards.p.Preordain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sphinx of the Second Sun", 1720, Rarity.MYTHIC, mage.cards.s.SphinxOfTheSecondSun.class)); @@ -1783,11 +1783,11 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Dauthi Voidwalker", 1760, Rarity.RARE, mage.cards.d.DauthiVoidwalker.class)); cards.add(new SetCardInfo("Magus of the Moon", 1761, Rarity.RARE, mage.cards.m.MagusOfTheMoon.class)); cards.add(new SetCardInfo("Witch's Oven", 1762, Rarity.RARE, mage.cards.w.WitchsOven.class)); - cards.add(new SetCardInfo("Doom Whisperer", 1763, Rarity.MYTHIC, mage.cards.d.DoomWhisperer.class)); - cards.add(new SetCardInfo("Ravenous Chupacabra", 1764, Rarity.RARE, mage.cards.r.RavenousChupacabra.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Koma, Cosmos Serpent", 1765, Rarity.MYTHIC, mage.cards.k.KomaCosmosSerpent.class)); - cards.add(new SetCardInfo("Mazirek, Kraul Death Priest", 1766, Rarity.MYTHIC, mage.cards.m.MazirekKraulDeathPriest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Uril, the Miststalker", 1767, Rarity.MYTHIC, mage.cards.u.UrilTheMiststalker.class)); + cards.add(new SetCardInfo("Doom Whisperer", 1763, Rarity.MYTHIC, mage.cards.d.DoomWhisperer.class, FULL_ART)); + cards.add(new SetCardInfo("Ravenous Chupacabra", 1764, Rarity.RARE, mage.cards.r.RavenousChupacabra.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Koma, Cosmos Serpent", 1765, Rarity.MYTHIC, mage.cards.k.KomaCosmosSerpent.class, FULL_ART)); + cards.add(new SetCardInfo("Mazirek, Kraul Death Priest", 1766, Rarity.MYTHIC, mage.cards.m.MazirekKraulDeathPriest.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Uril, the Miststalker", 1767, Rarity.MYTHIC, mage.cards.u.UrilTheMiststalker.class, FULL_ART)); cards.add(new SetCardInfo("Careful Study", 1768, Rarity.RARE, mage.cards.c.CarefulStudy.class)); cards.add(new SetCardInfo("Living End", 1769, Rarity.MYTHIC, mage.cards.l.LivingEnd.class)); cards.add(new SetCardInfo("Eladamri's Call", 1770, Rarity.RARE, mage.cards.e.EladamrisCall.class)); @@ -1833,11 +1833,11 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Varragoth, Bloodsky Sire", 1809, Rarity.RARE, mage.cards.v.VarragothBloodskySire.class)); cards.add(new SetCardInfo("Twinflame", 1810, Rarity.RARE, mage.cards.t.Twinflame.class)); cards.add(new SetCardInfo("Genesis Chamber", 1811, Rarity.RARE, mage.cards.g.GenesisChamber.class)); - cards.add(new SetCardInfo("Silence", 1816, Rarity.RARE, mage.cards.s.Silence.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Winds of Abandon", 1817, Rarity.RARE, mage.cards.w.WindsOfAbandon.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Culling the Weak", 1818, Rarity.RARE, mage.cards.c.CullingTheWeak.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Fatal Push", 1819, Rarity.RARE, mage.cards.f.FatalPush.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Young Wolf", 1820, Rarity.RARE, mage.cards.y.YoungWolf.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Silence", 1816, Rarity.RARE, mage.cards.s.Silence.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Winds of Abandon", 1817, Rarity.RARE, mage.cards.w.WindsOfAbandon.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Culling the Weak", 1818, Rarity.RARE, mage.cards.c.CullingTheWeak.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Fatal Push", 1819, Rarity.RARE, mage.cards.f.FatalPush.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Young Wolf", 1820, Rarity.RARE, mage.cards.y.YoungWolf.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Mana Geyser", 1821, Rarity.RARE, mage.cards.m.ManaGeyser.class)); cards.add(new SetCardInfo("Lightning Bolt", 1822, Rarity.RARE, mage.cards.l.LightningBolt.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fierce Guardianship", 1823, Rarity.RARE, mage.cards.f.FierceGuardianship.class)); @@ -1888,14 +1888,14 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Damn", 1870, Rarity.RARE, mage.cards.d.Damn.class)); cards.add(new SetCardInfo("Lightning Bolt", 1871, Rarity.RARE, mage.cards.l.LightningBolt.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Heroic Intervention", 1872, Rarity.RARE, mage.cards.h.HeroicIntervention.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Aesi, Tyrant of Gyre Strait", 1873, Rarity.MYTHIC, mage.cards.a.AesiTyrantOfGyreStrait.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Aesi, Tyrant of Gyre Strait", "1873b", Rarity.MYTHIC, mage.cards.a.AesiTyrantOfGyreStrait.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Anje Falkenrath", 1874, Rarity.MYTHIC, mage.cards.a.AnjeFalkenrath.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Anje Falkenrath", "1874b", Rarity.MYTHIC, mage.cards.a.AnjeFalkenrath.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Chulane, Teller of Tales", 1875, Rarity.MYTHIC, mage.cards.c.ChulaneTellerOfTales.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Chulane, Teller of Tales", "1875b", Rarity.MYTHIC, mage.cards.c.ChulaneTellerOfTales.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Radha, Heart of Keld", 1876, Rarity.RARE, mage.cards.r.RadhaHeartOfKeld.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Radha, Heart of Keld", "1876b", Rarity.RARE, mage.cards.r.RadhaHeartOfKeld.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aesi, Tyrant of Gyre Strait", 1873, Rarity.MYTHIC, mage.cards.a.AesiTyrantOfGyreStrait.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Aesi, Tyrant of Gyre Strait", "1873b", Rarity.MYTHIC, mage.cards.a.AesiTyrantOfGyreStrait.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Anje Falkenrath", 1874, Rarity.MYTHIC, mage.cards.a.AnjeFalkenrath.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Anje Falkenrath", "1874b", Rarity.MYTHIC, mage.cards.a.AnjeFalkenrath.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Chulane, Teller of Tales", 1875, Rarity.MYTHIC, mage.cards.c.ChulaneTellerOfTales.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Chulane, Teller of Tales", "1875b", Rarity.MYTHIC, mage.cards.c.ChulaneTellerOfTales.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Radha, Heart of Keld", 1876, Rarity.RARE, mage.cards.r.RadhaHeartOfKeld.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Radha, Heart of Keld", "1876b", Rarity.RARE, mage.cards.r.RadhaHeartOfKeld.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Light-Paws, Emperor's Voice", 1877, Rarity.RARE, mage.cards.l.LightPawsEmperorsVoice.class)); cards.add(new SetCardInfo("Murktide Regent", 1878, Rarity.MYTHIC, mage.cards.m.MurktideRegent.class)); cards.add(new SetCardInfo("Lightning Bolt", 1879, Rarity.RARE, mage.cards.l.LightningBolt.class, NON_FULL_USE_VARIOUS)); @@ -1976,16 +1976,16 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Liesa, Shroud of Dusk", 1961, Rarity.RARE, mage.cards.l.LiesaShroudOfDusk.class)); cards.add(new SetCardInfo("Oloro, Ageless Ascetic", 1962, Rarity.MYTHIC, mage.cards.o.OloroAgelessAscetic.class)); cards.add(new SetCardInfo("Sythis, Harvest's Hand", 1963, Rarity.RARE, mage.cards.s.SythisHarvestsHand.class)); - cards.add(new SetCardInfo("Parhelion II", 1964, Rarity.RARE, mage.cards.p.ParhelionII.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Parhelion II", "1964b", Rarity.RARE, mage.cards.p.ParhelionII.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mechtitan Core", 1965, Rarity.RARE, mage.cards.m.MechtitanCore.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mechtitan Core", "1965b", Rarity.RARE, mage.cards.m.MechtitanCore.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Peacewalker Colossus", 1966, Rarity.RARE, mage.cards.p.PeacewalkerColossus.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Peacewalker Colossus", "1966b", Rarity.RARE, mage.cards.p.PeacewalkerColossus.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Reckoner Bankbuster", 1967, Rarity.RARE, mage.cards.r.ReckonerBankbuster.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Reckoner Bankbuster", "1967b", Rarity.RARE, mage.cards.r.ReckonerBankbuster.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Smuggler's Copter", 1968, Rarity.RARE, mage.cards.s.SmugglersCopter.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Smuggler's Copter", "1968b", Rarity.RARE, mage.cards.s.SmugglersCopter.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Parhelion II", 1964, Rarity.RARE, mage.cards.p.ParhelionII.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Parhelion II", "1964b", Rarity.RARE, mage.cards.p.ParhelionII.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Mechtitan Core", 1965, Rarity.RARE, mage.cards.m.MechtitanCore.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Mechtitan Core", "1965b", Rarity.RARE, mage.cards.m.MechtitanCore.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Peacewalker Colossus", 1966, Rarity.RARE, mage.cards.p.PeacewalkerColossus.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Peacewalker Colossus", "1966b", Rarity.RARE, mage.cards.p.PeacewalkerColossus.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Reckoner Bankbuster", 1967, Rarity.RARE, mage.cards.r.ReckonerBankbuster.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Reckoner Bankbuster", "1967b", Rarity.RARE, mage.cards.r.ReckonerBankbuster.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Smuggler's Copter", 1968, Rarity.RARE, mage.cards.s.SmugglersCopter.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Smuggler's Copter", "1968b", Rarity.RARE, mage.cards.s.SmugglersCopter.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Dragonlord Atarka", 1970, Rarity.MYTHIC, mage.cards.d.DragonlordAtarka.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dragonlord Atarka", "1970b", Rarity.MYTHIC, mage.cards.d.DragonlordAtarka.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dragonlord Dromoka", 1971, Rarity.MYTHIC, mage.cards.d.DragonlordDromoka.class, NON_FULL_USE_VARIOUS)); @@ -2026,11 +2026,11 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Treasonous Ogre", 2007, Rarity.RARE, mage.cards.t.TreasonousOgre.class)); cards.add(new SetCardInfo("Uncivil Unrest", 2008, Rarity.RARE, mage.cards.u.UncivilUnrest.class)); cards.add(new SetCardInfo("Marchesa, the Black Rose", 2009, Rarity.RARE, mage.cards.m.MarchesaTheBlackRose.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Ashaya, Soul of the Wild", 2014, Rarity.MYTHIC, mage.cards.a.AshayaSoulOfTheWild.class)); - cards.add(new SetCardInfo("Elvish Reclaimer", 2015, Rarity.RARE, mage.cards.e.ElvishReclaimer.class)); - cards.add(new SetCardInfo("Harrow", 2016, Rarity.RARE, mage.cards.h.Harrow.class)); - cards.add(new SetCardInfo("World Shaper", 2017, Rarity.RARE, mage.cards.w.WorldShaper.class)); - cards.add(new SetCardInfo("Horn of Greed", 2018, Rarity.RARE, mage.cards.h.HornOfGreed.class)); + cards.add(new SetCardInfo("Ashaya, Soul of the Wild", 2014, Rarity.MYTHIC, mage.cards.a.AshayaSoulOfTheWild.class, FULL_ART)); + cards.add(new SetCardInfo("Elvish Reclaimer", 2015, Rarity.RARE, mage.cards.e.ElvishReclaimer.class, FULL_ART)); + cards.add(new SetCardInfo("Harrow", 2016, Rarity.RARE, mage.cards.h.Harrow.class, FULL_ART)); + cards.add(new SetCardInfo("World Shaper", 2017, Rarity.RARE, mage.cards.w.WorldShaper.class, FULL_ART)); + cards.add(new SetCardInfo("Horn of Greed", 2018, Rarity.RARE, mage.cards.h.HornOfGreed.class, FULL_ART)); cards.add(new SetCardInfo("Damnation", 2019, Rarity.RARE, mage.cards.d.Damnation.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dark Ritual", 2020, Rarity.RARE, mage.cards.d.DarkRitual.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Peer into the Abyss", 2021, Rarity.RARE, mage.cards.p.PeerIntoTheAbyss.class, NON_FULL_USE_VARIOUS)); @@ -2072,9 +2072,9 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Lightning Greaves", 2062, Rarity.RARE, mage.cards.l.LightningGreaves.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sol Ring", 2063, Rarity.RARE, mage.cards.s.SolRing.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Cultural Exchange", 2071, Rarity.RARE, mage.cards.c.CulturalExchange.class)); - cards.add(new SetCardInfo("Folio of Fancies", 2072, Rarity.RARE, mage.cards.f.FolioOfFancies.class)); - cards.add(new SetCardInfo("Concordant Crossroads", 2073, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Rites of Flourishing", 2074, Rarity.RARE, mage.cards.r.RitesOfFlourishing.class)); + cards.add(new SetCardInfo("Folio of Fancies", 2072, Rarity.RARE, mage.cards.f.FolioOfFancies.class, FULL_ART)); + cards.add(new SetCardInfo("Concordant Crossroads", 2073, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class, FULL_ART_USE_VARIOUS)); + cards.add(new SetCardInfo("Rites of Flourishing", 2074, Rarity.RARE, mage.cards.r.RitesOfFlourishing.class, FULL_ART)); cards.add(new SetCardInfo("Font of Mythos", 2075, Rarity.RARE, mage.cards.f.FontOfMythos.class)); cards.add(new SetCardInfo("Plains", 2076, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Island", 2077, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); @@ -2146,17 +2146,17 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Guardian Project", 2172, Rarity.MYTHIC, mage.cards.g.GuardianProject.class)); cards.add(new SetCardInfo("Roon of the Hidden Realm", 2173, Rarity.RARE, mage.cards.r.RoonOfTheHiddenRealm.class)); cards.add(new SetCardInfo("Soulherder", 2174, Rarity.RARE, mage.cards.s.Soulherder.class)); - cards.add(new SetCardInfo("Jaws, Relentless Predator", 2175, Rarity.MYTHIC, mage.cards.j.JawsRelentlessPredator.class)); + cards.add(new SetCardInfo("Jaws, Relentless Predator", 2175, Rarity.MYTHIC, mage.cards.j.JawsRelentlessPredator.class, FULL_ART)); cards.add(new SetCardInfo("Descent into Avernus", 2176, Rarity.RARE, mage.cards.d.DescentIntoAvernus.class)); cards.add(new SetCardInfo("Reckless Endeavor", 2177, Rarity.RARE, mage.cards.r.RecklessEndeavor.class)); cards.add(new SetCardInfo("Sneak Attack", 2178, Rarity.MYTHIC, mage.cards.s.SneakAttack.class)); cards.add(new SetCardInfo("Abrade", 2179, Rarity.RARE, mage.cards.a.Abrade.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bruvac the Grandiloquent", 2181, Rarity.MYTHIC, mage.cards.b.BruvacTheGrandiloquent.class)); - cards.add(new SetCardInfo("Windfall", 2182, Rarity.RARE, mage.cards.w.Windfall.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Windfall", 2182, Rarity.RARE, mage.cards.w.Windfall.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Captain N'ghathrod", 2183, Rarity.MYTHIC, mage.cards.c.CaptainNghathrod.class)); cards.add(new SetCardInfo("Nekusar, the Mindrazer", 2184, Rarity.RARE, mage.cards.n.NekusarTheMindrazer.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Iron Maiden", 2185, Rarity.RARE, mage.cards.i.IronMaiden.class)); - cards.add(new SetCardInfo("Mindcrank", 2186, Rarity.RARE, mage.cards.m.Mindcrank.class)); + cards.add(new SetCardInfo("Iron Maiden", 2185, Rarity.RARE, mage.cards.i.IronMaiden.class, FULL_ART)); + cards.add(new SetCardInfo("Mindcrank", 2186, Rarity.RARE, mage.cards.m.Mindcrank.class, FULL_ART)); cards.add(new SetCardInfo("Lethal Scheme", 2187, Rarity.RARE, mage.cards.l.LethalScheme.class)); cards.add(new SetCardInfo("Grave Titan", 2188, Rarity.MYTHIC, mage.cards.g.GraveTitan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Animate Dead", 2189, Rarity.RARE, mage.cards.a.AnimateDead.class)); diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 8916d75645e..a8dd1572a39 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -759,22 +759,26 @@ public class VerifyCardDataTest { continue; } - // CHECK: poster promoType and/or textless must use full art setting - if (((jsonCard.promoTypes != null && jsonCard.promoTypes.contains("poster")) || jsonCard.isTextless) && !card.isFullArt()) { - errorsList.add("Error: card must use full art setting: " - + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber()); - } - // CHECK: full art lands must use full art setting + // CHECK: non-full art lands must not use full art setting + // CHECK: if full art land is using full art setting, don't perform retro or poster tests boolean isLand = card.getRarity().equals(Rarity.LAND); if (isLand && jsonCard.isFullArt && !card.isFullArt()) { errorsList.add("Error: card must use full art lands setting: " + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber()); + continue; + } else if (isLand && !jsonCard.isFullArt && card.isFullArt()) { + errorsList.add("Error: card must NOT use full art lands setting: " + + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber()); + continue; + } else if (isLand && jsonCard.isFullArt && card.isFullArt()) { + // Land full art is correct, skip other tests + continue; } - // CHECK: non-full art lands must not use full art setting - if (isLand && !jsonCard.isFullArt && card.isFullArt()) { - errorsList.add("Error: card must NOT use full art lands setting: " + // CHECK: poster promoType and/or textless must use full art setting + if (((jsonCard.promoTypes != null && jsonCard.promoTypes.contains("poster")) || jsonCard.isTextless) && !card.isFullArt()) { + errorsList.add("Error: card must use full art setting: " + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber()); } -- 2.47.2 From 86d0910e1e5e09e7e6a3060e20afb31da35f6be9 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Sat, 8 Nov 2025 23:01:44 -0500 Subject: [PATCH 165/261] Update OptionalOneShotEffect with possibly better text generation. --- .../abilities/decorator/OptionalOneShotEffect.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java b/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java index c4d59047de3..ea8576a2301 100644 --- a/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java +++ b/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java @@ -18,6 +18,10 @@ public class OptionalOneShotEffect extends OneShotEffect { private final Effects effects = new Effects(); + public OptionalOneShotEffect(OneShotEffect effect) { + this(effect, null); + } + public OptionalOneShotEffect(OneShotEffect effect, String text) { super(effect.getOutcome()); if (effect != null) { @@ -38,7 +42,11 @@ public class OptionalOneShotEffect extends OneShotEffect { return true; } Player player = game.getPlayer(source.getControllerId()); - if (player != null && player.chooseUse(outcome, staticText, source, game)) { + String chooseText = staticText; + if (chooseText == null || chooseText.isEmpty()) { + chooseText = getText(new Mode(effects.get(0))); + } + if (player != null && player.chooseUse(outcome, chooseText, source, game)) { effects.setTargetPointer(this.getTargetPointer().copy()); effects.forEach(effect -> effect.apply(game, source)); return true; @@ -67,7 +75,7 @@ public class OptionalOneShotEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - return "you may " + CardUtil.getTextWithFirstCharLowerCase(effects.getText(mode)); + return "You may " + CardUtil.getTextWithFirstCharLowerCase(effects.getText(mode)); } @Override -- 2.47.2 From df20c64c5812816592f0dbdcb0c2281bdb60af5e Mon Sep 17 00:00:00 2001 From: ReSech Date: Sun, 9 Nov 2025 15:03:57 +1100 Subject: [PATCH 166/261] Update reprints and tokens [SLC] [SLD] [PW25] [PSPL] (#14074) * Add Mutagen Token * Add missing SLC * Add missing SLD * Add missing PW25 * Add missing PSPL * fix verify errors --- .../sources/ScryfallImageSupportTokens.java | 3 ++ .../src/mage/sets/SecretLairCountdown.java | 1 + Mage.Sets/src/mage/sets/SecretLairDrop.java | 39 +++++++++++++++---- Mage.Sets/src/mage/sets/SpotlightSeries.java | 5 ++- .../src/mage/sets/WizardsPlayNetwork2025.java | 7 +++- Mage/src/main/resources/tokens-database.txt | 3 ++ 6 files changed, 48 insertions(+), 10 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java index 17e0094521f..ef998d93ca8 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java @@ -2831,6 +2831,9 @@ public class ScryfallImageSupportTokens { put("SPM/Spider", "https://api.scryfall.com/cards/tspm/3?format=image"); put("SPM/Treasure", "https://api.scryfall.com/cards/tspm/7?format=image"); + // TMT + put("TMT/Mutagen", "https://api.scryfall.com/cards/ttmt/9?format=image"); + // JVC put("JVC/Elemental Shaman", "https://api.scryfall.com/cards/tjvc/4?format=image"); diff --git a/Mage.Sets/src/mage/sets/SecretLairCountdown.java b/Mage.Sets/src/mage/sets/SecretLairCountdown.java index bf9c227fbce..b66e5e1f650 100644 --- a/Mage.Sets/src/mage/sets/SecretLairCountdown.java +++ b/Mage.Sets/src/mage/sets/SecretLairCountdown.java @@ -19,6 +19,7 @@ public class SecretLairCountdown extends ExpansionSet { super("Secret Lair Countdown", "SLC", ExpansionSet.buildDate(2022, 11, 1), SetType.PROMOTIONAL); this.hasBasicLands = false; + cards.add(new SetCardInfo("Alhammarret's Archive", 27, Rarity.MYTHIC, mage.cards.a.AlhammarretsArchive.class, FULL_ART)); cards.add(new SetCardInfo("Altar of the Brood", 1, Rarity.RARE, mage.cards.a.AltarOfTheBrood.class)); cards.add(new SetCardInfo("Arclight Phoenix", 2018, Rarity.MYTHIC, mage.cards.a.ArclightPhoenix.class)); cards.add(new SetCardInfo("Birthing Pod", 2011, Rarity.RARE, mage.cards.b.BirthingPod.class)); diff --git a/Mage.Sets/src/mage/sets/SecretLairDrop.java b/Mage.Sets/src/mage/sets/SecretLairDrop.java index 3b9da5294b5..db3d84fa476 100644 --- a/Mage.Sets/src/mage/sets/SecretLairDrop.java +++ b/Mage.Sets/src/mage/sets/SecretLairDrop.java @@ -262,7 +262,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Kaya, Ghost Assassin", 247, Rarity.MYTHIC, mage.cards.k.KayaGhostAssassin.class)); cards.add(new SetCardInfo("Teferi, Hero of Dominaria", 248, Rarity.MYTHIC, mage.cards.t.TeferiHeroOfDominaria.class)); cards.add(new SetCardInfo("Sol Ring", 249, Rarity.RARE, mage.cards.s.SolRing.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Path of Ancestry", 250, Rarity.RARE, mage.cards.p.PathOfAncestry.class)); + cards.add(new SetCardInfo("Path of Ancestry", 250, Rarity.RARE, mage.cards.p.PathOfAncestry.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dack Fayden", 251, Rarity.MYTHIC, mage.cards.d.DackFayden.class, RETRO_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Teferi, Time Raveler", 252, Rarity.RARE, mage.cards.t.TeferiTimeRaveler.class, RETRO_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Karn, the Great Creator", 253, Rarity.RARE, mage.cards.k.KarnTheGreatCreator.class, RETRO_ART_USE_VARIOUS)); @@ -368,12 +368,12 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Forest", 363, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swords to Plowshares", 364, Rarity.RARE, mage.cards.s.SwordsToPlowshares.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Grim Tutor", 365, Rarity.MYTHIC, mage.cards.g.GrimTutor.class, FULL_ART_USE_VARIOUS)); - cards.add(new SetCardInfo("Blood Moon", 366, Rarity.RARE, mage.cards.b.BloodMoon.class)); + cards.add(new SetCardInfo("Blood Moon", 366, Rarity.RARE, mage.cards.b.BloodMoon.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Cut // Ribbons", 367, Rarity.RARE, mage.cards.c.CutRibbons.class)); cards.add(new SetCardInfo("Teferi's Puzzle Box", 368, Rarity.RARE, mage.cards.t.TeferisPuzzleBox.class)); cards.add(new SetCardInfo("Generous Gift", 369, Rarity.RARE, mage.cards.g.GenerousGift.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Chain Lightning", 370, Rarity.RARE, mage.cards.c.ChainLightning.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Kodama's Reach", 371, Rarity.RARE, mage.cards.k.KodamasReach.class)); + cards.add(new SetCardInfo("Kodama's Reach", 371, Rarity.RARE, mage.cards.k.KodamasReach.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Heirloom Blade", 372, Rarity.RARE, mage.cards.h.HeirloomBlade.class)); cards.add(new SetCardInfo("Mulldrifter", 373, Rarity.RARE, mage.cards.m.Mulldrifter.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mulldrifter", 374, Rarity.RARE, mage.cards.m.Mulldrifter.class, NON_FULL_USE_VARIOUS)); @@ -903,6 +903,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Arcane Signet", 908, Rarity.RARE, mage.cards.a.ArcaneSignet.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Gilded Lotus", 909, Rarity.RARE, mage.cards.g.GildedLotus.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sol Ring", 910, Rarity.RARE, mage.cards.s.SolRing.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Path of Ancestry", 914, Rarity.RARE, mage.cards.p.PathOfAncestry.class, NON_FULL_USE_VARIOUS)); } private void addPart2() { @@ -1031,7 +1032,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Etali, Primal Storm", "1123b", Rarity.RARE, mage.cards.e.EtaliPrimalStorm.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Ghalta, Primal Hunger", 1124, Rarity.RARE, mage.cards.g.GhaltaPrimalHunger.class, FULL_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Ghalta, Primal Hunger", "1124b", Rarity.RARE, mage.cards.g.GhaltaPrimalHunger.class, FULL_ART_USE_VARIOUS)); - cards.add(new SetCardInfo("Serra Ascendant", 1125, Rarity.RARE, mage.cards.s.SerraAscendant.class)); + cards.add(new SetCardInfo("Serra Ascendant", 1125, Rarity.RARE, mage.cards.s.SerraAscendant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Rapid Hybridization", 1126, Rarity.RARE, mage.cards.r.RapidHybridization.class)); cards.add(new SetCardInfo("Demonic Consultation", 1127, Rarity.RARE, mage.cards.d.DemonicConsultation.class)); cards.add(new SetCardInfo("Winds of Change", 1128, Rarity.RARE, mage.cards.w.WindsOfChange.class)); @@ -1610,7 +1611,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Inspiring Vantage", 1605, Rarity.RARE, mage.cards.i.InspiringVantage.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Inspiring Vantage", "1605*", Rarity.RARE, mage.cards.i.InspiringVantage.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Scrying Sheets", 1606, Rarity.RARE, mage.cards.s.ScryingSheets.class)); - cards.add(new SetCardInfo("Thespian's Stage", 1607, Rarity.RARE, mage.cards.t.ThespiansStage.class)); + cards.add(new SetCardInfo("Thespian's Stage", 1607, Rarity.RARE, mage.cards.t.ThespiansStage.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Avabruck Caretaker", 1608, Rarity.MYTHIC, mage.cards.a.AvabruckCaretaker.class)); cards.add(new SetCardInfo("Hollowhenge Huntmaster", 1608, Rarity.MYTHIC, mage.cards.h.HollowhengeHuntmaster.class)); cards.add(new SetCardInfo("Beastmaster Ascension", 1609, Rarity.RARE, mage.cards.b.BeastmasterAscension.class)); @@ -2067,7 +2068,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Tireless Provisioner", 2057, Rarity.RARE, mage.cards.t.TirelessProvisioner.class)); cards.add(new SetCardInfo("Sylvan Library", 2058, Rarity.RARE, mage.cards.s.SylvanLibrary.class)); cards.add(new SetCardInfo("Ancient Greenwarden", 2059, Rarity.MYTHIC, mage.cards.a.AncientGreenwarden.class)); - cards.add(new SetCardInfo("Expressive Iteration", 2060, Rarity.RARE, mage.cards.e.ExpressiveIteration.class)); + cards.add(new SetCardInfo("Expressive Iteration", 2060, Rarity.RARE, mage.cards.e.ExpressiveIteration.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Xenagos, God of Revels", 2061, Rarity.MYTHIC, mage.cards.x.XenagosGodOfRevels.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Lightning Greaves", 2062, Rarity.RARE, mage.cards.l.LightningGreaves.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sol Ring", 2063, Rarity.RARE, mage.cards.s.SolRing.class, NON_FULL_USE_VARIOUS)); @@ -2202,6 +2203,30 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Voja, Jaws of the Conclave", 2284, Rarity.MYTHIC, mage.cards.v.VojaJawsOfTheConclave.class)); cards.add(new SetCardInfo("Wilhelt, the Rotcleaver", 2285, Rarity.MYTHIC, mage.cards.w.WilheltTheRotcleaver.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Liberator, Urza's Battlethopter", 2286, Rarity.RARE, mage.cards.l.LiberatorUrzasBattlethopter.class)); + cards.add(new SetCardInfo("Torment of Hailfire", 2287, Rarity.RARE, mage.cards.t.TormentOfHailfire.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Blood Moon", 2288, Rarity.RARE, mage.cards.b.BloodMoon.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Lightning Bolt", 2289, Rarity.RARE, mage.cards.l.LightningBolt.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Dramatic Entrance", 2290, Rarity.RARE, mage.cards.d.DramaticEntrance.class)); + cards.add(new SetCardInfo("Serra Ascendant", 2291, Rarity.RARE, mage.cards.s.SerraAscendant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ponder", 2292, Rarity.RARE, mage.cards.p.Ponder.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Cryptolith Rite", 2293, Rarity.RARE, mage.cards.c.CryptolithRite.class)); + cards.add(new SetCardInfo("Kodama's Reach", 2294, Rarity.RARE, mage.cards.k.KodamasReach.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Chain of Vapor", 2295, Rarity.RARE, mage.cards.c.ChainOfVapor.class)); + cards.add(new SetCardInfo("Meltdown", 2296, Rarity.RARE, mage.cards.m.Meltdown.class)); + cards.add(new SetCardInfo("Nature's Claim", 2297, Rarity.RARE, mage.cards.n.NaturesClaim.class)); + cards.add(new SetCardInfo("Anguished Unmaking", 2298, Rarity.RARE, mage.cards.a.AnguishedUnmaking.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Putrefy", 2299, Rarity.RARE, mage.cards.p.Putrefy.class)); + cards.add(new SetCardInfo("Silence", 2300, Rarity.RARE, mage.cards.s.Silence.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Preordain", 2301, Rarity.COMMON, mage.cards.p.Preordain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Painful Truths", 2302, Rarity.RARE, mage.cards.p.PainfulTruths.class)); + cards.add(new SetCardInfo("Past in Flames", 2303, Rarity.MYTHIC, mage.cards.p.PastInFlames.class)); + cards.add(new SetCardInfo("Force of Vigor", 2304, Rarity.RARE, mage.cards.f.ForceOfVigor.class)); + cards.add(new SetCardInfo("Expressive Iteration", 2305, Rarity.RARE, mage.cards.e.ExpressiveIteration.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Phantasmal Image", 2306, Rarity.RARE, mage.cards.p.PhantasmalImage.class)); + cards.add(new SetCardInfo("Braid of Fire", 2307, Rarity.RARE, mage.cards.b.BraidOfFire.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Cursed Mirror", 2308, Rarity.RARE, mage.cards.c.CursedMirror.class)); + cards.add(new SetCardInfo("Mask of Memory", 2309, Rarity.RARE, mage.cards.m.MaskOfMemory.class)); + cards.add(new SetCardInfo("Thespian's Stage", 2310, Rarity.RARE, mage.cards.t.ThespiansStage.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Distant Melody", 2311, Rarity.RARE, mage.cards.d.DistantMelody.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Explore", 2312, Rarity.RARE, mage.cards.e.Explore.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Inspiring Call", 2313, Rarity.RARE, mage.cards.i.InspiringCall.class)); @@ -2249,7 +2274,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Jace, the Mind Sculptor", 8001, Rarity.MYTHIC, mage.cards.j.JaceTheMindSculptor.class)); cards.add(new SetCardInfo("Doom Blade", 9990, Rarity.RARE, mage.cards.d.DoomBlade.class)); cards.add(new SetCardInfo("Massacre", 9991, Rarity.RARE, mage.cards.m.Massacre.class)); - cards.add(new SetCardInfo("Torment of Hailfire", 9992, Rarity.RARE, mage.cards.t.TormentOfHailfire.class)); + cards.add(new SetCardInfo("Torment of Hailfire", 9992, Rarity.RARE, mage.cards.t.TormentOfHailfire.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ruination", 9993, Rarity.RARE, mage.cards.r.Ruination.class)); cards.add(new SetCardInfo("Mogis, God of Slaughter", 9994, Rarity.MYTHIC, mage.cards.m.MogisGodOfSlaughter.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Garruk, Caller of Beasts", 9995, Rarity.MYTHIC, mage.cards.g.GarrukCallerOfBeasts.class)); diff --git a/Mage.Sets/src/mage/sets/SpotlightSeries.java b/Mage.Sets/src/mage/sets/SpotlightSeries.java index 92d42cff327..4abfa43a33c 100644 --- a/Mage.Sets/src/mage/sets/SpotlightSeries.java +++ b/Mage.Sets/src/mage/sets/SpotlightSeries.java @@ -22,9 +22,10 @@ public final class SpotlightSeries extends ExpansionSet { this.hasBoosters = false; this.hasBasicLands = false; - cards.add(new SetCardInfo("Cloud, Midgar Mercenary", 5, Rarity.MYTHIC, mage.cards.c.CloudMidgarMercenary.class)); - cards.add(new SetCardInfo("Get Lost", 6, Rarity.RARE, mage.cards.g.GetLost.class)); + cards.add(new SetCardInfo("Cloud, Midgar Mercenary", 4, Rarity.MYTHIC, mage.cards.c.CloudMidgarMercenary.class)); + cards.add(new SetCardInfo("Get Lost", 5, Rarity.RARE, mage.cards.g.GetLost.class)); cards.add(new SetCardInfo("Kaldra Compleat", 2, Rarity.MYTHIC, mage.cards.k.KaldraCompleat.class)); + cards.add(new SetCardInfo("Spectacular Spider-Man", 6, Rarity.RARE, mage.cards.s.SpectacularSpiderMan.class)); cards.add(new SetCardInfo("Sword of Forge and Frontier", 3, Rarity.MYTHIC, mage.cards.s.SwordOfForgeAndFrontier.class)); cards.add(new SetCardInfo("Terror of the Peaks", 1, Rarity.RARE, mage.cards.t.TerrorOfThePeaks.class)); } diff --git a/Mage.Sets/src/mage/sets/WizardsPlayNetwork2025.java b/Mage.Sets/src/mage/sets/WizardsPlayNetwork2025.java index 5929c33e2fc..edc37e76764 100644 --- a/Mage.Sets/src/mage/sets/WizardsPlayNetwork2025.java +++ b/Mage.Sets/src/mage/sets/WizardsPlayNetwork2025.java @@ -20,15 +20,20 @@ public class WizardsPlayNetwork2025 extends ExpansionSet { this.hasBoosters = false; this.hasBasicLands = false; + cards.add(new SetCardInfo("Carnage, Crimson Chaos", 13, Rarity.RARE, mage.cards.c.CarnageCrimsonChaos.class)); cards.add(new SetCardInfo("Culling Ritual", 4, Rarity.RARE, mage.cards.c.CullingRitual.class)); cards.add(new SetCardInfo("Despark", 2, Rarity.UNCOMMON, mage.cards.d.Despark.class)); cards.add(new SetCardInfo("Dragon's Hoard", "1p", Rarity.RARE, mage.cards.d.DragonsHoard.class, RETRO_ART)); cards.add(new SetCardInfo("Dragonspeaker Shaman", 3, Rarity.RARE, mage.cards.d.DragonspeakerShaman.class)); + cards.add(new SetCardInfo("Gran-Gran", 14, Rarity.RARE, mage.cards.g.GranGran.class)); + cards.add(new SetCardInfo("Mary Jane Watson", 11, Rarity.RARE, mage.cards.m.MaryJaneWatson.class)); cards.add(new SetCardInfo("Monstrous Rage", 9, Rarity.RARE, mage.cards.m.MonstrousRage.class, RETRO_ART)); cards.add(new SetCardInfo("Palladium Myr", 6, Rarity.RARE, mage.cards.p.PalladiumMyr.class, RETRO_ART)); cards.add(new SetCardInfo("Rishkar's Expertise", 1, Rarity.RARE, mage.cards.r.RishkarsExpertise.class, RETRO_ART)); - cards.add(new SetCardInfo("Spectacular Spider-Man", 7, Rarity.RARE, mage.cards.s.SpectacularSpiderMan.class)); + cards.add(new SetCardInfo("Spider-Ham, Peter Porker", 10, Rarity.RARE, mage.cards.s.SpiderHamPeterPorker.class)); cards.add(new SetCardInfo("Trinket Mage", 8, Rarity.RARE, mage.cards.t.TrinketMage.class, RETRO_ART)); + cards.add(new SetCardInfo("Ultimate Green Goblin", 12, Rarity.RARE, mage.cards.u.UltimateGreenGoblin.class)); + cards.add(new SetCardInfo("Yuna, Grand Summoner", 16, Rarity.MYTHIC, mage.cards.y.YunaGrandSummoner.class)); cards.add(new SetCardInfo("Zidane, Tantalus Thief", 5, Rarity.RARE, mage.cards.z.ZidaneTantalusThief.class)); } } diff --git a/Mage/src/main/resources/tokens-database.txt b/Mage/src/main/resources/tokens-database.txt index fa695370dd3..5427226ba30 100644 --- a/Mage/src/main/resources/tokens-database.txt +++ b/Mage/src/main/resources/tokens-database.txt @@ -2884,6 +2884,9 @@ |Generate|TOK:SPM|Spider|||Spider21Token| |Generate|TOK:SPM|Treasure|||TreasureToken| +#TMT +|Generate|TOK:TMT|Mutagen|||MutagenToken| + # JVC |Generate|TOK:JVC|Elemental Shaman|||ElementalShamanToken| -- 2.47.2 From 784bea734f8fb710afa7b96202275f5dcc893832 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Sat, 8 Nov 2025 23:41:50 -0500 Subject: [PATCH 167/261] Better fix with text generation. --- .../mage/cards/a/AzulaRuthlessFirebender.java | 2 +- .../src/mage/cards/f/FirebenderAscension.java | 3 +-- .../decorator/OptionalOneShotEffect.java | 18 ++++++++---------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AzulaRuthlessFirebender.java b/Mage.Sets/src/mage/cards/a/AzulaRuthlessFirebender.java index f52e7430ef0..13749759c0e 100644 --- a/Mage.Sets/src/mage/cards/a/AzulaRuthlessFirebender.java +++ b/Mage.Sets/src/mage/cards/a/AzulaRuthlessFirebender.java @@ -42,7 +42,7 @@ public final class AzulaRuthlessFirebender extends CardImpl { this.addAbility(new FirebendingAbility(1)); // Whenever Azula attacks, you may discard a card. Then you get an experience counter for each player who discarded a card this turn. - Ability ability = new AttacksTriggeredAbility(new OptionalOneShotEffect(new DiscardControllerEffect(1), "You may discard a card")); + Ability ability = new AttacksTriggeredAbility(new OptionalOneShotEffect(new DiscardControllerEffect(1))); ability.addEffect(new AddCountersPlayersEffect(CounterType.EXPERIENCE.createInstance(), AzulaRuthlessFirebenderValue.instance, TargetController.YOU).setText("Then you get an experience counter for each player who discarded a card this turn.")); this.addAbility(ability, new DiscardedCardWatcher()); diff --git a/Mage.Sets/src/mage/cards/f/FirebenderAscension.java b/Mage.Sets/src/mage/cards/f/FirebenderAscension.java index cb6ef523762..b0424bb3997 100644 --- a/Mage.Sets/src/mage/cards/f/FirebenderAscension.java +++ b/Mage.Sets/src/mage/cards/f/FirebenderAscension.java @@ -60,8 +60,7 @@ class FirebenderAscensionTriggeredAbility extends TriggeredAbilityImpl { FirebenderAscensionTriggeredAbility() { super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.QUEST.createInstance(), true), false); - addEffect(new ConditionalOneShotEffect(new OptionalOneShotEffect(new CopyStackObjectEffect(), - "You may copy that ability. You may choose new targets for the copy."), condition, + addEffect(new ConditionalOneShotEffect(new OptionalOneShotEffect(new CopyStackObjectEffect()), condition, "Then if it has four or more quest counters on it, you may copy that ability. You may choose new targets for the copy.")); setTriggerPhrase("Whenever a creature you control attacking causes a triggered ability of that creature to trigger, "); } diff --git a/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java b/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java index ea8576a2301..13e909391ec 100644 --- a/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java +++ b/Mage/src/main/java/mage/abilities/decorator/OptionalOneShotEffect.java @@ -4,6 +4,7 @@ import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.Effects; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; import mage.target.targetpointer.TargetPointer; @@ -19,15 +20,11 @@ public class OptionalOneShotEffect extends OneShotEffect { private final Effects effects = new Effects(); public OptionalOneShotEffect(OneShotEffect effect) { - this(effect, null); - } - - public OptionalOneShotEffect(OneShotEffect effect, String text) { - super(effect.getOutcome()); - if (effect != null) { - this.effects.add(effect); + super(effect != null ? effect.getOutcome() : Outcome.Benefit); // must be first line, can't error for null effect here. + if (effect == null) { + throw new IllegalArgumentException("Wrong code usage: OptionalOneShotEffect should start with an effect to generate Outcome."); } - this.staticText = text; + this.effects.add(effect); } protected OptionalOneShotEffect(final OptionalOneShotEffect effect) { @@ -44,7 +41,8 @@ public class OptionalOneShotEffect extends OneShotEffect { Player player = game.getPlayer(source.getControllerId()); String chooseText = staticText; if (chooseText == null || chooseText.isEmpty()) { - chooseText = getText(new Mode(effects.get(0))); + chooseText = getText(source.getModes().getMode()); + chooseText = Character.toUpperCase(chooseText.charAt(0)) + chooseText.substring(1); } if (player != null && player.chooseUse(outcome, chooseText, source, game)) { effects.setTargetPointer(this.getTargetPointer().copy()); @@ -75,7 +73,7 @@ public class OptionalOneShotEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - return "You may " + CardUtil.getTextWithFirstCharLowerCase(effects.getText(mode)); + return "you may " + CardUtil.getTextWithFirstCharLowerCase(effects.getText(mode)); } @Override -- 2.47.2 From 865b05781e434d7aedc82ea6aabdddac864f2609 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sun, 9 Nov 2025 14:26:06 -0500 Subject: [PATCH 168/261] fix Zuko's Conviction missing target --- Mage.Sets/src/mage/cards/z/ZukosConviction.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mage.Sets/src/mage/cards/z/ZukosConviction.java b/Mage.Sets/src/mage/cards/z/ZukosConviction.java index f0ed6978e52..33b248dca9f 100644 --- a/Mage.Sets/src/mage/cards/z/ZukosConviction.java +++ b/Mage.Sets/src/mage/cards/z/ZukosConviction.java @@ -8,6 +8,8 @@ import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCardInYourGraveyard; import java.util.UUID; @@ -29,6 +31,7 @@ public final class ZukosConviction extends CardImpl { KickedCondition.ONCE, "return target creature card from your graveyard to your hand. " + "If this spell was kicked, instead put that card onto the battlefield tapped" )); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); } private ZukosConviction(final ZukosConviction card) { -- 2.47.2 From caf7a2b8a9caea3b7d6e0587bef21ac128aa5852 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sun, 9 Nov 2025 20:47:27 -0500 Subject: [PATCH 169/261] fix verify --- Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 2a1f684425f..856ccac7134 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -95,7 +95,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Fabled Passage", 57, Rarity.MYTHIC, mage.cards.f.FabledPassage.class)); cards.add(new SetCardInfo("Feed the Swarm", 257, Rarity.COMMON, mage.cards.f.FeedTheSwarm.class)); cards.add(new SetCardInfo("Fervor", 29, Rarity.MYTHIC, mage.cards.f.Fervor.class)); - cards.add(new SetCardInfo("Fevered Visions", 49, Rarity.RARE, mage.cards.f.FeveredVisions.class)); + cards.add(new SetCardInfo("Fevered Visions", 49, Rarity.MYTHIC, mage.cards.f.FeveredVisions.class)); cards.add(new SetCardInfo("Fierce Guardianship", 307, Rarity.RARE, mage.cards.f.FierceGuardianship.class)); cards.add(new SetCardInfo("Fiery Confluence", 165, Rarity.RARE, mage.cards.f.FieryConfluence.class)); cards.add(new SetCardInfo("Fire Nation Ambushers", 229, Rarity.COMMON, mage.cards.f.FireNationAmbushers.class)); @@ -125,7 +125,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Iroh, Dragon of the West", 194, Rarity.RARE, mage.cards.i.IrohDragonOfTheWest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 240, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 282, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Join the Dance", 50, Rarity.UNCOMMON, mage.cards.j.JoinTheDance.class)); + cards.add(new SetCardInfo("Join the Dance", 50, Rarity.MYTHIC, mage.cards.j.JoinTheDance.class)); cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Heroic Healer", 269, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Waterbending Master", 180, Rarity.MYTHIC, mage.cards.k.KataraWaterbendingMaster.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From f0e551dafb480363bcec36d6428e7f5af067ec3f Mon Sep 17 00:00:00 2001 From: ssk97 Date: Sun, 9 Nov 2025 17:47:59 -0800 Subject: [PATCH 170/261] Update damage prevention effects to use preventDamageAction (#14071) --- .../src/mage/cards/a/AcolytesReward.java | 71 ++++--------------- Mage.Sets/src/mage/cards/a/AweStrike.java | 5 +- .../src/mage/cards/b/BattletideAlchemist.java | 29 +++----- .../src/mage/cards/b/BraceForImpact.java | 26 ++----- Mage.Sets/src/mage/cards/c/CallousGiant.java | 7 +- Mage.Sets/src/mage/cards/c/CandlesGlow.java | 38 ++-------- Mage.Sets/src/mage/cards/c/ChannelHarm.java | 5 +- .../src/mage/cards/c/CrumblingSanctuary.java | 22 +++--- Mage.Sets/src/mage/cards/d/DarkSphere.java | 20 +----- .../src/mage/cards/d/DesperateGambit.java | 4 +- Mage.Sets/src/mage/cards/e/EnergyField.java | 16 ----- .../src/mage/cards/g/GideonsIntervention.java | 17 ----- Mage.Sets/src/mage/cards/h/HealingGrace.java | 9 +-- Mage.Sets/src/mage/cards/h/HeartOfLight.java | 18 ++--- Mage.Sets/src/mage/cards/h/HiddenRetreat.java | 6 -- Mage.Sets/src/mage/cards/i/ImmortalCoil.java | 20 ++---- Mage.Sets/src/mage/cards/m/MagebaneArmor.java | 17 ----- Mage.Sets/src/mage/cards/n/NineLives.java | 21 ++---- .../src/mage/cards/p/PersonalSanctuary.java | 16 ----- .../src/mage/cards/p/PhyrexianHydra.java | 25 +++---- .../src/mage/cards/p/ProtectiveSphere.java | 12 ++-- Mage.Sets/src/mage/cards/p/Purity.java | 9 ++- .../src/mage/cards/s/ShieldOfTheAvatar.java | 32 ++------- .../src/mage/cards/s/ShieldmageAdvocate.java | 14 ++-- .../src/mage/cards/s/StonewiseFortifier.java | 24 ------- .../src/mage/cards/s/StormwildCapridor.java | 1 - Mage.Sets/src/mage/cards/t/Temper.java | 50 +++---------- Mage.Sets/src/mage/cards/t/TestOfFaith.java | 39 +++------- .../src/mage/cards/v/VeteranBodyguard.java | 34 +++------ Mage.Sets/src/mage/cards/v/Vigor.java | 52 ++++++-------- Mage.Sets/src/mage/cards/w/WeepingAngel.java | 11 +-- 31 files changed, 156 insertions(+), 514 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AcolytesReward.java b/Mage.Sets/src/mage/cards/a/AcolytesReward.java index 130c6da7ec8..2767bc017a3 100644 --- a/Mage.Sets/src/mage/cards/a/AcolytesReward.java +++ b/Mage.Sets/src/mage/cards/a/AcolytesReward.java @@ -2,16 +2,14 @@ package mage.cards.a; import mage.abilities.Ability; import mage.abilities.dynamicvalue.common.DevotionCount; +import mage.abilities.effects.PreventionEffectData; import mage.abilities.effects.PreventionEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetAnyTarget; @@ -46,16 +44,14 @@ public final class AcolytesReward extends CardImpl { class AcolytesRewardEffect extends PreventionEffectImpl { - protected int amount = 0; AcolytesRewardEffect() { - super(Duration.EndOfTurn); + super(Duration.EndOfTurn, 0, false, true, DevotionCount.W); staticText = "Prevent the next X damage that would be dealt to target creature this turn, where X is your devotion to white. If damage is prevented this way, {this} deals that much damage to any target"; } private AcolytesRewardEffect(final AcolytesRewardEffect effect) { super(effect); - this.amount = effect.amount; } @Override @@ -63,64 +59,25 @@ class AcolytesRewardEffect extends PreventionEffectImpl { return new AcolytesRewardEffect(this); } - @Override - public void init(Ability source, Game game) { - super.init(source, game); - amount = DevotionCount.W.calculate(game, source, this); - } - @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - boolean result = false; - int toPrevent = amount; - if (event.getAmount() < this.amount) { - toPrevent = event.getAmount(); - amount -= event.getAmount(); - } else { - amount = 0; + PreventionEffectData preventionData = preventDamageAction(event, source, game); + if (preventionData.getPreventedDamage() > 0) { + Permanent targetCreature = game.getPermanent(source.getFirstTarget()); + if (targetCreature != null) { + targetCreature.damage(preventionData.getPreventedDamage(), source.getSourceId(), source, game, false, true); + } + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + if (targetCreature != null) { + targetPlayer.damage(preventionData.getPreventedDamage(), source.getSourceId(), source, game, false, true); + } } - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), toPrevent, ((DamageEvent) event).isCombatDamage()); - if (game.replaceEvent(preventEvent)) { - return result; - } - Permanent targetCreature = game.getPermanent(event.getTargetId()); - if (targetCreature == null) { - return result; - } - if (amount == 0) { - this.used = true; - this.discard(); - } - if (event.getAmount() >= toPrevent) { - event.setAmount(event.getAmount() - toPrevent); - } else { - event.setAmount(0); - result = true; - } - if (toPrevent == 0) { - return result; - } - game.informPlayers("Acolyte's Reward prevented " + toPrevent + " to " + targetCreature.getName()); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), toPrevent)); - - Player targetPlayer = game.getPlayer(source.getTargets().get(1).getFirstTarget()); - if (targetPlayer != null) { - targetPlayer.damage(toPrevent, source.getSourceId(), source, game); - game.informPlayers("Acolyte's Reward deals " + toPrevent + " damage to " + targetPlayer.getLogName()); - return result; - } - Permanent targetDamageCreature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (targetDamageCreature == null) { - return result; - } - targetDamageCreature.damage(toPrevent, source.getSourceId(), source, game, false, true); - game.informPlayers("Acolyte's Reward deals " + toPrevent + " damage to " + targetDamageCreature.getName()); - return result; + return false; } @Override public boolean applies(GameEvent event, Ability source, Game game) { - return !this.used && super.applies(event, source, game) && event.getTargetId().equals(source.getFirstTarget()); + return super.applies(event, source, game) && event.getTargetId().equals(source.getFirstTarget()); } } diff --git a/Mage.Sets/src/mage/cards/a/AweStrike.java b/Mage.Sets/src/mage/cards/a/AweStrike.java index fd3e498d7c9..232bda5b053 100755 --- a/Mage.Sets/src/mage/cards/a/AweStrike.java +++ b/Mage.Sets/src/mage/cards/a/AweStrike.java @@ -57,14 +57,13 @@ class AweStrikeEffect extends PreventionEffectImpl { if (player != null) { player.gainLife(preventionData.getPreventedDamage(), game, source); } - this.used = true; this.discard(); - return true; + return false; } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (!this.used && super.applies(event, source, game)) { + if (super.applies(event, source, game)) { Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); return targetCreature != null && targetCreature.getId().equals(event.getSourceId()); } diff --git a/Mage.Sets/src/mage/cards/b/BattletideAlchemist.java b/Mage.Sets/src/mage/cards/b/BattletideAlchemist.java index 779418b1cd0..e7c0020b3fe 100644 --- a/Mage.Sets/src/mage/cards/b/BattletideAlchemist.java +++ b/Mage.Sets/src/mage/cards/b/BattletideAlchemist.java @@ -7,13 +7,13 @@ import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.PreventionEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.players.Player; import java.util.UUID; @@ -46,7 +46,7 @@ public final class BattletideAlchemist extends CardImpl { class BattletideAlchemistEffect extends PreventionEffectImpl { BattletideAlchemistEffect() { - super(Duration.WhileOnBattlefield); + super(Duration.WhileOnBattlefield, 0, false, false, new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.CLERIC, "Clerics"))); this.staticText = "If a source would deal damage to a player, you may prevent X of that damage, where X is the number of Clerics you control"; } @@ -61,27 +61,14 @@ class BattletideAlchemistEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - boolean result = false; Player controller = game.getPlayer(source.getControllerId()); Player targetPlayer = game.getPlayer(event.getTargetId()); if (controller != null && targetPlayer != null) { - int numberOfClericsControlled = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.CLERIC, "Clerics")).calculate(game, source, this); - int toPrevent = Math.min(numberOfClericsControlled, event.getAmount()); - if (toPrevent > 0 && controller.chooseUse(Outcome.PreventDamage, "Prevent " + toPrevent + " damage to " + targetPlayer.getName() + '?', source, game)) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), toPrevent, ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - if (event.getAmount() >= toPrevent) { - event.setAmount(event.getAmount() - toPrevent); - } else { - event.setAmount(0); - result = true; - } - game.informPlayers("Battletide Alchemist prevented " + toPrevent + " damage to " + targetPlayer.getName()); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), toPrevent)); + if (amountToPrevent > 0 && controller.chooseUse(Outcome.PreventDamage, "Prevent " + amountToPrevent + " damage to " + targetPlayer.getName() + '?', source, game)) { + preventDamageAction(event, source, game); } } - } - return result; + return false; } @Override diff --git a/Mage.Sets/src/mage/cards/b/BraceForImpact.java b/Mage.Sets/src/mage/cards/b/BraceForImpact.java index 68e94370dd2..270f1af5ff0 100644 --- a/Mage.Sets/src/mage/cards/b/BraceForImpact.java +++ b/Mage.Sets/src/mage/cards/b/BraceForImpact.java @@ -1,6 +1,7 @@ package mage.cards.b; import mage.abilities.Ability; +import mage.abilities.effects.PreventionEffectData; import mage.abilities.effects.PreventionEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -10,13 +11,9 @@ import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.MulticoloredPredicate; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -67,26 +64,15 @@ class BraceForImpactPreventDamageTargetEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (game.replaceEvent(preventEvent)) { - return false; - } - int prevented; - int damage = event.getAmount(); - event.setAmount(0); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - prevented = damage; - - // add counters now - if (prevented > 0) { + PreventionEffectData preventionEffectData = preventDamageAction(event, source, game); + if (preventionEffectData.getPreventedDamage() > 0) { Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget()); if (targetPermanent != null) { - targetPermanent.addCounters(CounterType.P1P1.createInstance(prevented), source.getControllerId(), source, game); - game.informPlayers("Brace for Impact: Prevented " + prevented + " damage "); - game.informPlayers("Brace for Impact: Adding " + prevented + " +1/+1 counters to " + targetPermanent.getName()); + targetPermanent.addCounters(CounterType.P1P1.createInstance(preventionEffectData.getPreventedDamage()), source.getControllerId(), source, game); } + return false; } - return true; + return false; } @Override diff --git a/Mage.Sets/src/mage/cards/c/CallousGiant.java b/Mage.Sets/src/mage/cards/c/CallousGiant.java index ae5bad00412..1cc430a5560 100644 --- a/Mage.Sets/src/mage/cards/c/CallousGiant.java +++ b/Mage.Sets/src/mage/cards/c/CallousGiant.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -9,12 +8,13 @@ import mage.abilities.effects.PreventionEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.game.Game; import mage.game.events.GameEvent; +import java.util.UUID; + /** * * @author LoneFox @@ -63,7 +63,6 @@ class CallousGiantEffect extends PreventionEffectImpl { if(event.getAmount() <= 3) { preventDamageAction(event, source, game); - return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/c/CandlesGlow.java b/Mage.Sets/src/mage/cards/c/CandlesGlow.java index 789c20daff0..0a33180260d 100644 --- a/Mage.Sets/src/mage/cards/c/CandlesGlow.java +++ b/Mage.Sets/src/mage/cards/c/CandlesGlow.java @@ -1,6 +1,7 @@ package mage.cards.c; import mage.abilities.Ability; +import mage.abilities.effects.PreventionEffectData; import mage.abilities.effects.PreventionEffectImpl; import mage.abilities.keyword.SpliceAbility; import mage.cards.CardImpl; @@ -9,10 +10,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.players.Player; import mage.target.common.TargetAnyTarget; @@ -50,7 +48,7 @@ class CandlesGlowPreventDamageTargetEffect extends PreventionEffectImpl { private int amount = 3; public CandlesGlowPreventDamageTargetEffect(Duration duration) { - super(duration); + super(duration, 3, false); staticText = "Prevent the next 3 damage that would be dealt to any target this turn. You gain life equal to the damage prevented this way"; } @@ -66,39 +64,17 @@ class CandlesGlowPreventDamageTargetEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int prevented; - if (event.getAmount() >= this.amount) { - int damage = amount; - event.setAmount(event.getAmount() - amount); - this.used = true; - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - prevented = damage; - } else { - int damage = event.getAmount(); - event.setAmount(0); - amount -= damage; - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - prevented = damage; - } - - // add live now - if (prevented > 0) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - controller.gainLife(prevented, game, source); - game.informPlayers("Candles' Glow: Prevented " + prevented + " damage "); - game.informPlayers("Candles' Glow: " + controller.getLogName() + " gained " + prevented + "life"); - } - } + PreventionEffectData preventionData = preventDamageAction(event, source, game); + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + player.gainLife(preventionData.getPreventedDamage(), game, source); } return false; } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (!this.used && super.applies(event, source, game)) { + if (super.applies(event, source, game)) { return source.getTargets().getFirstTarget().equals(event.getTargetId()); } return false; diff --git a/Mage.Sets/src/mage/cards/c/ChannelHarm.java b/Mage.Sets/src/mage/cards/c/ChannelHarm.java index 562db66c07d..35755b9db94 100644 --- a/Mage.Sets/src/mage/cards/c/ChannelHarm.java +++ b/Mage.Sets/src/mage/cards/c/ChannelHarm.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.PreventionEffectData; @@ -18,6 +17,8 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author emerald000 @@ -70,7 +71,7 @@ class ChannelHarmEffect extends PreventionEffectImpl { } } } - return true; + return false; } @Override diff --git a/Mage.Sets/src/mage/cards/c/CrumblingSanctuary.java b/Mage.Sets/src/mage/cards/c/CrumblingSanctuary.java index 76cff5e1ca2..184ccc524e7 100644 --- a/Mage.Sets/src/mage/cards/c/CrumblingSanctuary.java +++ b/Mage.Sets/src/mage/cards/c/CrumblingSanctuary.java @@ -1,19 +1,21 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import java.util.UUID; + /** * * @author LoneFox @@ -38,10 +40,10 @@ public final class CrumblingSanctuary extends CardImpl { } } -class CrumblingSanctuaryEffect extends PreventionEffectImpl { +class CrumblingSanctuaryEffect extends ReplacementEffectImpl { CrumblingSanctuaryEffect() { - super(Duration.WhileOnBattlefield, Integer.MAX_VALUE, false, false); + super(Duration.WhileOnBattlefield, Outcome.PreventDamage); staticText = "If damage would be dealt to a player, that player exiles that many cards from the top of their library instead."; } @@ -59,16 +61,18 @@ class CrumblingSanctuaryEffect extends PreventionEffectImpl { int amount = event.getAmount(); Player player = game.getPlayer(event.getTargetId()); if(player != null) { - preventDamageAction(event, source, game); player.moveCards(player.getLibrary().getTopCards(game, amount), Zone.EXILED, source, game); - return true; } - return false; + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; } @Override public boolean applies(GameEvent event, Ability source, Game game) { - return super.applies(event, source, game) && (game.getPlayer(event.getTargetId()) != null); + return true; } - } diff --git a/Mage.Sets/src/mage/cards/d/DarkSphere.java b/Mage.Sets/src/mage/cards/d/DarkSphere.java index e084e635a1a..9ffd6c5f505 100644 --- a/Mage.Sets/src/mage/cards/d/DarkSphere.java +++ b/Mage.Sets/src/mage/cards/d/DarkSphere.java @@ -1,7 +1,6 @@ package mage.cards.d; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; @@ -15,7 +14,6 @@ import mage.filter.FilterSource; import mage.game.Game; import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.players.Player; import java.util.UUID; @@ -65,22 +63,10 @@ class DarkSpherePreventionEffect extends PreventNextDamageFromChosenSourceEffect @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source); DamageEvent damageEvent = (DamageEvent) event; - int damage = damageEvent.getAmount(); - if (controller == null || damage <= 0) { - return false; - } - controller.damage( - (int) Math.ceil(damage / 2.0), damageEvent.getSourceId(), source, game, - damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects() - ); - StringBuilder sb = new StringBuilder(sourceObject != null ? sourceObject.getLogName() : ""); - sb.append(": ").append(damage / 2).append(" damage prevented"); - sb.append(" from ").append(controller.getLogName()); - game.informPlayers(sb.toString()); + amountToPrevent = (int) Math.floor(damageEvent.getAmount() / 2.0); + preventDamageAction(event, source, game); discard(); // only one use - return true; + return false; } } diff --git a/Mage.Sets/src/mage/cards/d/DesperateGambit.java b/Mage.Sets/src/mage/cards/d/DesperateGambit.java index d51e7d978d6..53084581d5f 100644 --- a/Mage.Sets/src/mage/cards/d/DesperateGambit.java +++ b/Mage.Sets/src/mage/cards/d/DesperateGambit.java @@ -110,12 +110,10 @@ class DesperateGambitEffect extends PreventionEffectImpl { if (super.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0) { if (wonFlip) { event.setAmount(CardUtil.overflowMultiply(event.getAmount(), 2)); - this.discard(); } else { preventDamageAction(event, source, game); - this.discard(); - return true; } + this.discard(); } } return false; diff --git a/Mage.Sets/src/mage/cards/e/EnergyField.java b/Mage.Sets/src/mage/cards/e/EnergyField.java index 22955540fbd..d3e3ec3dfb7 100644 --- a/Mage.Sets/src/mage/cards/e/EnergyField.java +++ b/Mage.Sets/src/mage/cards/e/EnergyField.java @@ -10,12 +10,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.TargetController; -import mage.constants.Zone; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import java.util.Objects; import java.util.UUID; @@ -58,18 +54,6 @@ class EnergyFieldEffect extends PreventionEffectImpl { super(effect); } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int damage = event.getAmount(); - event.setAmount(0); - game.informPlayers("Damage has been prevented: " + damage); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - } - return false; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER) { diff --git a/Mage.Sets/src/mage/cards/g/GideonsIntervention.java b/Mage.Sets/src/mage/cards/g/GideonsIntervention.java index c0e02db3487..3e6e91f0681 100644 --- a/Mage.Sets/src/mage/cards/g/GideonsIntervention.java +++ b/Mage.Sets/src/mage/cards/g/GideonsIntervention.java @@ -15,13 +15,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.constants.Zone; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; import mage.util.CardUtil; @@ -118,19 +114,6 @@ class GideonsInterventionPreventAllDamageEffect extends PreventionEffectImpl { public GideonsInterventionPreventAllDamageEffect copy() { return new GideonsInterventionPreventAllDamageEffect(this); } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int damage = event.getAmount(); - event.setAmount(0); - game.informPlayers("Damage has been prevented: " + damage); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - } - return false; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { MageObject object = game.getObject(event.getSourceId()); diff --git a/Mage.Sets/src/mage/cards/h/HealingGrace.java b/Mage.Sets/src/mage/cards/h/HealingGrace.java index 7a98ba94c80..2910fe321e1 100644 --- a/Mage.Sets/src/mage/cards/h/HealingGrace.java +++ b/Mage.Sets/src/mage/cards/h/HealingGrace.java @@ -1,7 +1,6 @@ package mage.cards.h; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.PreventionEffectImpl; import mage.abilities.effects.common.GainLifeEffect; @@ -15,6 +14,8 @@ import mage.game.events.GameEvent; import mage.target.TargetSource; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author TheElk801 @@ -70,12 +71,6 @@ class HealingGraceEffect extends PreventionEffectImpl { } } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - preventDamageAction(event, source, game); - return false; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { if (super.applies(event, source, game)) { diff --git a/Mage.Sets/src/mage/cards/h/HeartOfLight.java b/Mage.Sets/src/mage/cards/h/HeartOfLight.java index a8ec748ad66..b38b66b42ed 100644 --- a/Mage.Sets/src/mage/cards/h/HeartOfLight.java +++ b/Mage.Sets/src/mage/cards/h/HeartOfLight.java @@ -7,12 +7,13 @@ import mage.abilities.effects.common.AttachEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; import mage.game.Game; import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -66,17 +67,6 @@ class HeartOfLightEffect extends PreventionEffectImpl { return new HeartOfLightEffect(this); } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int damage = event.getAmount(); - event.setAmount(0); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - } - return false; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { if (super.applies(event, source, game) && event instanceof DamageEvent) { diff --git a/Mage.Sets/src/mage/cards/h/HiddenRetreat.java b/Mage.Sets/src/mage/cards/h/HiddenRetreat.java index c2e56e51fe5..dc132a96978 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenRetreat.java +++ b/Mage.Sets/src/mage/cards/h/HiddenRetreat.java @@ -8,7 +8,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.DamageEvent; @@ -58,11 +57,6 @@ class HiddenRetreatEffect extends PreventionEffectImpl { return new HiddenRetreatEffect(this); } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { return (super.applies(event, source, game) diff --git a/Mage.Sets/src/mage/cards/i/ImmortalCoil.java b/Mage.Sets/src/mage/cards/i/ImmortalCoil.java index 60a13afacb5..f79ef75b715 100644 --- a/Mage.Sets/src/mage/cards/i/ImmortalCoil.java +++ b/Mage.Sets/src/mage/cards/i/ImmortalCoil.java @@ -6,6 +6,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.ExileFromGraveCost; import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.PreventionEffectData; import mage.abilities.effects.PreventionEffectImpl; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseGameSourceControllerEffect; @@ -17,10 +18,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; @@ -102,24 +100,14 @@ class ImmortalCoilPreventionEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - if (game.replaceEvent(new PreventDamageEvent( - event.getTargetId(), source.getSourceId(), source, source.getControllerId(), - event.getAmount(), ((DamageEvent) event).isCombatDamage() - ))) { - return false; - } - int damage = event.getAmount(); + PreventionEffectData preventionEffectData = preventDamageAction(event, source, game); Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(Math.min(damage, player.getGraveyard().size()), StaticFilters.FILTER_CARD); + if (player != null && preventionEffectData.getPreventedDamage() > 0) { + TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(Math.min(preventionEffectData.getPreventedDamage(), player.getGraveyard().size()), StaticFilters.FILTER_CARD); target.withNotTarget(true); player.choose(outcome, target, source, game); player.moveCards(new CardsImpl(target.getTargets()), Zone.EXILED, source, game); } - event.setAmount(0); - game.fireEvent(new PreventedDamageEvent( - event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage - )); return false; } diff --git a/Mage.Sets/src/mage/cards/m/MagebaneArmor.java b/Mage.Sets/src/mage/cards/m/MagebaneArmor.java index a34fa10a68d..fdd45252d5f 100644 --- a/Mage.Sets/src/mage/cards/m/MagebaneArmor.java +++ b/Mage.Sets/src/mage/cards/m/MagebaneArmor.java @@ -15,8 +15,6 @@ import mage.constants.*; import mage.game.Game; import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; import java.util.UUID; @@ -86,21 +84,6 @@ class MagebaneArmorPreventionEffect extends PreventionEffectImpl { return new MagebaneArmorPreventionEffect(this); } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent equipment = game.getPermanent(source.getSourceId()); - if (equipment != null && equipment.getAttachedTo() != null) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int damage = event.getAmount(); - event.setAmount(0); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - return true; - } - } - return false; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { if (super.applies(event, source, game) && !((DamageEvent) event).isCombatDamage()) { diff --git a/Mage.Sets/src/mage/cards/n/NineLives.java b/Mage.Sets/src/mage/cards/n/NineLives.java index 01257dac79c..9a8a37106be 100644 --- a/Mage.Sets/src/mage/cards/n/NineLives.java +++ b/Mage.Sets/src/mage/cards/n/NineLives.java @@ -15,12 +15,8 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; -import mage.players.Player; import java.util.UUID; @@ -74,20 +70,11 @@ class NineLivesPreventionEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int damage = event.getAmount(); - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - Permanent nineLives = source.getSourcePermanentIfItStillExists(game); - if (nineLives != null) { - nineLives.addCounters(CounterType.INCARNATION.createInstance(1), source.getControllerId(), source, game); - } - } - event.setAmount(0); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); + Permanent nineLives = source.getSourcePermanentIfItStillExists(game); + if (nineLives != null) { + nineLives.addCounters(CounterType.INCARNATION.createInstance(1), source.getControllerId(), source, game); } - return false; + return super.replaceEvent(event, source, game); } @Override diff --git a/Mage.Sets/src/mage/cards/p/PersonalSanctuary.java b/Mage.Sets/src/mage/cards/p/PersonalSanctuary.java index 6dc513854e7..2798dd1edfa 100644 --- a/Mage.Sets/src/mage/cards/p/PersonalSanctuary.java +++ b/Mage.Sets/src/mage/cards/p/PersonalSanctuary.java @@ -7,12 +7,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import java.util.UUID; @@ -50,18 +46,6 @@ class PersonalSanctuaryEffect extends PreventionEffectImpl { super(effect); } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int damage = event.getAmount(); - event.setAmount(0); - game.informPlayers("Damage has been prevented: " + damage); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - } - return false; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER) { diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianHydra.java b/Mage.Sets/src/mage/cards/p/PhyrexianHydra.java index e5007931682..7b1ca32472f 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianHydra.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianHydra.java @@ -3,6 +3,7 @@ package mage.cards.p; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.PreventionEffectData; import mage.abilities.effects.PreventionEffectImpl; import mage.abilities.keyword.InfectAbility; import mage.cards.CardImpl; @@ -10,13 +11,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; import java.util.UUID; @@ -67,19 +64,15 @@ class PhyrexianHydraEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - boolean retValue = false; - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - int damage = event.getAmount(); - if (!game.replaceEvent(preventEvent)) { - event.setAmount(0); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - retValue = true; + PreventionEffectData preventionEffectData = preventDamageAction(event, source, game); + if (preventionEffectData.getPreventedDamage() > 0) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + permanent.addCounters(CounterType.M1M1.createInstance(preventionEffectData.getPreventedDamage()), source.getControllerId(), source, game); + } + return false; } - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.addCounters(CounterType.M1M1.createInstance(damage), source.getControllerId(), source, game); - } - return retValue; + return false; } @Override diff --git a/Mage.Sets/src/mage/cards/p/ProtectiveSphere.java b/Mage.Sets/src/mage/cards/p/ProtectiveSphere.java index 215d66ae3d5..99bff0ea685 100644 --- a/Mage.Sets/src/mage/cards/p/ProtectiveSphere.java +++ b/Mage.Sets/src/mage/cards/p/ProtectiveSphere.java @@ -1,9 +1,6 @@ package mage.cards.p; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.Mana; import mage.ObjectColor; import mage.abilities.Ability; @@ -23,6 +20,10 @@ import mage.players.Player; import mage.target.TargetSource; import mage.util.CardUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** * * @author jeffwadsworth @@ -92,11 +93,6 @@ class ProtectiveSphereEffect extends PreventionEffectImpl { this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game); } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - return true; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { manaUsed = (Mana) game.getState().getValue("ProtectiveSphere" + source.getSourceId().toString()); diff --git a/Mage.Sets/src/mage/cards/p/Purity.java b/Mage.Sets/src/mage/cards/p/Purity.java index 70aab97b5fc..602024da32d 100644 --- a/Mage.Sets/src/mage/cards/p/Purity.java +++ b/Mage.Sets/src/mage/cards/p/Purity.java @@ -1,7 +1,6 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.PutIntoGraveFromAnywhereSourceTriggeredAbility; @@ -13,14 +12,15 @@ import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.game.Game; import mage.game.events.DamageEvent; import mage.game.events.GameEvent; import mage.players.Player; +import java.util.UUID; + /** * * @author Pete Rossi @@ -73,8 +73,7 @@ class PurityEffect extends PreventionEffectImpl { if (player != null) { player.gainLife(preventionData.getPreventedDamage(), game, source); } - - return true; + return false; } @Override diff --git a/Mage.Sets/src/mage/cards/s/ShieldOfTheAvatar.java b/Mage.Sets/src/mage/cards/s/ShieldOfTheAvatar.java index 3930bb4f6ec..e8442b280b1 100644 --- a/Mage.Sets/src/mage/cards/s/ShieldOfTheAvatar.java +++ b/Mage.Sets/src/mage/cards/s/ShieldOfTheAvatar.java @@ -9,12 +9,12 @@ import mage.abilities.hint.common.CreaturesYouControlHint; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; import java.util.UUID; @@ -50,7 +50,7 @@ public final class ShieldOfTheAvatar extends CardImpl { class ShieldOfTheAvatarPreventionEffect extends PreventionEffectImpl { ShieldOfTheAvatarPreventionEffect() { - super(Duration.WhileOnBattlefield); + super(Duration.WhileOnBattlefield, 0, false, false); this.staticText = "If a source would deal damage to equipped creature, prevent X of that damage, where X is the number of creatures you control."; } @@ -65,26 +65,8 @@ class ShieldOfTheAvatarPreventionEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - boolean result = false; - Permanent equipment = game.getPermanent(source.getSourceId()); - if (equipment != null && equipment.getAttachedTo() != null) { - int numberOfCreaturesControlled = CreaturesYouControlCount.PLURAL.calculate(game, source, this); - int toPrevent = Math.min(numberOfCreaturesControlled, event.getAmount()); - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), toPrevent, ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - if (event.getAmount() >= toPrevent) { - event.setAmount(event.getAmount() - toPrevent); - } else { - event.setAmount(0); - result = true; - } - if (toPrevent > 0) { - game.informPlayers("Shield of the Avatar " + "prevented " + toPrevent + " damage to " + game.getPermanent(equipment.getAttachedTo()).getName()); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), toPrevent)); - } - } - } - return result; + amountToPrevent = CreaturesYouControlCount.PLURAL.calculate(game, source, this); + return super.replaceEvent(event, source, game); } @Override diff --git a/Mage.Sets/src/mage/cards/s/ShieldmageAdvocate.java b/Mage.Sets/src/mage/cards/s/ShieldmageAdvocate.java index 5292792f6ef..5fcfe39ab60 100644 --- a/Mage.Sets/src/mage/cards/s/ShieldmageAdvocate.java +++ b/Mage.Sets/src/mage/cards/s/ShieldmageAdvocate.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -13,17 +12,18 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.SubType; import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.FilterCard; import mage.game.Game; import mage.game.events.GameEvent; import mage.target.TargetSource; -import mage.target.common.TargetCardInOpponentsGraveyard; import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetCardInOpponentsGraveyard; import mage.target.targetpointer.SecondTargetPointer; +import java.util.UUID; + /** * * @author L_J @@ -86,12 +86,6 @@ class ShieldmageAdvocateEffect extends PreventionEffectImpl { this.targetSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game); } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - preventDamageAction(event, source, game); - return false; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { if (super.applies(event, source, game)) { diff --git a/Mage.Sets/src/mage/cards/s/StonewiseFortifier.java b/Mage.Sets/src/mage/cards/s/StonewiseFortifier.java index e9efff07687..31bf8824c71 100644 --- a/Mage.Sets/src/mage/cards/s/StonewiseFortifier.java +++ b/Mage.Sets/src/mage/cards/s/StonewiseFortifier.java @@ -1,7 +1,6 @@ package mage.cards.s; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -11,12 +10,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -66,25 +61,6 @@ class StonewiseFortifierPreventAllDamageToEffect extends PreventionEffectImpl { return new StonewiseFortifierPreventAllDamageToEffect(this); } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), event.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int preventedDamage = event.getAmount(); - MageObject damageSource = game.getObject(event.getSourceId()); - MageObject preventionSource = game.getObject(source); - if (damageSource != null && preventionSource != null) { - String message = " damage from " + - damageSource.getName() + " prevented " + - '(' + preventionSource + ')'; - game.informPlayers(message); - } - event.setAmount(0); - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), preventedDamage)); - } - return false; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { if (super.applies(event, source, game) && event.getTargetId().equals(source.getSourceId())) { diff --git a/Mage.Sets/src/mage/cards/s/StormwildCapridor.java b/Mage.Sets/src/mage/cards/s/StormwildCapridor.java index edc2d3bf2fa..f3cb1458854 100644 --- a/Mage.Sets/src/mage/cards/s/StormwildCapridor.java +++ b/Mage.Sets/src/mage/cards/s/StormwildCapridor.java @@ -75,7 +75,6 @@ class StormwildCapridorEffect extends PreventionEffectImpl { if (permanent != null) { permanent.addCounters(CounterType.P1P1.createInstance(preventionEffectData.getPreventedDamage()), source.getControllerId(), source, game); } - return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/t/Temper.java b/Mage.Sets/src/mage/cards/t/Temper.java index 56e84ea56ba..8d70ed167a3 100644 --- a/Mage.Sets/src/mage/cards/t/Temper.java +++ b/Mage.Sets/src/mage/cards/t/Temper.java @@ -3,6 +3,7 @@ package mage.cards.t; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.GetXValue; +import mage.abilities.effects.PreventionEffectData; import mage.abilities.effects.PreventionEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -10,10 +11,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.counters.CounterType; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; @@ -44,22 +42,13 @@ public final class Temper extends CardImpl { class TemperPreventDamageTargetEffect extends PreventionEffectImpl { - private int amount; - private final DynamicValue dVal; - private boolean initialized; - public TemperPreventDamageTargetEffect(DynamicValue dVal, Duration duration) { - super(duration); - this.initialized = false; - this.dVal = dVal; + super(duration, 0, false, true, dVal); staticText = "Prevent the next X damage that would be dealt to target creature this turn. For each 1 damage prevented this way, put a +1/+1 counter on that creature"; } private TemperPreventDamageTargetEffect(final TemperPreventDamageTargetEffect effect) { super(effect); - this.amount = effect.amount; - this.dVal = effect.dVal; - this.initialized = effect.initialized; } @Override @@ -69,36 +58,13 @@ class TemperPreventDamageTargetEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - if (!initialized) { - amount = dVal.calculate(game, source, this); - initialized = true; - } - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int prevented = 0; - if (event.getAmount() >= this.amount) { - int damage = amount; - event.setAmount(event.getAmount() - amount); - this.used = true; - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - prevented = damage; - } else { - int damage = event.getAmount(); - event.setAmount(0); - amount -= damage; - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - prevented = damage; - } - - // add counters now - if (prevented > 0) { - Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget()); - if (targetPermanent != null) { - targetPermanent.addCounters(CounterType.P1P1.createInstance(prevented), source.getControllerId(), source, game); - game.informPlayers("Temper: Prevented " + prevented + " damage "); - game.informPlayers("Temper: Adding " + prevented + " +1/+1 counters to " + targetPermanent.getName()); - } + PreventionEffectData preventionEffectData = preventDamageAction(event, source, game); + if (preventionEffectData.getPreventedDamage() > 0) { + Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget()); + if (targetPermanent != null) { + targetPermanent.addCounters(CounterType.P1P1.createInstance(preventionEffectData.getPreventedDamage()), source.getControllerId(), source, game); } + return false; } return false; } diff --git a/Mage.Sets/src/mage/cards/t/TestOfFaith.java b/Mage.Sets/src/mage/cards/t/TestOfFaith.java index 067582d4dba..7412087c1c2 100644 --- a/Mage.Sets/src/mage/cards/t/TestOfFaith.java +++ b/Mage.Sets/src/mage/cards/t/TestOfFaith.java @@ -1,6 +1,7 @@ package mage.cards.t; import mage.abilities.Ability; +import mage.abilities.effects.PreventionEffectData; import mage.abilities.effects.PreventionEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -8,10 +9,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.counters.CounterType; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; @@ -42,16 +40,14 @@ public final class TestOfFaith extends CardImpl { class TestOfFaithPreventDamageTargetEffect extends PreventionEffectImpl { - private int amount = 3; public TestOfFaithPreventDamageTargetEffect(Duration duration) { - super(duration); + super(duration, 3, false); staticText = "Prevent the next 3 damage that would be dealt to target creature this turn. For each 1 damage prevented this way, put a +1/+1 counter on that creature"; } private TestOfFaithPreventDamageTargetEffect(final TestOfFaithPreventDamageTargetEffect effect) { super(effect); - this.amount = effect.amount; } @Override @@ -61,32 +57,13 @@ class TestOfFaithPreventDamageTargetEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int prevented = 0; - if (event.getAmount() >= this.amount) { - int damage = amount; - event.setAmount(event.getAmount() - amount); - this.used = true; - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - prevented = damage; - } else { - int damage = event.getAmount(); - event.setAmount(0); - amount -= damage; - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage)); - prevented = damage; - } - - // add counters now - if (prevented > 0) { - Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget()); - if (targetPermanent != null) { - targetPermanent.addCounters(CounterType.P1P1.createInstance(prevented), source.getControllerId(), source, game); - game.informPlayers("Test of Faith: Prevented " + prevented + " damage "); - game.informPlayers("Test of Faith: Adding " + prevented + " +1/+1 counters to " + targetPermanent.getName()); - } + PreventionEffectData preventionEffectData = preventDamageAction(event, source, game); + if (preventionEffectData.getPreventedDamage() > 0) { + Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget()); + if (targetPermanent != null) { + targetPermanent.addCounters(CounterType.P1P1.createInstance(preventionEffectData.getPreventedDamage()), source.getControllerId(), source, game); } + return false; } return false; } diff --git a/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java b/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java index 9acde8cdb6b..e5e88550434 100644 --- a/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java +++ b/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java @@ -4,21 +4,20 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SourceTappedCondition; -import mage.abilities.decorator.ConditionalPreventionEffect; -import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.decorator.ConditionalReplacementEffect; +import mage.abilities.effects.RedirectionEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.UnblockedPredicate; import mage.game.Game; import mage.game.events.DamageEvent; -import mage.game.events.DamagePlayerEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -35,10 +34,8 @@ public final class VeteranBodyguard extends CardImpl { this.toughness = new MageInt(5); // As long as Veteran Bodyguard is untapped, all damage that would be dealt to you by unblocked creatures is dealt to Veteran Bodyguard instead. - this.addAbility(new SimpleStaticAbility(new ConditionalPreventionEffect( - new VeteranBodyguardEffect(), - SourceTappedCondition.UNTAPPED, - "As long as {this} is untapped, all damage that would be dealt to you by unblocked creatures is dealt to {this} instead." + this.addAbility(new SimpleStaticAbility(new ConditionalReplacementEffect(new VeteranBodyguardEffect(), SourceTappedCondition.UNTAPPED) + .setText("As long as {this} is untapped, all damage that would be dealt to you by unblocked creatures is dealt to {this} instead." ))); } @@ -52,7 +49,7 @@ public final class VeteranBodyguard extends CardImpl { } } -class VeteranBodyguardEffect extends PreventionEffectImpl { +class VeteranBodyguardEffect extends RedirectionEffect { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked creatures"); @@ -69,22 +66,6 @@ class VeteranBodyguardEffect extends PreventionEffectImpl { super(effect); } - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - DamagePlayerEvent damageEvent = (DamagePlayerEvent) event; - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.damage(damageEvent.getAmount(), event.getSourceId(), source, game, damageEvent.isCombatDamage(), damageEvent.isPreventable()); - return true; - } - return false; - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; - } - @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getPlayerId().equals(source.getControllerId()) @@ -93,6 +74,9 @@ class VeteranBodyguardEffect extends PreventionEffectImpl { if (p != null) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { if (event.getSourceId().equals(permanent.getId())) { + TargetPermanent target = new TargetPermanent(); + target.add(source.getSourceId(), game); + this.redirectTarget = target; return true; } } diff --git a/Mage.Sets/src/mage/cards/v/Vigor.java b/Mage.Sets/src/mage/cards/v/Vigor.java index 8a654c5c59b..7b57cb6a3b9 100644 --- a/Mage.Sets/src/mage/cards/v/Vigor.java +++ b/Mage.Sets/src/mage/cards/v/Vigor.java @@ -4,18 +4,18 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.PutIntoGraveFromAnywhereSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.PreventionEffectData; +import mage.abilities.effects.PreventionEffectImpl; import mage.abilities.effects.common.ShuffleIntoLibrarySourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import mage.counters.CounterType; import mage.game.Game; -import mage.game.events.DamageEvent; import mage.game.events.GameEvent; -import mage.game.events.PreventDamageEvent; -import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; import java.util.UUID; @@ -37,7 +37,7 @@ public final class Vigor extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // If damage would be dealt to a creature you control other than Vigor, prevent that damage. Put a +1/+1 counter on that creature for each 1 damage prevented this way. - this.addAbility(new SimpleStaticAbility(new VigorReplacementEffect())); + this.addAbility(new SimpleStaticAbility(new VigorEffect())); // When Vigor is put into a graveyard from anywhere, shuffle it into its owner's library. this.addAbility(new PutIntoGraveFromAnywhereSourceTriggeredAbility(new ShuffleIntoLibrarySourceEffect())); @@ -53,36 +53,34 @@ public final class Vigor extends CardImpl { } } -class VigorReplacementEffect extends ReplacementEffectImpl { +class VigorEffect extends PreventionEffectImpl { - VigorReplacementEffect() { - super(Duration.WhileOnBattlefield, Outcome.BoostCreature); + VigorEffect() { + super(Duration.WhileOnBattlefield); staticText = "if damage would be dealt to another creature you control, prevent that damage. Put a +1/+1 counter on that creature for each 1 damage prevented this way"; + } - private VigorReplacementEffect(final VigorReplacementEffect effect) { + private VigorEffect(final VigorEffect effect) { super(effect); } @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage()); - if (!game.replaceEvent(preventEvent)) { - int preventedDamage = event.getAmount(); - event.setAmount(0); - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null) { - permanent.addCounters(CounterType.P1P1.createInstance(preventedDamage), source.getControllerId(), source, game); - } - game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), preventedDamage)); - return true; - } - return false; + public VigorEffect copy() { + return new VigorEffect(this); } @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGE_PERMANENT; + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + PreventionEffectData preventionEffectData = preventDamageAction(event, source, game); + if (preventionEffectData.getPreventedDamage() > 0) { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent != null) { + permanent.addCounters(CounterType.P1P1.createInstance(preventionEffectData.getPreventedDamage()), source.getControllerId(), source, game); + } + return false; + } + return false; } @Override @@ -94,8 +92,4 @@ class VigorReplacementEffect extends ReplacementEffectImpl { && !event.getTargetId().equals(source.getSourceId()); } - @Override - public VigorReplacementEffect copy() { - return new VigorReplacementEffect(this); - } } diff --git a/Mage.Sets/src/mage/cards/w/WeepingAngel.java b/Mage.Sets/src/mage/cards/w/WeepingAngel.java index 45623b0f5ea..664704822c0 100644 --- a/Mage.Sets/src/mage/cards/w/WeepingAngel.java +++ b/Mage.Sets/src/mage/cards/w/WeepingAngel.java @@ -1,19 +1,18 @@ package mage.cards.w; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.PreventionEffectImpl; -import mage.cards.Card; -import mage.constants.*; -import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.VigilanceAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.DamagePermanentEvent; @@ -21,6 +20,8 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.UUID; + /** * * @author jimga150 @@ -129,7 +130,7 @@ class WeepingAngelDamageEffect extends PreventionEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - game.preventDamage(event, source, game, Integer.MAX_VALUE); + preventDamageAction(event, source, game); Card card = game.getPermanent(event.getTargetId()); if (card == null) { return false; -- 2.47.2 From 066fb6dd464f579a41d33559788eff97c34c33f9 Mon Sep 17 00:00:00 2001 From: Steven Knipe Date: Fri, 31 Oct 2025 23:30:40 -0700 Subject: [PATCH 171/261] implement Sacred Boon and Scars of the Veteran --- Mage.Sets/src/mage/cards/s/SacredBoon.java | 83 ++++++++++++++++ .../src/mage/cards/s/ScarsOfTheVeteran.java | 99 +++++++++++++++++++ Mage.Sets/src/mage/sets/Alliances.java | 1 + Mage.Sets/src/mage/sets/FifthEdition.java | 1 + Mage.Sets/src/mage/sets/IceAge.java | 1 + Mage.Sets/src/mage/sets/MastersEditionII.java | 2 + .../replacement/prevent/SacredBoonTest.java | 62 ++++++++++++ .../base/impl/CardTestPlayerAPIImpl.java | 2 +- 8 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/s/SacredBoon.java create mode 100644 Mage.Sets/src/mage/cards/s/ScarsOfTheVeteran.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/SacredBoonTest.java diff --git a/Mage.Sets/src/mage/cards/s/SacredBoon.java b/Mage.Sets/src/mage/cards/s/SacredBoon.java new file mode 100644 index 00000000000..d0d119952d5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SacredBoon.java @@ -0,0 +1,83 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.PreventionEffectData; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * + * @author notgreat + */ +public final class SacredBoon extends CardImpl { + + public SacredBoon(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); + + // Prevent the next 3 damage that would be dealt to target creature this turn. At the beginning of the next end step, put a +0/+1 counter on that creature for each 1 damage prevented this way. + this.getSpellAbility().addEffect(new SacredBoonPreventDamageTargetEffect(Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private SacredBoon(final SacredBoon card) { + super(card); + } + + @Override + public SacredBoon copy() { + return new SacredBoon(this); + } +} + +class SacredBoonPreventDamageTargetEffect extends PreventionEffectImpl { + + + SacredBoonPreventDamageTargetEffect(Duration duration) { + super(duration, 3, false); + staticText = "Prevent the next 3 damage that would be dealt to target creature this turn. At the beginning of the next end step, put a +0/+1 counter on that creature for each 1 damage prevented this way."; + } + + private SacredBoonPreventDamageTargetEffect(final SacredBoonPreventDamageTargetEffect effect) { + super(effect); + } + + @Override + public SacredBoonPreventDamageTargetEffect copy() { + return new SacredBoonPreventDamageTargetEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + PreventionEffectData preventionEffectData = preventDamageAction(event, source, game); + if (preventionEffectData.getPreventedDamage() > 0) { + Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget()); + if (targetPermanent != null) { + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + new AddCountersTargetEffect(CounterType.P0P1.createInstance(preventionEffectData.getPreventedDamage())) + .setTargetPointer(new FixedTarget(targetPermanent, game))); + game.addDelayedTriggeredAbility(delayedAbility, source); + } + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return super.applies(event, source, game) && source.getTargets().getFirstTarget().equals(event.getTargetId()); + } + +} diff --git a/Mage.Sets/src/mage/cards/s/ScarsOfTheVeteran.java b/Mage.Sets/src/mage/cards/s/ScarsOfTheVeteran.java new file mode 100644 index 00000000000..3ddecf5249f --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScarsOfTheVeteran.java @@ -0,0 +1,99 @@ +package mage.cards.s; + +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.costs.AlternativeCostSourceAbility; +import mage.abilities.costs.common.ExileFromHandCost; +import mage.abilities.effects.PreventionEffectData; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.counters.CounterType; +import mage.filter.common.FilterOwnedCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetCardInHand; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * + * @author notgreat + */ +public final class ScarsOfTheVeteran extends CardImpl { + + private static final FilterOwnedCard filter + = new FilterOwnedCard("a white card from your hand"); + + static { + filter.add(new ColorPredicate(ObjectColor.WHITE)); + } + public ScarsOfTheVeteran(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{W}"); + + + // You may exile a white card from your hand rather than pay Scars of the Veteran's mana cost. + this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter)))); + + // Prevent the next 7 damage that would be dealt to any target this turn. If it’s a creature, put a +0/+1 counter on it for each 1 damage prevented this way at the beginning of the next end step. + this.getSpellAbility().addEffect(new ScarsOfTheVeteranPreventDamageTargetEffect(Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetAnyTarget()); + } + + private ScarsOfTheVeteran(final ScarsOfTheVeteran card) { + super(card); + } + + @Override + public ScarsOfTheVeteran copy() { + return new ScarsOfTheVeteran(this); + } +} + +class ScarsOfTheVeteranPreventDamageTargetEffect extends PreventionEffectImpl { + + ScarsOfTheVeteranPreventDamageTargetEffect(Duration duration) { + super(duration, 7, false); + staticText = "Prevent the next 7 damage that would be dealt to any target this turn. If it's a creature, put a +0/+1 counter on it for each 1 damage prevented this way at the beginning of the next end step."; + } + + private ScarsOfTheVeteranPreventDamageTargetEffect(final ScarsOfTheVeteranPreventDamageTargetEffect effect) { + super(effect); + } + + @Override + public ScarsOfTheVeteranPreventDamageTargetEffect copy() { + return new ScarsOfTheVeteranPreventDamageTargetEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + PreventionEffectData preventionEffectData = preventDamageAction(event, source, game); + if (preventionEffectData.getPreventedDamage() > 0) { + Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget()); + if (targetPermanent != null) { + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + new AddCountersTargetEffect(CounterType.P0P1.createInstance(preventionEffectData.getPreventedDamage())) + .setTargetPointer(new FixedTarget(targetPermanent, game))); + game.addDelayedTriggeredAbility(delayedAbility, source); + } + return false; + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return super.applies(event, source, game) && source.getTargets().getFirstTarget().equals(event.getTargetId()); + } + +} diff --git a/Mage.Sets/src/mage/sets/Alliances.java b/Mage.Sets/src/mage/sets/Alliances.java index 1509e7431c6..b01c236c242 100644 --- a/Mage.Sets/src/mage/sets/Alliances.java +++ b/Mage.Sets/src/mage/sets/Alliances.java @@ -158,6 +158,7 @@ public final class Alliances extends ExpansionSet { cards.add(new SetCardInfo("Royal Herbalist", "15a", Rarity.COMMON, mage.cards.r.RoyalHerbalist.class, RETRO_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Royal Herbalist", "15b", Rarity.COMMON, mage.cards.r.RoyalHerbalist.class, RETRO_ART_USE_VARIOUS)); cards.add(new SetCardInfo("Scarab of the Unseen", 128, Rarity.UNCOMMON, mage.cards.s.ScarabOfTheUnseen.class, RETRO_ART)); + cards.add(new SetCardInfo("Scars of the Veteran", 16, Rarity.UNCOMMON, mage.cards.s.ScarsOfTheVeteran.class, RETRO_ART)); cards.add(new SetCardInfo("School of the Unseen", 141, Rarity.UNCOMMON, mage.cards.s.SchoolOfTheUnseen.class, RETRO_ART)); cards.add(new SetCardInfo("Seasoned Tactician", 17, Rarity.UNCOMMON, mage.cards.s.SeasonedTactician.class, RETRO_ART)); cards.add(new SetCardInfo("Sheltered Valley", 142, Rarity.RARE, mage.cards.s.ShelteredValley.class, RETRO_ART)); diff --git a/Mage.Sets/src/mage/sets/FifthEdition.java b/Mage.Sets/src/mage/sets/FifthEdition.java index 811e772d46f..b8dd090e74a 100644 --- a/Mage.Sets/src/mage/sets/FifthEdition.java +++ b/Mage.Sets/src/mage/sets/FifthEdition.java @@ -367,6 +367,7 @@ public final class FifthEdition extends ExpansionSet { cards.add(new SetCardInfo("Rod of Ruin", 396, Rarity.UNCOMMON, mage.cards.r.RodOfRuin.class, RETRO_ART)); cards.add(new SetCardInfo("Ruins of Trokair", 422, Rarity.UNCOMMON, mage.cards.r.RuinsOfTrokair.class, RETRO_ART)); cards.add(new SetCardInfo("Sabretooth Tiger", 264, Rarity.COMMON, mage.cards.s.SabretoothTiger.class, RETRO_ART)); + cards.add(new SetCardInfo("Sacred Boon", 57, Rarity.UNCOMMON, mage.cards.s.SacredBoon.class, RETRO_ART)); cards.add(new SetCardInfo("Samite Healer", 58, Rarity.COMMON, mage.cards.s.SamiteHealer.class, RETRO_ART)); cards.add(new SetCardInfo("Sand Silos", 423, Rarity.RARE, mage.cards.s.SandSilos.class, RETRO_ART)); cards.add(new SetCardInfo("Scaled Wurm", 322, Rarity.COMMON, mage.cards.s.ScaledWurm.class, RETRO_ART)); diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index 93e4cdab640..fce20decb6b 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -300,6 +300,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("River Delta", 359, Rarity.RARE, mage.cards.r.RiverDelta.class, RETRO_ART)); cards.add(new SetCardInfo("Runed Arch", 334, Rarity.RARE, mage.cards.r.RunedArch.class, RETRO_ART)); cards.add(new SetCardInfo("Sabretooth Tiger", 215, Rarity.COMMON, mage.cards.s.SabretoothTiger.class, RETRO_ART)); + cards.add(new SetCardInfo("Sacred Boon", 50, Rarity.UNCOMMON, mage.cards.s.SacredBoon.class, RETRO_ART)); cards.add(new SetCardInfo("Scaled Wurm", 262, Rarity.COMMON, mage.cards.s.ScaledWurm.class, RETRO_ART)); cards.add(new SetCardInfo("Sea Spirit", 95, Rarity.UNCOMMON, mage.cards.s.SeaSpirit.class, RETRO_ART)); cards.add(new SetCardInfo("Seizures", 159, Rarity.COMMON, mage.cards.s.Seizures.class, RETRO_ART)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index 6ebaf10aca6..ff253d5dd56 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -205,7 +205,9 @@ public final class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Royal Decree", 31, Rarity.RARE, mage.cards.r.RoyalDecree.class, RETRO_ART)); cards.add(new SetCardInfo("Royal Trooper", 32, Rarity.COMMON, mage.cards.r.RoyalTrooper.class, RETRO_ART)); cards.add(new SetCardInfo("Ruins of Trokair", 234, Rarity.UNCOMMON, mage.cards.r.RuinsOfTrokair.class, RETRO_ART)); + cards.add(new SetCardInfo("Sacred Boon", 33, Rarity.UNCOMMON, mage.cards.s.SacredBoon.class, RETRO_ART)); cards.add(new SetCardInfo("Savannah", 235, Rarity.RARE, mage.cards.s.Savannah.class, new CardGraphicInfo(FrameStyle.LEA_ORIGINAL_DUAL_LAND_ART_BASIC, false))); + cards.add(new SetCardInfo("Scars of the Veteran", 34, Rarity.RARE, mage.cards.s.ScarsOfTheVeteran.class, RETRO_ART)); cards.add(new SetCardInfo("Screeching Drake", 63, Rarity.COMMON, mage.cards.s.ScreechingDrake.class, RETRO_ART)); cards.add(new SetCardInfo("Sea Drake", 64, Rarity.RARE, mage.cards.s.SeaDrake.class, RETRO_ART)); cards.add(new SetCardInfo("Sea Spirit", 65, Rarity.UNCOMMON, mage.cards.s.SeaSpirit.class, RETRO_ART)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/SacredBoonTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/SacredBoonTest.java new file mode 100644 index 00000000000..4e384225b0b --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/SacredBoonTest.java @@ -0,0 +1,62 @@ + +package org.mage.test.cards.replacement.prevent; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author notgreat + */ + +public class SacredBoonTest extends CardTestPlayerBase { + + @Test + public void testSacredBoonBigDamage() { + setStrictChooseMode(true); + + addCard(Zone.HAND, playerA, "Sacred Boon"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + addCard(Zone.HAND, playerB, "Bombard"); + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacred Boon", "Silvercoat Lion"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Bombard", "Silvercoat Lion"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + assertDamageReceived(playerA, "Silvercoat Lion", 1); + assertPowerToughness(playerA, "Silvercoat Lion", 2, 5); + } + + @Test + public void testSacredBoonSmallDamage() { + setStrictChooseMode(true); + + addCard(Zone.HAND, playerA, "Sacred Boon"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + addCard(Zone.HAND, playerB, "Scattershot"); + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacred Boon", "Silvercoat Lion"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Scattershot", "Silvercoat Lion"); + setChoice(playerB, false); // don't change scattershot targets + setChoice(playerA, "At the"); // stack triggers - technically incorrect, should be a single trigger + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + assertDamageReceived(playerA, "Silvercoat Lion", 0); + assertPowerToughness(playerA, "Silvercoat Lion", 2, 4); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index 4d910579aca..3a849814cb5 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -2037,7 +2037,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement * multiple targets can be seperated by ^; * no target marks as TestPlayer.NO_TARGET; * warning, do not support cards with target adjusters - use addTarget instead - * @param waitStackResolved if true, wait for stack to resolve + * @param waitStackResolved if true, wait for stack to resolve before continuing */ public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, String targetName, boolean waitStackResolved) { castSpell(turnNum, step, player, cardName, targetName); -- 2.47.2 From d785193b970ef67a49f4d59f7ee0cb0fe536e5b1 Mon Sep 17 00:00:00 2001 From: Steven Knipe Date: Fri, 31 Oct 2025 22:38:42 -0700 Subject: [PATCH 172/261] implement Orcish Farmer --- Mage.Sets/src/mage/cards/o/OrcishFarmer.java | 78 +++++++++++++++++++ Mage.Sets/src/mage/sets/FifthEdition.java | 1 + Mage.Sets/src/mage/sets/IceAge.java | 1 + Mage.Sets/src/mage/sets/MastersEditionII.java | 1 + .../LandTypeChangingEffectsTest.java | 25 ++++++ .../effects/ContinuousEffectImpl.java | 4 + 6 files changed, 110 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/o/OrcishFarmer.java diff --git a/Mage.Sets/src/mage/cards/o/OrcishFarmer.java b/Mage.Sets/src/mage/cards/o/OrcishFarmer.java new file mode 100644 index 00000000000..60e3956e1bb --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OrcishFarmer.java @@ -0,0 +1,78 @@ +package mage.cards.o; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.PhaseStep; +import mage.constants.SubType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetLandPermanent; + +import java.util.UUID; + +/** + * @author notgreat + */ +public final class OrcishFarmer extends CardImpl { + + public OrcishFarmer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}"); + + this.subtype.add(SubType.ORC); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {T}: Target land becomes a Swamp until its controller's next untap step. + Ability ability = new SimpleActivatedAbility(new OrcishFarmerEffect(), new TapSourceCost()); + ability.addTarget(new TargetLandPermanent()); + this.addAbility(ability); + } + + private OrcishFarmer(final OrcishFarmer card) { + super(card); + } + + @Override + public OrcishFarmer copy() { + return new OrcishFarmer(this); + } +} + +class OrcishFarmerEffect extends BecomesBasicLandTargetEffect { + + OrcishFarmerEffect() { + super(Duration.Custom, SubType.SWAMP); + setText("Target land becomes a Swamp until its controller's next untap step"); + } + + protected OrcishFarmerEffect(final OrcishFarmerEffect effect) { + super(effect); + } + + public OrcishFarmerEffect copy() { + return new OrcishFarmerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent p = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (p == null) { + discard(); + return false; + } + if (getEffectStartingOnTurn() != game.getTurnNum() + && game.isActivePlayer(p.getControllerId()) + && game.getStep().getType() == PhaseStep.UNTAP) { + discard(); + return false; + } + return super.apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/sets/FifthEdition.java b/Mage.Sets/src/mage/sets/FifthEdition.java index b8dd090e74a..14c3c57b194 100644 --- a/Mage.Sets/src/mage/sets/FifthEdition.java +++ b/Mage.Sets/src/mage/sets/FifthEdition.java @@ -317,6 +317,7 @@ public final class FifthEdition extends ExpansionSet { cards.add(new SetCardInfo("Obelisk of Undoing", 392, Rarity.RARE, mage.cards.o.ObeliskOfUndoing.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Artillery", 253, Rarity.UNCOMMON, mage.cards.o.OrcishArtillery.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Captain", 254, Rarity.UNCOMMON, mage.cards.o.OrcishCaptain.class, RETRO_ART)); + cards.add(new SetCardInfo("Orcish Farmer", 256, Rarity.COMMON, mage.cards.o.OrcishFarmer.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Oriflamme", 257, Rarity.UNCOMMON, mage.cards.o.OrcishOriflamme.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Squatters", 258, Rarity.RARE, mage.cards.o.OrcishSquatters.class, RETRO_ART)); cards.add(new SetCardInfo("Order of the Sacred Torch", 48, Rarity.RARE, mage.cards.o.OrderOfTheSacredTorch.class, RETRO_ART)); diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index fce20decb6b..6fe36b18bff 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -264,6 +264,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Oath of Lim-Dul", 156, Rarity.RARE, mage.cards.o.OathOfLimDul.class, RETRO_ART)); cards.add(new SetCardInfo("Onyx Talisman", 331, Rarity.UNCOMMON, mage.cards.o.OnyxTalisman.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Cannoneers", 205, Rarity.UNCOMMON, mage.cards.o.OrcishCannoneers.class, RETRO_ART)); + cards.add(new SetCardInfo("Orcish Farmer", 207, Rarity.COMMON, mage.cards.o.OrcishFarmer.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Healer", 208, Rarity.UNCOMMON, mage.cards.o.OrcishHealer.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Librarian", 209, Rarity.RARE, mage.cards.o.OrcishLibrarian.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Lumberjack", 210, Rarity.COMMON, mage.cards.o.OrcishLumberjack.class, RETRO_ART)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index ff253d5dd56..a60da0a7702 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -177,6 +177,7 @@ public final class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Orc General", 137, Rarity.UNCOMMON, mage.cards.o.OrcGeneral.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Cannoneers", 138, Rarity.UNCOMMON, mage.cards.o.OrcishCannoneers.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Captain", 139, Rarity.UNCOMMON, mage.cards.o.OrcishCaptain.class, RETRO_ART)); + cards.add(new SetCardInfo("Orcish Farmer", 141, Rarity.COMMON, mage.cards.o.OrcishFarmer.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Lumberjack", 142, Rarity.COMMON, mage.cards.o.OrcishLumberjack.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Squatters", 143, Rarity.RARE, mage.cards.o.OrcishSquatters.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Veteran", 144, Rarity.COMMON, mage.cards.o.OrcishVeteran.class, RETRO_ART)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java index 51749e04da0..0a5cc2b300e 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/LandTypeChangingEffectsTest.java @@ -266,4 +266,29 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase { assertType(urborgtoy, CardType.LAND, SubType.ISLAND); assertType("Mountain", CardType.LAND, SubType.ISLAND); } + @Test + public void testOrcishFarmer() { + // {T}: Target land becomes a Swamp until its controller's next untap step + addCard(Zone.BATTLEFIELD, playerA, "Orcish Farmer", 2); + + addCard(Zone.BATTLEFIELD, playerA, "Plains"); + addCard(Zone.BATTLEFIELD, playerB, "Reliquary Tower"); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target", "Plains"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target", "Reliquary Tower"); + checkSubType("Plains is Swamp on same turn", 1, PhaseStep.END_TURN, playerA, "Plains", SubType.SWAMP, true); + checkSubType("Plains is no longer Plains on same turn", 1, PhaseStep.END_TURN, playerA, "Plains", SubType.PLAINS, false); + checkSubType("Reliquary Tower is Swamp on same turn", 1, PhaseStep.END_TURN, playerB, "Reliquary Tower", SubType.SWAMP, true); + + checkSubType("Plains is Swamp on next turn", 2, PhaseStep.UPKEEP, playerA, "Plains", SubType.SWAMP, true); + checkSubType("Plains is no longer Plains on next turn", 2, PhaseStep.UPKEEP, playerA, "Plains", SubType.PLAINS, false); + checkSubType("Reliquary Tower no longer Swamp on next turn", 2, PhaseStep.UPKEEP, playerB, "Reliquary Tower", SubType.SWAMP, false); + + setStrictChooseMode(true); + setStopAt(3, PhaseStep.UPKEEP); + execute(); + + assertNotSubtype("Plains", SubType.SWAMP); + assertSubtype("Plains", SubType.PLAINS); + } } diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java index 0f9f25acc3a..1b282f109b0 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java @@ -248,6 +248,10 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu return startingControllerId; } + protected int getEffectStartingOnTurn() { + return effectStartingOnTurn; + } + @Override public void setStartingControllerAndTurnNum(Game game, UUID startingController, UUID activePlayerId) { this.startingControllerId = startingController; -- 2.47.2 From 00ff663c40ba2e11cb642ba4bfa1c4ccc42bec53 Mon Sep 17 00:00:00 2001 From: Steven Knipe Date: Fri, 31 Oct 2025 22:38:42 -0700 Subject: [PATCH 173/261] implement Orcish Conscripts, rework can't block alone ability --- .../src/mage/cards/b/BondedConstruct.java | 11 +- .../src/mage/cards/b/BondedHorncrest.java | 11 +- Mage.Sets/src/mage/cards/c/CravenHulk.java | 5 +- Mage.Sets/src/mage/cards/e/EmberBeast.java | 12 +- .../src/mage/cards/j/JackalFamiliar.java | 11 +- Mage.Sets/src/mage/cards/l/LoyalPegasus.java | 12 +- .../src/mage/cards/m/MilitiaRallier.java | 5 +- Mage.Sets/src/mage/cards/m/MoggFlunkies.java | 11 +- .../src/mage/cards/o/OrcishConscripts.java | 105 ++++++++++++++++++ Mage.Sets/src/mage/cards/r/RagingKronch.java | 5 +- .../src/mage/cards/s/SightlessBrawler.java | 10 +- .../src/mage/cards/t/TrustyCompanion.java | 11 +- Mage.Sets/src/mage/cards/w/Wirecat.java | 63 ++++++----- .../src/mage/cards/w/WojekBodyguard.java | 11 +- Mage.Sets/src/mage/sets/FifthEdition.java | 1 + Mage.Sets/src/mage/sets/IceAge.java | 1 + Mage.Sets/src/mage/sets/MastersEditionII.java | 1 + .../combat/CantAttackOrBlockAloneTest.java | 23 +++- .../combat/CantBlockAloneSourceEffect.java | 42 +++++++ .../keyword/CantAttackAloneAbility.java | 26 ----- .../CantAttackOrBlockAloneAbility.java | 29 +++++ .../keyword/CantBlockAloneAbility.java | 40 ------- .../java/mage/game/combat/CombatGroup.java | 23 ---- .../game/permanent/token/BeastieToken.java | 6 +- 24 files changed, 289 insertions(+), 186 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/o/OrcishConscripts.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/combat/CantBlockAloneSourceEffect.java delete mode 100644 Mage/src/main/java/mage/abilities/keyword/CantAttackAloneAbility.java create mode 100644 Mage/src/main/java/mage/abilities/keyword/CantAttackOrBlockAloneAbility.java delete mode 100644 Mage/src/main/java/mage/abilities/keyword/CantBlockAloneAbility.java diff --git a/Mage.Sets/src/mage/cards/b/BondedConstruct.java b/Mage.Sets/src/mage/cards/b/BondedConstruct.java index f8637ea0bb6..1a9aecd8719 100644 --- a/Mage.Sets/src/mage/cards/b/BondedConstruct.java +++ b/Mage.Sets/src/mage/cards/b/BondedConstruct.java @@ -1,28 +1,29 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; -import mage.abilities.keyword.CantAttackAloneAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantAttackAloneSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author fireshoes */ public final class BondedConstruct extends CardImpl { public BondedConstruct(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}"); this.subtype.add(SubType.CONSTRUCT); this.power = new MageInt(2); this.toughness = new MageInt(1); // Bonded Construct can't attack alone. - this.addAbility(new CantAttackAloneAbility()); + this.addAbility(new SimpleStaticAbility(new CantAttackAloneSourceEffect())); } private BondedConstruct(final BondedConstruct card) { diff --git a/Mage.Sets/src/mage/cards/b/BondedHorncrest.java b/Mage.Sets/src/mage/cards/b/BondedHorncrest.java index d2937895a95..0c1435af99f 100644 --- a/Mage.Sets/src/mage/cards/b/BondedHorncrest.java +++ b/Mage.Sets/src/mage/cards/b/BondedHorncrest.java @@ -1,14 +1,14 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; -import mage.abilities.keyword.CantAttackAloneAbility; -import mage.abilities.keyword.CantBlockAloneAbility; -import mage.constants.SubType; +import mage.abilities.keyword.CantAttackOrBlockAloneAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; /** * @@ -24,8 +24,7 @@ public final class BondedHorncrest extends CardImpl { this.toughness = new MageInt(5); // Bonded Horncrest can't attack or block alone. - this.addAbility(new CantAttackAloneAbility()); - this.addAbility(CantBlockAloneAbility.getInstance()); + this.addAbility(new CantAttackOrBlockAloneAbility()); } private BondedHorncrest(final BondedHorncrest card) { diff --git a/Mage.Sets/src/mage/cards/c/CravenHulk.java b/Mage.Sets/src/mage/cards/c/CravenHulk.java index 1eed5276fa9..2bfec9a8978 100644 --- a/Mage.Sets/src/mage/cards/c/CravenHulk.java +++ b/Mage.Sets/src/mage/cards/c/CravenHulk.java @@ -1,7 +1,8 @@ package mage.cards.c; import mage.MageInt; -import mage.abilities.keyword.CantBlockAloneAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantBlockAloneSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -23,7 +24,7 @@ public final class CravenHulk extends CardImpl { this.toughness = new MageInt(4); // Craven Hulk can't block alone. - this.addAbility(CantBlockAloneAbility.getInstance()); + this.addAbility(new SimpleStaticAbility(new CantBlockAloneSourceEffect())); } private CravenHulk(final CravenHulk card) { diff --git a/Mage.Sets/src/mage/cards/e/EmberBeast.java b/Mage.Sets/src/mage/cards/e/EmberBeast.java index c2f319d78d1..64067ef14a6 100644 --- a/Mage.Sets/src/mage/cards/e/EmberBeast.java +++ b/Mage.Sets/src/mage/cards/e/EmberBeast.java @@ -1,31 +1,29 @@ package mage.cards.e; -import java.util.UUID; import mage.MageInt; -import mage.abilities.keyword.CantAttackAloneAbility; -import mage.abilities.keyword.CantBlockAloneAbility; +import mage.abilities.keyword.CantAttackOrBlockAloneAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class EmberBeast extends CardImpl { public EmberBeast(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.BEAST); this.power = new MageInt(3); this.toughness = new MageInt(4); // Ember Beast can't attack or block alone. - this.addAbility(new CantAttackAloneAbility()); - this.addAbility(CantBlockAloneAbility.getInstance()); + this.addAbility(new CantAttackOrBlockAloneAbility()); } private EmberBeast(final EmberBeast card) { diff --git a/Mage.Sets/src/mage/cards/j/JackalFamiliar.java b/Mage.Sets/src/mage/cards/j/JackalFamiliar.java index cac871879e3..ed46e360569 100644 --- a/Mage.Sets/src/mage/cards/j/JackalFamiliar.java +++ b/Mage.Sets/src/mage/cards/j/JackalFamiliar.java @@ -1,30 +1,29 @@ package mage.cards.j; -import java.util.UUID; import mage.MageInt; -import mage.abilities.keyword.CantAttackAloneAbility; -import mage.abilities.keyword.CantBlockAloneAbility; +import mage.abilities.keyword.CantAttackOrBlockAloneAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * @author magenoxx_at_gmail.com */ public final class JackalFamiliar extends CardImpl { public JackalFamiliar(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); this.subtype.add(SubType.JACKAL); this.power = new MageInt(2); this.toughness = new MageInt(2); // Jackal Familiar can't attack or block alone. - this.addAbility(new CantAttackAloneAbility()); - this.addAbility(CantBlockAloneAbility.getInstance()); + this.addAbility(new CantAttackOrBlockAloneAbility()); } private JackalFamiliar(final JackalFamiliar card) { diff --git a/Mage.Sets/src/mage/cards/l/LoyalPegasus.java b/Mage.Sets/src/mage/cards/l/LoyalPegasus.java index b817a1d9443..4ec250d15e5 100644 --- a/Mage.Sets/src/mage/cards/l/LoyalPegasus.java +++ b/Mage.Sets/src/mage/cards/l/LoyalPegasus.java @@ -1,24 +1,23 @@ package mage.cards.l; -import java.util.UUID; import mage.MageInt; -import mage.abilities.keyword.CantAttackAloneAbility; -import mage.abilities.keyword.CantBlockAloneAbility; +import mage.abilities.keyword.CantAttackOrBlockAloneAbility; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class LoyalPegasus extends CardImpl { public LoyalPegasus(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); this.subtype.add(SubType.PEGASUS); this.power = new MageInt(2); @@ -27,8 +26,7 @@ public final class LoyalPegasus extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Loyal Pegasus can't attack or block alone. - this.addAbility(new CantAttackAloneAbility()); - this.addAbility(CantBlockAloneAbility.getInstance()); + this.addAbility(new CantAttackOrBlockAloneAbility()); } private LoyalPegasus(final LoyalPegasus card) { diff --git a/Mage.Sets/src/mage/cards/m/MilitiaRallier.java b/Mage.Sets/src/mage/cards/m/MilitiaRallier.java index a8d84fc63d9..169cd036ee7 100644 --- a/Mage.Sets/src/mage/cards/m/MilitiaRallier.java +++ b/Mage.Sets/src/mage/cards/m/MilitiaRallier.java @@ -3,8 +3,9 @@ package mage.cards.m; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.UntapTargetEffect; -import mage.abilities.keyword.CantAttackAloneAbility; +import mage.abilities.effects.common.combat.CantAttackAloneSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -27,7 +28,7 @@ public final class MilitiaRallier extends CardImpl { this.toughness = new MageInt(3); // Militia Rallier can't attack alone. - this.addAbility(new CantAttackAloneAbility()); + this.addAbility(new SimpleStaticAbility(new CantAttackAloneSourceEffect())); // Whenever Militia Rallier attacks, untap target creature. Ability ability = new AttacksTriggeredAbility(new UntapTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/m/MoggFlunkies.java b/Mage.Sets/src/mage/cards/m/MoggFlunkies.java index 39d4f7849c3..04d543b74f6 100644 --- a/Mage.Sets/src/mage/cards/m/MoggFlunkies.java +++ b/Mage.Sets/src/mage/cards/m/MoggFlunkies.java @@ -1,30 +1,29 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; -import mage.abilities.keyword.CantAttackAloneAbility; -import mage.abilities.keyword.CantBlockAloneAbility; +import mage.abilities.keyword.CantAttackOrBlockAloneAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * @author magenoxx_at_gmail.com */ public final class MoggFlunkies extends CardImpl { public MoggFlunkies(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); this.subtype.add(SubType.GOBLIN); this.power = new MageInt(3); this.toughness = new MageInt(3); // Mogg Flunkies can't attack or block alone. - this.addAbility(new CantAttackAloneAbility()); - this.addAbility(CantBlockAloneAbility.getInstance()); + this.addAbility(new CantAttackOrBlockAloneAbility()); } private MoggFlunkies(final MoggFlunkies card) { diff --git a/Mage.Sets/src/mage/cards/o/OrcishConscripts.java b/Mage.Sets/src/mage/cards/o/OrcishConscripts.java new file mode 100644 index 00000000000..7a6b84534e7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OrcishConscripts.java @@ -0,0 +1,105 @@ +package mage.cards.o; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.RestrictionEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterBlockingCreature; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * + * @author notgreat + */ +public final class OrcishConscripts extends CardImpl { + + public OrcishConscripts(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); + + this.subtype.add(SubType.ORC); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Orcish Conscripts can't attack unless at least two other creatures attack. + this.addAbility(new SimpleStaticAbility(new OrcishConscriptsAttackEffect())); + + // Orcish Conscripts can't block unless at least two other creatures block. + this.addAbility(new SimpleStaticAbility(new OrcishConscriptsBlockEffect())); + } + + private OrcishConscripts(final OrcishConscripts card) { + super(card); + } + + @Override + public OrcishConscripts copy() { + return new OrcishConscripts(this); + } +} + +class OrcishConscriptsAttackEffect extends RestrictionEffect { + + OrcishConscriptsAttackEffect() { + super(Duration.WhileOnBattlefield); + staticText = "{this} can't attack unless at least two other creatures attack"; + } + + private OrcishConscriptsAttackEffect(final OrcishConscriptsAttackEffect effect) { + super(effect); + } + + @Override + public OrcishConscriptsAttackEffect copy() { + return new OrcishConscriptsAttackEffect(this); + } + + @Override + public boolean canAttackCheckAfter(int numberOfAttackers, Ability source, Game game, boolean canUseChooseDialogs) { + return numberOfAttackers > 2; + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + return source.getSourceId().equals(permanent.getId()); + } +} + +class OrcishConscriptsBlockEffect extends RestrictionEffect { + + private static final FilterBlockingCreature filter = new FilterBlockingCreature("Blocking creatures"); + + public OrcishConscriptsBlockEffect() { + super(Duration.WhileOnBattlefield); + staticText = "{this} can't block unless at least two other creatures block"; + } + + private OrcishConscriptsBlockEffect(final OrcishConscriptsBlockEffect effect) { + super(effect); + } + + @Override + public OrcishConscriptsBlockEffect copy() { + return new OrcishConscriptsBlockEffect(this); + } + + @Override + public boolean canBlockCheckAfter(Ability source, Game game, boolean canUseChooseDialogs) { + return false; + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + if (permanent.getId().equals(source.getSourceId())) { + return game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game).size() <= 2; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RagingKronch.java b/Mage.Sets/src/mage/cards/r/RagingKronch.java index 6073012f684..481e46be31b 100644 --- a/Mage.Sets/src/mage/cards/r/RagingKronch.java +++ b/Mage.Sets/src/mage/cards/r/RagingKronch.java @@ -1,7 +1,8 @@ package mage.cards.r; import mage.MageInt; -import mage.abilities.keyword.CantAttackAloneAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantAttackAloneSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -22,7 +23,7 @@ public final class RagingKronch extends CardImpl { this.toughness = new MageInt(3); // Raging Kronch can't attack alone. - this.addAbility(new CantAttackAloneAbility()); + this.addAbility(new SimpleStaticAbility(new CantAttackAloneSourceEffect())); } private RagingKronch(final RagingKronch card) { diff --git a/Mage.Sets/src/mage/cards/s/SightlessBrawler.java b/Mage.Sets/src/mage/cards/s/SightlessBrawler.java index c7edb114474..71d9f85cc8a 100644 --- a/Mage.Sets/src/mage/cards/s/SightlessBrawler.java +++ b/Mage.Sets/src/mage/cards/s/SightlessBrawler.java @@ -1,22 +1,22 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.combat.CantAttackAloneAttachedEffect; +import mage.abilities.effects.common.combat.CantAttackAloneSourceEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; import mage.abilities.keyword.BestowAbility; -import mage.abilities.keyword.CantAttackAloneAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AttachmentType; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; + +import java.util.UUID; /** * @@ -35,7 +35,7 @@ public final class SightlessBrawler extends CardImpl { // Bestow 4W (If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature.) this.addAbility(new BestowAbility(this, "{4}{W}")); // Sightless Brawler can't attack alone. - this.addAbility(new CantAttackAloneAbility()); + this.addAbility(new SimpleStaticAbility(new CantAttackAloneSourceEffect())); // Enchanted creature gets +3/+2 and can't attack alone. Effect effect = new BoostEnchantedEffect(3, 2, Duration.WhileOnBattlefield); effect.setText("Enchanted creature gets +3/+2"); diff --git a/Mage.Sets/src/mage/cards/t/TrustyCompanion.java b/Mage.Sets/src/mage/cards/t/TrustyCompanion.java index 906a9baafd2..7a7c618f241 100644 --- a/Mage.Sets/src/mage/cards/t/TrustyCompanion.java +++ b/Mage.Sets/src/mage/cards/t/TrustyCompanion.java @@ -1,23 +1,24 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.keyword.CantAttackAloneAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantAttackAloneSourceEffect; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class TrustyCompanion extends CardImpl { public TrustyCompanion(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); this.subtype.add(SubType.HYENA); this.power = new MageInt(3); this.toughness = new MageInt(2); @@ -25,7 +26,7 @@ public final class TrustyCompanion extends CardImpl { // Vigilance this.addAbility(VigilanceAbility.getInstance()); // Trusty Companion can't attack alone. - this.addAbility(new CantAttackAloneAbility()); + this.addAbility(new SimpleStaticAbility(new CantAttackAloneSourceEffect())); } private TrustyCompanion(final TrustyCompanion card) { diff --git a/Mage.Sets/src/mage/cards/w/Wirecat.java b/Mage.Sets/src/mage/cards/w/Wirecat.java index 3b8e48ae566..d13b4386135 100644 --- a/Mage.Sets/src/mage/cards/w/Wirecat.java +++ b/Mage.Sets/src/mage/cards/w/Wirecat.java @@ -9,7 +9,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; @@ -39,39 +38,39 @@ public final class Wirecat extends CardImpl { public Wirecat copy() { return new Wirecat(this); } +} - static class WirecatEffect extends RestrictionEffect { +class WirecatEffect extends RestrictionEffect { - public WirecatEffect() { - super(Duration.WhileOnBattlefield); - staticText = "{this} can't attack or block if an enchantment is on the battlefield"; - } - - private WirecatEffect(final WirecatEffect effect) { - super(effect); - } - - @Override - public WirecatEffect copy() { - return new WirecatEffect(this); - } - - @Override - public boolean canAttackCheckAfter(int numberOfAttackers, Ability source, Game game, boolean canUseChooseDialogs) { - return false; - } - - @Override - public boolean canBlockCheckAfter(Ability source, Game game, boolean canUseChooseDialogs) { - return false; - } - - @Override - public boolean applies(Permanent permanent, Ability source, Game game) { - if (permanent.getId().equals(source.getSourceId())) { - return game.getBattlefield().contains(StaticFilters.FILTER_PERMANENT_ENCHANTMENT, source, game, 1); - } - return false; + WirecatEffect() { + super(Duration.WhileOnBattlefield); + staticText = "{this} can't attack or block if an enchantment is on the battlefield"; + } + + private WirecatEffect(final WirecatEffect effect) { + super(effect); + } + + @Override + public WirecatEffect copy() { + return new WirecatEffect(this); + } + + @Override + public boolean canAttackCheckAfter(int numberOfAttackers, Ability source, Game game, boolean canUseChooseDialogs) { + return false; + } + + @Override + public boolean canBlockCheckAfter(Ability source, Game game, boolean canUseChooseDialogs) { + return false; + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + if (permanent.getId().equals(source.getSourceId())) { + return game.getBattlefield().contains(StaticFilters.FILTER_PERMANENT_ENCHANTMENT, source, game, 1); } + return false; } } diff --git a/Mage.Sets/src/mage/cards/w/WojekBodyguard.java b/Mage.Sets/src/mage/cards/w/WojekBodyguard.java index 7041d3bd4d4..17a4b2189b6 100644 --- a/Mage.Sets/src/mage/cards/w/WojekBodyguard.java +++ b/Mage.Sets/src/mage/cards/w/WojekBodyguard.java @@ -1,14 +1,14 @@ package mage.cards.w; -import java.util.UUID; import mage.MageInt; -import mage.abilities.keyword.CantAttackAloneAbility; -import mage.abilities.keyword.CantBlockAloneAbility; -import mage.constants.SubType; +import mage.abilities.keyword.CantAttackOrBlockAloneAbility; import mage.abilities.keyword.MentorAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; /** * @@ -28,8 +28,7 @@ public final class WojekBodyguard extends CardImpl { this.addAbility(new MentorAbility()); // Wojek Bodyguard can't attack or block alone. - this.addAbility(new CantAttackAloneAbility()); - this.addAbility(CantBlockAloneAbility.getInstance()); + this.addAbility(new CantAttackOrBlockAloneAbility()); } private WojekBodyguard(final WojekBodyguard card) { diff --git a/Mage.Sets/src/mage/sets/FifthEdition.java b/Mage.Sets/src/mage/sets/FifthEdition.java index 14c3c57b194..ac5e7899839 100644 --- a/Mage.Sets/src/mage/sets/FifthEdition.java +++ b/Mage.Sets/src/mage/sets/FifthEdition.java @@ -317,6 +317,7 @@ public final class FifthEdition extends ExpansionSet { cards.add(new SetCardInfo("Obelisk of Undoing", 392, Rarity.RARE, mage.cards.o.ObeliskOfUndoing.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Artillery", 253, Rarity.UNCOMMON, mage.cards.o.OrcishArtillery.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Captain", 254, Rarity.UNCOMMON, mage.cards.o.OrcishCaptain.class, RETRO_ART)); + cards.add(new SetCardInfo("Orcish Conscripts", 255, Rarity.COMMON, mage.cards.o.OrcishConscripts.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Farmer", 256, Rarity.COMMON, mage.cards.o.OrcishFarmer.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Oriflamme", 257, Rarity.UNCOMMON, mage.cards.o.OrcishOriflamme.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Squatters", 258, Rarity.RARE, mage.cards.o.OrcishSquatters.class, RETRO_ART)); diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index 6fe36b18bff..c7772fdb108 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -264,6 +264,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Oath of Lim-Dul", 156, Rarity.RARE, mage.cards.o.OathOfLimDul.class, RETRO_ART)); cards.add(new SetCardInfo("Onyx Talisman", 331, Rarity.UNCOMMON, mage.cards.o.OnyxTalisman.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Cannoneers", 205, Rarity.UNCOMMON, mage.cards.o.OrcishCannoneers.class, RETRO_ART)); + cards.add(new SetCardInfo("Orcish Conscripts", 206, Rarity.COMMON, mage.cards.o.OrcishConscripts.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Farmer", 207, Rarity.COMMON, mage.cards.o.OrcishFarmer.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Healer", 208, Rarity.UNCOMMON, mage.cards.o.OrcishHealer.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Librarian", 209, Rarity.RARE, mage.cards.o.OrcishLibrarian.class, RETRO_ART)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index a60da0a7702..7666dcbd557 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -177,6 +177,7 @@ public final class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Orc General", 137, Rarity.UNCOMMON, mage.cards.o.OrcGeneral.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Cannoneers", 138, Rarity.UNCOMMON, mage.cards.o.OrcishCannoneers.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Captain", 139, Rarity.UNCOMMON, mage.cards.o.OrcishCaptain.class, RETRO_ART)); + cards.add(new SetCardInfo("Orcish Conscripts", 140, Rarity.COMMON, mage.cards.o.OrcishConscripts.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Farmer", 141, Rarity.COMMON, mage.cards.o.OrcishFarmer.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Lumberjack", 142, Rarity.COMMON, mage.cards.o.OrcishLumberjack.class, RETRO_ART)); cards.add(new SetCardInfo("Orcish Squatters", 143, Rarity.RARE, mage.cards.o.OrcishSquatters.class, RETRO_ART)); diff --git a/Mage.Tests/src/test/java/org/mage/test/combat/CantAttackOrBlockAloneTest.java b/Mage.Tests/src/test/java/org/mage/test/combat/CantAttackOrBlockAloneTest.java index 0a24dab7a21..a0a5689a376 100644 --- a/Mage.Tests/src/test/java/org/mage/test/combat/CantAttackOrBlockAloneTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/combat/CantAttackOrBlockAloneTest.java @@ -88,16 +88,35 @@ public class CantAttackOrBlockAloneTest extends CardTestPlayerBase { @Test public void testCantBlockAlone2() { addCard(Zone.BATTLEFIELD, playerA, "Mogg Flunkies"); - addCard(Zone.BATTLEFIELD, playerA, "Llanowar Elves"); + addCard(Zone.BATTLEFIELD, playerA, "Ember Beast"); addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard"); attack(2, playerB, "Elite Vanguard"); block(2, playerA, "Mogg Flunkies", "Elite Vanguard"); - block(2, playerA, "Llanowar Elves", "Elite Vanguard"); + block(2, playerA, "Ember Beast", "Elite Vanguard"); setStopAt(2, PhaseStep.END_TURN); execute(); assertLife(playerA, 20); } + + /** + * Try to attack with three Orcish Conscripts (can't attack unless 2 others attack) + */ + @Test + public void testCanAttackWithThree() { + addCard(Zone.BATTLEFIELD, playerA, "Orcish Conscripts", 3); // 2/2 + + attack(1, playerA, "Orcish Conscripts"); + attack(1, playerA, "Orcish Conscripts"); + attack(1, playerA, "Orcish Conscripts"); + + setStopAt(1, PhaseStep.END_TURN); + setStrictChooseMode(true); + execute(); + + assertLife(playerB, 14); + + } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBlockAloneSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBlockAloneSourceEffect.java new file mode 100644 index 00000000000..3028a85af92 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBlockAloneSourceEffect.java @@ -0,0 +1,42 @@ +package mage.abilities.effects.common.combat; + +import mage.abilities.Ability; +import mage.abilities.effects.RestrictionEffect; +import mage.constants.Duration; +import mage.filter.common.FilterBlockingCreature; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author LevelX2 + */ +public class CantBlockAloneSourceEffect extends RestrictionEffect { + + private static final FilterBlockingCreature filter = new FilterBlockingCreature("Blocking creatures"); + public CantBlockAloneSourceEffect() { + super(Duration.WhileOnBattlefield); + staticText = "{this} can't block alone"; + } + + protected CantBlockAloneSourceEffect(final CantBlockAloneSourceEffect effect) { + super(effect); + } + + @Override + public CantBlockAloneSourceEffect copy() { + return new CantBlockAloneSourceEffect(this); + } + + @Override + public boolean canBlockCheckAfter(Ability source, Game game, boolean canUseChooseDialogs) { + return false; + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + if (permanent.getId().equals(source.getSourceId())) { + return game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game).size() <= 1; + } + return false; + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/CantAttackAloneAbility.java b/Mage/src/main/java/mage/abilities/keyword/CantAttackAloneAbility.java deleted file mode 100644 index cb225680b6f..00000000000 --- a/Mage/src/main/java/mage/abilities/keyword/CantAttackAloneAbility.java +++ /dev/null @@ -1,26 +0,0 @@ - -package mage.abilities.keyword; - -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.combat.CantAttackAloneSourceEffect; -import mage.constants.Zone; - -/** - * @author magenoxx_at_googlemail.com - */ -public class CantAttackAloneAbility extends SimpleStaticAbility { - - public CantAttackAloneAbility() { - super(Zone.BATTLEFIELD, new CantAttackAloneSourceEffect()); - } - - private CantAttackAloneAbility(CantAttackAloneAbility ability) { - super(ability); - } - - @Override - public CantAttackAloneAbility copy() { - return new CantAttackAloneAbility(this); - } - -} diff --git a/Mage/src/main/java/mage/abilities/keyword/CantAttackOrBlockAloneAbility.java b/Mage/src/main/java/mage/abilities/keyword/CantAttackOrBlockAloneAbility.java new file mode 100644 index 00000000000..4b9dd9feab8 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/CantAttackOrBlockAloneAbility.java @@ -0,0 +1,29 @@ + + +package mage.abilities.keyword; + +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.combat.CantAttackAloneSourceEffect; +import mage.abilities.effects.common.combat.CantBlockAloneSourceEffect; +import mage.constants.Zone; + +/** + * @author notgreat + */ +public class CantAttackOrBlockAloneAbility extends SimpleStaticAbility { + + public CantAttackOrBlockAloneAbility() { + super(Zone.BATTLEFIELD, new CantAttackAloneSourceEffect().setText("{this} can't attack or block alone")); + this.addEffect(new CantBlockAloneSourceEffect().setText("")); + } + + private CantAttackOrBlockAloneAbility(CantAttackOrBlockAloneAbility ability) { + super(ability); + } + + @Override + public CantAttackOrBlockAloneAbility copy() { + return new CantAttackOrBlockAloneAbility(this); + } + +} diff --git a/Mage/src/main/java/mage/abilities/keyword/CantBlockAloneAbility.java b/Mage/src/main/java/mage/abilities/keyword/CantBlockAloneAbility.java deleted file mode 100644 index 62e64e4948d..00000000000 --- a/Mage/src/main/java/mage/abilities/keyword/CantBlockAloneAbility.java +++ /dev/null @@ -1,40 +0,0 @@ - - -package mage.abilities.keyword; - -import mage.constants.Zone; -import mage.abilities.MageSingleton; -import mage.abilities.StaticAbility; - -import java.io.ObjectStreamException; - -/** - * @author magenoxx_at_googlemail.com - */ -public class CantBlockAloneAbility extends StaticAbility implements MageSingleton { - - private static final CantBlockAloneAbility instance = new CantBlockAloneAbility(); - - private Object readResolve() throws ObjectStreamException { - return instance; - } - - public static CantBlockAloneAbility getInstance() { - return instance; - } - - private CantBlockAloneAbility() { - super(Zone.BATTLEFIELD, null); - } - - @Override - public String getRule() { - return "{this} can't block alone."; - } - - @Override - public CantBlockAloneAbility copy() { - return instance; - } - -} diff --git a/Mage/src/main/java/mage/game/combat/CombatGroup.java b/Mage/src/main/java/mage/game/combat/CombatGroup.java index 9940f345875..9e264afa759 100644 --- a/Mage/src/main/java/mage/game/combat/CombatGroup.java +++ b/Mage/src/main/java/mage/game/combat/CombatGroup.java @@ -679,29 +679,6 @@ public class CombatGroup implements Serializable, Copyable { possibleBlockers.put(attacker.getId(), goodBlockers); } - // effects: can't block alone - // too much blockers - if (blockersCount == 1) { - List toBeRemoved = new ArrayList<>(); - for (UUID blockerId : getBlockers()) { - Permanent blocker = game.getPermanent(blockerId); - if (blocker != null && blocker.getAbilities().containsKey(CantBlockAloneAbility.getInstance().getId())) { - blockWasLegal = false; - if (!game.isSimulation()) { - game.informPlayers(blocker.getLogName() + " can't block alone. Removing it from combat."); - } - toBeRemoved.add(blockerId); - } - } - - for (UUID blockerId : toBeRemoved) { - game.getCombat().removeBlocker(blockerId, game); - } - if (blockers.isEmpty()) { - this.blocked = false; - } - } - for (UUID uuid : attackers) { Permanent attacker = game.getPermanent(uuid); if (attacker != null && this.blocked) { diff --git a/Mage/src/main/java/mage/game/permanent/token/BeastieToken.java b/Mage/src/main/java/mage/game/permanent/token/BeastieToken.java index b5e4f4fe03d..b4ccf693cfb 100644 --- a/Mage/src/main/java/mage/game/permanent/token/BeastieToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/BeastieToken.java @@ -1,8 +1,7 @@ package mage.game.permanent.token; import mage.MageInt; -import mage.abilities.keyword.CantAttackAloneAbility; -import mage.abilities.keyword.CantBlockAloneAbility; +import mage.abilities.keyword.CantAttackOrBlockAloneAbility; import mage.constants.CardType; import mage.constants.SubType; @@ -19,8 +18,7 @@ public final class BeastieToken extends TokenImpl { power = new MageInt(4); toughness = new MageInt(4); - this.addAbility(new CantAttackAloneAbility()); - this.addAbility(CantBlockAloneAbility.getInstance()); + this.addAbility(new CantAttackOrBlockAloneAbility()); } private BeastieToken(final BeastieToken token) { -- 2.47.2 From f7855dda8b528515b4122708eedeec997107e120 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sun, 9 Nov 2025 20:55:23 -0500 Subject: [PATCH 174/261] fix Awaken the Maelstrom --- Mage.Sets/src/mage/cards/a/AwakenTheMaelstrom.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AwakenTheMaelstrom.java b/Mage.Sets/src/mage/cards/a/AwakenTheMaelstrom.java index ff4ba76a560..3ff192f04d9 100644 --- a/Mage.Sets/src/mage/cards/a/AwakenTheMaelstrom.java +++ b/Mage.Sets/src/mage/cards/a/AwakenTheMaelstrom.java @@ -16,7 +16,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.TargetPlayer; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanentAmount; import mage.target.common.TargetPermanentAmount; import mage.target.targetpointer.SecondTargetPointer; @@ -97,7 +97,7 @@ class AwakenTheMaelstromEffect extends OneShotEffect { } private void makeToken(Player player, Game game, Ability source) { - TargetPermanent target = new TargetControlledCreaturePermanent(); + TargetPermanent target = new TargetControlledPermanent(); target.withNotTarget(true); target.withChooseHint("to copy"); if (!target.canChoose(player.getId(), source, game)) { -- 2.47.2 From cd1f3985fdafd2c5825541f2a8083c194a5b3fbf Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sun, 9 Nov 2025 23:13:29 -0500 Subject: [PATCH 175/261] add test cases (not depending on lifelink) --- .../damage/DamageMultiTriggerTest.java | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiTriggerTest.java diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiTriggerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiTriggerTest.java new file mode 100644 index 00000000000..ced360b10bf --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiTriggerTest.java @@ -0,0 +1,188 @@ +package org.mage.test.cards.triggers.damage; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.CounterType; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author xenohedron + */ +public class DamageMultiTriggerTest extends CardTestPlayerBase { + + private static final String hatchling = "Kraken Hatchling"; // 0/4 + private static final String wishcoin = "Wishcoin Crab"; // 2/5 + + private static final String brothers = "Brothers of Fire"; // 2/2 + // 1RR: 1 dmg to any target and 1 dmg to you + private static final String embermage = "Reckless Embermage"; // 2/2 + // 1R: 1 dmg to any target and 1 dmg to itself + + private static final String arc = "Arc Trail"; + // Arc Trail deals 2 damage to any target and 1 damage to another target. + private static final String cone = "Cone of Flame"; + // Cone of Flame deals 1 damage to any target, 2 damage to another target, and 3 damage to a third target. + private static final String chaar = "Char"; + // Char deals 4 damage to any target and 2 damage to you. + private static final String outrage = "Chandra's Outrage"; + // Chandra's Outrage deals 4 damage to target creature and 2 damage to that creature's controller. + private static final String fury = "Chandra's Fury"; + // Chandra's Fury deals 4 damage to target player or planeswalker + // and 1 damage to each creature that player or that planeswalker's controller controls. + + private static final String tamanoa = "Tamanoa"; // 2/4 + // Whenever a noncreature source you control deals damage, you gain that much life. + private static final String spiritLink = "Spirit Link"; // 2/2 + // Whenever enchanted creature deals damage, you gain that much life. + private static final String pridemate = "Ajani's Pridemate"; // 2/2 + // Whenever you gain life, put a +1/+1 counter on this creature. + + private void setupBattlefield() { + addCard(Zone.BATTLEFIELD, playerA, "Plateau", 5); + addCard(Zone.BATTLEFIELD, playerA, tamanoa); + addCard(Zone.HAND, playerA, spiritLink); + addCard(Zone.BATTLEFIELD, playerA, pridemate); + addCard(Zone.BATTLEFIELD, playerA, hatchling); + addCard(Zone.BATTLEFIELD, playerB, wishcoin); + } + + @Test + public void testCreatureDamageTargetAndYou() { + setupBattlefield(); + addCard(Zone.BATTLEFIELD, playerA, brothers); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, spiritLink, brothers); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{R}{R}: "); + addTarget(playerA, wishcoin); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 - 1 + 2); + assertLife(playerB, 20); + assertDamageReceived(playerB, wishcoin, 1); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + public void testCreatureDamageTargetAndSelf() { + setupBattlefield(); + addCard(Zone.BATTLEFIELD, playerA, embermage); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, spiritLink, embermage); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{R}: "); + addTarget(playerA, wishcoin); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 2); + assertLife(playerB, 20); + assertDamageReceived(playerB, wishcoin, 1); + assertDamageReceived(playerA, embermage, 1); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + public void testSpellDamageTargetAndTarget() { + setupBattlefield(); + addCard(Zone.HAND, playerA, arc); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, arc); + addTarget(playerA, wishcoin); + addTarget(playerA, hatchling); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 3); + assertLife(playerB, 20); + assertDamageReceived(playerB, wishcoin, 2); + assertDamageReceived(playerA, hatchling, 1); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + public void testSpellDamageThreeTargets() { + setupBattlefield(); + addCard(Zone.HAND, playerA, cone); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, cone); + addTarget(playerA, wishcoin); + addTarget(playerA, hatchling); + addTarget(playerA, tamanoa); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 6); + assertLife(playerB, 20); + assertDamageReceived(playerB, wishcoin, 1); + assertDamageReceived(playerA, hatchling, 2); + assertDamageReceived(playerA, tamanoa, 3); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + public void testSpellDamageTargetAndYou() { + setupBattlefield(); + addCard(Zone.HAND, playerA, chaar); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chaar); + addTarget(playerA, wishcoin); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 - 2 + 6); + assertLife(playerB, 20); + assertDamageReceived(playerB, wishcoin, 4); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + public void testSpellDamageTargetAndController() { + setupBattlefield(); + addCard(Zone.HAND, playerA, outrage); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, outrage); + addTarget(playerA, wishcoin); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 6); + assertLife(playerB, 20 - 2); + assertDamageReceived(playerB, wishcoin, 4); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + + @Test + public void testSpellDamagePlayerAndControlled() { + setupBattlefield(); + addCard(Zone.HAND, playerA, fury); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, fury); + addTarget(playerA, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 5); + assertLife(playerB, 20 - 4); + assertDamageReceived(playerB, wishcoin, 1); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + +} -- 2.47.2 From 06c51bd829252a568036d7a612128cd981b21892 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sun, 9 Nov 2025 23:18:23 -0500 Subject: [PATCH 176/261] update to check damage batch by source --- Mage.Sets/src/mage/cards/s/Spiritualize.java | 3 +-- .../abilities/common/DealsDamageAttachedTriggeredAbility.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/Spiritualize.java b/Mage.Sets/src/mage/cards/s/Spiritualize.java index 143b0e2ac33..01b32b45836 100644 --- a/Mage.Sets/src/mage/cards/s/Spiritualize.java +++ b/Mage.Sets/src/mage/cards/s/Spiritualize.java @@ -62,8 +62,7 @@ class SpiritualizeTriggeredAbility extends DelayedTriggeredAbility { @Override public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER - || event.getType() == GameEvent.EventType.DAMAGED_PERMANENT; + return event.getType() == GameEvent.EventType.DAMAGED_BATCH_BY_SOURCE; } @Override diff --git a/Mage/src/main/java/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java index a1f6f9c286f..532c2ea65e1 100644 --- a/Mage/src/main/java/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DealsDamageAttachedTriggeredAbility.java @@ -29,8 +29,7 @@ public class DealsDamageAttachedTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT - || event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + return event.getType() == GameEvent.EventType.DAMAGED_BATCH_BY_SOURCE; } @Override -- 2.47.2 From 7a6dfb7a2f6c698ececea5096d1382089c11d0ff Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sun, 9 Nov 2025 23:25:37 -0500 Subject: [PATCH 177/261] new DamageTargetAndTargetEffect --- Mage.Sets/src/mage/cards/a/ArcTrail.java | 64 +---------------- .../common/DamageTargetAndTargetEffect.java | 68 +++++++++++++++++++ 2 files changed, 71 insertions(+), 61 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java diff --git a/Mage.Sets/src/mage/cards/a/ArcTrail.java b/Mage.Sets/src/mage/cards/a/ArcTrail.java index a85ec5afa8e..2a7a57ede4f 100644 --- a/Mage.Sets/src/mage/cards/a/ArcTrail.java +++ b/Mage.Sets/src/mage/cards/a/ArcTrail.java @@ -1,21 +1,14 @@ package mage.cards.a; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.filter.common.FilterAnyTarget; import mage.filter.common.FilterPermanentOrPlayer; import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.Target; import mage.target.common.TargetPermanentOrPlayer; -import java.io.ObjectStreamException; import java.util.UUID; /** @@ -34,8 +27,8 @@ public final class ArcTrail extends CardImpl { public ArcTrail(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}"); - // Arc Trail deals 2 damage to any target and 1 damage to another any target - this.getSpellAbility().addEffect(ArcTrailEffect.getInstance()); + // Arc Trail deals 2 damage to any target and 1 damage to another target + this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 1)); this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter1).setTargetTag(1)); this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter2).setTargetTag(2)); } @@ -50,54 +43,3 @@ public final class ArcTrail extends CardImpl { } } - -class ArcTrailEffect extends OneShotEffect { - - private static final ArcTrailEffect instance = new ArcTrailEffect(); - - private Object readResolve() throws ObjectStreamException { - return instance; - } - - public static ArcTrailEffect getInstance() { - return instance; - } - - private ArcTrailEffect() { - super(Outcome.Damage); - staticText = "{this} deals 2 damage to any target and 1 damage to another target"; - } - - @Override - public boolean apply(Game game, Ability source) { - - boolean applied = false; - boolean twoDamageDone = false; - int damage = 2; - - for (Target target : source.getTargets()) { - Permanent permanent = game.getPermanent(target.getFirstTarget()); - - if (twoDamageDone) { - damage = 1; - } - - if (permanent != null) { - applied |= (permanent.damage(damage, source.getSourceId(), source, game, false, true) > 0); - } - Player player = game.getPlayer(target.getFirstTarget()); - if (player != null) { - applied |= (player.damage(damage, source.getSourceId(), source, game) > 0); - } - - twoDamageDone = true; - } - return applied; - } - - @Override - public ArcTrailEffect copy() { - return instance; - } - -} diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java new file mode 100644 index 00000000000..2b9acbebcf2 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java @@ -0,0 +1,68 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author xenohedron + */ +public class DamageTargetAndTargetEffect extends OneShotEffect { + + private final int firstAmount; + private final int secondAmount; + + /** + * Deals simultaneous damage to two targets. Must set target tag 1 and 2 + */ + public DamageTargetAndTargetEffect(int firstAmount, int secondAmount) { + super(Outcome.Damage); + this.firstAmount = firstAmount; + this.secondAmount = secondAmount; + } + + protected DamageTargetAndTargetEffect(final DamageTargetAndTargetEffect effect) { + super(effect); + this.firstAmount = effect.firstAmount; + this.secondAmount = effect.secondAmount; + } + + @Override + public DamageTargetAndTargetEffect copy() { + return new DamageTargetAndTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + source.getTargets().getByTag(1).getTargets().forEach(uuid -> damageTarget(uuid, firstAmount, source, game)); + source.getTargets().getByTag(2).getTargets().forEach(uuid -> damageTarget(uuid, secondAmount, source, game)); + return true; + } + + private void damageTarget(UUID targetId, int amount, Ability source, Game game) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + permanent.damage(amount, source.getSourceId(), source, game) ; + } else { + Player player = game.getPlayer(targetId); + if (player != null) { + player.damage(amount, source.getSourceId(), source, game); + } + } + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + return "{this} deals " + firstAmount + "damage to " + mode.getTargets().getByTag(1).getDescription() + + " and " + secondAmount + "damage to " + mode.getTargets().getByTag(2).getDescription(); + } +} -- 2.47.2 From 9f663f2a23e0686321c0ce764acb4a90c3318a18 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sun, 9 Nov 2025 23:33:18 -0500 Subject: [PATCH 178/261] new DamageTargetAndYouEffect --- .../src/mage/cards/b/BrothersOfFire.java | 14 +--- Mage.Sets/src/mage/cards/c/Char.java | 14 +--- .../common/DamageTargetAndYouEffect.java | 77 +++++++++++++++++++ 3 files changed, 85 insertions(+), 20 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndYouEffect.java diff --git a/Mage.Sets/src/mage/cards/b/BrothersOfFire.java b/Mage.Sets/src/mage/cards/b/BrothersOfFire.java index ba5e830dd35..98098bfe433 100644 --- a/Mage.Sets/src/mage/cards/b/BrothersOfFire.java +++ b/Mage.Sets/src/mage/cards/b/BrothersOfFire.java @@ -1,21 +1,18 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author LoneFox @@ -29,10 +26,7 @@ public final class BrothersOfFire extends CardImpl { this.toughness = new MageInt(2); // {1}{R}{R}: Brothers of Fire deals 1 damage to any target and 1 damage to you. - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{R}{R}")); - Effect effect = new DamageControllerEffect(1); - effect.setText("and 1 damage to you"); - ability.addEffect(effect); + Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(1), new ManaCostsImpl<>("{1}{R}{R}")); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/Char.java b/Mage.Sets/src/mage/cards/c/Char.java index d3fb54b2f59..96fbde8965a 100644 --- a/Mage.Sets/src/mage/cards/c/Char.java +++ b/Mage.Sets/src/mage/cards/c/Char.java @@ -1,15 +1,13 @@ - package mage.cards.c; -import java.util.UUID; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author LevelX2 @@ -19,13 +17,9 @@ public final class Char extends CardImpl { public Char(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}"); - // Char deals 4 damage to any target and 2 damage to you. - this.getSpellAbility().addEffect(new DamageTargetEffect(4)); + this.getSpellAbility().addEffect(new DamageTargetAndYouEffect(4, 2)); this.getSpellAbility().addTarget(new TargetAnyTarget()); - Effect effect = new DamageControllerEffect(2); - effect.setText("and 2 damage to you"); - this.getSpellAbility().addEffect(effect); } private Char(final Char card) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndYouEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndYouEffect.java new file mode 100644 index 00000000000..b1e874e845e --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndYouEffect.java @@ -0,0 +1,77 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author xenohedron + */ +public class DamageTargetAndYouEffect extends OneShotEffect { + + private final int firstAmount; + private final int secondAmount; + + /** + * Deals simultaneous damage to the target and the controller of the source + */ + public DamageTargetAndYouEffect(int amount) { + this(amount, amount); + } + + /** + * Deals simultaneous damage to the target and the controller of the source + */ + public DamageTargetAndYouEffect(int firstAmount, int secondAmount) { + super(Outcome.Damage); + this.firstAmount = firstAmount; + this.secondAmount = secondAmount; + } + + protected DamageTargetAndYouEffect(final DamageTargetAndYouEffect effect) { + super(effect); + this.firstAmount = effect.firstAmount; + this.secondAmount = effect.secondAmount; + } + + @Override + public DamageTargetAndYouEffect copy() { + return new DamageTargetAndYouEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + permanent.damage(firstAmount, source.getSourceId(), source, game); + } else { + Player player = game.getPlayer(targetId); + if (player != null) { + player.damage(firstAmount, source.getSourceId(), source, game); + } + } + } + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + controller.damage(secondAmount, source.getSourceId(), source, game); + } + return true; + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + return "{this} deals " + firstAmount + "damage to " + + getTargetPointer().describeTargets(mode.getTargets(), "that creature") + + " and " + secondAmount + "damage to you"; + } +} -- 2.47.2 From 24785b6d81b84c3d5a8b020e53b41e77d657bc68 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sun, 9 Nov 2025 23:36:12 -0500 Subject: [PATCH 179/261] new DamageTargetAndSelfEffect --- .../src/mage/cards/r/RecklessEmbermage.java | 11 +-- .../common/DamageTargetAndSelfEffect.java | 77 +++++++++++++++++++ 2 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndSelfEffect.java diff --git a/Mage.Sets/src/mage/cards/r/RecklessEmbermage.java b/Mage.Sets/src/mage/cards/r/RecklessEmbermage.java index 9446db91015..4605538e0c5 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessEmbermage.java +++ b/Mage.Sets/src/mage/cards/r/RecklessEmbermage.java @@ -1,20 +1,18 @@ - package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.DamageSelfEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndSelfEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author Quercitron @@ -30,8 +28,7 @@ public final class RecklessEmbermage extends CardImpl { this.toughness = new MageInt(2); // {1}{R}: Reckless Embermage deals 1 damage to any target and 1 damage to itself. - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{R}")); - ability.addEffect(new DamageSelfEffect(1).setText("and 1 damage to itself")); + Ability ability = new SimpleActivatedAbility(new DamageTargetAndSelfEffect(1), new ManaCostsImpl<>("{1}{R}")); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndSelfEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndSelfEffect.java new file mode 100644 index 00000000000..ea7bc7c38ea --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndSelfEffect.java @@ -0,0 +1,77 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author xenohedron + */ +public class DamageTargetAndSelfEffect extends OneShotEffect { + + private final int firstAmount; + private final int secondAmount; + + /** + * Deals simultaneous damage to the target and to itself + */ + public DamageTargetAndSelfEffect(int amount) { + this(amount, amount); + } + + /** + * Deals simultaneous damage to the target and to itself + */ + public DamageTargetAndSelfEffect(int firstAmount, int secondAmount) { + super(Outcome.Damage); + this.firstAmount = firstAmount; + this.secondAmount = secondAmount; + } + + protected DamageTargetAndSelfEffect(final DamageTargetAndSelfEffect effect) { + super(effect); + this.firstAmount = effect.firstAmount; + this.secondAmount = effect.secondAmount; + } + + @Override + public DamageTargetAndSelfEffect copy() { + return new DamageTargetAndSelfEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + permanent.damage(firstAmount, source.getSourceId(), source, game); + } else { + Player player = game.getPlayer(targetId); + if (player != null) { + player.damage(firstAmount, source.getSourceId(), source, game); + } + } + } + Permanent itself = source.getSourcePermanentIfItStillExists(game); + if (itself != null) { + itself.damage(secondAmount, source.getSourceId(), source, game); + } + return true; + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + return "{this} deals " + firstAmount + "damage to " + + getTargetPointer().describeTargets(mode.getTargets(), "that creature") + + " and " + secondAmount + "damage to itself"; + } +} -- 2.47.2 From 03100a932ea1e5023dfaa64f83f5dc57f2367624 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sun, 9 Nov 2025 23:47:44 -0500 Subject: [PATCH 180/261] new DamageTargetAndTargetControllerEffect --- .../src/mage/cards/c/ChandrasOutrage.java | 14 ++-- ...DamageTargetAndTargetControllerEffect.java | 65 +++++++++++++++++++ 2 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java diff --git a/Mage.Sets/src/mage/cards/c/ChandrasOutrage.java b/Mage.Sets/src/mage/cards/c/ChandrasOutrage.java index ddaaed5fe15..e3517234cdf 100644 --- a/Mage.Sets/src/mage/cards/c/ChandrasOutrage.java +++ b/Mage.Sets/src/mage/cards/c/ChandrasOutrage.java @@ -1,16 +1,13 @@ - - package mage.cards.c; -import java.util.UUID; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageTargetControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author BetaSteward_at_googlemail.com @@ -21,10 +18,7 @@ public final class ChandrasOutrage extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}{R}"); // Chandra's Outrage deals 4 damage to target creature and 2 damage to that creature's controller. - this.getSpellAbility().addEffect(new DamageTargetEffect(4)); - Effect effect = new DamageTargetControllerEffect(2); - effect.setText("and 2 damage to that creature's controller"); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new DamageTargetAndTargetControllerEffect(4, 2)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java new file mode 100644 index 00000000000..de20b0cb6aa --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java @@ -0,0 +1,65 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author xenohedron + */ +public class DamageTargetAndTargetControllerEffect extends OneShotEffect { + + private final int firstAmount; + private final int secondAmount; + + /** + * Deals simultaneous damage to the target and to the controller of the target + */ + public DamageTargetAndTargetControllerEffect(int firstAmount, int secondAmount) { + super(Outcome.Damage); + this.firstAmount = firstAmount; + this.secondAmount = secondAmount; + } + + protected DamageTargetAndTargetControllerEffect(final DamageTargetAndTargetControllerEffect effect) { + super(effect); + this.firstAmount = effect.firstAmount; + this.secondAmount = effect.secondAmount; + } + + @Override + public DamageTargetAndTargetControllerEffect copy() { + return new DamageTargetAndTargetControllerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + permanent.damage(firstAmount, source.getSourceId(), source, game); + Player player = game.getPlayer(permanent.getControllerId()); + if (player != null) { + player.damage(secondAmount, source.getSourceId(), source, game); + } + } + } + return true; + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + return "{this} deals " + firstAmount + "damage to " + + getTargetPointer().describeTargets(mode.getTargets(), "that creature") + + " and " + secondAmount + "damage to that creature's controller"; + } +} -- 2.47.2 From b8394f99e22d402374fea1368aeeac71e77641d1 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Sun, 9 Nov 2025 23:58:45 -0500 Subject: [PATCH 181/261] new DamageTargetAndAllControlledEffect --- Mage.Sets/src/mage/cards/c/ChandrasFury.java | 14 ++-- .../DamageTargetAndAllControlledEffect.java | 73 +++++++++++++++++++ 2 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java diff --git a/Mage.Sets/src/mage/cards/c/ChandrasFury.java b/Mage.Sets/src/mage/cards/c/ChandrasFury.java index 98e752ca138..87f167a107f 100644 --- a/Mage.Sets/src/mage/cards/c/ChandrasFury.java +++ b/Mage.Sets/src/mage/cards/c/ChandrasFury.java @@ -1,14 +1,14 @@ - package mage.cards.c; -import java.util.UUID; -import mage.abilities.effects.common.DamageAllControlledTargetEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndAllControlledEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.filter.StaticFilters; import mage.target.common.TargetPlayerOrPlaneswalker; +import java.util.UUID; + /** * * @author North @@ -19,10 +19,8 @@ public final class ChandrasFury extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}"); // Chandra's Fury deals 4 damage to target player and 1 damage to each creature that player controls. - this.getSpellAbility().addEffect(new DamageTargetEffect(4)); - this.getSpellAbility().addEffect(new DamageAllControlledTargetEffect(1) - .setText("and 1 damage to each creature that player or that planeswalker's controller controls") - ); + this.getSpellAbility().addEffect(new DamageTargetAndAllControlledEffect(4, 1, + StaticFilters.FILTER_PERMANENT_CREATURE)); this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java new file mode 100644 index 00000000000..843bd5609ce --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java @@ -0,0 +1,73 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * @author xenohedron + */ +public class DamageTargetAndAllControlledEffect extends OneShotEffect { + + private final int firstAmount; + private final int secondAmount; + private final FilterPermanent filter; + + /** + * Deals simultaneous damage to the target and to each creature the target controls + */ + public DamageTargetAndAllControlledEffect(int firstAmount, int secondAmount, FilterPermanent filter) { + super(Outcome.Damage); + this.firstAmount = firstAmount; + this.secondAmount = secondAmount; + this.filter = filter; + } + + protected DamageTargetAndAllControlledEffect(final DamageTargetAndAllControlledEffect effect) { + super(effect); + this.firstAmount = effect.firstAmount; + this.secondAmount = effect.secondAmount; + this.filter = effect.filter.copy(); + } + + @Override + public DamageTargetAndAllControlledEffect copy() { + return new DamageTargetAndAllControlledEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + permanent.damage(firstAmount, source.getSourceId(), source, game); + } else { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null) { + player.damage(firstAmount, source.getSourceId(), source, game); + } + } + Player controller = game.getPlayerOrPlaneswalkerController(getTargetPointer().getFirst(game, source)); + if (controller != null) { + for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { + perm.damage(secondAmount, source.getSourceId(), source, game, false, true); + } + } + return true; + } + + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } + return "{this} deals " + firstAmount + "damage to " + + getTargetPointer().describeTargets(mode.getTargets(), "that creature") + + " and " + secondAmount + " damage to each " + filter.getMessage() + + " that player or that planeswalker's controller controls"; + } +} -- 2.47.2 From 1a1f7ec588252412d9a9414554c2fb3bdb63e8ab Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Mon, 10 Nov 2025 01:37:28 -0500 Subject: [PATCH 182/261] update all cards that deal damage to two or more specific things simultaneously --- Mage.Sets/src/mage/cards/a/ArcTrail.java | 6 ++- .../src/mage/cards/a/AssembledAlphas.java | 13 ++--- .../src/mage/cards/b/BellowingFiend.java | 20 ++++--- .../src/mage/cards/b/BurningSunsAvatar.java | 15 +++--- .../src/mage/cards/c/CarnivalCarnage.java | 5 +- .../src/mage/cards/c/ChandraFlamesFury.java | 48 ++--------------- .../src/mage/cards/c/ChandraPyromaster.java | 9 ++-- .../src/mage/cards/c/ConductElectricity.java | 14 ++--- Mage.Sets/src/mage/cards/c/CunningStrike.java | 22 +++----- .../src/mage/cards/c/CuombajjWitches.java | 5 +- Mage.Sets/src/mage/cards/d/DaggerCaster.java | 38 ++++++++++--- .../src/mage/cards/d/DragonsparkReactor.java | 3 +- .../mage/cards/d/DrakusethMawOfFlames.java | 50 ++--------------- .../src/mage/cards/e/ExplosiveWelcome.java | 22 +++----- Mage.Sets/src/mage/cards/f/FearFireFoes.java | 5 +- .../src/mage/cards/f/FireAndBrimstone.java | 6 +-- Mage.Sets/src/mage/cards/f/Fireslinger.java | 6 +-- Mage.Sets/src/mage/cards/f/Firespout.java | 47 +++++++++++++--- Mage.Sets/src/mage/cards/f/FirstVolley.java | 10 +--- Mage.Sets/src/mage/cards/f/ForgeDevil.java | 17 ++---- .../src/mage/cards/g/GoblinArtillery.java | 8 +-- .../src/mage/cards/g/GrangerGuildmage.java | 13 ++--- Mage.Sets/src/mage/cards/h/HailStorm.java | 41 ++++++++++++-- Mage.Sets/src/mage/cards/h/HungryFlames.java | 48 ++--------------- Mage.Sets/src/mage/cards/i/InsultInjury.java | 40 ++------------ .../src/mage/cards/i/InvasionOfRegatha.java | 19 ++----- Mage.Sets/src/mage/cards/j/JudgmentBolt.java | 38 ++++++++++--- Mage.Sets/src/mage/cards/k/KamahlsSledge.java | 15 +++--- Mage.Sets/src/mage/cards/l/Lunge.java | 18 +++---- Mage.Sets/src/mage/cards/n/NeonatesRush.java | 41 ++------------ .../src/mage/cards/o/OrcishArtillery.java | 11 ++-- .../src/mage/cards/o/OrcishCannonade.java | 14 ++--- .../src/mage/cards/o/OrcishCannoneers.java | 15 ++---- Mage.Sets/src/mage/cards/p/PsionicBlast.java | 6 +-- Mage.Sets/src/mage/cards/p/PsionicEntity.java | 13 ++--- Mage.Sets/src/mage/cards/p/PsionicSliver.java | 18 ++----- .../src/mage/cards/p/PunishTheEnemy.java | 15 +++--- .../src/mage/cards/r/RadiatingLightning.java | 11 ++-- .../src/mage/cards/r/RakdosFirewheeler.java | 11 ++-- Mage.Sets/src/mage/cards/r/RecklessRage.java | 15 ++---- Mage.Sets/src/mage/cards/s/SeismicWave.java | 6 +-- Mage.Sets/src/mage/cards/s/SelfDestruct.java | 2 +- .../src/mage/cards/s/ShadowGuildmage.java | 12 ++--- .../src/mage/cards/s/ShockerUnshakable.java | 6 +-- .../src/mage/cards/s/ShowerOfSparks.java | 13 ++--- .../src/mage/cards/s/SoulOfShandalar.java | 3 +- Mage.Sets/src/mage/cards/s/Sparksmith.java | 54 +++++++++++++------ .../src/mage/cards/s/SunflareShaman.java | 15 +++--- .../mage/cards/s/SynchronizedSpellcraft.java | 23 ++------ .../src/mage/cards/t/TheFallOfKroog.java | 12 ++--- Mage.Sets/src/mage/cards/t/TrickShot.java | 10 +--- Mage.Sets/src/mage/cards/u/UnleashShell.java | 10 ++-- Mage.Sets/src/mage/cards/w/WildfireHowl.java | 2 + .../DamageTargetAndAllControlledEffect.java | 18 +++++-- ...DamageTargetAndTargetControllerEffect.java | 12 +++-- 55 files changed, 397 insertions(+), 572 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/ArcTrail.java b/Mage.Sets/src/mage/cards/a/ArcTrail.java index 2a7a57ede4f..703e3c7ecf8 100644 --- a/Mage.Sets/src/mage/cards/a/ArcTrail.java +++ b/Mage.Sets/src/mage/cards/a/ArcTrail.java @@ -29,8 +29,10 @@ public final class ArcTrail extends CardImpl { // Arc Trail deals 2 damage to any target and 1 damage to another target this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 1)); - this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter1).setTargetTag(1)); - this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter2).setTargetTag(2)); + this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter1) + .withChooseHint("to deal 2 damage").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter2) + .withChooseHint("to deal 1 damage").setTargetTag(2)); } private ArcTrail(final ArcTrail card) { diff --git a/Mage.Sets/src/mage/cards/a/AssembledAlphas.java b/Mage.Sets/src/mage/cards/a/AssembledAlphas.java index dd5ca0e07cf..fbb15e6b892 100644 --- a/Mage.Sets/src/mage/cards/a/AssembledAlphas.java +++ b/Mage.Sets/src/mage/cards/a/AssembledAlphas.java @@ -1,16 +1,14 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.BlocksOrBlockedByCreatureSourceTriggeredAbility; -import mage.abilities.effects.common.DamageTargetControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.StaticFilters; + +import java.util.UUID; /** * @@ -25,9 +23,8 @@ public final class AssembledAlphas extends CardImpl { this.toughness = new MageInt(5); // Whenever Assembled Alphas blocks or becomes blocked by a creature, Assembled Alphas deals 3 damage to that creature and 3 damage to that creature's controller. - Ability ability = new BlocksOrBlockedByCreatureSourceTriggeredAbility(new DamageTargetEffect(3, true, "that creature")); - ability.addEffect(new DamageTargetControllerEffect(3).setText("and 3 damage to that creature's controller")); - this.addAbility(ability); + this.addAbility(new BlocksOrBlockedByCreatureSourceTriggeredAbility( + new DamageTargetAndTargetControllerEffect(3, 3))); } private AssembledAlphas(final AssembledAlphas card) { diff --git a/Mage.Sets/src/mage/cards/b/BellowingFiend.java b/Mage.Sets/src/mage/cards/b/BellowingFiend.java index 7638ae26eb9..b38acec47c7 100644 --- a/Mage.Sets/src/mage/cards/b/BellowingFiend.java +++ b/Mage.Sets/src/mage/cards/b/BellowingFiend.java @@ -3,9 +3,7 @@ package mage.cards.b; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsDamageToACreatureTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,12 +29,10 @@ public final class BellowingFiend extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // Whenever Bellowing Fiend deals damage to a creature, Bellowing Fiend deals 3 damage to that creature's controller and 3 damage to you. - Ability ability = new DealsDamageToACreatureTriggeredAbility(new BellowingFiendEffect(), false, false, true); - Effect effect = new DamageControllerEffect(3); - effect.setText("and 3 damage to you"); - ability.addEffect(effect); - this.addAbility(ability); + this.addAbility(new DealsDamageToACreatureTriggeredAbility( + new BellowingFiendEffect(), false, false, true)); } private BellowingFiend(final BellowingFiend card) { @@ -53,7 +49,7 @@ class BellowingFiendEffect extends OneShotEffect { BellowingFiendEffect() { super(Outcome.Detriment); - this.staticText = "{this} deals 3 damage to that creature's controller"; + this.staticText = "{this} deals 3 damage to that creature's controller and 3 damage to you"; } private BellowingFiendEffect(final BellowingFiendEffect effect) { @@ -67,15 +63,17 @@ class BellowingFiendEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - boolean applied = false; Permanent damagedCreature = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); if (damagedCreature != null) { Player controller = game.getPlayer(damagedCreature.getControllerId()); if (controller != null) { controller.damage(3, source.getSourceId(), source, game); - applied = true; } } - return applied; + Player you = game.getPlayer(source.getControllerId()); + if (you != null) { + you.damage(3, source.getSourceId(), source, game); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/b/BurningSunsAvatar.java b/Mage.Sets/src/mage/cards/b/BurningSunsAvatar.java index 0aca1c22fc8..4394b57717d 100644 --- a/Mage.Sets/src/mage/cards/b/BurningSunsAvatar.java +++ b/Mage.Sets/src/mage/cards/b/BurningSunsAvatar.java @@ -1,12 +1,9 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -14,6 +11,8 @@ import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponentOrPlaneswalker; +import java.util.UUID; + /** * * @author TheElk801 @@ -29,11 +28,9 @@ public final class BurningSunsAvatar extends CardImpl { this.toughness = new MageInt(6); // When Burning Sun's Avatar enters the battlefield, it deals 3 damage to target opponent and 3 damage to up to one target creature. - Effect effect = new DamageTargetEffect(3); - effect.setText("it deals 3 damage to target opponent or planeswalker and 3 damage to up to one target creature"); - Ability ability = new EntersBattlefieldTriggeredAbility(effect, false); - ability.addTarget(new TargetOpponentOrPlaneswalker()); - ability.addTarget(new TargetCreaturePermanent(0, 1)); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetAndTargetEffect(3, 3)); + ability.addTarget(new TargetOpponentOrPlaneswalker().setTargetTag(1)); + ability.addTarget(new TargetCreaturePermanent(0, 1).setTargetTag(2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java b/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java index 8ff9875068c..33452f3972e 100644 --- a/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java +++ b/Mage.Sets/src/mage/cards/c/CarnivalCarnage.java @@ -1,6 +1,6 @@ package mage.cards.c; -import mage.abilities.effects.common.DamageTargetControllerEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardSetInfo; @@ -22,8 +22,7 @@ public final class CarnivalCarnage extends SplitCard { // Carnival // Carnival deals 1 damage to target creature or planeswalker and 1 damage to that permanent's controller. - this.getLeftHalfCard().getSpellAbility().addEffect(new DamageTargetEffect(1)); - this.getLeftHalfCard().getSpellAbility().addEffect(new DamageTargetControllerEffect(1).setText("and 1 damage to that permanent's controller")); + this.getLeftHalfCard().getSpellAbility().addEffect(new DamageTargetAndTargetControllerEffect(1, 1)); this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker()); // Carnage diff --git a/Mage.Sets/src/mage/cards/c/ChandraFlamesFury.java b/Mage.Sets/src/mage/cards/c/ChandraFlamesFury.java index a3303380cae..16beae1a99b 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraFlamesFury.java +++ b/Mage.Sets/src/mage/cards/c/ChandraFlamesFury.java @@ -2,19 +2,14 @@ package mage.cards.c; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DamageAllControlledTargetEffect; +import mage.abilities.effects.common.DamageTargetAndAllControlledEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.abilities.effects.common.DamageTargetEffect; 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.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetCreaturePermanent; @@ -39,15 +34,12 @@ public final class ChandraFlamesFury extends CardImpl { this.addAbility(ability); // −2: Chandra, Flame's Fury deals 4 damage to target creature and 2 damage to that creature's controller. - ability = new LoyaltyAbility(new ChandraFlamesFuryEffect(), -2); + ability = new LoyaltyAbility(new DamageTargetAndTargetControllerEffect(4, 2), -2); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); // −8: Chandra, Flame's Fury deals 10 damage to target player and each creature that player controls. - ability = new LoyaltyAbility(new DamageTargetEffect(10), -8); - ability.addEffect(new DamageAllControlledTargetEffect( - 10, StaticFilters.FILTER_PERMANENT_CREATURE - ).setText("and each creature that player controls")); + ability = new LoyaltyAbility(new DamageTargetAndAllControlledEffect(10), -8); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } @@ -61,35 +53,3 @@ public final class ChandraFlamesFury extends CardImpl { return new ChandraFlamesFury(this); } } - -class ChandraFlamesFuryEffect extends OneShotEffect { - - ChandraFlamesFuryEffect() { - super(Outcome.Benefit); - staticText = "{this} deals 4 damage to target creature and 2 damage to that creature's controller."; - } - - private ChandraFlamesFuryEffect(final ChandraFlamesFuryEffect effect) { - super(effect); - } - - @Override - public ChandraFlamesFuryEffect copy() { - return new ChandraFlamesFuryEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent == null) { - return false; - } - Player player = game.getPlayer(permanent.getControllerId()); - if (player == null) { - return false; - } - permanent.damage(4, source.getSourceId(), source, game); - player.damage(2, source.getSourceId(), source, game); - return true; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java b/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java index 035f31d6a6d..8a8b4880a1b 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java +++ b/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java @@ -36,8 +36,7 @@ public final class ChandraPyromaster extends CardImpl { this.setStartingLoyalty(4); - // +1: Chandra, Pyromaster deals 1 damage to target player and 1 damage to - // up to one target creature that player controls. That creature can't block this turn. + // +1: Chandra, Pyromaster deals 1 damage to target player and 1 damage to up to one target creature that player controls. That creature can't block this turn. LoyaltyAbility ability1 = new LoyaltyAbility(new ChandraPyromasterEffect1(), 1); Target target1 = new TargetPlayerOrPlaneswalker(); ability1.addTarget(target1); @@ -68,7 +67,7 @@ public final class ChandraPyromaster extends CardImpl { class ChandraPyromasterEffect1 extends OneShotEffect { - public ChandraPyromasterEffect1() { + ChandraPyromasterEffect1() { super(Outcome.Damage); staticText = "{this} deals 1 damage to target player or planeswalker " + "and 1 damage to up to one target creature that player or that " @@ -101,7 +100,7 @@ class ChandraPyromasterEffect1 extends OneShotEffect { class ChandraPyromasterTarget extends TargetPermanent { - public ChandraPyromasterTarget() { + ChandraPyromasterTarget() { super(0, 1, new FilterCreaturePermanent("creature that the targeted player " + "or planeswalker's controller controls"), false); } @@ -138,7 +137,7 @@ class ChandraPyromasterTarget extends TargetPermanent { class ChandraPyromasterEffect2 extends OneShotEffect { - public ChandraPyromasterEffect2() { + ChandraPyromasterEffect2() { super(Outcome.Detriment); this.staticText = "Exile the top card of your library. You may play it this turn"; } diff --git a/Mage.Sets/src/mage/cards/c/ConductElectricity.java b/Mage.Sets/src/mage/cards/c/ConductElectricity.java index 335dae1cb40..339fddbc851 100644 --- a/Mage.Sets/src/mage/cards/c/ConductElectricity.java +++ b/Mage.Sets/src/mage/cards/c/ConductElectricity.java @@ -1,13 +1,12 @@ package mage.cards.c; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.SecondTargetPointer; import java.util.UUID; @@ -20,16 +19,11 @@ public final class ConductElectricity extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}"); // Conduct Electricity deals 6 damage to target creature and 2 damage to up to one target creature token. - this.getSpellAbility().addEffect(new DamageTargetEffect( - 6, true, "", true - )); - this.getSpellAbility().addEffect(new DamageTargetEffect( - 2, true, "", true - ).setTargetPointer(new SecondTargetPointer()).setText("and 2 damage to up to one target creature token")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(6, 2)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); this.getSpellAbility().addTarget(new TargetPermanent( 0, 1, StaticFilters.FILTER_CREATURE_TOKEN - )); + ).setTargetTag(2)); } private ConductElectricity(final ConductElectricity card) { diff --git a/Mage.Sets/src/mage/cards/c/CunningStrike.java b/Mage.Sets/src/mage/cards/c/CunningStrike.java index e3bdf684b9d..0b1d21da301 100644 --- a/Mage.Sets/src/mage/cards/c/CunningStrike.java +++ b/Mage.Sets/src/mage/cards/c/CunningStrike.java @@ -1,17 +1,14 @@ - package mage.cards.c; -import java.util.UUID; -import mage.abilities.dynamicvalue.common.StaticValue; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; -import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; /** * @@ -22,14 +19,11 @@ public final class CunningStrike extends CardImpl { public CunningStrike(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{R}"); - // Cunning Strike deals 2 damage to target creature and 2 damage to target player. - this.getSpellAbility().addEffect(new DamageTargetEffect(StaticValue.get(2), true, "", true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - Effect effect = new DamageTargetEffect(StaticValue.get(2), true, "", true); - effect.setTargetPointer(new SecondTargetPointer()); - effect.setText("and 2 damage to target player or planeswalker"); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); + // Cunning Strike deals 2 damage to target creature and 2 damage to target player or planeswalker. + this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 2)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(2)); + // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); } diff --git a/Mage.Sets/src/mage/cards/c/CuombajjWitches.java b/Mage.Sets/src/mage/cards/c/CuombajjWitches.java index 2389a6b11b8..79029a89b03 100644 --- a/Mage.Sets/src/mage/cards/c/CuombajjWitches.java +++ b/Mage.Sets/src/mage/cards/c/CuombajjWitches.java @@ -1,4 +1,3 @@ - package mage.cards.c; import mage.MageInt; @@ -12,13 +11,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; import mage.game.Game; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetOpponent; import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -35,7 +34,7 @@ public final class CuombajjWitches extends CardImpl { this.toughness = new MageInt(3); // {T}: Cuombajj Witches deals 1 damage to any target and 1 damage to any target of an opponent's choice. - Effect effect = new DamageTargetEffect(1); + Effect effect = new DamageTargetEffect(1).setTargetPointer(new EachTargetPointer()); effect.setText("{this} deals 1 damage to any target and 1 damage to any target of an opponent's choice"); Ability ability = new SimpleActivatedAbility(effect, new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/d/DaggerCaster.java b/Mage.Sets/src/mage/cards/d/DaggerCaster.java index aed8e187569..18a7388ae79 100644 --- a/Mage.Sets/src/mage/cards/d/DaggerCaster.java +++ b/Mage.Sets/src/mage/cards/d/DaggerCaster.java @@ -3,14 +3,17 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.effects.common.DamagePlayersEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.StaticFilters; +import mage.game.Game; import java.util.UUID; @@ -28,14 +31,7 @@ public final class DaggerCaster extends CardImpl { this.toughness = new MageInt(3); // When Dagger Caster enters the battlefield, it deals 1 damage to each opponent and 1 damage to each creature your opponents control. - Ability ability = new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect( - 1, TargetController.OPPONENT, "it" - )); - ability.addEffect( - new DamageAllEffect(1, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE) - .setText("and 1 damage to each creature your opponents control") - ); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DaggerCasterEffect())); } private DaggerCaster(final DaggerCaster card) { @@ -47,3 +43,29 @@ public final class DaggerCaster extends CardImpl { return new DaggerCaster(this); } } + +// needed for simultaneous damage +class DaggerCasterEffect extends OneShotEffect { + + DaggerCasterEffect() { + super(Outcome.Damage); + staticText = "it deals 1 damage to each opponent and 1 damage to each creature your opponents control"; + } + + private DaggerCasterEffect(final DaggerCasterEffect effect) { + super(effect); + } + + @Override + public DaggerCasterEffect copy() { + return new DaggerCasterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + new DamagePlayersEffect(1, TargetController.OPPONENT, "it").apply(game, source); + new DamageAllEffect(1, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE).apply(game, source); + return true; + } + +} diff --git a/Mage.Sets/src/mage/cards/d/DragonsparkReactor.java b/Mage.Sets/src/mage/cards/d/DragonsparkReactor.java index 45469a4de18..0f9d6fcbdd3 100644 --- a/Mage.Sets/src/mage/cards/d/DragonsparkReactor.java +++ b/Mage.Sets/src/mage/cards/d/DragonsparkReactor.java @@ -16,6 +16,7 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -40,7 +41,7 @@ public final class DragonsparkReactor extends CardImpl { new DamageTargetEffect(xValue).setText( "it deals damage equal to the number of charge counters on it to target player " + "and that much damage to up to one target creature" - ), new GenericManaCost(4) + ).setTargetPointer(new EachTargetPointer()), new GenericManaCost(4) ); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetPlayer()); diff --git a/Mage.Sets/src/mage/cards/d/DrakusethMawOfFlames.java b/Mage.Sets/src/mage/cards/d/DrakusethMawOfFlames.java index 5b05e77d8d3..be989545f08 100644 --- a/Mage.Sets/src/mage/cards/d/DrakusethMawOfFlames.java +++ b/Mage.Sets/src/mage/cards/d/DrakusethMawOfFlames.java @@ -3,20 +3,16 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.abilities.keyword.FlyingAbility; 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.filter.common.FilterAnyTarget; import mage.filter.common.FilterPermanentOrPlayer; import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetPermanentOrPlayer; @@ -26,6 +22,7 @@ import java.util.UUID; * @author TheElk801 */ public final class DrakusethMawOfFlames extends CardImpl { + private static final FilterPermanentOrPlayer filter = new FilterAnyTarget("any target"); static { @@ -45,7 +42,8 @@ public final class DrakusethMawOfFlames extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Drakuseth, Maw of Flames attacks, it deals 4 damage to any target and 3 damage to each of up to two other targets. - Ability ability = new AttacksTriggeredAbility(new DrakusethMawOfFlamesEffect(), false); + Ability ability = new AttacksTriggeredAbility(new DamageTargetAndTargetEffect(4, 3) + .setText("it deals 4 damage to any target and 3 damage to each of up to two other targets")); ability.addTarget(new TargetAnyTarget().withChooseHint("to deal 4 damage").setTargetTag(1)); ability.addTarget(new TargetPermanentOrPlayer( 0, 2, filter, false @@ -62,43 +60,3 @@ public final class DrakusethMawOfFlames extends CardImpl { return new DrakusethMawOfFlames(this); } } - -class DrakusethMawOfFlamesEffect extends OneShotEffect { - - DrakusethMawOfFlamesEffect() { - super(Outcome.Damage); - staticText = "it deals 4 damage to any target and 3 damage to each of " - + "up to two other targets."; - } - - private DrakusethMawOfFlamesEffect(final DrakusethMawOfFlamesEffect effect) { - super(effect); - } - - @Override - public DrakusethMawOfFlamesEffect copy() { - return new DrakusethMawOfFlamesEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - damage(4, source.getTargets().get(0).getFirstTarget(), game, source); - source.getTargets() - .get(1) - .getTargets() - .stream() - .forEach(targetId -> damage(3, targetId, game, source)); - return true; - } - - private static void damage(int damage, UUID targetId, Game game, Ability source) { - Permanent permanent = game.getPermanent(targetId); - if (permanent != null) { - permanent.damage(damage, source.getSourceId(), source, game, false, true); - } - Player player = game.getPlayer(targetId); - if (player != null) { - player.damage(damage, source.getSourceId(), source, game); - } - } -} diff --git a/Mage.Sets/src/mage/cards/e/ExplosiveWelcome.java b/Mage.Sets/src/mage/cards/e/ExplosiveWelcome.java index a38deebd541..34d261a336d 100644 --- a/Mage.Sets/src/mage/cards/e/ExplosiveWelcome.java +++ b/Mage.Sets/src/mage/cards/e/ExplosiveWelcome.java @@ -1,8 +1,7 @@ package mage.cards.e; import mage.Mana; -import mage.abilities.dynamicvalue.common.StaticValue; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.abilities.effects.mana.BasicManaEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -11,10 +10,8 @@ import mage.constants.ManaType; import mage.filter.common.FilterAnyTarget; import mage.filter.common.FilterPermanentOrPlayer; import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.target.Target; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetPermanentOrPlayer; -import mage.target.targetpointer.SecondTargetPointer; import java.util.UUID; @@ -34,19 +31,12 @@ public final class ExplosiveWelcome extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{7}{R}"); // Explosive Welcome deals 5 damage to any target and 3 damage to any other target. Add {R}{R}{R}. - this.getSpellAbility().addEffect(new DamageTargetEffect(StaticValue.get(5), true, "", true)); - this.getSpellAbility().addEffect( - new DamageTargetEffect(StaticValue.get(3), true, "", true) - .setTargetPointer(new SecondTargetPointer()) - .setText("and 3 damage to any other target.") - ); + this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(5, 3)); this.getSpellAbility().addEffect(new BasicManaEffect(new Mana(ManaType.RED, 3))); - Target target = new TargetAnyTarget(); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); - target = new TargetPermanentOrPlayer(filter); - target.setTargetTag(2); - this.getSpellAbility().addTarget(target); + this.getSpellAbility().addTarget(new TargetAnyTarget() + .withChooseHint("to deal 5 damage").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter) + .withChooseHint("to deal 3 damage").setTargetTag(2)); } private ExplosiveWelcome(final ExplosiveWelcome card) { diff --git a/Mage.Sets/src/mage/cards/f/FearFireFoes.java b/Mage.Sets/src/mage/cards/f/FearFireFoes.java index 230a0c21a29..0e598e70321 100644 --- a/Mage.Sets/src/mage/cards/f/FearFireFoes.java +++ b/Mage.Sets/src/mage/cards/f/FearFireFoes.java @@ -34,7 +34,6 @@ public final class FearFireFoes extends CardImpl { this.getSpellAbility().addEffect(new DamageCantBePreventedEffect( Duration.EndOfTurn )); - this.getSpellAbility().addEffect(new DamageTargetEffect(GetXValue.instance)); this.getSpellAbility().addEffect(new FearFireFoesEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } @@ -53,7 +52,8 @@ class FearFireFoesEffect extends OneShotEffect { FearFireFoesEffect() { super(Outcome.Benefit); - staticText = "and 1 damage to each other creature with the same controller"; + staticText = "{this} deals X damage to target creature " + + "and 1 damage to each other creature with the same controller"; } private FearFireFoesEffect(final FearFireFoesEffect effect) { @@ -67,6 +67,7 @@ class FearFireFoesEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + new DamageTargetEffect(GetXValue.instance).apply(game, source); Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent == null) { return false; diff --git a/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java b/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java index f7258a53ac3..701183efdd5 100644 --- a/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java +++ b/Mage.Sets/src/mage/cards/f/FireAndBrimstone.java @@ -1,7 +1,6 @@ package mage.cards.f; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -30,8 +29,7 @@ public final class FireAndBrimstone extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}{W}"); // Fire and Brimstone deals 4 damage to target player who attacked this turn and 4 damage to you. - this.getSpellAbility().addEffect(new DamageTargetEffect(4)); - this.getSpellAbility().addEffect(new DamageControllerEffect(4).setText("and 4 damage to you")); + this.getSpellAbility().addEffect(new DamageTargetAndYouEffect(4)); this.getSpellAbility().addTarget(new TargetPlayer(1, 1, false, filter)); } diff --git a/Mage.Sets/src/mage/cards/f/Fireslinger.java b/Mage.Sets/src/mage/cards/f/Fireslinger.java index d0312a29d12..92e78e6cb22 100644 --- a/Mage.Sets/src/mage/cards/f/Fireslinger.java +++ b/Mage.Sets/src/mage/cards/f/Fireslinger.java @@ -4,8 +4,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -26,8 +25,7 @@ public final class Fireslinger extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost()); - ability.addEffect(new DamageControllerEffect(1).setText("and 1 damage to you")); + Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(1), new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/Firespout.java b/Mage.Sets/src/mage/cards/f/Firespout.java index c8ed77f2799..a992ca121da 100644 --- a/Mage.Sets/src/mage/cards/f/Firespout.java +++ b/Mage.Sets/src/mage/cards/f/Firespout.java @@ -1,17 +1,20 @@ - package mage.cards.f; +import mage.abilities.Ability; import mage.abilities.condition.common.ManaWasSpentCondition; import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Outcome; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.game.Game; import java.util.UUID; @@ -30,12 +33,8 @@ public final class Firespout extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R/G}"); // Firespout deals 3 damage to each creature without flying if {R} was spent to cast Firespout and 3 damage to each creature with flying if {G} was spent to cast it. - this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new DamageAllEffect(3, filter1), - ManaWasSpentCondition.RED, "{this} deals 3 damage to each creature without flying if {R} was spent to cast this spell")); - this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new DamageAllEffect(3, StaticFilters.FILTER_CREATURE_FLYING), - ManaWasSpentCondition.GREEN, "and 3 damage to each creature with flying if {G} was spent to cast this spell. (Do both if {R}{G} was spent.)")); + this.getSpellAbility().addEffect(new FirespoutEffect()); + } private Firespout(final Firespout card) { @@ -47,3 +46,37 @@ public final class Firespout extends CardImpl { return new Firespout(this); } } + +// needed for simultaneous damage +class FirespoutEffect extends OneShotEffect { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature without flying"); + static { + filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); + } + + FirespoutEffect() { + super(Outcome.Benefit); + staticText = "{this} deals 3 damage to each creature without flying if {R} was spent to cast this spell " + + "and 3 damage to each creature with flying if {G} was spent to cast this spell. " + + "(Do both if {R}{G} was spent.)"; + } + + private FirespoutEffect(final FirespoutEffect effect) { + super(effect); + } + + @Override + public FirespoutEffect copy() { + return new FirespoutEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + new ConditionalOneShotEffect(new DamageAllEffect(3, filter), + ManaWasSpentCondition.RED).apply(game, source); + new ConditionalOneShotEffect(new DamageAllEffect(3, StaticFilters.FILTER_CREATURE_FLYING), + ManaWasSpentCondition.GREEN).apply(game, source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/f/FirstVolley.java b/Mage.Sets/src/mage/cards/f/FirstVolley.java index 8186188eeae..da125cec8a0 100644 --- a/Mage.Sets/src/mage/cards/f/FirstVolley.java +++ b/Mage.Sets/src/mage/cards/f/FirstVolley.java @@ -1,9 +1,6 @@ - package mage.cards.f; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageTargetControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -23,10 +20,7 @@ public final class FirstVolley extends CardImpl { this.subtype.add(SubType.ARCANE); // First Volley deals 1 damage to target creature and 1 damage to that creature's controller. - this.getSpellAbility().addEffect(new DamageTargetEffect(1)); - Effect effect = new DamageTargetControllerEffect(1); - effect.setText("and 1 damage to that creature's controller"); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new DamageTargetAndTargetControllerEffect(1, 1)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/f/ForgeDevil.java b/Mage.Sets/src/mage/cards/f/ForgeDevil.java index 6229e8bbba7..a5ce17b7fa7 100644 --- a/Mage.Sets/src/mage/cards/f/ForgeDevil.java +++ b/Mage.Sets/src/mage/cards/f/ForgeDevil.java @@ -1,22 +1,20 @@ - package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * - * @author anonymous + * @author xenohedron */ public final class ForgeDevil extends CardImpl { @@ -28,13 +26,8 @@ public final class ForgeDevil extends CardImpl { this.toughness = new MageInt(1); // When Forge Devil enters the battlefield, it deals 1 damage to target creature and 1 damage to you. - Effect effect = new DamageTargetEffect(1); - effect.setText("it deals 1 damage to target creature"); - Ability ability = new EntersBattlefieldTriggeredAbility(effect); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetAndYouEffect(1)); ability.addTarget(new TargetCreaturePermanent()); - effect = new DamageControllerEffect(1); - effect.setText("and 1 damage to you"); - ability.addEffect(effect); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinArtillery.java b/Mage.Sets/src/mage/cards/g/GoblinArtillery.java index 77b0946d7be..c5c19053734 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinArtillery.java +++ b/Mage.Sets/src/mage/cards/g/GoblinArtillery.java @@ -4,8 +4,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -26,8 +25,9 @@ public final class GoblinArtillery extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(3); - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapSourceCost()); - ability.addEffect(new DamageControllerEffect(3).setText("and 3 damage to you")); + + // {T}: This creature deals 2 damage to any target and 3 damage to you. + Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(2, 3), new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GrangerGuildmage.java b/Mage.Sets/src/mage/cards/g/GrangerGuildmage.java index aa45d3eb1c8..c7dbd57ec8f 100644 --- a/Mage.Sets/src/mage/cards/g/GrangerGuildmage.java +++ b/Mage.Sets/src/mage/cards/g/GrangerGuildmage.java @@ -1,25 +1,23 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author fireshoes @@ -34,9 +32,8 @@ public final class GrangerGuildmage extends CardImpl { this.toughness = new MageInt(1); // {R}, {tap}: Granger Guildmage deals 1 damage to any target and 1 damage to you. - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{R}")); + Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(1, 1), new ManaCostsImpl<>("{R}")); ability.addCost(new TapSourceCost()); - ability.addEffect(new DamageControllerEffect(1).setText("and 1 damage to you")); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HailStorm.java b/Mage.Sets/src/mage/cards/h/HailStorm.java index 8668f420724..71c0938b515 100644 --- a/Mage.Sets/src/mage/cards/h/HailStorm.java +++ b/Mage.Sets/src/mage/cards/h/HailStorm.java @@ -1,14 +1,18 @@ - package mage.cards.h; -import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.effects.common.DamageControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Outcome; import mage.filter.StaticFilters; import mage.filter.common.FilterAttackingCreature; +import mage.game.Game; + +import java.util.UUID; /** * @@ -20,9 +24,7 @@ public final class HailStorm extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}{G}"); // Hail Storm deals 2 damage to each attacking creature and 1 damage to you and each creature you control. - this.getSpellAbility().addEffect(new DamageAllEffect(2, new FilterAttackingCreature())); - this.getSpellAbility().addEffect(new DamageControllerEffect(1).setText("and 1 damage to you")); - this.getSpellAbility().addEffect(new DamageAllEffect(1, StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED).setText("and each creature you control.")); + this.getSpellAbility().addEffect(new HailStormEffect()); } private HailStorm(final HailStorm card) { @@ -34,3 +36,32 @@ public final class HailStorm extends CardImpl { return new HailStorm(this); } } + +// needed for simultaneous damage +class HailStormEffect extends OneShotEffect { + + private static final FilterAttackingCreature filter = new FilterAttackingCreature(); + + HailStormEffect() { + super(Outcome.Benefit); + staticText = "{this} deals 2 damage to each attacking creature " + + "and 1 damage to you and each creature you control"; + } + + private HailStormEffect(final HailStormEffect effect) { + super(effect); + } + + @Override + public HailStormEffect copy() { + return new HailStormEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + new DamageAllEffect(2, filter).apply(game, source); + new DamageControllerEffect(1).apply(game, source); + new DamageAllEffect(1, StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED).apply(game, source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/h/HungryFlames.java b/Mage.Sets/src/mage/cards/h/HungryFlames.java index bd704cb8b14..d458bb6b8d2 100644 --- a/Mage.Sets/src/mage/cards/h/HungryFlames.java +++ b/Mage.Sets/src/mage/cards/h/HungryFlames.java @@ -1,14 +1,9 @@ package mage.cards.h; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; @@ -22,10 +17,10 @@ public final class HungryFlames extends CardImpl { public HungryFlames(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}"); - // Hungry Flames deals 3 damage to target creature and 2 damage to target player. - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); - this.getSpellAbility().addEffect(new HungryFlamesEffect()); + // Hungry Flames deals 3 damage to target creature and 2 damage to target player or planeswalker. + this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(2)); + this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(3, 2)); } private HungryFlames(final HungryFlames card) { @@ -37,37 +32,4 @@ public final class HungryFlames extends CardImpl { return new HungryFlames(this); } - private static class HungryFlamesEffect extends OneShotEffect { - - HungryFlamesEffect() { - super(Outcome.Damage); - this.staticText = "{this} deals 3 damage to target creature and 2 damage to target player or planeswalker"; - } - - private HungryFlamesEffect(final HungryFlamesEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getTargets().get(0).getFirstTarget()); - Player player = game.getPlayer(source.getTargets().get(1).getFirstTarget()); - - if (permanent != null) { - permanent.damage(3, source.getSourceId(), source, game, false, true); - } - - if (player != null) { - player.damage(2, source.getSourceId(), source, game); - } - - return true; - } - - @Override - public HungryFlamesEffect copy() { - return new HungryFlamesEffect(this); - } - } - } diff --git a/Mage.Sets/src/mage/cards/i/InsultInjury.java b/Mage.Sets/src/mage/cards/i/InsultInjury.java index 9a9caea0e0c..a55864cd52c 100644 --- a/Mage.Sets/src/mage/cards/i/InsultInjury.java +++ b/Mage.Sets/src/mage/cards/i/InsultInjury.java @@ -1,8 +1,8 @@ package mage.cards.i; import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.continuous.DamageCantBePreventedEffect; import mage.abilities.keyword.AftermathAbility; import mage.cards.CardSetInfo; @@ -13,10 +13,9 @@ import mage.constants.Outcome; import mage.constants.SpellAbilityType; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; +import mage.target.targetpointer.EachTargetPointer; import mage.util.CardUtil; import java.util.UUID; @@ -41,7 +40,7 @@ public final class InsultInjury extends SplitCard { getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); getRightHalfCard().getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); - getRightHalfCard().getSpellAbility().addEffect(new InjuryEffect()); + getRightHalfCard().getSpellAbility().addEffect(new DamageTargetEffect(2).setTargetPointer(new EachTargetPointer())); } private InsultInjury(final InsultInjury card) { @@ -87,36 +86,3 @@ class InsultDoubleDamageEffect extends ReplacementEffectImpl { return false; } } - -class InjuryEffect extends OneShotEffect { - - InjuryEffect() { - super(Outcome.Damage); - this.staticText = "{this} deals 2 damage to target creature and 2 damage to target player or planeswalker"; - } - - private InjuryEffect(final InjuryEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getTargets().get(0).getFirstTarget()); - Player player = game.getPlayer(source.getTargets().get(1).getFirstTarget()); - - if (permanent != null) { - permanent.damage(2, source.getSourceId(), source, game, false, true); - } - - if (player != null) { - player.damage(2, source.getSourceId(), source, game); - } - - return true; - } - - @Override - public InjuryEffect copy() { - return new InjuryEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/i/InvasionOfRegatha.java b/Mage.Sets/src/mage/cards/i/InvasionOfRegatha.java index 6096e876853..f6068787a4b 100644 --- a/Mage.Sets/src/mage/cards/i/InvasionOfRegatha.java +++ b/Mage.Sets/src/mage/cards/i/InvasionOfRegatha.java @@ -3,7 +3,7 @@ package mage.cards.i; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SiegeAbility; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -14,7 +14,6 @@ import mage.filter.common.FilterPermanentOrPlayer; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPermanentOrPlayer; -import mage.target.targetpointer.SecondTargetPointer; import java.util.UUID; @@ -43,19 +42,9 @@ public final class InvasionOfRegatha extends CardImpl { this.addAbility(new SiegeAbility()); // When Invasion of Regatha enters the battlefield, it deals 4 damage to another target battle or opponent and 1 damage to up to one target creature. - Ability ability = new EntersBattlefieldTriggeredAbility( - new DamageTargetEffect( - 4, true, - "another target battle or opponent", "it" - - ).setUseOnlyTargetPointer(true) - ); - ability.addTarget(new TargetPermanentOrPlayer(filter)); - ability.addEffect(new DamageTargetEffect(1) - .setUseOnlyTargetPointer(true) - .setTargetPointer(new SecondTargetPointer()) - .setText("and 1 damage to up to one target creature")); - ability.addTarget(new TargetCreaturePermanent(0, 1)); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetAndTargetEffect(4, 1)); + ability.addTarget(new TargetPermanentOrPlayer(filter).setTargetTag(1)); + ability.addTarget(new TargetCreaturePermanent(0, 1).setTargetTag(2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JudgmentBolt.java b/Mage.Sets/src/mage/cards/j/JudgmentBolt.java index d0581aa5d85..164fc2740aa 100644 --- a/Mage.Sets/src/mage/cards/j/JudgmentBolt.java +++ b/Mage.Sets/src/mage/cards/j/JudgmentBolt.java @@ -1,16 +1,19 @@ package mage.cards.j; +import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; -import mage.abilities.effects.common.DamageTargetControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.abilities.hint.Hint; import mage.abilities.hint.ValueHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -20,16 +23,14 @@ import java.util.UUID; */ public final class JudgmentBolt extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.EQUIPMENT)); + static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.EQUIPMENT)); private static final Hint hint = new ValueHint("Equipment you control", xValue); public JudgmentBolt(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}"); // Judgment Bolt deals 5 damage to target creature and X damage to that creature's controller, where X is the number of Equipment you control. - this.getSpellAbility().addEffect(new DamageTargetEffect(5)); - this.getSpellAbility().addEffect(new DamageTargetControllerEffect(xValue) - .setText("and X damage to that creature's controller, where X is the number of Equipment you control")); + this.getSpellAbility().addEffect(new JudgmentBoltEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addHint(hint); } @@ -43,3 +44,28 @@ public final class JudgmentBolt extends CardImpl { return new JudgmentBolt(this); } } + +// too lazy to handle dynamic value properly in the common class +class JudgmentBoltEffect extends OneShotEffect { + + JudgmentBoltEffect() { + super(Outcome.Benefit); + staticText = "{this} deals 5 damage to target creature and X damage to that creature's controller," + + " where X is the number of Equipment you control"; + } + + private JudgmentBoltEffect(final JudgmentBoltEffect effect) { + super(effect); + } + + @Override + public JudgmentBoltEffect copy() { + return new JudgmentBoltEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return new DamageTargetAndTargetControllerEffect(5, JudgmentBolt.xValue.calculate(game, source, this)) + .apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KamahlsSledge.java b/Mage.Sets/src/mage/cards/k/KamahlsSledge.java index 2349adb94c2..38f2f014855 100644 --- a/Mage.Sets/src/mage/cards/k/KamahlsSledge.java +++ b/Mage.Sets/src/mage/cards/k/KamahlsSledge.java @@ -2,7 +2,7 @@ package mage.cards.k; import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.effects.common.DamageTargetControllerEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -21,15 +21,16 @@ public final class KamahlsSledge extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{R}{R}"); // Kamahl's Sledge deals 4 damage to target creature. - this.getSpellAbility().addEffect(new DamageTargetEffect(4)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - // Threshold - If seven or more cards are in your graveyard, instead Kamahl's Sledge deals 4 damage to that creature and 4 damage to that creature's controller. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( - new DamageTargetControllerEffect(4), ThresholdCondition.instance, "
" + - AbilityWord.THRESHOLD.formatWord() + "If seven or more cards are in your graveyard, " + - "instead {this} deals 4 damage to that creature and 4 damage to that creature's controller." + new DamageTargetAndTargetControllerEffect(4, 4), + new DamageTargetEffect(4), + ThresholdCondition.instance, + "{this} deals 4 damage to target creature.
" + + AbilityWord.THRESHOLD.formatWord() + "If seven or more cards are in your graveyard, " + + "instead {this} deals 4 damage to that creature and 4 damage to that creature's controller." )); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } private KamahlsSledge(final KamahlsSledge card) { diff --git a/Mage.Sets/src/mage/cards/l/Lunge.java b/Mage.Sets/src/mage/cards/l/Lunge.java index b3bb6efb96f..feb397b976c 100644 --- a/Mage.Sets/src/mage/cards/l/Lunge.java +++ b/Mage.Sets/src/mage/cards/l/Lunge.java @@ -1,15 +1,13 @@ - package mage.cards.l; -import java.util.UUID; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; -import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; /** * @@ -21,14 +19,10 @@ public final class Lunge extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}"); // Lunge deals 2 damage to target creature and 2 damage to target player. - this.getSpellAbility().addEffect(new DamageTargetEffect(2).setUseOnlyTargetPointer(true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 2)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(2)); - Effect effect = new DamageTargetEffect(2).setUseOnlyTargetPointer(true); - effect.setTargetPointer(new SecondTargetPointer()); - effect.setText("and 2 damage to target player or planeswalker"); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); } private Lunge(final Lunge card) { diff --git a/Mage.Sets/src/mage/cards/n/NeonatesRush.java b/Mage.Sets/src/mage/cards/n/NeonatesRush.java index 148c3eeb053..b907fd0b0b3 100644 --- a/Mage.Sets/src/mage/cards/n/NeonatesRush.java +++ b/Mage.Sets/src/mage/cards/n/NeonatesRush.java @@ -1,10 +1,9 @@ package mage.cards.n; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; import mage.abilities.hint.ConditionHint; @@ -12,13 +11,9 @@ import mage.abilities.hint.Hint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterPermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -42,7 +37,8 @@ public final class NeonatesRush extends CardImpl { ).addHint(hint).setRuleAtTheTop(true)); // Neonate's Rush deals 1 damage to target creature and 1 damage to its controller. Draw a card. - this.getSpellAbility().addEffect(new NeonatesRushEffect()); + this.getSpellAbility().addEffect(new DamageTargetAndTargetControllerEffect(1, 1) + .setText("{this} deals 1 damage to target creature and 1 damage to its controller")); this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } @@ -56,34 +52,3 @@ public final class NeonatesRush extends CardImpl { return new NeonatesRush(this); } } - -class NeonatesRushEffect extends OneShotEffect { - - NeonatesRushEffect() { - super(Outcome.Benefit); - staticText = "{this} deals 1 damage to target creature and 1 damage to its controller."; - } - - private NeonatesRushEffect(final NeonatesRushEffect effect) { - super(effect); - } - - @Override - public NeonatesRushEffect copy() { - return new NeonatesRushEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent == null) { - return false; - } - permanent.damage(1, source.getSourceId(), source, game); - Player player = game.getPlayer(permanent.getControllerId()); - if (player != null) { - player.damage(1, source.getSourceId(), source, game); - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/o/OrcishArtillery.java b/Mage.Sets/src/mage/cards/o/OrcishArtillery.java index c4589153f12..52f7b05ec24 100644 --- a/Mage.Sets/src/mage/cards/o/OrcishArtillery.java +++ b/Mage.Sets/src/mage/cards/o/OrcishArtillery.java @@ -1,20 +1,18 @@ - package mage.cards.o; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author Plopman @@ -30,9 +28,8 @@ public final class OrcishArtillery extends CardImpl { this.toughness = new MageInt(3); // {tap}: Orcish Artillery deals 2 damage to any target and 3 damage to you. - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(2, 3), new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); - ability.addEffect(new DamageControllerEffect(3).setText("and 3 damage to you")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OrcishCannonade.java b/Mage.Sets/src/mage/cards/o/OrcishCannonade.java index fe965ea9193..c33c70f1ae6 100644 --- a/Mage.Sets/src/mage/cards/o/OrcishCannonade.java +++ b/Mage.Sets/src/mage/cards/o/OrcishCannonade.java @@ -1,16 +1,14 @@ - package mage.cards.o; -import java.util.UUID; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author LevelX2 @@ -21,11 +19,9 @@ public final class OrcishCannonade extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}{R}"); // Orcish Cannonade deals 2 damage to any target and 3 damage to you. - this.getSpellAbility().addEffect(new DamageTargetEffect(2)); + this.getSpellAbility().addEffect(new DamageTargetAndYouEffect(2, 3)); this.getSpellAbility().addTarget(new TargetAnyTarget()); - Effect effect = new DamageControllerEffect(3); - effect.setText("and 3 damage to you"); - this.getSpellAbility().addEffect(effect); + // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); } diff --git a/Mage.Sets/src/mage/cards/o/OrcishCannoneers.java b/Mage.Sets/src/mage/cards/o/OrcishCannoneers.java index bf873ae3736..a2ad2abab8a 100644 --- a/Mage.Sets/src/mage/cards/o/OrcishCannoneers.java +++ b/Mage.Sets/src/mage/cards/o/OrcishCannoneers.java @@ -1,21 +1,18 @@ - package mage.cards.o; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author LoneFox @@ -31,10 +28,8 @@ public final class OrcishCannoneers extends CardImpl { this.toughness = new MageInt(3); // {tap}: Orcish Cannoneers deals 2 damage to any target and 3 damage to you. - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); - Effect effect = new DamageControllerEffect(3); - effect.setText("and 3 damage to you"); - ability.addEffect(effect); + Ability ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(2, 3), new TapSourceCost()); + ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PsionicBlast.java b/Mage.Sets/src/mage/cards/p/PsionicBlast.java index 254ff05fe3d..47ca09ad239 100644 --- a/Mage.Sets/src/mage/cards/p/PsionicBlast.java +++ b/Mage.Sets/src/mage/cards/p/PsionicBlast.java @@ -1,7 +1,6 @@ package mage.cards.p; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -18,8 +17,7 @@ public final class PsionicBlast extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); // Psionic Blast deals 4 damage to any target and 2 damage to you. - this.getSpellAbility().addEffect(new DamageTargetEffect(4)); - this.getSpellAbility().addEffect(new DamageControllerEffect(2).setText("and 2 damage to you")); + this.getSpellAbility().addEffect(new DamageTargetAndYouEffect(4, 2)); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/p/PsionicEntity.java b/Mage.Sets/src/mage/cards/p/PsionicEntity.java index 02b0b3a1e10..3c7121bef86 100644 --- a/Mage.Sets/src/mage/cards/p/PsionicEntity.java +++ b/Mage.Sets/src/mage/cards/p/PsionicEntity.java @@ -1,20 +1,18 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.common.DamageSelfEffect; -import mage.abilities.effects.common.DamageTargetEffect; -import mage.constants.SubType; +import mage.abilities.effects.common.DamageTargetAndSelfEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author TheElk801 @@ -29,8 +27,7 @@ public final class PsionicEntity extends CardImpl { this.toughness = new MageInt(2); // {tap}: Psionic Entity deals 2 damage to any target and 3 damage to itself. - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapSourceCost()); - ability.addEffect(new DamageSelfEffect(3).setText("and 3 damage to itself")); + Ability ability = new SimpleActivatedAbility(new DamageTargetAndSelfEffect(2, 3), new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PsionicSliver.java b/Mage.Sets/src/mage/cards/p/PsionicSliver.java index beb44bdeed6..08eb41473cb 100644 --- a/Mage.Sets/src/mage/cards/p/PsionicSliver.java +++ b/Mage.Sets/src/mage/cards/p/PsionicSliver.java @@ -1,28 +1,24 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.common.DamageSelfEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndSelfEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * - * @author anonymous - * @see mage.sets.seventhedition.RecklessEmbermage + * @author xenohedron */ public final class PsionicSliver extends CardImpl { @@ -35,11 +31,7 @@ public final class PsionicSliver extends CardImpl { this.toughness = new MageInt(2); // All Sliver creatures have "{T}: This creature deals 2 damage to any target and 3 damage to itself." - Ability ability = new SimpleActivatedAbility( - new DamageTargetEffect(2).setText("This creature deals 2 damage to any target"), - new TapSourceCost() - ); - ability.addEffect(new DamageSelfEffect(3).setText("3 damage to itself.")); + Ability ability = new SimpleActivatedAbility(new DamageTargetAndSelfEffect(2, 3), new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); this.addAbility( new SimpleStaticAbility(new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, filter, diff --git a/Mage.Sets/src/mage/cards/p/PunishTheEnemy.java b/Mage.Sets/src/mage/cards/p/PunishTheEnemy.java index aa474c088ee..a56e57185f6 100644 --- a/Mage.Sets/src/mage/cards/p/PunishTheEnemy.java +++ b/Mage.Sets/src/mage/cards/p/PunishTheEnemy.java @@ -1,15 +1,14 @@ - package mage.cards.p; -import java.util.UUID; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.target.Target; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; +import java.util.UUID; + /** * * @author LevelX2 @@ -20,11 +19,9 @@ public final class PunishTheEnemy extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}"); // Punish the Enemy deals 3 damage to target player and 3 damage to target creature. - this.getSpellAbility().addEffect(new DamageTargetEffect(3, true, "target player or planeswalker and 3 damage to target creature")); - Target target = new TargetPlayerOrPlaneswalker(); - this.getSpellAbility().addTarget(target); - target = new TargetCreaturePermanent(); - this.getSpellAbility().addTarget(target); + this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(3, 3)); + this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(2)); } private PunishTheEnemy(final PunishTheEnemy card) { diff --git a/Mage.Sets/src/mage/cards/r/RadiatingLightning.java b/Mage.Sets/src/mage/cards/r/RadiatingLightning.java index 106f3759b40..afd1b213b5d 100644 --- a/Mage.Sets/src/mage/cards/r/RadiatingLightning.java +++ b/Mage.Sets/src/mage/cards/r/RadiatingLightning.java @@ -1,12 +1,10 @@ - package mage.cards.r; -import mage.abilities.effects.common.DamageAllControlledTargetEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndAllControlledEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.StaticFilters; import mage.target.TargetPlayer; import java.util.UUID; @@ -20,10 +18,9 @@ public final class RadiatingLightning extends CardImpl { public RadiatingLightning(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{R}"); - // Radiating Lightning deals 3 damage to target player and 1 damage to each creature that player controls. - this.getSpellAbility().addEffect(new DamageTargetEffect(3)); - this.getSpellAbility().addEffect(new DamageAllControlledTargetEffect(1, new FilterCreaturePermanent()).setText("and 1 damage to each creature that player controls")); + this.getSpellAbility().addEffect(new DamageTargetAndAllControlledEffect( + 3, 1, StaticFilters.FILTER_PERMANENT_CREATURE)); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java b/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java index e9db64acfe7..aa004843f01 100644 --- a/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java +++ b/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java @@ -3,8 +3,7 @@ package mage.cards.r; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -29,11 +28,9 @@ public final class RakdosFirewheeler extends CardImpl { this.toughness = new MageInt(3); // When Rakdos Firewheeler enters the battlefield, it deals 2 damage to target opponent and 2 damage to up to one target creature or planeswalker. - Effect effect = new DamageTargetEffect(2); - effect.setText("it deals 2 damage to target opponent and 2 damage to up to one target creature or planeswalker"); - Ability ability = new EntersBattlefieldTriggeredAbility(effect, false); - ability.addTarget(new TargetOpponent()); - ability.addTarget(new TargetCreatureOrPlaneswalker(0, 1)); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetAndTargetEffect(2, 2)); + ability.addTarget(new TargetOpponent().setTargetTag(1)); + ability.addTarget(new TargetCreatureOrPlaneswalker(0, 1).setTargetTag(2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RecklessRage.java b/Mage.Sets/src/mage/cards/r/RecklessRage.java index 79b30f0ec35..c052f4c0c8a 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessRage.java +++ b/Mage.Sets/src/mage/cards/r/RecklessRage.java @@ -1,19 +1,15 @@ package mage.cards.r; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.SecondTargetPointer; import java.util.UUID; -import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; - /** * @author JayDi85 */ @@ -23,12 +19,9 @@ public final class RecklessRage extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); // Reckless Rage deals 4 damage to target creature you don't control and 2 damage to target creature you control. - this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); - this.getSpellAbility().addEffect(new DamageTargetEffect(4).setUseOnlyTargetPointer(true)); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addEffect(new DamageTargetEffect(2).setUseOnlyTargetPointer(true) - .setText("and 2 damage to target creature you control") - .setTargetPointer(new SecondTargetPointer())); + this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(4, 2)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL).setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(2)); } private RecklessRage(final RecklessRage card) { diff --git a/Mage.Sets/src/mage/cards/s/SeismicWave.java b/Mage.Sets/src/mage/cards/s/SeismicWave.java index ebc6f6a8e18..e3cf4e810a4 100644 --- a/Mage.Sets/src/mage/cards/s/SeismicWave.java +++ b/Mage.Sets/src/mage/cards/s/SeismicWave.java @@ -28,8 +28,8 @@ public final class SeismicWave extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}"); // Seismic Wave deals 2 damage to any target and 1 damage to each nonartifact creature target opponent controls. - this.getSpellAbility().addTarget(new TargetAnyTarget().withChooseHint("2 damage")); - this.getSpellAbility().addTarget(new TargetOpponent().withChooseHint("1 damage to each nonartifact creature target opponent controls")); + this.getSpellAbility().addTarget(new TargetAnyTarget().withChooseHint("to deal 2 damage")); + this.getSpellAbility().addTarget(new TargetOpponent().withChooseHint("1 damage to each nonartifact creature they control")); this.getSpellAbility().addEffect(new SeismicWaveEffect()); } @@ -51,7 +51,7 @@ class SeismicWaveEffect extends OneShotEffect { filter.add(Predicates.not(CardType.ARTIFACT.getPredicate())); } - public SeismicWaveEffect() { + SeismicWaveEffect() { super(Outcome.Damage); this.staticText = "{this} deals 2 damage to any target and 1 damage to each nonartifact creature target opponent controls"; } diff --git a/Mage.Sets/src/mage/cards/s/SelfDestruct.java b/Mage.Sets/src/mage/cards/s/SelfDestruct.java index 8e57a76ef4c..4d4fbb70754 100644 --- a/Mage.Sets/src/mage/cards/s/SelfDestruct.java +++ b/Mage.Sets/src/mage/cards/s/SelfDestruct.java @@ -89,7 +89,7 @@ class SelfDestructEffect extends OneShotEffect { if (player != null) { player.damage(power, creature.getId(), source, game); } - permanent.damage(power, permanent.getId(), source, game); + creature.damage(power, creature.getId(), source, game); return true; } } diff --git a/Mage.Sets/src/mage/cards/s/ShadowGuildmage.java b/Mage.Sets/src/mage/cards/s/ShadowGuildmage.java index af5c2d262a4..eafc596a173 100644 --- a/Mage.Sets/src/mage/cards/s/ShadowGuildmage.java +++ b/Mage.Sets/src/mage/cards/s/ShadowGuildmage.java @@ -1,21 +1,20 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.abilities.effects.common.PutOnLibraryTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** * @@ -37,9 +36,8 @@ public final class ShadowGuildmage extends CardImpl { this.addAbility(ability); // {R}, {tap}: Shadow Guildmage deals 1 damage to any target and 1 damage to you. - ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{R}")); + ability = new SimpleActivatedAbility(new DamageTargetAndYouEffect(1, 1), new ManaCostsImpl<>("{R}")); ability.addCost(new TapSourceCost()); - ability.addEffect(new DamageControllerEffect(1).setText("and 1 damage to you")); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ShockerUnshakable.java b/Mage.Sets/src/mage/cards/s/ShockerUnshakable.java index 661ecfe7032..d4a1b2c57d1 100644 --- a/Mage.Sets/src/mage/cards/s/ShockerUnshakable.java +++ b/Mage.Sets/src/mage/cards/s/ShockerUnshakable.java @@ -6,8 +6,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.effects.common.DamageTargetControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; @@ -42,8 +41,7 @@ public final class ShockerUnshakable extends CardImpl { ))); // Vibro-Shock Gauntlets -- When Shocker enters, he deals 2 damage to target creature and 2 damage to that creature's controller. - Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2, "he")); - ability.addEffect(new DamageTargetControllerEffect(2).setText("and 2 damage to that creature's controller")); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetAndTargetControllerEffect(2, 2)); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability.withFlavorWord("Vibro-Shock Gauntlets")); } diff --git a/Mage.Sets/src/mage/cards/s/ShowerOfSparks.java b/Mage.Sets/src/mage/cards/s/ShowerOfSparks.java index db144515b38..8d13d17e372 100644 --- a/Mage.Sets/src/mage/cards/s/ShowerOfSparks.java +++ b/Mage.Sets/src/mage/cards/s/ShowerOfSparks.java @@ -1,13 +1,14 @@ package mage.cards.s; -import java.util.UUID; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; +import java.util.UUID; + /** * * @author LevelX2 @@ -17,10 +18,10 @@ public final class ShowerOfSparks extends CardImpl { public ShowerOfSparks(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); - // Shower of sparks deals 1 damage to target creature and 1 damage to target player. - this.getSpellAbility().addEffect(new DamageTargetEffect(1, true, "target creature and 1 damage to target player or planeswalker")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); + // Shower of Sparks deals 1 damage to target creature and 1 damage to target player or planeswalker. + this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(1, 1)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(2)); } private ShowerOfSparks(final ShowerOfSparks card) { diff --git a/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java b/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java index f18b7cf1613..5b4fe81e8b6 100644 --- a/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java +++ b/Mage.Sets/src/mage/cards/s/SoulOfShandalar.java @@ -1,4 +1,3 @@ - package mage.cards.s; import mage.MageInt; @@ -93,7 +92,7 @@ class SoulOfShandalarEffect extends OneShotEffect { class SoulOfShandalarTarget extends TargetPermanent { - public SoulOfShandalarTarget() { + SoulOfShandalarTarget() { super(0, 1, new FilterCreaturePermanent("creature that the targeted player or planeswalker's controller controls")); } diff --git a/Mage.Sets/src/mage/cards/s/Sparksmith.java b/Mage.Sets/src/mage/cards/s/Sparksmith.java index 7a11696bfc3..158c416bd05 100644 --- a/Mage.Sets/src/mage/cards/s/Sparksmith.java +++ b/Mage.Sets/src/mage/cards/s/Sparksmith.java @@ -1,35 +1,30 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; -import mage.abilities.effects.common.DamageControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetAndYouEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterPermanent; +import mage.game.Game; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author Plopman */ public final class Sparksmith extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("Goblins on the battlefield"); - static { - filter.add(SubType.GOBLIN.getPredicate()); - } - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter); - public Sparksmith(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}"); this.subtype.add(SubType.GOBLIN); @@ -38,11 +33,8 @@ public final class Sparksmith extends CardImpl { this.toughness = new MageInt(1); // {tap}: Sparksmith deals X damage to target creature and X damage to you, where X is the number of Goblins on the battlefield. - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(xValue) - .setText("{this} deals X damage to target creature"), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(new SparksmithEffect(), new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); - ability.addEffect(new DamageControllerEffect(xValue) - .setText("and X damage to you, where X is the number of Goblins on the battlefield")); this.addAbility(ability); } @@ -55,3 +47,35 @@ public final class Sparksmith extends CardImpl { return new Sparksmith(this); } } + +// too lazy to handle dynamic value properly in the common class +class SparksmithEffect extends OneShotEffect { + + + private static final FilterPermanent filter = new FilterPermanent("Goblins on the battlefield"); + static { + filter.add(SubType.GOBLIN.getPredicate()); + } + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter); + + SparksmithEffect() { + super(Outcome.Benefit); + staticText = "{this} deals X damage to target creature and X damage to you, " + + "where X is the number of Goblins on the battlefield"; + } + + private SparksmithEffect(final SparksmithEffect effect) { + super(effect); + } + + @Override + public SparksmithEffect copy() { + return new SparksmithEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = xValue.calculate(game, source, this); + return new DamageTargetAndYouEffect(amount, amount).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SunflareShaman.java b/Mage.Sets/src/mage/cards/s/SunflareShaman.java index 70e6d1ada1a..31a468e6fa8 100644 --- a/Mage.Sets/src/mage/cards/s/SunflareShaman.java +++ b/Mage.Sets/src/mage/cards/s/SunflareShaman.java @@ -1,26 +1,24 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DamageSelfEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndSelfEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author jeffwadsworth @@ -60,7 +58,7 @@ class SunflareShamanEffect extends OneShotEffect { filter.add(SubType.ELEMENTAL.getPredicate()); } - public SunflareShamanEffect() { + SunflareShamanEffect() { super(Outcome.Damage); this.staticText = "{this} deals X damage to any target and X damage to itself, where X is the number of Elemental cards in your graveyard"; } @@ -78,9 +76,8 @@ class SunflareShamanEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - int ElementalsInYourGraveyard = controller.getGraveyard().count(filter, game); - new DamageTargetEffect(ElementalsInYourGraveyard).apply(game, source); - new DamageSelfEffect(ElementalsInYourGraveyard).apply(game, source); + int amount = controller.getGraveyard().count(filter, game); + new DamageTargetAndSelfEffect(amount, amount).apply(game, source); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/s/SynchronizedSpellcraft.java b/Mage.Sets/src/mage/cards/s/SynchronizedSpellcraft.java index 1a4e756ff70..699427c2482 100644 --- a/Mage.Sets/src/mage/cards/s/SynchronizedSpellcraft.java +++ b/Mage.Sets/src/mage/cards/s/SynchronizedSpellcraft.java @@ -3,15 +3,13 @@ package mage.cards.s; import mage.abilities.Ability; import mage.abilities.dynamicvalue.common.PartyCount; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.abilities.hint.common.PartyCountHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -25,7 +23,6 @@ public final class SynchronizedSpellcraft extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}"); // Synchronized Spellcraft deals 4 damage to target creature and X damage to that creature's controller, where X is the number of creatures in your party. - this.getSpellAbility().addEffect(new DamageTargetEffect(4)); this.getSpellAbility().addEffect(new SynchronizedSpellcraftEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addHint(PartyCountHint.instance); @@ -45,7 +42,8 @@ class SynchronizedSpellcraftEffect extends OneShotEffect { SynchronizedSpellcraftEffect() { super(Outcome.Benefit); - staticText = "and X damage to that creature's controller, " + + staticText = "{this} deals 4 damage to target creature " + + "and X damage to that creature's controller, " + "where X is the number of creatures in your party. " + PartyCount.getReminder(); } @@ -60,18 +58,7 @@ class SynchronizedSpellcraftEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - int partyCount = PartyCount.instance.calculate(game, source, this); - if (partyCount < 1) { - return false; - } - Permanent permanent = game.getPermanentOrLKIBattlefield(source.getFirstTarget()); - if (permanent == null) { - return false; - } - Player player = game.getPlayer(permanent.getControllerId()); - if (player == null) { - return false; - } - return player.damage(partyCount, source.getSourceId(), source, game) > 0; + int amount = PartyCount.instance.calculate(game, source, this); + return new DamageTargetAndTargetControllerEffect(4, amount).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/t/TheFallOfKroog.java b/Mage.Sets/src/mage/cards/t/TheFallOfKroog.java index 2d16a039f9d..c52ca2da726 100644 --- a/Mage.Sets/src/mage/cards/t/TheFallOfKroog.java +++ b/Mage.Sets/src/mage/cards/t/TheFallOfKroog.java @@ -2,8 +2,7 @@ package mage.cards.t; import mage.MageItem; import mage.abilities.Ability; -import mage.abilities.effects.common.DamageAllControlledTargetEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndAllControlledEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -32,12 +31,9 @@ public final class TheFallOfKroog extends CardImpl { this.getSpellAbility().addEffect(new DestroyTargetEffect() .setText("choose target opponent. Destroy target land that player controls") .setTargetPointer(new SecondTargetPointer())); - this.getSpellAbility().addEffect(new DamageTargetEffect( - 3, true, "that player" - )); - this.getSpellAbility().addEffect(new DamageAllControlledTargetEffect( - 1, StaticFilters.FILTER_PERMANENT_CREATURE - ).setText("and 1 damage to each creature they control")); + this.getSpellAbility().addEffect(new DamageTargetAndAllControlledEffect( + 3, 1, StaticFilters.FILTER_PERMANENT_CREATURE + ).setText("{this} deals 3 damage to that player and 1 damage to each creature they control")); this.getSpellAbility().addTarget(new TargetOpponent()); this.getSpellAbility().addTarget(new TheFallOfKroogTarget()); } diff --git a/Mage.Sets/src/mage/cards/t/TrickShot.java b/Mage.Sets/src/mage/cards/t/TrickShot.java index 9eeb2b6385f..e233fc090af 100644 --- a/Mage.Sets/src/mage/cards/t/TrickShot.java +++ b/Mage.Sets/src/mage/cards/t/TrickShot.java @@ -1,6 +1,6 @@ package mage.cards.t; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -9,7 +9,6 @@ import mage.filter.predicate.other.AnotherTargetPredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.SecondTargetPointer; import java.util.UUID; @@ -31,12 +30,7 @@ public final class TrickShot extends CardImpl { // Trick Shot deals 6 damage to target creature and 2 damage to up to one other target creature token. this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter).setTargetTag(2)); - this.getSpellAbility().addEffect(new DamageTargetEffect(6, true, "", true)); - this.getSpellAbility().addEffect( - new DamageTargetEffect(2, true, "", true) - .setTargetPointer(new SecondTargetPointer()) - .setText("and 2 damage to up to one other target creature token") - ); + this.getSpellAbility().addEffect(new DamageTargetAndTargetEffect(6, 2)); } private TrickShot(final TrickShot card) { diff --git a/Mage.Sets/src/mage/cards/u/UnleashShell.java b/Mage.Sets/src/mage/cards/u/UnleashShell.java index a52d7e657df..ffd4fd4c34d 100644 --- a/Mage.Sets/src/mage/cards/u/UnleashShell.java +++ b/Mage.Sets/src/mage/cards/u/UnleashShell.java @@ -1,14 +1,13 @@ package mage.cards.u; -import java.util.UUID; - -import mage.abilities.effects.common.DamageTargetControllerEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreatureOrPlaneswalker; +import java.util.UUID; + /** * * @author weirddan455 @@ -19,9 +18,8 @@ public final class UnleashShell extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}{R}"); // Unleash Shell deals 5 damage to target creature or planeswalker and 2 damage to that permanent's controller. - this.getSpellAbility().addEffect(new DamageTargetEffect(5)); - this.getSpellAbility().addEffect(new DamageTargetControllerEffect(2).setText("and 2 damage to that permanent's controller")); this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker()); + this.getSpellAbility().addEffect(new DamageTargetAndTargetControllerEffect(5, 2)); } private UnleashShell(final UnleashShell card) { diff --git a/Mage.Sets/src/mage/cards/w/WildfireHowl.java b/Mage.Sets/src/mage/cards/w/WildfireHowl.java index c61f9d097a4..e897682c8de 100644 --- a/Mage.Sets/src/mage/cards/w/WildfireHowl.java +++ b/Mage.Sets/src/mage/cards/w/WildfireHowl.java @@ -33,6 +33,8 @@ public final class WildfireHowl extends CardImpl { GiftWasPromisedCondition.TRUE, "{this} deals 2 damage to each creature. " + "If the gift was promised, instead {this} deals 1 damage to any target and 2 damage to each creature" ).addEffect(new DamageAllEffect(2, StaticFilters.FILTER_PERMANENT_CREATURE))); + // ConditionalOneShotEffect doesn't call processAction between effects, so currently works + // if that gets changed (which it perhaps should?) then need to make this a single effect this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster( GiftWasPromisedCondition.TRUE, new TargetAnyTarget() )); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java index 843bd5609ce..b62896f7e90 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndAllControlledEffect.java @@ -5,6 +5,7 @@ import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -18,6 +19,13 @@ public class DamageTargetAndAllControlledEffect extends OneShotEffect { private final int secondAmount; private final FilterPermanent filter; + /** + * Deals simultaneous damage to the target and to each creature the target controls + */ + public DamageTargetAndAllControlledEffect(int amount) { + this(amount, amount, StaticFilters.FILTER_PERMANENT_CREATURE); + } + /** * Deals simultaneous damage to the target and to each creature the target controls */ @@ -54,7 +62,7 @@ public class DamageTargetAndAllControlledEffect extends OneShotEffect { Player controller = game.getPlayerOrPlaneswalkerController(getTargetPointer().getFirst(game, source)); if (controller != null) { for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { - perm.damage(secondAmount, source.getSourceId(), source, game, false, true); + perm.damage(secondAmount, source.getSourceId(), source, game); } } return true; @@ -65,9 +73,11 @@ public class DamageTargetAndAllControlledEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - return "{this} deals " + firstAmount + "damage to " + - getTargetPointer().describeTargets(mode.getTargets(), "that creature") + + String description = getTargetPointer().describeTargets(mode.getTargets(), "that player"); + return "{this} deals " + firstAmount + "damage to " + description + " and " + secondAmount + " damage to each " + filter.getMessage() + - " that player or that planeswalker's controller controls"; + " that player" + + (description.contains("planeswalker") ? " or that planeswalker's controller" : "") + + " controls"; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java index de20b0cb6aa..50f4bbda6ec 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetControllerEffect.java @@ -44,7 +44,10 @@ public class DamageTargetAndTargetControllerEffect extends OneShotEffect { Permanent permanent = game.getPermanent(targetId); if (permanent != null) { permanent.damage(firstAmount, source.getSourceId(), source, game); - Player player = game.getPlayer(permanent.getControllerId()); + } + Permanent lki = game.getPermanentOrLKIBattlefield(targetId); + if (lki != null) { + Player player = game.getPlayer(lki.getControllerId()); if (player != null) { player.damage(secondAmount, source.getSourceId(), source, game); } @@ -58,8 +61,9 @@ public class DamageTargetAndTargetControllerEffect extends OneShotEffect { if (staticText != null && !staticText.isEmpty()) { return staticText; } - return "{this} deals " + firstAmount + "damage to " + - getTargetPointer().describeTargets(mode.getTargets(), "that creature") + - " and " + secondAmount + "damage to that creature's controller"; + String description = getTargetPointer().describeTargets(mode.getTargets(), "that creature"); + return "{this} deals " + firstAmount + "damage to " + description + + " and " + secondAmount + "damage to that " + + (description.contains(" or ") ? "permanent's" : "creature's") + " controller"; } } -- 2.47.2 From 0ae2c2b86e6dd6b32e2123cc990aa4611200a329 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Mon, 10 Nov 2025 01:52:30 -0500 Subject: [PATCH 183/261] remove custom multitarget handling from DamageTargetEffect --- .../src/mage/cards/a/AvalancheOfSector7.java | 2 +- Mage.Sets/src/mage/cards/b/BarretWallace.java | 2 +- .../src/mage/cards/b/BedeckBedazzle.java | 5 ++- .../src/mage/cards/b/BurningTreeShaman.java | 2 +- Mage.Sets/src/mage/cards/c/CutIn.java | 6 +--- .../src/mage/cards/e/ExpansionExplosion.java | 3 +- .../src/mage/cards/f/FieryAnnihilation.java | 2 +- .../mage/cards/f/FlamescrollCelebrant.java | 2 +- Mage.Sets/src/mage/cards/h/HarshMentor.java | 2 +- .../src/mage/cards/i/IchneumonDruid.java | 7 ++-- .../src/mage/cards/i/ImmolationShaman.java | 2 +- .../src/mage/cards/j/JeskaiRevelation.java | 2 +- .../mage/cards/m/ManticoreOfTheGauntlet.java | 4 +-- .../src/mage/cards/n/NivMizzetGuildpact.java | 1 - Mage.Sets/src/mage/cards/s/Simulacrum.java | 3 +- .../effects/common/DamageTargetEffect.java | 36 ++----------------- 16 files changed, 19 insertions(+), 62 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AvalancheOfSector7.java b/Mage.Sets/src/mage/cards/a/AvalancheOfSector7.java index 6ef053cc5c2..863b8b6def2 100644 --- a/Mage.Sets/src/mage/cards/a/AvalancheOfSector7.java +++ b/Mage.Sets/src/mage/cards/a/AvalancheOfSector7.java @@ -65,7 +65,7 @@ public final class AvalancheOfSector7 extends CardImpl { class AvalancheOfSector7TriggeredAbility extends TriggeredAbilityImpl { AvalancheOfSector7TriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(1, true, "that player", true)); + super(Zone.BATTLEFIELD, new DamageTargetEffect(1, true, "that player")); setTriggerPhrase("Whenever an opponent activates an ability of an artifact they control, "); } diff --git a/Mage.Sets/src/mage/cards/b/BarretWallace.java b/Mage.Sets/src/mage/cards/b/BarretWallace.java index e040ec94df4..d7e9c48f3ad 100644 --- a/Mage.Sets/src/mage/cards/b/BarretWallace.java +++ b/Mage.Sets/src/mage/cards/b/BarretWallace.java @@ -49,7 +49,7 @@ public final class BarretWallace extends CardImpl { // Whenever Barret Wallace attacks, it deals damage equal to the number of equipped creatures you control to defending player. this.addAbility(new AttacksTriggeredAbility( - new DamageTargetEffect(xValue, true, "it", true) + new DamageTargetEffect(xValue, true, "it") .setText("it deals damage equal to the number of equipped creatures you control to defending player"), false, null, SetTargetPointer.PLAYER ).withRuleTextReplacement(true).addHint(hint)); diff --git a/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java b/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java index b0b65e3af98..2b76d6a4d8c 100644 --- a/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java +++ b/Mage.Sets/src/mage/cards/b/BedeckBedazzle.java @@ -1,7 +1,6 @@ package mage.cards.b; import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; @@ -75,9 +74,9 @@ class BedazzleEffect extends OneShotEffect { if (permanent != null) { permanent.destroy(source, game, false); } - Effect effect = new DamageTargetEffect(StaticValue.get(2), true, "", true); + Effect effect = new DamageTargetEffect(2); effect.setTargetPointer(new FixedTarget(source.getTargets().get(1).getFirstTarget(), game)); effect.apply(game, source); return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java b/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java index 4b0fd3eac54..9295e4ec8b0 100644 --- a/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java +++ b/Mage.Sets/src/mage/cards/b/BurningTreeShaman.java @@ -46,7 +46,7 @@ public final class BurningTreeShaman extends CardImpl { class BurningTreeShamanTriggeredAbility extends TriggeredAbilityImpl { BurningTreeShamanTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player", true)); + super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player")); } private BurningTreeShamanTriggeredAbility(final BurningTreeShamanTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/c/CutIn.java b/Mage.Sets/src/mage/cards/c/CutIn.java index 9d23e5e6a82..a0d73d9e607 100644 --- a/Mage.Sets/src/mage/cards/c/CutIn.java +++ b/Mage.Sets/src/mage/cards/c/CutIn.java @@ -22,11 +22,7 @@ public final class CutIn extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); // Cut In deals 4 damage to target creature. - this.getSpellAbility().addEffect( - new DamageTargetEffect(4) - .setUseOnlyTargetPointer(true) - .setTargetPointer(new FirstTargetPointer()) - ); + this.getSpellAbility().addEffect(new DamageTargetEffect(4)); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // Create a Young Hero Role token attached to up to one target creature you control. diff --git a/Mage.Sets/src/mage/cards/e/ExpansionExplosion.java b/Mage.Sets/src/mage/cards/e/ExpansionExplosion.java index 4c6fb4651f6..3115b588596 100644 --- a/Mage.Sets/src/mage/cards/e/ExpansionExplosion.java +++ b/Mage.Sets/src/mage/cards/e/ExpansionExplosion.java @@ -1,7 +1,6 @@ package mage.cards.e; import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CopyTargetStackObjectEffect; @@ -82,7 +81,7 @@ class ExplosionEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { int xValue = CardUtil.getSourceCostsTag(game, source, "X", 0); - Effect effect = new DamageTargetEffect(StaticValue.get(xValue), true, "", true); + Effect effect = new DamageTargetEffect(xValue); effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game)); effect.apply(game, source); Player player = game.getPlayer(source.getTargets().get(1).getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/f/FieryAnnihilation.java b/Mage.Sets/src/mage/cards/f/FieryAnnihilation.java index ad81f8376c0..2196e4d6699 100644 --- a/Mage.Sets/src/mage/cards/f/FieryAnnihilation.java +++ b/Mage.Sets/src/mage/cards/f/FieryAnnihilation.java @@ -37,7 +37,7 @@ public final class FieryAnnihilation extends CardImpl { // Fiery Annihilation deals 5 damage to target creature. Exile up to one target Equipment attached to that creature. If that creature would die this turn, exile it instead. this.getSpellAbility().addEffect(new DamageTargetEffect( - 5, true, "target creature", true + 5, true, "target creature" )); this.getSpellAbility().addEffect(new ExileTargetEffect() .setTargetPointer(new SecondTargetPointer()) diff --git a/Mage.Sets/src/mage/cards/f/FlamescrollCelebrant.java b/Mage.Sets/src/mage/cards/f/FlamescrollCelebrant.java index de0e113027a..ee7cedd0b5a 100644 --- a/Mage.Sets/src/mage/cards/f/FlamescrollCelebrant.java +++ b/Mage.Sets/src/mage/cards/f/FlamescrollCelebrant.java @@ -73,7 +73,7 @@ public final class FlamescrollCelebrant extends ModalDoubleFacedCard { class FlamescrollCelebrantTriggeredAbility extends TriggeredAbilityImpl { FlamescrollCelebrantTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player", true)); + super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player")); } private FlamescrollCelebrantTriggeredAbility(final FlamescrollCelebrantTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/h/HarshMentor.java b/Mage.Sets/src/mage/cards/h/HarshMentor.java index d317abe73b2..281c340514d 100644 --- a/Mage.Sets/src/mage/cards/h/HarshMentor.java +++ b/Mage.Sets/src/mage/cards/h/HarshMentor.java @@ -48,7 +48,7 @@ public final class HarshMentor extends CardImpl { class HarshMentorTriggeredAbility extends TriggeredAbilityImpl { HarshMentorTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(2), true, "that player", true)); + super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(2), true, "that player")); } private HarshMentorTriggeredAbility(final HarshMentorTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/i/IchneumonDruid.java b/Mage.Sets/src/mage/cards/i/IchneumonDruid.java index 8ab18e4d7ab..174558742a7 100644 --- a/Mage.Sets/src/mage/cards/i/IchneumonDruid.java +++ b/Mage.Sets/src/mage/cards/i/IchneumonDruid.java @@ -1,4 +1,3 @@ - package mage.cards.i; import java.util.HashMap; @@ -50,8 +49,8 @@ public final class IchneumonDruid extends CardImpl { class IchneumonDruidAbility extends TriggeredAbilityImpl { - public IchneumonDruidAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(4), false, "that player", true)); + IchneumonDruidAbility() { + super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(4), false, "that player")); } private IchneumonDruidAbility(final IchneumonDruidAbility ability) { @@ -95,7 +94,7 @@ class IchneumonDruidWatcher extends Watcher { private final Map playerInstantCount = new HashMap<>(); - public IchneumonDruidWatcher() { + IchneumonDruidWatcher() { super(WatcherScope.GAME); } diff --git a/Mage.Sets/src/mage/cards/i/ImmolationShaman.java b/Mage.Sets/src/mage/cards/i/ImmolationShaman.java index 79fad9b9bdf..785653ee816 100644 --- a/Mage.Sets/src/mage/cards/i/ImmolationShaman.java +++ b/Mage.Sets/src/mage/cards/i/ImmolationShaman.java @@ -67,7 +67,7 @@ public final class ImmolationShaman extends CardImpl { class ImmolationShamanTriggeredAbility extends TriggeredAbilityImpl { ImmolationShamanTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player", true)); + super(Zone.BATTLEFIELD, new DamageTargetEffect(StaticValue.get(1), true, "that player")); setTriggerPhrase("Whenever an opponent activates an ability of an artifact, creature, or land that isn't a mana ability, "); } diff --git a/Mage.Sets/src/mage/cards/j/JeskaiRevelation.java b/Mage.Sets/src/mage/cards/j/JeskaiRevelation.java index 5a4a488cc07..4a0b4d6f52b 100644 --- a/Mage.Sets/src/mage/cards/j/JeskaiRevelation.java +++ b/Mage.Sets/src/mage/cards/j/JeskaiRevelation.java @@ -23,7 +23,7 @@ public final class JeskaiRevelation extends CardImpl { this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); this.getSpellAbility().addTarget(new TargetSpellOrPermanent()); this.getSpellAbility().addEffect(new DamageTargetEffect( - 4, true, "any target", true + 4, true, "any target" ).setTargetPointer(new SecondTargetPointer())); this.getSpellAbility().addTarget(new TargetAnyTarget()); this.getSpellAbility().addEffect(new CreateTokenEffect(new MonasteryMentorToken(), 2)); diff --git a/Mage.Sets/src/mage/cards/m/ManticoreOfTheGauntlet.java b/Mage.Sets/src/mage/cards/m/ManticoreOfTheGauntlet.java index 53ecb2e7186..60611147a48 100644 --- a/Mage.Sets/src/mage/cards/m/ManticoreOfTheGauntlet.java +++ b/Mage.Sets/src/mage/cards/m/ManticoreOfTheGauntlet.java @@ -1,11 +1,9 @@ - package mage.cards.m; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; @@ -37,7 +35,7 @@ public final class ManticoreOfTheGauntlet extends CardImpl { counters.setText("put a -1/-1 counter on target creature you control"); counters.setTargetPointer(new FirstTargetPointer()); - Effect damage = new DamageTargetEffect(StaticValue.get(3), true, "", true); + Effect damage = new DamageTargetEffect(3); damage.setText("{this} deals 3 damage to target opponent or planeswalker."); damage.setTargetPointer(new SecondTargetPointer()); diff --git a/Mage.Sets/src/mage/cards/n/NivMizzetGuildpact.java b/Mage.Sets/src/mage/cards/n/NivMizzetGuildpact.java index 2c12aaf71c7..e6336262de4 100644 --- a/Mage.Sets/src/mage/cards/n/NivMizzetGuildpact.java +++ b/Mage.Sets/src/mage/cards/n/NivMizzetGuildpact.java @@ -52,7 +52,6 @@ public final class NivMizzetGuildpact extends CardImpl { // Whenever Niv-Mizzet, Guildpact deals combat damage to a player, it deals X damage to any target, target player draws X cards, and you gain X life, where X is the number of different color pairs among permanents you control that are exactly two colors. Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility( new DamageTargetEffect(NivMizzetGuildpactCount.instance) - .setUseOnlyTargetPointer(true) .setText("it deals X damage to any target"), false); ability.addTarget(new TargetAnyTarget()); ability.addEffect(new DrawCardTargetEffect(NivMizzetGuildpactCount.instance) diff --git a/Mage.Sets/src/mage/cards/s/Simulacrum.java b/Mage.Sets/src/mage/cards/s/Simulacrum.java index 282bbf88232..ac2fcc450ce 100644 --- a/Mage.Sets/src/mage/cards/s/Simulacrum.java +++ b/Mage.Sets/src/mage/cards/s/Simulacrum.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -27,7 +26,7 @@ public final class Simulacrum extends CardImpl { // You gain life equal to the damage dealt to you this turn. Simulacrum deals damage to target creature you control equal to the damage dealt to you this turn. this.getSpellAbility().addEffect(new GainLifeEffect(new SimulacrumAmount(), "You gain life equal to the damage dealt to you this turn.")); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - Effect effect = new DamageTargetEffect(new SimulacrumAmount(), true, "target creature you control", true); + Effect effect = new DamageTargetEffect(new SimulacrumAmount(), true, "target creature you control"); effect.setText(" {this} deals damage to target creature you control equal to the damage dealt to you this turn."); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addWatcher(new AmountOfDamageAPlayerReceivedThisTurnWatcher()); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java index ae23687ce8a..217f6dd4bdf 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java @@ -4,7 +4,6 @@ import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.game.Game; @@ -24,7 +23,6 @@ public class DamageTargetEffect extends OneShotEffect { protected DynamicValue amount; protected boolean preventable; protected String targetDescription; - protected boolean useOnlyTargetPointer; // TODO: investigate why do we ignore targetPointer by default?? protected String sourceName = "{this}"; public DamageTargetEffect(int amount) { @@ -44,10 +42,6 @@ public class DamageTargetEffect extends OneShotEffect { this(StaticValue.get(amount), preventable, targetDescription); } - public DamageTargetEffect(int amount, boolean preventable, String targetDescription, boolean useOnlyTargetPointer) { - this(StaticValue.get(amount), preventable, targetDescription, useOnlyTargetPointer); - } - public DamageTargetEffect(int amount, boolean preventable, String targetDescription, String whoDealDamageName) { this(StaticValue.get(amount), preventable, targetDescription); this.sourceName = whoDealDamageName; @@ -67,15 +61,10 @@ public class DamageTargetEffect extends OneShotEffect { } public DamageTargetEffect(DynamicValue amount, boolean preventable, String targetDescription) { - this(amount, preventable, targetDescription, false); - } - - public DamageTargetEffect(DynamicValue amount, boolean preventable, String targetDescription, boolean useOnlyTargetPointer) { super(Outcome.Damage); this.amount = amount; this.preventable = preventable; this.targetDescription = targetDescription; - this.useOnlyTargetPointer = useOnlyTargetPointer; } public int getAmount() { @@ -95,21 +84,15 @@ public class DamageTargetEffect extends OneShotEffect { this.amount = effect.amount.copy(); this.preventable = effect.preventable; this.targetDescription = effect.targetDescription; - this.useOnlyTargetPointer = effect.useOnlyTargetPointer; this.sourceName = effect.sourceName; } + @Override public DamageTargetEffect withTargetDescription(String targetDescription) { this.targetDescription = targetDescription; return this; } - // TODO: this should most likely be refactored to not be needed and always use target pointer. - public Effect setUseOnlyTargetPointer(boolean useOnlyTargetPointer) { - this.useOnlyTargetPointer = useOnlyTargetPointer; - return this; - } - @Override public DamageTargetEffect copy() { return new DamageTargetEffect(this); @@ -117,21 +100,6 @@ public class DamageTargetEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - if (!useOnlyTargetPointer && source.getTargets().size() > 1) { - for (Target target : source.getTargets()) { - for (UUID targetId : target.getTargets()) { - Permanent permanent = game.getPermanent(targetId); - if (permanent != null) { - permanent.damage(amount.calculate(game, source, this), source.getSourceId(), source, game, false, preventable); - } - Player player = game.getPlayer(targetId); - if (player != null) { - player.damage(amount.calculate(game, source, this), source.getSourceId(), source, game, false, preventable); - } - } - } - return true; - } for (UUID targetId : this.getTargetPointer().getTargets(game, source)) { Permanent permanent = game.getPermanent(targetId); if (permanent != null) { @@ -154,7 +122,7 @@ public class DamageTargetEffect extends OneShotEffect { StringBuilder sb = new StringBuilder(); String message = amount.getMessage(); sb.append(this.sourceName).append(" deals "); - if (message.isEmpty() || !message.equals("1")) { + if (!message.equals("1")) { sb.append(amount); } if (!sb.toString().endsWith(" ")) { -- 2.47.2 From 1fb0d26db97ee7af769df3e86a9088e942713f74 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Mon, 10 Nov 2025 02:01:58 -0500 Subject: [PATCH 184/261] cleanup to common class --- .../src/mage/cards/f/FlashConscription.java | 58 +++---------------- .../token/VrondissRageOfAncientsToken.java | 39 +------------ 2 files changed, 10 insertions(+), 87 deletions(-) diff --git a/Mage.Sets/src/mage/cards/f/FlashConscription.java b/Mage.Sets/src/mage/cards/f/FlashConscription.java index 189881c60b1..b4fba0da72f 100644 --- a/Mage.Sets/src/mage/cards/f/FlashConscription.java +++ b/Mage.Sets/src/mage/cards/f/FlashConscription.java @@ -1,10 +1,9 @@ - package mage.cards.f; -import java.util.UUID; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DealsCombatDamageTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.dynamicvalue.common.SavedDamageValue; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; @@ -13,15 +12,11 @@ import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ColoredManaSymbol; import mage.constants.Duration; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.DamagedEvent; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author LevelX2 @@ -36,7 +31,10 @@ public final class FlashConscription extends CardImpl { this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn).setText("and gain control of it until end of turn")); this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("That creature gains haste until end of turn")); this.getSpellAbility().addEffect(new ConditionalContinuousEffect( - new GainAbilityTargetEffect(new FlashConscriptionTriggeredAbility(), Duration.EndOfTurn), + new GainAbilityTargetEffect( + new DealsCombatDamageTriggeredAbility(new GainLifeEffect(SavedDamageValue.MUCH), false), + Duration.EndOfTurn + ), ManaWasSpentCondition.WHITE, "If {W} was spent to cast this spell, the creature gains " + "\"Whenever this creature deals combat damage, you gain that much life\" until end of turn" @@ -54,43 +52,3 @@ public final class FlashConscription extends CardImpl { return new FlashConscription(this); } } - -class FlashConscriptionTriggeredAbility extends TriggeredAbilityImpl { - - public FlashConscriptionTriggeredAbility() { - super(Zone.BATTLEFIELD, null); - } - - private FlashConscriptionTriggeredAbility(final FlashConscriptionTriggeredAbility ability) { - super(ability); - } - - @Override - public FlashConscriptionTriggeredAbility copy() { - return new FlashConscriptionTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT - || event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - DamagedEvent damageEvent = (DamagedEvent) event; - if (damageEvent.isCombatDamage()) { - if (event.getSourceId().equals(this.sourceId)) { - this.getEffects().clear(); - this.getEffects().add(new GainLifeEffect(damageEvent.getAmount())); - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever {this} deals combat damage, you gain that much life."; - } -} diff --git a/Mage/src/main/java/mage/game/permanent/token/VrondissRageOfAncientsToken.java b/Mage/src/main/java/mage/game/permanent/token/VrondissRageOfAncientsToken.java index f5b0d1c0bf9..de93c7ee3de 100644 --- a/Mage/src/main/java/mage/game/permanent/token/VrondissRageOfAncientsToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/VrondissRageOfAncientsToken.java @@ -1,13 +1,10 @@ package mage.game.permanent.token; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DealsCombatDamageTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; public final class VrondissRageOfAncientsToken extends TokenImpl { @@ -21,7 +18,7 @@ public final class VrondissRageOfAncientsToken extends TokenImpl { power = new MageInt(5); toughness = new MageInt(4); - this.addAbility(new VrondissRageOfAncientsTokenTriggeredAbility()); + this.addAbility(new DealsCombatDamageTriggeredAbility(new SacrificeSourceEffect(), false)); } private VrondissRageOfAncientsToken(final VrondissRageOfAncientsToken token) { @@ -32,35 +29,3 @@ public final class VrondissRageOfAncientsToken extends TokenImpl { return new VrondissRageOfAncientsToken(this); } } - -class VrondissRageOfAncientsTokenTriggeredAbility extends TriggeredAbilityImpl { - - public VrondissRageOfAncientsTokenTriggeredAbility() { - super(Zone.BATTLEFIELD, new SacrificeSourceEffect(), false); - } - - protected VrondissRageOfAncientsTokenTriggeredAbility(final VrondissRageOfAncientsTokenTriggeredAbility ability) { - super(ability); - } - - @Override - public VrondissRageOfAncientsTokenTriggeredAbility copy() { - return new VrondissRageOfAncientsTokenTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER - || event.getType() == GameEvent.EventType.DAMAGED_PERMANENT; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getSourceId().equals(this.getSourceId()); - } - - @Override - public String getRule() { - return "When this creature deals damage, sacrifice it."; - } -} -- 2.47.2 From 71269f972ef9752880e5e2c135d2bb9d0c29bc57 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Mon, 10 Nov 2025 02:02:59 -0500 Subject: [PATCH 185/261] add failing tests using lifelink --- .../DamageMultiLifelinkTriggerTest.java | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiLifelinkTriggerTest.java diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiLifelinkTriggerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiLifelinkTriggerTest.java new file mode 100644 index 00000000000..35b642b209c --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/damage/DamageMultiLifelinkTriggerTest.java @@ -0,0 +1,191 @@ +package org.mage.test.cards.triggers.damage; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.CounterType; +import org.junit.Ignore; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author xenohedron + */ +public class DamageMultiLifelinkTriggerTest extends CardTestPlayerBase { + + private static final String hatchling = "Kraken Hatchling"; // 0/4 + private static final String wishcoin = "Wishcoin Crab"; // 2/5 + + private static final String devil = "Forge Devil"; // 1/1 + // ETB 1 dmg to any target and 1 dmg to you + private static final String embermage = "Reckless Embermage"; // 2/2 + // 1R: 1 dmg to any target and 1 dmg to itself + + private static final String arc = "Arc Trail"; + // Arc Trail deals 2 damage to any target and 1 damage to another target. + private static final String cone = "Cone of Flame"; + // Cone of Flame deals 1 damage to any target, 2 damage to another target, and 3 damage to a third target. + private static final String chaar = "Char"; + // Char deals 4 damage to any target and 2 damage to you. + private static final String outrage = "Chandra's Outrage"; + // Chandra's Outrage deals 4 damage to target creature and 2 damage to that creature's controller. + private static final String fury = "Chandra's Fury"; + // Chandra's Fury deals 4 damage to target player or planeswalker + // and 1 damage to each creature that player or that planeswalker's controller controls. + + private static final String whip = "Whip of Erebos"; + // Creatures you control have lifelink. + private static final String firesong = "Firesong and Sunspeaker"; + // Red instant and sorcery spells you control have lifelink. + private static final String pridemate = "Ajani's Pridemate"; // 2/2 + // Whenever you gain life, put a +1/+1 counter on this creature. + + private void setupBattlefield() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + addCard(Zone.BATTLEFIELD, playerA, whip); + addCard(Zone.BATTLEFIELD, playerA, firesong); + addCard(Zone.BATTLEFIELD, playerA, pridemate); + addCard(Zone.BATTLEFIELD, playerA, hatchling); + addCard(Zone.BATTLEFIELD, playerB, wishcoin); + } + + @Test + @Ignore + public void testCreatureDamageTargetAndYou() { + setupBattlefield(); + addCard(Zone.HAND, playerA, devil); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, devil); + addTarget(playerA, wishcoin); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 - 1 + 2); + assertLife(playerB, 20); + assertDamageReceived(playerB, wishcoin, 1); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + @Ignore + public void testCreatureDamageTargetAndSelf() { + setupBattlefield(); + addCard(Zone.BATTLEFIELD, playerA, embermage); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{R}: "); + addTarget(playerA, wishcoin); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 2); + assertLife(playerB, 20); + assertDamageReceived(playerB, wishcoin, 1); + assertDamageReceived(playerB, embermage, 1); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + @Ignore + public void testSpellDamageTargetAndTarget() { + setupBattlefield(); + addCard(Zone.HAND, playerA, arc); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, arc); + addTarget(playerA, wishcoin); + addTarget(playerA, hatchling); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 3); + assertLife(playerB, 20); + assertDamageReceived(playerB, wishcoin, 2); + assertDamageReceived(playerA, hatchling, 1); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + @Ignore + public void testSpellDamageThreeTargets() { + setupBattlefield(); + addCard(Zone.HAND, playerA, cone); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, cone); + addTarget(playerA, wishcoin); + addTarget(playerA, hatchling); + addTarget(playerA, firesong); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 6); + assertLife(playerB, 20); + assertDamageReceived(playerB, wishcoin, 3); + assertDamageReceived(playerA, hatchling, 2); + assertDamageReceived(playerA, firesong, 1); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + @Ignore + public void testSpellDamageTargetAndYou() { + setupBattlefield(); + addCard(Zone.HAND, playerA, chaar); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chaar); + addTarget(playerA, wishcoin); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 - 2 + 6); + assertLife(playerB, 20); + assertDamageReceived(playerB, wishcoin, 4); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + @Ignore + public void testSpellDamageTargetAndController() { + setupBattlefield(); + addCard(Zone.HAND, playerA, outrage); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, outrage); + addTarget(playerA, wishcoin); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 6); + assertLife(playerB, 20 - 2); + assertDamageReceived(playerB, wishcoin, 4); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + + @Test + @Ignore + public void testSpellDamagePlayerAndControlled() { + setupBattlefield(); + addCard(Zone.HAND, playerA, fury); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, fury); + addTarget(playerA, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 5); + assertLife(playerB, 20 - 4); + assertDamageReceived(playerB, wishcoin, 1); + assertCounterCount(pridemate, CounterType.P1P1, 1); + } + +} -- 2.47.2 From 2799c3f1c076a1ef282dedd99fe1be67a6f742a3 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 10 Nov 2025 11:17:55 -0500 Subject: [PATCH 186/261] update ban lists --- .../Mage.Deck.Constructed/src/mage/deck/Legacy.java | 2 ++ .../Mage.Deck.Constructed/src/mage/deck/Pauper.java | 1 + .../Mage.Deck.Constructed/src/mage/deck/Pioneer.java | 1 + .../Mage.Deck.Constructed/src/mage/deck/Standard.java | 3 +++ 4 files changed, 7 insertions(+) diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java index a75071e26b9..a1df921d081 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java @@ -32,6 +32,7 @@ public class Legacy extends Constructed { banned.add("Dig Through Time"); banned.add("Dreadhorde Arcanist"); banned.add("Earthcraft"); + banned.add("Entomb"); banned.add("Fastbond"); banned.add("Flash"); banned.add("Frantic Search"); @@ -56,6 +57,7 @@ public class Legacy extends Constructed { banned.add("Mox Ruby"); banned.add("Mox Sapphire"); banned.add("Mystical Tutor"); + banned.add("Nadu, Winged Wisdom"); banned.add("Necropotence"); banned.add("Oath of Druids"); banned.add("Oko, Thief of Crowns"); diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Pauper.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Pauper.java index 6dbba75643f..b4c431c6642 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Pauper.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Pauper.java @@ -46,6 +46,7 @@ public class Pauper extends Constructed { banned.add("Gitaxian Probe"); banned.add("Grapeshot"); banned.add("Gush"); + banned.add("High Tide"); banned.add("Hymn to Tourach"); banned.add("Invigorate"); banned.add("Kuldotha Rebirth"); diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Pioneer.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Pioneer.java index 4d86075f3ee..22cf8af5c0f 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Pioneer.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Pioneer.java @@ -30,6 +30,7 @@ public class Pioneer extends Constructed { banned.add("Field of the Dead"); banned.add("Flooded Strand"); banned.add("Geological Appraiser"); + banned.add("Heartfire Hero"); banned.add("Inverter of Truth"); banned.add("Jegantha, the Wellspring"); banned.add("Karn, the Great Creator"); diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java index 0796aaf056d..b1973ae9f0b 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java @@ -24,8 +24,11 @@ public class Standard extends Constructed { banned.add("Heartfire Hero"); banned.add("Hopeless Nightmare"); banned.add("Monstrous Rage"); + banned.add("Proft's Eidetic Memory"); + banned.add("Screaming Nemesis"); banned.add("This Town Ain't Big Enough"); banned.add("Up the Beanstalk"); + banned.add("Vivi Ornitier"); } static List makeLegalSets() { -- 2.47.2 From 97fd15d7a63f97cdafac16f31829e70a7d7fa5c9 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Mon, 10 Nov 2025 22:06:41 -0500 Subject: [PATCH 187/261] fix oversight --- Mage.Sets/src/mage/cards/i/InsultInjury.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/i/InsultInjury.java b/Mage.Sets/src/mage/cards/i/InsultInjury.java index a55864cd52c..196069f5d48 100644 --- a/Mage.Sets/src/mage/cards/i/InsultInjury.java +++ b/Mage.Sets/src/mage/cards/i/InsultInjury.java @@ -2,7 +2,7 @@ package mage.cards.i; import mage.abilities.Ability; import mage.abilities.effects.ReplacementEffectImpl; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DamageTargetAndTargetEffect; import mage.abilities.effects.common.continuous.DamageCantBePreventedEffect; import mage.abilities.keyword.AftermathAbility; import mage.cards.CardSetInfo; @@ -15,7 +15,6 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; -import mage.target.targetpointer.EachTargetPointer; import mage.util.CardUtil; import java.util.UUID; @@ -40,7 +39,7 @@ public final class InsultInjury extends SplitCard { getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); getRightHalfCard().getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); - getRightHalfCard().getSpellAbility().addEffect(new DamageTargetEffect(2).setTargetPointer(new EachTargetPointer())); + getRightHalfCard().getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 2)); } private InsultInjury(final InsultInjury card) { -- 2.47.2 From 646d34a90eb9f04ce458ed22cfa4a68f5642500c Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Mon, 10 Nov 2025 22:35:55 -0500 Subject: [PATCH 188/261] fix oversight for real this time --- Mage.Sets/src/mage/cards/i/InsultInjury.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/i/InsultInjury.java b/Mage.Sets/src/mage/cards/i/InsultInjury.java index 196069f5d48..a7cc880c8f6 100644 --- a/Mage.Sets/src/mage/cards/i/InsultInjury.java +++ b/Mage.Sets/src/mage/cards/i/InsultInjury.java @@ -37,8 +37,8 @@ public final class InsultInjury extends SplitCard { // Injury // Injury deals 2 damage to target creature and 2 damage to target player. getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); - getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent()); - getRightHalfCard().getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); + getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); + getRightHalfCard().getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker().setTargetTag(2)); getRightHalfCard().getSpellAbility().addEffect(new DamageTargetAndTargetEffect(2, 2)); } -- 2.47.2 From f2bf831e6169190ba412c9e1c44d3b04c8a909e9 Mon Sep 17 00:00:00 2001 From: xenohedron <12538125+xenohedron@users.noreply.github.com> Date: Tue, 11 Nov 2025 00:20:32 -0500 Subject: [PATCH 189/261] improve verify checks for target tag usage --- .../common/DamageTargetAndTargetEffect.java | 8 +++-- .../common/TargetsDamageTargetsEffect.java | 30 +++++++------------ 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java index 2b9acbebcf2..55a951b8085 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetAndTargetEffect.java @@ -40,8 +40,8 @@ public class DamageTargetAndTargetEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - source.getTargets().getByTag(1).getTargets().forEach(uuid -> damageTarget(uuid, firstAmount, source, game)); - source.getTargets().getByTag(2).getTargets().forEach(uuid -> damageTarget(uuid, secondAmount, source, game)); + source.getTargets().getTargetsByTag(1).forEach(uuid -> damageTarget(uuid, firstAmount, source, game)); + source.getTargets().getTargetsByTag(2).forEach(uuid -> damageTarget(uuid, secondAmount, source, game)); return true; } @@ -59,6 +59,10 @@ public class DamageTargetAndTargetEffect extends OneShotEffect { @Override public String getText(Mode mode) { + // verify check that target tags are properly setup + if (mode.getTargets().getByTag(1) == null || mode.getTargets().getByTag(2) == null) { + throw new IllegalArgumentException("Wrong code usage: need to add tags to targets"); + } if (staticText != null && !staticText.isEmpty()) { return staticText; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/TargetsDamageTargetsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TargetsDamageTargetsEffect.java index cad1c21c75b..577b5b508dc 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/TargetsDamageTargetsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/TargetsDamageTargetsEffect.java @@ -6,7 +6,6 @@ import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.Target; import java.util.ArrayList; import java.util.List; @@ -42,37 +41,26 @@ public class TargetsDamageTargetsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - if (source.getTargets().size() < 2) { - return false; - } - - Target damageTarget = source.getTargets().getByTag(1); - Target additionalDamageTarget = source.getTargets().getByTag(2); - Target destTarget = source.getTargets().getByTag(3); - List damagingPermanents = new ArrayList<>(); List receivingPermanents = new ArrayList<>(); - for (UUID id : damageTarget.getTargets()) { + for (UUID id : source.getTargets().getTargetsByTag(1)) { // dealing damage Permanent permanent = game.getPermanent(id); if (permanent != null) { damagingPermanents.add(permanent); } } - if (additionalDamageTarget != null) { - for (UUID id : additionalDamageTarget.getTargets()) { - Permanent permanent = game.getPermanent(id); - if (permanent != null) { - damagingPermanents.add(permanent); - } + for (UUID id : source.getTargets().getTargetsByTag(2)) { // additional dealing damage, if applicable + Permanent permanent = game.getPermanent(id); + if (permanent != null) { + damagingPermanents.add(permanent); } } - for (UUID id : destTarget.getTargets()) { + for (UUID id : source.getTargets().getTargetsByTag(3)) { // receiving damage Permanent permanent = game.getPermanent(id); if (permanent != null) { receivingPermanents.add(permanent); } } - if (receivingPermanents.isEmpty() || damagingPermanents.isEmpty()) { return false; } @@ -86,6 +74,10 @@ public class TargetsDamageTargetsEffect extends OneShotEffect { @Override public String getText(Mode mode) { + // verify check that target tags are properly setup + if (mode.getTargets().getByTag(1) == null || mode.getTargets().getByTag(3) == null) { + throw new IllegalArgumentException("Wrong code usage: need to add tags to targets"); + } if (staticText != null && !staticText.isEmpty()) { return staticText; } @@ -102,4 +94,4 @@ public class TargetsDamageTargetsEffect extends OneShotEffect { sb.append(mode.getTargets().getByTag(3).getDescription()); return sb.toString(); } -} \ No newline at end of file +} -- 2.47.2 From 9d49f601c213cfc6a81bb03f795acc7073efe57c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 10:59:32 -0500 Subject: [PATCH 190/261] [TLE] Implement Aang, A Lot to Learn --- .../src/mage/cards/a/AangALotToLearn.java | 58 +++++++++++++++++++ .../src/mage/cards/d/DragonflySwarm.java | 13 +---- .../src/mage/cards/f/FireNationCadets.java | 13 +---- .../src/mage/cards/f/FirstTimeFlyer.java | 15 ++--- Mage.Sets/src/mage/cards/g/GranGran.java | 16 +---- Mage.Sets/src/mage/cards/m/MasterPakku.java | 6 +- Mage.Sets/src/mage/cards/p/PlatypusBear.java | 13 +---- Mage.Sets/src/mage/cards/t/TheLionTurtle.java | 17 +----- .../sets/AvatarTheLastAirbenderEternal.java | 1 + .../common/LessonsInGraveCondition.java | 45 ++++++++++++++ 10 files changed, 124 insertions(+), 73 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/a/AangALotToLearn.java create mode 100644 Mage/src/main/java/mage/abilities/condition/common/LessonsInGraveCondition.java diff --git a/Mage.Sets/src/mage/cards/a/AangALotToLearn.java b/Mage.Sets/src/mage/cards/a/AangALotToLearn.java new file mode 100644 index 00000000000..348834371d5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AangALotToLearn.java @@ -0,0 +1,58 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.LessonsInGraveCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AangALotToLearn extends CardImpl { + + public AangALotToLearn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G/W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.AVATAR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Aang has vigilance as long as there's a Lesson card in your graveyard. + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new GainAbilitySourceEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield), + LessonsInGraveCondition.ONE, "{this} has vigilance as long as there's a Lesson card in your graveyard" + )).addHint(LessonsInGraveCondition.getHint())); + + // Whenever another creature you control dies, put a +1/+1 counter on Aang. + this.addAbility(new DiesCreatureTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), + false, StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL + )); + } + + private AangALotToLearn(final AangALotToLearn card) { + super(card); + } + + @Override + public AangALotToLearn copy() { + return new AangALotToLearn(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DragonflySwarm.java b/Mage.Sets/src/mage/cards/d/DragonflySwarm.java index be39d818143..35683a3dd5f 100644 --- a/Mage.Sets/src/mage/cards/d/DragonflySwarm.java +++ b/Mage.Sets/src/mage/cards/d/DragonflySwarm.java @@ -3,16 +3,12 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.CompoundCondition; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.condition.common.LessonsInGraveCondition; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.SetBasePowerSourceEffect; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.WardAbility; import mage.cards.CardImpl; @@ -38,11 +34,6 @@ public final class DragonflySwarm extends CardImpl { } private static final DynamicValue xValue = new CardsInControllerGraveyardCount(filter); - private static final Condition condition = new CompoundCondition( - "there's a Lesson card in your graveyard", - new CardsInControllerGraveyardCondition(1, new FilterCard(SubType.LESSON)) - ); - private static final Hint hint = new ConditionHint(condition); public DragonflySwarm(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}"); @@ -63,7 +54,7 @@ public final class DragonflySwarm extends CardImpl { // When this creature dies, if there's a Lesson card in your graveyard, draw a card. this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)) - .withInterveningIf(condition).addHint(hint)); + .withInterveningIf(LessonsInGraveCondition.ONE).addHint(LessonsInGraveCondition.getHint())); } private DragonflySwarm(final DragonflySwarm card) { diff --git a/Mage.Sets/src/mage/cards/f/FireNationCadets.java b/Mage.Sets/src/mage/cards/f/FireNationCadets.java index f1eac9405e8..8b5a49df213 100644 --- a/Mage.Sets/src/mage/cards/f/FireNationCadets.java +++ b/Mage.Sets/src/mage/cards/f/FireNationCadets.java @@ -3,21 +3,17 @@ package mage.cards.f; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.condition.common.LessonsInGraveCondition; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; import mage.abilities.keyword.FirebendingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.FilterCard; import java.util.UUID; @@ -26,9 +22,6 @@ import java.util.UUID; */ public final class FireNationCadets extends CardImpl { - private static final Condition condition = new CardsInControllerGraveyardCondition(1, new FilterCard(SubType.LESSON)); - private static final Hint hint = new ConditionHint(condition, "There's a Lesson card in your graveyard"); - public FireNationCadets(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); @@ -39,9 +32,9 @@ public final class FireNationCadets extends CardImpl { // This creature has firebending 2 as long as there's a Lesson card in your graveyard. this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( - new GainAbilitySourceEffect(new FirebendingAbility(2)), condition, + new GainAbilitySourceEffect(new FirebendingAbility(2)), LessonsInGraveCondition.ONE, "{this} has firebending 2 as long as there's a Lesson card in your graveyard" - )).addHint(hint)); + )).addHint(LessonsInGraveCondition.getHint())); // {2}: This creature gets +1/+0 until end of turn. this.addAbility(new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/f/FirstTimeFlyer.java b/Mage.Sets/src/mage/cards/f/FirstTimeFlyer.java index 945c34d9b2b..fa877cfb032 100644 --- a/Mage.Sets/src/mage/cards/f/FirstTimeFlyer.java +++ b/Mage.Sets/src/mage/cards/f/FirstTimeFlyer.java @@ -2,19 +2,15 @@ package mage.cards.f; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.condition.common.LessonsInGraveCondition; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.FilterCard; import java.util.UUID; @@ -23,9 +19,6 @@ import java.util.UUID; */ public final class FirstTimeFlyer extends CardImpl { - private static final Condition condition = new CardsInControllerGraveyardCondition(1, new FilterCard(SubType.LESSON)); - private static final Hint hint = new ConditionHint(condition, "There's a Lesson card in your graveyard"); - public FirstTimeFlyer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); @@ -40,9 +33,9 @@ public final class FirstTimeFlyer extends CardImpl { // This creature gets +1/+1 as long as there's a Lesson card in your graveyard. this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( - new BoostSourceEffect(1, 1, Duration.WhileOnBattlefield), - condition, "{this} gets +1/+1 as long as there's a Lesson card in your graveyard" - )).addHint(hint)); + new BoostSourceEffect(1, 1, Duration.WhileOnBattlefield), LessonsInGraveCondition.ONE, + "{this} gets +1/+1 as long as there's a Lesson card in your graveyard" + )).addHint(LessonsInGraveCondition.getHint())); } private FirstTimeFlyer(final FirstTimeFlyer card) { diff --git a/Mage.Sets/src/mage/cards/g/GranGran.java b/Mage.Sets/src/mage/cards/g/GranGran.java index fcd4d51fdd8..74a1d6538d3 100644 --- a/Mage.Sets/src/mage/cards/g/GranGran.java +++ b/Mage.Sets/src/mage/cards/g/GranGran.java @@ -3,20 +3,15 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.common.BecomesTappedSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.condition.common.LessonsInGraveCondition; import mage.abilities.decorator.ConditionalCostModificationEffect; -import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.FilterCard; import mage.filter.StaticFilters; import java.util.UUID; @@ -26,11 +21,6 @@ import java.util.UUID; */ public final class GranGran extends CardImpl { - private static final Condition condition = new CardsInControllerGraveyardCondition(3, new FilterCard(SubType.LESSON)); - private static final Hint hint = new ValueHint( - "Lesson cards in your graveyard", new CardsInControllerGraveyardCount(new FilterCard(SubType.LESSON)) - ); - public GranGran(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}"); @@ -47,9 +37,9 @@ public final class GranGran extends CardImpl { // Noncreature spells you cast cost {1} less to cast as long as there are three or more Lesson cards in your graveyard. this.addAbility(new SimpleStaticAbility(new ConditionalCostModificationEffect( new SpellsCostReductionControllerEffect(StaticFilters.FILTER_CARD_NON_CREATURE, 1), - condition, "noncreature spells you cast cost {1} less to cast as long as " + + LessonsInGraveCondition.THREE, "noncreature spells you cast cost {1} less to cast as long as " + "there are three or more Lesson cards in your graveyard" - )).addHint(hint)); + )).addHint(LessonsInGraveCondition.getHint())); } private GranGran(final GranGran card) { diff --git a/Mage.Sets/src/mage/cards/m/MasterPakku.java b/Mage.Sets/src/mage/cards/m/MasterPakku.java index 2ee107fed73..98eb78240ab 100644 --- a/Mage.Sets/src/mage/cards/m/MasterPakku.java +++ b/Mage.Sets/src/mage/cards/m/MasterPakku.java @@ -3,11 +3,10 @@ package mage.cards.m; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BecomesTappedSourceTriggeredAbility; +import mage.abilities.condition.common.LessonsInGraveCondition; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; import mage.abilities.effects.common.MillCardsTargetEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.abilities.keyword.ProwessAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -25,7 +24,6 @@ import java.util.UUID; public final class MasterPakku extends CardImpl { private static final DynamicValue xValue = new CardsInControllerGraveyardCount(new FilterCard(SubType.LESSON, "Lesson cards"), null); - private static final Hint hint = new ValueHint("Lesson cards in your graveyard", xValue); public MasterPakku(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); @@ -43,7 +41,7 @@ public final class MasterPakku extends CardImpl { // Whenever Master Pakku becomes tapped, target player mills X cards, where X is the number of Lesson cards in your graveyard. Ability ability = new BecomesTappedSourceTriggeredAbility(new MillCardsTargetEffect(xValue)); ability.addTarget(new TargetPlayer()); - this.addAbility(ability.addHint(hint)); + this.addAbility(ability.addHint(LessonsInGraveCondition.getHint())); } private MasterPakku(final MasterPakku card) { diff --git a/Mage.Sets/src/mage/cards/p/PlatypusBear.java b/Mage.Sets/src/mage/cards/p/PlatypusBear.java index 3bbe15feeb9..c7179e3c93b 100644 --- a/Mage.Sets/src/mage/cards/p/PlatypusBear.java +++ b/Mage.Sets/src/mage/cards/p/PlatypusBear.java @@ -3,20 +3,16 @@ package mage.cards.p; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.CardsInControllerGraveyardCondition; +import mage.abilities.condition.common.LessonsInGraveCondition; import mage.abilities.decorator.ConditionalAsThoughEffect; import mage.abilities.effects.common.MillCardsControllerEffect; import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderSourceEffect; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; import mage.abilities.keyword.DefenderAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.FilterCard; import java.util.UUID; @@ -25,9 +21,6 @@ import java.util.UUID; */ public final class PlatypusBear extends CardImpl { - private static final Condition condition = new CardsInControllerGraveyardCondition(1, new FilterCard(SubType.LESSON)); - private static final Hint hint = new ConditionHint(condition, "There is a Lesson card in your graveyard"); - public PlatypusBear(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G/U}"); @@ -44,9 +37,9 @@ public final class PlatypusBear extends CardImpl { // As long as there is a Lesson card in your graveyard, this creature can attack as though it didn't have defender. this.addAbility(new SimpleStaticAbility(new ConditionalAsThoughEffect( - new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.WhileOnBattlefield), condition + new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.WhileOnBattlefield), LessonsInGraveCondition.ONE ).setText("as long as there is a Lesson card in your graveyard, " + - "this creature can attack as though it didn't have defender")).addHint(hint)); + "this creature can attack as though it didn't have defender")).addHint(LessonsInGraveCondition.getHint())); } private PlatypusBear(final PlatypusBear card) { diff --git a/Mage.Sets/src/mage/cards/t/TheLionTurtle.java b/Mage.Sets/src/mage/cards/t/TheLionTurtle.java index 543651f65dd..487744f2be8 100644 --- a/Mage.Sets/src/mage/cards/t/TheLionTurtle.java +++ b/Mage.Sets/src/mage/cards/t/TheLionTurtle.java @@ -3,13 +3,9 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.CardsInControllerGraveyardCondition; -import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.condition.common.LessonsInGraveCondition; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.combat.CantAttackBlockUnlessConditionSourceEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.abilities.keyword.ReachAbility; import mage.abilities.keyword.VigilanceAbility; import mage.abilities.mana.AnyColorManaAbility; @@ -18,7 +14,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.FilterCard; import java.util.UUID; @@ -27,13 +22,6 @@ import java.util.UUID; */ public final class TheLionTurtle extends CardImpl { - private static final Condition condition = new CardsInControllerGraveyardCondition( - 3, new FilterCard(SubType.LESSON, "Lesson cards") - ); - private static final Hint hint = new ValueHint( - "Lesson cards in your graveyard", new CardsInControllerGraveyardCount(new FilterCard(SubType.LESSON)) - ); - public TheLionTurtle(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{U}"); @@ -54,7 +42,8 @@ public final class TheLionTurtle extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3))); // The Lion-Turtle can't attack or block unless there are three or more Lesson cards in your graveyard. - this.addAbility(new SimpleStaticAbility(new CantAttackBlockUnlessConditionSourceEffect(condition)).addHint(hint)); + this.addAbility(new SimpleStaticAbility(new CantAttackBlockUnlessConditionSourceEffect(LessonsInGraveCondition.THREE)) + .addHint(LessonsInGraveCondition.getHint())); // {T}: Add one mana of any color. this.addAbility(new AnyColorManaAbility()); diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 856ccac7134..ef12e7fa88d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -28,6 +28,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Aang's Defense", 211, Rarity.COMMON, mage.cards.a.AangsDefense.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang's Defense", 266, Rarity.COMMON, mage.cards.a.AangsDefense.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, A Lot to Learn", 146, Rarity.UNCOMMON, mage.cards.a.AangALotToLearn.class)); cards.add(new SetCardInfo("Aang, Air Nomad", 210, Rarity.RARE, mage.cards.a.AangAirNomad.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, Air Nomad", 265, Rarity.RARE, mage.cards.a.AangAirNomad.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, Airbending Master", 171, Rarity.MYTHIC, mage.cards.a.AangAirbendingMaster.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/condition/common/LessonsInGraveCondition.java b/Mage/src/main/java/mage/abilities/condition/common/LessonsInGraveCondition.java new file mode 100644 index 00000000000..2c2f00f2fe1 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/LessonsInGraveCondition.java @@ -0,0 +1,45 @@ +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * @author TheElk801 + */ +public enum LessonsInGraveCondition implements Condition { + ONE(1), + THREE(3); + private final int amount; + private static final FilterCard filter = new FilterCard(SubType.LESSON); + private static final Hint hint = new ValueHint("Lesson cards in your graveyard", new CardsInControllerGraveyardCount(filter)); + + public static Hint getHint() { + return hint; + } + + LessonsInGraveCondition(int amount) { + this.amount = amount; + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + return player != null && player.getGraveyard().count(filter, game) >= this.amount; + } + + @Override + public String toString() { + if (amount == 1) { + return "there's a Lesson card in your graveyard"; + } + return "there are " + CardUtil.numberToText(this.amount) + " or more Lesson cards in your graveyard"; + } +} -- 2.47.2 From 3bca2e4eabcabe9fa19c46fe73943b63a44c9c4e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:05:31 -0500 Subject: [PATCH 191/261] [TLE] Implement Chakra Meditation --- .../src/mage/cards/c/ChakraMeditation.java | 50 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 2 + 2 files changed, 52 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/ChakraMeditation.java diff --git a/Mage.Sets/src/mage/cards/c/ChakraMeditation.java b/Mage.Sets/src/mage/cards/c/ChakraMeditation.java new file mode 100644 index 00000000000..b6ff38883ce --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ChakraMeditation.java @@ -0,0 +1,50 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.condition.common.LessonsInGraveCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCardInYourGraveyard; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ChakraMeditation extends CardImpl { + + public ChakraMeditation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + // When this enchantment enters, return up to one target instant or sorcery card from your graveyard to your hand. + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()); + ability.addTarget(new TargetCardInYourGraveyard(0, 1, StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD)); + this.addAbility(ability); + + // Whenever you cast an instant or sorcery spell, draw a card. Then discard a card unless there are three or more Lesson cards in your graveyard. + ability = new SpellCastControllerTriggeredAbility( + new DrawCardSourceControllerEffect(1), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false + ); + ability.addEffect(new ConditionalOneShotEffect( + null, LessonsInGraveCondition.THREE, "Then discard a card " + + "unless there are three or more Lesson cards in your graveyard")); + this.addAbility(ability); + } + + private ChakraMeditation(final ChakraMeditation card) { + super(card); + } + + @Override + public ChakraMeditation copy() { + return new ChakraMeditation(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index ef12e7fa88d..badcc194c7c 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -61,6 +61,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Capital Guard", 277, Rarity.COMMON, mage.cards.c.CapitalGuard.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Captain Sisay", 47, Rarity.MYTHIC, mage.cards.c.CaptainSisay.class)); cards.add(new SetCardInfo("Cathartic Reunion", 164, Rarity.COMMON, mage.cards.c.CatharticReunion.class)); + cards.add(new SetCardInfo("Chakra Meditation", 179, Rarity.RARE, mage.cards.c.ChakraMeditation.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Chakra Meditation", 91, Rarity.RARE, mage.cards.c.ChakraMeditation.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Cityscape Leveler", 53, Rarity.MYTHIC, mage.cards.c.CityscapeLeveler.class)); cards.add(new SetCardInfo("Clone Legion", 12, Rarity.MYTHIC, mage.cards.c.CloneLegion.class)); cards.add(new SetCardInfo("Clone", 11, Rarity.MYTHIC, mage.cards.c.Clone.class)); -- 2.47.2 From bfed992bf8e53921cc8598d0ad66ac285d0e29e3 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:09:03 -0500 Subject: [PATCH 192/261] [TLE] Implement Cracked Earth Technique --- .../mage/cards/c/CrackedEarthTechnique.java | 42 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 43 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CrackedEarthTechnique.java diff --git a/Mage.Sets/src/mage/cards/c/CrackedEarthTechnique.java b/Mage.Sets/src/mage/cards/c/CrackedEarthTechnique.java new file mode 100644 index 00000000000..2230220930d --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CrackedEarthTechnique.java @@ -0,0 +1,42 @@ +package mage.cards.c; + +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetControlledLandPermanent; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CrackedEarthTechnique extends CardImpl { + + public CrackedEarthTechnique(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}"); + + this.subtype.add(SubType.LESSON); + + // Earthbend 3, then earthbend 3. You gain 3 life. + this.getSpellAbility().addEffect(new EarthbendTargetEffect(3)); + this.getSpellAbility().addEffect(new EarthbendTargetEffect(3) + .setTargetPointer(new SecondTargetPointer()) + .concatBy(", then")); + this.getSpellAbility().addTarget(new TargetControlledLandPermanent().withChooseHint("first target")); + this.getSpellAbility().addTarget(new TargetControlledLandPermanent().withChooseHint("second target")); + this.getSpellAbility().addEffect(new GainLifeEffect(3)); + } + + private CrackedEarthTechnique(final CrackedEarthTechnique card) { + super(card); + } + + @Override + public CrackedEarthTechnique copy() { + return new CrackedEarthTechnique(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index badcc194c7c..0dbac7c704e 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -69,6 +69,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Cloudshift", 152, Rarity.COMMON, mage.cards.c.Cloudshift.class)); cards.add(new SetCardInfo("Coastal Piracy", 156, Rarity.UNCOMMON, mage.cards.c.CoastalPiracy.class)); cards.add(new SetCardInfo("Consider", 157, Rarity.COMMON, mage.cards.c.Consider.class)); + cards.add(new SetCardInfo("Cracked Earth Technique", 135, Rarity.UNCOMMON, mage.cards.c.CrackedEarthTechnique.class)); cards.add(new SetCardInfo("Cruel Tutor", 24, Rarity.MYTHIC, mage.cards.c.CruelTutor.class)); cards.add(new SetCardInfo("Dark Deal", 161, Rarity.UNCOMMON, mage.cards.d.DarkDeal.class)); cards.add(new SetCardInfo("Dark Depths", 56, Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); -- 2.47.2 From 7bb5e54eec19fd24776e9d62a04ce8813b9d6cd2 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:10:46 -0500 Subject: [PATCH 193/261] [TLE] Implement Creeping Crystal Coating --- .../mage/cards/c/CreepingCrystalCoating.java | 59 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 60 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CreepingCrystalCoating.java diff --git a/Mage.Sets/src/mage/cards/c/CreepingCrystalCoating.java b/Mage.Sets/src/mage/cards/c/CreepingCrystalCoating.java new file mode 100644 index 00000000000..08ddafcbd0b --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CreepingCrystalCoating.java @@ -0,0 +1,59 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.game.permanent.token.FoodToken; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CreepingCrystalCoating extends CardImpl { + + public CreepingCrystalCoating(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); + + this.subtype.add(SubType.AURA); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + this.addAbility(new EnchantAbility(auraTarget)); + + // Enchanted creature gets +0/+3 and has "Whenever this creature attacks, create a Food token." + Ability ability = new SimpleStaticAbility(new BoostEnchantedEffect(0, 3)); + ability.addEffect(new GainAbilityAttachedEffect( + new AttacksTriggeredAbility(new CreateTokenEffect(new FoodToken())), AttachmentType.AURA + ).setText("and has \"Whenever this creature attacks, create a Food token.\"")); + this.addAbility(ability); + } + + private CreepingCrystalCoating(final CreepingCrystalCoating card) { + super(card); + } + + @Override + public CreepingCrystalCoating copy() { + return new CreepingCrystalCoating(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 0dbac7c704e..ac2fff0a8c9 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -70,6 +70,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Coastal Piracy", 156, Rarity.UNCOMMON, mage.cards.c.CoastalPiracy.class)); cards.add(new SetCardInfo("Consider", 157, Rarity.COMMON, mage.cards.c.Consider.class)); cards.add(new SetCardInfo("Cracked Earth Technique", 135, Rarity.UNCOMMON, mage.cards.c.CrackedEarthTechnique.class)); + cards.add(new SetCardInfo("Creeping Crystal Coating", 136, Rarity.UNCOMMON, mage.cards.c.CreepingCrystalCoating.class)); cards.add(new SetCardInfo("Cruel Tutor", 24, Rarity.MYTHIC, mage.cards.c.CruelTutor.class)); cards.add(new SetCardInfo("Dark Deal", 161, Rarity.UNCOMMON, mage.cards.d.DarkDeal.class)); cards.add(new SetCardInfo("Dark Depths", 56, Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); -- 2.47.2 From 8794545c9fa417e51f5509ceedeb7b061d1777bc Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:12:08 -0500 Subject: [PATCH 194/261] [TLE] Implement Crystalline Armor --- .../src/mage/cards/c/CrystallineArmor.java | 56 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 2 + 2 files changed, 58 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CrystallineArmor.java diff --git a/Mage.Sets/src/mage/cards/c/CrystallineArmor.java b/Mage.Sets/src/mage/cards/c/CrystallineArmor.java new file mode 100644 index 00000000000..4a39d5fb10a --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CrystallineArmor.java @@ -0,0 +1,56 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.LandsYouControlCount; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CrystallineArmor extends CardImpl { + + public CrystallineArmor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + this.addAbility(new EnchantAbility(auraTarget)); + + // Enchanted creature gets +1/+1 for each land you control and has trample. + Ability ability = new SimpleStaticAbility(new BoostEnchantedEffect( + LandsYouControlCount.instance, LandsYouControlCount.instance + ).setText("enchanted creature gets +1/+1 for each land you control")); + ability.addEffect(new GainAbilityAttachedEffect( + TrampleAbility.getInstance(), AttachmentType.AURA + ).setText("and has trample")); + this.addAbility(ability); + } + + private CrystallineArmor(final CrystallineArmor card) { + super(card); + } + + @Override + public CrystallineArmor copy() { + return new CrystallineArmor(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index ac2fff0a8c9..0cb1348dee0 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -72,6 +72,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Cracked Earth Technique", 135, Rarity.UNCOMMON, mage.cards.c.CrackedEarthTechnique.class)); cards.add(new SetCardInfo("Creeping Crystal Coating", 136, Rarity.UNCOMMON, mage.cards.c.CreepingCrystalCoating.class)); cards.add(new SetCardInfo("Cruel Tutor", 24, Rarity.MYTHIC, mage.cards.c.CruelTutor.class)); + cards.add(new SetCardInfo("Crystalline Armor", 137, Rarity.RARE, mage.cards.c.CrystallineArmor.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Crystalline Armor", 204, Rarity.RARE, mage.cards.c.CrystallineArmor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dark Deal", 161, Rarity.UNCOMMON, mage.cards.d.DarkDeal.class)); cards.add(new SetCardInfo("Dark Depths", 56, Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); cards.add(new SetCardInfo("Deadly Rollick", 309, Rarity.RARE, mage.cards.d.DeadlyRollick.class)); -- 2.47.2 From bea75d55af8fd8ee468d96aa9fbb46223a8d659e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:13:24 -0500 Subject: [PATCH 195/261] [TLE] Implement Dai Li Censor --- Mage.Sets/src/mage/cards/d/DaiLiCensor.java | 48 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/d/DaiLiCensor.java diff --git a/Mage.Sets/src/mage/cards/d/DaiLiCensor.java b/Mage.Sets/src/mage/cards/d/DaiLiCensor.java new file mode 100644 index 00000000000..c9c68eb9dcb --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DaiLiCensor.java @@ -0,0 +1,48 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DaiLiCensor extends CardImpl { + + public DaiLiCensor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.ADVISOR); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // {1}, Sacrifice another creature: This creature gets +2/+2 until end of turn. Activate only once each turn. + Ability ability = new LimitedTimesPerTurnActivatedAbility( + new BoostSourceEffect(2, 2, Duration.EndOfTurn), new GenericManaCost(1) + ); + ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_ANOTHER_CREATURE)); + this.addAbility(ability); + } + + private DaiLiCensor(final DaiLiCensor card) { + super(card); + } + + @Override + public DaiLiCensor copy() { + return new DaiLiCensor(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 0cb1348dee0..d69df9c096c 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -74,6 +74,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Cruel Tutor", 24, Rarity.MYTHIC, mage.cards.c.CruelTutor.class)); cards.add(new SetCardInfo("Crystalline Armor", 137, Rarity.RARE, mage.cards.c.CrystallineArmor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Crystalline Armor", 204, Rarity.RARE, mage.cards.c.CrystallineArmor.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Dai Li Censor", 102, Rarity.COMMON, mage.cards.d.DaiLiCensor.class)); cards.add(new SetCardInfo("Dark Deal", 161, Rarity.UNCOMMON, mage.cards.d.DarkDeal.class)); cards.add(new SetCardInfo("Dark Depths", 56, Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); cards.add(new SetCardInfo("Deadly Rollick", 309, Rarity.RARE, mage.cards.d.DeadlyRollick.class)); -- 2.47.2 From 6fb84830b35aad7821f51935b49b3ecb042597fc Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:13:45 -0500 Subject: [PATCH 196/261] [TLE] Implement Deer-Dog --- Mage.Sets/src/mage/cards/d/DeerDog.java | 37 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 38 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/d/DeerDog.java diff --git a/Mage.Sets/src/mage/cards/d/DeerDog.java b/Mage.Sets/src/mage/cards/d/DeerDog.java new file mode 100644 index 00000000000..45518297a9d --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeerDog.java @@ -0,0 +1,37 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DeerDog extends CardImpl { + + public DeerDog(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.ELK); + this.subtype.add(SubType.DOG); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + } + + private DeerDog(final DeerDog card) { + super(card); + } + + @Override + public DeerDog copy() { + return new DeerDog(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index d69df9c096c..9a18fb6059b 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -78,6 +78,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Dark Deal", 161, Rarity.UNCOMMON, mage.cards.d.DarkDeal.class)); cards.add(new SetCardInfo("Dark Depths", 56, Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); cards.add(new SetCardInfo("Deadly Rollick", 309, Rarity.RARE, mage.cards.d.DeadlyRollick.class)); + cards.add(new SetCardInfo("Deer-Dog", 114, Rarity.COMMON, mage.cards.d.DeerDog.class)); cards.add(new SetCardInfo("Deflecting Swat", 311, Rarity.RARE, mage.cards.d.DeflectingSwat.class)); cards.add(new SetCardInfo("Deny Entry", 222, Rarity.COMMON, mage.cards.d.DenyEntry.class)); cards.add(new SetCardInfo("Descendants' Path", 167, Rarity.RARE, mage.cards.d.DescendantsPath.class)); -- 2.47.2 From f5802be13369b4242448f65d550b86be78d6b061 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:21:37 -0500 Subject: [PATCH 197/261] [TLE] Implement Earthshape --- Mage.Sets/src/mage/cards/e/Earthshape.java | 81 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + .../keyword/EarthbendTargetEffect.java | 8 +- 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/e/Earthshape.java diff --git a/Mage.Sets/src/mage/cards/e/Earthshape.java b/Mage.Sets/src/mage/cards/e/Earthshape.java new file mode 100644 index 00000000000..713f6a7273b --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/Earthshape.java @@ -0,0 +1,81 @@ +package mage.cards.e; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.abilities.keyword.HexproofAbility; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Earthshape extends CardImpl { + + public Earthshape(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); + + // Earthbend 3. Then each creature you control with power less than or equal to that land's power gains hexproof and indestructible until end of turn. You gain hexproof until end of turn. + this.getSpellAbility().addEffect(new EarthshapeEffect()); + this.getSpellAbility().addTarget(new TargetControlledLandPermanent()); + this.getSpellAbility().addEffect(new GainAbilityControllerEffect(HexproofAbility.getInstance(), Duration.EndOfTurn)); + } + + private Earthshape(final Earthshape card) { + super(card); + } + + @Override + public Earthshape copy() { + return new Earthshape(this); + } +} + +class EarthshapeEffect extends OneShotEffect { + + EarthshapeEffect() { + super(Outcome.Benefit); + staticText = "Earthbend 3. Then each creature you control with power less than or equal " + + "to that land's power gains hexproof and indestructible until end of turn"; + } + + private EarthshapeEffect(final EarthshapeEffect effect) { + super(effect); + } + + @Override + public EarthshapeEffect copy() { + return new EarthshapeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent == null) { + return false; + } + EarthbendTargetEffect.doEarthBend(permanent, 3, game, source); + game.processAction(); + int power = permanent.getPower().getValue(); + FilterPermanent filter = new FilterControlledCreaturePermanent(); + filter.add(new PowerPredicate(ComparisonType.OR_LESS, power)); + game.addEffect(new GainAbilityAllEffect(HexproofAbility.getInstance(), Duration.EndOfTurn, filter), source); + game.addEffect(new GainAbilityAllEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn, filter), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 9a18fb6059b..0ce71d2b830 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -91,6 +91,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Drannith Magistrate", 2, Rarity.MYTHIC, mage.cards.d.DrannithMagistrate.class)); cards.add(new SetCardInfo("Duelist's Heritage", 153, Rarity.RARE, mage.cards.d.DuelistsHeritage.class)); cards.add(new SetCardInfo("Earthbending Student", 249, Rarity.UNCOMMON, mage.cards.e.EarthbendingStudent.class)); + cards.add(new SetCardInfo("Earthshape", 67, Rarity.RARE, mage.cards.e.Earthshape.class)); cards.add(new SetCardInfo("Eel-Hounds", 250, Rarity.UNCOMMON, mage.cards.e.EelHounds.class)); cards.add(new SetCardInfo("Eladamri's Call", 48, Rarity.MYTHIC, mage.cards.e.EladamrisCall.class)); cards.add(new SetCardInfo("Elemental Bond", 40, Rarity.MYTHIC, mage.cards.e.ElementalBond.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/EarthbendTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/EarthbendTargetEffect.java index 9ed6c95b839..f9d73740e2d 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/EarthbendTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/EarthbendTargetEffect.java @@ -54,19 +54,23 @@ public class EarthbendTargetEffect extends OneShotEffect { if (permanent == null) { return false; } + int value = amount.calculate(game, source, this); + doEarthBend(permanent, value, game, source); + return true; + } + + public static void doEarthBend(Permanent permanent, int value, Game game, Ability source) { game.addEffect(new BecomesCreatureTargetEffect( new CreatureToken(0, 0) .withAbility(HasteAbility.getInstance()), false, true, Duration.Custom ), source); - int value = amount.calculate(game, source, this); permanent.addCounters(CounterType.P1P1.createInstance(value), source, game); game.addDelayedTriggeredAbility(new EarthbendingDelayedTriggeredAbility(permanent, game), source); game.fireEvent(GameEvent.getEvent( GameEvent.EventType.EARTHBENDED, permanent.getId(), source, source.getControllerId(), value )); - return true; } @Override -- 2.47.2 From d64e8b91947141c7a9192ef4ced78f15c3b47c93 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:23:23 -0500 Subject: [PATCH 198/261] [TLE] Implement Fire Nation Occupation --- .../mage/cards/f/FireNationOccupation.java | 39 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 2 + 2 files changed, 41 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FireNationOccupation.java diff --git a/Mage.Sets/src/mage/cards/f/FireNationOccupation.java b/Mage.Sets/src/mage/cards/f/FireNationOccupation.java new file mode 100644 index 00000000000..e3412910b9a --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FireNationOccupation.java @@ -0,0 +1,39 @@ +package mage.cards.f; + +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.condition.common.OpponentsTurnCondition; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.permanent.token.SoldierFirebendingToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FireNationOccupation extends CardImpl { + + public FireNationOccupation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); + + // When this enchantment enters, create a 2/2 red Soldier creature token with firebending 1. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SoldierFirebendingToken()))); + + // Whenever you cast a spell during an opponent's turn, create a 2/2 red Soldier creature token with firebending 1. + this.addAbility(new SpellCastControllerTriggeredAbility( + new CreateTokenEffect(new SoldierFirebendingToken()), false + ).withTriggerCondition(OpponentsTurnCondition.instance)); + } + + private FireNationOccupation(final FireNationOccupation card) { + super(card); + } + + @Override + public FireNationOccupation copy() { + return new FireNationOccupation(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 0ce71d2b830..a301649d4d8 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -110,6 +110,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Fiery Confluence", 165, Rarity.RARE, mage.cards.f.FieryConfluence.class)); cards.add(new SetCardInfo("Fire Nation Ambushers", 229, Rarity.COMMON, mage.cards.f.FireNationAmbushers.class)); cards.add(new SetCardInfo("Fire Nation Archers", 237, Rarity.RARE, mage.cards.f.FireNationArchers.class)); + cards.add(new SetCardInfo("Fire Nation Occupation", 105, Rarity.RARE, mage.cards.f.FireNationOccupation.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fire Nation Occupation", 187, Rarity.RARE, mage.cards.f.FireNationOccupation.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation Sentinels", 230, Rarity.RARE, mage.cards.f.FireNationSentinels.class)); cards.add(new SetCardInfo("Fire Nation Soldier", 238, Rarity.COMMON, mage.cards.f.FireNationSoldier.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation Soldier", 280, Rarity.COMMON, mage.cards.f.FireNationSoldier.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 4cc7a079ecb759755e472983a437aa3609cd32a6 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:26:05 -0500 Subject: [PATCH 199/261] [TLE] Implement Fire Nation Turret --- .../src/mage/cards/f/FireNationTurret.java | 60 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 61 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FireNationTurret.java diff --git a/Mage.Sets/src/mage/cards/f/FireNationTurret.java b/Mage.Sets/src/mage/cards/f/FireNationTurret.java new file mode 100644 index 00000000000..be67f432b7c --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FireNationTurret.java @@ -0,0 +1,60 @@ +package mage.cards.f; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveCountersSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.FirebendingAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FireNationTurret extends CardImpl { + + public FireNationTurret(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{R}"); + + // At the beginning of combat on your turn, up to one target creature gets +2/+0 and gains firebending 2 until end of turn. + Ability ability = new BeginningOfCombatTriggeredAbility(new BoostTargetEffect(2, 0) + .setText("up to one target creature gets +2/+0")); + ability.addEffect(new GainAbilityTargetEffect(new FirebendingAbility(2)) + .setText("and gains firebending 2 until end of turn")); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + this.addAbility(ability); + + // {R}: Put a charge counter on this artifact. + this.addAbility(new SimpleActivatedAbility( + new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), new ManaCostsImpl<>("{R}") + )); + + // Remove fifty charge counters from this artifact: It deals 50 damage to any target. + ability = new SimpleActivatedAbility( + new DamageTargetEffect(50, "it"), + new RemoveCountersSourceCost(CounterType.CHARGE.createInstance(50)) + ); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + } + + private FireNationTurret(final FireNationTurret card) { + super(card); + } + + @Override + public FireNationTurret copy() { + return new FireNationTurret(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index a301649d4d8..a7c1e5e7e75 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -115,6 +115,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Fire Nation Sentinels", 230, Rarity.RARE, mage.cards.f.FireNationSentinels.class)); cards.add(new SetCardInfo("Fire Nation Soldier", 238, Rarity.COMMON, mage.cards.f.FireNationSoldier.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation Soldier", 280, Rarity.COMMON, mage.cards.f.FireNationSoldier.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fire Nation Turret", 64, Rarity.RARE, mage.cards.f.FireNationTurret.class)); cards.add(new SetCardInfo("Fire Nation's Conquest", 239, Rarity.UNCOMMON, mage.cards.f.FireNationsConquest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation's Conquest", 281, Rarity.UNCOMMON, mage.cards.f.FireNationsConquest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fists of Flame", 166, Rarity.COMMON, mage.cards.f.FistsOfFlame.class)); -- 2.47.2 From eafc6600da9b8d315992b84d5c5817545d92ffdc Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:28:13 -0500 Subject: [PATCH 200/261] [TLE] Implement Founding of Omashu --- .../src/mage/cards/f/FoundingOfOmashu.java | 51 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 52 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FoundingOfOmashu.java diff --git a/Mage.Sets/src/mage/cards/f/FoundingOfOmashu.java b/Mage.Sets/src/mage/cards/f/FoundingOfOmashu.java new file mode 100644 index 00000000000..3e642cc27e8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FoundingOfOmashu.java @@ -0,0 +1,51 @@ +package mage.cards.f; + +import mage.abilities.common.SagaAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SagaChapter; +import mage.constants.SubType; +import mage.game.permanent.token.AllyToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FoundingOfOmashu extends CardImpl { + + public FoundingOfOmashu(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + + this.subtype.add(SubType.SAGA); + + // (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.) + SagaAbility sagaAbility = new SagaAbility(this); + + // I -- Create two 1/1 white Ally creature tokens. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, new CreateTokenEffect(new AllyToken(), 2)); + + // II -- You may discard a card. If you do, draw a card. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_II, new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new DiscardCardCost())); + + // III -- Creatures you control get +1/+0 until end of turn. + sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, new BoostControlledEffect(1, 0, Duration.EndOfTurn)); + this.addAbility(sagaAbility); + } + + private FoundingOfOmashu(final FoundingOfOmashu card) { + super(card); + } + + @Override + public FoundingOfOmashu copy() { + return new FoundingOfOmashu(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index a7c1e5e7e75..b1a3898951d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -122,6 +122,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Flawless Maneuver", 306, Rarity.RARE, mage.cards.f.FlawlessManeuver.class)); cards.add(new SetCardInfo("Flying Dolphin-Fish", 223, Rarity.COMMON, mage.cards.f.FlyingDolphinFish.class)); cards.add(new SetCardInfo("Force of Negation", 13, Rarity.MYTHIC, mage.cards.f.ForceOfNegation.class)); + cards.add(new SetCardInfo("Founding of Omashu", 116, Rarity.UNCOMMON, mage.cards.f.FoundingOfOmashu.class)); cards.add(new SetCardInfo("Frantic Search", 159, Rarity.COMMON, mage.cards.f.FranticSearch.class)); cards.add(new SetCardInfo("Frog-Squirrels", 251, Rarity.COMMON, mage.cards.f.FrogSquirrels.class)); cards.add(new SetCardInfo("Gamble", 312, Rarity.RARE, mage.cards.g.Gamble.class)); -- 2.47.2 From 25e010ee01ad0a93088f14a916d7b80014da473b Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:30:08 -0500 Subject: [PATCH 201/261] [TLE] Implement Frantic Confrontation --- .../mage/cards/f/FranticConfrontation.java | 42 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 43 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FranticConfrontation.java diff --git a/Mage.Sets/src/mage/cards/f/FranticConfrontation.java b/Mage.Sets/src/mage/cards/f/FranticConfrontation.java new file mode 100644 index 00000000000..b9c4d989924 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FranticConfrontation.java @@ -0,0 +1,42 @@ +package mage.cards.f; + +import mage.abilities.dynamicvalue.common.GetXValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FranticConfrontation extends CardImpl { + + public FranticConfrontation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}"); + + // Target creature you control gets +X/+0 and gains first strike and trample until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(GetXValue.instance, StaticValue.get(0)) + .setText("target creature you control gets +X/+0")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance()) + .setText("and gains first strike")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance()) + .setText("and trample until end of turn")); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + } + + private FranticConfrontation(final FranticConfrontation card) { + super(card); + } + + @Override + public FranticConfrontation copy() { + return new FranticConfrontation(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index b1a3898951d..3eca1be9d06 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -123,6 +123,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Flying Dolphin-Fish", 223, Rarity.COMMON, mage.cards.f.FlyingDolphinFish.class)); cards.add(new SetCardInfo("Force of Negation", 13, Rarity.MYTHIC, mage.cards.f.ForceOfNegation.class)); cards.add(new SetCardInfo("Founding of Omashu", 116, Rarity.UNCOMMON, mage.cards.f.FoundingOfOmashu.class)); + cards.add(new SetCardInfo("Frantic Confrontation", 117, Rarity.UNCOMMON, mage.cards.f.FranticConfrontation.class)); cards.add(new SetCardInfo("Frantic Search", 159, Rarity.COMMON, mage.cards.f.FranticSearch.class)); cards.add(new SetCardInfo("Frog-Squirrels", 251, Rarity.COMMON, mage.cards.f.FrogSquirrels.class)); cards.add(new SetCardInfo("Gamble", 312, Rarity.RARE, mage.cards.g.Gamble.class)); -- 2.47.2 From 97f57fc0e0bbee9e9b64c2d65d2f88abe7734fdd Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:31:34 -0500 Subject: [PATCH 202/261] [TLE] Implement Inspired Insurgent --- .../src/mage/cards/i/InspiredInsurgent.java | 47 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 48 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/InspiredInsurgent.java diff --git a/Mage.Sets/src/mage/cards/i/InspiredInsurgent.java b/Mage.Sets/src/mage/cards/i/InspiredInsurgent.java new file mode 100644 index 00000000000..57c6b2f563c --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InspiredInsurgent.java @@ -0,0 +1,47 @@ +package mage.cards.i; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class InspiredInsurgent extends CardImpl { + + public InspiredInsurgent(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.PEASANT); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {1}, Sacrifice this creature: Destroy target artifact or enchantment. + Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new GenericManaCost(1)); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); + this.addAbility(ability); + } + + private InspiredInsurgent(final InspiredInsurgent card) { + super(card); + } + + @Override + public InspiredInsurgent copy() { + return new InspiredInsurgent(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 3eca1be9d06..cffe6b091d6 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -133,6 +133,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Hippo-Cows", 252, Rarity.COMMON, mage.cards.h.HippoCows.class)); cards.add(new SetCardInfo("Humble Defector", 30, Rarity.MYTHIC, mage.cards.h.HumbleDefector.class)); cards.add(new SetCardInfo("Imprisoned in the Moon", 14, Rarity.MYTHIC, mage.cards.i.ImprisonedInTheMoon.class)); + cards.add(new SetCardInfo("Inspired Insurgent", 77, Rarity.COMMON, mage.cards.i.InspiredInsurgent.class)); cards.add(new SetCardInfo("Inspiring Call", 168, Rarity.UNCOMMON, mage.cards.i.InspiringCall.class)); cards.add(new SetCardInfo("Insurrection", 31, Rarity.MYTHIC, mage.cards.i.Insurrection.class)); cards.add(new SetCardInfo("Intruder Alarm", 15, Rarity.MYTHIC, mage.cards.i.IntruderAlarm.class)); -- 2.47.2 From ee99f7b0948ae909581a167017192ea8ba127515 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:39:22 -0500 Subject: [PATCH 203/261] [TLE] Implement Jet, Rebel Leader --- .../src/mage/cards/j/JetRebelLeader.java | 50 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 2 + .../main/java/mage/constants/PutCards.java | 26 ++++++++++ 3 files changed, 78 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/j/JetRebelLeader.java diff --git a/Mage.Sets/src/mage/cards/j/JetRebelLeader.java b/Mage.Sets/src/mage/cards/j/JetRebelLeader.java new file mode 100644 index 00000000000..ff558865f8b --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JetRebelLeader.java @@ -0,0 +1,50 @@ +package mage.cards.j; + +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.ManaValuePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JetRebelLeader extends CardImpl { + + private static final FilterCard filter = new FilterCreatureCard("creature card with mana value 3 or less"); + + static { + filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4)); + } + + public JetRebelLeader(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.REBEL); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Whenever Jet attacks, look at the top five cards of your library. You may put a creature card with mana value 3 or less from among them onto the battlefield tapped and attacking. Put the rest on the bottom of your library in a random order. + this.addAbility(new AttacksTriggeredAbility(new LookLibraryAndPickControllerEffect( + 5, 1, filter, PutCards.BATTLEFIELD_TAPPED_ATTACKING, PutCards.BOTTOM_RANDOM + ))); + } + + private JetRebelLeader(final JetRebelLeader card) { + super(card); + } + + @Override + public JetRebelLeader copy() { + return new JetRebelLeader(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index cffe6b091d6..2027677b2d1 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -141,6 +141,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Iroh, Dragon of the West", 194, Rarity.RARE, mage.cards.i.IrohDragonOfTheWest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 240, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroh, Firebending Instructor", 282, Rarity.UNCOMMON, mage.cards.i.IrohFirebendingInstructor.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Jet, Rebel Leader", 172, Rarity.RARE, mage.cards.j.JetRebelLeader.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Jet, Rebel Leader", 78, Rarity.RARE, mage.cards.j.JetRebelLeader.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Join the Dance", 50, Rarity.MYTHIC, mage.cards.j.JoinTheDance.class)); cards.add(new SetCardInfo("Katara, Heroic Healer", 215, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Heroic Healer", 269, Rarity.UNCOMMON, mage.cards.k.KataraHeroicHealer.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/constants/PutCards.java b/Mage/src/main/java/mage/constants/PutCards.java index e23963b6746..59ffc721e5f 100644 --- a/Mage/src/main/java/mage/constants/PutCards.java +++ b/Mage/src/main/java/mage/constants/PutCards.java @@ -6,7 +6,11 @@ import mage.cards.Card; import mage.cards.Cards; import mage.cards.CardsImpl; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; +import mage.util.CardUtil; + +import java.util.Set; /** * @author awjackson @@ -17,6 +21,7 @@ public enum PutCards { GRAVEYARD(Outcome.Discard, Zone.GRAVEYARD, "into your graveyard"), BATTLEFIELD(Outcome.PutCardInPlay, Zone.BATTLEFIELD, "onto the battlefield"), BATTLEFIELD_TAPPED(Outcome.PutCardInPlay, Zone.BATTLEFIELD, "onto the battlefield tapped"), + BATTLEFIELD_TAPPED_ATTACKING(Outcome.PutCardInPlay, Zone.BATTLEFIELD, "onto the battlefield tapped and attacking"), BATTLEFIELD_TRANSFORMED(Outcome.PutCardInPlay, Zone.BATTLEFIELD, "onto the battlefield transformed"), EXILED(Outcome.Exile, Zone.EXILED, "into exile"), // may need special case code to generate correct text TOP_OR_BOTTOM(Outcome.Benefit, Zone.LIBRARY, "on the top or bottom of your library"), @@ -75,6 +80,15 @@ public enum PutCards { return player.putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, false); case BATTLEFIELD_TAPPED: return player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); + case BATTLEFIELD_TAPPED_ATTACKING: + if (player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null)) { + Permanent permanent = CardUtil.getPermanentFromCardPutToBattlefield(card, game); + if (permanent != null) { + game.getCombat().addAttackingCreature(permanent.getId(), game); + } + return true; + } + return false; case SHUFFLE: return player.shuffleCardsToLibrary(card, game, source); case BATTLEFIELD_TRANSFORMED: @@ -101,6 +115,18 @@ public enum PutCards { return player.putCardsOnBottomOfLibrary(cards, game, source, false); case BATTLEFIELD_TAPPED: return player.moveCards(cards.getCards(game), Zone.BATTLEFIELD, source, game, true, false, false, null); + case BATTLEFIELD_TAPPED_ATTACKING: + Set cardSet = cards.getCards(game); + if (player.moveCards(cardSet, Zone.BATTLEFIELD, source, game, true, false, false, null)) { + for (Card card : cardSet) { + Permanent permanent = CardUtil.getPermanentFromCardPutToBattlefield(card, game); + if (permanent != null) { + game.getCombat().addAttackingCreature(permanent.getId(), game); + } + } + return true; + } + return false; case SHUFFLE: return player.shuffleCardsToLibrary(cards, game, source); case BATTLEFIELD_TRANSFORMED: -- 2.47.2 From defa5e20f52650a5f923da2bc711686c0186853a Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 11:40:11 -0500 Subject: [PATCH 204/261] [TLE] Implement Koala-Sheep --- Mage.Sets/src/mage/cards/k/KoalaSheep.java | 38 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 39 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/k/KoalaSheep.java diff --git a/Mage.Sets/src/mage/cards/k/KoalaSheep.java b/Mage.Sets/src/mage/cards/k/KoalaSheep.java new file mode 100644 index 00000000000..9d344c20698 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KoalaSheep.java @@ -0,0 +1,38 @@ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KoalaSheep extends CardImpl { + + public KoalaSheep(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.BEAR); + this.subtype.add(SubType.SHEEP); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When this creature enters, you gain 3 life. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3))); + } + + private KoalaSheep(final KoalaSheep card) { + super(card); + } + + @Override + public KoalaSheep copy() { + return new KoalaSheep(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 2027677b2d1..40996db3e40 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -149,6 +149,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Katara, Waterbending Master", 180, Rarity.MYTHIC, mage.cards.k.KataraWaterbendingMaster.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Waterbending Master", 93, Rarity.MYTHIC, mage.cards.k.KataraWaterbendingMaster.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Kindly Customer", 79, Rarity.COMMON, mage.cards.k.KindlyCustomer.class)); + cards.add(new SetCardInfo("Koala-Sheep", 80, Rarity.COMMON, mage.cards.k.KoalaSheep.class)); cards.add(new SetCardInfo("Koma, Cosmos Serpent", 51, Rarity.MYTHIC, mage.cards.k.KomaCosmosSerpent.class)); cards.add(new SetCardInfo("Komodo Rhino", 241, Rarity.COMMON, mage.cards.k.KomodoRhino.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Komodo Rhino", 283, Rarity.COMMON, mage.cards.k.KomodoRhino.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 4742d414ebcfcab7481d27c3607d3418f2fb8ffc Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:02:17 -0500 Subject: [PATCH 205/261] [TLE] Implement Longshot, Rebel Bowman --- .../src/mage/cards/l/LongshotRebelBowman.java | 63 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 64 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LongshotRebelBowman.java diff --git a/Mage.Sets/src/mage/cards/l/LongshotRebelBowman.java b/Mage.Sets/src/mage/cards/l/LongshotRebelBowman.java new file mode 100644 index 00000000000..e5501216631 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LongshotRebelBowman.java @@ -0,0 +1,63 @@ +package mage.cards.l; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.predicate.Predicates; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class LongshotRebelBowman extends CardImpl { + + private static final FilterCard filter = new FilterCard("noncreature spells"); + + static { + filter.add(Predicates.not(CardType.CREATURE.getPredicate())); + } + + public LongshotRebelBowman(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.REBEL); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // Noncreature spells you cast cost {1} less to cast. + this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1))); + + // Whenever you cast a noncreature spell, Longshot deals 2 damage to each opponent. + this.addAbility(new SpellCastControllerTriggeredAbility( + new DamagePlayersEffect(2, TargetController.OPPONENT), + StaticFilters.FILTER_SPELL_A_NON_CREATURE, false + )); + } + + private LongshotRebelBowman(final LongshotRebelBowman card) { + super(card); + } + + @Override + public LongshotRebelBowman copy() { + return new LongshotRebelBowman(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 40996db3e40..b48b8421746 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -157,6 +157,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Lightning Bolt", 32, Rarity.MYTHIC, mage.cards.l.LightningBolt.class)); cards.add(new SetCardInfo("Lion Vulture", 232, Rarity.RARE, mage.cards.l.LionVulture.class)); cards.add(new SetCardInfo("Lita, Mechanical Engineer", 4, Rarity.MYTHIC, mage.cards.l.LitaMechanicalEngineer.class)); + cards.add(new SetCardInfo("Longshot, Rebel Bowman", 120, Rarity.UNCOMMON, mage.cards.l.LongshotRebelBowman.class)); cards.add(new SetCardInfo("Lost in the Spirit World", 224, Rarity.UNCOMMON, mage.cards.l.LostInTheSpiritWorld.class)); cards.add(new SetCardInfo("Loyal Fire Sage", 242, Rarity.UNCOMMON, mage.cards.l.LoyalFireSage.class)); cards.add(new SetCardInfo("Many Partings", 169, Rarity.COMMON, mage.cards.m.ManyPartings.class)); -- 2.47.2 From 81592ac7109044f7d85064d0269da99b7da90378 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:04:12 -0500 Subject: [PATCH 206/261] [TLE] Implement Mai and Zuko --- Mage.Sets/src/mage/cards/m/MaiAndZuko.java | 57 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 58 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MaiAndZuko.java diff --git a/Mage.Sets/src/mage/cards/m/MaiAndZuko.java b/Mage.Sets/src/mage/cards/m/MaiAndZuko.java new file mode 100644 index 00000000000..d25a07f936c --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MaiAndZuko.java @@ -0,0 +1,57 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.CastAsThoughItHadFlashAllEffect; +import mage.abilities.keyword.FirebendingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MaiAndZuko extends CardImpl { + + private static final FilterCard filter = new FilterCard("Ally spells and artifact spells"); + + static { + filter.add(Predicates.or( + SubType.ALLY.getPredicate(), + CardType.ARTIFACT.getPredicate() + )); + } + + public MaiAndZuko(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(5); + + // Firebending 3 + this.addAbility(new FirebendingAbility(3)); + + // You may cast Ally spells and artifact spells as though they had flash. + this.addAbility(new SimpleStaticAbility(new CastAsThoughItHadFlashAllEffect(Duration.WhileOnBattlefield, filter))); + } + + private MaiAndZuko(final MaiAndZuko card) { + super(card); + } + + @Override + public MaiAndZuko copy() { + return new MaiAndZuko(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index b48b8421746..b7333167b03 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -160,6 +160,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Longshot, Rebel Bowman", 120, Rarity.UNCOMMON, mage.cards.l.LongshotRebelBowman.class)); cards.add(new SetCardInfo("Lost in the Spirit World", 224, Rarity.UNCOMMON, mage.cards.l.LostInTheSpiritWorld.class)); cards.add(new SetCardInfo("Loyal Fire Sage", 242, Rarity.UNCOMMON, mage.cards.l.LoyalFireSage.class)); + cards.add(new SetCardInfo("Mai and Zuko", 68, Rarity.RARE, mage.cards.m.MaiAndZuko.class)); cards.add(new SetCardInfo("Many Partings", 169, Rarity.COMMON, mage.cards.m.ManyPartings.class)); cards.add(new SetCardInfo("Match the Odds", 253, Rarity.UNCOMMON, mage.cards.m.MatchTheOdds.class)); cards.add(new SetCardInfo("Mechanical Glider", 256, Rarity.COMMON, mage.cards.m.MechanicalGlider.class)); -- 2.47.2 From 04bd66b638789e46aff53b938038717e08692fab Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:09:27 -0500 Subject: [PATCH 207/261] [TLE] Implement Moku, Meandering Drummer --- .../mage/cards/m/MokuMeanderingDrummer.java | 53 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 54 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MokuMeanderingDrummer.java diff --git a/Mage.Sets/src/mage/cards/m/MokuMeanderingDrummer.java b/Mage.Sets/src/mage/cards/m/MokuMeanderingDrummer.java new file mode 100644 index 00000000000..df3a746648d --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MokuMeanderingDrummer.java @@ -0,0 +1,53 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MokuMeanderingDrummer extends CardImpl { + + public MokuMeanderingDrummer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.BARD); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever you cast a noncreature spell, you may pay {1}. If you do, Moku gets +2/+1 and creatures you control gain haste until end of turn. + this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid( + new BoostSourceEffect(2, 1, Duration.EndOfTurn) + .setText("{this} gets +2/+1"), new GenericManaCost(1) + ).addEffect(new GainAbilityAllEffect( + HasteAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_CONTROLLED_CREATURES + ).concatBy("and")), StaticFilters.FILTER_SPELL_A_NON_CREATURE, false)); + } + + private MokuMeanderingDrummer(final MokuMeanderingDrummer card) { + super(card); + } + + @Override + public MokuMeanderingDrummer copy() { + return new MokuMeanderingDrummer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index b7333167b03..58117e13696 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -166,6 +166,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Mechanical Glider", 256, Rarity.COMMON, mage.cards.m.MechanicalGlider.class)); cards.add(new SetCardInfo("Meteorite", 54, Rarity.MYTHIC, mage.cards.m.Meteorite.class)); cards.add(new SetCardInfo("Mirrorwing Dragon", 33, Rarity.MYTHIC, mage.cards.m.MirrorwingDragon.class)); + cards.add(new SetCardInfo("Moku, Meandering Drummer", 122, Rarity.UNCOMMON, mage.cards.m.MokuMeanderingDrummer.class)); cards.add(new SetCardInfo("Momo, Rambunctious Rascal", 217, Rarity.UNCOMMON, mage.cards.m.MomoRambunctiousRascal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Momo, Rambunctious Rascal", 270, Rarity.UNCOMMON, mage.cards.m.MomoRambunctiousRascal.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mountain", 289, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From b412b9dd9ab6baef4d1b4f08fb1af5b788d1cf2d Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:15:55 -0500 Subject: [PATCH 208/261] [TLE] Implement Overwhelming Victory --- .../src/mage/cards/o/OverwhelmingVictory.java | 79 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 2 + 2 files changed, 81 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/o/OverwhelmingVictory.java diff --git a/Mage.Sets/src/mage/cards/o/OverwhelmingVictory.java b/Mage.Sets/src/mage/cards/o/OverwhelmingVictory.java new file mode 100644 index 00000000000..7b939370502 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OverwhelmingVictory.java @@ -0,0 +1,79 @@ +package mage.cards.o; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.target.common.TargetCreaturePermanent; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class OverwhelmingVictory extends CardImpl { + + public OverwhelmingVictory(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}"); + + this.subtype.add(SubType.LESSON); + + // Overwhelming Victory deals 5 damage to target creature. Each creature you control gains trample and gets +X/+0 until end of turn, where X is the amount of excess damage dealt this way. + this.getSpellAbility().addEffect(new OverwhelmingVictoryEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private OverwhelmingVictory(final OverwhelmingVictory card) { + super(card); + } + + @Override + public OverwhelmingVictory copy() { + return new OverwhelmingVictory(this); + } +} + +class OverwhelmingVictoryEffect extends OneShotEffect { + + OverwhelmingVictoryEffect() { + super(Outcome.Benefit); + staticText = "{this} deals 5 damage to target creature. Each creature you control gains trample " + + "and gets +X/+0 until end of turn, where X is the amount of excess damage dealt this way"; + } + + private OverwhelmingVictoryEffect(final OverwhelmingVictoryEffect effect) { + super(effect); + } + + @Override + public OverwhelmingVictoryEffect copy() { + return new OverwhelmingVictoryEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int excess = Optional + .ofNullable(getTargetPointer().getFirst(game, source)) + .map(game::getPermanent) + .map(permanent -> permanent.damageWithExcess(5, source, game)) + .orElse(0); + game.addEffect(new GainAbilityAllEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_CONTROLLED_CREATURE + ), source); + if (excess > 0) { + game.addEffect(new BoostControlledEffect(excess, 0, Duration.EndOfTurn), source); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 58117e13696..e0eeaceacbd 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -181,6 +181,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Mystical Tutor", 308, Rarity.RARE, mage.cards.m.MysticalTutor.class)); cards.add(new SetCardInfo("Noxious Gearhulk", 25, Rarity.MYTHIC, mage.cards.n.NoxiousGearhulk.class)); cards.add(new SetCardInfo("Obscuring Haze", 313, Rarity.RARE, mage.cards.o.ObscuringHaze.class)); + cards.add(new SetCardInfo("Overwhelming Victory", 123, Rarity.RARE, mage.cards.o.OverwhelmingVictory.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Overwhelming Victory", 196, Rarity.RARE, mage.cards.o.OverwhelmingVictory.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Path to Redemption", 271, Rarity.COMMON, mage.cards.p.PathToRedemption.class)); cards.add(new SetCardInfo("Plains", 297, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 298, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 58206f24d52093837b6d3a682fafad886f526611 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:17:57 -0500 Subject: [PATCH 209/261] [TLE] Implement Pipsqueak, Rebel Strongarm --- .../mage/cards/p/PipsqueakRebelStrongarm.java | 51 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 52 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/PipsqueakRebelStrongarm.java diff --git a/Mage.Sets/src/mage/cards/p/PipsqueakRebelStrongarm.java b/Mage.Sets/src/mage/cards/p/PipsqueakRebelStrongarm.java new file mode 100644 index 00000000000..7280cbee6ae --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PipsqueakRebelStrongarm.java @@ -0,0 +1,51 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.decorator.ConditionalRestrictionEffect; +import mage.abilities.effects.common.combat.CantAttackAloneSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PipsqueakRebelStrongarm extends CardImpl { + + private static final Condition condition = new SourceHasCounterCondition(CounterType.P1P1, ComparisonType.EQUAL_TO, 0); + + public PipsqueakRebelStrongarm(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.REBEL); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Pipsqueak can't attack alone unless he has a +1/+1 counter on him. + this.addAbility(new SimpleStaticAbility(new ConditionalRestrictionEffect( + new CantAttackAloneSourceEffect(), condition, + "{this} can't attack alone unless he has a +1/+1 counter on him" + ))); + } + + private PipsqueakRebelStrongarm(final PipsqueakRebelStrongarm card) { + super(card); + } + + @Override + public PipsqueakRebelStrongarm copy() { + return new PipsqueakRebelStrongarm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index e0eeaceacbd..d37ae04959e 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -184,6 +184,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Overwhelming Victory", 123, Rarity.RARE, mage.cards.o.OverwhelmingVictory.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Overwhelming Victory", 196, Rarity.RARE, mage.cards.o.OverwhelmingVictory.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Path to Redemption", 271, Rarity.COMMON, mage.cards.p.PathToRedemption.class)); + cards.add(new SetCardInfo("Pipsqueak, Rebel Strongarm", 82, Rarity.UNCOMMON, mage.cards.p.PipsqueakRebelStrongarm.class)); cards.add(new SetCardInfo("Plains", 297, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 298, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 299, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 6cd0c9d5006f814fd5f782bc5e7a8c9c40c51a63 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:21:04 -0500 Subject: [PATCH 210/261] [TLE] Implement Ruthless Waterbender --- .../src/mage/cards/r/RuthlessWaterbender.java | 45 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 46 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/r/RuthlessWaterbender.java diff --git a/Mage.Sets/src/mage/cards/r/RuthlessWaterbender.java b/Mage.Sets/src/mage/cards/r/RuthlessWaterbender.java new file mode 100644 index 00000000000..261f0d79329 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RuthlessWaterbender.java @@ -0,0 +1,45 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.common.WaterbendCost; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RuthlessWaterbender extends CardImpl { + + public RuthlessWaterbender(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Waterbend {2}: This creature gets +1/+1 until end of turn. Activate only during your turn. + this.addAbility(new ActivateIfConditionActivatedAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), + new WaterbendCost(2), MyTurnCondition.instance + )); + } + + private RuthlessWaterbender(final RuthlessWaterbender card) { + super(card); + } + + @Override + public RuthlessWaterbender copy() { + return new RuthlessWaterbender(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index d37ae04959e..968b34d3ca9 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -204,6 +204,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Roku's Mastery", 243, Rarity.UNCOMMON, mage.cards.r.RokusMastery.class)); cards.add(new SetCardInfo("Run Amok", 258, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Run Amok", 284, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ruthless Waterbender", 110, Rarity.UNCOMMON, mage.cards.r.RuthlessWaterbender.class)); cards.add(new SetCardInfo("Sakashima of a Thousand Faces", 18, Rarity.MYTHIC, mage.cards.s.SakashimaOfAThousandFaces.class)); cards.add(new SetCardInfo("Scout's Warning", 6, Rarity.MYTHIC, mage.cards.s.ScoutsWarning.class)); cards.add(new SetCardInfo("Searing Blood", 35, Rarity.MYTHIC, mage.cards.s.SearingBlood.class)); -- 2.47.2 From 4c3a48b5f95647267129678114ca49ef37ad0997 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:24:30 -0500 Subject: [PATCH 211/261] [TLE] Implement Smellerbee, Rebel Fighter --- .../mage/cards/s/SmellerbeeRebelFighter.java | 69 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 2 + 2 files changed, 71 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SmellerbeeRebelFighter.java diff --git a/Mage.Sets/src/mage/cards/s/SmellerbeeRebelFighter.java b/Mage.Sets/src/mage/cards/s/SmellerbeeRebelFighter.java new file mode 100644 index 00000000000..8902fc9366c --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SmellerbeeRebelFighter.java @@ -0,0 +1,69 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.DiscardHandCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.AttackingCreatureCount; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SmellerbeeRebelFighter extends CardImpl { + + private static final DynamicValue xValue = new AttackingCreatureCount(); + private static final Hint hint = new ValueHint("Attacking creatures", xValue); + + public SmellerbeeRebelFighter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.REBEL); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // Other creatures you control have haste. + this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( + HasteAbility.getInstance(), Duration.WhileOnBattlefield, + StaticFilters.FILTER_PERMANENT_CREATURES, true + ))); + + // Whenever Smellerbee attacks, you may discard your hand. If you do, draw cards equal to the number of attacking creatures. + this.addAbility(new AttacksTriggeredAbility(new DoIfCostPaid( + new DrawCardSourceControllerEffect(xValue) + .setText("draw cards equal to the number of attacking creatures"), + new DiscardHandCost() + )).addHint(hint)); + } + + private SmellerbeeRebelFighter(final SmellerbeeRebelFighter card) { + super(card); + } + + @Override + public SmellerbeeRebelFighter copy() { + return new SmellerbeeRebelFighter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 968b34d3ca9..68a9ecfbfff 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -212,6 +212,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Shattering Spree", 36, Rarity.MYTHIC, mage.cards.s.ShatteringSpree.class)); cards.add(new SetCardInfo("Sledding Otter-Penguin", 218, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sledding Otter-Penguin", 273, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Smellerbee, Rebel Fighter", 125, Rarity.RARE, mage.cards.s.SmellerbeeRebelFighter.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Smellerbee, Rebel Fighter", 198, Rarity.RARE, mage.cards.s.SmellerbeeRebelFighter.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka's Sword Training", 84, Rarity.COMMON, mage.cards.s.SokkasSwordTraining.class)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 219, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 274, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 654a29cba995daa37152ded4f1fedde4a86f67a0 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:28:55 -0500 Subject: [PATCH 212/261] [TLE] Implement Sokka's Charge --- Mage.Sets/src/mage/cards/s/SokkasCharge.java | 50 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 51 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SokkasCharge.java diff --git a/Mage.Sets/src/mage/cards/s/SokkasCharge.java b/Mage.Sets/src/mage/cards/s/SokkasCharge.java new file mode 100644 index 00000000000..578d94dfb93 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SokkasCharge.java @@ -0,0 +1,50 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SokkasCharge extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.ALLY); + + public SokkasCharge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); + + // During your turn, Allies you control have double strike and lifelink. + Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( + new GainAbilityAllEffect(DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, filter), + MyTurnCondition.instance, "during your turn, Allies you control have double strike" + )); + ability.addEffect(new ConditionalContinuousEffect( + new GainAbilityAllEffect(LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, filter), + MyTurnCondition.instance, "and lifelink" + )); + this.addAbility(ability); + } + + private SokkasCharge(final SokkasCharge card) { + super(card); + } + + @Override + public SokkasCharge copy() { + return new SokkasCharge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 68a9ecfbfff..a2a7ad8225c 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -214,6 +214,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Sledding Otter-Penguin", 273, Rarity.COMMON, mage.cards.s.SleddingOtterPenguin.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Smellerbee, Rebel Fighter", 125, Rarity.RARE, mage.cards.s.SmellerbeeRebelFighter.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Smellerbee, Rebel Fighter", 198, Rarity.RARE, mage.cards.s.SmellerbeeRebelFighter.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sokka's Charge", 66, Rarity.RARE, mage.cards.s.SokkasCharge.class)); cards.add(new SetCardInfo("Sokka's Sword Training", 84, Rarity.COMMON, mage.cards.s.SokkasSwordTraining.class)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 219, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 274, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 9bdda9c5fd0fae87e1d381224ce03d042cda42dd Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:32:36 -0500 Subject: [PATCH 213/261] [TLE] Implement The Art of Tea --- Mage.Sets/src/mage/cards/t/TheArtOfTea.java | 39 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 40 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TheArtOfTea.java diff --git a/Mage.Sets/src/mage/cards/t/TheArtOfTea.java b/Mage.Sets/src/mage/cards/t/TheArtOfTea.java new file mode 100644 index 00000000000..478b09f941a --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheArtOfTea.java @@ -0,0 +1,39 @@ +package mage.cards.t; + +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.game.permanent.token.FoodToken; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheArtOfTea extends CardImpl { + + public TheArtOfTea(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); + + this.subtype.add(SubType.LESSON); + + // Put a +1/+1 counter on up to one target creature you control. Create a Food token. + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 1)); + this.getSpellAbility().addEffect(new CreateTokenEffect(new FoodToken())); + } + + private TheArtOfTea(final TheArtOfTea card) { + super(card); + } + + @Override + public TheArtOfTea copy() { + return new TheArtOfTea(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index a2a7ad8225c..d84d3eadeca 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -227,6 +227,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Tarnished Citadel", 59, Rarity.MYTHIC, mage.cards.t.TarnishedCitadel.class)); cards.add(new SetCardInfo("Taunting Challenge", 46, Rarity.MYTHIC, mage.cards.t.TauntingChallenge.class)); cards.add(new SetCardInfo("Teferi's Protection", 7, Rarity.MYTHIC, mage.cards.t.TeferisProtection.class)); + cards.add(new SetCardInfo("The Art of Tea", 129, Rarity.COMMON, mage.cards.t.TheArtOfTea.class)); cards.add(new SetCardInfo("The Cabbage Merchant", 134, Rarity.RARE, mage.cards.t.TheCabbageMerchant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Cabbage Merchant", 203, Rarity.RARE, mage.cards.t.TheCabbageMerchant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Great Henge", 41, Rarity.MYTHIC, mage.cards.t.TheGreatHenge.class)); -- 2.47.2 From 47246ee3813598660b9caa46c1390ff0d448e017 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:35:34 -0500 Subject: [PATCH 214/261] [TLE] Implement Tui and La, Moon and Ocean --- .../mage/cards/t/TuiAndLaMoonAndOcean.java | 50 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 2 + 2 files changed, 52 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TuiAndLaMoonAndOcean.java diff --git a/Mage.Sets/src/mage/cards/t/TuiAndLaMoonAndOcean.java b/Mage.Sets/src/mage/cards/t/TuiAndLaMoonAndOcean.java new file mode 100644 index 00000000000..15d8b8d9953 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TuiAndLaMoonAndOcean.java @@ -0,0 +1,50 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.BecomesTappedSourceTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.InspiredAbility; +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 java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TuiAndLaMoonAndOcean extends CardImpl { + + public TuiAndLaMoonAndOcean(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.FISH); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever Tui and La become tapped, draw a card. + this.addAbility(new BecomesTappedSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .setTriggerPhrase("Whenever {this} become tapped, ")); + + // Whenever Tui and La become untapped, put a +1/+1 counter on them. + this.addAbility(new InspiredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()) + .setText("put a +1/+1 counter on them")) + .setTriggerPhrase("Whenever {this} become untapped, ") + .setAbilityWord(null)); + } + + private TuiAndLaMoonAndOcean(final TuiAndLaMoonAndOcean card) { + super(card); + } + + @Override + public TuiAndLaMoonAndOcean copy() { + return new TuiAndLaMoonAndOcean(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index d84d3eadeca..7332ec60dfb 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -243,6 +243,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Toucan-Puffin", 88, Rarity.COMMON, mage.cards.t.ToucanPuffin.class)); cards.add(new SetCardInfo("Training Grounds", 20, Rarity.MYTHIC, mage.cards.t.TrainingGrounds.class)); cards.add(new SetCardInfo("Treetop Village", 60, Rarity.MYTHIC, mage.cards.t.TreetopVillage.class)); + cards.add(new SetCardInfo("Tui and La, Moon and Ocean", 181, Rarity.RARE, mage.cards.t.TuiAndLaMoonAndOcean.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Tui and La, Moon and Ocean", 96, Rarity.RARE, mage.cards.t.TuiAndLaMoonAndOcean.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tundra Wall", 220, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tundra Wall", 275, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Turtle-Seals", 226, Rarity.COMMON, mage.cards.t.TurtleSeals.class)); -- 2.47.2 From 32d9c6887c5917dc668e5489acc2d1118f03ae56 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:38:06 -0500 Subject: [PATCH 215/261] [TLE] Implement Unagi's Spray --- Mage.Sets/src/mage/cards/u/UnagisSpray.java | 63 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 64 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/u/UnagisSpray.java diff --git a/Mage.Sets/src/mage/cards/u/UnagisSpray.java b/Mage.Sets/src/mage/cards/u/UnagisSpray.java new file mode 100644 index 00000000000..3cb20b02a75 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UnagisSpray.java @@ -0,0 +1,63 @@ +package mage.cards.u; + +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UnagisSpray extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent(); + + static { + filter.add(Predicates.or( + SubType.FISH.getPredicate(), + SubType.OCTOPUS.getPredicate(), + SubType.OTTER.getPredicate(), + SubType.SEAL.getPredicate(), + SubType.SERPENT.getPredicate(), + SubType.WHALE.getPredicate() + )); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + private static final Hint hint = new ConditionHint(condition, "You control a Fish, Octopus, Otter, Seal, Serpent, or Whale"); + + public UnagisSpray(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); + + // Target creature gets -4/-0 until end of turn. If you control a Fish, Octopus, Otter, Seal, Serpent, or Whale, draw a card. + this.getSpellAbility().addEffect(new BoostTargetEffect(-4, 0)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(1), condition, + "If you control a Fish, Octopus, Otter, Seal, Serpent, or Whale, draw a card" + )); + this.getSpellAbility().addHint(hint); + } + + private UnagisSpray(final UnagisSpray card) { + super(card); + } + + @Override + public UnagisSpray copy() { + return new UnagisSpray(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 7332ec60dfb..7d5acc13f54 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -248,6 +248,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Tundra Wall", 220, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tundra Wall", 275, Rarity.COMMON, mage.cards.t.TundraWall.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Turtle-Seals", 226, Rarity.COMMON, mage.cards.t.TurtleSeals.class)); + cards.add(new SetCardInfo("Unagi's Spray", 97, Rarity.COMMON, mage.cards.u.UnagisSpray.class)); cards.add(new SetCardInfo("Valakut, the Molten Pinnacle", 61, Rarity.MYTHIC, mage.cards.v.ValakutTheMoltenPinnacle.class)); cards.add(new SetCardInfo("Valorous Stance", 154, Rarity.UNCOMMON, mage.cards.v.ValorousStance.class)); cards.add(new SetCardInfo("Visions of Beyond", 21, Rarity.MYTHIC, mage.cards.v.VisionsOfBeyond.class)); -- 2.47.2 From 9057461c291ad8133834232e803b1ff3ff182f7c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:40:22 -0500 Subject: [PATCH 216/261] [TLE] Implement Whirlwind Technique --- .../src/mage/cards/w/WhirlwindTechnique.java | 44 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 45 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/w/WhirlwindTechnique.java diff --git a/Mage.Sets/src/mage/cards/w/WhirlwindTechnique.java b/Mage.Sets/src/mage/cards/w/WhirlwindTechnique.java new file mode 100644 index 00000000000..de87e822f74 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WhirlwindTechnique.java @@ -0,0 +1,44 @@ +package mage.cards.w; + +import mage.abilities.effects.common.DrawDiscardTargetEffect; +import mage.abilities.effects.keyword.AirbendTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.TargetPlayer; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WhirlwindTechnique extends CardImpl { + + public WhirlwindTechnique(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{U}{U}"); + + this.subtype.add(SubType.LESSON); + + // Target player draws two cards, then discards a card. + this.getSpellAbility().addEffect(new DrawDiscardTargetEffect(2, 1)); + this.getSpellAbility().addTarget(new TargetPlayer()); + + // Airbend up to two target creatures. + this.getSpellAbility().addEffect(new AirbendTargetEffect() + .setText("
Airbend up to two target creatures") + .setTargetPointer(new SecondTargetPointer())); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2)); + } + + private WhirlwindTechnique(final WhirlwindTechnique card) { + super(card); + } + + @Override + public WhirlwindTechnique copy() { + return new WhirlwindTechnique(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 7d5acc13f54..0948eade0b1 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -257,6 +257,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Warship Scout", 285, Rarity.COMMON, mage.cards.w.WarshipScout.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Warstorm Surge", 38, Rarity.MYTHIC, mage.cards.w.WarstormSurge.class)); cards.add(new SetCardInfo("Water Whip", 227, Rarity.RARE, mage.cards.w.WaterWhip.class)); + cards.add(new SetCardInfo("Whirlwind Technique", 100, Rarity.UNCOMMON, mage.cards.w.WhirlwindTechnique.class)); cards.add(new SetCardInfo("Wolf Cove Villager", 221, Rarity.COMMON, mage.cards.w.WolfCoveVillager.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Wolf Cove Villager", 276, Rarity.COMMON, mage.cards.w.WolfCoveVillager.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Worldly Tutor", 314, Rarity.RARE, mage.cards.w.WorldlyTutor.class)); -- 2.47.2 From c9af0467b9134489e28a21589635342f25a99440 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:41:47 -0500 Subject: [PATCH 217/261] [TLE] Implement Zuko, Seeking Honor --- .../src/mage/cards/z/ZukoSeekingHonor.java | 58 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 59 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/z/ZukoSeekingHonor.java diff --git a/Mage.Sets/src/mage/cards/z/ZukoSeekingHonor.java b/Mage.Sets/src/mage/cards/z/ZukoSeekingHonor.java new file mode 100644 index 00000000000..dd0899f43d6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/z/ZukoSeekingHonor.java @@ -0,0 +1,58 @@ +package mage.cards.z; + +import mage.MageInt; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.FirebendingAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ZukoSeekingHonor extends CardImpl { + + public ZukoSeekingHonor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B/R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Firebending 1 + this.addAbility(new FirebendingAbility(1)); + + // Whenever you cast a noncreature spell, Zuko gains first strike until end of turn. + this.addAbility(new SpellCastControllerTriggeredAbility( + new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), + StaticFilters.FILTER_SPELL_A_NON_CREATURE, false + )); + + // Whenever Zuko deals combat damage to a player, put a +1/+1 counter on him. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)).setText("put a +1/+1 counter on him") + )); + } + + private ZukoSeekingHonor(final ZukoSeekingHonor card) { + super(card); + } + + @Override + public ZukoSeekingHonor copy() { + return new ZukoSeekingHonor(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 0948eade0b1..7858f70fd5e 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -269,6 +269,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Zuko, Avatar Hunter", 287, Rarity.RARE, mage.cards.z.ZukoAvatarHunter.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Zuko, Firebending Master", 127, Rarity.MYTHIC, mage.cards.z.ZukoFirebendingMaster.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Zuko, Firebending Master", 200, Rarity.MYTHIC, mage.cards.z.ZukoFirebendingMaster.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Zuko, Seeking Honor", 150, Rarity.UNCOMMON, mage.cards.z.ZukoSeekingHonor.class)); cards.removeIf(setCardInfo -> unfinished.contains(setCardInfo.getName())); } -- 2.47.2 From 697a91489264d3f02ef317c7962343febb4e808c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:45:23 -0500 Subject: [PATCH 218/261] [TLE] Implement Scarring Memories --- .../src/mage/cards/s/ScarringMemories.java | 62 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 63 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/ScarringMemories.java diff --git a/Mage.Sets/src/mage/cards/s/ScarringMemories.java b/Mage.Sets/src/mage/cards/s/ScarringMemories.java new file mode 100644 index 00000000000..1c6058d0283 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScarringMemories.java @@ -0,0 +1,62 @@ +package mage.cards.s; + +import mage.abilities.common.CastAsThoughItHadFlashIfConditionAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.effects.common.SacrificeEffect; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +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.StaticFilters; +import mage.filter.common.FilterAttackingCreature; +import mage.target.common.TargetOpponent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ScarringMemories extends CardImpl { + + private static final FilterPermanent filter = new FilterAttackingCreature("you control an attacking legendary creature"); + + static { + filter.add(SuperType.LEGENDARY.getPredicate()); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + private static final Hint hint = new ConditionHint(condition); + + public ScarringMemories(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}"); + + this.subtype.add(SubType.LESSON); + + // You may cast this spell as though it had flash if you control an attacking legendary creature. + this.addAbility(new CastAsThoughItHadFlashIfConditionAbility( + condition, "you may cast this spell as though it had flash if you control an attacking legendary creature" + )); + + // Target opponent sacrifices a creature of their choice, discards a card, and loses 3 life. + this.getSpellAbility().addEffect(new SacrificeEffect(StaticFilters.FILTER_PERMANENT_CREATURE, 1, "target opponent")); + this.getSpellAbility().addEffect(new DiscardTargetEffect(1).setText(", discards a card")); + this.getSpellAbility().addEffect(new LoseLifeTargetEffect(3).setText(", and loses 3 life")); + this.getSpellAbility().addTarget(new TargetOpponent()); + } + + private ScarringMemories(final ScarringMemories card) { + super(card); + } + + @Override + public ScarringMemories copy() { + return new ScarringMemories(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 7858f70fd5e..d72fec34998 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -206,6 +206,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Run Amok", 284, Rarity.COMMON, mage.cards.r.RunAmok.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ruthless Waterbender", 110, Rarity.UNCOMMON, mage.cards.r.RuthlessWaterbender.class)); cards.add(new SetCardInfo("Sakashima of a Thousand Faces", 18, Rarity.MYTHIC, mage.cards.s.SakashimaOfAThousandFaces.class)); + cards.add(new SetCardInfo("Scarring Memories", 111, Rarity.UNCOMMON, mage.cards.s.ScarringMemories.class)); cards.add(new SetCardInfo("Scout's Warning", 6, Rarity.MYTHIC, mage.cards.s.ScoutsWarning.class)); cards.add(new SetCardInfo("Searing Blood", 35, Rarity.MYTHIC, mage.cards.s.SearingBlood.class)); cards.add(new SetCardInfo("Seismic Tutelage", 254, Rarity.RARE, mage.cards.s.SeismicTutelage.class)); -- 2.47.2 From 43e7d31cc51778d4f0d5bd7cbc2621df583f85c0 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 12:47:03 -0500 Subject: [PATCH 219/261] [TLE] Implement Solid Ground --- Mage.Sets/src/mage/cards/s/SolidGround.java | 44 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 45 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SolidGround.java diff --git a/Mage.Sets/src/mage/cards/s/SolidGround.java b/Mage.Sets/src/mage/cards/s/SolidGround.java new file mode 100644 index 00000000000..63c9d570457 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SolidGround.java @@ -0,0 +1,44 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.replacement.ModifyCountersAddedEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SolidGround extends CardImpl { + + public SolidGround(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + + // When this enchantment enters, earthbend 3. + Ability ability = new EntersBattlefieldTriggeredAbility(new EarthbendTargetEffect(3)); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability); + + // If one or more +1/+1 counters would be put on a permanent you control, that many plus one +1/+1 counters are put on it instead. + this.addAbility(new SimpleStaticAbility(new ModifyCountersAddedEffect( + StaticFilters.FILTER_CONTROLLED_PERMANENT, CounterType.P1P1 + ))); + } + + private SolidGround(final SolidGround card) { + super(card); + } + + @Override + public SolidGround copy() { + return new SolidGround(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index d72fec34998..2e117ffe1ac 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -220,6 +220,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 219, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sokka, Wolf Cove's Protector", 274, Rarity.UNCOMMON, mage.cards.s.SokkaWolfCovesProtector.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Sol Ring", 316, Rarity.RARE, mage.cards.s.SolRing.class)); + cards.add(new SetCardInfo("Solid Ground", 142, Rarity.UNCOMMON, mage.cards.s.SolidGround.class)); cards.add(new SetCardInfo("Standstill", 19, Rarity.MYTHIC, mage.cards.s.Standstill.class)); cards.add(new SetCardInfo("Sunbaked Canyon", 58, Rarity.MYTHIC, mage.cards.s.SunbakedCanyon.class)); cards.add(new SetCardInfo("Sundial of the Infinite", 55, Rarity.MYTHIC, mage.cards.s.SundialOfTheInfinite.class)); -- 2.47.2 From 0ff60c91c1ff081c0d47bbb7c75a968a7e12a570 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 13:03:50 -0500 Subject: [PATCH 220/261] fix test failure --- Mage.Sets/src/mage/cards/c/ChakraMeditation.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/c/ChakraMeditation.java b/Mage.Sets/src/mage/cards/c/ChakraMeditation.java index b6ff38883ce..1a156405ea6 100644 --- a/Mage.Sets/src/mage/cards/c/ChakraMeditation.java +++ b/Mage.Sets/src/mage/cards/c/ChakraMeditation.java @@ -7,6 +7,7 @@ import mage.abilities.condition.common.LessonsInGraveCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -34,8 +35,9 @@ public final class ChakraMeditation extends CardImpl { StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false ); ability.addEffect(new ConditionalOneShotEffect( - null, LessonsInGraveCondition.THREE, "Then discard a card " + - "unless there are three or more Lesson cards in your graveyard")); + null, new DiscardControllerEffect(1), LessonsInGraveCondition.THREE, + "Then discard a card unless there are three or more Lesson cards in your graveyard" + )); this.addAbility(ability); } -- 2.47.2 From 6fc4a5fbbac99ee4d4e4c2a39f0a5d6a2681ed56 Mon Sep 17 00:00:00 2001 From: ReSech Date: Wed, 12 Nov 2025 10:07:57 +1100 Subject: [PATCH 221/261] Add TLA and TLE Tokens (#14083) * Add copy tokens * TLE Tokens * Add TLA Tokens --- .../sources/ScryfallImageSupportTokens.java | 25 +++++++++++++++++++ .../cards/repository/TokenRepository.java | 2 ++ Mage/src/main/resources/tokens-database.txt | 25 +++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java index ef998d93ca8..a70aa38e89b 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java @@ -2831,6 +2831,31 @@ public class ScryfallImageSupportTokens { put("SPM/Spider", "https://api.scryfall.com/cards/tspm/3?format=image"); put("SPM/Treasure", "https://api.scryfall.com/cards/tspm/7?format=image"); + // TLA + put("TLA/Ally/1", "https://api.scryfall.com/cards/ttla/4/?format=image"); + put("TLA/Ally/2", "https://api.scryfall.com/cards/ttla/5/?format=image"); + put("TLA/Ally/3", "https://api.scryfall.com/cards/ttla/6/?format=image"); + put("TLA/Ally/4", "https://api.scryfall.com/cards/ttla/7/?format=image"); + put("TLA/Ally/5", "https://api.scryfall.com/cards/ttla/8/?format=image"); + put("TLA/Ballistic Boulder", "https://api.scryfall.com/cards/ttla/13/?format=image"); + put("TLA/Bear", "https://api.scryfall.com/cards/ttla/12/?format=image"); + put("TLA/Clue/1", "https://api.scryfall.com/cards/ttla/14/?format=image"); + put("TLA/Clue/2", "https://api.scryfall.com/cards/ttla/15/?format=image"); + put("TLA/Clue/3", "https://api.scryfall.com/cards/ttla/16/?format=image"); + put("TLA/Clue/4", "https://api.scryfall.com/cards/ttla/17/?format=image"); + put("TLA/Clue/5", "https://api.scryfall.com/cards/ttla/18/?format=image"); + put("TLA/Food/1", "https://api.scryfall.com/cards/ttla/19/?format=image"); + put("TLA/Food/2", "https://api.scryfall.com/cards/ttla/20/?format=image"); + put("TLA/Food/3", "https://api.scryfall.com/cards/ttla/21/?format=image"); + put("TLA/Monk", "https://api.scryfall.com/cards/ttla/10/?format=image"); + put("TLA/Soldier", "https://api.scryfall.com/cards/ttla/11/?format=image"); + put("TLA/Spirit", "https://api.scryfall.com/cards/ttla/3/?format=image"); + put("TLA/Treasure", "https://api.scryfall.com/cards/ttla/22?format=image"); + + // TLE + put("TLE/Marit Lage", "https://api.scryfall.com/cards/ttle/1/?format=image"); + put("TLE/Soldier", "https://api.scryfall.com/cards/ttle/2?format=image"); + // TMT put("TMT/Mutagen", "https://api.scryfall.com/cards/ttmt/9?format=image"); diff --git a/Mage/src/main/java/mage/cards/repository/TokenRepository.java b/Mage/src/main/java/mage/cards/repository/TokenRepository.java index 819e2b20335..b2ddaef9cf1 100644 --- a/Mage/src/main/java/mage/cards/repository/TokenRepository.java +++ b/Mage/src/main/java/mage/cards/repository/TokenRepository.java @@ -272,6 +272,8 @@ public enum TokenRepository { res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 12, "https://api.scryfall.com/cards/tpip/1/en?format=image")); res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 13, "https://api.scryfall.com/cards/teoc/1/en?format=image")); res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 14, "https://api.scryfall.com/cards/tspm/1/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 15, "https://api.scryfall.com/cards/ttla/1/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 16, "https://api.scryfall.com/cards/ttla/2/en?format=image")); // City's Blessing // https://scryfall.com/search?q=type%3Atoken+include%3Aextras+unique%3Aprints+City%27s+Blessing+&unique=cards&as=grid&order=name diff --git a/Mage/src/main/resources/tokens-database.txt b/Mage/src/main/resources/tokens-database.txt index 5427226ba30..ce8aa97b8f8 100644 --- a/Mage/src/main/resources/tokens-database.txt +++ b/Mage/src/main/resources/tokens-database.txt @@ -2884,6 +2884,31 @@ |Generate|TOK:SPM|Spider|||Spider21Token| |Generate|TOK:SPM|Treasure|||TreasureToken| +#TLA +|Generate|TOK:TLA|Ally|1||AllyToken| +|Generate|TOK:TLA|Ally|2||AllyToken| +|Generate|TOK:TLA|Ally|3||AllyToken| +|Generate|TOK:TLA|Ally|4||AllyToken| +|Generate|TOK:TLA|Ally|5||AllyToken| +|Generate|TOK:TLA|Ballistic Boulder|||BallisticBoulder| +|Generate|TOK:TLA|Bear|||BearsCompanionBearToken| +|Generate|TOK:TLA|Clue|1||ClueArtifactToken| +|Generate|TOK:TLA|Clue|2||ClueArtifactToken| +|Generate|TOK:TLA|Clue|3||ClueArtifactToken| +|Generate|TOK:TLA|Clue|4||ClueArtifactToken| +|Generate|TOK:TLA|Clue|5||ClueArtifactToken| +|Generate|TOK:TLA|Food|1||FoodToken| +|Generate|TOK:TLA|Food|2||FoodToken| +|Generate|TOK:TLA|Food|3||FoodToken| +|Generate|TOK:TLA|Monk|||MonkRedToken| +|Generate|TOK:TLA|Soldier|||SoldierFirebendingToken| +|Generate|TOK:TLA|Spirit|||SpiritWorldToken| +|Generate|TOK:TLA|Treasure|||TreasureToken| + +#TLE +|Generate|TOK:TLE|Marit Lage|||MaritLageToken| +|Generate|TOK:TLE|Soldier|||SoldierRedToken| + #TMT |Generate|TOK:TMT|Mutagen|||MutagenToken| -- 2.47.2 From 522e54e2158ee8bfe2c6939ee49f82613a303da4 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 13:50:15 -0500 Subject: [PATCH 222/261] [TLA] Implement Accumulate Wisdom --- .../src/mage/cards/a/AccumulateWisdom.java | 43 +++++++++++++++++++ .../src/mage/cards/c/ChakraMeditation.java | 2 +- .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/a/AccumulateWisdom.java diff --git a/Mage.Sets/src/mage/cards/a/AccumulateWisdom.java b/Mage.Sets/src/mage/cards/a/AccumulateWisdom.java new file mode 100644 index 00000000000..d0e1e859fcb --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AccumulateWisdom.java @@ -0,0 +1,43 @@ +package mage.cards.a; + +import mage.abilities.condition.common.LessonsInGraveCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.PutCards; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AccumulateWisdom extends CardImpl { + + public AccumulateWisdom(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); + + this.subtype.add(SubType.LESSON); + + // Look at the top three cards of your library. Put one of those cards into your hand and the rest on the bottom of your library in any order. Put each of those cards into your hand instead if there are three or more Lesson cards in your graveyard. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new LookLibraryAndPickControllerEffect(3, 3, PutCards.HAND, PutCards.BOTTOM_ANY), + new LookLibraryAndPickControllerEffect(3, 1, PutCards.HAND, PutCards.BOTTOM_ANY), + LessonsInGraveCondition.THREE, "look at the top three cards of your library. " + + "Put one of those cards into your hand and the rest on the bottom of your library in any order. " + + "Put each of those cards into your hand instead if there are three or more Lesson cards in your graveyard" + )); + this.getSpellAbility().addHint(LessonsInGraveCondition.getHint()); + } + + private AccumulateWisdom(final AccumulateWisdom card) { + super(card); + } + + @Override + public AccumulateWisdom copy() { + return new AccumulateWisdom(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ChakraMeditation.java b/Mage.Sets/src/mage/cards/c/ChakraMeditation.java index 1a156405ea6..e6aaca2b37d 100644 --- a/Mage.Sets/src/mage/cards/c/ChakraMeditation.java +++ b/Mage.Sets/src/mage/cards/c/ChakraMeditation.java @@ -38,7 +38,7 @@ public final class ChakraMeditation extends CardImpl { null, new DiscardControllerEffect(1), LessonsInGraveCondition.THREE, "Then discard a card unless there are three or more Lesson cards in your graveyard" )); - this.addAbility(ability); + this.addAbility(ability.addHint(LessonsInGraveCondition.getHint())); } private ChakraMeditation(final ChakraMeditation card) { diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 702862826a6..3518491c94a 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -35,6 +35,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Abandon Attachments", 205, Rarity.COMMON, mage.cards.a.AbandonAttachments.class)); cards.add(new SetCardInfo("Abandoned Air Temple", 263, Rarity.RARE, mage.cards.a.AbandonedAirTemple.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Abandoned Air Temple", 386, Rarity.RARE, mage.cards.a.AbandonedAirTemple.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Accumulate Wisdom", 44, Rarity.UNCOMMON, mage.cards.a.AccumulateWisdom.class)); cards.add(new SetCardInfo("Agna Qel'a", 264, Rarity.RARE, mage.cards.a.AgnaQela.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Agna Qel'a", 387, Rarity.RARE, mage.cards.a.AgnaQela.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Air Nomad Legacy", 206, Rarity.UNCOMMON, mage.cards.a.AirNomadLegacy.class)); -- 2.47.2 From 4eaf1233c9673b7ea5dc269bc7ca331100bf7610 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 15:50:37 -0500 Subject: [PATCH 223/261] [TLA] Implement Realm of Koh --- Mage.Sets/src/mage/cards/r/RealmOfKoh.java | 47 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 49 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/r/RealmOfKoh.java diff --git a/Mage.Sets/src/mage/cards/r/RealmOfKoh.java b/Mage.Sets/src/mage/cards/r/RealmOfKoh.java new file mode 100644 index 00000000000..f6112e942ec --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RealmOfKoh.java @@ -0,0 +1,47 @@ +package mage.cards.r; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedUnlessAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.YouControlABasicLandCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.game.permanent.token.SpiritWorldToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RealmOfKoh extends CardImpl { + + public RealmOfKoh(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // This land enters tapped unless you control a basic land. + this.addAbility(new EntersBattlefieldTappedUnlessAbility(YouControlABasicLandCondition.instance) + .addHint(YouControlABasicLandCondition.getHint())); + + // {T}: Add {B}. + this.addAbility(new BlackManaAbility()); + + // {3}{B}, {T}: Create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures." + Ability ability = new SimpleActivatedAbility(new CreateTokenEffect(new SpiritWorldToken()), new ManaCostsImpl<>("{3}{B}")); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + private RealmOfKoh(final RealmOfKoh card) { + super(card); + } + + @Override + public RealmOfKoh copy() { + return new RealmOfKoh(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 3518491c94a..896c281f1a4 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -223,6 +223,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Ran and Shaw", 325, Rarity.RARE, mage.cards.r.RanAndShaw.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Raucous Audience", 190, Rarity.COMMON, mage.cards.r.RaucousAudience.class)); cards.add(new SetCardInfo("Razor Rings", 33, Rarity.COMMON, mage.cards.r.RazorRings.class)); + cards.add(new SetCardInfo("Realm of Koh", 276, Rarity.RARE, mage.cards.r.RealmOfKoh.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Realm of Koh", 391, Rarity.RARE, mage.cards.r.RealmOfKoh.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Rebellious Captives", 191, Rarity.COMMON, mage.cards.r.RebelliousCaptives.class)); cards.add(new SetCardInfo("Redirect Lightning", 151, Rarity.RARE, mage.cards.r.RedirectLightning.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Redirect Lightning", 343, Rarity.RARE, mage.cards.r.RedirectLightning.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 019e3ecf1cf82c94e06a0729618946d8c185102a Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 17:20:40 -0500 Subject: [PATCH 224/261] [TLA] Implement Boiling Rock Rioter --- .../src/mage/cards/b/BoilingRockRioter.java | 104 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 106 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BoilingRockRioter.java diff --git a/Mage.Sets/src/mage/cards/b/BoilingRockRioter.java b/Mage.Sets/src/mage/cards/b/BoilingRockRioter.java new file mode 100644 index 00000000000..3c703be49a6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BoilingRockRioter.java @@ -0,0 +1,104 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileTargetForSourceEffect; +import mage.abilities.keyword.FirebendingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; +import mage.util.CardUtil; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BoilingRockRioter extends CardImpl { + + private static final FilterControlledPermanent filter + = new FilterControlledPermanent(SubType.ALLY, "untaped Ally you control"); + + static { + filter.add(TappedPredicate.UNTAPPED); + } + + public BoilingRockRioter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Firebending 1 + this.addAbility(new FirebendingAbility(1)); + + // Tap an untapped Ally you control: Exile target card from a graveyard. + Ability ability = new SimpleActivatedAbility(new ExileTargetForSourceEffect(), new TapTargetCost(filter)); + ability.addTarget(new TargetCardInGraveyard()); + this.addAbility(ability); + + // Whenever this creature attacks, you may cast an Ally spell from among cards you own exiled with this creature. + this.addAbility(new AttacksTriggeredAbility(new BoilingRockRioterEffect())); + } + + private BoilingRockRioter(final BoilingRockRioter card) { + super(card); + } + + @Override + public BoilingRockRioter copy() { + return new BoilingRockRioter(this); + } +} + +class BoilingRockRioterEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard(SubType.ALLY); + + BoilingRockRioterEffect() { + super(Outcome.Benefit); + staticText = "you may cast an Ally spell from among cards you own exiled with this creature"; + } + + private BoilingRockRioterEffect(final BoilingRockRioterEffect effect) { + super(effect); + } + + @Override + public BoilingRockRioterEffect copy() { + return new BoilingRockRioterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Cards cards = Optional + .ofNullable(CardUtil.getExileZoneId(game, source)) + .map(game.getExile()::getExileZone) + .map(CardsImpl::new) + .orElseGet(CardsImpl::new); + cards.removeIf(uuid -> !source.isControlledBy(game.getOwnerId(uuid))); + return CardUtil.castSpellWithAttributesForFree(player, source, game, cards, filter); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 896c281f1a4..9f816c5bd48 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -64,6 +64,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Benevolent River Spirit", 45, Rarity.UNCOMMON, mage.cards.b.BenevolentRiverSpirit.class)); cards.add(new SetCardInfo("Boar-q-pine", 124, Rarity.COMMON, mage.cards.b.BoarQPine.class)); cards.add(new SetCardInfo("Boiling Rock Prison", 267, Rarity.COMMON, mage.cards.b.BoilingRockPrison.class)); + cards.add(new SetCardInfo("Boiling Rock Rioter", 372, Rarity.RARE, mage.cards.b.BoilingRockRioter.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Boiling Rock Rioter", 87, Rarity.RARE, mage.cards.b.BoilingRockRioter.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Boomerang Basics", 46, Rarity.UNCOMMON, mage.cards.b.BoomerangBasics.class)); cards.add(new SetCardInfo("Bumi Bash", 125, Rarity.COMMON, mage.cards.b.BumiBash.class)); cards.add(new SetCardInfo("Bumi, Unleashed", 211, Rarity.MYTHIC, mage.cards.b.BumiUnleashed.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 6cdc989c0480eb6c3934334f24c3d93f666d4730 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 17:24:44 -0500 Subject: [PATCH 225/261] [TLA] Implement Bitter Work --- Mage.Sets/src/mage/cards/b/BitterWork.java | 58 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 59 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BitterWork.java diff --git a/Mage.Sets/src/mage/cards/b/BitterWork.java b/Mage.Sets/src/mage/cards/b/BitterWork.java new file mode 100644 index 00000000000..8b941f867c6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BitterWork.java @@ -0,0 +1,58 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.abilities.keyword.ExhaustAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SetTargetPointer; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BitterWork extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent(); + + static { + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + } + + public BitterWork(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{G}"); + + // Whenever you attack a player with one or more creatures with power 4 or greater, draw a card. + this.addAbility(new AttacksPlayerWithCreaturesTriggeredAbility( + new DrawCardSourceControllerEffect(1), filter, SetTargetPointer.NONE + ).setTriggerPhrase("Whenever you attack a player with one or more creatures with power 4 or greater, ")); + + // Exhaust -- {4}: Earthbend 4. Activate only during your turn. + Ability ability = new ExhaustAbility(new EarthbendTargetEffect(4), new GenericManaCost(4)) + .setCondition(MyTurnCondition.instance); + ability.addTarget(new TargetControlledLandPermanent()); + ability.addEffect(new InfoEffect("Activate only during your turn")); + this.addAbility(ability); + } + + private BitterWork(final BitterWork card) { + super(card); + } + + @Override + public BitterWork copy() { + return new BitterWork(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 9f816c5bd48..062d1028210 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -62,6 +62,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Beetle-Headed Merchants", 86, Rarity.COMMON, mage.cards.b.BeetleHeadedMerchants.class)); cards.add(new SetCardInfo("Bender's Waterskin", 255, Rarity.COMMON, mage.cards.b.BendersWaterskin.class)); cards.add(new SetCardInfo("Benevolent River Spirit", 45, Rarity.UNCOMMON, mage.cards.b.BenevolentRiverSpirit.class)); + cards.add(new SetCardInfo("Bitter Work", 210, Rarity.UNCOMMON, mage.cards.b.BitterWork.class)); cards.add(new SetCardInfo("Boar-q-pine", 124, Rarity.COMMON, mage.cards.b.BoarQPine.class)); cards.add(new SetCardInfo("Boiling Rock Prison", 267, Rarity.COMMON, mage.cards.b.BoilingRockPrison.class)); cards.add(new SetCardInfo("Boiling Rock Rioter", 372, Rarity.RARE, mage.cards.b.BoilingRockRioter.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From d88f7c68d4cb123c54f4e0cbd4755a85eafc7bfb Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 17:29:11 -0500 Subject: [PATCH 226/261] [TLA] Implement Day of Black Sun --- Mage.Sets/src/mage/cards/d/DayOfBlackSun.java | 56 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 58 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/d/DayOfBlackSun.java diff --git a/Mage.Sets/src/mage/cards/d/DayOfBlackSun.java b/Mage.Sets/src/mage/cards/d/DayOfBlackSun.java new file mode 100644 index 00000000000..8cbea998118 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DayOfBlackSun.java @@ -0,0 +1,56 @@ +package mage.cards.d; + +import mage.abilities.dynamicvalue.common.GetXValue; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.abilities.effects.common.continuous.LoseAllAbilitiesAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DayOfBlackSun extends CardImpl { + + private static final FilterPermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(DayOfBlackSunPredicate.instance); + } + + public DayOfBlackSun(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}"); + + // Each creature with mana value X or less loses all abilities until end of turn. Destroy those creatures. + this.getSpellAbility().addEffect(new LoseAllAbilitiesAllEffect(filter, Duration.EndOfTurn) + .setText("each creature with mana value X or less loses all abilities until end of turn")); + this.getSpellAbility().addEffect(new DestroyAllEffect(filter).setText("Destroy those creatures")); + } + + private DayOfBlackSun(final DayOfBlackSun card) { + super(card); + } + + @Override + public DayOfBlackSun copy() { + return new DayOfBlackSun(this); + } +} + +enum DayOfBlackSunPredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return input.getObject().getManaValue() <= GetXValue.instance.calculate(game, input.getSource(), null); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 062d1028210..8258162562d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -86,6 +86,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Dai Li Agents", 214, Rarity.UNCOMMON, mage.cards.d.DaiLiAgents.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dai Li Agents", 306, Rarity.UNCOMMON, mage.cards.d.DaiLiAgents.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dai Li Indoctrination", 93, Rarity.COMMON, mage.cards.d.DaiLiIndoctrination.class)); + cards.add(new SetCardInfo("Day of Black Sun", 373, Rarity.RARE, mage.cards.d.DayOfBlackSun.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Day of Black Sun", 94, Rarity.RARE, mage.cards.d.DayOfBlackSun.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Deadly Precision", 95, Rarity.COMMON, mage.cards.d.DeadlyPrecision.class)); cards.add(new SetCardInfo("Deserter's Disciple", 131, Rarity.COMMON, mage.cards.d.DesertersDisciple.class)); cards.add(new SetCardInfo("Diligent Zookeeper", 171, Rarity.RARE, mage.cards.d.DiligentZookeeper.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From e562c20f1dbb6a6c38283b76727b7fe6ee885edf Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 17:51:53 -0500 Subject: [PATCH 227/261] [TLA] Implement Earthen Ally --- Mage.Sets/src/mage/cards/e/EarthenAlly.java | 119 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 121 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EarthenAlly.java diff --git a/Mage.Sets/src/mage/cards/e/EarthenAlly.java b/Mage.Sets/src/mage/cards/e/EarthenAlly.java new file mode 100644 index 00000000000..e2e6715fc0b --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EarthenAlly.java @@ -0,0 +1,119 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.abilities.hint.Hint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public final class EarthenAlly extends CardImpl { + + public EarthenAlly(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(0); + this.toughness = new MageInt(2); + + // This creature gets +1/+0 for each color among Allies you control. + this.addAbility(new SimpleStaticAbility(new BoostSourceEffect( + EarthenAllyValue.instance, StaticValue.get(0), Duration.WhileOnBattlefield + )).addHint(EarthenAllyHint.instance)); + + // {2}{W}{U}{B}{R}{G}: Earthbend 5. + Ability ability = new SimpleActivatedAbility( + new EarthbendTargetEffect(5), new ManaCostsImpl<>("{2}{W}{U}{B}{R}{G}") + ); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability); + } + + private EarthenAlly(final EarthenAlly card) { + super(card); + } + + @Override + public EarthenAlly copy() { + return new EarthenAlly(this); + } +} + +enum EarthenAllyValue implements DynamicValue { + instance; + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.ALLY); + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return getColors(game, sourceAbility).getColorCount(); + } + + static ObjectColor getColors(Game game, Ability sourceAbility) { + return game.getBattlefield() + .getActivePermanents(filter, sourceAbility.getControllerId(), sourceAbility, game) + .stream() + .map(permanent -> permanent.getColor(game)) + .collect(Collectors.reducing((c1, c2) -> c1.union(c2))) + .orElseGet(ObjectColor::new); + } + + @Override + public EarthenAllyValue copy() { + return this; + } + + @Override + public String getMessage() { + return "color among Allies you control"; + } + + @Override + public String toString() { + return "1"; + } +} + +enum EarthenAllyHint implements Hint { + instance; + + @Override + public String getText(Game game, Ability ability) { + ObjectColor color = EarthenAllyValue.getColors(game, ability); + return "Colors among Allies you control: " + color.getColorCount() + + (color.getColorCount() > 0 + ? color + .getColors() + .stream() + .map(ObjectColor::getDescription) + .collect(Collectors.joining(", ", " (", ")")) + : ""); + } + + @Override + public Hint copy() { + return this; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 8258162562d..04cc987b06e 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -104,6 +104,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Earthbender Ascension", 175, Rarity.RARE, mage.cards.e.EarthbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earthbender Ascension", 307, Rarity.RARE, mage.cards.e.EarthbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earthbending Lesson", 176, Rarity.COMMON, mage.cards.e.EarthbendingLesson.class)); + cards.add(new SetCardInfo("Earthen Ally", 177, Rarity.RARE, mage.cards.e.EarthenAlly.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Earthen Ally", 377, Rarity.RARE, mage.cards.e.EarthenAlly.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Enter the Avatar State", 18, Rarity.UNCOMMON, mage.cards.e.EnterTheAvatarState.class)); cards.add(new SetCardInfo("Epic Downfall", 96, Rarity.UNCOMMON, mage.cards.e.EpicDownfall.class)); cards.add(new SetCardInfo("Fancy Footwork", 19, Rarity.UNCOMMON, mage.cards.f.FancyFootwork.class)); -- 2.47.2 From ad063f7874b4153445d7e5cbcfea79e41fd9086b Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 17:54:57 -0500 Subject: [PATCH 228/261] [TLA] Implement Jeong Jeong, the Deserter --- .../mage/cards/j/JeongJeongTheDeserter.java | 59 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 60 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/j/JeongJeongTheDeserter.java diff --git a/Mage.Sets/src/mage/cards/j/JeongJeongTheDeserter.java b/Mage.Sets/src/mage/cards/j/JeongJeongTheDeserter.java new file mode 100644 index 00000000000..c5e1fc61e9f --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JeongJeongTheDeserter.java @@ -0,0 +1,59 @@ +package mage.cards.j; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.delayed.CopyNextSpellDelayedTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.ExhaustAbility; +import mage.abilities.keyword.FirebendingAbility; +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.filter.FilterSpell; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JeongJeongTheDeserter extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("a Lesson spell"); + + static { + filter.add(SubType.LESSON.getPredicate()); + } + + public JeongJeongTheDeserter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.REBEL); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Firebending 1 + this.addAbility(new FirebendingAbility(1)); + + // Exhaust -- {3}: Put a +1/+1 counter on Jeong Jeong. When you next cast a Lesson spell this turn, copy it and you may choose new targets for the copy. + Ability ability = new ExhaustAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new GenericManaCost(3)); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new CopyNextSpellDelayedTriggeredAbility(filter))); + this.addAbility(ability); + } + + private JeongJeongTheDeserter(final JeongJeongTheDeserter card) { + super(card); + } + + @Override + public JeongJeongTheDeserter copy() { + return new JeongJeongTheDeserter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 04cc987b06e..df77ca81523 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -170,6 +170,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Island", 293, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("It'll Quench Ya!", 58, Rarity.COMMON, mage.cards.i.ItllQuenchYa.class)); cards.add(new SetCardInfo("Jeong Jeong's Deserters", 25, Rarity.COMMON, mage.cards.j.JeongJeongsDeserters.class)); + cards.add(new SetCardInfo("Jeong Jeong, the Deserter", 142, Rarity.UNCOMMON, mage.cards.j.JeongJeongTheDeserter.class)); cards.add(new SetCardInfo("Jet's Brainwashing", 143, Rarity.UNCOMMON, mage.cards.j.JetsBrainwashing.class)); cards.add(new SetCardInfo("Joo Dee, One of Many", 105, Rarity.UNCOMMON, mage.cards.j.JooDeeOneOfMany.class)); cards.add(new SetCardInfo("Katara, Bending Prodigy", 59, Rarity.UNCOMMON, mage.cards.k.KataraBendingProdigy.class)); -- 2.47.2 From b87735aa498a082e4423e6d0848949a789470902 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 17:58:30 -0500 Subject: [PATCH 229/261] [TLA] Implement June, Bounty Hunter --- .../src/mage/cards/j/JuneBountyHunter.java | 60 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 61 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/j/JuneBountyHunter.java diff --git a/Mage.Sets/src/mage/cards/j/JuneBountyHunter.java b/Mage.Sets/src/mage/cards/j/JuneBountyHunter.java new file mode 100644 index 00000000000..afe5ebc8378 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JuneBountyHunter.java @@ -0,0 +1,60 @@ +package mage.cards.j; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.DrewTwoOrMoreCardsCondition; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.decorator.ConditionalRestrictionEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect; +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.game.permanent.token.ClueArtifactToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JuneBountyHunter extends CardImpl { + + public JuneBountyHunter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.MERCENARY); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // June can't be blocked as long as you've drawn two or more cards this turn. + this.addAbility(new SimpleStaticAbility(new ConditionalRestrictionEffect( + new CantBeBlockedSourceEffect(), DrewTwoOrMoreCardsCondition.instance, + "{this} can't be blocked as long as you've drawn two or more cards this turn" + ))); + + // {1}, Sacrifice another creature: Create a Clue token. Activate only during your turn. + Ability ability = new ActivateIfConditionActivatedAbility( + new CreateTokenEffect(new ClueArtifactToken()), new GenericManaCost(1), MyTurnCondition.instance + ); + ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_ANOTHER_CREATURE)); + this.addAbility(ability); + } + + private JuneBountyHunter(final JuneBountyHunter card) { + super(card); + } + + @Override + public JuneBountyHunter copy() { + return new JuneBountyHunter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index df77ca81523..208a9c946d2 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -173,6 +173,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Jeong Jeong, the Deserter", 142, Rarity.UNCOMMON, mage.cards.j.JeongJeongTheDeserter.class)); cards.add(new SetCardInfo("Jet's Brainwashing", 143, Rarity.UNCOMMON, mage.cards.j.JetsBrainwashing.class)); cards.add(new SetCardInfo("Joo Dee, One of Many", 105, Rarity.UNCOMMON, mage.cards.j.JooDeeOneOfMany.class)); + cards.add(new SetCardInfo("June, Bounty Hunter", 106, Rarity.UNCOMMON, mage.cards.j.JuneBountyHunter.class)); cards.add(new SetCardInfo("Katara, Bending Prodigy", 59, Rarity.UNCOMMON, mage.cards.k.KataraBendingProdigy.class)); cards.add(new SetCardInfo("Katara, Water Tribe's Hope", 231, Rarity.RARE, mage.cards.k.KataraWaterTribesHope.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Katara, Water Tribe's Hope", 351, Rarity.RARE, mage.cards.k.KataraWaterTribesHope.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From e6cb3fe68e9a57777fb706dc0f01eefc8c05998c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 18:00:30 -0500 Subject: [PATCH 230/261] [TLA] Implement Jet, Freedom Fighter --- .../src/mage/cards/j/JetFreedomFighter.java | 57 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 58 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/j/JetFreedomFighter.java diff --git a/Mage.Sets/src/mage/cards/j/JetFreedomFighter.java b/Mage.Sets/src/mage/cards/j/JetFreedomFighter.java new file mode 100644 index 00000000000..51d031ae5c7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JetFreedomFighter.java @@ -0,0 +1,57 @@ +package mage.cards.j; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.CreaturesYouControlCount; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +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.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class JetFreedomFighter extends CardImpl { + + public JetFreedomFighter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R/W}{R/W}{R/W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.REBEL); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // When Jet enters, he deals damage equal to the number of creatures you control to target creature an opponent controls. + Ability ability = new EntersBattlefieldTriggeredAbility( + new DamageTargetEffect(CreaturesYouControlCount.PLURAL, "he") + ); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + + // When Jet dies, put a +1/+1 counter on each of up to two target creatures. + ability = new DiesSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); + ability.addTarget(new TargetCreaturePermanent(0, 2)); + this.addAbility(ability); + } + + private JetFreedomFighter(final JetFreedomFighter card) { + super(card); + } + + @Override + public JetFreedomFighter copy() { + return new JetFreedomFighter(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 208a9c946d2..cd14d67f34f 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -172,6 +172,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Jeong Jeong's Deserters", 25, Rarity.COMMON, mage.cards.j.JeongJeongsDeserters.class)); cards.add(new SetCardInfo("Jeong Jeong, the Deserter", 142, Rarity.UNCOMMON, mage.cards.j.JeongJeongTheDeserter.class)); cards.add(new SetCardInfo("Jet's Brainwashing", 143, Rarity.UNCOMMON, mage.cards.j.JetsBrainwashing.class)); + cards.add(new SetCardInfo("Jet, Freedom Fighter", 229, Rarity.UNCOMMON, mage.cards.j.JetFreedomFighter.class)); cards.add(new SetCardInfo("Joo Dee, One of Many", 105, Rarity.UNCOMMON, mage.cards.j.JooDeeOneOfMany.class)); cards.add(new SetCardInfo("June, Bounty Hunter", 106, Rarity.UNCOMMON, mage.cards.j.JuneBountyHunter.class)); cards.add(new SetCardInfo("Katara, Bending Prodigy", 59, Rarity.UNCOMMON, mage.cards.k.KataraBendingProdigy.class)); -- 2.47.2 From 7bd6c157a81b5010da9c28f4857a0cf3f303a7dd Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 11 Nov 2025 18:07:48 -0500 Subject: [PATCH 231/261] [SLD] Implement Kratos, Stoic Father --- .../src/mage/cards/k/KratosStoicFather.java | 69 +++++++++++++++++++ Mage.Sets/src/mage/sets/SecretLairDrop.java | 1 + 2 files changed, 70 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/k/KratosStoicFather.java diff --git a/Mage.Sets/src/mage/cards/k/KratosStoicFather.java b/Mage.Sets/src/mage/cards/k/KratosStoicFather.java new file mode 100644 index 00000000000..edd10bbbf1b --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KratosStoicFather.java @@ -0,0 +1,69 @@ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CountersControllerCount; +import mage.abilities.effects.common.counter.AddCountersPlayersEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.meta.OrTriggeredAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KratosStoicFather extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.GOD); + private static final DynamicValue xValue = new CountersControllerCount(CounterType.EXPERIENCE); + + public KratosStoicFather(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.GOD); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Whenever you attack with one or more Gods and whenever a God dies, you get an experience counter. + this.addAbility(new OrTriggeredAbility( + Zone.BATTLEFIELD, + new AddCountersPlayersEffect(CounterType.EXPERIENCE.createInstance(), TargetController.YOU), + new AttacksWithCreaturesTriggeredAbility(null, 1, filter), + new DiesCreatureTriggeredAbility(null, false, filter) + ).setTriggerPhrase("Whenever you attack with one or more Gods and whenever a God dies, ")); + + // At the beginning of your end step, put a number of +1/+1 counters on target creature equal to the number of experience counters you have. + Ability ability = new BeginningOfEndStepTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance(), xValue) + .setText(" put a number of +1/+1 counters on target creature " + + "equal to the number of experience counters you have") + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + // Partner--Father & son + this.addAbility(PartnerVariantType.FATHER_AND_SON.makeAbility()); + } + + private KratosStoicFather(final KratosStoicFather card) { + super(card); + } + + @Override + public KratosStoicFather copy() { + return new KratosStoicFather(this); + } +} diff --git a/Mage.Sets/src/mage/sets/SecretLairDrop.java b/Mage.Sets/src/mage/sets/SecretLairDrop.java index db3d84fa476..2875eacd749 100644 --- a/Mage.Sets/src/mage/sets/SecretLairDrop.java +++ b/Mage.Sets/src/mage/sets/SecretLairDrop.java @@ -2182,6 +2182,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Sulfuric Vortex", 2210, Rarity.RARE, mage.cards.s.SulfuricVortex.class)); cards.add(new SetCardInfo("Pyrohemia", 2211, Rarity.RARE, mage.cards.p.Pyrohemia.class)); cards.add(new SetCardInfo("Atreus, Impulsive Son", 2212, Rarity.MYTHIC, mage.cards.a.AtreusImpulsiveSon.class)); + cards.add(new SetCardInfo("Kratos, Stoic Father", 2213, Rarity.MYTHIC, mage.cards.k.KratosStoicFather.class)); cards.add(new SetCardInfo("Teferi's Ageless Insight", 2214, Rarity.RARE, mage.cards.t.TeferisAgelessInsight.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Teferi's Ageless Insight", "2214b", Rarity.RARE, mage.cards.t.TeferisAgelessInsight.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iroas, God of Victory", 2215, Rarity.MYTHIC, mage.cards.i.IroasGodOfVictory.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From e338f5c3f2e80ec185ec7ea769294a1d69175a6f Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 08:46:31 -0500 Subject: [PATCH 232/261] [TLA] Implement Aang, at the Crossroads / Aang, Destined Savior --- .../src/mage/cards/a/AangAtTheCrossroads.java | 67 +++++++++++++++++++ .../src/mage/cards/a/AangDestinedSavior.java | 66 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 6 ++ 3 files changed, 139 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AangAtTheCrossroads.java create mode 100644 Mage.Sets/src/mage/cards/a/AangDestinedSavior.java diff --git a/Mage.Sets/src/mage/cards/a/AangAtTheCrossroads.java b/Mage.Sets/src/mage/cards/a/AangAtTheCrossroads.java new file mode 100644 index 00000000000..4418a5a1ef8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AangAtTheCrossroads.java @@ -0,0 +1,67 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.LeavesBattlefieldAllTriggeredAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.ManaValuePredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AangAtTheCrossroads extends CardImpl { + + private static final FilterCard filter = new FilterCreatureCard("creature card with mana value 4 or less"); + + static { + filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 5)); + } + + public AangAtTheCrossroads(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{W}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.AVATAR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.a.AangDestinedSavior.class; + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Aang enters, look at the top five cards of your library. You may put a creature card with mana value 4 or less from among them onto the battlefield. Put the rest on the bottom of your library in a random order. + this.addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect( + 5, 1, filter, PutCards.BATTLEFIELD, PutCards.BOTTOM_RANDOM + ))); + + // When another creature you control leaves the battlefield, transform Aang at the beginning of the next upkeep. + this.addAbility(new TransformAbility()); + this.addAbility(new LeavesBattlefieldAllTriggeredAbility(new CreateDelayedTriggeredAbilityEffect( + new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new TransformSourceEffect()) + ).setText("transform {this} at the beginning of the next upkeep"), StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL)); + } + + private AangAtTheCrossroads(final AangAtTheCrossroads card) { + super(card); + } + + @Override + public AangAtTheCrossroads copy() { + return new AangAtTheCrossroads(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AangDestinedSavior.java b/Mage.Sets/src/mage/cards/a/AangDestinedSavior.java new file mode 100644 index 00000000000..952fe02c8a1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AangDestinedSavior.java @@ -0,0 +1,66 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AangDestinedSavior extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("land creatures"); + + static { + filter.add(CardType.LAND.getPredicate()); + filter.add(CardType.CREATURE.getPredicate()); + } + + public AangDestinedSavior(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.AVATAR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + this.nightCard = true; + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Land creatures you control have vigilance. + this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( + VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, filter + ))); + + // At the beginning of combat on your turn, earthbend 2. + Ability ability = new BeginningOfCombatTriggeredAbility(new EarthbendTargetEffect(2)); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability); + } + + private AangDestinedSavior(final AangDestinedSavior card) { + super(card); + } + + @Override + public AangDestinedSavior copy() { + return new AangDestinedSavior(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index cd14d67f34f..496dfc4b484 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -28,9 +28,15 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Aang's Iceberg", 336, Rarity.RARE, mage.cards.a.AangsIceberg.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang's Iceberg", 5, Rarity.RARE, mage.cards.a.AangsIceberg.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang's Journey", 1, Rarity.COMMON, mage.cards.a.AangsJourney.class)); + cards.add(new SetCardInfo("Aang, Destined Savior", 203, Rarity.RARE, mage.cards.a.AangDestinedSavior.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, Destined Savior", 304, Rarity.RARE, mage.cards.a.AangDestinedSavior.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, Destined Savior", 346, Rarity.RARE, mage.cards.a.AangDestinedSavior.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, Master of Elements", 207, Rarity.MYTHIC, mage.cards.a.AangMasterOfElements.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, Master of Elements", 308, Rarity.MYTHIC, mage.cards.a.AangMasterOfElements.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, Master of Elements", 363, Rarity.MYTHIC, mage.cards.a.AangMasterOfElements.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, at the Crossroads", 203, Rarity.RARE, mage.cards.a.AangAtTheCrossroads.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, at the Crossroads", 304, Rarity.RARE, mage.cards.a.AangAtTheCrossroads.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, at the Crossroads", 346, Rarity.RARE, mage.cards.a.AangAtTheCrossroads.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, the Last Airbender", 4, Rarity.UNCOMMON, mage.cards.a.AangTheLastAirbender.class)); cards.add(new SetCardInfo("Abandon Attachments", 205, Rarity.COMMON, mage.cards.a.AbandonAttachments.class)); cards.add(new SetCardInfo("Abandoned Air Temple", 263, Rarity.RARE, mage.cards.a.AbandonedAirTemple.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From c76dd063f27b0bf361d3ce57645690eebe4a26cc Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 08:52:03 -0500 Subject: [PATCH 233/261] [TLA] Implement Beifong's Bounty Hunters --- .../mage/cards/b/BeifongsBountyHunters.java | 87 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 89 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BeifongsBountyHunters.java diff --git a/Mage.Sets/src/mage/cards/b/BeifongsBountyHunters.java b/Mage.Sets/src/mage/cards/b/BeifongsBountyHunters.java new file mode 100644 index 00000000000..c1253abe2e9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BeifongsBountyHunters.java @@ -0,0 +1,87 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BeifongsBountyHunters extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("nonland creature you control"); + + static { + filter.add(Predicates.not(CardType.LAND.getPredicate())); + } + + public BeifongsBountyHunters(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.MERCENARY); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Whenever a nonland creature you control dies, earthbend X, where X is that creature's power. + Ability ability = new DiesCreatureTriggeredAbility( + new EarthbendTargetEffect(BeifongsBountyHuntersValue.instance), false, filter + ); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability); + } + + private BeifongsBountyHunters(final BeifongsBountyHunters card) { + super(card); + } + + @Override + public BeifongsBountyHunters copy() { + return new BeifongsBountyHunters(this); + } +} + +enum BeifongsBountyHuntersValue implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return Optional + .ofNullable((Permanent) effect.getValue("creatureDied")) + .map(MageObject::getPower) + .map(MageInt::getValue) + .orElse(0); + } + + @Override + public BeifongsBountyHuntersValue copy() { + return this; + } + + @Override + public String getMessage() { + return "that creature's power"; + } + + @Override + public String toString() { + return "X"; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 496dfc4b484..b2651720404 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -66,6 +66,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Badgermole", 166, Rarity.COMMON, mage.cards.b.Badgermole.class)); cards.add(new SetCardInfo("Barrels of Blasting Jelly", 254, Rarity.COMMON, mage.cards.b.BarrelsOfBlastingJelly.class)); cards.add(new SetCardInfo("Beetle-Headed Merchants", 86, Rarity.COMMON, mage.cards.b.BeetleHeadedMerchants.class)); + cards.add(new SetCardInfo("Beifong's Bounty Hunters", 209, Rarity.RARE, mage.cards.b.BeifongsBountyHunters.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Beifong's Bounty Hunters", 379, Rarity.RARE, mage.cards.b.BeifongsBountyHunters.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bender's Waterskin", 255, Rarity.COMMON, mage.cards.b.BendersWaterskin.class)); cards.add(new SetCardInfo("Benevolent River Spirit", 45, Rarity.UNCOMMON, mage.cards.b.BenevolentRiverSpirit.class)); cards.add(new SetCardInfo("Bitter Work", 210, Rarity.UNCOMMON, mage.cards.b.BitterWork.class)); -- 2.47.2 From 4c3af32a5081df975d79e0b3eba54cb0f0e37bf9 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 08:55:11 -0500 Subject: [PATCH 234/261] [TLA] Implement Combustion Technique --- .../src/mage/cards/c/CombustionTechnique.java | 48 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 50 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/c/CombustionTechnique.java diff --git a/Mage.Sets/src/mage/cards/c/CombustionTechnique.java b/Mage.Sets/src/mage/cards/c/CombustionTechnique.java new file mode 100644 index 00000000000..4586a052905 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CombustionTechnique.java @@ -0,0 +1,48 @@ +package mage.cards.c; + +import mage.abilities.condition.common.LessonsInGraveCondition; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.IntPlusDynamicValue; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.ExileTargetIfDiesEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class CombustionTechnique extends CardImpl { + + private static final DynamicValue xValue = new IntPlusDynamicValue( + 2, new CardsInControllerGraveyardCount(new FilterCard(SubType.LESSON)) + ); + + public CombustionTechnique(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); + + this.subtype.add(SubType.LESSON); + + // Combustion Technique deals damage equal to 2 plus the number of Lesson cards in your graveyard to target creature. If that creature would die this turn, exile it instead. + this.getSpellAbility().addEffect(new DamageTargetEffect(xValue) + .setText("{this} deals damage equal to 2 plus the number of Lesson cards in your graveyard to target creature")); + this.getSpellAbility().addEffect(new ExileTargetIfDiesEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addHint(LessonsInGraveCondition.getHint()); + } + + private CombustionTechnique(final CombustionTechnique card) { + super(card); + } + + @Override + public CombustionTechnique copy() { + return new CombustionTechnique(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b2651720404..8a95bdd63a9 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -84,6 +84,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Canyon Crawler", 90, Rarity.COMMON, mage.cards.c.CanyonCrawler.class)); cards.add(new SetCardInfo("Cat-Gator", 91, Rarity.UNCOMMON, mage.cards.c.CatGator.class)); cards.add(new SetCardInfo("Cat-Owl", 212, Rarity.COMMON, mage.cards.c.CatOwl.class)); + cards.add(new SetCardInfo("Combustion Technique", 128, Rarity.UNCOMMON, mage.cards.c.CombustionTechnique.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Combustion Technique", 301, Rarity.UNCOMMON, mage.cards.c.CombustionTechnique.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Compassionate Healer", 13, Rarity.COMMON, mage.cards.c.CompassionateHealer.class)); cards.add(new SetCardInfo("Corrupt Court Official", 92, Rarity.COMMON, mage.cards.c.CorruptCourtOfficial.class)); cards.add(new SetCardInfo("Crescent Island Temple", 129, Rarity.UNCOMMON, mage.cards.c.CrescentIslandTemple.class)); -- 2.47.2 From 626317cf6833b34ba479c811c50776b14c985f36 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 09:01:52 -0500 Subject: [PATCH 235/261] [TLA] Implement Ember Island Production --- .../mage/cards/e/EmberIslandProduction.java | 55 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + .../common/CreateTokenCopyTargetEffect.java | 14 ++++- 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/e/EmberIslandProduction.java diff --git a/Mage.Sets/src/mage/cards/e/EmberIslandProduction.java b/Mage.Sets/src/mage/cards/e/EmberIslandProduction.java new file mode 100644 index 00000000000..6c5c00c99d6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EmberIslandProduction.java @@ -0,0 +1,55 @@ +package mage.cards.e; + +import mage.abilities.Mode; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EmberIslandProduction extends CardImpl { + + public EmberIslandProduction(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{U}"); + + // Choose one-- + // * Create a token that's a copy of target creature you control, except it's not legendary and it's a 4/4 Hero in addition to its other types. + this.getSpellAbility().addEffect( + new CreateTokenCopyTargetEffect() + .setIsntLegendary(true) + .setPower(4) + .setToughness(4) + .withAdditionalSubType(SubType.HERO) + .setText("create a token that's a copy of target creature you control, " + + "except it's not legendary and it's a 4/4 Hero in addition to its other types") + ); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + + // * Create a token that's a copy of target creature an opponent controls, except it's not legendary and it's a 2/2 Coward in addition to its other types. + this.getSpellAbility().addMode(new Mode( + new CreateTokenCopyTargetEffect() + .setIsntLegendary(true) + .setPower(2) + .setToughness(2) + .withAdditionalSubType(SubType.COWARD) + .setText("create a token that's a copy of target creature an opponent controls, " + + "except it's not legendary and it's a 2/2 Coward in addition to its other types") + ).addTarget(new TargetOpponentsCreaturePermanent())); + } + + private EmberIslandProduction(final EmberIslandProduction card) { + super(card); + } + + @Override + public EmberIslandProduction copy() { + return new EmberIslandProduction(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 8a95bdd63a9..8df57f70d93 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -116,6 +116,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Earthbending Lesson", 176, Rarity.COMMON, mage.cards.e.EarthbendingLesson.class)); cards.add(new SetCardInfo("Earthen Ally", 177, Rarity.RARE, mage.cards.e.EarthenAlly.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earthen Ally", 377, Rarity.RARE, mage.cards.e.EarthenAlly.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ember Island Production", 48, Rarity.UNCOMMON, mage.cards.e.EmberIslandProduction.class)); cards.add(new SetCardInfo("Enter the Avatar State", 18, Rarity.UNCOMMON, mage.cards.e.EnterTheAvatarState.class)); cards.add(new SetCardInfo("Epic Downfall", 96, Rarity.UNCOMMON, mage.cards.e.EpicDownfall.class)); cards.add(new SetCardInfo("Fancy Footwork", 19, Rarity.UNCOMMON, mage.cards.f.FancyFootwork.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java index 6f02329d0b3..eed991c7797 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java @@ -58,8 +58,8 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { private final boolean tapped; private Permanent savedPermanent = null; private int startingLoyalty = -1; - private final int tokenPower; - private final int tokenToughness; + private int tokenPower; + private int tokenToughness; private boolean useLKI = false; private PermanentModifier permanentModifier = null; @@ -387,6 +387,16 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect { return this; } + public CreateTokenCopyTargetEffect setPower(int tokenPower) { + this.tokenPower = tokenPower; + return this; + } + + public CreateTokenCopyTargetEffect setToughness(int tokenToughness) { + this.tokenToughness = tokenToughness; + return this; + } + public CreateTokenCopyTargetEffect addAbilityClassesToRemoveFromTokens(Class clazz) { this.abilityClazzesToRemove.add(clazz); return this; -- 2.47.2 From 473df7ac12bdcc5ba8a95c664508d57fb16ccb14 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 09:06:29 -0500 Subject: [PATCH 236/261] [TLA] Implement Fire Navy Trebuchet --- .../src/mage/cards/f/FireNavyTrebuchet.java | 83 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 84 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FireNavyTrebuchet.java diff --git a/Mage.Sets/src/mage/cards/f/FireNavyTrebuchet.java b/Mage.Sets/src/mage/cards/f/FireNavyTrebuchet.java new file mode 100644 index 00000000000..14384d8587e --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FireNavyTrebuchet.java @@ -0,0 +1,83 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeTargetEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.abilities.keyword.ReachAbility; +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.game.permanent.token.BallisticBoulder; +import mage.game.permanent.token.Token; +import mage.target.targetpointer.FixedTargets; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FireNavyTrebuchet extends CardImpl { + + public FireNavyTrebuchet(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.WALL); + this.power = new MageInt(0); + this.toughness = new MageInt(4); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // Whenever you attack, create a 2/1 colorless Construct artifact creature token with flying named Ballistic Boulder that's tapped and attacking. Sacrifice that token at the beginning of the next end step. + this.addAbility(new AttacksWithCreaturesTriggeredAbility(new FireNavyTrebuchetEffect(), 1)); + } + + private FireNavyTrebuchet(final FireNavyTrebuchet card) { + super(card); + } + + @Override + public FireNavyTrebuchet copy() { + return new FireNavyTrebuchet(this); + } +} + +class FireNavyTrebuchetEffect extends OneShotEffect { + + FireNavyTrebuchetEffect() { + super(Outcome.Benefit); + staticText = "create a 2/1 colorless Construct artifact creature token with flying named Ballistic Boulder " + + "that's tapped and attacking. Sacrifice that token at the beginning of the next end step."; + } + + private FireNavyTrebuchetEffect(final FireNavyTrebuchetEffect effect) { + super(effect); + } + + @Override + public FireNavyTrebuchetEffect copy() { + return new FireNavyTrebuchetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Token token = new BallisticBoulder(); + token.putOntoBattlefield(1, game, source, source.getControllerId(), true, true); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + new SacrificeTargetEffect() + .setTargetPointer(new FixedTargets(token, game)) + .setText("sacrifice those tokens") + ), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 8df57f70d93..ea3ff8cca11 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -139,6 +139,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Fire Nation Palace", 389, Rarity.RARE, mage.cards.f.FireNationPalace.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fire Nation Raider", 135, Rarity.COMMON, mage.cards.f.FireNationRaider.class)); cards.add(new SetCardInfo("Fire Nation Warship", 256, Rarity.UNCOMMON, mage.cards.f.FireNationWarship.class)); + cards.add(new SetCardInfo("Fire Navy Trebuchet", 100, Rarity.UNCOMMON, mage.cards.f.FireNavyTrebuchet.class)); cards.add(new SetCardInfo("Fire Sages", 136, Rarity.UNCOMMON, mage.cards.f.FireSages.class)); cards.add(new SetCardInfo("Firebender Ascension", 137, Rarity.RARE, mage.cards.f.FirebenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Firebender Ascension", 312, Rarity.RARE, mage.cards.f.FirebenderAscension.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From d83e1f1e4eff015731fbfb47c5152ef8a0678be8 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 09:21:11 -0500 Subject: [PATCH 237/261] [TLA] Implement Foggy Swamp Hunters --- .../src/mage/cards/f/FoggySwampHunters.java | 53 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 54 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FoggySwampHunters.java diff --git a/Mage.Sets/src/mage/cards/f/FoggySwampHunters.java b/Mage.Sets/src/mage/cards/f/FoggySwampHunters.java new file mode 100644 index 00000000000..57290f092f4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FoggySwampHunters.java @@ -0,0 +1,53 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.DrewTwoOrMoreCardsCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.dynamicvalue.common.CardsDrawnThisTurnDynamicValue; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FoggySwampHunters extends CardImpl { + + public FoggySwampHunters(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.RANGER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // As long as you've drawn two or more cards this turn, this creature has lifelink and menace. + Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( + new GainAbilitySourceEffect(LifelinkAbility.getInstance()), DrewTwoOrMoreCardsCondition.instance, + "as long as you've drawn two or more cards this turn, {this} has lifelink" + )); + ability.addEffect(new ConditionalContinuousEffect( + new GainAbilitySourceEffect(new MenaceAbility(false)), + DrewTwoOrMoreCardsCondition.instance, "and menace" + )); + this.addAbility(ability.addHint(CardsDrawnThisTurnDynamicValue.getHint())); + } + + private FoggySwampHunters(final FoggySwampHunters card) { + super(card); + } + + @Override + public FoggySwampHunters copy() { + return new FoggySwampHunters(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index ea3ff8cca11..009d796dd4d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -151,6 +151,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Flexible Waterbender", 50, Rarity.COMMON, mage.cards.f.FlexibleWaterbender.class)); cards.add(new SetCardInfo("Flopsie, Bumi's Buddy", 179, Rarity.UNCOMMON, mage.cards.f.FlopsieBumisBuddy.class)); cards.add(new SetCardInfo("Foggy Bottom Swamp", 269, Rarity.COMMON, mage.cards.f.FoggyBottomSwamp.class)); + cards.add(new SetCardInfo("Foggy Swamp Hunters", 101, Rarity.COMMON, mage.cards.f.FoggySwampHunters.class)); cards.add(new SetCardInfo("Foggy Swamp Vinebender", 180, Rarity.COMMON, mage.cards.f.FoggySwampVinebender.class)); cards.add(new SetCardInfo("Forecasting Fortune Teller", 51, Rarity.COMMON, mage.cards.f.ForecastingFortuneTeller.class)); cards.add(new SetCardInfo("Forest", 286, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 6efb4e5df455a6ce0c64a78c8cf9f9cf2b1d6d66 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 09:22:04 -0500 Subject: [PATCH 238/261] [TLA] Implement Foggy Swamp Spirit Keeper --- .../mage/cards/f/FoggySwampSpiritKeeper.java | 44 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 45 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FoggySwampSpiritKeeper.java diff --git a/Mage.Sets/src/mage/cards/f/FoggySwampSpiritKeeper.java b/Mage.Sets/src/mage/cards/f/FoggySwampSpiritKeeper.java new file mode 100644 index 00000000000..34f7ebcd407 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FoggySwampSpiritKeeper.java @@ -0,0 +1,44 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.DrawNthCardTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.SpiritWorldToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FoggySwampSpiritKeeper extends CardImpl { + + public FoggySwampSpiritKeeper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.DRUID); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // Whenever you draw your second card each turn, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures." + this.addAbility(new DrawNthCardTriggeredAbility(new CreateTokenEffect(new SpiritWorldToken()))); + } + + private FoggySwampSpiritKeeper(final FoggySwampSpiritKeeper card) { + super(card); + } + + @Override + public FoggySwampSpiritKeeper copy() { + return new FoggySwampSpiritKeeper(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 009d796dd4d..4bb14ee9a0f 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -152,6 +152,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Flopsie, Bumi's Buddy", 179, Rarity.UNCOMMON, mage.cards.f.FlopsieBumisBuddy.class)); cards.add(new SetCardInfo("Foggy Bottom Swamp", 269, Rarity.COMMON, mage.cards.f.FoggyBottomSwamp.class)); cards.add(new SetCardInfo("Foggy Swamp Hunters", 101, Rarity.COMMON, mage.cards.f.FoggySwampHunters.class)); + cards.add(new SetCardInfo("Foggy Swamp Spirit Keeper", 222, Rarity.UNCOMMON, mage.cards.f.FoggySwampSpiritKeeper.class)); cards.add(new SetCardInfo("Foggy Swamp Vinebender", 180, Rarity.COMMON, mage.cards.f.FoggySwampVinebender.class)); cards.add(new SetCardInfo("Forecasting Fortune Teller", 51, Rarity.COMMON, mage.cards.f.ForecastingFortuneTeller.class)); cards.add(new SetCardInfo("Forest", 286, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From c602edeca3e868aaba5e98f4afa29a493fc8624f Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 10:10:03 -0500 Subject: [PATCH 239/261] [TLA] Implement Kyoshi Island Plaza --- .../mage/cards/g/GoShintaiOfAncientWars.java | 19 ++--- .../cards/g/GoShintaiOfBoundlessVigor.java | 24 ++---- .../cards/g/GoShintaiOfHiddenCruelty.java | 15 +--- .../mage/cards/g/GoShintaiOfLostWisdom.java | 17 +---- .../cards/g/GoShintaiOfSharedPurpose.java | 22 ++---- .../mage/cards/h/HondenOfCleansingFire.java | 19 ++--- .../mage/cards/h/HondenOfInfiniteRage.java | 22 ++---- .../src/mage/cards/h/HondenOfLifesWeb.java | 21 ++--- .../src/mage/cards/h/HondenOfNightsReach.java | 18 ++--- .../src/mage/cards/h/HondenOfSeeingWinds.java | 20 +---- .../src/mage/cards/k/KyoshiIslandPlaza.java | 76 +++++++++++++++++++ .../src/mage/cards/n/NorthernAirTemple.java | 25 ++---- Mage.Sets/src/mage/cards/s/SanctumOfAll.java | 22 ++---- .../src/mage/cards/s/SanctumOfCalmWaters.java | 22 ++---- .../cards/s/SanctumOfFruitfulHarvest.java | 29 ++----- .../cards/s/SanctumOfShatteredHeights.java | 24 +++--- .../src/mage/cards/s/SanctumOfStoneFangs.java | 24 ++---- .../mage/cards/s/SanctumOfTranquilLight.java | 19 +---- .../src/mage/cards/s/SouthernAirTemple.java | 22 +----- .../src/mage/cards/t/TheSpiritOasis.java | 21 +---- .../src/mage/sets/AvatarTheLastAirbender.java | 1 + .../common/ShrinesYouControlCount.java | 55 ++++++++++++++ .../effects/common/GainLifeEffect.java | 1 + .../main/java/mage/filter/StaticFilters.java | 7 ++ 24 files changed, 243 insertions(+), 302 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/k/KyoshiIslandPlaza.java create mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/ShrinesYouControlCount.java diff --git a/Mage.Sets/src/mage/cards/g/GoShintaiOfAncientWars.java b/Mage.Sets/src/mage/cards/g/GoShintaiOfAncientWars.java index 01011d968ac..6640e0dd927 100644 --- a/Mage.Sets/src/mage/cards/g/GoShintaiOfAncientWars.java +++ b/Mage.Sets/src/mage/cards/g/GoShintaiOfAncientWars.java @@ -1,22 +1,18 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.delayed.ReflexiveTriggeredAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DoWhenCostPaid; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterControlledPermanent; import mage.target.common.TargetPlayerOrPlaneswalker; import java.util.UUID; @@ -26,11 +22,6 @@ import java.util.UUID; */ public final class GoShintaiOfAncientWars extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( - new FilterControlledPermanent(SubType.SHRINE) - ); - private static final Hint hint = new ValueHint("Shrines you control", xValue); - public GoShintaiOfAncientWars(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{2}{R}"); @@ -44,13 +35,13 @@ public final class GoShintaiOfAncientWars extends CardImpl { // At the beginning of your end step, you may pay {1}. When you do, Go-Shintai of Ancient Wars deals X damage to target player or planeswalker, where X is the number of Shrines you control. ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility( - new DamageTargetEffect(xValue), false, "{this} deals X damage to target " + - "player or planeswalker, where X is the number of Shrines you control" + new DamageTargetEffect(ShrinesYouControlCount.WHERE_X), false, "{this} deals X damage " + + "to target player or planeswalker, where X is the number of Shrines you control" ); ability.addTarget(new TargetPlayerOrPlaneswalker()); this.addAbility(new BeginningOfEndStepTriggeredAbility( new DoWhenCostPaid(ability, new GenericManaCost(1), "Pay {1}?") - ).addHint(hint)); + ).addHint(ShrinesYouControlCount.getHint())); } private GoShintaiOfAncientWars(final GoShintaiOfAncientWars card) { diff --git a/Mage.Sets/src/mage/cards/g/GoShintaiOfBoundlessVigor.java b/Mage.Sets/src/mage/cards/g/GoShintaiOfBoundlessVigor.java index 6c50c66c30e..6f3af4a118b 100644 --- a/Mage.Sets/src/mage/cards/g/GoShintaiOfBoundlessVigor.java +++ b/Mage.Sets/src/mage/cards/g/GoShintaiOfBoundlessVigor.java @@ -1,16 +1,13 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.delayed.ReflexiveTriggeredAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.DoWhenCostPaid; import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -18,7 +15,6 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.counters.CounterType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledPermanent; import mage.target.TargetPermanent; import java.util.UUID; @@ -28,11 +24,7 @@ import java.util.UUID; */ public final class GoShintaiOfBoundlessVigor extends CardImpl { - private static final FilterPermanent filter - = new FilterPermanent(SubType.SHRINE, "Shrine"); - private static final DynamicValue xValue - = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.SHRINE)); - private static final Hint hint = new ValueHint("Shrines you control", xValue); + private static final FilterPermanent filter = new FilterPermanent(SubType.SHRINE, "Shrine"); public GoShintaiOfBoundlessVigor(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{1}{G}"); @@ -46,15 +38,13 @@ public final class GoShintaiOfBoundlessVigor extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // At the beginning of your end step, you may pay {1}. When you do, put a +1/+1 counter on target Shrine for each Shrine you control. - ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility( - new AddCountersTargetEffect( - CounterType.P1P1.createInstance(0), xValue - ), false - ); + ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(new AddCountersTargetEffect( + CounterType.P1P1.createInstance(0), ShrinesYouControlCount.FOR_EACH + ), false); ability.addTarget(new TargetPermanent(filter)); this.addAbility(new BeginningOfEndStepTriggeredAbility(new DoWhenCostPaid( ability, new GenericManaCost(1), "Pay {1}?" - )).addHint(hint)); + )).addHint(ShrinesYouControlCount.getHint())); } private GoShintaiOfBoundlessVigor(final GoShintaiOfBoundlessVigor card) { diff --git a/Mage.Sets/src/mage/cards/g/GoShintaiOfHiddenCruelty.java b/Mage.Sets/src/mage/cards/g/GoShintaiOfHiddenCruelty.java index 38c76716b3f..4a4fd0f0c5b 100644 --- a/Mage.Sets/src/mage/cards/g/GoShintaiOfHiddenCruelty.java +++ b/Mage.Sets/src/mage/cards/g/GoShintaiOfHiddenCruelty.java @@ -1,15 +1,13 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.delayed.ReflexiveTriggeredAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DoWhenCostPaid; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -58,7 +56,7 @@ public final class GoShintaiOfHiddenCruelty extends CardImpl { ability.addTarget(new TargetPermanent(filter)); this.addAbility(new BeginningOfEndStepTriggeredAbility( new DoWhenCostPaid(ability, new GenericManaCost(1), "Pay {1}?") - ).addHint(GoShintaiOfHiddenCrueltyPredicate.getHint())); + ).addHint(ShrinesYouControlCount.getHint())); } private GoShintaiOfHiddenCruelty(final GoShintaiOfHiddenCruelty card) { @@ -74,13 +72,6 @@ public final class GoShintaiOfHiddenCruelty extends CardImpl { enum GoShintaiOfHiddenCrueltyPredicate implements ObjectSourcePlayerPredicate { instance; private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SHRINE); - private static final Hint hint = new ValueHint( - "Shrines you control", new PermanentsOnBattlefieldCount(filter) - ); - - public static Hint getHint() { - return hint; - } @Override public boolean apply(ObjectSourcePlayer input, Game game) { diff --git a/Mage.Sets/src/mage/cards/g/GoShintaiOfLostWisdom.java b/Mage.Sets/src/mage/cards/g/GoShintaiOfLostWisdom.java index aee2e8ce8a9..efdf3706723 100644 --- a/Mage.Sets/src/mage/cards/g/GoShintaiOfLostWisdom.java +++ b/Mage.Sets/src/mage/cards/g/GoShintaiOfLostWisdom.java @@ -1,22 +1,18 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.delayed.ReflexiveTriggeredAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.DoWhenCostPaid; import mage.abilities.effects.common.MillCardsTargetEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterControlledPermanent; import mage.target.TargetPlayer; import java.util.UUID; @@ -26,11 +22,6 @@ import java.util.UUID; */ public final class GoShintaiOfLostWisdom extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( - new FilterControlledPermanent(SubType.SHRINE) - ); - private static final Hint hint = new ValueHint("Shrines you control", xValue); - public GoShintaiOfLostWisdom(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{1}{U}"); @@ -44,13 +35,13 @@ public final class GoShintaiOfLostWisdom extends CardImpl { // At the beginning of your end step, you may pay {1}. When you do, target player mills X cards, where X is the number of Shrines you control. ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility( - new MillCardsTargetEffect(xValue), false, + new MillCardsTargetEffect(ShrinesYouControlCount.WHERE_X), false, "target player mills X cards, where X is the number of Shrines you control" ); ability.addTarget(new TargetPlayer()); this.addAbility(new BeginningOfEndStepTriggeredAbility(new DoWhenCostPaid( ability, new GenericManaCost(1), "Pay {1}?" - )).addHint(hint)); + )).addHint(ShrinesYouControlCount.getHint())); } private GoShintaiOfLostWisdom(final GoShintaiOfLostWisdom card) { diff --git a/Mage.Sets/src/mage/cards/g/GoShintaiOfSharedPurpose.java b/Mage.Sets/src/mage/cards/g/GoShintaiOfSharedPurpose.java index f565593f6bd..66c1398927c 100644 --- a/Mage.Sets/src/mage/cards/g/GoShintaiOfSharedPurpose.java +++ b/Mage.Sets/src/mage/cards/g/GoShintaiOfSharedPurpose.java @@ -1,21 +1,17 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DoIfCostPaid; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterControlledPermanent; import mage.game.permanent.token.SpiritToken; import java.util.UUID; @@ -25,11 +21,6 @@ import java.util.UUID; */ public final class GoShintaiOfSharedPurpose extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( - new FilterControlledPermanent(SubType.SHRINE) - ); - private static final Hint hint = new ValueHint("Shrines you control", xValue); - public GoShintaiOfSharedPurpose(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{3}{W}"); @@ -42,12 +33,9 @@ public final class GoShintaiOfSharedPurpose extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // At the beginning of your end step, you may pay {1}. If you do, create a 1/1 colorless Spirit creature token for each Shrine you control. - this.addAbility(new BeginningOfEndStepTriggeredAbility( - new DoIfCostPaid( - new CreateTokenEffect(new SpiritToken(), xValue), - new GenericManaCost(1) - ) - ).addHint(hint)); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new DoIfCostPaid( + new CreateTokenEffect(new SpiritToken(), ShrinesYouControlCount.FOR_EACH), new GenericManaCost(1) + )).addHint(ShrinesYouControlCount.getHint())); } private GoShintaiOfSharedPurpose(final GoShintaiOfSharedPurpose card) { diff --git a/Mage.Sets/src/mage/cards/h/HondenOfCleansingFire.java b/Mage.Sets/src/mage/cards/h/HondenOfCleansingFire.java index 33833f95671..e2a8022bcc2 100644 --- a/Mage.Sets/src/mage/cards/h/HondenOfCleansingFire.java +++ b/Mage.Sets/src/mage/cards/h/HondenOfCleansingFire.java @@ -1,20 +1,15 @@ - - package mage.cards.h; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.MultipliedValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.GainLifeEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterControlledPermanent; import java.util.UUID; @@ -23,19 +18,15 @@ import java.util.UUID; */ public final class HondenOfCleansingFire extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( - new FilterControlledPermanent(SubType.SHRINE) - ); - private static final Hint hint = new ValueHint("Shrines you control", xValue); + private static final DynamicValue xValue = new MultipliedValue(ShrinesYouControlCount.FOR_EACH, 2); public HondenOfCleansingFire(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SHRINE); - // At the beginning of your upkeep, you gain 2 life for each Shrine you control. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(new MultipliedValue(xValue, 2))).addHint(hint)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(xValue)).addHint(ShrinesYouControlCount.getHint())); } private HondenOfCleansingFire(final HondenOfCleansingFire card) { diff --git a/Mage.Sets/src/mage/cards/h/HondenOfInfiniteRage.java b/Mage.Sets/src/mage/cards/h/HondenOfInfiniteRage.java index aba3e7383c7..d3951458985 100644 --- a/Mage.Sets/src/mage/cards/h/HondenOfInfiniteRage.java +++ b/Mage.Sets/src/mage/cards/h/HondenOfInfiniteRage.java @@ -1,39 +1,33 @@ package mage.cards.h; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.DamageTargetEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterControlledPermanent; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author Loki */ public final class HondenOfInfiniteRage extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( - new FilterControlledPermanent(SubType.SHRINE) - ); - private static final Hint hint = new ValueHint("Shrines you control", xValue); - public HondenOfInfiniteRage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SHRINE); // At the beginning of your upkeep, Honden of Infinite Rage deals damage to any target equal to the number of Shrines you control. - Ability ability = new BeginningOfUpkeepTriggeredAbility(new DamageTargetEffect(xValue)).addHint(hint); + Ability ability = new BeginningOfUpkeepTriggeredAbility( + new DamageTargetEffect(ShrinesYouControlCount.WHERE_X) + .setText("{this} deals damage to any target equal to the number of Shrines you control") + ).addHint(ShrinesYouControlCount.getHint()); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HondenOfLifesWeb.java b/Mage.Sets/src/mage/cards/h/HondenOfLifesWeb.java index a454a61824e..e387bb9e671 100644 --- a/Mage.Sets/src/mage/cards/h/HondenOfLifesWeb.java +++ b/Mage.Sets/src/mage/cards/h/HondenOfLifesWeb.java @@ -1,19 +1,13 @@ - - package mage.cards.h; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterControlledPermanent; import mage.game.permanent.token.SpiritToken; import java.util.UUID; @@ -23,17 +17,14 @@ import java.util.UUID; */ public final class HondenOfLifesWeb extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( - new FilterControlledPermanent(SubType.SHRINE) - ); - private static final Hint hint = new ValueHint("Shrines you control", xValue); - public HondenOfLifesWeb(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SHRINE); - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new SpiritToken(), xValue)).addHint(hint)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new CreateTokenEffect(new SpiritToken(), ShrinesYouControlCount.FOR_EACH) + ).addHint(ShrinesYouControlCount.getHint())); } private HondenOfLifesWeb(final HondenOfLifesWeb card) { diff --git a/Mage.Sets/src/mage/cards/h/HondenOfNightsReach.java b/Mage.Sets/src/mage/cards/h/HondenOfNightsReach.java index 6741ac4a502..eebc9b261c6 100644 --- a/Mage.Sets/src/mage/cards/h/HondenOfNightsReach.java +++ b/Mage.Sets/src/mage/cards/h/HondenOfNightsReach.java @@ -1,38 +1,30 @@ package mage.cards.h; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.discard.DiscardTargetEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterControlledPermanent; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** * @author Loki */ public final class HondenOfNightsReach extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( - new FilterControlledPermanent(SubType.SHRINE) - ); - private static final Hint hint = new ValueHint("Shrines you control", xValue); - public HondenOfNightsReach(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SHRINE); // At the beginning of your upkeep, target opponent discards a card for each Shrine you control. - Ability ability = new BeginningOfUpkeepTriggeredAbility(new DiscardTargetEffect(xValue)).addHint(hint); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new DiscardTargetEffect(ShrinesYouControlCount.FOR_EACH)).addHint(ShrinesYouControlCount.getHint()); ability.addTarget(new TargetOpponent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HondenOfSeeingWinds.java b/Mage.Sets/src/mage/cards/h/HondenOfSeeingWinds.java index b033db25dbe..2b096f91c2f 100644 --- a/Mage.Sets/src/mage/cards/h/HondenOfSeeingWinds.java +++ b/Mage.Sets/src/mage/cards/h/HondenOfSeeingWinds.java @@ -1,19 +1,13 @@ - - package mage.cards.h; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterControlledPermanent; import java.util.UUID; @@ -22,19 +16,13 @@ import java.util.UUID; */ public final class HondenOfSeeingWinds extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( - new FilterControlledPermanent(SubType.SHRINE) - ); - private static final Hint hint = new ValueHint("Shrines you control", xValue); - public HondenOfSeeingWinds(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SHRINE); - // At the beginning of your upkeep, draw a card for each Shrine you control. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(xValue)).addHint(hint)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(ShrinesYouControlCount.FOR_EACH)).addHint(ShrinesYouControlCount.getHint())); } private HondenOfSeeingWinds(final HondenOfSeeingWinds card) { diff --git a/Mage.Sets/src/mage/cards/k/KyoshiIslandPlaza.java b/Mage.Sets/src/mage/cards/k/KyoshiIslandPlaza.java new file mode 100644 index 00000000000..6bfd4c5fe3c --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KyoshiIslandPlaza.java @@ -0,0 +1,76 @@ +package mage.cards.k; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +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.filter.StaticFilters; +import mage.game.Game; +import mage.target.common.TargetCardInLibrary; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KyoshiIslandPlaza extends CardImpl { + + public KyoshiIslandPlaza(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.SHRINE); + + // When Kyoshi Island Plaza enters, search your library for up to X basic land cards, where X is the number of Shrines you control. Put those cards onto the battlefield tapped, then shuffle. + this.addAbility(new EntersBattlefieldTriggeredAbility(new KyoshiIslandPlazaEffect()) + .addHint(ShrinesYouControlCount.getHint())); + + // Whenever another Shrine you control enters, search your library for a basic land card, put it onto the battlefield tapped, then shuffle. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new SearchLibraryPutInPlayEffect( + new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true + ), StaticFilters.FILTER_ANOTHER_CONTROLLED_SHRINE)); + } + + private KyoshiIslandPlaza(final KyoshiIslandPlaza card) { + super(card); + } + + @Override + public KyoshiIslandPlaza copy() { + return new KyoshiIslandPlaza(this); + } +} + +class KyoshiIslandPlazaEffect extends OneShotEffect { + + KyoshiIslandPlazaEffect() { + super(Outcome.Benefit); + staticText = "search your library for up to X basic land cards, where X is the number of Shrines you control. " + + "Put those cards onto the battlefield tapped, then shuffle"; + } + + private KyoshiIslandPlazaEffect(final KyoshiIslandPlazaEffect effect) { + super(effect); + } + + @Override + public KyoshiIslandPlazaEffect copy() { + return new KyoshiIslandPlazaEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int count = ShrinesYouControlCount.WHERE_X.calculate(game, source, this); + return new SearchLibraryPutInPlayEffect( + new TargetCardInLibrary(0, count, StaticFilters.FILTER_CARD_BASIC_LANDS), true + ).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NorthernAirTemple.java b/Mage.Sets/src/mage/cards/n/NorthernAirTemple.java index 6187b83987f..6f92b379e66 100644 --- a/Mage.Sets/src/mage/cards/n/NorthernAirTemple.java +++ b/Mage.Sets/src/mage/cards/n/NorthernAirTemple.java @@ -3,20 +3,15 @@ package mage.cards.n; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeOpponentsEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; 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.FilterControlledPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import java.util.UUID; @@ -25,14 +20,6 @@ import java.util.UUID; */ public final class NorthernAirTemple extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.SHRINE), null); - private static final Hint hint = new ValueHint("Shrines you control", xValue); - private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SHRINE, "another Shrine you control"); - - static { - filter.add(AnotherPredicate.instance); - } - public NorthernAirTemple(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}"); @@ -40,13 +27,13 @@ public final class NorthernAirTemple extends CardImpl { this.subtype.add(SubType.SHRINE); // When Northern Air Temple enters, each opponent loses X life and you gain X life, where X is the number of Shrines you control. - Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeOpponentsEffect(xValue) + Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeOpponentsEffect(ShrinesYouControlCount.WHERE_X) .setText("each opponent loses X life")); - ability.addEffect(new GainLifeEffect(xValue).concatBy("and")); - this.addAbility(ability.addHint(hint)); + ability.addEffect(new GainLifeEffect(ShrinesYouControlCount.WHERE_X).setText("and you gain X life, where X is the number of Shrines you control")); + this.addAbility(ability.addHint(ShrinesYouControlCount.getHint())); // Whenever another Shrine you control enters, each opponent loses 1 life and you gain 1 life. - ability = new EntersBattlefieldAllTriggeredAbility(new LoseLifeOpponentsEffect(1), filter); + ability = new EntersBattlefieldAllTriggeredAbility(new LoseLifeOpponentsEffect(1), StaticFilters.FILTER_ANOTHER_CONTROLLED_SHRINE); ability.addEffect(new GainLifeEffect(1).concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfAll.java b/Mage.Sets/src/mage/cards/s/SanctumOfAll.java index c82143cf4e6..ddbfa2bead4 100644 --- a/Mage.Sets/src/mage/cards/s/SanctumOfAll.java +++ b/Mage.Sets/src/mage/cards/s/SanctumOfAll.java @@ -1,22 +1,15 @@ package mage.cards.s; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.search.SearchLibraryGraveyardPutOntoBattlefieldEffect; -import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.SuperType; +import mage.constants.*; import mage.filter.FilterCard; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledPermanent; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -24,18 +17,13 @@ import mage.game.permanent.Permanent; import java.util.UUID; /** - * * @author htrajan */ public final class SanctumOfAll extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); private static final FilterCard filterCard = new FilterCard("Shrine card"); - static final PermanentsOnBattlefieldCount count = new PermanentsOnBattlefieldCount(filter); - static { - filter.add(SubType.SHRINE.getPredicate()); filterCard.add(SubType.SHRINE.getPredicate()); } @@ -49,7 +37,7 @@ public final class SanctumOfAll extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SearchLibraryGraveyardPutOntoBattlefieldEffect(filterCard), true)); // If an ability of another Shrine you control triggers while you control six or more Shrines, that ability triggers an additional time. - this.addAbility(new SimpleStaticAbility(new SanctumOfAllTriggerEffect()).addHint(new ValueHint("Shrines you control", count))); + this.addAbility(new SimpleStaticAbility(new SanctumOfAllTriggerEffect()).addHint(ShrinesYouControlCount.getHint())); } private SanctumOfAll(final SanctumOfAll card) { @@ -94,7 +82,7 @@ class SanctumOfAllTriggerEffect extends ReplacementEffectImpl { // Only triggers of the controller of Sanctum of All if (source.isControlledBy(event.getPlayerId())) { // Only trigger while you control six or more Shrines - int numShrines = SanctumOfAll.count.calculate(game, source, this); + int numShrines = ShrinesYouControlCount.FOR_EACH.calculate(game, source, this); if (numShrines >= 6) { // Only for triggers of other Shrines Permanent permanent = game.getPermanent(event.getSourceId()); diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfCalmWaters.java b/Mage.Sets/src/mage/cards/s/SanctumOfCalmWaters.java index 1f4696f4578..e4c6560fe95 100644 --- a/Mage.Sets/src/mage/cards/s/SanctumOfCalmWaters.java +++ b/Mage.Sets/src/mage/cards/s/SanctumOfCalmWaters.java @@ -1,34 +1,23 @@ package mage.cards.s; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.discard.DiscardControllerEffect; -import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility; 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.FilterControlledPermanent; import java.util.UUID; /** * @author jmharmon */ - public final class SanctumOfCalmWaters extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); - private static final PermanentsOnBattlefieldCount xValue = new PermanentsOnBattlefieldCount(filter); - - static { - filter.add(SubType.SHRINE.getPredicate()); - } - public SanctumOfCalmWaters(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}"); @@ -36,10 +25,9 @@ public final class SanctumOfCalmWaters extends CardImpl { this.subtype.add(SubType.SHRINE); // At the beginning of your precombat main phase, you may draw X cards, where X is the number of Shrines you control. If you do, discard a card. - Ability ability = new BeginningOfFirstMainTriggeredAbility(new DrawCardSourceControllerEffect(xValue) - .setText("you may draw X cards, where X is the number of Shrines you control"), true - ) - .addHint(new ValueHint("Shrines you control", xValue)); + Ability ability = new BeginningOfFirstMainTriggeredAbility( + new DrawCardSourceControllerEffect(ShrinesYouControlCount.WHERE_X), true + ).addHint(ShrinesYouControlCount.getHint()); ability.addEffect(new DiscardControllerEffect(1).setText("If you do, discard a card")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfFruitfulHarvest.java b/Mage.Sets/src/mage/cards/s/SanctumOfFruitfulHarvest.java index 049e03d2f0f..8e8767a1feb 100644 --- a/Mage.Sets/src/mage/cards/s/SanctumOfFruitfulHarvest.java +++ b/Mage.Sets/src/mage/cards/s/SanctumOfFruitfulHarvest.java @@ -1,48 +1,33 @@ package mage.cards.s; import mage.Mana; -import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.mana.DynamicManaEffect; -import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility; 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.FilterControlledPermanent; import java.util.UUID; /** - * * @author htrajan */ public final class SanctumOfFruitfulHarvest extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); - private static final PermanentsOnBattlefieldCount xValue = new PermanentsOnBattlefieldCount(filter); - - static { - filter.add(SubType.SHRINE.getPredicate()); - } - public SanctumOfFruitfulHarvest(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SHRINE); // At the beginning of your precombat main phase, add X mana of any one color, where X is the number of Shrines you control. - this.addAbility(new BeginningOfFirstMainTriggeredAbility( - new DynamicManaEffect( - Mana.AnyMana(1), - xValue, - "add X mana of any one color, where X is the number of Shrines you control", - true) - ) - .addHint(new ValueHint("Shrines you control", xValue))); + this.addAbility(new BeginningOfFirstMainTriggeredAbility(new DynamicManaEffect( + Mana.AnyMana(1), ShrinesYouControlCount.WHERE_X, + "add X mana of any one color, where X is the number of Shrines you control", true + )).addHint(ShrinesYouControlCount.getHint())); } private SanctumOfFruitfulHarvest(final SanctumOfFruitfulHarvest card) { diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfShatteredHeights.java b/Mage.Sets/src/mage/cards/s/SanctumOfShatteredHeights.java index cfaafbf6305..6f62d277894 100644 --- a/Mage.Sets/src/mage/cards/s/SanctumOfShatteredHeights.java +++ b/Mage.Sets/src/mage/cards/s/SanctumOfShatteredHeights.java @@ -3,18 +3,15 @@ package mage.cards.s; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.DiscardTargetCost; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.DamageTargetEffect; -import mage.abilities.hint.ValueHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.FilterCard; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.target.common.TargetCardInHand; import mage.target.common.TargetCreatureOrPlaneswalker; @@ -28,12 +25,12 @@ import java.util.UUID; public final class SanctumOfShatteredHeights extends CardImpl { private static final FilterCard filter = new FilterCard("a land card or Shrine card"); - private static final FilterPermanent filterShrinesOnly = new FilterControlledPermanent("Shrine you control"); - private static final PermanentsOnBattlefieldCount xValue = new PermanentsOnBattlefieldCount(filterShrinesOnly); static { - filter.add(Predicates.or(CardType.LAND.getPredicate(), SubType.SHRINE.getPredicate())); - filterShrinesOnly.add(SubType.SHRINE.getPredicate()); + filter.add(Predicates.or( + CardType.LAND.getPredicate(), + SubType.SHRINE.getPredicate() + )); } public SanctumOfShatteredHeights(UUID ownerId, CardSetInfo setInfo) { @@ -43,10 +40,11 @@ public final class SanctumOfShatteredHeights extends CardImpl { this.subtype.add(SubType.SHRINE); // {1}, Discard a land card or Shrine card: Sanctum of Shattered Heights deals X damage to target creature or planeswalker, where X is the number of Shrines you control. - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(xValue) - .setText("{this} deals X damage to target creature or planeswalker, where X is the number of Shrines you control"), - new ManaCostsImpl<>("{1}")) - .addHint(new ValueHint("Shrines you control", xValue)); + Ability ability = new SimpleActivatedAbility( + new DamageTargetEffect(ShrinesYouControlCount.WHERE_X) + .setText("{this} deals X damage to target creature or planeswalker, where X is the number of Shrines you control"), + new GenericManaCost(1) + ).addHint(ShrinesYouControlCount.getHint()); ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter))); ability.addTarget(new TargetCreatureOrPlaneswalker()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfStoneFangs.java b/Mage.Sets/src/mage/cards/s/SanctumOfStoneFangs.java index b21aa11d119..b88130ad6f5 100644 --- a/Mage.Sets/src/mage/cards/s/SanctumOfStoneFangs.java +++ b/Mage.Sets/src/mage/cards/s/SanctumOfStoneFangs.java @@ -1,46 +1,34 @@ package mage.cards.s; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeOpponentsEffect; -import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility; 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.FilterControlledPermanent; import java.util.UUID; /** - * * @author htrajan */ public final class SanctumOfStoneFangs extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(""); - private static final PermanentsOnBattlefieldCount xValue = new PermanentsOnBattlefieldCount(filter, null); - - static { - filter.add(SubType.SHRINE.getPredicate()); - } - public SanctumOfStoneFangs(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SHRINE); // At the beginning of your precombat main phase, each opponent loses X life and you gain X life, where X is the number of Shrines you control. Ability ability = new BeginningOfFirstMainTriggeredAbility( - new LoseLifeOpponentsEffect(xValue).setText("each opponent loses X life") - ) - .addHint(new ValueHint("Shrines you control", xValue)); - ability.addEffect(new GainLifeEffect(xValue).setText("and you gain X life, where X is the number of Shrines you control")); + new LoseLifeOpponentsEffect(ShrinesYouControlCount.WHERE_X).setText("each opponent loses X life") + ).addHint(ShrinesYouControlCount.getHint()); + ability.addEffect(new GainLifeEffect(ShrinesYouControlCount.WHERE_X).setText("and you gain X life, where X is the number of Shrines you control")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfTranquilLight.java b/Mage.Sets/src/mage/cards/s/SanctumOfTranquilLight.java index ab18f92bf92..3edd1fe5766 100644 --- a/Mage.Sets/src/mage/cards/s/SanctumOfTranquilLight.java +++ b/Mage.Sets/src/mage/cards/s/SanctumOfTranquilLight.java @@ -4,19 +4,14 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.TapTargetEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; 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.FilterControlledPermanent; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; @@ -40,7 +35,7 @@ public final class SanctumOfTranquilLight extends CardImpl { ability.addEffect(new InfoEffect("This ability costs {1} less to activate for each Shrine you control")); ability.addTarget(new TargetCreaturePermanent()); ability.setCostAdjuster(SanctumOfTranquilLightAdjuster.instance); - this.addAbility(ability.addHint(SanctumOfTranquilLightAdjuster.getHint())); + this.addAbility(ability.addHint(ShrinesYouControlCount.getHint())); } private SanctumOfTranquilLight(final SanctumOfTranquilLight card) { @@ -56,19 +51,11 @@ public final class SanctumOfTranquilLight extends CardImpl { enum SanctumOfTranquilLightAdjuster implements CostAdjuster { instance; - private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SHRINE); - private static final DynamicValue count = new PermanentsOnBattlefieldCount(filter); - private static final Hint hint = new ValueHint("Shrines you control", count); - - public static Hint getHint() { - return hint; - } - @Override public void reduceCost(Ability ability, Game game) { Player controller = game.getPlayer(ability.getControllerId()); if (controller != null) { - CardUtil.reduceCost(ability, count.calculate(game, ability, null)); + CardUtil.reduceCost(ability, ShrinesYouControlCount.FOR_EACH.calculate(game, ability, null)); } } } diff --git a/Mage.Sets/src/mage/cards/s/SouthernAirTemple.java b/Mage.Sets/src/mage/cards/s/SouthernAirTemple.java index ce184fcb615..b73e9dd010f 100644 --- a/Mage.Sets/src/mage/cards/s/SouthernAirTemple.java +++ b/Mage.Sets/src/mage/cards/s/SouthernAirTemple.java @@ -2,21 +2,15 @@ package mage.cards.s; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.counter.AddCountersAllEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; 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.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; import java.util.UUID; @@ -25,14 +19,6 @@ import java.util.UUID; */ public final class SouthernAirTemple extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.SHRINE)); - private static final Hint hint = new ValueHint("Shrines you control", xValue); - private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SHRINE, "another Shrine you control"); - - static { - filter.add(AnotherPredicate.instance); - } - public SouthernAirTemple(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); @@ -41,13 +27,13 @@ public final class SouthernAirTemple extends CardImpl { // When Southern Air Temple enters, put X +1/+1 counters on each creature you control, where X is the number of Shrines you control. this.addAbility(new EntersBattlefieldTriggeredAbility(new AddCountersAllEffect( - CounterType.P1P1.createInstance(), xValue, StaticFilters.FILTER_CONTROLLED_CREATURE - ).setText("put X +1/+1 counters on each creature you control, where X is the number of Shrines you control")).addHint(hint)); + CounterType.P1P1.createInstance(), ShrinesYouControlCount.WHERE_X, StaticFilters.FILTER_CONTROLLED_CREATURE + ).setText("put X +1/+1 counters on each creature you control, where X is the number of Shrines you control")).addHint(ShrinesYouControlCount.getHint())); // Whenever another Shrine you control enters, put a +1/+1 counter on each creature you control. this.addAbility(new EntersBattlefieldAllTriggeredAbility(new AddCountersAllEffect( CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE - ), filter)); + ), StaticFilters.FILTER_ANOTHER_CONTROLLED_SHRINE)); } private SouthernAirTemple(final SouthernAirTemple card) { diff --git a/Mage.Sets/src/mage/cards/t/TheSpiritOasis.java b/Mage.Sets/src/mage/cards/t/TheSpiritOasis.java index 750985f58ae..555db17f626 100644 --- a/Mage.Sets/src/mage/cards/t/TheSpiritOasis.java +++ b/Mage.Sets/src/mage/cards/t/TheSpiritOasis.java @@ -2,19 +2,14 @@ package mage.cards.t; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.ShrinesYouControlCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; 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.FilterControlledPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import java.util.UUID; @@ -23,14 +18,6 @@ import java.util.UUID; */ public final class TheSpiritOasis extends CardImpl { - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.SHRINE)); - private static final Hint hint = new ValueHint("Shrines you control", xValue); - private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SHRINE, "another Shrine you control"); - - static { - filter.add(AnotherPredicate.instance); - } - public TheSpiritOasis(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); @@ -38,10 +25,10 @@ public final class TheSpiritOasis extends CardImpl { this.subtype.add(SubType.SHRINE); // When The Spirit Oasis enters, draw a card for each Shrine you control. - this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(xValue))); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(ShrinesYouControlCount.FOR_EACH))); // Whenever another Shrine you control enters, draw a card. - this.addAbility(new EntersBattlefieldAllTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new DrawCardSourceControllerEffect(1), StaticFilters.FILTER_ANOTHER_CONTROLLED_SHRINE)); } private TheSpiritOasis(final TheSpiritOasis card) { diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 4bb14ee9a0f..e6e834b21c0 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -198,6 +198,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Katara, the Fearless", 361, Rarity.RARE, mage.cards.k.KataraTheFearless.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Knowledge Seeker", 60, Rarity.UNCOMMON, mage.cards.k.KnowledgeSeeker.class)); cards.add(new SetCardInfo("Kyoshi Battle Fan", 257, Rarity.COMMON, mage.cards.k.KyoshiBattleFan.class)); + cards.add(new SetCardInfo("Kyoshi Island Plaza", 184, Rarity.UNCOMMON, mage.cards.k.KyoshiIslandPlaza.class)); cards.add(new SetCardInfo("Kyoshi Village", 271, Rarity.COMMON, mage.cards.k.KyoshiVillage.class)); cards.add(new SetCardInfo("Kyoshi Warriors", 26, Rarity.COMMON, mage.cards.k.KyoshiWarriors.class)); cards.add(new SetCardInfo("Leaves from the Vine", 185, Rarity.UNCOMMON, mage.cards.l.LeavesFromTheVine.class)); diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ShrinesYouControlCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ShrinesYouControlCount.java new file mode 100644 index 00000000000..10c4b2ef290 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ShrinesYouControlCount.java @@ -0,0 +1,55 @@ +package mage.abilities.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; + +/** + * @author TheElk801 + */ +public enum ShrinesYouControlCount implements DynamicValue { + WHERE_X("X", "the number of Shrines you control"), + FOR_EACH("1", "Shrine you control"); + + private static final Hint hint = new ValueHint("Shrines you control", WHERE_X); + + public static Hint getHint() { + return hint; + } + + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SHRINE); + + private final String number; + private final String message; + + ShrinesYouControlCount(String number, String message) { + this.number = number; + this.message = message; + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return game.getBattlefield().count(filter, sourceAbility.getControllerId(), sourceAbility, game); + } + + @Override + public ShrinesYouControlCount copy() { + return this; + } + + @Override + public String getMessage() { + return message; + } + + @Override + public String toString() { + return number; + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/GainLifeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/GainLifeEffect.java index 67307e1916b..a49c919887c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/GainLifeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/GainLifeEffect.java @@ -54,6 +54,7 @@ public class GainLifeEffect extends OneShotEffect { @Override public String getText(Mode mode) { + // TODO: this text generation probably needs reworking if (staticText != null && !staticText.isEmpty()) { return staticText; } diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 748c56a2dec..01547efbb0b 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -902,6 +902,13 @@ public final class StaticFilters { FILTER_CONTROLLED_SAMURAI_OR_WARRIOR.setLockedFilter(true); } + public static final FilterControlledPermanent FILTER_ANOTHER_CONTROLLED_SHRINE = new FilterControlledPermanent(SubType.SHRINE, "another Shrine you control"); + + static { + FILTER_ANOTHER_CONTROLLED_SHRINE.add(AnotherPredicate.instance); + FILTER_ANOTHER_CONTROLLED_SHRINE.setLockedFilter(true); + } + public static final FilterPlaneswalkerPermanent FILTER_PERMANENT_PLANESWALKER = new FilterPlaneswalkerPermanent(); static { -- 2.47.2 From c0e10f05696232e0c87b1b87cb6afd282db5c3ee Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 10:17:13 -0500 Subject: [PATCH 240/261] [TLA] Implement Lo and Li, Twin Tutors --- .../src/mage/cards/l/LoAndLiTwinTutors.java | 75 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 76 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LoAndLiTwinTutors.java diff --git a/Mage.Sets/src/mage/cards/l/LoAndLiTwinTutors.java b/Mage.Sets/src/mage/cards/l/LoAndLiTwinTutors.java new file mode 100644 index 00000000000..0a7fd5d7a44 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LoAndLiTwinTutors.java @@ -0,0 +1,75 @@ +package mage.cards.l; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterNonlandCard; +import mage.filter.predicate.Predicates; +import mage.target.common.TargetCardInLibrary; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class LoAndLiTwinTutors extends CardImpl { + + private static final FilterCard filter = new FilterCard("a Lesson or Noble card"); + private static final FilterPermanent filter2 = new FilterCreaturePermanent(SubType.NOBLE, ""); + private static final FilterNonlandCard filter3 = new FilterNonlandCard("Lesson spells you control"); + + static { + filter.add(Predicates.or( + SubType.LESSON.getPredicate(), + SubType.NOBLE.getPredicate() + )); + filter3.add(SubType.LESSON.getPredicate()); + } + + public LoAndLiTwinTutors(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ADVISOR); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Lo and Li enter, search your library for a Lesson or Noble card, reveal it, put it into your hand, then shuffle. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true) + ).setTriggerPhrase("When {this} enter, ")); + + // Noble creatures you control and Lesson spells you control have lifelink. + Ability ability = new SimpleStaticAbility(new GainAbilityControlledEffect( + LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, filter2 + ).setText("Noble creatures you control")); + ability.addEffect(new GainAbilityControlledSpellsEffect( + LifelinkAbility.getInstance(), filter3 + ).concatBy("and")); + this.addAbility(ability); + } + + private LoAndLiTwinTutors(final LoAndLiTwinTutors card) { + super(card); + } + + @Override + public LoAndLiTwinTutors copy() { + return new LoAndLiTwinTutors(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index e6e834b21c0..b587ea004e8 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -203,6 +203,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Kyoshi Warriors", 26, Rarity.COMMON, mage.cards.k.KyoshiWarriors.class)); cards.add(new SetCardInfo("Leaves from the Vine", 185, Rarity.UNCOMMON, mage.cards.l.LeavesFromTheVine.class)); cards.add(new SetCardInfo("Lightning Strike", 146, Rarity.COMMON, mage.cards.l.LightningStrike.class)); + cards.add(new SetCardInfo("Lo and Li, Twin Tutors", 108, Rarity.UNCOMMON, mage.cards.l.LoAndLiTwinTutors.class)); cards.add(new SetCardInfo("Long Feng, Grand Secretariat", 233, Rarity.UNCOMMON, mage.cards.l.LongFengGrandSecretariat.class)); cards.add(new SetCardInfo("Mai, Jaded Edge", 147, Rarity.UNCOMMON, mage.cards.m.MaiJadedEdge.class)); cards.add(new SetCardInfo("Mai, Scornful Striker", 109, Rarity.RARE, mage.cards.m.MaiScornfulStriker.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From f5ce27f6c82b6b98221281c8e2eb7a349ca56f31 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 10:18:47 -0500 Subject: [PATCH 241/261] [TLA] Implement Messenger Hawk --- Mage.Sets/src/mage/cards/m/MessengerHawk.java | 55 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 56 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MessengerHawk.java diff --git a/Mage.Sets/src/mage/cards/m/MessengerHawk.java b/Mage.Sets/src/mage/cards/m/MessengerHawk.java new file mode 100644 index 00000000000..a3255377265 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MessengerHawk.java @@ -0,0 +1,55 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.DrewTwoOrMoreCardsCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.dynamicvalue.common.CardsDrawnThisTurnDynamicValue; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.game.permanent.token.ClueArtifactToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MessengerHawk extends CardImpl { + + public MessengerHawk(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U/B}"); + + this.subtype.add(SubType.BIRD); + this.subtype.add(SubType.SCOUT); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When this creature enters, create a Clue token. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ClueArtifactToken()))); + + // This creature gets +2/+0 as long as you've drawn two or more cards this turn. + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new BoostSourceEffect(2, 0, Duration.WhileOnBattlefield), + DrewTwoOrMoreCardsCondition.instance, "{this} gets +2/+0 as long as you've drawn two or more cards this turn" + )).addHint(CardsDrawnThisTurnDynamicValue.getHint())); + } + + private MessengerHawk(final MessengerHawk card) { + super(card); + } + + @Override + public MessengerHawk copy() { + return new MessengerHawk(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b587ea004e8..22d503520e8 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -212,6 +212,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Master Piandao", 28, Rarity.UNCOMMON, mage.cards.m.MasterPiandao.class)); cards.add(new SetCardInfo("Meditation Pools", 272, Rarity.COMMON, mage.cards.m.MeditationPools.class)); cards.add(new SetCardInfo("Merchant of Many Hats", 110, Rarity.COMMON, mage.cards.m.MerchantOfManyHats.class)); + cards.add(new SetCardInfo("Messenger Hawk", 234, Rarity.COMMON, mage.cards.m.MessengerHawk.class)); cards.add(new SetCardInfo("Meteor Sword", 258, Rarity.UNCOMMON, mage.cards.m.MeteorSword.class)); cards.add(new SetCardInfo("Misty Palms Oasis", 273, Rarity.COMMON, mage.cards.m.MistyPalmsOasis.class)); cards.add(new SetCardInfo("Momo, Friendly Flier", 29, Rarity.RARE, mage.cards.m.MomoFriendlyFlier.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 096795be00a3f15abbab704fba2790532234919e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 10:25:39 -0500 Subject: [PATCH 242/261] [TLA] Implement Pirate Peddlers --- .../src/mage/cards/a/AmarethTheLustrous.java | 13 ++---- Mage.Sets/src/mage/cards/b/Bloodbriar.java | 14 ++---- .../mage/cards/c/CrystallineResonance.java | 10 +--- .../src/mage/cards/e/EstridTheMasked.java | 6 +-- .../src/mage/cards/f/FurnaceCelebration.java | 15 ++---- .../src/mage/cards/g/GixianInfiltrator.java | 11 +---- Mage.Sets/src/mage/cards/i/ImmovableRod.java | 11 +---- .../mage/cards/k/KorvoldFaeCursedKing.java | 13 ++---- .../mage/cards/m/MazirekKraulDeathPriest.java | 22 ++++----- .../src/mage/cards/p/PiratePeddlers.java | 46 +++++++++++++++++++ .../src/mage/cards/s/SorcerersBroom.java | 11 +---- Mage.Sets/src/mage/cards/s/SuperShredder.java | 11 +---- .../mage/cards/v/VitoFanaticOfAclazotz.java | 21 ++++----- .../src/mage/sets/AvatarTheLastAirbender.java | 1 + .../main/java/mage/filter/StaticFilters.java | 7 +++ 15 files changed, 97 insertions(+), 115 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/p/PiratePeddlers.java diff --git a/Mage.Sets/src/mage/cards/a/AmarethTheLustrous.java b/Mage.Sets/src/mage/cards/a/AmarethTheLustrous.java index 8cd758c8a31..4589a8833ec 100644 --- a/Mage.Sets/src/mage/cards/a/AmarethTheLustrous.java +++ b/Mage.Sets/src/mage/cards/a/AmarethTheLustrous.java @@ -10,8 +10,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.CardsImpl; import mage.constants.*; -import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -23,12 +22,6 @@ import java.util.UUID; */ public final class AmarethTheLustrous extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public AmarethTheLustrous(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{W}{U}"); @@ -41,7 +34,9 @@ public final class AmarethTheLustrous extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever another permanent you control enters, look at the top card of your library. If it shares a card type with that permanent, you may reveal that card and put it into your hand. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new AmarethTheLustrousEffect(), filter)); + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + new AmarethTheLustrousEffect(), StaticFilters.FILTER_ANOTHER_PERMANENT + )); } private AmarethTheLustrous(final AmarethTheLustrous card) { diff --git a/Mage.Sets/src/mage/cards/b/Bloodbriar.java b/Mage.Sets/src/mage/cards/b/Bloodbriar.java index c6792f5d9cb..859346ea148 100644 --- a/Mage.Sets/src/mage/cards/b/Bloodbriar.java +++ b/Mage.Sets/src/mage/cards/b/Bloodbriar.java @@ -9,32 +9,24 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; -import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import java.util.UUID; /** - * * @author LevelX2 */ public final class Bloodbriar extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public Bloodbriar(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.PLANT, SubType.ELEMENTAL); this.power = new MageInt(2); this.toughness = new MageInt(3); // Whenever you sacrifice another permanent, put a +1/+1 counter on Bloodbriar. this.addAbility(new SacrificePermanentTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), StaticFilters.FILTER_ANOTHER_PERMANENT )); } diff --git a/Mage.Sets/src/mage/cards/c/CrystallineResonance.java b/Mage.Sets/src/mage/cards/c/CrystallineResonance.java index 8167b56cd06..47339a11835 100644 --- a/Mage.Sets/src/mage/cards/c/CrystallineResonance.java +++ b/Mage.Sets/src/mage/cards/c/CrystallineResonance.java @@ -8,9 +8,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.target.TargetPermanent; import mage.util.functions.CopyApplier; @@ -22,12 +20,6 @@ import java.util.UUID; */ public final class CrystallineResonance extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public CrystallineResonance(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); @@ -54,7 +46,7 @@ public final class CrystallineResonance extends CardImpl { "except it has this ability" ), true ); - ability.addTarget(new TargetPermanent(filter)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_PERMANENT)); return ability; } } diff --git a/Mage.Sets/src/mage/cards/e/EstridTheMasked.java b/Mage.Sets/src/mage/cards/e/EstridTheMasked.java index 5449a95c129..1117674c1c6 100644 --- a/Mage.Sets/src/mage/cards/e/EstridTheMasked.java +++ b/Mage.Sets/src/mage/cards/e/EstridTheMasked.java @@ -10,9 +10,9 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterEnchantmentCard; import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.EnchantedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -28,11 +28,9 @@ import java.util.UUID; public final class EstridTheMasked extends CardImpl { private static final FilterPermanent filter = new FilterPermanent(); - private static final FilterPermanent filter2 = new FilterPermanent("another permanent"); static { filter.add(EnchantedPredicate.instance); - filter2.add(AnotherPredicate.instance); } public EstridTheMasked(UUID ownerId, CardSetInfo setInfo) { @@ -51,7 +49,7 @@ public final class EstridTheMasked extends CardImpl { Ability ability = new LoyaltyAbility( new EstridTheMaskedTokenEffect(), -1 ); - ability.addTarget(new TargetPermanent(filter2)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_PERMANENT)); this.addAbility(ability); // -7: Put the top seven cards of your library into your graveyard. Return all non-Aura enchantment cards from your graveyard to the battlefield, then do the same for Aura cards. diff --git a/Mage.Sets/src/mage/cards/f/FurnaceCelebration.java b/Mage.Sets/src/mage/cards/f/FurnaceCelebration.java index 484a37433a5..5ffc9e8dfca 100644 --- a/Mage.Sets/src/mage/cards/f/FurnaceCelebration.java +++ b/Mage.Sets/src/mage/cards/f/FurnaceCelebration.java @@ -8,30 +8,23 @@ import mage.abilities.effects.common.DoIfCostPaid; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import mage.target.common.TargetAnyTarget; import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public final class FurnaceCelebration extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public FurnaceCelebration(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{R}"); // Whenever you sacrifice another permanent, you may pay {2}. If you do, Furnace Celebration deals 2 damage to any target. Ability ability = new SacrificePermanentTriggeredAbility(new DoIfCostPaid( - new DamageTargetEffect(2), new GenericManaCost(2)), filter); + new DamageTargetEffect(2), new GenericManaCost(2) + ), StaticFilters.FILTER_ANOTHER_PERMANENT); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GixianInfiltrator.java b/Mage.Sets/src/mage/cards/g/GixianInfiltrator.java index 765dc60b4e5..741efdfca77 100644 --- a/Mage.Sets/src/mage/cards/g/GixianInfiltrator.java +++ b/Mage.Sets/src/mage/cards/g/GixianInfiltrator.java @@ -8,8 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; -import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import java.util.UUID; @@ -18,12 +17,6 @@ import java.util.UUID; */ public final class GixianInfiltrator extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public GixianInfiltrator(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); @@ -34,7 +27,7 @@ public final class GixianInfiltrator extends CardImpl { // Whenever you sacrifice another permanent, put a +1/+1 counter on Gixian Infiltrator. this.addAbility(new SacrificePermanentTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), StaticFilters.FILTER_ANOTHER_PERMANENT )); } diff --git a/Mage.Sets/src/mage/cards/i/ImmovableRod.java b/Mage.Sets/src/mage/cards/i/ImmovableRod.java index 49cc0385d2d..4aeda0b0973 100644 --- a/Mage.Sets/src/mage/cards/i/ImmovableRod.java +++ b/Mage.Sets/src/mage/cards/i/ImmovableRod.java @@ -13,8 +13,7 @@ import mage.abilities.keyword.InspiredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; @@ -26,12 +25,6 @@ import java.util.UUID; */ public final class ImmovableRod extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public ImmovableRod(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{W}"); @@ -46,7 +39,7 @@ public final class ImmovableRod extends CardImpl { Ability ability = new SimpleActivatedAbility(new ImmovableRodAbilityEffect(), new ManaCostsImpl<>("{3}{W}")); ability.addEffect(new ImmovableRodAttackBlockTargetEffect()); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetPermanent(filter)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_PERMANENT)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KorvoldFaeCursedKing.java b/Mage.Sets/src/mage/cards/k/KorvoldFaeCursedKing.java index f2fd40b4b93..d3771655893 100644 --- a/Mage.Sets/src/mage/cards/k/KorvoldFaeCursedKing.java +++ b/Mage.Sets/src/mage/cards/k/KorvoldFaeCursedKing.java @@ -14,9 +14,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; import mage.counters.CounterType; -import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.predicate.mageobject.AnotherPredicate; import java.util.UUID; @@ -25,12 +23,6 @@ import java.util.UUID; */ public final class KorvoldFaeCursedKing extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public KorvoldFaeCursedKing(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{R}{G}"); @@ -45,13 +37,14 @@ public final class KorvoldFaeCursedKing extends CardImpl { // Whenever Korvold, Fae-Cursed King enters the battlefield or attacks, sacrifice another permanent. this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility( - new SacrificeControllerEffect(filter, 1, "") + new SacrificeControllerEffect(StaticFilters.FILTER_ANOTHER_PERMANENT, 1, "") )); // Whenever you sacrifice a permanent, put a +1/+1 counter on Korvold and draw a card. Ability ability = new SacrificePermanentTriggeredAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance()), - StaticFilters.FILTER_PERMANENT); + StaticFilters.FILTER_PERMANENT + ); ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MazirekKraulDeathPriest.java b/Mage.Sets/src/mage/cards/m/MazirekKraulDeathPriest.java index 111ba402199..8d458e37df1 100644 --- a/Mage.Sets/src/mage/cards/m/MazirekKraulDeathPriest.java +++ b/Mage.Sets/src/mage/cards/m/MazirekKraulDeathPriest.java @@ -6,28 +6,22 @@ import mage.abilities.effects.common.counter.AddCountersAllEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; import mage.counters.CounterType; -import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.predicate.mageobject.AnotherPredicate; import java.util.UUID; /** - * * @author fireshoes */ public final class MazirekKraulDeathPriest extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public MazirekKraulDeathPriest(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{G}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.INSECT); this.subtype.add(SubType.SHAMAN); @@ -38,9 +32,9 @@ public final class MazirekKraulDeathPriest extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever a player sacrifices another permanent, put a +1/+1 counter on each creature you control. - this.addAbility(new SacrificePermanentTriggeredAbility(Zone.BATTLEFIELD, - new AddCountersAllEffect(CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE), - filter, TargetController.ANY, SetTargetPointer.NONE, false)); + this.addAbility(new SacrificePermanentTriggeredAbility(new AddCountersAllEffect( + CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE + ), StaticFilters.FILTER_ANOTHER_PERMANENT, TargetController.ANY)); } private MazirekKraulDeathPriest(final MazirekKraulDeathPriest card) { diff --git a/Mage.Sets/src/mage/cards/p/PiratePeddlers.java b/Mage.Sets/src/mage/cards/p/PiratePeddlers.java new file mode 100644 index 00000000000..1eff54a0024 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PiratePeddlers.java @@ -0,0 +1,46 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.common.SacrificePermanentTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class PiratePeddlers extends CardImpl { + + public PiratePeddlers(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.PIRATE); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // Whenever you sacrifice another permanent, put a +1/+1 counter on this creature. + this.addAbility(new SacrificePermanentTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), StaticFilters.FILTER_ANOTHER_PERMANENT + )); + } + + private PiratePeddlers(final PiratePeddlers card) { + super(card); + } + + @Override + public PiratePeddlers copy() { + return new PiratePeddlers(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SorcerersBroom.java b/Mage.Sets/src/mage/cards/s/SorcerersBroom.java index e4511c9179c..d2a3e0c89b8 100644 --- a/Mage.Sets/src/mage/cards/s/SorcerersBroom.java +++ b/Mage.Sets/src/mage/cards/s/SorcerersBroom.java @@ -9,8 +9,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import java.util.UUID; @@ -19,12 +18,6 @@ import java.util.UUID; */ public final class SorcerersBroom extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public SorcerersBroom(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}"); @@ -35,7 +28,7 @@ public final class SorcerersBroom extends CardImpl { // Whenever you sacrifice another permanent, you may pay {3}. If you do, create a token that's a copy of Sorcerer's Broom. this.addAbility(new SacrificePermanentTriggeredAbility( new DoIfCostPaid(new CreateTokenCopySourceEffect(), new GenericManaCost(3)), - filter + StaticFilters.FILTER_ANOTHER_PERMANENT )); } diff --git a/Mage.Sets/src/mage/cards/s/SuperShredder.java b/Mage.Sets/src/mage/cards/s/SuperShredder.java index 13f72b0e6dc..d76f9999635 100644 --- a/Mage.Sets/src/mage/cards/s/SuperShredder.java +++ b/Mage.Sets/src/mage/cards/s/SuperShredder.java @@ -10,8 +10,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; import mage.counters.CounterType; -import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import java.util.UUID; @@ -20,12 +19,6 @@ import java.util.UUID; */ public final class SuperShredder extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public SuperShredder(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); @@ -41,7 +34,7 @@ public final class SuperShredder extends CardImpl { // Whenever another permanent leaves the battlefield, put a +1/+1 counter on Super Shredder. this.addAbility(new LeavesBattlefieldAllTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), StaticFilters.FILTER_ANOTHER_PERMANENT )); } diff --git a/Mage.Sets/src/mage/cards/v/VitoFanaticOfAclazotz.java b/Mage.Sets/src/mage/cards/v/VitoFanaticOfAclazotz.java index 602f5b141ec..7be536253ce 100644 --- a/Mage.Sets/src/mage/cards/v/VitoFanaticOfAclazotz.java +++ b/Mage.Sets/src/mage/cards/v/VitoFanaticOfAclazotz.java @@ -3,13 +3,18 @@ package mage.cards.v; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SacrificePermanentTriggeredAbility; -import mage.abilities.effects.common.*; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.IfAbilityHasResolvedXTimesEffect; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; import mage.game.permanent.token.VampireDemonToken; import mage.watchers.common.AbilityResolvedWatcher; @@ -20,12 +25,6 @@ import java.util.UUID; */ public final class VitoFanaticOfAclazotz extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another permanent"); - - static { - filter.add(AnotherPredicate.instance); - } - public VitoFanaticOfAclazotz(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{B}"); @@ -43,7 +42,7 @@ public final class VitoFanaticOfAclazotz extends CardImpl { new IfAbilityHasResolvedXTimesEffect( Outcome.GainLife, 1, new GainLifeEffect(2) ).setText("you gain 2 life if this is the first time this ability has resolved this turn"), - filter + StaticFilters.FILTER_ANOTHER_PERMANENT ); ability.addEffect( new IfAbilityHasResolvedXTimesEffect( diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 22d503520e8..0f95ff6baeb 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -237,6 +237,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Ozai, the Phoenix King", 335, Rarity.MYTHIC, mage.cards.o.OzaiThePhoenixKing.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Path to Redemption", 31, Rarity.COMMON, mage.cards.p.PathToRedemption.class)); cards.add(new SetCardInfo("Pillar Launch", 189, Rarity.COMMON, mage.cards.p.PillarLaunch.class)); + cards.add(new SetCardInfo("Pirate Peddlers", 115, Rarity.COMMON, mage.cards.p.PiratePeddlers.class)); cards.add(new SetCardInfo("Plains", 282, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 287, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Plains", 292, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 01547efbb0b..83ff2fb5d20 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -601,6 +601,13 @@ public final class StaticFilters { FILTER_OPPONENTS_PERMANENT_ARTIFACT_OR_CREATURE.setLockedFilter(true); } + public static final FilterPermanent FILTER_ANOTHER_PERMANENT = new FilterPermanent("another permanent"); + + static { + FILTER_ANOTHER_PERMANENT.add(AnotherPredicate.instance); + FILTER_ANOTHER_PERMANENT.setLockedFilter(true); + } + public static final FilterCreaturePermanent FILTER_ANOTHER_CREATURE = new FilterCreaturePermanent("another creature"); static { -- 2.47.2 From d63b816a5f088baadd80a952bc2cc5baac1a52a4 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 10:31:11 -0500 Subject: [PATCH 243/261] [TLA] Implement Teo, Spirited Glider --- .../src/mage/cards/t/TeoSpiritedGlider.java | 100 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 101 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TeoSpiritedGlider.java diff --git a/Mage.Sets/src/mage/cards/t/TeoSpiritedGlider.java b/Mage.Sets/src/mage/cards/t/TeoSpiritedGlider.java new file mode 100644 index 00000000000..9f54102d33d --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TeoSpiritedGlider.java @@ -0,0 +1,100 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; +import mage.abilities.common.delayed.ReflexiveTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +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; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TeoSpiritedGlider extends CardImpl { + + public TeoSpiritedGlider(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.PILOT); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever one or more creatures you control with flying attack, draw a card, then discard a card. When you discard a nonland card this way, put a +1/+1 counter on target creature you control. + Ability ability = new AttacksWithCreaturesTriggeredAbility( + new DrawCardSourceControllerEffect(1), + 1, StaticFilters.FILTER_CREATURE_FLYING + ).setTriggerPhrase("Whenever one or more creatures you control with flying attack, "); + ability.addEffect(new TeoSpiritedGliderEffect()); + this.addAbility(ability); + } + + private TeoSpiritedGlider(final TeoSpiritedGlider card) { + super(card); + } + + @Override + public TeoSpiritedGlider copy() { + return new TeoSpiritedGlider(this); + } +} + +class TeoSpiritedGliderEffect extends OneShotEffect { + + TeoSpiritedGliderEffect() { + super(Outcome.Benefit); + staticText = ", then discard a card. When you discard a nonland card this way, " + + "put a +1/+1 counter on target creature you control"; + } + + private TeoSpiritedGliderEffect(final TeoSpiritedGliderEffect effect) { + super(effect); + } + + @Override + public TeoSpiritedGliderEffect copy() { + return new TeoSpiritedGliderEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Card card = player.discardOne(false, false, source, game); + if (card == null) { + return false; + } + if (card.isLand(game)) { + return true; + } + ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false + ); + ability.addTarget(new TargetControlledCreaturePermanent()); + game.fireReflexiveTriggeredAbility(ability, source); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 0f95ff6baeb..9655ec70f32 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -290,6 +290,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Swamp", 289, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swamp", 294, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swampsnare Trap", 120, Rarity.COMMON, mage.cards.s.SwampsnareTrap.class)); + cards.add(new SetCardInfo("Teo, Spirited Glider", 74, Rarity.UNCOMMON, mage.cards.t.TeoSpiritedGlider.class)); cards.add(new SetCardInfo("The Boulder, Ready to Rumble", 168, Rarity.UNCOMMON, mage.cards.t.TheBoulderReadyToRumble.class)); cards.add(new SetCardInfo("The Cave of Two Lovers", 126, Rarity.UNCOMMON, mage.cards.t.TheCaveOfTwoLovers.class)); cards.add(new SetCardInfo("The Lion-Turtle", 232, Rarity.RARE, mage.cards.t.TheLionTurtle.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 3c3b6b435309a507c0bacada6f3d3b04523bdeb2 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 10:33:48 -0500 Subject: [PATCH 244/261] [TLA] Implement Walltop Sentries --- .../src/mage/cards/w/WalltopSentries.java | 50 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 51 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/w/WalltopSentries.java diff --git a/Mage.Sets/src/mage/cards/w/WalltopSentries.java b/Mage.Sets/src/mage/cards/w/WalltopSentries.java new file mode 100644 index 00000000000..27a43ef954c --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WalltopSentries.java @@ -0,0 +1,50 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.condition.common.LessonsInGraveCondition; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WalltopSentries extends CardImpl { + + public WalltopSentries(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // When this creature dies, if there's a Lesson card in your graveyard, you gain 2 life. + this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(2)) + .withInterveningIf(LessonsInGraveCondition.ONE) + .addHint(LessonsInGraveCondition.getHint())); + } + + private WalltopSentries(final WalltopSentries card) { + super(card); + } + + @Override + public WalltopSentries copy() { + return new WalltopSentries(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 9655ec70f32..d1b0af177cb 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -322,6 +322,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("United Front", 331, Rarity.MYTHIC, mage.cards.u.UnitedFront.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("United Front", 39, Rarity.MYTHIC, mage.cards.u.UnitedFront.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Vindictive Warden", 249, Rarity.COMMON, mage.cards.v.VindictiveWarden.class)); + cards.add(new SetCardInfo("Walltop Sentries", 202, Rarity.COMMON, mage.cards.w.WalltopSentries.class)); cards.add(new SetCardInfo("Wandering Musicians", 250, Rarity.COMMON, mage.cards.w.WanderingMusicians.class)); cards.add(new SetCardInfo("War Balloon", 159, Rarity.UNCOMMON, mage.cards.w.WarBalloon.class)); cards.add(new SetCardInfo("Water Tribe Captain", 41, Rarity.COMMON, mage.cards.w.WaterTribeCaptain.class)); -- 2.47.2 From 74f7a4fcbe423a0e4dddff7bfb63496c99302cf0 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 10:37:58 -0500 Subject: [PATCH 245/261] [TLA] Implement Waterbender Ascension --- .../mage/cards/w/WaterbenderAscension.java | 58 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 60 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/w/WaterbenderAscension.java diff --git a/Mage.Sets/src/mage/cards/w/WaterbenderAscension.java b/Mage.Sets/src/mage/cards/w/WaterbenderAscension.java new file mode 100644 index 00000000000..1530dd67eb2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WaterbenderAscension.java @@ -0,0 +1,58 @@ +package mage.cards.w; + +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.common.WaterbendCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SetTargetPointer; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WaterbenderAscension extends CardImpl { + + private static final Condition condition = new SourceHasCounterCondition(CounterType.QUEST, 4); + + public WaterbenderAscension(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); + + // Whenever a creature you control deals combat damage to a player, put a quest counter on this enchantment. Then if it has four or more quest counters on it, draw a card. + Ability ability = new DealsDamageToAPlayerAllTriggeredAbility( + new AddCountersSourceEffect(CounterType.QUEST.createInstance()), + StaticFilters.FILTER_CONTROLLED_CREATURE, false, SetTargetPointer.NONE, true + ); + ability.addEffect(new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(1), condition, + "Then if it has four or more quest counters on it, draw a card" + )); + this.addAbility(ability); + + // Waterbend {4}: Target creature can't be blocked this turn. + ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new WaterbendCost(4)); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + private WaterbenderAscension(final WaterbenderAscension card) { + super(card); + } + + @Override + public WaterbenderAscension copy() { + return new WaterbenderAscension(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index d1b0af177cb..31a61609bd2 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -327,6 +327,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("War Balloon", 159, Rarity.UNCOMMON, mage.cards.w.WarBalloon.class)); cards.add(new SetCardInfo("Water Tribe Captain", 41, Rarity.COMMON, mage.cards.w.WaterTribeCaptain.class)); cards.add(new SetCardInfo("Water Tribe Rallier", 42, Rarity.UNCOMMON, mage.cards.w.WaterTribeRallier.class)); + cards.add(new SetCardInfo("Waterbender Ascension", 310, Rarity.RARE, mage.cards.w.WaterbenderAscension.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Waterbender Ascension", 79, Rarity.RARE, mage.cards.w.WaterbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); cards.add(new SetCardInfo("Watery Grasp", 82, Rarity.COMMON, mage.cards.w.WateryGrasp.class)); cards.add(new SetCardInfo("White Lotus Reinforcements", 251, Rarity.UNCOMMON, mage.cards.w.WhiteLotusReinforcements.class)); -- 2.47.2 From 70444ba7de249142e990459b7c4db7604c622c4e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 10:41:23 -0500 Subject: [PATCH 246/261] [TLA] Implement Waterbending Scroll --- .../src/mage/cards/w/WaterbendingScroll.java | 63 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 64 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/w/WaterbendingScroll.java diff --git a/Mage.Sets/src/mage/cards/w/WaterbendingScroll.java b/Mage.Sets/src/mage/cards/w/WaterbendingScroll.java new file mode 100644 index 00000000000..38465a00dc7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WaterbendingScroll.java @@ -0,0 +1,63 @@ +package mage.cards.w; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.CostAdjuster; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WaterbendingScroll extends CardImpl { + + public WaterbendingScroll(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{U}"); + + // {6}, {T}: Draw a card. This ability costs {1} less to activate for each Island you control. + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(6)); + ability.addCost(new TapSourceCost()); + ability.addEffect(new InfoEffect("This ability costs {1} less to activate for each Island you control")); + this.addAbility(ability.setCostAdjuster(WaterbendingScrollAdjuster.instance).addHint(WaterbendingScrollAdjuster.getHint())); + } + + private WaterbendingScroll(final WaterbendingScroll card) { + super(card); + } + + @Override + public WaterbendingScroll copy() { + return new WaterbendingScroll(this); + } +} + +enum WaterbendingScrollAdjuster implements CostAdjuster { + instance; + private static final DynamicValue cardsCount = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.ISLAND)); + private static final Hint hint = new ValueHint("Islands you control", cardsCount); + + static Hint getHint() { + return hint; + } + + @Override + public void reduceCost(Ability ability, Game game) { + int count = cardsCount.calculate(game, ability, null); + CardUtil.reduceCost(ability, count); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 31a61609bd2..8b44d6a3ac8 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -330,6 +330,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Waterbender Ascension", 310, Rarity.RARE, mage.cards.w.WaterbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Waterbender Ascension", 79, Rarity.RARE, mage.cards.w.WaterbenderAscension.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Waterbending Lesson", 80, Rarity.COMMON, mage.cards.w.WaterbendingLesson.class)); + cards.add(new SetCardInfo("Waterbending Scroll", 81, Rarity.UNCOMMON, mage.cards.w.WaterbendingScroll.class)); cards.add(new SetCardInfo("Watery Grasp", 82, Rarity.COMMON, mage.cards.w.WateryGrasp.class)); cards.add(new SetCardInfo("White Lotus Reinforcements", 251, Rarity.UNCOMMON, mage.cards.w.WhiteLotusReinforcements.class)); cards.add(new SetCardInfo("White Lotus Tile", 262, Rarity.MYTHIC, mage.cards.w.WhiteLotusTile.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From d7b5c21894ad90668397ab7591357e55a880b78c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 10:50:21 -0500 Subject: [PATCH 247/261] [TLA] Implement Zhao, the Moon Slayer --- Mage.Sets/src/mage/cards/b/BloodMoon.java | 65 +----------------- .../src/mage/cards/m/MagusOfTheMoon.java | 67 ++----------------- .../src/mage/cards/z/ZhaoTheMoonSlayer.java | 66 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + .../NonbasicLandsAreMountainsEffect.java | 45 +++++++++++++ .../main/java/mage/counters/CounterType.java | 1 + 6 files changed, 121 insertions(+), 125 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/z/ZhaoTheMoonSlayer.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/continuous/NonbasicLandsAreMountainsEffect.java diff --git a/Mage.Sets/src/mage/cards/b/BloodMoon.java b/Mage.Sets/src/mage/cards/b/BloodMoon.java index 40b3f9a2b23..04ef447040d 100644 --- a/Mage.Sets/src/mage/cards/b/BloodMoon.java +++ b/Mage.Sets/src/mage/cards/b/BloodMoon.java @@ -1,16 +1,10 @@ package mage.cards.b; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.mana.RedManaAbility; +import mage.abilities.effects.common.continuous.NonbasicLandsAreMountainsEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.common.FilterLandPermanent; -import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.CardType; import java.util.UUID; @@ -23,7 +17,7 @@ public final class BloodMoon extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // Nonbasic lands are Mountains. - this.addAbility(new SimpleStaticAbility(new BloodMoonEffect())); + this.addAbility(new SimpleStaticAbility(new NonbasicLandsAreMountainsEffect())); } private BloodMoon(final BloodMoon card) { @@ -34,57 +28,4 @@ public final class BloodMoon extends CardImpl { public BloodMoon copy() { return new BloodMoon(this); } - - static class BloodMoonEffect extends ContinuousEffectImpl { - - private static final FilterLandPermanent filter = new FilterLandPermanent(); - - static { - filter.add(Predicates.not(SuperType.BASIC.getPredicate())); - } - - BloodMoonEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); - this.staticText = "Nonbasic lands are Mountains"; - this.dependencyTypes.add(DependencyType.BecomeMountain); - this.dependendToTypes.add(DependencyType.BecomeNonbasicLand); - } - - private BloodMoonEffect(final BloodMoonEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public BloodMoonEffect copy() { - return new BloodMoonEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent land : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { - switch (layer) { - case TypeChangingEffects_4: - // 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects - // So the ability removing has to be done before Layer 6 - // Lands have their mana ability intrinsically, so that is added in layer 4 - land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); - land.addSubType(game, SubType.MOUNTAIN); - land.removeAllAbilities(source.getSourceId(), game); - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - break; - } - } - return true; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } - } } diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java b/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java index e07c277a4e8..2fa259f8e8f 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheMoon.java @@ -1,17 +1,12 @@ package mage.cards.m; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.mana.RedManaAbility; +import mage.abilities.effects.common.continuous.NonbasicLandsAreMountainsEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.common.FilterLandPermanent; -import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.SubType; import java.util.UUID; @@ -29,7 +24,7 @@ public final class MagusOfTheMoon extends CardImpl { this.toughness = new MageInt(2); // Nonbasic lands are Mountains. - this.addAbility(new SimpleStaticAbility(new MagusOfTheMoonEffect())); + this.addAbility(new SimpleStaticAbility(new NonbasicLandsAreMountainsEffect())); } private MagusOfTheMoon(final MagusOfTheMoon card) { @@ -40,58 +35,4 @@ public final class MagusOfTheMoon extends CardImpl { public MagusOfTheMoon copy() { return new MagusOfTheMoon(this); } - -} - -class MagusOfTheMoonEffect extends ContinuousEffectImpl { - - private static final FilterLandPermanent filter = new FilterLandPermanent(); - - static { - filter.add(Predicates.not(SuperType.BASIC.getPredicate())); - } - - MagusOfTheMoonEffect() { - super(Duration.WhileOnBattlefield, Outcome.Detriment); - this.staticText = "Nonbasic lands are Mountains"; - dependendToTypes.add(DependencyType.BecomeNonbasicLand); - dependencyTypes.add(DependencyType.BecomeMountain); - } - - private MagusOfTheMoonEffect(final MagusOfTheMoonEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public MagusOfTheMoonEffect copy() { - return new MagusOfTheMoonEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent land : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { - switch (layer) { - case TypeChangingEffects_4: - // 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects - // So the ability removing has to be done before Layer 6 - land.removeAllAbilities(source.getSourceId(), game); - land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); - land.addSubType(game, SubType.MOUNTAIN); - // Mountains have the red mana ability intrinsically so the ability must be added in this layer - land.addAbility(new RedManaAbility(), source.getSourceId(), game); - break; - } - } - return true; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.TypeChangingEffects_4; - } } diff --git a/Mage.Sets/src/mage/cards/z/ZhaoTheMoonSlayer.java b/Mage.Sets/src/mage/cards/z/ZhaoTheMoonSlayer.java new file mode 100644 index 00000000000..eea55758eee --- /dev/null +++ b/Mage.Sets/src/mage/cards/z/ZhaoTheMoonSlayer.java @@ -0,0 +1,66 @@ +package mage.cards.z; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.PermanentsEnterBattlefieldTappedEffect; +import mage.abilities.effects.common.continuous.NonbasicLandsAreMountainsEffect; +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.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ZhaoTheMoonSlayer extends CardImpl { + + private static final Condition condition = new SourceHasCounterCondition(CounterType.CONQUEROR); + + public ZhaoTheMoonSlayer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Menace + this.addAbility(new MenaceAbility()); + + // Nonbasic lands enter tapped. + this.addAbility(new SimpleStaticAbility(new PermanentsEnterBattlefieldTappedEffect(StaticFilters.FILTER_LANDS_NONBASIC))); + + // {7}: Put a conqueror counter on Zhao. + this.addAbility(new SimpleActivatedAbility( + new AddCountersSourceEffect(CounterType.CONQUEROR.createInstance()), new GenericManaCost(7) + )); + + // As long as Zhao has a conqueror counter on him, nonbasic lands are Mountains. + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new NonbasicLandsAreMountainsEffect(), condition, + "as long as {this} has a conqueror counter on him, nonbasic lands are Mountains" + ))); + } + + private ZhaoTheMoonSlayer(final ZhaoTheMoonSlayer card) { + super(card); + } + + @Override + public ZhaoTheMoonSlayer copy() { + return new ZhaoTheMoonSlayer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 8b44d6a3ac8..010c7d4ba6c 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -341,6 +341,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Yue, the Moon Spirit", 83, Rarity.RARE, mage.cards.y.YueTheMoonSpirit.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Yuyan Archers", 161, Rarity.COMMON, mage.cards.y.YuyanArchers.class)); cards.add(new SetCardInfo("Zhao, Ruthless Admiral", 252, Rarity.UNCOMMON, mage.cards.z.ZhaoRuthlessAdmiral.class)); + cards.add(new SetCardInfo("Zhao, the Moon Slayer", 162, Rarity.RARE, mage.cards.z.ZhaoTheMoonSlayer.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Zhao, the Moon Slayer", 376, Rarity.RARE, mage.cards.z.ZhaoTheMoonSlayer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Zuko's Conviction", 123, Rarity.UNCOMMON, mage.cards.z.ZukosConviction.class)); cards.add(new SetCardInfo("Zuko's Exile", 3, Rarity.COMMON, mage.cards.z.ZukosExile.class)); cards.add(new SetCardInfo("Zuko, Exiled Prince", 163, Rarity.UNCOMMON, mage.cards.z.ZukoExiledPrince.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/NonbasicLandsAreMountainsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/NonbasicLandsAreMountainsEffect.java new file mode 100644 index 00000000000..0136982dbb9 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/NonbasicLandsAreMountainsEffect.java @@ -0,0 +1,45 @@ +package mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.mana.RedManaAbility; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author LevelX2 + */ +public class NonbasicLandsAreMountainsEffect extends ContinuousEffectImpl { + + public NonbasicLandsAreMountainsEffect() { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); + this.staticText = "nonbasic lands are Mountains"; + this.dependencyTypes.add(DependencyType.BecomeMountain); + this.dependendToTypes.add(DependencyType.BecomeNonbasicLand); + } + + private NonbasicLandsAreMountainsEffect(final NonbasicLandsAreMountainsEffect effect) { + super(effect); + } + + @Override + public NonbasicLandsAreMountainsEffect copy() { + return new NonbasicLandsAreMountainsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent land : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LANDS_NONBASIC, source.getControllerId(), game)) { + // 305.7 Note that this doesn't remove any abilities that were granted to the land by other effects + // So the ability removing has to be done before Layer 6 + // Lands have their mana ability intrinsically, so that is added in layer 4 + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); + land.addSubType(game, SubType.MOUNTAIN); + land.removeAllAbilities(source.getSourceId(), game); + land.addAbility(new RedManaAbility(), source.getSourceId(), game); + } + return true; + } +} diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index c774348bd19..b5b5a74d71a 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -46,6 +46,7 @@ public enum CounterType { COLLECTION("collection"), COMPONENT("component"), CONTESTED("contested"), + CONQUEROR("conqueror"), CORPSE("corpse"), CORRUPTION("corruption"), CREDIT("credit"), -- 2.47.2 From ac71e5d5d87e9cbd505a5382212bee207f34d9e2 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 12 Nov 2025 10:53:02 -0500 Subject: [PATCH 248/261] [TLA] Implement Vengeful Villagers --- .../src/mage/cards/v/VengefulVillagers.java | 52 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 53 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/v/VengefulVillagers.java diff --git a/Mage.Sets/src/mage/cards/v/VengefulVillagers.java b/Mage.Sets/src/mage/cards/v/VengefulVillagers.java new file mode 100644 index 00000000000..287c86f2764 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VengefulVillagers.java @@ -0,0 +1,52 @@ +package mage.cards.v; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class VengefulVillagers extends CardImpl { + + public VengefulVillagers(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CITIZEN); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever this creature attacks, choose target creature an opponent controls. Tap it, then you may sacrifice an artifact or creature. If you do, put a stun counter on the chosen creature. + Ability ability = new AttacksTriggeredAbility(new TapTargetEffect("choose target creature an opponent controls. Tap it")); + ability.addEffect(new DoIfCostPaid( + new AddCountersTargetEffect(CounterType.STUN.createInstance()) + .setText("put a stun counter on the chosen creature"), + new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE) + )); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); + } + + private VengefulVillagers(final VengefulVillagers card) { + super(card); + } + + @Override + public VengefulVillagers copy() { + return new VengefulVillagers(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 010c7d4ba6c..043b468eb24 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -321,6 +321,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Uncle Iroh", 248, Rarity.UNCOMMON, mage.cards.u.UncleIroh.class)); cards.add(new SetCardInfo("United Front", 331, Rarity.MYTHIC, mage.cards.u.UnitedFront.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("United Front", 39, Rarity.MYTHIC, mage.cards.u.UnitedFront.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Vengeful Villagers", 40, Rarity.UNCOMMON, mage.cards.v.VengefulVillagers.class)); cards.add(new SetCardInfo("Vindictive Warden", 249, Rarity.COMMON, mage.cards.v.VindictiveWarden.class)); cards.add(new SetCardInfo("Walltop Sentries", 202, Rarity.COMMON, mage.cards.w.WalltopSentries.class)); cards.add(new SetCardInfo("Wandering Musicians", 250, Rarity.COMMON, mage.cards.w.WanderingMusicians.class)); -- 2.47.2 From ee77746db8475913fb832167780907f94d26ae89 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 09:08:50 -0500 Subject: [PATCH 249/261] [TLA] Implement Secret Tunnel --- Mage.Sets/src/mage/cards/s/SecretTunnel.java | 93 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 95 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SecretTunnel.java diff --git a/Mage.Sets/src/mage/cards/s/SecretTunnel.java b/Mage.Sets/src/mage/cards/s/SecretTunnel.java new file mode 100644 index 00000000000..8b36b7017ba --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SecretTunnel.java @@ -0,0 +1,93 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.common.GreatestSharedCreatureTypeCount; +import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; +import mage.abilities.keyword.CantBeBlockedSourceAbility; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SecretTunnel extends CardImpl { + + public SecretTunnel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + this.subtype.add(SubType.CAVE); + + // This land can't be blocked. + this.addAbility(new CantBeBlockedSourceAbility()); + + // {T}: Add {C}. + this.addAbility(new ColorlessManaAbility()); + + // {4}, {T}: Two target creatures you control that share a creature type can't be blocked this turn. + Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new GenericManaCost(4)); + ability.addCost(new TapSourceCost()); + ability.addTarget(new SecretTunnelTarget()); + this.addAbility(ability); + } + + private SecretTunnel(final SecretTunnel card) { + super(card); + } + + @Override + public SecretTunnel copy() { + return new SecretTunnel(this); + } +} + +class SecretTunnelTarget extends TargetPermanent { + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("creatures you control that share a creature type"); + + SecretTunnelTarget() { + super(2, 2, filter, false); + } + + private SecretTunnelTarget(final SecretTunnelTarget target) { + super(target); + } + + @Override + public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { + if (!super.canTarget(playerId, id, source, game)) { + return false; + } + if (getTargets().isEmpty()) { + return true; + } + Permanent targetOne = game.getPermanent(getTargets().get(0)); + Permanent targetTwo = game.getPermanent(id); + if (targetOne == null || targetTwo == null) { + return false; + } + return targetOne.shareCreatureTypes(game, targetTwo); + } + + @Override + public boolean canChoose(UUID sourceControllerId, Ability source, Game game) { + return GreatestSharedCreatureTypeCount.getValue(sourceControllerId, source, game) >= 2; + } + + @Override + public SecretTunnelTarget copy() { + return new SecretTunnelTarget(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 043b468eb24..a3fdd03df08 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -263,6 +263,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Rumble Arena", 277, Rarity.COMMON, mage.cards.r.RumbleArena.class)); cards.add(new SetCardInfo("Saber-Tooth Moose-Lion", 194, Rarity.COMMON, mage.cards.s.SaberToothMooseLion.class)); cards.add(new SetCardInfo("Sandbenders' Storm", 34, Rarity.COMMON, mage.cards.s.SandbendersStorm.class)); + cards.add(new SetCardInfo("Secret Tunnel", 278, Rarity.RARE, mage.cards.s.SecretTunnel.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Secret Tunnel", 392, Rarity.RARE, mage.cards.s.SecretTunnel.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Seismic Sense", 195, Rarity.UNCOMMON, mage.cards.s.SeismicSense.class)); cards.add(new SetCardInfo("Serpent of the Pass", 70, Rarity.UNCOMMON, mage.cards.s.SerpentOfThePass.class)); cards.add(new SetCardInfo("Serpent's Pass", 279, Rarity.COMMON, mage.cards.s.SerpentsPass.class)); -- 2.47.2 From 13f4a314a76ea2431894590f7b1cac96f6970ec1 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 09:11:56 -0500 Subject: [PATCH 250/261] [TLA] Implement Allies at Last --- Mage.Sets/src/mage/cards/a/AlliesAtLast.java | 39 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + .../java/mage/constants/AffinityType.java | 1 + 3 files changed, 41 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AlliesAtLast.java diff --git a/Mage.Sets/src/mage/cards/a/AlliesAtLast.java b/Mage.Sets/src/mage/cards/a/AlliesAtLast.java new file mode 100644 index 00000000000..be50ca1cdb0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AlliesAtLast.java @@ -0,0 +1,39 @@ +package mage.cards.a; + +import mage.abilities.effects.common.TargetsDamageTargetsEffect; +import mage.abilities.keyword.AffinityAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AffinityType; +import mage.constants.CardType; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AlliesAtLast extends CardImpl { + + public AlliesAtLast(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}"); + + // Affinity for Allies + this.addAbility(new AffinityAbility(AffinityType.ALLIES)); + + // Up to two target creatures you control each deal damage equal to their power to target creature an opponent controls. + this.getSpellAbility().addEffect(new TargetsDamageTargetsEffect(true)); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 2).setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent().setTargetTag(3)); + } + + private AlliesAtLast(final AlliesAtLast card) { + super(card); + } + + @Override + public AlliesAtLast copy() { + return new AlliesAtLast(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index a3fdd03df08..b19486cfb34 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -50,6 +50,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Airbender's Reversal", 7, Rarity.UNCOMMON, mage.cards.a.AirbendersReversal.class)); cards.add(new SetCardInfo("Airbending Lesson", 8, Rarity.COMMON, mage.cards.a.AirbendingLesson.class)); cards.add(new SetCardInfo("Airship Engine Room", 265, Rarity.COMMON, mage.cards.a.AirshipEngineRoom.class)); + cards.add(new SetCardInfo("Allies at Last", 164, Rarity.UNCOMMON, mage.cards.a.AlliesAtLast.class)); cards.add(new SetCardInfo("Appa, Loyal Sky Bison", 9, Rarity.UNCOMMON, mage.cards.a.AppaLoyalSkyBison.class)); cards.add(new SetCardInfo("Appa, Steadfast Guardian", 10, Rarity.MYTHIC, mage.cards.a.AppaSteadfastGuardian.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Appa, Steadfast Guardian", 316, Rarity.MYTHIC, mage.cards.a.AppaSteadfastGuardian.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/constants/AffinityType.java b/Mage/src/main/java/mage/constants/AffinityType.java index de6fb741683..104ace0f9cb 100644 --- a/Mage/src/main/java/mage/constants/AffinityType.java +++ b/Mage/src/main/java/mage/constants/AffinityType.java @@ -42,6 +42,7 @@ public enum AffinityType { BIRDS(new FilterControlledPermanent(SubType.BIRD, "Birds")), CITIZENS(new FilterControlledPermanent(SubType.CITIZEN, "Citizens")), SLIVERS(new FilterControlledPermanent(SubType.SLIVER, "Slivers")), + ALLIES(new FilterControlledPermanent(SubType.ALLY, "Allies"), "Ally"), TOWNS(new FilterControlledPermanent(SubType.TOWN, "Towns")), GATES(new FilterControlledPermanent(SubType.GATE, "Gates"), GatesYouControlHint.instance), SNOW_LANDS(AffinityFilters.SNOW_LANDS), -- 2.47.2 From 694f5332cc11a542148f58b2b551b484b8019fc0 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 09:22:25 -0500 Subject: [PATCH 251/261] [TLA] Implement Aang, Swift Savior / Aang and La, Ocean's Fury --- .../src/mage/cards/a/AangAndLaOceansFury.java | 60 ++++++++++++++++ .../src/mage/cards/a/AangSwiftSavior.java | 71 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 8 +++ .../effects/keyword/AirbendTargetEffect.java | 15 ++-- 4 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/a/AangAndLaOceansFury.java create mode 100644 Mage.Sets/src/mage/cards/a/AangSwiftSavior.java diff --git a/Mage.Sets/src/mage/cards/a/AangAndLaOceansFury.java b/Mage.Sets/src/mage/cards/a/AangAndLaOceansFury.java new file mode 100644 index 00000000000..cd195db2c64 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AangAndLaOceansFury.java @@ -0,0 +1,60 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.abilities.keyword.ReachAbility; +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 mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.TappedPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AangAndLaOceansFury extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("tapped creature you control"); + + static { + filter.add(TappedPredicate.TAPPED); + } + + public AangAndLaOceansFury(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.AVATAR); + this.subtype.add(SubType.SPIRIT); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + this.nightCard = true; + + // Reach + this.addAbility(ReachAbility.getInstance()); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Whenever Aang and La attack, put a +1/+1 counter on each tapped creature you control. + this.addAbility(new AttacksTriggeredAbility(new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter))); + } + + private AangAndLaOceansFury(final AangAndLaOceansFury card) { + super(card); + } + + @Override + public AangAndLaOceansFury copy() { + return new AangAndLaOceansFury(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AangSwiftSavior.java b/Mage.Sets/src/mage/cards/a/AangSwiftSavior.java new file mode 100644 index 00000000000..a23c4d1af15 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AangSwiftSavior.java @@ -0,0 +1,71 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.WaterbendCost; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.keyword.AirbendTargetEffect; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.FlyingAbility; +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.common.FilterSpellOrPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.common.TargetSpellOrPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AangSwiftSavior extends CardImpl { + + private static final FilterSpellOrPermanent filter = new FilterSpellOrPermanent("other target creature or spell"); + + static { + filter.getPermanentFilter().add(CardType.CREATURE.getPredicate()); + filter.getPermanentFilter().add(AnotherPredicate.instance); + } + + public AangSwiftSavior(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.AVATAR); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + this.secondSideCardClazz = mage.cards.a.AangAndLaOceansFury.class; + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Aang enters, airbend up to one other target creature or spell. + Ability ability = new EntersBattlefieldTriggeredAbility(new AirbendTargetEffect()); + ability.addTarget(new TargetSpellOrPermanent(0, 1, filter, false)); + this.addAbility(ability); + + // Waterbend {8}: Transform Aang. + this.addAbility(new TransformAbility()); + this.addAbility(new SimpleActivatedAbility(new TransformSourceEffect(), new WaterbendCost(8))); + } + + private AangSwiftSavior(final AangSwiftSavior card) { + super(card); + } + + @Override + public AangSwiftSavior copy() { + return new AangSwiftSavior(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index b19486cfb34..8c6d9c95adf 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -25,6 +25,10 @@ public final class AvatarTheLastAirbender extends ExpansionSet { this.rotationSet = true; this.hasBasicLands = true; + cards.add(new SetCardInfo("Aang and La, Ocean's Fury", 204, Rarity.RARE, mage.cards.a.AangAndLaOceansFury.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang and La, Ocean's Fury", 298, Rarity.RARE, mage.cards.a.AangAndLaOceansFury.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang and La, Ocean's Fury", 347, Rarity.RARE, mage.cards.a.AangAndLaOceansFury.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang and La, Ocean's Fury", 359, Rarity.RARE, mage.cards.a.AangAndLaOceansFury.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang's Iceberg", 336, Rarity.RARE, mage.cards.a.AangsIceberg.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang's Iceberg", 5, Rarity.RARE, mage.cards.a.AangsIceberg.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang's Journey", 1, Rarity.COMMON, mage.cards.a.AangsJourney.class)); @@ -34,6 +38,10 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Aang, Master of Elements", 207, Rarity.MYTHIC, mage.cards.a.AangMasterOfElements.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, Master of Elements", 308, Rarity.MYTHIC, mage.cards.a.AangMasterOfElements.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, Master of Elements", 363, Rarity.MYTHIC, mage.cards.a.AangMasterOfElements.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, Swift Savior", 204, Rarity.RARE, mage.cards.a.AangSwiftSavior.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, Swift Savior", 298, Rarity.RARE, mage.cards.a.AangSwiftSavior.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, Swift Savior", 347, Rarity.RARE, mage.cards.a.AangSwiftSavior.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Aang, Swift Savior", 359, Rarity.RARE, mage.cards.a.AangSwiftSavior.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, at the Crossroads", 203, Rarity.RARE, mage.cards.a.AangAtTheCrossroads.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, at the Crossroads", 304, Rarity.RARE, mage.cards.a.AangAtTheCrossroads.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aang, at the Crossroads", 346, Rarity.RARE, mage.cards.a.AangAtTheCrossroads.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/AirbendTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/AirbendTargetEffect.java index b98f6b35221..dace0a8893e 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/AirbendTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/AirbendTargetEffect.java @@ -17,11 +17,11 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.targetpointer.FixedTarget; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -47,18 +47,21 @@ public class AirbendTargetEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - Set permanents = this + if (player == null) { + return false; + } + Set objects = this .getTargetPointer() .getTargets(game, source) .stream() - .map(game::getPermanent) + .map(uuid -> Optional.ofNullable((Card) game.getPermanent(uuid)).orElseGet(() -> game.getSpell(uuid))) .filter(Objects::nonNull) .collect(Collectors.toSet()); - if (player == null || permanents.isEmpty()) { + if (objects.isEmpty()) { return false; } - player.moveCards(permanents, Zone.EXILED, source, game); - Cards cards = new CardsImpl(permanents); + player.moveCards(objects, Zone.EXILED, source, game); + Cards cards = new CardsImpl(objects); cards.retainZone(Zone.EXILED, game); for (Card card : cards.getCards(game)) { game.addEffect(new AirbendingCastEffect(card, game), source); -- 2.47.2 From 09d3d89045d210b6e6747fd09b633a5d261853b1 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 09:28:13 -0500 Subject: [PATCH 252/261] [TLA] Implement Avatar's Wrath --- Mage.Sets/src/mage/cards/a/AvatarsWrath.java | 114 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 116 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AvatarsWrath.java diff --git a/Mage.Sets/src/mage/cards/a/AvatarsWrath.java b/Mage.Sets/src/mage/cards/a/AvatarsWrath.java new file mode 100644 index 00000000000..164e1700fcb --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AvatarsWrath.java @@ -0,0 +1,114 @@ +package mage.cards.a; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileSpellEffect; +import mage.abilities.effects.keyword.AirbendTargetEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTargets; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AvatarsWrath extends CardImpl { + + public AvatarsWrath(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}{W}"); + + // Choose up to one target creature, then airbend all other creatures. + this.getSpellAbility().addEffect(new AvatarsWrathAirbendEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1)); + + // Until your next turn, your opponents can't cast spells from anywhere other than their hand. + this.getSpellAbility().addEffect(new AvatarsWrathRuleEffect()); + + // Exile Avatar's Wrath. + this.getSpellAbility().addEffect(new ExileSpellEffect().concatBy("
")); + } + + private AvatarsWrath(final AvatarsWrath card) { + super(card); + } + + @Override + public AvatarsWrath copy() { + return new AvatarsWrath(this); + } +} + +class AvatarsWrathAirbendEffect extends OneShotEffect { + + AvatarsWrathAirbendEffect() { + super(Outcome.Benefit); + staticText = "choose up to one target creature, then airbend all other creatures"; + } + + private AvatarsWrathAirbendEffect(final AvatarsWrathAirbendEffect effect) { + super(effect); + } + + @Override + public AvatarsWrathAirbendEffect copy() { + return new AvatarsWrathAirbendEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + List permanents = game + .getBattlefield() + .getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game); + Optional.ofNullable(game.getPermanent(getTargetPointer().getFirst(game, source))) + .ifPresent(permanents::remove); + return !permanents.isEmpty() + && new AirbendTargetEffect() + .setTargetPointer(new FixedTargets(permanents, game)) + .apply(game, source); + } +} + +class AvatarsWrathRuleEffect extends ContinuousRuleModifyingEffectImpl { + + AvatarsWrathRuleEffect() { + super(Duration.UntilYourNextTurn, Outcome.Benefit); + staticText = "
Until your next turn, your opponents can't cast spells from anywhere other than their hand."; + } + + private AvatarsWrathRuleEffect(final AvatarsWrathRuleEffect effect) { + super(effect); + } + + @Override + public AvatarsWrathRuleEffect copy() { + return new AvatarsWrathRuleEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (!game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + return false; + } + Card card = game.getCard(event.getSourceId()); + return card != null && game.getState().getZone(card.getId()) != Zone.HAND; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 8c6d9c95adf..e3b69172c2f 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -66,6 +66,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Avatar Aang", 308, Rarity.MYTHIC, mage.cards.a.AvatarAang.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Avatar Aang", 363, Rarity.MYTHIC, mage.cards.a.AvatarAang.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Avatar Enthusiasts", 11, Rarity.COMMON, mage.cards.a.AvatarEnthusiasts.class)); + 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)); cards.add(new SetCardInfo("Azula, On the Hunt", 85, Rarity.UNCOMMON, mage.cards.a.AzulaOnTheHunt.class)); cards.add(new SetCardInfo("Ba Sing Se", 266, Rarity.RARE, mage.cards.b.BaSingSe.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 998b737ab58c02d801bdc8d10d08c104c5404d13 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 09:35:04 -0500 Subject: [PATCH 253/261] [TLA] Implement Earth Kingdom General --- .../src/mage/cards/e/EarthKingdomGeneral.java | 56 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 57 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EarthKingdomGeneral.java diff --git a/Mage.Sets/src/mage/cards/e/EarthKingdomGeneral.java b/Mage.Sets/src/mage/cards/e/EarthKingdomGeneral.java new file mode 100644 index 00000000000..c497d0e1b5b --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EarthKingdomGeneral.java @@ -0,0 +1,56 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.PutCounterOnPermanentTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.EffectKeyValue; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledLandPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class EarthKingdomGeneral extends CardImpl { + + private static final DynamicValue xValue = new EffectKeyValue("countersAdded", "that many"); + + public EarthKingdomGeneral(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When this creature enters, earthbend 2. + Ability ability = new EntersBattlefieldTriggeredAbility(new EarthbendTargetEffect(2)); + ability.addTarget(new TargetControlledLandPermanent()); + this.addAbility(ability); + + // Whenever you put one or more +1/+1 counters on a creature, you may gain that much life. Do this only once each turn. + this.addAbility(new PutCounterOnPermanentTriggeredAbility( + new GainLifeEffect(xValue), CounterType.P1P1, StaticFilters.FILTER_PERMANENT_CREATURE + ).setDoOnlyOnceEachTurn(true)); + } + + private EarthKingdomGeneral(final EarthKingdomGeneral card) { + super(card); + } + + @Override + public EarthKingdomGeneral copy() { + return new EarthKingdomGeneral(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index e3b69172c2f..6028fbe651d 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -116,6 +116,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Dragonfly Swarm", 215, Rarity.UNCOMMON, mage.cards.d.DragonflySwarm.class)); cards.add(new SetCardInfo("Earth King's Lieutenant", 217, Rarity.RARE, mage.cards.e.EarthKingsLieutenant.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earth King's Lieutenant", 380, Rarity.RARE, mage.cards.e.EarthKingsLieutenant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Earth Kingdom General", 173, Rarity.UNCOMMON, mage.cards.e.EarthKingdomGeneral.class)); cards.add(new SetCardInfo("Earth Kingdom Jailer", 16, Rarity.UNCOMMON, mage.cards.e.EarthKingdomJailer.class)); cards.add(new SetCardInfo("Earth Kingdom Protectors", 17, Rarity.UNCOMMON, mage.cards.e.EarthKingdomProtectors.class)); cards.add(new SetCardInfo("Earth Kingdom Soldier", 216, Rarity.COMMON, mage.cards.e.EarthKingdomSoldier.class)); -- 2.47.2 From 5ce393f61770665550046a45cb14892b3807774a Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 09:44:59 -0500 Subject: [PATCH 254/261] [TLA] Implement Energybending --- .../mage/cards/d/DryadOfTheIlysianGrove.java | 2 +- Mage.Sets/src/mage/cards/e/Energybending.java | 39 ++++++++++ .../mage/cards/l/LeylineOfTheGuildpact.java | 2 +- Mage.Sets/src/mage/cards/p/PrismaticOmen.java | 3 +- .../src/mage/sets/AvatarTheLastAirbender.java | 1 + .../BecomesAllBasicsControlledEffect.java | 75 +++++++++++++------ 6 files changed, 96 insertions(+), 26 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/e/Energybending.java diff --git a/Mage.Sets/src/mage/cards/d/DryadOfTheIlysianGrove.java b/Mage.Sets/src/mage/cards/d/DryadOfTheIlysianGrove.java index 7e81a8956d2..cf76238a377 100644 --- a/Mage.Sets/src/mage/cards/d/DryadOfTheIlysianGrove.java +++ b/Mage.Sets/src/mage/cards/d/DryadOfTheIlysianGrove.java @@ -31,7 +31,7 @@ public final class DryadOfTheIlysianGrove extends CardImpl { )); // Lands you control are every basic land type in addition to their other types. - this.addAbility(new SimpleStaticAbility(new BecomesAllBasicsControlledEffect())); + this.addAbility(new SimpleStaticAbility(new BecomesAllBasicsControlledEffect(Duration.WhileOnBattlefield))); } private DryadOfTheIlysianGrove(final DryadOfTheIlysianGrove card) { diff --git a/Mage.Sets/src/mage/cards/e/Energybending.java b/Mage.Sets/src/mage/cards/e/Energybending.java new file mode 100644 index 00000000000..af92484b839 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/Energybending.java @@ -0,0 +1,39 @@ +package mage.cards.e; + +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.BecomesAllBasicsControlledEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Energybending extends CardImpl { + + public Energybending(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}"); + + this.subtype.add(SubType.LESSON); + + // Lands you control gain all basic land types until end of turn. + this.getSpellAbility().addEffect(new BecomesAllBasicsControlledEffect(Duration.EndOfTurn) + .setText("lands you control gain all basic land types until end of turn")); + + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); + } + + private Energybending(final Energybending card) { + super(card); + } + + @Override + public Energybending copy() { + return new Energybending(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LeylineOfTheGuildpact.java b/Mage.Sets/src/mage/cards/l/LeylineOfTheGuildpact.java index a3de4e672b2..d3dcca61a2c 100644 --- a/Mage.Sets/src/mage/cards/l/LeylineOfTheGuildpact.java +++ b/Mage.Sets/src/mage/cards/l/LeylineOfTheGuildpact.java @@ -30,7 +30,7 @@ public final class LeylineOfTheGuildpact extends CardImpl { this.addAbility(new SimpleStaticAbility(new LeylineOfTheGuildpactEffect())); // Lands you control are every basic land type in addition to their other types. - this.addAbility(new SimpleStaticAbility(new BecomesAllBasicsControlledEffect())); + this.addAbility(new SimpleStaticAbility(new BecomesAllBasicsControlledEffect(Duration.WhileOnBattlefield))); } private LeylineOfTheGuildpact(final LeylineOfTheGuildpact card) { diff --git a/Mage.Sets/src/mage/cards/p/PrismaticOmen.java b/Mage.Sets/src/mage/cards/p/PrismaticOmen.java index 9a53dca6d17..2b975ebb774 100644 --- a/Mage.Sets/src/mage/cards/p/PrismaticOmen.java +++ b/Mage.Sets/src/mage/cards/p/PrismaticOmen.java @@ -5,6 +5,7 @@ import mage.abilities.effects.common.continuous.BecomesAllBasicsControlledEffect import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; import java.util.UUID; @@ -17,7 +18,7 @@ public final class PrismaticOmen extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); // Lands you control are every basic land type in addition to their other types. - this.addAbility(new SimpleStaticAbility(new BecomesAllBasicsControlledEffect())); + this.addAbility(new SimpleStaticAbility(new BecomesAllBasicsControlledEffect(Duration.WhileOnBattlefield))); } private PrismaticOmen(final PrismaticOmen card) { diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 6028fbe651d..41735249da5 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -129,6 +129,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Earthen Ally", 177, Rarity.RARE, mage.cards.e.EarthenAlly.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Earthen Ally", 377, Rarity.RARE, mage.cards.e.EarthenAlly.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ember Island Production", 48, Rarity.UNCOMMON, mage.cards.e.EmberIslandProduction.class)); + cards.add(new SetCardInfo("Energybending", 2, Rarity.UNCOMMON, mage.cards.e.Energybending.class)); cards.add(new SetCardInfo("Enter the Avatar State", 18, Rarity.UNCOMMON, mage.cards.e.EnterTheAvatarState.class)); cards.add(new SetCardInfo("Epic Downfall", 96, Rarity.UNCOMMON, mage.cards.e.EpicDownfall.class)); cards.add(new SetCardInfo("Fancy Footwork", 19, Rarity.UNCOMMON, mage.cards.f.FancyFootwork.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java index 1e96acf7468..6b61f21586c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesAllBasicsControlledEffect.java @@ -1,5 +1,6 @@ package mage.abilities.effects.common.continuous; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.mana.*; @@ -8,6 +9,8 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.Iterator; + /** * @author TheElk801 */ @@ -21,9 +24,9 @@ public class BecomesAllBasicsControlledEffect extends ContinuousEffectImpl { new GreenManaAbility() }; - public BecomesAllBasicsControlledEffect() { - super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); - this.staticText = "Lands you control are every basic land type in addition to their other types"; + public BecomesAllBasicsControlledEffect(Duration duration) { + super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Detriment); + this.staticText = "lands you control are every basic land type in addition to their other types"; dependendToTypes.add(DependencyType.BecomeNonbasicLand); dependencyTypes.add(DependencyType.BecomeMountain); dependencyTypes.add(DependencyType.BecomeForest); @@ -42,29 +45,55 @@ public class BecomesAllBasicsControlledEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - for (Permanent permanent : game.getBattlefield().getActivePermanents( - StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, source.getControllerId(), game)) { - permanent.addSubType(game, - SubType.PLAINS, - SubType.ISLAND, - SubType.SWAMP, - SubType.MOUNTAIN, - SubType.FOREST); - // Optimization: Remove basic mana abilities since they are redundant with AnyColorManaAbility - // and keeping them will only produce too many combinations inside ManaOptions - for (Ability basicManaAbility : basicManaAbilities) { - if (permanent.getAbilities(game).containsRule(basicManaAbility)) { - permanent.removeAbility(basicManaAbility, source.getSourceId(), game); - } + public void init(Ability source, Game game) { + super.init(source, game); + if (getAffectedObjectsSet()) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, source.getControllerId(), game)) { + affectedObjectList.add(new MageObjectReference(permanent, game)); } - // Add the {T}: Add one mana of any color ability - // This is functionally equivalent to having five "{T}: Add {COLOR}" for each COLOR in {W}{U}{B}{R}{G} - AnyColorManaAbility ability = new AnyColorManaAbility(); - if (!permanent.getAbilities(game).containsRule(ability)) { - permanent.addAbility(ability, source.getSourceId(), game); + } + } + + @Override + public boolean apply(Game game, Ability source) { + if (!getAffectedObjectsSet()) { + for (Permanent permanent : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, source.getControllerId(), game + )) { + removeTypes(permanent, game, source); + } + return true; + } + for (Iterator it = affectedObjectList.iterator(); it.hasNext(); ) { + Permanent permanent = it.next().getPermanent(game); + if (permanent != null) { + removeTypes(permanent, game, source); + } else { + it.remove(); } } return true; } + + private static void removeTypes(Permanent permanent, Game game, Ability source) { + permanent.addSubType(game, + SubType.PLAINS, + SubType.ISLAND, + SubType.SWAMP, + SubType.MOUNTAIN, + SubType.FOREST); + // Optimization: Remove basic mana abilities since they are redundant with AnyColorManaAbility + // and keeping them will only produce too many combinations inside ManaOptions + for (Ability basicManaAbility : basicManaAbilities) { + if (permanent.getAbilities(game).containsRule(basicManaAbility)) { + permanent.removeAbility(basicManaAbility, source.getSourceId(), game); + } + } + // Add the {T}: Add one mana of any color ability + // This is functionally equivalent to having five "{T}: Add {COLOR}" for each COLOR in {W}{U}{B}{R}{G} + AnyColorManaAbility ability = new AnyColorManaAbility(); + if (!permanent.getAbilities(game).containsRule(ability)) { + permanent.addAbility(ability, source.getSourceId(), game); + } + } } -- 2.47.2 From ab2980116d3bdcca95ac13c82eeb22a05d57966b Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 09:48:59 -0500 Subject: [PATCH 255/261] [TLA] Implement Fatal Fissure --- Mage.Sets/src/mage/cards/f/FatalFissure.java | 40 +++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 1 + 2 files changed, 41 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FatalFissure.java diff --git a/Mage.Sets/src/mage/cards/f/FatalFissure.java b/Mage.Sets/src/mage/cards/f/FatalFissure.java new file mode 100644 index 00000000000..7078dea7373 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FatalFissure.java @@ -0,0 +1,40 @@ +package mage.cards.f; + +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.keyword.EarthbendTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.common.TargetControlledLandPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FatalFissure extends CardImpl { + + public FatalFissure(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}"); + + // Choose target creature. When that creature dies this turn, you earthbend 4. + DelayedTriggeredAbility ability = new WhenTargetDiesDelayedTriggeredAbility(new EarthbendTargetEffect(4).setText("you earthbend 4")); + ability.addTarget(new TargetControlledLandPermanent()); + this.getSpellAbility().addEffect(new InfoEffect("choose target creature")); + this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(ability, false)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + private FatalFissure(final FatalFissure card) { + super(card); + } + + @Override + public FatalFissure copy() { + return new FatalFissure(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 41735249da5..2e71d88dae8 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -133,6 +133,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Enter the Avatar State", 18, Rarity.UNCOMMON, mage.cards.e.EnterTheAvatarState.class)); cards.add(new SetCardInfo("Epic Downfall", 96, Rarity.UNCOMMON, mage.cards.e.EpicDownfall.class)); cards.add(new SetCardInfo("Fancy Footwork", 19, Rarity.UNCOMMON, mage.cards.f.FancyFootwork.class)); + cards.add(new SetCardInfo("Fatal Fissure", 97, Rarity.UNCOMMON, mage.cards.f.FatalFissure.class)); cards.add(new SetCardInfo("Fated Firepower", 132, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fated Firepower", 297, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Fated Firepower", 341, Rarity.MYTHIC, mage.cards.f.FatedFirepower.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 7a0142867ad61148142fb8d2565abcf32e355ad7 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 09:56:03 -0500 Subject: [PATCH 256/261] [TLA] Implement Iroh, Grand Lotus --- .../src/mage/cards/i/IrohGrandLotus.java | 100 ++++++++++++++++++ .../src/mage/sets/AvatarTheLastAirbender.java | 2 + 2 files changed, 102 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/IrohGrandLotus.java diff --git a/Mage.Sets/src/mage/cards/i/IrohGrandLotus.java b/Mage.Sets/src/mage/cards/i/IrohGrandLotus.java new file mode 100644 index 00000000000..e96799fb099 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/IrohGrandLotus.java @@ -0,0 +1,100 @@ +package mage.cards.i; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.keyword.FirebendingAbility; +import mage.abilities.keyword.FlashbackAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.common.FilterInstantOrSorceryCard; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class IrohGrandLotus extends CardImpl { + + public IrohGrandLotus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{U}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.NOBLE); + this.subtype.add(SubType.ALLY); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Firebending 2 + this.addAbility(new FirebendingAbility(2)); + + // During your turn, each non-Lesson instant and sorcery card in your graveyard has flashback. The flashback cost is equal to that card's mana cost. + this.addAbility(new SimpleStaticAbility(new IrohGrandLotusEffect(false))); + + // During your turn, each Lesson card in your graveyard has flashback {1}. + this.addAbility(new SimpleStaticAbility(new IrohGrandLotusEffect(true))); + } + + private IrohGrandLotus(final IrohGrandLotus card) { + super(card); + } + + @Override + public IrohGrandLotus copy() { + return new IrohGrandLotus(this); + } +} + +class IrohGrandLotusEffect extends ContinuousEffectImpl { + + private static final FilterCard filterNonLesson = new FilterInstantOrSorceryCard(); + private static final FilterCard filterLesson = new FilterCard(SubType.LESSON); + private final boolean isLesson; + + IrohGrandLotusEffect(boolean isLesson) { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + this.isLesson = isLesson; + if (isLesson) { + staticText = "during your turn, each Lesson card in your graveyard has flashback {1}"; + } else { + staticText = "during your turn, each non-Lesson instant and sorcery card in your graveyard has flashback. " + + "The flashback cost is equal to that card's mana cost"; + } + } + + private IrohGrandLotusEffect(final IrohGrandLotusEffect effect) { + super(effect); + this.isLesson = effect.isLesson; + } + + @Override + public IrohGrandLotusEffect copy() { + return new IrohGrandLotusEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (!game.isActivePlayer(source.getControllerId())) { + return false; + } + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + for (Card card : player.getGraveyard().getCards(isLesson ? filterLesson : filterNonLesson, game)) { + Ability ability = new FlashbackAbility(card, isLesson ? new GenericManaCost(1) : card.getManaCost()); + ability.setSourceId(card.getId()); + ability.setControllerId(card.getOwnerId()); + game.getState().addOtherAbility(card, ability); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 2e71d88dae8..09565a8ab8f 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -193,6 +193,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Invasion Submersible", 57, Rarity.UNCOMMON, mage.cards.i.InvasionSubmersible.class)); cards.add(new SetCardInfo("Invasion Tactics", 183, Rarity.UNCOMMON, mage.cards.i.InvasionTactics.class)); cards.add(new SetCardInfo("Iroh's Demonstration", 141, Rarity.UNCOMMON, mage.cards.i.IrohsDemonstration.class)); + cards.add(new SetCardInfo("Iroh, Grand Lotus", 227, Rarity.RARE, mage.cards.i.IrohGrandLotus.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Iroh, Grand Lotus", 349, Rarity.RARE, mage.cards.i.IrohGrandLotus.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Island", 283, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Island", 288, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Island", 293, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); -- 2.47.2 From 5c62f53b08114c6485b6d1c67a6be7699282cde9 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 10:00:12 -0500 Subject: [PATCH 257/261] [TLE] Implement Air Nomad Student --- .../src/mage/cards/a/AirNomadStudent.java | 51 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 52 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/AirNomadStudent.java diff --git a/Mage.Sets/src/mage/cards/a/AirNomadStudent.java b/Mage.Sets/src/mage/cards/a/AirNomadStudent.java new file mode 100644 index 00000000000..2174728a083 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AirNomadStudent.java @@ -0,0 +1,51 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.AttackedThisTurnSourceCondition; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AirNomadStudent extends CardImpl { + + private static final Condition condition = new InvertCondition( + AttackedThisTurnSourceCondition.instance, "{this} didn't attack this turn" + ); + + public AirNomadStudent(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.MONK); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // At the beginning of your end step, if this creature didn't attack this turn, put a +1/+1 counter on it. + this.addAbility(new BeginningOfEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()) + .setText("put a +1/+1 counter on it")).withInterveningIf(condition)); + } + + private AirNomadStudent(final AirNomadStudent card) { + super(card); + } + + @Override + public AirNomadStudent copy() { + return new AirNomadStudent(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 2e117ffe1ac..dfbec2cb347 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -37,6 +37,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Aardvark Sloth", 267, Rarity.COMMON, mage.cards.a.AardvarkSloth.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Acrobatic Leap", 151, Rarity.COMMON, mage.cards.a.AcrobaticLeap.class)); cards.add(new SetCardInfo("Agent of Treachery", 9, Rarity.MYTHIC, mage.cards.a.AgentOfTreachery.class)); + cards.add(new SetCardInfo("Air Nomad Student", 75, Rarity.UNCOMMON, mage.cards.a.AirNomadStudent.class)); cards.add(new SetCardInfo("Allied Teamwork", 213, Rarity.RARE, mage.cards.a.AlliedTeamwork.class)); cards.add(new SetCardInfo("Appa, Aang's Companion", 214, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Appa, Aang's Companion", 268, Rarity.UNCOMMON, mage.cards.a.AppaAangsCompanion.class, NON_FULL_USE_VARIOUS)); -- 2.47.2 From 3d4454c7da9fb765b66934fcb5886ae056d8bfb1 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 10:03:52 -0500 Subject: [PATCH 258/261] [TLE] Implement Baboon Spirit --- Mage.Sets/src/mage/cards/b/BaboonSpirit.java | 64 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 2 + 2 files changed, 66 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BaboonSpirit.java diff --git a/Mage.Sets/src/mage/cards/b/BaboonSpirit.java b/Mage.Sets/src/mage/cards/b/BaboonSpirit.java new file mode 100644 index 00000000000..c3c9c72746d --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BaboonSpirit.java @@ -0,0 +1,64 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.ExileReturnBattlefieldNextEndStepTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.permanent.token.SpiritWorldToken; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BaboonSpirit extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledPermanent(SubType.SPIRIT, "another nontoken Spirit you control"); + + static { + filter.add(AnotherPredicate.instance); + filter.add(TokenPredicate.FALSE); + } + + public BaboonSpirit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.MONKEY); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Whenever another nontoken Spirit you control enters, create a 1/1 colorless Spirit creature token with "This token can't block or be blocked by non-Spirit creatures." + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new CreateTokenEffect(new SpiritWorldToken()), filter)); + + // {3}{U}: Exile another target creature you control. Return it to the battlefield under its owner's control at the beginning of the next end step. + Ability ability = new SimpleActivatedAbility( + new ExileReturnBattlefieldNextEndStepTargetEffect(), new ManaCostsImpl<>("{3}{U}") + ); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + this.addAbility(ability); + } + + private BaboonSpirit(final BaboonSpirit card) { + super(card); + } + + @Override + public BaboonSpirit copy() { + return new BaboonSpirit(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index dfbec2cb347..4dbf8422e91 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -48,6 +48,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Avatar Roku, Firebender", 191, Rarity.MYTHIC, mage.cards.a.AvatarRokuFirebender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Azula, Ruthless Firebender", 101, Rarity.MYTHIC, mage.cards.a.AzulaRuthlessFirebender.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Azula, Ruthless Firebender", 184, Rarity.MYTHIC, mage.cards.a.AzulaRuthlessFirebender.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Baboon Spirit", 177, Rarity.RARE, mage.cards.b.BaboonSpirit.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Baboon Spirit", 89, Rarity.RARE, mage.cards.b.BaboonSpirit.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bastion of Remembrance", 160, Rarity.UNCOMMON, mage.cards.b.BastionOfRemembrance.class)); cards.add(new SetCardInfo("Beastmaster Ascension", 39, Rarity.MYTHIC, mage.cards.b.BeastmasterAscension.class)); cards.add(new SetCardInfo("Black Sun's Zenith", 22, Rarity.MYTHIC, mage.cards.b.BlackSunsZenith.class)); -- 2.47.2 From c76ffbb3f5eb1731e172553acd086ab32631edf0 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 10:20:13 -0500 Subject: [PATCH 259/261] [TLE] Implement Bison Whistle --- Mage.Sets/src/mage/cards/b/BisonWhistle.java | 93 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 2 + 2 files changed, 95 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BisonWhistle.java diff --git a/Mage.Sets/src/mage/cards/b/BisonWhistle.java b/Mage.Sets/src/mage/cards/b/BisonWhistle.java new file mode 100644 index 00000000000..19cfa97f413 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BisonWhistle.java @@ -0,0 +1,93 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BisonWhistle extends CardImpl { + + public BisonWhistle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{G}"); + + // {1}, {T}: Look at the top card of your library. If it's a Bison card, you may put it onto the battlefield. If it's a creature card, you may reveal it and put it into your hand. Otherwise, you may put it into your graveyard. + Ability ability = new SimpleActivatedAbility(new BisonWhistleEffect(), new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + private BisonWhistle(final BisonWhistle card) { + super(card); + } + + @Override + public BisonWhistle copy() { + return new BisonWhistle(this); + } +} + +class BisonWhistleEffect extends OneShotEffect { + + BisonWhistleEffect() { + super(Outcome.Benefit); + staticText = "look at the top card of your library. If it's a Bison card, you may put it onto the battlefield. " + + "If it's a creature card, you may reveal it and put it into your hand. Otherwise, you may put it into your graveyard"; + } + + private BisonWhistleEffect(final BisonWhistleEffect effect) { + super(effect); + } + + @Override + public BisonWhistleEffect copy() { + return new BisonWhistleEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Card card = player.getLibrary().getFromTop(game); + if (card == null) { + return false; + } + player.lookAtCards("Top of library", card, game); + if (card.hasSubtype(SubType.BISON, game) && player.chooseUse( + Outcome.PutCardInPlay, "Put " + card.getIdName() + " onto the battlefield?", source, game + )) { + player.moveCards(card, Zone.BATTLEFIELD, source, game); + // cards like Crib Swap and Containment Priest make it possible for the card + // to either stay in the library or go to a different zone, so we only exit if it's not still on top + if (!Zone.LIBRARY.match(game.getState().getZone(card.getId()))) { + return true; + } + } + if (card.isCreature(game) && player.chooseUse( + Outcome.DrawCard, "Put " + card.getIdName() + " into your hand?", source, game + )) { + player.revealCards(source, new CardsImpl(card), game); + return player.moveCards(card, Zone.HAND, source, game); + } + return player.chooseUse( + Outcome.Discard, "Put " + card.getIdName() + " into your graveyard?", source, game + ) && player.moveCards(card, Zone.GRAVEYARD, source, game); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index 4dbf8422e91..a559a19d210 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -52,6 +52,8 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Baboon Spirit", 89, Rarity.RARE, mage.cards.b.BaboonSpirit.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bastion of Remembrance", 160, Rarity.UNCOMMON, mage.cards.b.BastionOfRemembrance.class)); cards.add(new SetCardInfo("Beastmaster Ascension", 39, Rarity.MYTHIC, mage.cards.b.BeastmasterAscension.class)); + cards.add(new SetCardInfo("Bison Whistle", 131, Rarity.RARE, mage.cards.b.BisonWhistle.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Bison Whistle", 202, Rarity.RARE, mage.cards.b.BisonWhistle.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Black Sun's Zenith", 22, Rarity.MYTHIC, mage.cards.b.BlackSunsZenith.class)); cards.add(new SetCardInfo("Blasphemous Act", 26, Rarity.MYTHIC, mage.cards.b.BlasphemousAct.class)); cards.add(new SetCardInfo("Bloodchief Ascension", 23, Rarity.MYTHIC, mage.cards.b.BloodchiefAscension.class)); -- 2.47.2 From 62ad2a1545867c70fe55ae9222cdcf69b73294c5 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 13 Nov 2025 10:23:44 -0500 Subject: [PATCH 260/261] [TLE] Implement Bosco, Just a Bear --- .../src/mage/cards/b/BoscoJustABear.java | 67 +++++++++++++++++++ .../sets/AvatarTheLastAirbenderEternal.java | 1 + 2 files changed, 68 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BoscoJustABear.java diff --git a/Mage.Sets/src/mage/cards/b/BoscoJustABear.java b/Mage.Sets/src/mage/cards/b/BoscoJustABear.java new file mode 100644 index 00000000000..fb19192af94 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BoscoJustABear.java @@ -0,0 +1,67 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.permanent.token.FoodToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BoscoJustABear extends CardImpl { + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_CREATURE_LEGENDARY); + private static final Hint hint = new ValueHint("Legendary creatures you control", xValue); + + public BoscoJustABear(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.BEAR); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // When Bosco enters, create a Food token for each legendary creature you control. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new FoodToken(), xValue)).addHint(hint)); + + // {2}{G}, Sacrifice a Food: Put two +1/+1 counters on Bosco. He gains trample until end of turn. + Ability ability = new SimpleActivatedAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new ManaCostsImpl<>("{2}{G}") + ); + ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_FOOD)); + ability.addEffect(new GainAbilitySourceEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn + ).setText("He gains trample until end of turn")); + this.addAbility(ability); + } + + private BoscoJustABear(final BoscoJustABear card) { + super(card); + } + + @Override + public BoscoJustABear copy() { + return new BoscoJustABear(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java index a559a19d210..7184b565771 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbenderEternal.java @@ -58,6 +58,7 @@ public final class AvatarTheLastAirbenderEternal extends ExpansionSet { cards.add(new SetCardInfo("Blasphemous Act", 26, Rarity.MYTHIC, mage.cards.b.BlasphemousAct.class)); cards.add(new SetCardInfo("Bloodchief Ascension", 23, Rarity.MYTHIC, mage.cards.b.BloodchiefAscension.class)); cards.add(new SetCardInfo("Bolt Bend", 163, Rarity.UNCOMMON, mage.cards.b.BoltBend.class)); + cards.add(new SetCardInfo("Bosco, Just a Bear", 132, Rarity.UNCOMMON, mage.cards.b.BoscoJustABear.class)); cards.add(new SetCardInfo("Brainstorm", 155, Rarity.COMMON, mage.cards.b.Brainstorm.class)); cards.add(new SetCardInfo("Bribery", 10, Rarity.MYTHIC, mage.cards.b.Bribery.class)); cards.add(new SetCardInfo("Brought Back", 1, Rarity.MYTHIC, mage.cards.b.BroughtBack.class)); -- 2.47.2 From 5bfd0ae796a41a4477cc40d927dffe9b68822ad0 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Thu, 13 Nov 2025 16:21:40 -0500 Subject: [PATCH 261/261] Syr Vondam's second ability needs to function from the graveyard and/or exile zones. --- Mage.Sets/src/mage/cards/s/SyrVondamSunstarExemplar.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/s/SyrVondamSunstarExemplar.java b/Mage.Sets/src/mage/cards/s/SyrVondamSunstarExemplar.java index 7f8662a830d..d08d37f22e7 100644 --- a/Mage.Sets/src/mage/cards/s/SyrVondamSunstarExemplar.java +++ b/Mage.Sets/src/mage/cards/s/SyrVondamSunstarExemplar.java @@ -105,7 +105,7 @@ class SyrVondamSunstarExemplarFirstTriggeredAbility extends TriggeredAbilityImpl class SyrVondamSunstarExemplarSecondTriggeredAbility extends TriggeredAbilityImpl { SyrVondamSunstarExemplarSecondTriggeredAbility() { - super(Zone.BATTLEFIELD, new DestroyTargetEffect()); + super(Zone.ALL, new DestroyTargetEffect()); this.addTarget(new TargetNonlandPermanent(0, 1)); this.setTriggerPhrase("When {this} dies or is put into exile while its power is 4 or greater, "); this.setLeavesTheBattlefieldTrigger(true); -- 2.47.2