From 3cfead576c79061902b94c1a4fa19dc373634922 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 11 Jan 2020 17:32:06 +0100 Subject: [PATCH] Implemented Slaughter-Priest of Mogis and Storm Herald --- .../mage/cards/h/HavenOfTheSpiritDragon.java | 6 +- .../mage/cards/s/SlaughterPriestOfMogis.java | 93 +++++++ Mage.Sets/src/mage/cards/s/StormHerald.java | 246 ++++++++++++++++++ 3 files changed, 341 insertions(+), 4 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/s/SlaughterPriestOfMogis.java create mode 100644 Mage.Sets/src/mage/cards/s/StormHerald.java diff --git a/Mage.Sets/src/mage/cards/h/HavenOfTheSpiritDragon.java b/Mage.Sets/src/mage/cards/h/HavenOfTheSpiritDragon.java index 5259cb2d73..c2ae2b0383 100644 --- a/Mage.Sets/src/mage/cards/h/HavenOfTheSpiritDragon.java +++ b/Mage.Sets/src/mage/cards/h/HavenOfTheSpiritDragon.java @@ -1,6 +1,6 @@ - package mage.cards.h; +import java.util.UUID; import mage.ConditionalMana; import mage.MageObject; import mage.Mana; @@ -27,8 +27,6 @@ import mage.filter.predicate.Predicates; import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; -import java.util.UUID; - /** * * @author jeffwadsworth @@ -43,7 +41,7 @@ public final class HavenOfTheSpiritDragon extends CardImpl { } public HavenOfTheSpiritDragon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // {T}: Add {C}. this.addAbility(new ColorlessManaAbility()); diff --git a/Mage.Sets/src/mage/cards/s/SlaughterPriestOfMogis.java b/Mage.Sets/src/mage/cards/s/SlaughterPriestOfMogis.java new file mode 100644 index 0000000000..a96a015fc7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SlaughterPriestOfMogis.java @@ -0,0 +1,93 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +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.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author LevelX2 + */ +public final class SlaughterPriestOfMogis extends CardImpl { + + public SlaughterPriestOfMogis(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{R}"); + + this.subtype.add(SubType.MINOTAUR); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever you sacrifice a permanent, Slaughter-Priest of Mogis gets +2/+0 until end of turn. + this.addAbility(new SlaughterPriestOfMogisAbility()); + + // {2}, Sacrifice another creature or enchantment: Slaughter-Priest of Mogis gains first strike until end of turn. + FilterControlledPermanent filter = new FilterControlledPermanent("another creature or enchantment"); + filter.add(Predicates.or(CardType.CREATURE.getPredicate(), CardType.ENCHANTMENT.getPredicate())); + filter.add(AnotherPredicate.instance); + Ability ability = new SimpleActivatedAbility( + new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), + new GenericManaCost(2)); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter))); + this.addAbility(ability); + } + + private SlaughterPriestOfMogis(final SlaughterPriestOfMogis card) { + super(card); + } + + @Override + public SlaughterPriestOfMogis copy() { + return new SlaughterPriestOfMogis(this); + } +} + +class SlaughterPriestOfMogisAbility extends TriggeredAbilityImpl { + + SlaughterPriestOfMogisAbility() { + super(Zone.BATTLEFIELD, new BoostSourceEffect(2, 0, Duration.EndOfTurn)); + } + + private SlaughterPriestOfMogisAbility(final SlaughterPriestOfMogisAbility ability) { + super(ability); + } + + @Override + public SlaughterPriestOfMogisAbility copy() { + return new SlaughterPriestOfMogisAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SACRIFICED_PERMANENT; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.getControllerId()); + } + + @Override + public String getRule() { + return "Whenever you sacrifice a permanent, {this} gets +2/+0 until end of turn."; + } +} diff --git a/Mage.Sets/src/mage/cards/s/StormHerald.java b/Mage.Sets/src/mage/cards/s/StormHerald.java new file mode 100644 index 0000000000..b120c0e34c --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StormHerald.java @@ -0,0 +1,246 @@ +package mage.cards.s; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.Filter; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; +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.Target; +import mage.target.TargetCard; +import mage.target.TargetPermanent; +import mage.target.targetpointer.FixedTargets; + +/** + * + * @author LevelX2 + */ +public final class StormHerald extends CardImpl { + + public StormHerald(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // When Storm Herald enters the battlefield, return any number of Aura cards from your graveyard to the battlefield attached to creatures you control. Exile those Auras at the beginning of your next end step. If those Auras would leave the battlefield, exile them instead of putting them anywhere else. + this.addAbility(new EntersBattlefieldTriggeredAbility(new StormHeraldEffect(), false)); + + } + + private StormHerald(final StormHerald card) { + super(card); + } + + @Override + public StormHerald copy() { + return new StormHerald(this); + } +} + +class StormHeraldEffect extends OneShotEffect { + + public StormHeraldEffect() { + super(Outcome.Benefit); + this.staticText = "return any number of Aura cards from your graveyard to the battlefield attached to creatures you control. " + + "Exile those Auras at the beginning of your next end step. " + + "If those Auras would leave the battlefield, exile them instead of putting them anywhere else"; + } + + public StormHeraldEffect(final StormHeraldEffect effect) { + super(effect); + } + + @Override + public StormHeraldEffect copy() { + return new StormHeraldEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + FilterCard filter = new FilterCard("aura cards to attach to creatures you control"); + filter.add(SubType.AURA.getPredicate()); + filter.add(new StormHeraldAttachablePredicate(controller.getId())); + Set possibleTargets = controller.getGraveyard().getCards(filter, source.getSourceId(), controller.getId(), game); + if (!possibleTargets.isEmpty()) { + TargetCard targetAuras = new TargetCard(0, Integer.MAX_VALUE, Zone.GRAVEYARD, filter); + targetAuras.setNotTarget(true); + controller.chooseTarget(outcome, new CardsImpl(possibleTargets), targetAuras, source, game); + + // Move the cards to the battlefield to a creature you control + List toExile = new ArrayList<>(); + for (UUID auraId : targetAuras.getTargets()) { + Card auraCard = game.getCard(auraId); + if (auraCard != null) { + FilterPermanent filterAttachTo = new FilterControlledCreaturePermanent("creature you control to attach " + auraCard.getIdName() + " to"); + filterAttachTo.add(new StormHeraldAttachableToPredicate(auraCard)); + TargetPermanent targetCreature = new TargetPermanent(filterAttachTo); + targetCreature.setNotTarget(true); + if (controller.choose(Outcome.PutCardInPlay, targetCreature, source.getSourceId(), game)) { + Permanent targetPermanent = game.getPermanent(targetCreature.getFirstTarget()); + if (!targetPermanent.cantBeAttachedBy(auraCard, game)) { + game.getState().setValue("attachTo:" + auraCard.getId(), targetPermanent); + controller.moveCards(auraCard, Zone.BATTLEFIELD, source, game); + targetPermanent.addAttachment(auraCard.getId(), game); + Permanent permanent = game.getPermanent(auraId); + if (permanent != null) { + toExile.add(permanent); + } + } + } + } + } + + ContinuousEffect continuousEffect = new StormHeraldReplacementEffect(); + continuousEffect.setTargetPointer(new FixedTargets(toExile, game)); + game.addEffect(continuousEffect, source); + + Effect exileEffect = new ExileTargetEffect("exile those Auras"); + exileEffect.setTargetPointer(new FixedTargets(toExile, game)); + game.addDelayedTriggeredAbility( + new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect), source); + } + return true; + } + return false; + } +} + +class StormHeraldReplacementEffect extends ReplacementEffectImpl { + + StormHeraldReplacementEffect() { + super(Duration.EndOfTurn, Outcome.Exile); + staticText = "If those Auras would leave the battlefield, exile them instead of putting them anywhere else"; + } + + StormHeraldReplacementEffect(final StormHeraldReplacementEffect effect) { + super(effect); + } + + @Override + public StormHeraldReplacementEffect copy() { + return new StormHeraldReplacementEffect(this); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + ((ZoneChangeEvent) event).setToZone(Zone.EXILED); + Permanent aura = ((ZoneChangeEvent) event).getTarget(); + MageObject sourceObject = source.getSourceObject(game); + if (aura != null && sourceObject != null) { + game.informPlayers(aura.getLogName() + "goes to exile instead (" + sourceObject.getLogName() + ")"); + } + 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.getType() == GameEvent.EventType.ZONE_CHANGE + && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD + && ((ZoneChangeEvent) event).getToZone() != Zone.EXILED + && getTargetPointer().getTargets(game, source).contains(event.getTargetId())) { + return true; + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } +} + +class StormHeraldAttachablePredicate implements mage.filter.predicate.Predicate { + + private final UUID controllerId; + + public StormHeraldAttachablePredicate(UUID controllerId) { + this.controllerId = controllerId; + } + + @Override + public boolean apply(Card input, Game game) { + Filter filter; + for (Target target : input.getSpellAbility().getTargets()) { + filter = target.getFilter(); + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, controllerId, game)) { + if (filter.match(permanent, game)) { + return true; + } + } + + } + return false; + } + + @Override + public String toString() { + return "Aura cards that can be attached to controlles creatures"; + } +} + +class StormHeraldAttachableToPredicate implements mage.filter.predicate.Predicate { + + private final Card aura; + + public StormHeraldAttachableToPredicate(Card aura) { + this.aura = aura; + } + + @Override + public boolean apply(Permanent input, Game game) { + Filter filter; + for (Target target : aura.getSpellAbility().getTargets()) { + filter = target.getFilter(); + if (filter.match(input, game)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return "creature that the aura can be attached to"; + } +}