simplified and consolidated effects which check cards put into graveyards from the battlefield

This commit is contained in:
Evan Kranzler 2021-02-25 10:45:26 -05:00
parent c01e1cd133
commit 35be23537f
15 changed files with 311 additions and 594 deletions

View file

@ -1,15 +1,12 @@
package mage.cards.b; package mage.cards.b;
import mage.MageObjectReference;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.common.FilterPermanentCard; import mage.filter.common.FilterPermanentCard;
import mage.filter.predicate.Predicate; import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate;
import mage.game.Game;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
import mage.watchers.common.CardsPutIntoGraveyardWatcher; import mage.watchers.common.CardsPutIntoGraveyardWatcher;
@ -25,7 +22,7 @@ public final class BroughtBack extends CardImpl {
); );
static { static {
filter.add(BroughtBackPredicate.instance); filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance);
} }
public BroughtBack(UUID ownerId, CardSetInfo setInfo) { public BroughtBack(UUID ownerId, CardSetInfo setInfo) {
@ -51,14 +48,3 @@ public final class BroughtBack extends CardImpl {
return new BroughtBack(this); return new BroughtBack(this);
} }
} }
enum BroughtBackPredicate implements Predicate<Card> {
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));
}
}

View file

@ -1,11 +1,13 @@
package mage.cards.c; package mage.cards.c;
import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.continuous.BoostAllEffect; 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.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
@ -67,15 +69,8 @@ class CryOfTheCarnariumExileEffect extends OneShotEffect {
if (player == null || watcher == null) { if (player == null || watcher == null) {
return false; return false;
} }
Cards cards = new CardsImpl(); Cards cards = new CardsImpl(watcher.getCardsPutToGraveyardFromBattlefield(game));
for (MageObjectReference mor : watcher.getCardsPutToGraveyardFromBattlefield()) { cards.removeIf(uuid -> !game.getCard(uuid).isCreature());
if (game.getState().getZoneChangeCounter(mor.getSourceId()) == mor.getZoneChangeCounter()) {
Card card = mor.getCard(game);
if (card != null && card.isCreature()) {
cards.add(card);
}
}
}
player.moveCards(cards, Zone.EXILED, source, game); player.moveCards(cards, Zone.EXILED, source, game);
return true; return true;
} }

View file

