[DFT] Canyon Vaulter, Cloudspire Skycycle, Dune Drifter (#13382)

* Support Mounts and Your Main restriction in CrewsVehicleSourceTriggeredAbility

* Genericize Reckless Velocitaur

* Implement [DFT] Canyon Vaulter, Cloudspire Skycycle, and Dune Drifter
This commit is contained in:
ssk97 2025-02-26 00:14:48 -08:00 committed by GitHub
parent a20e304234
commit 705ce2320d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 192 additions and 48 deletions

View file

@ -0,0 +1,43 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CrewsVehicleSourceTriggeredAbility;
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.Duration;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author notgreat
*/
public final class CanyonVaulter extends CardImpl {
public CanyonVaulter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.KOR);
this.subtype.add(SubType.PILOT);
this.power = new MageInt(3);
this.toughness = new MageInt(1);
// Whenever this creature saddles a Mount or crews a Vehicle during your main phase, that Mount or Vehicle gains flying until end of turn.
Effect effect = new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn);
effect.setText("that Mount or Vehicle gains flying until end of turn");
this.addAbility(new CrewsVehicleSourceTriggeredAbility(effect, true, true));
}
private CanyonVaulter(final CanyonVaulter card) {
super(card);
}
@Override
public CanyonVaulter copy() {
return new CanyonVaulter(this);
}
}

View file

@ -0,0 +1,60 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.counter.DistributeCountersEffect;
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.SubType;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.target.common.TargetPermanentAmount;
import java.util.UUID;
/**
* @author notgreat
*/
public final class CloudspireSkycycle extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("other target Vehicles and/or creatures you control");
static {
filter.add(AnotherPredicate.instance);
filter.add(Predicates.or(SubType.VEHICLE.getPredicate(), CardType.CREATURE.getPredicate()));
}
public CloudspireSkycycle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{R}{W}");
this.subtype.add(SubType.VEHICLE);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// When this Vehicle enters, distribute two +1/+1 counters among one or two other target Vehicles and/or creatures you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect());
ability.addTarget(new TargetPermanentAmount(2, 1, filter));
this.addAbility(ability);
// Crew 1
this.addAbility(new CrewAbility(1));
}
private CloudspireSkycycle(final CloudspireSkycycle card) {
super(card);
}
@Override
public CloudspireSkycycle copy() {
return new CloudspireSkycycle(this);
}
}

View file

@ -0,0 +1,57 @@
package mage.cards.d;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.keyword.CrewAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetadjustment.XManaValueTargetAdjuster;
import java.util.UUID;
/**
* @author notgreat
*/
public final class DuneDrifter extends CardImpl {
private static final FilterCard filter = new FilterCard("artifact or creature card with mana value X or less from your graveyard");
static {
filter.add(Predicates.or(CardType.ARTIFACT.getPredicate(), CardType.CREATURE.getPredicate()));
}
public DuneDrifter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{X}{W}{B}");
this.subtype.add(SubType.VEHICLE);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// When this Vehicle enters, return target artifact or creature card with mana value X or less from your graveyard to the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect());
ability.addTarget(new TargetCardInYourGraveyard(filter));
ability.setTargetAdjuster(new XManaValueTargetAdjuster(ComparisonType.OR_LESS));
this.addAbility(ability);
// Crew 2
this.addAbility(new CrewAbility(2));
}
private DuneDrifter(final DuneDrifter card) {
super(card);
}
@Override
public DuneDrifter copy() {
return new DuneDrifter(this);
}
}

View file

@ -1,18 +1,17 @@
package mage.cards.r;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CrewsVehicleSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
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.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
@ -30,7 +29,14 @@ public final class RecklessVelocitaur extends CardImpl {
this.toughness = new MageInt(3);
// Whenever this creature saddles a Mount or crews a Vehicle during your main phase, that Mount or Vehicle gets +2/+0 and gains trample until end of turn.
this.addAbility(new RecklessVelocitaurTriggeredAbility());
Effect boostEffect = new BoostTargetEffect(1, 1, Duration.EndOfTurn)
.setText("that Mount or Vehicle gets +2/+0");
Effect abilityGainEffect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn)
.setText("and gains trample until end of turn");
Ability ability = new CrewsVehicleSourceTriggeredAbility(boostEffect, true, true);
ability.addEffect(abilityGainEffect);
this.addAbility(ability);
}
private RecklessVelocitaur(final RecklessVelocitaur card) {
@ -42,43 +48,3 @@ public final class RecklessVelocitaur extends CardImpl {
return new RecklessVelocitaur(this);
}
}
class RecklessVelocitaurTriggeredAbility extends TriggeredAbilityImpl {
RecklessVelocitaurTriggeredAbility() {
super(Zone.BATTLEFIELD, new BoostTargetEffect(2, 0).setText("that Mount or Vehicle gets +2/+0"));
this.addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance()).setText("and gains trample until end of turn"));
this.setTriggerPhrase("Whenever {this} saddles a Mount or crews a Vehicle during your main phase, ");
}
private RecklessVelocitaurTriggeredAbility(final RecklessVelocitaurTriggeredAbility ability) {
super(ability);
}
@Override
public RecklessVelocitaurTriggeredAbility copy() {
return new RecklessVelocitaurTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
switch (event.getType()) {
case SADDLED_MOUNT:
case CREWED_VEHICLE:
return true;
default:
return false;
}
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!this.isControlledBy(game.getActivePlayerId())
|| !game.isMainPhase()
|| !event.getTargetId().equals(this.getSourceId())) {
return false;
}
this.getEffects().setTargetPointer(new FixedTarget(event.getSourceId()));
return true;
}
}

