From 59678389df10885c46a5ec0b275a8ef542e1fbb3 Mon Sep 17 00:00:00 2001 From: Daniel Bomar Date: Sat, 5 Jun 2021 07:03:04 -0500 Subject: [PATCH] [MH2] Implemented Persist (#7889) --- .../src/mage/cards/g/GracefulRestoration.java | 51 +------- Mage.Sets/src/mage/cards/p/Persist.java | 43 +++++++ .../src/mage/cards/u/UnbreakableBond.java | 57 +-------- Mage.Sets/src/mage/sets/ModernHorizons2.java | 1 + ...dToBattlefieldWithCounterTargetEffect.java | 113 ++++++++++++++++++ 5 files changed, 161 insertions(+), 104 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/p/Persist.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldWithCounterTargetEffect.java diff --git a/Mage.Sets/src/mage/cards/g/GracefulRestoration.java b/Mage.Sets/src/mage/cards/g/GracefulRestoration.java index 565b523f0e..fed8e25db2 100644 --- a/Mage.Sets/src/mage/cards/g/GracefulRestoration.java +++ b/Mage.Sets/src/mage/cards/g/GracefulRestoration.java @@ -2,25 +2,17 @@ package mage.cards.g; import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.Mode; -import mage.abilities.effects.ReplacementEffectImpl; -import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldWithCounterTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; -import mage.constants.Duration; -import mage.constants.Outcome; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.PowerPredicate; -import mage.game.Game; -import mage.game.events.EntersTheBattlefieldEvent; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.target.common.TargetCardInYourGraveyard; /** @@ -40,9 +32,7 @@ public final class GracefulRestoration extends CardImpl { // Choose one — // • Return target creature card from your graveyard to the battlefield with an additional +1/+1 counter on it. - this.getSpellAbility().addEffect(new GracefulRestorationReplacementEffect()); - this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); - this.getSpellAbility().addEffect(new InfoEffect("with an additional +1/+1 counter on it")); + this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(CounterType.P1P1.createInstance(), true)); this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); // • Return up to two target creature cards with power 2 or less from your graveyard to the battlefield. @@ -60,40 +50,3 @@ public final class GracefulRestoration extends CardImpl { return new GracefulRestoration(this); } } - -class GracefulRestorationReplacementEffect extends ReplacementEffectImpl { - - public GracefulRestorationReplacementEffect() { - super(Duration.EndOfStep, Outcome.BoostCreature); - } - - private GracefulRestorationReplacementEffect(final GracefulRestorationReplacementEffect effect) { - super(effect); - } - - @Override - public GracefulRestorationReplacementEffect copy() { - return new GracefulRestorationReplacementEffect(this); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - return event.getTargetId().equals(getTargetPointer().getFirst(game, source)); - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); - if (creature == null) { - return false; - } - creature.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game, event.getAppliedEffects()); - discard(); - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/p/Persist.java b/Mage.Sets/src/mage/cards/p/Persist.java new file mode 100644 index 0000000000..87fd0feffc --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/Persist.java @@ -0,0 +1,43 @@ +package mage.cards.p; + +import java.util.UUID; + +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldWithCounterTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.Predicates; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author weirddan455 + */ +public final class Persist extends CardImpl { + + private static final FilterCreatureCard filter = new FilterCreatureCard("nonlegendary creature card from your graveyard"); + + static { + filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate())); + } + + public Persist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}"); + + // Return target nonlegendary creature card from your graveyard to the battlefield with a -1/-1 counter on it. + this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(CounterType.M1M1.createInstance())); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(filter)); + } + + private Persist(final Persist card) { + super(card); + } + + @Override + public Persist copy() { + return new Persist(this); + } +} diff --git a/Mage.Sets/src/mage/cards/u/UnbreakableBond.java b/Mage.Sets/src/mage/cards/u/UnbreakableBond.java index e67158554c..5c66570834 100644 --- a/Mage.Sets/src/mage/cards/u/UnbreakableBond.java +++ b/Mage.Sets/src/mage/cards/u/UnbreakableBond.java @@ -1,20 +1,11 @@ package mage.cards.u; -import mage.abilities.Ability; -import mage.abilities.effects.ReplacementEffectImpl; -import mage.abilities.effects.common.InfoEffect; -import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldWithCounterTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; import mage.counters.CounterType; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.events.EntersTheBattlefieldEvent; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.target.common.TargetCardInYourGraveyard; import java.util.UUID; @@ -28,9 +19,7 @@ public final class UnbreakableBond extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}"); // Return target creature card from your graveyard to the battlefield with a lifelink counter on it. - this.getSpellAbility().addEffect(new UnbreakableBondReplacementEffect()); - this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); - this.getSpellAbility().addEffect(new InfoEffect("with a lifelink counter on it")); + this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(CounterType.LIFELINK.createInstance())); this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); } @@ -43,45 +32,3 @@ public final class UnbreakableBond extends CardImpl { return new UnbreakableBond(this); } } - -class UnbreakableBondReplacementEffect extends ReplacementEffectImpl { - - UnbreakableBondReplacementEffect() { - super(Duration.EndOfStep, Outcome.BoostCreature); - } - - private UnbreakableBondReplacementEffect(UnbreakableBondReplacementEffect effect) { - super(effect); - } - - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - return event.getTargetId().equals(getTargetPointer().getFirst(game, source)); - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); - if (creature == null) { - return false; - } - creature.addCounters(CounterType.LIFELINK.createInstance(), source.getControllerId(), source, game, event.getAppliedEffects()); - discard(); - return false; - } - - @Override - public UnbreakableBondReplacementEffect copy() { - return new UnbreakableBondReplacementEffect(this); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/ModernHorizons2.java b/Mage.Sets/src/mage/sets/ModernHorizons2.java index 310b9f95d4..55e49898f9 100644 --- a/Mage.Sets/src/mage/sets/ModernHorizons2.java +++ b/Mage.Sets/src/mage/sets/ModernHorizons2.java @@ -200,6 +200,7 @@ public final class ModernHorizons2 extends ExpansionSet { cards.add(new SetCardInfo("Parcel Myr", 54, Rarity.COMMON, mage.cards.p.ParcelMyr.class)); cards.add(new SetCardInfo("Patchwork Gnomes", 299, Rarity.COMMON, mage.cards.p.PatchworkGnomes.class)); cards.add(new SetCardInfo("Patriarch's Bidding", 275, Rarity.RARE, mage.cards.p.PatriarchsBidding.class)); + cards.add(new SetCardInfo("Persist", 96, Rarity.RARE, mage.cards.p.Persist.class)); cards.add(new SetCardInfo("Phantasmal Dreadmaw", 55, Rarity.COMMON, mage.cards.p.PhantasmalDreadmaw.class)); cards.add(new SetCardInfo("Piercing Rays", 24, Rarity.COMMON, mage.cards.p.PiercingRays.class)); cards.add(new SetCardInfo("Piru, the Volatile", 207, Rarity.RARE, mage.cards.p.PiruTheVolatile.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldWithCounterTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldWithCounterTargetEffect.java new file mode 100644 index 0000000000..05afdc49e8 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldWithCounterTargetEffect.java @@ -0,0 +1,113 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.counters.Counter; +import mage.game.Game; +import mage.game.events.EntersTheBattlefieldEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +public class ReturnFromGraveyardToBattlefieldWithCounterTargetEffect extends ReturnFromGraveyardToBattlefieldTargetEffect { + + private final Counter counter; + private final boolean additional; + + public ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(Counter counter) { + this(counter, false); + } + + public ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(Counter counter, boolean additional) { + super(); + this.counter = counter; + this.additional = additional; + } + + private ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(final ReturnFromGraveyardToBattlefieldWithCounterTargetEffect effect) { + super(effect); + this.counter = effect.counter; + this.additional = effect.additional; + } + + @Override + public ReturnFromGraveyardToBattlefieldWithCounterTargetEffect copy() { + return new ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + AddCounterReplacementEffect counterEffect = new AddCounterReplacementEffect(counter); + game.addEffect(counterEffect, source); + return super.apply(game, source); + } + + @Override + public String getText(Mode mode) { + StringBuilder sb = new StringBuilder(super.getText(mode)); + sb.append(" with "); + if (additional) { + if (counter.getCount() == 1) { + sb.append("an"); + } else { + sb.append(counter.getCount()); + } + sb.append(" additional"); + } else if (counter.getCount() == 1) { + sb.append("a"); + } else { + sb.append(counter.getCount()); + } + sb.append(' '); + sb.append(counter.getName()); + sb.append(" counter"); + if (counter.getCount() != 1) { + sb.append('s'); + } + sb.append(" on it"); + return sb.toString(); + } +} + +class AddCounterReplacementEffect extends ReplacementEffectImpl { + + private final Counter counter; + + public AddCounterReplacementEffect(Counter counter) { + super(Duration.EndOfStep, Outcome.BoostCreature); + this.counter = counter; + } + + private AddCounterReplacementEffect(final AddCounterReplacementEffect effect) { + super(effect); + this.counter = effect.counter; + } + + @Override + public AddCounterReplacementEffect copy() { + return new AddCounterReplacementEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getTargetId().equals(getTargetPointer().getFirst(game, source)); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); + if (creature == null) { + return false; + } + creature.addCounters(counter.copy(), source.getControllerId(), source, game, event.getAppliedEffects()); + discard(); + return false; + } +}