diff --git a/Mage.Sets/src/mage/cards/f/FlameKinWarScout.java b/Mage.Sets/src/mage/cards/f/FlameKinWarScout.java index 5accde322e5..ed99973787e 100644 --- a/Mage.Sets/src/mage/cards/f/FlameKinWarScout.java +++ b/Mage.Sets/src/mage/cards/f/FlameKinWarScout.java @@ -10,13 +10,8 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.SetTargetPointer; -import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.constants.*; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; @@ -26,12 +21,6 @@ import mage.game.permanent.Permanent; */ public final class FlameKinWarScout extends CardImpl { - private static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); - - static { - filter.add(AnotherPredicate.instance); - } - public FlameKinWarScout(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); @@ -41,7 +30,11 @@ public final class FlameKinWarScout extends CardImpl { this.toughness = new MageInt(4); // When another creature enters the battlefield, sacrifice Flame-Kin War Scout. If you do, Flame-Kin War Scout deals 4 damage to that creature. - this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new FlameKinWarScourEffect(), filter, false, SetTargetPointer.PERMANENT, null)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new FlameKinWarScourEffect(), + StaticFilters.FILTER_ANOTHER_CREATURE, false, + SetTargetPointer.PERMANENT, null + )); } diff --git a/Mage.Sets/src/mage/cards/h/HerdGnarr.java b/Mage.Sets/src/mage/cards/h/HerdGnarr.java index a966e80e38f..a1b1927d4bb 100644 --- a/Mage.Sets/src/mage/cards/h/HerdGnarr.java +++ b/Mage.Sets/src/mage/cards/h/HerdGnarr.java @@ -1,4 +1,3 @@ - package mage.cards.h; import java.util.UUID; diff --git a/Mage.Sets/src/mage/cards/l/LiesaForgottenArchangel.java b/Mage.Sets/src/mage/cards/l/LiesaForgottenArchangel.java index 3445993d122..1bc1200511b 100644 --- a/Mage.Sets/src/mage/cards/l/LiesaForgottenArchangel.java +++ b/Mage.Sets/src/mage/cards/l/LiesaForgottenArchangel.java @@ -9,21 +9,21 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.ReturnToHandTargetEffect; -import mage.constants.*; +import mage.abilities.effects.common.replacement.CreaturesAreExiledOnDeathReplacementEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; -import mage.players.Player; /** * @@ -57,7 +57,9 @@ public final class LiesaForgottenArchangel extends CardImpl { this.addAbility(new DiesCreatureTriggeredAbility(new LiesaForgottenArchangelReturnToHandEffect(), false, filter, true)); // If a creature an opponent controls would die, exile it instead. - this.addAbility(new SimpleStaticAbility(new LiesaForgottenArchangelReplacementEffect())); + this.addAbility(new SimpleStaticAbility( + new CreaturesAreExiledOnDeathReplacementEffect(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE) + )); } private LiesaForgottenArchangel(final LiesaForgottenArchangel card) { @@ -96,44 +98,3 @@ class LiesaForgottenArchangelReturnToHandEffect extends OneShotEffect { return true; } } - -class LiesaForgottenArchangelReplacementEffect extends ReplacementEffectImpl { - - public LiesaForgottenArchangelReplacementEffect() { - super(Duration.WhileOnBattlefield, Outcome.Exile); - staticText = "If a creature an opponent controls would die, exile it instead"; - } - - private LiesaForgottenArchangelReplacementEffect(final LiesaForgottenArchangelReplacementEffect effect) { - super(effect); - } - - @Override - public LiesaForgottenArchangelReplacementEffect copy() { - return new LiesaForgottenArchangelReplacementEffect(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) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.isDiesEvent()) { - Permanent permanent = zEvent.getTarget(); - if (permanent != null && permanent.isCreature()) { - Player player = game.getPlayer(source.getControllerId()); - return player != null && player.hasOpponent(permanent.getControllerId(), game); - } - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/l/LorcanWarlockCollector.java b/Mage.Sets/src/mage/cards/l/LorcanWarlockCollector.java index 89c4852242f..d28ef6f0485 100644 --- a/Mage.Sets/src/mage/cards/l/LorcanWarlockCollector.java +++ b/Mage.Sets/src/mage/cards/l/LorcanWarlockCollector.java @@ -7,18 +7,16 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.continuous.AddCardSubTypeTargetEffect; +import mage.abilities.effects.common.replacement.CreaturesAreExiledOnDeathReplacementEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; 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.targetpointer.FixedTarget; @@ -48,7 +46,9 @@ public final class LorcanWarlockCollector extends CardImpl { )); // If a Warlock you control would die, exile it instead. - this.addAbility(new SimpleStaticAbility(new LorcanWarlockCollectorReplacementEffect())); + this.addAbility(new SimpleStaticAbility( + new CreaturesAreExiledOnDeathReplacementEffect(new FilterControlledCreaturePermanent(SubType.WARLOCK)) + )); } private LorcanWarlockCollector(final LorcanWarlockCollector card) { @@ -95,45 +95,4 @@ class LorcanWarlockCollectorReturnEffect extends OneShotEffect { player.moveCards(card, Zone.BATTLEFIELD, source, game); return true; } -} - -class LorcanWarlockCollectorReplacementEffect extends ReplacementEffectImpl { - - LorcanWarlockCollectorReplacementEffect() { - super(Duration.WhileOnBattlefield, Outcome.Exile); - staticText = "if a Warlock you control would die, exile it instead"; - } - - private LorcanWarlockCollectorReplacementEffect(final LorcanWarlockCollectorReplacementEffect effect) { - super(effect); - } - - @Override - public LorcanWarlockCollectorReplacementEffect copy() { - return new LorcanWarlockCollectorReplacementEffect(this); - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent permanent = ((ZoneChangeEvent) event).getTarget(); - if (permanent == null) { - return false; - } - Player player = game.getPlayer(permanent.getControllerId()); - return player != null && player.moveCards(permanent, Zone.EXILED, source, game); - } - - @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.getTarget() != null - && zEvent.getTarget().isControlledBy(source.getControllerId()) - && zEvent.getTarget().hasSubtype(SubType.WARLOCK, game) - && zEvent.isDiesEvent(); - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MiserysShadow.java b/Mage.Sets/src/mage/cards/m/MiserysShadow.java index 50937a1f759..ca631769276 100644 --- a/Mage.Sets/src/mage/cards/m/MiserysShadow.java +++ b/Mage.Sets/src/mage/cards/m/MiserysShadow.java @@ -1,22 +1,19 @@ package mage.cards.m; +import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.replacement.CreaturesAreExiledOnDeathReplacementEffect; 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.players.Player; - -import java.util.UUID; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; /** * @author PurpleCrowbar @@ -30,7 +27,9 @@ public final class MiserysShadow extends CardImpl { this.toughness = new MageInt(2); // If a creature an opponent controls would die, exile it instead. - this.addAbility(new SimpleStaticAbility(new MiserysShadowReplacementEffect())); + this.addAbility(new SimpleStaticAbility( + new CreaturesAreExiledOnDeathReplacementEffect(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE) + )); // {1}: Misery's Shadow gets +1/+1 until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 1, Duration.EndOfTurn), new GenericManaCost(1))); @@ -45,44 +44,3 @@ public final class MiserysShadow extends CardImpl { return new MiserysShadow(this); } } - -class MiserysShadowReplacementEffect extends ReplacementEffectImpl { - - public MiserysShadowReplacementEffect() { - super(Duration.WhileOnBattlefield, Outcome.Exile); - staticText = "If a creature an opponent controls would die, exile it instead"; - } - - private MiserysShadowReplacementEffect(final MiserysShadowReplacementEffect effect) { - super(effect); - } - - @Override - public MiserysShadowReplacementEffect copy() { - return new MiserysShadowReplacementEffect(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) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.isDiesEvent()) { - Permanent permanent = zEvent.getTarget(); - if (permanent != null && permanent.isCreature()) { - Player player = game.getPlayer(source.getControllerId()); - return player != null && player.hasOpponent(permanent.getControllerId(), game); - } - } - return false; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MoggBombers.java b/Mage.Sets/src/mage/cards/m/MoggBombers.java index 49b996e0a82..fb36dae7ed8 100644 --- a/Mage.Sets/src/mage/cards/m/MoggBombers.java +++ b/Mage.Sets/src/mage/cards/m/MoggBombers.java @@ -7,13 +7,12 @@ import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.SacrificeSourceEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import mage.target.TargetPlayer; /** @@ -23,11 +22,6 @@ import mage.target.TargetPlayer; public final class MoggBombers extends CardImpl { private static final String rule = "When another creature enters the battlefield, sacrifice {this} and it deals 3 damage to target player."; - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); - - static { - filter.add(AnotherPredicate.instance); - } public MoggBombers(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); @@ -40,9 +34,11 @@ public final class MoggBombers extends CardImpl { Effect sacrificeMoggBombers = new SacrificeSourceEffect(); Effect damageTargetPlayer = new DamageTargetEffect(3); Ability ability = new EntersBattlefieldAllTriggeredAbility( - Zone.BATTLEFIELD, - sacrificeMoggBombers, - filter, false, rule); + Zone.BATTLEFIELD, + sacrificeMoggBombers, + StaticFilters.FILTER_ANOTHER_CREATURE, + false, + rule); ability.addEffect(damageTargetPlayer); ability.addTarget(new TargetPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/StoneOfErech.java b/Mage.Sets/src/mage/cards/s/StoneOfErech.java new file mode 100644 index 00000000000..b82327ad53c --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StoneOfErech.java @@ -0,0 +1,54 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.ExileGraveyardAllTargetPlayerEffect; +import mage.abilities.effects.common.replacement.CreaturesAreExiledOnDeathReplacementEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; +import mage.target.TargetPlayer; + +/** + * + * @author Susucr + */ +public final class StoneOfErech extends CardImpl { + + public StoneOfErech(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); + + this.supertype.add(SuperType.LEGENDARY); + + // If a creature an opponent controls would die, exile it instead. + this.addAbility(new SimpleStaticAbility( + new CreaturesAreExiledOnDeathReplacementEffect(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE) + )); + + // {2}, {T}, Sacrifice Stone of Erech: Exile target player's graveyard. Draw a card. + SimpleActivatedAbility ability = new SimpleActivatedAbility( + new ExileGraveyardAllTargetPlayerEffect(), new TapSourceCost() + ); + ability.addEffect(new DrawCardSourceControllerEffect(1)); + ability.addCost(new GenericManaCost(2)); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + private StoneOfErech(final StoneOfErech card) { + super(card); + } + + @Override + public StoneOfErech copy() { + return new StoneOfErech(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TimidDrake.java b/Mage.Sets/src/mage/cards/t/TimidDrake.java index 109c69a5f4a..fd926bd73de 100644 --- a/Mage.Sets/src/mage/cards/t/TimidDrake.java +++ b/Mage.Sets/src/mage/cards/t/TimidDrake.java @@ -1,18 +1,16 @@ - package mage.cards.t; import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.ReturnToHandSourceEffect; -import mage.constants.SubType; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; /** * @@ -20,12 +18,6 @@ import mage.filter.predicate.mageobject.AnotherPredicate; */ public final class TimidDrake extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); - - static { - filter.add(AnotherPredicate.instance); - } - public TimidDrake(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); @@ -38,7 +30,8 @@ public final class TimidDrake extends CardImpl { // When another creature enters the battlefield, return Timid Drake to its owner's hand. this.addAbility(new EntersBattlefieldAllTriggeredAbility( - Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), filter, false, + Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), + StaticFilters.FILTER_ANOTHER_CREATURE, false, "When another creature enters the battlefield, return {this} to its owner's hand." )); } diff --git a/Mage.Sets/src/mage/sets/TheLordOfTheRingsTalesOfMiddleEarth.java b/Mage.Sets/src/mage/sets/TheLordOfTheRingsTalesOfMiddleEarth.java index 74a9cd6a037..4a5c09b0b5b 100644 --- a/Mage.Sets/src/mage/sets/TheLordOfTheRingsTalesOfMiddleEarth.java +++ b/Mage.Sets/src/mage/sets/TheLordOfTheRingsTalesOfMiddleEarth.java @@ -240,6 +240,7 @@ public final class TheLordOfTheRingsTalesOfMiddleEarth extends ExpansionSet { cards.add(new SetCardInfo("Stalwarts of Osgiliath", 33, Rarity.COMMON, mage.cards.s.StalwartsOfOsgiliath.class)); cards.add(new SetCardInfo("Stern Scolding", 71, Rarity.UNCOMMON, mage.cards.s.SternScolding.class)); cards.add(new SetCardInfo("Stew the Coneys", 189, Rarity.UNCOMMON, mage.cards.s.StewTheConeys.class)); + cards.add(new SetCardInfo("Stone of Erech", 251, Rarity.UNCOMMON, mage.cards.s.StoneOfErech.class)); cards.add(new SetCardInfo("Storm of Saruman", 72, Rarity.MYTHIC, mage.cards.s.StormOfSaruman.class)); cards.add(new SetCardInfo("Surrounded by Orcs", 73, Rarity.COMMON, mage.cards.s.SurroundedByOrcs.class)); cards.add(new SetCardInfo("Swamp", 266, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/replacement/CreaturesAreExiledOnDeathReplacementEffect.java b/Mage/src/main/java/mage/abilities/effects/common/replacement/CreaturesAreExiledOnDeathReplacementEffect.java new file mode 100644 index 00000000000..483a0972b55 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/replacement/CreaturesAreExiledOnDeathReplacementEffect.java @@ -0,0 +1,62 @@ +package mage.abilities.effects.common.replacement; + +import mage.abilities.Ability; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.util.CardUtil; + +/** + * @author Susucr + */ +public class CreaturesAreExiledOnDeathReplacementEffect extends ReplacementEffectImpl { + + private FilterPermanent filter; + + public CreaturesAreExiledOnDeathReplacementEffect(FilterPermanent filter) { + super(Duration.WhileOnBattlefield, Outcome.Exile); + staticText = "If " + CardUtil.addArticle(filter.getMessage()) + " would die, exile it instead"; + } + + private CreaturesAreExiledOnDeathReplacementEffect(final CreaturesAreExiledOnDeathReplacementEffect effect) { + super(effect); + this.filter = effect.filter; + } + + @Override + public CreaturesAreExiledOnDeathReplacementEffect copy() { + return new CreaturesAreExiledOnDeathReplacementEffect(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) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (!zEvent.isDiesEvent()) { + return false; + } + + Permanent permanent = zEvent.getTarget(); + if (permanent == null) { + return false; + } + + return filter.match(permanent, source.getControllerId(), source, game); + } +} diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 9174b5cab86..29adaa2d237 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -560,6 +560,13 @@ public final class StaticFilters { FILTER_OPPONENTS_PERMANENT_ARTIFACT_OR_CREATURE.setLockedFilter(true); } + public static final FilterCreaturePermanent FILTER_ANOTHER_CREATURE = new FilterCreaturePermanent("another creature"); + + static { + FILTER_ANOTHER_CREATURE.add(AnotherPredicate.instance); + FILTER_ANOTHER_CREATURE.setLockedFilter(true); + } + public static final FilterCreaturePermanent FILTER_ANOTHER_TARGET_CREATURE = new FilterCreaturePermanent("another target creature"); static {