diff --git a/Mage.Sets/src/mage/cards/f/FeatherTheRedeemed.java b/Mage.Sets/src/mage/cards/f/FeatherTheRedeemed.java new file mode 100644 index 00000000000..74de65b44f7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FeatherTheRedeemed.java @@ -0,0 +1,184 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.SpellAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.Target; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FeatherTheRedeemed extends CardImpl { + + public FeatherTheRedeemed(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever you cast an instant or sorcery spell that targets a creature you control, exile that card instead of putting it into your graveyard as it resolves. If you do, return it to your hand at the beginning of the next end step. + this.addAbility(new FeatherTheRedeemedTriggeredAbility()); + } + + private FeatherTheRedeemed(final FeatherTheRedeemed card) { + super(card); + } + + @Override + public FeatherTheRedeemed copy() { + return new FeatherTheRedeemed(this); + } +} + +class FeatherTheRedeemedTriggeredAbility extends TriggeredAbilityImpl { + + FeatherTheRedeemedTriggeredAbility() { + super(Zone.BATTLEFIELD, null, false); + } + + private FeatherTheRedeemedTriggeredAbility(final FeatherTheRedeemedTriggeredAbility ability) { + super(ability); + } + + @Override + public FeatherTheRedeemedTriggeredAbility copy() { + return new FeatherTheRedeemedTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getPlayerId().equals(this.getControllerId())) { + return false; + } + Spell spell = game.getStack().getSpell(event.getTargetId()); + return checkSpell(spell, game); + } + + private boolean checkSpell(Spell spell, Game game) { + if (spell == null) { + return false; + } + SpellAbility sa = spell.getSpellAbility(); + for (UUID modeId : sa.getModes().getSelectedModes()) { + Mode mode = sa.getModes().get(modeId); + for (Target target : mode.getTargets()) { + for (UUID targetId : target.getTargets()) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null && permanent.isCreature() + && permanent.isControlledBy(getControllerId())) { + this.getEffects().clear(); + this.addEffect(new FeatherTheRedeemedEffect(new MageObjectReference(spell, game))); + return true; + } + } + } + for (Effect effect : mode.getEffects()) { + for (UUID targetId : effect.getTargetPointer().getTargets(game, sa)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null && permanent.isCreature() + && permanent.isControlledBy(getControllerId())) { + this.getEffects().clear(); + this.addEffect(new FeatherTheRedeemedEffect(new MageObjectReference(spell, game))); + return true; + } + } + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever you cast an instant or sorcery spell that targets a creature you control, " + + "exile that card instead of putting it into your graveyard as it resolves. " + + "If you do, return it to your hand at the beginning of the next end step."; + } +} + +class FeatherTheRedeemedEffect extends ReplacementEffectImpl { + + private final MageObjectReference mor; + + FeatherTheRedeemedEffect(MageObjectReference mor) { + super(Duration.WhileOnStack, Outcome.Benefit); + this.mor = mor; + } + + private FeatherTheRedeemedEffect(final FeatherTheRedeemedEffect effect) { + super(effect); + this.mor = effect.mor; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Spell sourceSpell = game.getStack().getSpell(event.getTargetId()); + if (sourceSpell == null || sourceSpell.isCopy()) { + return false; + } + Player player = game.getPlayer(sourceSpell.getOwnerId()); + if (player == null) { + return false; + } + Effect effect = new ReturnToHandTargetEffect().setText("return " + sourceSpell.getName() + " to its owner's hand"); + player.moveCards(sourceSpell, Zone.EXILED, source, game); + effect.setTargetPointer(new FixedTarget(event.getTargetId(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); + return true; + } + + @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); + if (zEvent.getFromZone() == Zone.STACK + && zEvent.getToZone() == Zone.GRAVEYARD + && event.getSourceId() != null) { + if (event.getSourceId().equals(event.getTargetId())) { + Spell spell = game.getStack().getSpell(mor.getSourceId()); + if (spell != null && spell.isInstantOrSorcery()) { + return true; + } + } + } + return false; + } + + @Override + public FeatherTheRedeemedEffect copy() { + return new FeatherTheRedeemedEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/WarOfTheSpark.java b/Mage.Sets/src/mage/sets/WarOfTheSpark.java index f245358ef70..d95d7419d6a 100644 --- a/Mage.Sets/src/mage/sets/WarOfTheSpark.java +++ b/Mage.Sets/src/mage/sets/WarOfTheSpark.java @@ -75,6 +75,7 @@ public final class WarOfTheSpark extends ExpansionSet { cards.add(new SetCardInfo("Eternal Taskmaster", 90, Rarity.UNCOMMON, mage.cards.e.EternalTaskmaster.class)); cards.add(new SetCardInfo("Evolution Sage", 159, Rarity.UNCOMMON, mage.cards.e.EvolutionSage.class)); cards.add(new SetCardInfo("Fblthp, the Lost", 50, Rarity.RARE, mage.cards.f.FblthpTheLost.class)); + cards.add(new SetCardInfo("Feather, the Redeemed", 197, Rarity.RARE, mage.cards.f.FeatherTheRedeemed.class)); cards.add(new SetCardInfo("Firemind Vessel", 237, Rarity.UNCOMMON, mage.cards.f.FiremindVessel.class)); cards.add(new SetCardInfo("Flux Channeler", 52, Rarity.UNCOMMON, mage.cards.f.FluxChanneler.class)); cards.add(new SetCardInfo("Forced Landing", 161, Rarity.COMMON, mage.cards.f.ForcedLanding.class));