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;
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<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;
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;
}

View file

@ -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<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;
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<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;
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<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();
return player.moveCards(player.getGraveyard().getCards(
filter, source.getSourceId(), source.getControllerId(), game
), Zone.BATTLEFIELD, source, game);
}
}
// dont mourn for me. this is my destiny.

View file

@ -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 {
// <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
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<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;
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<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;
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<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;
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<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.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<Card> 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<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;
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);
}
}

View file

@ -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<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;
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:
}
}
}

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;
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<MageObjectReference> getCardsPutToGraveyardFromBattlefield() {
return cardsPutToGraveyardFromBattlefield;
public Set<Card> 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