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; + } +}