@ -1,26 +1,19 @@
package mage.cards.f; package mage.cards.f;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.WatcherScope;
import mage.constants.Zone; 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.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.players.Player; 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; 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. // 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().addEffect(new FaithsRewardEffect());
this.getSpellAbility().addWatcher(new FaithsRewardWatcher()); this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher());
} }
private FaithsReward(final FaithsReward card) { private FaithsReward(final FaithsReward card) {
@ -48,6 +41,12 @@ public final class FaithsReward extends CardImpl {
class FaithsRewardEffect extends OneShotEffect { class FaithsRewardEffect extends OneShotEffect {
private static final FilterCard filter = new FilterPermanentCard();
static {
filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance);
}
FaithsRewardEffect() { FaithsRewardEffect() {
super(Outcome.PutCardInPlay); super(Outcome.PutCardInPlay);
staticText = "Return to the battlefield all permanent cards in your graveyard that were put there from the battlefield this turn"; 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 @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
FaithsRewardWatcher watcher = game.getState().getWatcher(FaithsRewardWatcher.class); if (player == null) {
if (player == null || watcher == null) {
return false; 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 @Override
@ -72,36 +72,3 @@ class FaithsRewardEffect extends OneShotEffect {
return new FaithsRewardEffect(this); return new FaithsRewardEffect(this);
} }
} }
class FaithsRewardWatcher extends Watcher {
private final Set<MageObjectReference> 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();
}
}

View file

@ -1,32 +1,27 @@
package mage.cards.f; package mage.cards.f;
import mage.MageInt; import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl; 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.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards; import mage.constants.CardType;
import mage.cards.CardsImpl; import mage.constants.Duration;
import mage.constants.*; import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.FilterCard;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.game.Game; import mage.filter.common.FilterCreatureCard;
import mage.game.events.GameEvent; import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate;
import mage.game.events.ZoneChangeEvent;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent; 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; import java.util.UUID;
/** /**
@ -34,6 +29,12 @@ import java.util.UUID;
*/ */
public final class FellShepherd extends CardImpl { public final class FellShepherd extends CardImpl {
private static final FilterCard filter = new FilterCreatureCard();
static {
filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance);
}
public FellShepherd(UUID ownerId, CardSetInfo setInfo) { public FellShepherd(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}");
this.subtype.add(SubType.AVATAR); this.subtype.add(SubType.AVATAR);
@ -42,14 +43,20 @@ public final class FellShepherd extends CardImpl {
this.toughness = new MageInt(6); 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. // 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. // {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.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)));
ability.addTarget(new TargetCreaturePermanent()); ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability); this.addAbility(ability);
} }
private FellShepherd(final FellShepherd card) { private FellShepherd(final FellShepherd card) {
@ -61,63 +68,3 @@ public final class FellShepherd extends CardImpl {
return new FellShepherd(this); 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<MageObjectReference> 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();
}
}

View file

@ -1,26 +1,21 @@
package mage.cards.g; package mage.cards.g;
import mage.MageInt; import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSourceEffect; import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.players.Player; 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.UUID;
import java.util.stream.Collectors;
/** /**
* @author TheElk801 * @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. // 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 ability = new DiesSourceTriggeredAbility(new ExileSourceEffect().setText("exile it"));
ability.addEffect(new GerrardWeatherlightHeroEffect()); ability.addEffect(new GerrardWeatherlightHeroEffect());
this.addAbility(ability, new GerrardWeatherlightHeroWatcher()); this.addAbility(ability, new CardsPutIntoGraveyardWatcher());
} }
private GerrardWeatherlightHero(final GerrardWeatherlightHero card) { private GerrardWeatherlightHero(final GerrardWeatherlightHero card) {
@ -57,6 +52,15 @@ public final class GerrardWeatherlightHero extends CardImpl {
class GerrardWeatherlightHeroEffect extends OneShotEffect { class GerrardWeatherlightHeroEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard();
static {
filter.add(Predicates.or(
CardType.ARTIFACT.getPredicate(),
CardType.CREATURE.getPredicate()
));
}
GerrardWeatherlightHeroEffect() { GerrardWeatherlightHeroEffect() {
super(Outcome.Benefit); super(Outcome.Benefit);
staticText = "and return to the battlefield all artifact and creature cards " + staticText = "and return to the battlefield all artifact and creature cards " +
@ -75,48 +79,12 @@ class GerrardWeatherlightHeroEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
GerrardWeatherlightHeroWatcher watcher = game.getState().getWatcher(GerrardWeatherlightHeroWatcher.class); if (player == null) {
if (player == null || watcher == null) {
return false; return false;
} }
return player.moveCards( return player.moveCards(player.getGraveyard().getCards(
player.getGraveyard() filter, source.getSourceId(), source.getControllerId(), game
.getCards(game) ), Zone.BATTLEFIELD, source, game);
.stream()
.filter(card -> watcher.checkCard(card, game))
.collect(Collectors.toSet()),
Zone.BATTLEFIELD, source, game
);
}
}
class GerrardWeatherlightHeroWatcher extends Watcher {
private final List<MageObjectReference> 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();
} }
} }
// dont mourn for me. this is my destiny. // dont mourn for me. this is my destiny.

View file

@ -1,34 +1,37 @@
package mage.cards.g; package mage.cards.g;
import java.util.Set;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.ReturnToHandFromGraveyardAllEffect;
import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.TrampleAbility;
import mage.cards.*; import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.TargetController; import mage.constants.TargetController;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.filter.FilterCard;
import mage.players.Player; import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate;
import mage.watchers.common.CardsPutIntoGraveyardWatcher; import mage.watchers.common.CardsPutIntoGraveyardWatcher;
import java.util.UUID;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public final class Gleancrawler extends CardImpl { public final class Gleancrawler extends CardImpl {
private static final FilterCard filter = new FilterCreatureCard();
static {
filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance);
}
public Gleancrawler(UUID ownerId, CardSetInfo setInfo) { 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.INSECT);
this.subtype.add(SubType.HORROR); this.subtype.add(SubType.HORROR);
this.power = new MageInt(6); this.power = new MageInt(6);
@ -36,11 +39,17 @@ public final class Gleancrawler extends CardImpl {
// <i>({B/G} can be paid with either {B} or {G}.)</i> // <i>({B/G} can be paid with either {B} or {G}.)</i>
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("<i>({B/G} can be paid with either {B} or {G}.)</i>"))); this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("<i>({B/G} can be paid with either {B} or {G}.)</i>")));
// Trample // Trample
this.addAbility(TrampleAbility.getInstance()); 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) { private Gleancrawler(final Gleancrawler card) {
@ -52,44 +61,3 @@ public final class Gleancrawler extends CardImpl {
return new Gleancrawler(this); 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<MageObjectReference> 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;
}
}

View file

@ -1,24 +1,15 @@
package mage.cards.g; package mage.cards.g;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.Predicates; import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate;
import mage.filter.predicate.mageobject.CardIdPredicate;
import mage.game.Game;
import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCardInGraveyard;
import mage.target.targetadjustment.TargetAdjuster;
import mage.watchers.common.CardsPutIntoGraveyardWatcher; import mage.watchers.common.CardsPutIntoGraveyardWatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
/** /**
@ -26,16 +17,22 @@ import java.util.UUID;
*/ */
public final class GrimReturn extends CardImpl { 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) { public GrimReturn(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}"); 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. // 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(); this.getSpellAbility().addEffect(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"); .setText("Choose target creature card in a graveyard that was put there from the " +
this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); "battlefield this turn. Put that card onto the battlefield under your control"));
this.getSpellAbility().setTargetAdjuster(GrimReturnAdjuster.instance); this.getSpellAbility().addTarget(new TargetCardInGraveyard(filter));
this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher()); this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher());
} }
@ -48,26 +45,3 @@ public final class GrimReturn extends CardImpl {
return new GrimReturn(this); 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<CardIdPredicate> 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));
}
}

