From 35be23537f4c93a840dbab077f7c5ce03d8f2e5b Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 25 Feb 2021 10:45:26 -0500 Subject: [PATCH] simplified and consolidated effects which check cards put into graveyards from the battlefield --- Mage.Sets/src/mage/cards/b/BroughtBack.java | 18 +-- .../src/mage/cards/c/CryOfTheCarnarium.java | 17 +-- Mage.Sets/src/mage/cards/f/FaithsReward.java | 63 +++------- Mage.Sets/src/mage/cards/f/FellShepherd.java | 101 ++++------------ .../mage/cards/g/GerrardWeatherlightHero.java | 66 +++-------- Mage.Sets/src/mage/cards/g/Gleancrawler.java | 78 ++++--------- Mage.Sets/src/mage/cards/g/GrimReturn.java | 50 ++------ .../src/mage/cards/n/NoRestForTheWicked.java | 109 ++++-------------- .../src/mage/cards/s/SalvagerOfRuin.java | 30 ++--- Mage.Sets/src/mage/cards/s/SecondSunrise.java | 97 ++++++---------- .../src/mage/cards/t/ThrillingEncore.java | 67 ++++++----- .../src/mage/cards/t/TwilightShepherd.java | 77 +++---------- .../ReturnToHandFromGraveyardAllEffect.java | 72 +++++++++--- ...GraveFromBattlefieldThisTurnPredicate.java | 19 +++ .../common/CardsPutIntoGraveyardWatcher.java | 41 ++++--- 15 files changed, 311 insertions(+), 594 deletions(-) create mode 100644 Mage/src/main/java/mage/filter/predicate/card/PutIntoGraveFromBattlefieldThisTurnPredicate.java diff --git a/Mage.Sets/src/mage/cards/b/BroughtBack.java b/Mage.Sets/src/mage/cards/b/BroughtBack.java index a8ede6d62a..62104591a7 100644 --- a/Mage.Sets/src/mage/cards/b/BroughtBack.java +++ b/Mage.Sets/src/mage/cards/b/BroughtBack.java @@ -1,15 +1,12 @@ package mage.cards.b; -import mage.MageObjectReference; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.FilterCard; import mage.filter.common.FilterPermanentCard; -import mage.filter.predicate.Predicate; -import mage.game.Game; +import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate; import mage.target.common.TargetCardInYourGraveyard; import mage.watchers.common.CardsPutIntoGraveyardWatcher; @@ -25,7 +22,7 @@ public final class BroughtBack extends CardImpl { ); static { - filter.add(BroughtBackPredicate.instance); + filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance); } public BroughtBack(UUID ownerId, CardSetInfo setInfo) { @@ -51,14 +48,3 @@ public final class BroughtBack extends CardImpl { return new BroughtBack(this); } } - -enum BroughtBackPredicate implements Predicate { - instance; - - @Override - public boolean apply(Card input, Game game) { - CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); - return watcher != null - && watcher.getCardsPutToGraveyardFromBattlefield().contains(new MageObjectReference(input, game)); - } -} diff --git a/Mage.Sets/src/mage/cards/c/CryOfTheCarnarium.java b/Mage.Sets/src/mage/cards/c/CryOfTheCarnarium.java index f8a451c4f2..f6880f696e 100644 --- a/Mage.Sets/src/mage/cards/c/CryOfTheCarnarium.java +++ b/Mage.Sets/src/mage/cards/c/CryOfTheCarnarium.java @@ -1,11 +1,13 @@ package mage.cards.c; -import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.continuous.BoostAllEffect; -import mage.cards.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; @@ -67,15 +69,8 @@ class CryOfTheCarnariumExileEffect extends OneShotEffect { if (player == null || watcher == null) { return false; } - Cards cards = new CardsImpl(); - for (MageObjectReference mor : watcher.getCardsPutToGraveyardFromBattlefield()) { - if (game.getState().getZoneChangeCounter(mor.getSourceId()) == mor.getZoneChangeCounter()) { - Card card = mor.getCard(game); - if (card != null && card.isCreature()) { - cards.add(card); - } - } - } + Cards cards = new CardsImpl(watcher.getCardsPutToGraveyardFromBattlefield(game)); + cards.removeIf(uuid -> !game.getCard(uuid).isCreature()); player.moveCards(cards, Zone.EXILED, source, game); return true; } diff --git a/Mage.Sets/src/mage/cards/f/FaithsReward.java b/Mage.Sets/src/mage/cards/f/FaithsReward.java index 2b42bc1c12..7c643ba5a9 100644 --- a/Mage.Sets/src/mage/cards/f/FaithsReward.java +++ b/Mage.Sets/src/mage/cards/f/FaithsReward.java @@ -1,26 +1,19 @@ package mage.cards.f; -import mage.MageObject; -import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.WatcherScope; import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterPermanentCard; +import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.players.Player; -import mage.watchers.Watcher; +import mage.watchers.common.CardsPutIntoGraveyardWatcher; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; import java.util.UUID; /** @@ -33,7 +26,7 @@ public final class FaithsReward extends CardImpl { // Return to the battlefield all permanent cards in your graveyard that were put there from the battlefield this turn. this.getSpellAbility().addEffect(new FaithsRewardEffect()); - this.getSpellAbility().addWatcher(new FaithsRewardWatcher()); + this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher()); } private FaithsReward(final FaithsReward card) { @@ -48,6 +41,12 @@ public final class FaithsReward extends CardImpl { class FaithsRewardEffect extends OneShotEffect { + private static final FilterCard filter = new FilterPermanentCard(); + + static { + filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance); + } + FaithsRewardEffect() { super(Outcome.PutCardInPlay); staticText = "Return to the battlefield all permanent cards in your graveyard that were put there from the battlefield this turn"; @@ -60,11 +59,12 @@ class FaithsRewardEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - FaithsRewardWatcher watcher = game.getState().getWatcher(FaithsRewardWatcher.class); - if (player == null || watcher == null) { + if (player == null) { return false; } - return player.moveCards(watcher.getCards(source.getControllerId(), game), Zone.BATTLEFIELD, source, game); + return player.moveCards(player.getGraveyard().getCards( + filter, source.getSourceId(), source.getControllerId(), game + ), Zone.BATTLEFIELD, source, game); } @Override @@ -72,36 +72,3 @@ class FaithsRewardEffect extends OneShotEffect { return new FaithsRewardEffect(this); } } - -class FaithsRewardWatcher extends Watcher { - - private final Set morMap = new HashSet<>(); - - FaithsRewardWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) { - morMap.add(new MageObjectReference(((ZoneChangeEvent) event).getTarget(), game, 1)); - } - } - - Cards getCards(UUID ownerId, Game game) { - Cards cards = new CardsImpl(); - morMap.stream() - .map(m -> m.getCard(game)) - .filter(Objects::nonNull) - .filter(MageObject::isPermanent) - .filter(c -> c.isOwnedBy(ownerId)) - .forEach(cards::add); - return cards; - } - - @Override - public void reset() { - super.reset(); - morMap.clear(); - } -} diff --git a/Mage.Sets/src/mage/cards/f/FellShepherd.java b/Mage.Sets/src/mage/cards/f/FellShepherd.java index 8265e363d2..f0e3e7f045 100644 --- a/Mage.Sets/src/mage/cards/f/FellShepherd.java +++ b/Mage.Sets/src/mage/cards/f/FellShepherd.java @@ -1,32 +1,27 @@ package mage.cards.f; import mage.MageInt; -import mage.MageObject; -import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnToHandFromGraveyardAllEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.FilterCard; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; -import mage.players.Player; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; -import mage.watchers.Watcher; +import mage.watchers.common.CardsPutIntoGraveyardWatcher; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; import java.util.UUID; /** @@ -34,6 +29,12 @@ import java.util.UUID; */ public final class FellShepherd extends CardImpl { + private static final FilterCard filter = new FilterCreatureCard(); + + static { + filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance); + } + public FellShepherd(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}"); this.subtype.add(SubType.AVATAR); @@ -42,14 +43,20 @@ public final class FellShepherd extends CardImpl { this.toughness = new MageInt(6); // Whenever Fell Shepherd deals combat damage to a player, you may return to your hand all creature cards that were put into your graveyard from the battlefield this turn. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new FellShepherdEffect(), true), new FellShepherdWatcher()); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new ReturnToHandFromGraveyardAllEffect(filter, TargetController.YOU) + .setText("return to your hand all creature cards that were " + + "put into your graveyard from the battlefield this turn"), + true + ), new CardsPutIntoGraveyardWatcher()); // {B}, Sacrifice another creature: Target creature gets -2/-2 until end of turn. - Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn), new ManaCostsImpl("{B}")); + Ability ability = new SimpleActivatedAbility( + new BoostTargetEffect(-2, -2, Duration.EndOfTurn), new ManaCostsImpl("{B}") + ); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE))); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); - } private FellShepherd(final FellShepherd card) { @@ -61,63 +68,3 @@ public final class FellShepherd extends CardImpl { return new FellShepherd(this); } } - -class FellShepherdEffect extends OneShotEffect { - - FellShepherdEffect() { - super(Outcome.PutCardInPlay); - staticText = "return to your hand all creature cards that were put into your graveyard from the battlefield this turn"; - } - - private FellShepherdEffect(final FellShepherdEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - FellShepherdWatcher watcher = game.getState().getWatcher(FellShepherdWatcher.class); - if (player == null || watcher == null) { - return false; - } - return player.moveCards(watcher.getCards(source.getControllerId(), game), Zone.HAND, source, game); - } - - @Override - public FellShepherdEffect copy() { - return new FellShepherdEffect(this); - } -} - -class FellShepherdWatcher extends Watcher { - - private final Set morMap = new HashSet<>(); - - FellShepherdWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) { - morMap.add(new MageObjectReference(((ZoneChangeEvent) event).getTarget(), game, 1)); - } - } - - Cards getCards(UUID ownerId, Game game) { - Cards cards = new CardsImpl(); - morMap.stream() - .map(m -> m.getCard(game)) - .filter(Objects::nonNull) - .filter(MageObject::isCreature) - .filter(c -> c.isOwnedBy(ownerId)) - .forEach(cards::add); - return cards; - } - - @Override - public void reset() { - super.reset(); - morMap.clear(); - } -} diff --git a/Mage.Sets/src/mage/cards/g/GerrardWeatherlightHero.java b/Mage.Sets/src/mage/cards/g/GerrardWeatherlightHero.java index 9e627ba1b4..7411e7c33b 100644 --- a/Mage.Sets/src/mage/cards/g/GerrardWeatherlightHero.java +++ b/Mage.Sets/src/mage/cards/g/GerrardWeatherlightHero.java @@ -1,26 +1,21 @@ package mage.cards.g; import mage.MageInt; -import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.players.Player; -import mage.watchers.Watcher; +import mage.watchers.common.CardsPutIntoGraveyardWatcher; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; /** * @author TheElk801 @@ -42,7 +37,7 @@ public final class GerrardWeatherlightHero extends CardImpl { // When Gerrard, Weatherlight Hero dies, exile it and return to the battlefield all artifact and creature cards in your graveyard that were put there from the battlefield this turn. Ability ability = new DiesSourceTriggeredAbility(new ExileSourceEffect().setText("exile it")); ability.addEffect(new GerrardWeatherlightHeroEffect()); - this.addAbility(ability, new GerrardWeatherlightHeroWatcher()); + this.addAbility(ability, new CardsPutIntoGraveyardWatcher()); } private GerrardWeatherlightHero(final GerrardWeatherlightHero card) { @@ -57,6 +52,15 @@ public final class GerrardWeatherlightHero extends CardImpl { class GerrardWeatherlightHeroEffect extends OneShotEffect { + private static final FilterCard filter = new FilterCard(); + + static { + filter.add(Predicates.or( + CardType.ARTIFACT.getPredicate(), + CardType.CREATURE.getPredicate() + )); + } + GerrardWeatherlightHeroEffect() { super(Outcome.Benefit); staticText = "and return to the battlefield all artifact and creature cards " + @@ -75,48 +79,12 @@ class GerrardWeatherlightHeroEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - GerrardWeatherlightHeroWatcher watcher = game.getState().getWatcher(GerrardWeatherlightHeroWatcher.class); - if (player == null || watcher == null) { + if (player == null) { return false; } - return player.moveCards( - player.getGraveyard() - .getCards(game) - .stream() - .filter(card -> watcher.checkCard(card, game)) - .collect(Collectors.toSet()), - Zone.BATTLEFIELD, source, game - ); - } -} - -class GerrardWeatherlightHeroWatcher extends Watcher { - - private final List cards = new ArrayList<>(); - - GerrardWeatherlightHeroWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE - && ((ZoneChangeEvent) event).isDiesEvent()) { - cards.add(new MageObjectReference(event.getTargetId(), game)); - } - } - - boolean checkCard(Card card, Game game) { - if (!card.isCreature() && !card.isArtifact()) { - return false; - } - return cards.stream().anyMatch(mageObjectReference -> mageObjectReference.refersTo(card, game)); - } - - @Override - public void reset() { - super.reset(); - cards.clear(); + return player.moveCards(player.getGraveyard().getCards( + filter, source.getSourceId(), source.getControllerId(), game + ), Zone.BATTLEFIELD, source, game); } } // don’t mourn for me. this is my destiny. diff --git a/Mage.Sets/src/mage/cards/g/Gleancrawler.java b/Mage.Sets/src/mage/cards/g/Gleancrawler.java index a5223fafd6..0bd1536904 100644 --- a/Mage.Sets/src/mage/cards/g/Gleancrawler.java +++ b/Mage.Sets/src/mage/cards/g/Gleancrawler.java @@ -1,34 +1,37 @@ - package mage.cards.g; -import java.util.Set; -import java.util.UUID; import mage.MageInt; -import mage.MageObjectReference; -import mage.abilities.Ability; import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.ReturnToHandFromGraveyardAllEffect; import mage.abilities.keyword.TrampleAbility; -import mage.cards.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; import mage.constants.TargetController; import mage.constants.Zone; -import mage.game.Game; -import mage.players.Player; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate; import mage.watchers.common.CardsPutIntoGraveyardWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Gleancrawler extends CardImpl { + private static final FilterCard filter = new FilterCreatureCard(); + + static { + filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance); + } + public Gleancrawler(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B/G}{B/G}{B/G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B/G}{B/G}{B/G}"); this.subtype.add(SubType.INSECT); this.subtype.add(SubType.HORROR); this.power = new MageInt(6); @@ -36,11 +39,17 @@ public final class Gleancrawler extends CardImpl { // ({B/G} can be paid with either {B} or {G}.) this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("({B/G} can be paid with either {B} or {G}.)"))); + // Trample this.addAbility(TrampleAbility.getInstance()); - // At the beginning of your end step, return to your hand all creature cards in your graveyard that were put there from the battlefield this turn. - this.addAbility(new BeginningOfEndStepTriggeredAbility(new GleancrawlerEffect(), TargetController.YOU, false), new CardsPutIntoGraveyardWatcher()); + // At the beginning of your end step, return to your hand all creature cards in your graveyard that were put there from the battlefield this turn. + this.addAbility(new BeginningOfEndStepTriggeredAbility( + new ReturnToHandFromGraveyardAllEffect(filter, TargetController.YOU) + .setText("return to your hand all creature cards in your graveyard " + + "that were put there from the battlefield this turn"), + TargetController.YOU, false + ), new CardsPutIntoGraveyardWatcher()); } private Gleancrawler(final Gleancrawler card) { @@ -52,44 +61,3 @@ public final class Gleancrawler extends CardImpl { return new Gleancrawler(this); } } - -class GleancrawlerEffect extends OneShotEffect { - - boolean applied = false; - - public GleancrawlerEffect() { - super(Outcome.ReturnToHand); - this.staticText = "return to your hand all creature cards in your graveyard that were put there from the battlefield this turn"; - } - - public GleancrawlerEffect(final GleancrawlerEffect effect) { - super(effect); - } - - @Override - public GleancrawlerEffect copy() { - return new GleancrawlerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && watcher != null) { - Set cardsToGraveyardThisTurn = watcher.getCardsPutToGraveyardFromBattlefield(); - Cards cardsToHand = new CardsImpl(); - for (MageObjectReference mor : cardsToGraveyardThisTurn) { - if (game.getState().getZoneChangeCounter(mor.getSourceId()) == mor.getZoneChangeCounter()) { - Card card = game.getCard(mor.getSourceId()); - if (card != null && card.isCreature() - && card.isOwnedBy(source.getControllerId())) { - cardsToHand.add(card); - } - } - } - controller.moveCards(cardsToHand, Zone.HAND, source, game); - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/g/GrimReturn.java b/Mage.Sets/src/mage/cards/g/GrimReturn.java index e2571eebef..074589c7ce 100644 --- a/Mage.Sets/src/mage/cards/g/GrimReturn.java +++ b/Mage.Sets/src/mage/cards/g/GrimReturn.java @@ -1,24 +1,15 @@ - package mage.cards.g; -import mage.MageObjectReference; -import mage.abilities.Ability; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardIdPredicate; -import mage.game.Game; +import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate; import mage.target.common.TargetCardInGraveyard; -import mage.target.targetadjustment.TargetAdjuster; import mage.watchers.common.CardsPutIntoGraveyardWatcher; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; /** @@ -26,16 +17,22 @@ import java.util.UUID; */ public final class GrimReturn extends CardImpl { - private static final String textFilter = "creature card in a graveyard that was put there from the battlefield this turn"; + private static final FilterCard filter = new FilterCreatureCard( + "creature card in a graveyard that was put there from the battlefield this turn" + ); + + static { + filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance); + } public GrimReturn(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}"); // Choose target creature card in a graveyard that was put there from the battlefield this turn. Put that card onto the battlefield under your control. - Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect(); - effect.setText("Choose target creature card in a graveyard that was put there from the battlefield this turn. Put that card onto the battlefield under your control"); - this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); - this.getSpellAbility().setTargetAdjuster(GrimReturnAdjuster.instance); + this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect() + .setText("Choose target creature card in a graveyard that was put there from the " + + "battlefield this turn. Put that card onto the battlefield under your control")); + this.getSpellAbility().addTarget(new TargetCardInGraveyard(filter)); this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher()); } @@ -48,26 +45,3 @@ public final class GrimReturn extends CardImpl { return new GrimReturn(this); } } - -enum GrimReturnAdjuster implements TargetAdjuster { - instance; - private static final String textFilter = "creature card in a graveyard that was put there from the battlefield this turn"; - - @Override - public void adjustTargets(Ability ability, Game game) { - CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); - if (watcher == null) { - return; - } - FilterCard filter = new FilterCreatureCard(textFilter); - List uuidPredicates = new ArrayList<>(); - for (MageObjectReference mor : watcher.getCardsPutToGraveyardFromBattlefield()) { - if (mor.zoneCounterIsCurrent(game)) { - uuidPredicates.add(new CardIdPredicate(mor.getSourceId())); - } - } - filter.add(Predicates.or(uuidPredicates)); - ability.getTargets().clear(); - ability.addTarget(new TargetCardInGraveyard(filter)); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java b/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java index cdb4749d7e..d3c9163c0a 100644 --- a/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java +++ b/Mage.Sets/src/mage/cards/n/NoRestForTheWicked.java @@ -1,38 +1,40 @@ - package mage.cards.n; -import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.effects.OneShotEffect; -import mage.cards.*; +import mage.abilities.effects.common.ReturnToHandFromGraveyardAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.WatcherScope; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; -import mage.players.Player; -import mage.watchers.Watcher; +import mage.constants.TargetController; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate; +import mage.watchers.common.CardsPutIntoGraveyardWatcher; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; /** - * * @author anonymous */ public final class NoRestForTheWicked extends CardImpl { + private static final FilterCard filter = new FilterCreatureCard(); + + static { + filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance); + } + public NoRestForTheWicked(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); // Sacrifice No Rest for the Wicked: Return to your hand all creature cards in your graveyard that were put there from the battlefield this turn. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new NoRestForTheWickedEffect(), new SacrificeSourceCost()); - Watcher watcher = new NoRestForTheWickedWatcher(); - addAbility(ability, watcher); + this.addAbility(new SimpleActivatedAbility( + new ReturnToHandFromGraveyardAllEffect(filter, TargetController.YOU) + .setText("return to your hand all creature cards in your graveyard " + + "that were put there from the battlefield this turn"), + new SacrificeSourceCost() + ), new CardsPutIntoGraveyardWatcher()); } private NoRestForTheWicked(final NoRestForTheWicked card) { @@ -44,72 +46,3 @@ public final class NoRestForTheWicked extends CardImpl { return new NoRestForTheWicked(this); } } - -class NoRestForTheWickedEffect extends OneShotEffect { - - NoRestForTheWickedEffect() { - super(Outcome.Sacrifice); - staticText = "Return to your hand all creature cards in your graveyard that were put there from the battlefield this turn"; - } - - NoRestForTheWickedEffect(final NoRestForTheWickedEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - NoRestForTheWickedWatcher watcher = game.getState().getWatcher(NoRestForTheWickedWatcher.class); - Player controller = game.getPlayer(source.getControllerId()); - if (watcher != null && controller != null) { - Cards cardsToHand = new CardsImpl(); - for (UUID cardId : watcher.getCards()) { - Card c = game.getCard(cardId); - if (c != null) { - if (game.getState().getZone(cardId) == Zone.GRAVEYARD - && c.isCreature() - && c.isOwnedBy(source.getControllerId())) { - cardsToHand.add(c); - } - } - } - controller.moveCards(cardsToHand, Zone.HAND, source, game); - return true; - } - return false; - } - - @Override - public NoRestForTheWickedEffect copy() { - return new NoRestForTheWickedEffect(this); - - } -} - -class NoRestForTheWickedWatcher extends Watcher { - - public List getCards() { - return cards; - } - - private List cards; - - public NoRestForTheWickedWatcher() { - super(WatcherScope.GAME); - this.cards = new ArrayList<>(); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE - && ((ZoneChangeEvent) event).isDiesEvent()) { - //400.3 Intercept only the controller's events - cards.add(event.getTargetId()); - } - } - - @Override - public void reset() { - super.reset(); - cards.clear(); - } -} diff --git a/Mage.Sets/src/mage/cards/s/SalvagerOfRuin.java b/Mage.Sets/src/mage/cards/s/SalvagerOfRuin.java index d5d7b88f7c..54f95345fe 100644 --- a/Mage.Sets/src/mage/cards/s/SalvagerOfRuin.java +++ b/Mage.Sets/src/mage/cards/s/SalvagerOfRuin.java @@ -1,20 +1,17 @@ package mage.cards.s; import mage.MageInt; -import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.FilterCard; import mage.filter.common.FilterPermanentCard; -import mage.filter.predicate.Predicate; -import mage.game.Game; +import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate; import mage.target.common.TargetCardInYourGraveyard; import mage.watchers.common.CardsPutIntoGraveyardWatcher; @@ -30,7 +27,7 @@ public final class SalvagerOfRuin extends CardImpl { ); static { - filter.add(SalvagerOfRuinPredicate.instance); + filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance); } public SalvagerOfRuin(UUID ownerId, CardSetInfo setInfo) { @@ -41,11 +38,13 @@ public final class SalvagerOfRuin extends CardImpl { this.toughness = new MageInt(1); // Sacrifice Salvager of Ruin: Choose target permanent card in your graveyard that was put there from the battlefield this turn. Return it to your hand. - Ability ability = new SimpleActivatedAbility(new ReturnFromGraveyardToHandTargetEffect().setText( - "Choose target permanent card in your graveyard " + - "that was put there from the battlefield this turn. " + - "Return it to your hand." - ), new SacrificeSourceCost()); + Ability ability = new SimpleActivatedAbility( + new ReturnFromGraveyardToHandTargetEffect() + .setText("Choose target permanent card in your graveyard " + + "that was put there from the battlefield this turn. " + + "Return it to your hand."), + new SacrificeSourceCost() + ); ability.addTarget(new TargetCardInYourGraveyard(1, filter)); this.addAbility(ability, new CardsPutIntoGraveyardWatcher()); } @@ -59,14 +58,3 @@ public final class SalvagerOfRuin extends CardImpl { return new SalvagerOfRuin(this); } } - -enum SalvagerOfRuinPredicate implements Predicate { - instance; - - @Override - public boolean apply(Card input, Game game) { - CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); - return watcher != null - && watcher.getCardsPutToGraveyardFromBattlefield().contains(new MageObjectReference(input, game)); - } -} diff --git a/Mage.Sets/src/mage/cards/s/SecondSunrise.java b/Mage.Sets/src/mage/cards/s/SecondSunrise.java index 2f22582456..7d8a17e573 100644 --- a/Mage.Sets/src/mage/cards/s/SecondSunrise.java +++ b/Mage.Sets/src/mage/cards/s/SecondSunrise.java @@ -2,27 +2,21 @@ package mage.cards.s; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.WatcherScope; import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; -import mage.watchers.Watcher; - -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; import mage.players.Player; +import mage.watchers.common.CardsPutIntoGraveyardWatcher; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class SecondSunrise extends CardImpl { @@ -32,7 +26,7 @@ public final class SecondSunrise extends CardImpl { // Each player returns to the battlefield all artifact, creature, enchantment, and land cards in their graveyard that were put there from the battlefield this turn. this.getSpellAbility().addEffect(new SecondSunriseEffect()); - this.getSpellAbility().addWatcher(new SecondSunriseWatcher()); + this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher()); } private SecondSunrise(final SecondSunrise card) { @@ -47,39 +41,41 @@ public final class SecondSunrise extends CardImpl { class SecondSunriseEffect extends OneShotEffect { - SecondSunriseEffect() { - super(Outcome.PutCardInPlay); - staticText = "Each player returns to the battlefield all artifact, creature, enchantment, and land cards in their graveyard that were put there from the battlefield this turn"; + private static final FilterCard filter = new FilterCard(); + + static { + filter.add(Predicates.or( + CardType.ARTIFACT.getPredicate(), + CardType.CREATURE.getPredicate(), + CardType.ENCHANTMENT.getPredicate(), + CardType.LAND.getPredicate() + )); + filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance); } - SecondSunriseEffect(final SecondSunriseEffect effect) { + SecondSunriseEffect() { + super(Outcome.PutCardInPlay); + staticText = "Each player returns to the battlefield all artifact, creature, enchantment, " + + "and land cards in their graveyard that were put there from the battlefield this turn."; + } + + private SecondSunriseEffect(final SecondSunriseEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { - SecondSunriseWatcher watcher = game.getState().getWatcher(SecondSunriseWatcher.class); - if (watcher != null) { - Set cardsToBattlefield = new LinkedHashSet<>(); - for (UUID id : watcher.getCards()) { - Card card = game.getCard(id); - if (card != null - && game.getState().getZone(id) == Zone.GRAVEYARD) { - if (card.isArtifact() || card.isCreature() - || card.isEnchantment() || card.isLand()) { - cardsToBattlefield.add(card); - } - } + boolean result = false; + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; } - for (Card card : cardsToBattlefield) { - Player owner = game.getPlayer(card.getOwnerId()); - if (owner != null) { - owner.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - return true; + result |= player.moveCards(player.getGraveyard().getCards( + filter, source.getSourceId(), source.getControllerId(), game + ), Zone.BATTLEFIELD, source, game); } - return false; + return result; } @Override @@ -87,30 +83,3 @@ class SecondSunriseEffect extends OneShotEffect { return new SecondSunriseEffect(this); } } - -class SecondSunriseWatcher extends Watcher { - - private List cards = new ArrayList<>(); - - public SecondSunriseWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE - && ((ZoneChangeEvent) event).isDiesEvent()) { - cards.add(event.getTargetId()); - } - } - - @Override - public void reset() { - super.reset(); - cards.clear(); - } - - public List getCards() { - return cards; - } -} diff --git a/Mage.Sets/src/mage/cards/t/ThrillingEncore.java b/Mage.Sets/src/mage/cards/t/ThrillingEncore.java index 2dcfe48a9d..865b21b9ea 100644 --- a/Mage.Sets/src/mage/cards/t/ThrillingEncore.java +++ b/Mage.Sets/src/mage/cards/t/ThrillingEncore.java @@ -1,30 +1,31 @@ - package mage.cards.t; -import java.util.UUID; -import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate; import mage.game.Game; -import mage.target.targetpointer.FixedTarget; +import mage.players.Player; import mage.watchers.common.CardsPutIntoGraveyardWatcher; +import java.util.UUID; + /** - * * @author L_J */ public final class ThrillingEncore extends CardImpl { public ThrillingEncore(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{B}"); - + // Put onto the battlefield under your control all creature cards in all graveyards that were put there from the battlefield this turn. this.getSpellAbility().addEffect(new ThrillingEncoreEffect()); this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher()); @@ -41,36 +42,42 @@ public final class ThrillingEncore extends CardImpl { } class ThrillingEncoreEffect extends OneShotEffect { - - public ThrillingEncoreEffect() { - super(Outcome.PutCardInPlay); - this.staticText = "Put onto the battlefield under your control all creature cards in all graveyards that were put there from the battlefield this turn"; + + private static final FilterCard filter = new FilterCreatureCard(); + + static { + filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance); } - - public ThrillingEncoreEffect(final ThrillingEncoreEffect effect) { + + ThrillingEncoreEffect() { + super(Outcome.PutCardInPlay); + this.staticText = "Put onto the battlefield under your control all creature cards " + + "in all graveyards that were put there from the battlefield this turn"; + } + + private ThrillingEncoreEffect(final ThrillingEncoreEffect effect) { super(effect); } - + @Override public ThrillingEncoreEffect copy() { return new ThrillingEncoreEffect(this); } - + @Override public boolean apply(Game game, Ability source) { - CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); - if (watcher != null) { - for (MageObjectReference mor : watcher.getCardsPutToGraveyardFromBattlefield()) { - if (game.getState().getZoneChangeCounter(mor.getSourceId()) == mor.getZoneChangeCounter()) { - Card card = mor.getCard(game); - if (card != null && card.isCreature()) { - Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect(); - effect.setTargetPointer(new FixedTarget(card, game)); - effect.apply(game, source); - } - } - } + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; } - return true; + Cards cards = new CardsImpl(); + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + cards.addAll(player.getGraveyard().getCards(filter, source.getSourceId(), playerId, game)); + } + return controller.moveCards(cards, Zone.BATTLEFIELD, source, game); } } diff --git a/Mage.Sets/src/mage/cards/t/TwilightShepherd.java b/Mage.Sets/src/mage/cards/t/TwilightShepherd.java index 5738d4d4ab..5ab7293ba4 100644 --- a/Mage.Sets/src/mage/cards/t/TwilightShepherd.java +++ b/Mage.Sets/src/mage/cards/t/TwilightShepherd.java @@ -1,38 +1,35 @@ - package mage.cards.t; -import java.util.Set; -import java.util.UUID; import mage.MageInt; -import mage.MageObjectReference; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnToHandFromGraveyardAllEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.PersistAbility; import mage.abilities.keyword.VigilanceAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.players.Player; +import mage.constants.TargetController; +import mage.filter.FilterCard; +import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate; import mage.watchers.common.CardsPutIntoGraveyardWatcher; +import java.util.UUID; + /** - * * @author jeffwadsworth - * */ public final class TwilightShepherd extends CardImpl { + private static final FilterCard filter = new FilterCard(); + + static { + filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance); + } + public TwilightShepherd(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}{W}"); this.subtype.add(SubType.ANGEL); this.power = new MageInt(5); @@ -45,7 +42,12 @@ public final class TwilightShepherd extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // When Twilight Shepherd enters the battlefield, return to your hand all cards in your graveyard that were put there from the battlefield this turn. - this.addAbility(new EntersBattlefieldTriggeredAbility(new TwilightShepherdEffect(), false), new CardsPutIntoGraveyardWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new ReturnToHandFromGraveyardAllEffect(filter, TargetController.YOU) + .setText("return to your hand all cards in your graveyard " + + "that were put there from the battlefield this turn"), + false + ), new CardsPutIntoGraveyardWatcher()); // Persist this.addAbility(new PersistAbility()); @@ -60,44 +62,3 @@ public final class TwilightShepherd extends CardImpl { return new TwilightShepherd(this); } } - -class TwilightShepherdEffect extends OneShotEffect { - - boolean applied = false; - - public TwilightShepherdEffect() { - super(Outcome.ReturnToHand); - this.staticText = "return to your hand all cards in your graveyard that were put there from the battlefield this turn"; - } - - public TwilightShepherdEffect(final TwilightShepherdEffect effect) { - super(effect); - } - - @Override - public TwilightShepherdEffect copy() { - return new TwilightShepherdEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && watcher != null) { - Set cardsInGraveyard = watcher.getCardsPutToGraveyardFromBattlefield(); - Cards cardsToHand = new CardsImpl(); - for (MageObjectReference mor : cardsInGraveyard) { - if (game.getState().getZoneChangeCounter(mor.getSourceId()) == mor.getZoneChangeCounter()) { - Card card = game.getCard(mor.getSourceId()); - if (card != null - && card.isOwnedBy(source.getControllerId())) { - cardsToHand.add(card); - } - } - } - controller.moveCards(cardsToHand, Zone.HAND, source, game); - return true; - } - return false; - } -} diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromGraveyardAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromGraveyardAllEffect.java index 9d89562071..11d3fd4595 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromGraveyardAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ReturnToHandFromGraveyardAllEffect.java @@ -1,53 +1,89 @@ package mage.abilities.effects.common; -import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; +import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author LevelX2 */ public class ReturnToHandFromGraveyardAllEffect extends OneShotEffect { private final FilterCard filter; + private final TargetController targetController; public ReturnToHandFromGraveyardAllEffect(FilterCard filter) { - super(Outcome.ReturnToHand); - this.filter = filter; - staticText = "Each player returns all " + filter.getMessage() + " from their graveyard to their hand"; + this(filter, TargetController.EACH_PLAYER); } - public ReturnToHandFromGraveyardAllEffect(final ReturnToHandFromGraveyardAllEffect effect) { + public ReturnToHandFromGraveyardAllEffect(FilterCard filter, TargetController targetController) { + super(Outcome.ReturnToHand); + this.filter = filter; + this.targetController = targetController; + } + + private ReturnToHandFromGraveyardAllEffect(final ReturnToHandFromGraveyardAllEffect effect) { super(effect); this.filter = effect.filter; + this.targetController = effect.targetController; } @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - Player player = game.getPlayer(playerId); - if (player != null) { - player.moveCards(player.getGraveyard() - .getCards(filter, source.getSourceId(), player.getId(), game), - Zone.HAND, source, game); - } - - } - return true; + if (controller == null) { + return false; } - return false; + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + switch (targetController) { + case ANY: + case EACH_PLAYER: + break; + case OPPONENT: + if (!controller.hasOpponent(playerId, game)) { + continue; + } + case YOU: + if (!controller.getId().equals(playerId)) { + continue; + } + } + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + player.moveCards(player.getGraveyard().getCards( + filter, source.getSourceId(), player.getId(), game + ), Zone.HAND, source, game); + } + return true; } @Override public ReturnToHandFromGraveyardAllEffect copy() { return new ReturnToHandFromGraveyardAllEffect(this); } + + @Override + public String getText(Mode mode) { + if(staticText!=null&&!staticText.isEmpty()){ + return staticText; + } + String rule=""; + switch (targetController){ + case EACH_PLAYER: + rule+="each player";break; + case OPPONENT:rule+="opponent";break; + case YOU: + + } + } } diff --git a/Mage/src/main/java/mage/filter/predicate/card/PutIntoGraveFromBattlefieldThisTurnPredicate.java b/Mage/src/main/java/mage/filter/predicate/card/PutIntoGraveFromBattlefieldThisTurnPredicate.java new file mode 100644 index 0000000000..c0be0f81fc --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/card/PutIntoGraveFromBattlefieldThisTurnPredicate.java @@ -0,0 +1,19 @@ +package mage.filter.predicate.card; + +import mage.cards.Card; +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.watchers.common.CardsPutIntoGraveyardWatcher; + +/** + * @author TheElk801 + */ +public enum PutIntoGraveFromBattlefieldThisTurnPredicate implements Predicate { + instance; + + @Override + public boolean apply(Card input, Game game) { + CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); + return watcher != null && watcher.checkCardFromBattlefield(input, game); + } +} diff --git a/Mage/src/main/java/mage/watchers/common/CardsPutIntoGraveyardWatcher.java b/Mage/src/main/java/mage/watchers/common/CardsPutIntoGraveyardWatcher.java index 0a73067aab..75ed33cdb5 100644 --- a/Mage/src/main/java/mage/watchers/common/CardsPutIntoGraveyardWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/CardsPutIntoGraveyardWatcher.java @@ -1,13 +1,7 @@ - package mage.watchers.common; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - import mage.MageObjectReference; +import mage.cards.Card; import mage.constants.WatcherScope; import mage.constants.Zone; import mage.game.Game; @@ -15,6 +9,9 @@ import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.watchers.Watcher; +import java.util.*; +import java.util.stream.Collectors; + /** * Counts amount of cards put into graveyards of players during the current * turn. Also the UUIDs of cards that went to graveyard from Battlefield this @@ -33,19 +30,17 @@ public class CardsPutIntoGraveyardWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.UNTAP_STEP_PRE) { - reset(); + if (event.getType() != GameEvent.EventType.ZONE_CHANGE + || ((ZoneChangeEvent) event).getToZone() != Zone.GRAVEYARD) { + return; } - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { - UUID playerId = event.getPlayerId(); - if (playerId != null && game.getCard(event.getTargetId()) != null) { - amountOfCardsThisTurn.putIfAbsent(playerId, 0); - amountOfCardsThisTurn.compute(playerId, (k, amount) -> amount += 1); - - if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { - cardsPutToGraveyardFromBattlefield.add(new MageObjectReference(event.getTargetId(), game)); - } - } + UUID playerId = event.getPlayerId(); + if (playerId == null || game.getCard(event.getTargetId()) == null) { + return; + } + amountOfCardsThisTurn.compute(playerId, (k, amount) -> amount == null ? 1 : Integer.sum(amount, 1)); + if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { + cardsPutToGraveyardFromBattlefield.add(new MageObjectReference(((ZoneChangeEvent) event).getTarget(), game, 1)); } } @@ -53,8 +48,12 @@ public class CardsPutIntoGraveyardWatcher extends Watcher { return amountOfCardsThisTurn.getOrDefault(playerId, 0); } - public Set getCardsPutToGraveyardFromBattlefield() { - return cardsPutToGraveyardFromBattlefield; + public Set getCardsPutToGraveyardFromBattlefield(Game game) { + return cardsPutToGraveyardFromBattlefield.stream().map(mor -> mor.getCard(game)).filter(Objects::nonNull).collect(Collectors.toSet()); + } + + public boolean checkCardFromBattlefield(Card card, Game game) { + return cardsPutToGraveyardFromBattlefield.stream().anyMatch(mor -> mor.refersTo(card, game)); } @Override