View file

@ -62,6 +62,7 @@ public final class Aetherdrift extends ExpansionSet {
cards.add(new SetCardInfo("Burnout Bashtronaut", 115, Rarity.RARE, mage.cards.b.BurnoutBashtronaut.class));
cards.add(new SetCardInfo("Caelorna, Coral Tyrant", 40, Rarity.UNCOMMON, mage.cards.c.CaelornaCoralTyrant.class));
cards.add(new SetCardInfo("Camera Launcher", 232, Rarity.COMMON, mage.cards.c.CameraLauncher.class));
cards.add(new SetCardInfo("Canyon Vaulter", 8, Rarity.UNCOMMON, mage.cards.c.CanyonVaulter.class));
cards.add(new SetCardInfo("Caradora, Heart of Alacria", 195, Rarity.RARE, mage.cards.c.CaradoraHeartOfAlacria.class));
cards.add(new SetCardInfo("Carrion Cruiser", 78, Rarity.UNCOMMON, mage.cards.c.CarrionCruiser.class));
cards.add(new SetCardInfo("Chandra, Spark Hunter", 116, Rarity.MYTHIC, mage.cards.c.ChandraSparkHunter.class));
@ -69,6 +70,7 @@ public final class Aetherdrift extends ExpansionSet {
cards.add(new SetCardInfo("Clamorous Ironclad", 117, Rarity.COMMON, mage.cards.c.ClamorousIronclad.class));
cards.add(new SetCardInfo("Cloudspire Captain", 9, Rarity.UNCOMMON, mage.cards.c.CloudspireCaptain.class));
cards.add(new SetCardInfo("Cloudspire Coordinator", 196, Rarity.UNCOMMON, mage.cards.c.CloudspireCoordinator.class));
cards.add(new SetCardInfo("Cloudspire Skycycle", 197, Rarity.UNCOMMON, mage.cards.c.CloudspireSkycycle.class));
cards.add(new SetCardInfo("Coalstoke Gearhulk", 198, Rarity.MYTHIC, mage.cards.c.CoalstokeGearhulk.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Coalstoke Gearhulk", 349, Rarity.MYTHIC, mage.cards.c.CoalstokeGearhulk.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Coalstoke Gearhulk", 477, Rarity.MYTHIC, mage.cards.c.CoalstokeGearhulk.class, NON_FULL_USE_VARIOUS));
@ -95,6 +97,7 @@ public final class Aetherdrift extends ExpansionSet {
cards.add(new SetCardInfo("Draconautics Engineer", 121, Rarity.RARE, mage.cards.d.DraconauticsEngineer.class));
cards.add(new SetCardInfo("Dracosaur Auxiliary", 122, Rarity.UNCOMMON, mage.cards.d.DracosaurAuxiliary.class));
cards.add(new SetCardInfo("Dredger's Insight", 159, Rarity.UNCOMMON, mage.cards.d.DredgersInsight.class));
cards.add(new SetCardInfo("Dune Drifter", 200, Rarity.UNCOMMON, mage.cards.d.DuneDrifter.class));
cards.add(new SetCardInfo("Dynamite Diver", 123, Rarity.COMMON, mage.cards.d.DynamiteDiver.class));
cards.add(new SetCardInfo("Earthrumbler", 160, Rarity.UNCOMMON, mage.cards.e.Earthrumbler.class));
cards.add(new SetCardInfo("Embalmed Ascendant", 201, Rarity.UNCOMMON, mage.cards.e.EmbalmedAscendant.class));

View file

@ -10,14 +10,26 @@ import mage.target.targetpointer.FixedTarget;
public class CrewsVehicleSourceTriggeredAbility extends TriggeredAbilityImpl {
private final boolean mountsAlso;
private final boolean yourMainPhaseOnly;
public CrewsVehicleSourceTriggeredAbility(Effect effect) {
this(effect, false, false);
}
public CrewsVehicleSourceTriggeredAbility(Effect effect, boolean mountsAlso, boolean yourMainPhaseOnly) {
super(Zone.BATTLEFIELD, effect, false);
this.addIcon(CardIconImpl.ABILITY_CREW);
setTriggerPhrase("Whenever {this} crews a Vehicle, ");
this.mountsAlso = mountsAlso;
this.yourMainPhaseOnly = yourMainPhaseOnly;
setTriggerPhrase("Whenever {this}" + (mountsAlso ? " saddles a Mount or" : "") +
" crews a Vehicle" + (yourMainPhaseOnly ? " during your main phase" : "") + ", ");
}
protected CrewsVehicleSourceTriggeredAbility(final CrewsVehicleSourceTriggeredAbility ability) {
super(ability);
this.mountsAlso = ability.mountsAlso;
this.yourMainPhaseOnly = ability.yourMainPhaseOnly;
}
@Override
@ -27,11 +39,14 @@ public class CrewsVehicleSourceTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.CREWED_VEHICLE;
return event.getType() == GameEvent.EventType.CREWED_VEHICLE || (mountsAlso && event.getType() == GameEvent.EventType.SADDLED_MOUNT);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (yourMainPhaseOnly && !(game.isMainPhase() && this.isControlledBy(game.getActivePlayerId()))) {
return false;
}
if (event.getTargetId().equals(getSourceId())) {
for (Effect effect : getEffects()) {
// set the vehicle id as target