View file

@ -1,38 +1,40 @@
package mage.cards.n; package mage.cards.n;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnToHandFromGraveyardAllEffect;
import mage.cards.*; import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.TargetController;
import mage.constants.WatcherScope; import mage.filter.FilterCard;
import mage.constants.Zone; import mage.filter.common.FilterCreatureCard;
import mage.game.Game; import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate;
import mage.game.events.GameEvent; import mage.watchers.common.CardsPutIntoGraveyardWatcher;
import mage.game.events.ZoneChangeEvent;
import mage.players.Player;
import mage.watchers.Watcher;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
/** /**
*
* @author anonymous * @author anonymous
*/ */
public final class NoRestForTheWicked extends CardImpl { public final class NoRestForTheWicked extends CardImpl {
private static final FilterCard filter = new FilterCreatureCard();
static {
filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance);
}
public NoRestForTheWicked(UUID ownerId, CardSetInfo setInfo) { 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. // 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()); this.addAbility(new SimpleActivatedAbility(
Watcher watcher = new NoRestForTheWickedWatcher(); new ReturnToHandFromGraveyardAllEffect(filter, TargetController.YOU)
addAbility(ability, watcher); .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) { private NoRestForTheWicked(final NoRestForTheWicked card) {
@ -44,72 +46,3 @@ public final class NoRestForTheWicked extends CardImpl {
return new NoRestForTheWicked(this); 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<UUID> getCards() {
return cards;
}
private List<UUID> 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();
}
}

View file

@ -1,20 +1,17 @@
package mage.cards.s; package mage.cards.s;
import mage.MageInt; import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.common.FilterPermanentCard; import mage.filter.common.FilterPermanentCard;
import mage.filter.predicate.Predicate; import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate;
import mage.game.Game;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
import mage.watchers.common.CardsPutIntoGraveyardWatcher; import mage.watchers.common.CardsPutIntoGraveyardWatcher;
@ -30,7 +27,7 @@ public final class SalvagerOfRuin extends CardImpl {
); );
static { static {
filter.add(SalvagerOfRuinPredicate.instance); filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance);
} }
public SalvagerOfRuin(UUID ownerId, CardSetInfo setInfo) { public SalvagerOfRuin(UUID ownerId, CardSetInfo setInfo) {
@ -41,11 +38,13 @@ public final class SalvagerOfRuin extends CardImpl {
this.toughness = new MageInt(1); 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. // 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( Ability ability = new SimpleActivatedAbility(
"Choose target permanent card in your graveyard " + new ReturnFromGraveyardToHandTargetEffect()
"that was put there from the battlefield this turn. " + .setText("Choose target permanent card in your graveyard " +
"Return it to your hand." "that was put there from the battlefield this turn. " +
), new SacrificeSourceCost()); "Return it to your hand."),
new SacrificeSourceCost()
);
ability.addTarget(new TargetCardInYourGraveyard(1, filter)); ability.addTarget(new TargetCardInYourGraveyard(1, filter));
this.addAbility(ability, new CardsPutIntoGraveyardWatcher()); this.addAbility(ability, new CardsPutIntoGraveyardWatcher());
} }
@ -59,14 +58,3 @@ public final class SalvagerOfRuin extends CardImpl {
return new SalvagerOfRuin(this); return new SalvagerOfRuin(this);
} }
} }
enum SalvagerOfRuinPredicate implements Predicate<Card> {
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));
}
}

View file

