From 6e145c65ce513dd59661417c8e5c14e5a964c5cc Mon Sep 17 00:00:00 2001 From: Matt M Date: Sun, 23 Apr 2023 22:13:21 +0100 Subject: [PATCH] [MOC] Implement Moira and Teshar (#10260) Co-authored-by: Zelane --- .../src/mage/cards/m/MoiraAndTeshar.java | 161 ++++++++++++++++++ .../mage/sets/MarchOfTheMachineCommander.java | 1 + 2 files changed, 162 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MoiraAndTeshar.java diff --git a/Mage.Sets/src/mage/cards/m/MoiraAndTeshar.java b/Mage.Sets/src/mage/cards/m/MoiraAndTeshar.java new file mode 100644 index 0000000000..56a6b3b2ad --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MoiraAndTeshar.java @@ -0,0 +1,161 @@ +package mage.cards.m; + +import java.util.UUID; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.common.FilterHistoricSpell; +import mage.filter.common.FilterPermanentCard; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetpointer.FixedTarget; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.game.events.ZoneChangeEvent; + +public final class MoiraAndTeshar extends CardImpl { + + private static final FilterSpell filter = new FilterHistoricSpell(); + private static final FilterPermanentCard targetFilter = new FilterPermanentCard( + "nonland permanent card from your graveyard"); + + public MoiraAndTeshar(UUID ownerId, CardSetInfo setInfo) { + + super(ownerId, setInfo, new CardType[] { CardType.CREATURE }, "{3}{W}{B}"); + addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.PHYREXIAN); + this.subtype.add(SubType.SPIRIT); + this.subtype.add(SubType.BIRD); + + this.power = new MageInt(4); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever you cast a historic spell, return target nonland permanent card from + // your graveyard to the battlefield. It gains haste. Exile it at the beginning + // of the next end step. + Ability ability = new SpellCastControllerTriggeredAbility(new MoiraAndTesharEffect(), filter, false); + ability.addTarget(new TargetCardInYourGraveyard(targetFilter)); + + // If it would leave the battlefield, exile it instead of putting it anywhere + // else. (Artifacts, legendaries, and Sagas are historic.) + ability.addEffect(new MoiraAndTesharReplacementEffect()); + this.addAbility(ability); + } + + private MoiraAndTeshar(final MoiraAndTeshar card) { + super(card); + } + + @Override + public Card copy() { + return new MoiraAndTeshar(this); + } +} + +class MoiraAndTesharEffect extends OneShotEffect { + + MoiraAndTesharEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Return target nonland permanent card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step"; + } + + private MoiraAndTesharEffect(final MoiraAndTesharEffect effect) { + super(effect); + } + + @Override + public MoiraAndTesharEffect copy() { + return new MoiraAndTesharEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(this.getTargetPointer().getFirst(game, source)); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && card != null) { + if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) { + Permanent permanent = game.getPermanent(card.getId()); + if (permanent != null) { + // It gains haste + ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); + // Exile at begin of next end step + ExileTargetEffect exileEffect = new ExileTargetEffect(null, null, Zone.BATTLEFIELD); + exileEffect.setTargetPointer(new FixedTarget(permanent, game)); + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect); + game.addDelayedTriggeredAbility(delayedAbility, source); + } + } + return true; + } + return false; + } +} + +class MoiraAndTesharReplacementEffect extends ReplacementEffectImpl { + + MoiraAndTesharReplacementEffect() { + super(Duration.EndOfTurn, Outcome.Tap); + staticText = "If it would leave the battlefield, exile it instead of putting it anywhere else"; + } + + private MoiraAndTesharReplacementEffect(final MoiraAndTesharReplacementEffect effect) { + super(effect); + } + + @Override + public MoiraAndTesharReplacementEffect copy() { + return new MoiraAndTesharReplacementEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + ((ZoneChangeEvent) event).setToZone(Zone.EXILED); + 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) { + if (event.getTargetId().equals(source.getFirstTarget()) + && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD + && ((ZoneChangeEvent) event).getToZone() != Zone.EXILED) { + return true; + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/MarchOfTheMachineCommander.java b/Mage.Sets/src/mage/sets/MarchOfTheMachineCommander.java index 0d825bf7b4..22328f6320 100644 --- a/Mage.Sets/src/mage/sets/MarchOfTheMachineCommander.java +++ b/Mage.Sets/src/mage/sets/MarchOfTheMachineCommander.java @@ -212,6 +212,7 @@ public final class MarchOfTheMachineCommander extends ExpansionSet { cards.add(new SetCardInfo("Mindless Automaton", 365, Rarity.UNCOMMON, mage.cards.m.MindlessAutomaton.class)); cards.add(new SetCardInfo("Mirror-Style Master", 32, Rarity.RARE, mage.cards.m.MirrorStyleMaster.class)); cards.add(new SetCardInfo("Mistmeadow Vanisher", 42, Rarity.RARE, mage.cards.m.MistmeadowVanisher.class)); + cards.add(new SetCardInfo("Moira and Teshar", 7, Rarity.MYTHIC, mage.cards.m.MoiraAndTeshar.class)); cards.add(new SetCardInfo("Mortify", 337, Rarity.UNCOMMON, mage.cards.m.Mortify.class)); cards.add(new SetCardInfo("Mossfire Valley", 414, Rarity.RARE, mage.cards.m.MossfireValley.class)); cards.add(new SetCardInfo("Mosswort Bridge", 415, Rarity.RARE, mage.cards.m.MosswortBridge.class));