[MKM] Implement Kylox's Voltstrider; adjust Collect evidence cost (#11800)

This commit is contained in:
Matthew Wilson 2024-02-21 07:53:46 +02:00 committed by GitHub
parent 1df59f2f32
commit 244f8d24cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 177 additions and 1 deletions

View file

@ -0,0 +1,163 @@
package mage.cards.k;
import java.util.UUID;
import mage.ApprovingObject;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.CollectEvidenceCost;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect;
import mage.cards.Card;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.abilities.keyword.CrewAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInExile;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
/**
*
* @author DominionSpy
*/
public final class KyloxsVoltstrider extends CardImpl {
public KyloxsVoltstrider(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{U}{R}");
this.subtype.add(SubType.VEHICLE);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Collect evidence 6: Kylox's Voltstrider becomes an artifact creature until end of turn.
this.addAbility(new SimpleActivatedAbility(
new AddCardTypeSourceEffect(Duration.EndOfTurn, CardType.ARTIFACT, CardType.CREATURE)
.setText("{this} becomes an artifact creature until end of turn"),
new CollectEvidenceCost(6, true)));
// Whenever Kylox's Voltstrider attacks, you may cast an instant or sorcery spell from among cards exiled with it.
// If that spell would be put into a graveyard, put it on the bottom of its owner's library instead.
this.addAbility(new AttacksTriggeredAbility(new KyloxsVoltstriderEffect(), true));
// Crew 2
this.addAbility(new CrewAbility(2));
}
private KyloxsVoltstrider(final KyloxsVoltstrider card) {
super(card);
}
@Override
public KyloxsVoltstrider copy() {
return new KyloxsVoltstrider(this);
}
}
class KyloxsVoltstriderEffect extends OneShotEffect {
KyloxsVoltstriderEffect() {
super(Outcome.Benefit);
this.staticText = "you may cast an instant or sorcery spell from among cards exiled with it. " +
"If that spell would be put into a graveyard, put it on the bottom of its owner's library instead.";
}
private KyloxsVoltstriderEffect(final KyloxsVoltstriderEffect effect) {
super(effect);
}
@Override
public KyloxsVoltstriderEffect copy() {
return new KyloxsVoltstriderEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(),
game.getState().getZoneChangeCounter(source.getSourceId()));
ExileZone exileZone = game.getExile().getExileZone(exileId);
if (controller == null || exileZone == null) {
return false;
}
TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY, exileId);
target.withNotTarget(true);
if (!target.canChoose(source.getControllerId(), source, game)) {
return true;
}
controller.chooseTarget(outcome, target, source, game);
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
controller.cast(controller.chooseAbilityForCast(card, game, false),
game, false, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
// If that spell would be put into a graveyard, put it on the bottom of its owner's library instead.
ContinuousEffect effect = new KyloxsVoltstriderReplacementEffect();
effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source);
}
return true;
}
}
class KyloxsVoltstriderReplacementEffect extends ReplacementEffectImpl {
KyloxsVoltstriderReplacementEffect() {
super(Duration.Custom, Outcome.Exile);
staticText = "If that spell would be put into a graveyard, put it on the bottom of its owner's library instead.";
}
private KyloxsVoltstriderReplacementEffect(final KyloxsVoltstriderReplacementEffect effect) {
super(effect);
}
@Override
public KyloxsVoltstriderReplacementEffect copy() {
return new KyloxsVoltstriderReplacementEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
return zEvent.getToZone() == Zone.GRAVEYARD &&
event.getTargetId().equals(((FixedTarget) getTargetPointer()).getTarget()) &&
((FixedTarget) getTargetPointer()).getZoneChangeCounter() ==
game.getState().getZoneChangeCounter(zEvent.getTargetId());
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (card == null || controller == null) {
return false;
}
controller.putCardsOnBottomOfLibrary(card, game, source, false);
return true;
}
}

View file

@ -143,6 +143,7 @@ public final class MurdersAtKarlovManor extends ExpansionSet {
cards.add(new SetCardInfo("Krenko's Buzzcrusher", 136, Rarity.RARE, mage.cards.k.KrenkosBuzzcrusher.class));
cards.add(new SetCardInfo("Krenko, Baron of Tin Street", 135, Rarity.RARE, mage.cards.k.KrenkoBaronOfTinStreet.class));
cards.add(new SetCardInfo("Krovod Haunch", 21, Rarity.UNCOMMON, mage.cards.k.KrovodHaunch.class));
cards.add(new SetCardInfo("Kylox's Voltstrider", 215, Rarity.MYTHIC, mage.cards.k.KyloxsVoltstrider.class));
cards.add(new SetCardInfo("Kylox, Visionary Inventor", 214, Rarity.RARE, mage.cards.k.KyloxVisionaryInventor.class));
cards.add(new SetCardInfo("Lamplight Phoenix", 137, Rarity.RARE, mage.cards.l.LamplightPhoenix.class));
cards.add(new SetCardInfo("Lazav, Wearer of Faces", 216, Rarity.RARE, mage.cards.l.LazavWearerOfFaces.class));

View file

@ -14,6 +14,7 @@ import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInYourGraveyard;
import mage.util.CardUtil;
import java.awt.*;
import java.util.Objects;
@ -25,16 +26,23 @@ import java.util.UUID;
public class CollectEvidenceCost extends CostImpl {
private final int amount;
private final boolean withSource;
public CollectEvidenceCost(int amount) {
this(amount, false);
}
public CollectEvidenceCost(int amount, boolean withSource) {
super();
this.amount = amount;
this.withSource = withSource;
this.text = "collect evidence " + amount;
}
private CollectEvidenceCost(final CollectEvidenceCost cost) {
super(cost);
this.amount = cost.amount;
this.withSource = cost.withSource;
}
@Override
@ -83,7 +91,11 @@ public class CollectEvidenceCost extends CostImpl {
.mapToInt(MageObject::getManaValue)
.sum() >= amount;
if (paid) {
player.moveCards(cards, Zone.EXILED, source, game);
if (withSource) {
player.moveCardsToExile(cards.getCards(game), source, game, true, CardUtil.getExileZoneId(game, source), CardUtil.getSourceName(game, source));
} else {
player.moveCards(cards, Zone.EXILED, source, game);
}
game.fireEvent(GameEvent.getEvent(
GameEvent.EventType.EVIDENCE_COLLECTED,
source.getSourceId(), source, source.getControllerId(), amount