@ -2,27 +2,21 @@ package mage.cards.s;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.WatcherScope;
import mage.constants.Zone; 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.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.players.Player;
import mage.watchers.common.CardsPutIntoGraveyardWatcher;
import java.util.UUID;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public final class SecondSunrise extends CardImpl { 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. // 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().addEffect(new SecondSunriseEffect());
this.getSpellAbility().addWatcher(new SecondSunriseWatcher()); this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher());
} }
private SecondSunrise(final SecondSunrise card) { private SecondSunrise(final SecondSunrise card) {
@ -47,39 +41,41 @@ public final class SecondSunrise extends CardImpl {
class SecondSunriseEffect extends OneShotEffect { class SecondSunriseEffect extends OneShotEffect {
SecondSunriseEffect() { private static final FilterCard filter = new FilterCard();
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"; 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); super(effect);
} }
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
SecondSunriseWatcher watcher = game.getState().getWatcher(SecondSunriseWatcher.class); boolean result = false;
if (watcher != null) { for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Set<Card> cardsToBattlefield = new LinkedHashSet<>(); Player player = game.getPlayer(playerId);
for (UUID id : watcher.getCards()) { if (player == null) {
Card card = game.getCard(id); continue;
if (card != null
&& game.getState().getZone(id) == Zone.GRAVEYARD) {
if (card.isArtifact() || card.isCreature()
|| card.isEnchantment() || card.isLand()) {
cardsToBattlefield.add(card);
}
}
} }
for (Card card : cardsToBattlefield) { result |= player.moveCards(player.getGraveyard().getCards(
Player owner = game.getPlayer(card.getOwnerId()); filter, source.getSourceId(), source.getControllerId(), game
if (owner != null) { ), Zone.BATTLEFIELD, source, game);
owner.moveCards(card, Zone.BATTLEFIELD, source, game);
}
}
return true;
} }
return false; return result;
} }
@Override @Override
@ -87,30 +83,3 @@ class SecondSunriseEffect extends OneShotEffect {
return new SecondSunriseEffect(this); return new SecondSunriseEffect(this);
} }
} }
class SecondSunriseWatcher extends Watcher {
private List<UUID> 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<UUID> getCards() {
return cards;
}
}

View file

@ -1,30 +1,31 @@
package mage.cards.t; package mage.cards.t;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; 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.game.Game;
import mage.target.targetpointer.FixedTarget; import mage.players.Player;
import mage.watchers.common.CardsPutIntoGraveyardWatcher; import mage.watchers.common.CardsPutIntoGraveyardWatcher;
import java.util.UUID;
/** /**
*
* @author L_J * @author L_J
*/ */
public final class ThrillingEncore extends CardImpl { public final class ThrillingEncore extends CardImpl {
public ThrillingEncore(UUID ownerId, CardSetInfo setInfo) { public ThrillingEncore(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{B}"); 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. // 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().addEffect(new ThrillingEncoreEffect());
this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher()); this.getSpellAbility().addWatcher(new CardsPutIntoGraveyardWatcher());
@ -41,36 +42,42 @@ public final class ThrillingEncore extends CardImpl {
} }
class ThrillingEncoreEffect extends OneShotEffect { class ThrillingEncoreEffect extends OneShotEffect {
public ThrillingEncoreEffect() { private static final FilterCard filter = new FilterCreatureCard();
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"; 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); super(effect);
} }
@Override @Override
public ThrillingEncoreEffect copy() { public ThrillingEncoreEffect copy() {
return new ThrillingEncoreEffect(this); return new ThrillingEncoreEffect(this);
} }
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class); Player controller = game.getPlayer(source.getControllerId());
if (watcher != null) { if (controller == null) {
for (MageObjectReference mor : watcher.getCardsPutToGraveyardFromBattlefield()) { return false;
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);
}
}
}
} }
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);
} }
} }

View file

