From 2f85f46e32570e29b8b1f277f55e09b53730c2eb Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 14 Aug 2025 17:23:26 -0400 Subject: [PATCH] [TLE] Implement Aang, Airbending Master --- .../mage/cards/a/AangAirbendingMaster.java | 67 +++++-------------- Mage.Sets/src/mage/cards/d/DourPortMage.java | 49 ++------------ ...MoreLeaveWithoutDyingTriggeredAbility.java | 52 ++++++++++++++ 3 files changed, 72 insertions(+), 96 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/common/OneOrMoreLeaveWithoutDyingTriggeredAbility.java diff --git a/Mage.Sets/src/mage/cards/a/AangAirbendingMaster.java b/Mage.Sets/src/mage/cards/a/AangAirbendingMaster.java index 93777a102f1..6f1ac6a3f2b 100644 --- a/Mage.Sets/src/mage/cards/a/AangAirbendingMaster.java +++ b/Mage.Sets/src/mage/cards/a/AangAirbendingMaster.java @@ -1,33 +1,30 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.BatchTriggeredAbility; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.OneOrMoreLeaveWithoutDyingTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CountersControllerCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersPlayersEffect; import mage.abilities.effects.keyword.AirbendTargetEffect; import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.constants.*; 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.filter.StaticFilters; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeBatchEvent; -import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; import mage.game.permanent.token.AllyToken; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * - * @author Grath + * @author TheElk801 */ public final class AangAirbendingMaster extends CardImpl { @@ -35,7 +32,7 @@ public final class AangAirbendingMaster extends CardImpl { public AangAirbendingMaster(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.AVATAR); @@ -44,15 +41,19 @@ public final class AangAirbendingMaster extends CardImpl { this.toughness = new MageInt(4); // When Aang enters, airbend another target creature. - Ability ability = new EntersBattlefieldTriggeredAbility(new AirbendTargetEffect(), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new AirbendTargetEffect()); ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); // Whenever one or more creatures you control leave the battlefield without dying, you get an experience counter. - this.addAbility(new AangAirbendingMasterTriggeredAbility()); + this.addAbility(new OneOrMoreLeaveWithoutDyingTriggeredAbility( + new AddCountersPlayersEffect(CounterType.EXPERIENCE.createInstance(), TargetController.YOU), + StaticFilters.FILTER_CONTROLLED_CREATURES + )); // At the beginning of your upkeep, create a 1/1 white Ally creature token for each experience counter you have. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new AllyToken(), xValue))); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new AllyToken(), xValue) + .setText("create a 1/1 white Ally creature token for each experience counter you have"))); } private AangAirbendingMaster(final AangAirbendingMaster card) { @@ -64,39 +65,3 @@ public final class AangAirbendingMaster extends CardImpl { return new AangAirbendingMaster(this); } } - -class AangAirbendingMasterTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility { - - AangAirbendingMasterTriggeredAbility() { - super(Zone.BATTLEFIELD, new AddCountersPlayersEffect(CounterType.EXPERIENCE.createInstance(), TargetController.YOU)); - setTriggerPhrase("Whenever one or more creatures you control leave the battlefield without dying, "); - } - - private AangAirbendingMasterTriggeredAbility(final AangAirbendingMasterTriggeredAbility ability) { - super(ability); - } - - @Override - public AangAirbendingMasterTriggeredAbility copy() { - return new AangAirbendingMasterTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH; - } - - @Override - public boolean checkEvent(ZoneChangeEvent event, Game game) { - if (event.getFromZone() != Zone.BATTLEFIELD || event.getToZone() == Zone.GRAVEYARD) { - return false; - } - Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - return permanent != null && permanent.isCreature(game) && permanent.isControlledBy(getControllerId()); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return !getFilteredEvents((ZoneChangeBatchEvent) event, game).isEmpty(); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DourPortMage.java b/Mage.Sets/src/mage/cards/d/DourPortMage.java index 34cf369b0b7..070db06b979 100644 --- a/Mage.Sets/src/mage/cards/d/DourPortMage.java +++ b/Mage.Sets/src/mage/cards/d/DourPortMage.java @@ -2,8 +2,7 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.BatchTriggeredAbility; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.OneOrMoreLeaveWithoutDyingTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -13,13 +12,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeBatchEvent; -import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import java.util.UUID; @@ -38,7 +31,9 @@ public final class DourPortMage extends CardImpl { this.toughness = new MageInt(3); // Whenever one or more other creatures you control leave the battlefield without dying, draw a card. - this.addAbility(new DourPortMageTriggeredAbility()); + this.addAbility(new OneOrMoreLeaveWithoutDyingTriggeredAbility( + new DrawCardSourceControllerEffect(1), StaticFilters.FILTER_OTHER_CONTROLLED_CREATURES + )); // {1}{U}, {T}: Return another target creature you control to its owner's hand. Ability ability = new SimpleActivatedAbility(new ReturnToHandTargetEffect(), new ManaCostsImpl<>("{1}{U}")); @@ -56,39 +51,3 @@ public final class DourPortMage extends CardImpl { return new DourPortMage(this); } } - -class DourPortMageTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility { - - DourPortMageTriggeredAbility() { - super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1)); - setTriggerPhrase("Whenever one or more other creatures you control leave the battlefield without dying, "); - } - - private DourPortMageTriggeredAbility(final DourPortMageTriggeredAbility ability) { - super(ability); - } - - @Override - public DourPortMageTriggeredAbility copy() { - return new DourPortMageTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH; - } - - @Override - public boolean checkEvent(ZoneChangeEvent event, Game game) { - if (event.getFromZone() != Zone.BATTLEFIELD || event.getToZone() == Zone.GRAVEYARD || event.getTargetId().equals(getSourceId())) { - return false; - } - Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - return permanent != null && permanent.isCreature(game) && permanent.isControlledBy(getControllerId()); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return !getFilteredEvents((ZoneChangeBatchEvent) event, game).isEmpty(); - } -} diff --git a/Mage/src/main/java/mage/abilities/common/OneOrMoreLeaveWithoutDyingTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/OneOrMoreLeaveWithoutDyingTriggeredAbility.java new file mode 100644 index 00000000000..cad44fa1bf2 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/OneOrMoreLeaveWithoutDyingTriggeredAbility.java @@ -0,0 +1,52 @@ +package mage.abilities.common; + +import mage.abilities.BatchTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeBatchEvent; +import mage.game.events.ZoneChangeEvent; + +/** + * @author TheElk801 + */ +public class OneOrMoreLeaveWithoutDyingTriggeredAbility extends TriggeredAbilityImpl implements BatchTriggeredAbility { + + private final FilterPermanent filter; + + public OneOrMoreLeaveWithoutDyingTriggeredAbility(Effect effect, FilterPermanent filter) { + super(Zone.BATTLEFIELD, effect); + this.filter = filter; + setTriggerPhrase("Whenever one or more " + filter.getMessage() + " leave the battlefield without dying, "); + } + + private OneOrMoreLeaveWithoutDyingTriggeredAbility(final OneOrMoreLeaveWithoutDyingTriggeredAbility ability) { + super(ability); + this.filter = ability.filter; + } + + @Override + public OneOrMoreLeaveWithoutDyingTriggeredAbility copy() { + return new OneOrMoreLeaveWithoutDyingTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE_BATCH; + } + + @Override + public boolean checkEvent(ZoneChangeEvent event, Game game) { + return Zone.BATTLEFIELD.match(event.getFromZone()) + && !Zone.GRAVEYARD.match(event.getToZone()) + && filter.match(event.getTarget(), getControllerId(), this, game); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return !getFilteredEvents((ZoneChangeBatchEvent) event, game).isEmpty(); + } +}