diff --git a/Mage.Sets/src/mage/cards/d/DreadhordeArcanist.java b/Mage.Sets/src/mage/cards/d/DreadhordeArcanist.java new file mode 100644 index 0000000000..0a7880c94c --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DreadhordeArcanist.java @@ -0,0 +1,165 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.common.FilterInstantOrSorceryCard; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DreadhordeArcanist extends CardImpl { + + private static final FilterCard filter = new FilterInstantOrSorceryCard( + "instant or sorcery card with converted mana cost less than or equal to this creature's power" + ); + + static { + filter.add(DreadhordeArcanistPredicate.instance); + } + + public DreadhordeArcanist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); + + this.subtype.add(SubType.ZOMBIE); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Whenever Dreadhorde Arcanist attacks, you may cast target instant or sorcery card with converted mana cost less than or equal to Dreadhorde Arcanist's power from your graveyard without paying its mana cost. If that card would be put into your graveyard this turn, exile it instead. + Ability ability = new AttacksTriggeredAbility(new DreadhordeArcanistEffect(), false); + ability.addTarget(new TargetCardInYourGraveyard(filter)); + this.addAbility(ability); + } + + private DreadhordeArcanist(final DreadhordeArcanist card) { + super(card); + } + + @Override + public DreadhordeArcanist copy() { + return new DreadhordeArcanist(this); + } +} + +enum DreadhordeArcanistPredicate implements ObjectSourcePlayerPredicate> { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(input.getSourceId()); + return sourcePermanent != null + & input.getObject().getConvertedManaCost() <= sourcePermanent.getPower().getValue(); + } +} + +class DreadhordeArcanistEffect extends OneShotEffect { + + DreadhordeArcanistEffect() { + super(Outcome.Benefit); + this.staticText = "you may cast target instant or sorcery card with converted mana cost " + + "less than or equal to {this}'s power from your graveyard without paying its mana cost. " + + "If that card would be put into your graveyard this turn, exile it instead."; + } + + private DreadhordeArcanistEffect(final DreadhordeArcanistEffect effect) { + super(effect); + } + + @Override + public DreadhordeArcanistEffect copy() { + return new DreadhordeArcanistEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Card card = game.getCard(this.getTargetPointer().getFirst(game, source)); + if (card == null + || !controller.chooseUse(outcome, "Cast " + card.getLogName() + '?', source, game) + || !controller.cast( + card.getSpellAbility(), game, true, + new MageObjectReference(source.getSourceObject(game), game) + )) { + return false; + } + ContinuousEffect effect = new DreadhordeArcanistReplacementEffect(card.getId()); + effect.setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId()))); + game.addEffect(effect, source); + return true; + } +} + +class DreadhordeArcanistReplacementEffect extends ReplacementEffectImpl { + + private final UUID cardId; + + DreadhordeArcanistReplacementEffect(UUID cardId) { + super(Duration.EndOfTurn, Outcome.Exile); + this.cardId = cardId; + staticText = "If that card would be put into your graveyard this turn, exile it instead"; + } + + private DreadhordeArcanistReplacementEffect(final DreadhordeArcanistReplacementEffect effect) { + super(effect); + this.cardId = effect.cardId; + } + + @Override + public DreadhordeArcanistReplacementEffect copy() { + return new DreadhordeArcanistReplacementEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + Card card = game.getCard(this.cardId); + if (controller != null && card != null) { + controller.moveCardToExileWithInfo( + card, null, "", source.getSourceId(), + game, Zone.STACK, true + ); + return true; + } + return false; + } + + @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 + && zEvent.getTargetId().equals(this.cardId); + } +} diff --git a/Mage.Sets/src/mage/sets/WarOfTheSpark.java b/Mage.Sets/src/mage/sets/WarOfTheSpark.java index 83a653e512..e78f328467 100644 --- a/Mage.Sets/src/mage/sets/WarOfTheSpark.java +++ b/Mage.Sets/src/mage/sets/WarOfTheSpark.java @@ -41,6 +41,7 @@ public final class WarOfTheSpark extends ExpansionSet { cards.add(new SetCardInfo("Davriel, Rogue Shadowmage", 83, Rarity.UNCOMMON, mage.cards.d.DavrielRogueShadowmage.class)); cards.add(new SetCardInfo("Deathsprout", 189, Rarity.UNCOMMON, mage.cards.d.Deathsprout.class)); cards.add(new SetCardInfo("Dovin's Veto", 193, Rarity.UNCOMMON, mage.cards.d.DovinsVeto.class)); + cards.add(new SetCardInfo("Dreadhorde Arcanist", 125, Rarity.RARE, mage.cards.d.DreadhordeArcanist.class)); cards.add(new SetCardInfo("Dreadhorde Butcher", 194, Rarity.RARE, mage.cards.d.DreadhordeButcher.class)); cards.add(new SetCardInfo("Dreadhorde Invasion", 86, Rarity.RARE, mage.cards.d.DreadhordeInvasion.class)); cards.add(new SetCardInfo("Emergence Zone", 245, Rarity.UNCOMMON, mage.cards.e.EmergenceZone.class));