From 051301260614124bd226bf2d8627334c5dee59e7 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 10 Jul 2025 09:55:51 -0400 Subject: [PATCH] [EOE] Implement The Endstone --- Mage.Sets/src/mage/cards/f/FlubsTheFool.java | 52 ++++---------- .../src/mage/cards/i/InfernalSovereign.java | 38 ++-------- .../cards/p/PiaNalaarConsulOfRevival.java | 6 +- Mage.Sets/src/mage/cards/t/TheEndstone.java | 70 +++++++++++++++++++ .../src/mage/cards/u/UriangerAugurelt.java | 4 +- Mage.Sets/src/mage/sets/EdgeOfEternities.java | 4 ++ ...dOrCastSpellFromExileTriggeredAbility.java | 38 ---------- .../PlayLandOrCastSpellTriggeredAbility.java | 46 ++++++++++++ 8 files changed, 144 insertions(+), 114 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/t/TheEndstone.java delete mode 100644 Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellFromExileTriggeredAbility.java create mode 100644 Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellTriggeredAbility.java diff --git a/Mage.Sets/src/mage/cards/f/FlubsTheFool.java b/Mage.Sets/src/mage/cards/f/FlubsTheFool.java index 4eb42eba9b2..1e0162a1d5c 100644 --- a/Mage.Sets/src/mage/cards/f/FlubsTheFool.java +++ b/Mage.Sets/src/mage/cards/f/FlubsTheFool.java @@ -1,20 +1,21 @@ package mage.cards.f; -import java.util.UUID; - import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.PlayLandOrCastSpellTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.HellbentCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.PlayAdditionalLandsControllerEffect; import mage.abilities.effects.common.discard.DiscardControllerEffect; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.game.Game; -import mage.game.events.GameEvent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; + +import java.util.UUID; /** * @author Cguy7777 @@ -32,10 +33,14 @@ public final class FlubsTheFool extends CardImpl { // You may play an additional land on each of your turns. this.addAbility(new SimpleStaticAbility( - new PlayAdditionalLandsControllerEffect(1, Duration.WhileOnBattlefield))); + new PlayAdditionalLandsControllerEffect(1, Duration.WhileOnBattlefield) + )); // Whenever you play a land or cast a spell, draw a card if you have no cards in hand. Otherwise, discard a card. - this.addAbility(new FlubsTheFoolTriggeredAbility()); + this.addAbility(new PlayLandOrCastSpellTriggeredAbility(new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(1), new DiscardControllerEffect(1), + HellbentCondition.instance, "draw a card if you have no cards in hand. Otherwise, discard a card" + ))); } private FlubsTheFool(final FlubsTheFool card) { @@ -47,34 +52,3 @@ public final class FlubsTheFool extends CardImpl { return new FlubsTheFool(this); } } - -class FlubsTheFoolTriggeredAbility extends TriggeredAbilityImpl { - - FlubsTheFoolTriggeredAbility() { - super(Zone.BATTLEFIELD, new ConditionalOneShotEffect( - new DrawCardSourceControllerEffect(1), - new DiscardControllerEffect(1), - HellbentCondition.instance, - "draw a card if you have no cards in hand. Otherwise, discard a card")); - setTriggerPhrase("Whenever you play a land or cast a spell, "); - } - - private FlubsTheFoolTriggeredAbility(final FlubsTheFoolTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.LAND_PLAYED || event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals(controllerId); - } - - @Override - public FlubsTheFoolTriggeredAbility copy() { - return new FlubsTheFoolTriggeredAbility(this); - } -} diff --git a/Mage.Sets/src/mage/cards/i/InfernalSovereign.java b/Mage.Sets/src/mage/cards/i/InfernalSovereign.java index 05615210eeb..07af6fe2061 100644 --- a/Mage.Sets/src/mage/cards/i/InfernalSovereign.java +++ b/Mage.Sets/src/mage/cards/i/InfernalSovereign.java @@ -1,7 +1,8 @@ package mage.cards.i; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.PlayLandOrCastSpellTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; @@ -12,9 +13,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; import java.util.UUID; @@ -39,7 +37,9 @@ public final class InfernalSovereign extends CardImpl { this.addAbility(new SimpleStaticAbility(new SkipDrawStepEffect())); // Whenever you play a land or cast a spell, you draw a card and you lose 1 life. - this.addAbility(new InfernalSovereignTriggeredAbility()); + Ability ability = new PlayLandOrCastSpellTriggeredAbility(new DrawCardSourceControllerEffect(1, true)); + ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and")); + this.addAbility(ability); } private InfernalSovereign(final InfernalSovereign card) { @@ -51,31 +51,3 @@ public final class InfernalSovereign extends CardImpl { return new InfernalSovereign(this); } } - -class InfernalSovereignTriggeredAbility extends TriggeredAbilityImpl { - - public InfernalSovereignTriggeredAbility() { - super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1).setText("you draw a card")); - this.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and")); - setTriggerPhrase("Whenever you play a land or cast a spell, "); - } - - private InfernalSovereignTriggeredAbility(final InfernalSovereignTriggeredAbility ability) { - super(ability); - } - - @Override - public InfernalSovereignTriggeredAbility copy() { - return new InfernalSovereignTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.LAND_PLAYED || event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals(controllerId); - } -} diff --git a/Mage.Sets/src/mage/cards/p/PiaNalaarConsulOfRevival.java b/Mage.Sets/src/mage/cards/p/PiaNalaarConsulOfRevival.java index d1d824a73c4..408f158493c 100644 --- a/Mage.Sets/src/mage/cards/p/PiaNalaarConsulOfRevival.java +++ b/Mage.Sets/src/mage/cards/p/PiaNalaarConsulOfRevival.java @@ -1,7 +1,7 @@ package mage.cards.p; import mage.MageInt; -import mage.abilities.common.PlayLandOrCastSpellFromExileTriggeredAbility; +import mage.abilities.common.PlayLandOrCastSpellTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; @@ -39,7 +39,9 @@ public final class PiaNalaarConsulOfRevival extends CardImpl { ))); // Whenever you play a land from exile or cast a spell from exile, create a 1/1 colorless Thopter artifact creature token with flying. - this.addAbility(new PlayLandOrCastSpellFromExileTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken()))); + this.addAbility(new PlayLandOrCastSpellTriggeredAbility( + new CreateTokenEffect(new ThopterColorlessToken()), true, false + )); } private PiaNalaarConsulOfRevival(final PiaNalaarConsulOfRevival card) { diff --git a/Mage.Sets/src/mage/cards/t/TheEndstone.java b/Mage.Sets/src/mage/cards/t/TheEndstone.java new file mode 100644 index 00000000000..c38de5d4f99 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheEndstone.java @@ -0,0 +1,70 @@ +package mage.cards.t; + +import mage.abilities.Ability; +import mage.abilities.common.PlayLandOrCastSpellTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.game.Controllable; +import mage.game.Game; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheEndstone extends CardImpl { + + public TheEndstone(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{7}"); + + this.supertype.add(SuperType.LEGENDARY); + + // Whenever you play a land or cast a spell, draw a card. + this.addAbility(new PlayLandOrCastSpellTriggeredAbility(new DrawCardSourceControllerEffect(1))); + + // At the beginning of your end step, your life total becomes half your starting life total, rounded up. + this.addAbility(new BeginningOfEndStepTriggeredAbility(new TheEndstoneEffect())); + } + + private TheEndstone(final TheEndstone card) { + super(card); + } + + @Override + public TheEndstone copy() { + return new TheEndstone(this); + } +} + +class TheEndstoneEffect extends OneShotEffect { + + TheEndstoneEffect() { + super(Outcome.Benefit); + staticText = "your life total becomes half your starting life total, rounded up"; + } + + private TheEndstoneEffect(final TheEndstoneEffect effect) { + super(effect); + } + + @Override + public TheEndstoneEffect copy() { + return new TheEndstoneEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Optional.ofNullable(source) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .ifPresent(player -> player.setLife(game.getStartingLife() / 2 + game.getStartingLife() % 2, game, source)); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/u/UriangerAugurelt.java b/Mage.Sets/src/mage/cards/u/UriangerAugurelt.java index a72e0d4c91d..df9fcd03c86 100644 --- a/Mage.Sets/src/mage/cards/u/UriangerAugurelt.java +++ b/Mage.Sets/src/mage/cards/u/UriangerAugurelt.java @@ -3,7 +3,7 @@ package mage.cards.u; import mage.MageIdentifier; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.PlayLandOrCastSpellFromExileTriggeredAbility; +import mage.abilities.common.PlayLandOrCastSpellTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.AsThoughEffectImpl; @@ -38,7 +38,7 @@ public final class UriangerAugurelt extends CardImpl { this.toughness = new MageInt(3); // Whenever you play a land from exile or cast a spell from exile, you gain 2 life. - this.addAbility(new PlayLandOrCastSpellFromExileTriggeredAbility(new GainLifeEffect(2))); + this.addAbility(new PlayLandOrCastSpellTriggeredAbility(new GainLifeEffect(2), true, false)); // Draw Arcanum -- {T}: Look at the top card of your library. You may exile it face down. this.addAbility(new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/sets/EdgeOfEternities.java b/Mage.Sets/src/mage/sets/EdgeOfEternities.java index d4a35ffaef8..a0e3e43502b 100644 --- a/Mage.Sets/src/mage/sets/EdgeOfEternities.java +++ b/Mage.Sets/src/mage/sets/EdgeOfEternities.java @@ -154,6 +154,10 @@ public final class EdgeOfEternities extends ExpansionSet { cards.add(new SetCardInfo("Terrasymbiosis", 312, Rarity.RARE, mage.cards.t.Terrasymbiosis.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tezzeret, Cruel Captain", 2, Rarity.MYTHIC, mage.cards.t.TezzeretCruelCaptain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Tezzeret, Cruel Captain", 287, Rarity.MYTHIC, mage.cards.t.TezzeretCruelCaptain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Endstone", 240, Rarity.MYTHIC, mage.cards.t.TheEndstone.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Endstone", 353, Rarity.MYTHIC, mage.cards.t.TheEndstone.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Endstone", 365, Rarity.MYTHIC, mage.cards.t.TheEndstone.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Endstone", 391, Rarity.MYTHIC, mage.cards.t.TheEndstone.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Eternity Elevator", 241, Rarity.RARE, mage.cards.t.TheEternityElevator.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Eternity Elevator", 354, Rarity.RARE, mage.cards.t.TheEternityElevator.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Seriema", 323, Rarity.RARE, mage.cards.t.TheSeriema.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellFromExileTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellFromExileTriggeredAbility.java deleted file mode 100644 index ff24dcc6cd6..00000000000 --- a/Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellFromExileTriggeredAbility.java +++ /dev/null @@ -1,38 +0,0 @@ -package mage.abilities.common; - -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; - -/** - * @author TheElk801 - */ -public class PlayLandOrCastSpellFromExileTriggeredAbility extends TriggeredAbilityImpl { - - public PlayLandOrCastSpellFromExileTriggeredAbility(Effect effect) { - super(Zone.BATTLEFIELD, effect); - setTriggerPhrase("Whenever you play a land from exile or cast a spell from exile, "); - } - - private PlayLandOrCastSpellFromExileTriggeredAbility(final PlayLandOrCastSpellFromExileTriggeredAbility ability) { - super(ability); - } - - @Override - public PlayLandOrCastSpellFromExileTriggeredAbility copy() { - return new PlayLandOrCastSpellFromExileTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.LAND_PLAYED - || event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return isControlledBy(event.getPlayerId()) && event.getZone() == Zone.EXILED; - } -} diff --git a/Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellTriggeredAbility.java new file mode 100644 index 00000000000..40a89e8dc3e --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/PlayLandOrCastSpellTriggeredAbility.java @@ -0,0 +1,46 @@ +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * @author TheElk801 + */ +public class PlayLandOrCastSpellTriggeredAbility extends TriggeredAbilityImpl { + + private final boolean fromExile; + + public PlayLandOrCastSpellTriggeredAbility(Effect effect) { + this(effect, false, false); + } + + public PlayLandOrCastSpellTriggeredAbility(Effect effect, boolean fromExile, boolean optional) { + super(Zone.BATTLEFIELD, effect, optional); + this.fromExile = fromExile; + setTriggerPhrase("Whenever you play a land from exile or cast a spell" + (fromExile ? " from exile" : "") + ", "); + } + + private PlayLandOrCastSpellTriggeredAbility(final PlayLandOrCastSpellTriggeredAbility ability) { + super(ability); + this.fromExile = ability.fromExile; + } + + @Override + public PlayLandOrCastSpellTriggeredAbility copy() { + return new PlayLandOrCastSpellTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.LAND_PLAYED + || event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return isControlledBy(event.getPlayerId()) && (!fromExile || event.getZone() == Zone.EXILED); + } +}