From 7c55d444b08a09af9d10fd20e1ac84c2b6a2d1af Mon Sep 17 00:00:00 2001
From: Jmlundeen <98545818+Jmlundeen@users.noreply.github.com>
Date: Sat, 15 Mar 2025 19:17:44 -0500
Subject: [PATCH] [DFT] Implement Push the Limit (#13408)
---
.../src/mage/cards/a/ArmedAndArmored.java | 39 +------
Mage.Sets/src/mage/cards/p/PushTheLimit.java | 108 ++++++++++++++++++
.../src/mage/cards/s/StartYourEngines.java | 39 +------
Mage.Sets/src/mage/sets/Aetherdrift.java | 1 +
.../VehiclesBecomeArtifactCreatureEffect.java | 42 +++++++
5 files changed, 155 insertions(+), 74 deletions(-)
create mode 100644 Mage.Sets/src/mage/cards/p/PushTheLimit.java
create mode 100644 Mage/src/main/java/mage/abilities/effects/common/continuous/VehiclesBecomeArtifactCreatureEffect.java
diff --git a/Mage.Sets/src/mage/cards/a/ArmedAndArmored.java b/Mage.Sets/src/mage/cards/a/ArmedAndArmored.java
index 6dd15a380c7..614df035243 100644
--- a/Mage.Sets/src/mage/cards/a/ArmedAndArmored.java
+++ b/Mage.Sets/src/mage/cards/a/ArmedAndArmored.java
@@ -4,8 +4,8 @@ import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.VehiclesBecomeArtifactCreatureEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@@ -25,7 +25,7 @@ public final class ArmedAndArmored extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Vehicles you control become artifact creatures until end of turn.
- this.getSpellAbility().addEffect(new ArmedAndArmoredEffect());
+ this.getSpellAbility().addEffect(new VehiclesBecomeArtifactCreatureEffect(Duration.EndOfTurn));
// Choose a Dwarf you control. Attach any number of Equipment you control to it.
this.getSpellAbility().addEffect(new ArmedAndArmoredEquipEffect());
@@ -41,41 +41,6 @@ public final class ArmedAndArmored extends CardImpl {
}
}
-class ArmedAndArmoredEffect extends ContinuousEffectImpl {
-
- ArmedAndArmoredEffect() {
- super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
- staticText = "Vehicles you control become artifact creatures until end of turn";
- }
-
- private ArmedAndArmoredEffect(final ArmedAndArmoredEffect effect) {
- super(effect);
- }
-
- @Override
- public ArmedAndArmoredEffect copy() {
- return new ArmedAndArmoredEffect(this);
- }
-
- @Override
- public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
- for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
- if (permanent != null && permanent.hasSubtype(SubType.VEHICLE, game)) {
- if (sublayer == SubLayer.NA) {
- permanent.addCardType(game, CardType.ARTIFACT);
- permanent.addCardType(game, CardType.CREATURE);// TODO: Check if giving CREATURE Type is correct
- }
- }
- }
- return true;
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return false;
- }
-}
-
class ArmedAndArmoredEquipEffect extends OneShotEffect {
ArmedAndArmoredEquipEffect() {
diff --git a/Mage.Sets/src/mage/cards/p/PushTheLimit.java b/Mage.Sets/src/mage/cards/p/PushTheLimit.java
new file mode 100644
index 00000000000..1ee2960811f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/PushTheLimit.java
@@ -0,0 +1,108 @@
+package mage.cards.p;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import mage.MageObjectReference;
+import mage.abilities.Ability;
+import mage.abilities.DelayedTriggeredAbility;
+import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.*;
+import mage.abilities.effects.common.continuous.BecomesSubtypeAllEffect;
+import mage.abilities.effects.common.continuous.CreaturesBecomeOtherTypeEffect;
+import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
+import mage.abilities.effects.common.continuous.VehiclesBecomeArtifactCreatureEffect;
+import mage.abilities.keyword.HasteAbility;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.Cards;
+import mage.constants.*;
+import mage.filter.FilterCard;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.mageobject.MageObjectReferencePredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.targetpointer.FixedTargets;
+
+/**
+ *
+ * @author Jmlundeen
+ */
+public final class PushTheLimit extends CardImpl {
+ private static final FilterPermanent filterCreatures = new FilterControlledPermanent("Creatures you control");
+
+ public PushTheLimit(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{R}{R}");
+
+
+ // Return all Mount and Vehicle cards from your graveyard to the battlefield. Sacrifice them at the beginning of the next end step.
+ this.getSpellAbility().addEffect(new PushTheLimitEffect());
+ // Vehicles you control become artifact creatures until end of turn. Creatures you control gain haste until end of turn.
+ this.getSpellAbility().addEffect(new VehiclesBecomeArtifactCreatureEffect(Duration.EndOfTurn)
+ .concatBy("
"));
+ this.getSpellAbility().addEffect(new GainAbilityAllEffect(HasteAbility.getInstance(), Duration.EndOfTurn, filterCreatures));
+ }
+
+ private PushTheLimit(final PushTheLimit card) {
+ super(card);
+ }
+
+ @Override
+ public PushTheLimit copy() {
+ return new PushTheLimit(this);
+ }
+}
+
+class PushTheLimitEffect extends OneShotEffect {
+ private static final FilterCard filter = new FilterCard("Mount and Vehicle cards");
+ static {
+ filter.add(Predicates.or(
+ SubType.MOUNT.getPredicate(),
+ SubType.VEHICLE.getPredicate()
+ ));
+ }
+ public PushTheLimitEffect() {
+ super(Outcome.PutCreatureInPlay);
+ staticText = "return all " + filter.getMessage() + " from your graveyard to the battlefield. " +
+ "Sacrifice them at the beginning of the next end step.";
+ }
+
+ public PushTheLimitEffect(final PushTheLimitEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public PushTheLimitEffect copy() {
+ return new PushTheLimitEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller == null) {
+ return false;
+ }
+ Set cards = controller.getGraveyard().getCards(filter, source.getControllerId(), source, game);
+ boolean result = controller.moveCards(cards, Zone.BATTLEFIELD, source, game,
+ false, false, false, null);
+ if (result) {
+ List permanentsToSac = cards.stream()
+ .map(card -> game.getPermanent(card.getId()))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ Effect sacrificeEffect = new SacrificeTargetEffect("sacrifice them", source.getControllerId());
+ sacrificeEffect.setTargetPointer(new FixedTargets(permanentsToSac, game));
+ game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(sacrificeEffect), source);
+ }
+ return result;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/StartYourEngines.java b/Mage.Sets/src/mage/cards/s/StartYourEngines.java
index a14c7ede336..bba91ec4f90 100644
--- a/Mage.Sets/src/mage/cards/s/StartYourEngines.java
+++ b/Mage.Sets/src/mage/cards/s/StartYourEngines.java
@@ -6,6 +6,7 @@ import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
+import mage.abilities.effects.common.continuous.VehiclesBecomeArtifactCreatureEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@@ -22,7 +23,7 @@ public final class StartYourEngines extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}");
// Vehicles you control becomes artifact creatures until end of turn.
- Effect effect = new StartYourEnginesEffect();
+ Effect effect = new VehiclesBecomeArtifactCreatureEffect(Duration.EndOfTurn);
this.getSpellAbility().addEffect(effect);
// Creatures you control get +2/+0 until end of turn.
@@ -38,39 +39,3 @@ public final class StartYourEngines extends CardImpl {
return new StartYourEngines(this);
}
}
-
-class StartYourEnginesEffect extends ContinuousEffectImpl {
-
- StartYourEnginesEffect() {
- super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
- staticText = "Vehicles you control become artifact creatures until end of turn";
- }
-
- private StartYourEnginesEffect(final StartYourEnginesEffect effect) {
- super(effect);
- }
-
- @Override
- public StartYourEnginesEffect copy() {
- return new StartYourEnginesEffect(this);
- }
-
- @Override
- public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
- for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
- if (permanent != null && permanent.hasSubtype(SubType.VEHICLE, game)) {
- if (sublayer == SubLayer.NA) {
- permanent.addCardType(game, CardType.ARTIFACT);
- permanent.addCardType(game, CardType.CREATURE);// TODO: Check if giving CREATURE Type is correct
- }
- }
- }
- return true;
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return false;
- }
-
-}
diff --git a/Mage.Sets/src/mage/sets/Aetherdrift.java b/Mage.Sets/src/mage/sets/Aetherdrift.java
index 5e2dbd77c71..b3174d15646 100644
--- a/Mage.Sets/src/mage/sets/Aetherdrift.java
+++ b/Mage.Sets/src/mage/sets/Aetherdrift.java
@@ -214,6 +214,7 @@ public final class Aetherdrift extends ExpansionSet {
cards.add(new SetCardInfo("Pothole Mole", 176, Rarity.COMMON, mage.cards.p.PotholeMole.class));
cards.add(new SetCardInfo("Pride of the Road", 24, Rarity.UNCOMMON, mage.cards.p.PrideOfTheRoad.class));
cards.add(new SetCardInfo("Prowcatcher Specialist", 142, Rarity.COMMON, mage.cards.p.ProwcatcherSpecialist.class));
+ cards.add(new SetCardInfo("Push the Limit", 143, Rarity.UNCOMMON, mage.cards.p.PushTheLimit.class));
cards.add(new SetCardInfo("Pyrewood Gearhulk", 216, Rarity.MYTHIC, mage.cards.p.PyrewoodGearhulk.class));
cards.add(new SetCardInfo("Quag Feast", 100, Rarity.RARE, mage.cards.q.QuagFeast.class));
cards.add(new SetCardInfo("Racers' Scoreboard", 239, Rarity.UNCOMMON, mage.cards.r.RacersScoreboard.class));
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/VehiclesBecomeArtifactCreatureEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/VehiclesBecomeArtifactCreatureEffect.java
new file mode 100644
index 00000000000..961adf11310
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/VehiclesBecomeArtifactCreatureEffect.java
@@ -0,0 +1,42 @@
+package mage.abilities.effects.common.continuous;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.ContinuousEffectImpl;
+import mage.constants.*;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+
+public class VehiclesBecomeArtifactCreatureEffect extends ContinuousEffectImpl {
+
+ public VehiclesBecomeArtifactCreatureEffect(Duration duration) {
+ super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.BecomeCreature);
+ staticText = "Vehicles you control become artifact creatures until end of turn";
+ }
+
+ private VehiclesBecomeArtifactCreatureEffect(final VehiclesBecomeArtifactCreatureEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public VehiclesBecomeArtifactCreatureEffect copy() {
+ return new VehiclesBecomeArtifactCreatureEffect(this);
+ }
+
+ @Override
+ public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
+ for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
+ if (permanent != null && permanent.hasSubtype(SubType.VEHICLE, game)) {
+ if (sublayer == SubLayer.NA) {
+ permanent.addCardType(game, CardType.ARTIFACT);
+ permanent.addCardType(game, CardType.CREATURE);// TODO: Check if giving CREATURE Type is correct
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return false;
+ }
+}