@ -1,38 +1,35 @@
package mage.cards.t; package mage.cards.t;
import java.util.Set;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; 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.FlyingAbility;
import mage.abilities.keyword.PersistAbility; import mage.abilities.keyword.PersistAbility;
import mage.abilities.keyword.VigilanceAbility; import mage.abilities.keyword.VigilanceAbility;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Outcome; import mage.constants.TargetController;
import mage.constants.Zone; import mage.filter.FilterCard;
import mage.game.Game; import mage.filter.predicate.card.PutIntoGraveFromBattlefieldThisTurnPredicate;
import mage.players.Player;
import mage.watchers.common.CardsPutIntoGraveyardWatcher; import mage.watchers.common.CardsPutIntoGraveyardWatcher;
import java.util.UUID;
/** /**
*
* @author jeffwadsworth * @author jeffwadsworth
*
*/ */
public final class TwilightShepherd extends CardImpl { public final class TwilightShepherd extends CardImpl {
private static final FilterCard filter = new FilterCard();
static {
filter.add(PutIntoGraveFromBattlefieldThisTurnPredicate.instance);
}
public TwilightShepherd(UUID ownerId, CardSetInfo setInfo) { 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.subtype.add(SubType.ANGEL);
this.power = new MageInt(5); this.power = new MageInt(5);
@ -45,7 +42,12 @@ public final class TwilightShepherd extends CardImpl {
this.addAbility(VigilanceAbility.getInstance()); 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. // 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 // Persist
this.addAbility(new PersistAbility()); this.addAbility(new PersistAbility());
@ -60,44 +62,3 @@ public final class TwilightShepherd extends CardImpl {
return new TwilightShepherd(this); 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<MageObjectReference> 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;
}
}

View file

@ -1,53 +1,89 @@
package mage.abilities.effects.common; package mage.abilities.effects.common;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.game.Game; import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import java.util.UUID;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public class ReturnToHandFromGraveyardAllEffect extends OneShotEffect { public class ReturnToHandFromGraveyardAllEffect extends OneShotEffect {
private final FilterCard filter; private final FilterCard filter;
private final TargetController targetController;
public ReturnToHandFromGraveyardAllEffect(FilterCard filter) { public ReturnToHandFromGraveyardAllEffect(FilterCard filter) {
super(Outcome.ReturnToHand); this(filter, TargetController.EACH_PLAYER);
this.filter = filter;
staticText = "Each player returns all " + filter.getMessage() + " from their graveyard to their hand";
} }
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); super(effect);
this.filter = effect.filter; this.filter = effect.filter;
this.targetController = effect.targetController;
} }
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { if (controller == null) {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { return false;
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;
} }
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 @Override
public ReturnToHandFromGraveyardAllEffect copy() { public ReturnToHandFromGraveyardAllEffect copy() {
return new ReturnToHandFromGraveyardAllEffect(this); 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:
}
}
} }

View file

@ -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<Card> {
instance;
@Override
public boolean apply(Card input, Game game) {
CardsPutIntoGraveyardWatcher watcher = game.getState().getWatcher(CardsPutIntoGraveyardWatcher.class);
return watcher != null && watcher.checkCardFromBattlefield(input, game);
}
}

View file

@ -1,13 +1,7 @@
package mage.watchers.common; 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.MageObjectReference;
import mage.cards.Card;
import mage.constants.WatcherScope; import mage.constants.WatcherScope;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
@ -15,6 +9,9 @@ import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent; import mage.game.events.ZoneChangeEvent;
import mage.watchers.Watcher; import mage.watchers.Watcher;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* Counts amount of cards put into graveyards of players during the current * 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 * turn. Also the UUIDs of cards that went to graveyard from Battlefield this
@ -33,19 +30,17 @@ public class CardsPutIntoGraveyardWatcher extends Watcher {
@Override @Override
public void watch(GameEvent event, Game game) { public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.UNTAP_STEP_PRE) { if (event.getType() != GameEvent.EventType.ZONE_CHANGE
reset(); || ((ZoneChangeEvent) event).getToZone() != Zone.GRAVEYARD) {
return;
} }
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD) { UUID playerId = event.getPlayerId();
UUID playerId = event.getPlayerId(); if (playerId == null || game.getCard(event.getTargetId()) == null) {
if (playerId != null && game.getCard(event.getTargetId()) != null) { return;
amountOfCardsThisTurn.putIfAbsent(playerId, 0); }
amountOfCardsThisTurn.compute(playerId, (k, amount) -> amount += 1); amountOfCardsThisTurn.compute(playerId, (k, amount) -> amount == null ? 1 : Integer.sum(amount, 1));
if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) {
if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { cardsPutToGraveyardFromBattlefield.add(new MageObjectReference(((ZoneChangeEvent) event).getTarget(), game, 1));
cardsPutToGraveyardFromBattlefield.add(new MageObjectReference(event.getTargetId(), game));
}
}
} }
} }
@ -53,8 +48,12 @@ public class CardsPutIntoGraveyardWatcher extends Watcher {
return amountOfCardsThisTurn.getOrDefault(playerId, 0); return amountOfCardsThisTurn.getOrDefault(playerId, 0);
} }
public Set<MageObjectReference> getCardsPutToGraveyardFromBattlefield() { public Set<Card> getCardsPutToGraveyardFromBattlefield(Game game) {
return cardsPutToGraveyardFromBattlefield; 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 @Override