refactored card.moveToExile usages A through D

heavily reworked Dark Impostor and Dimensional Breach
This commit is contained in:
Evan Kranzler 2021-02-28 16:10:23 -05:00
parent 129a477f56
commit 4a09654743
8 changed files with 248 additions and 247 deletions

View file

@ -1,22 +1,22 @@
package mage.cards.a;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
@ -37,7 +37,10 @@ public final class ArgentSphinx extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// <i>Metalcraft</i> &mdash; {U}: Exile Argent Sphinx. Return it to the battlefield under your control at the beginning of the next end step. Activate this ability only if you control three or more artifacts.
Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ArgentSphinxEffect(), new ManaCostsImpl("{U}"), MetalcraftCondition.instance);
Ability ability = new ActivateIfConditionActivatedAbility(
Zone.BATTLEFIELD, new ArgentSphinxEffect(),
new ManaCostsImpl("{U}"), MetalcraftCondition.instance
);
ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addHint(MetalcraftHint.instance);
this.addAbility(ability);
@ -56,37 +59,38 @@ public final class ArgentSphinx extends CardImpl {
class ArgentSphinxEffect extends OneShotEffect {
private static final String effectText = "Exile {this}. Return it to the battlefield under your control at the beginning of the next end step";
private static final String effectText = "Exile {this}. Return it to the battlefield " +
"under your control at the beginning of the next end step";
ArgentSphinxEffect() {
super(Outcome.Benefit);
staticText = effectText;
}
ArgentSphinxEffect(ArgentSphinxEffect effect) {
private ArgentSphinxEffect(ArgentSphinxEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (permanent != null && sourceObject != null) {
if (permanent.moveToExile(source.getSourceId(), sourceObject.getIdName(), source, game)) {
//create delayed triggered ability
Effect effect = new ReturnToBattlefieldUnderYourControlTargetEffect();
effect.setText("Return it to the battlefield under your control at the beginning of the next end step");
effect.setTargetPointer(new FixedTarget(source.getSourceId(), game));
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source);
return true;
}
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (player == null || permanent == null) {
return false;
}
return false;
Card card = permanent.getMainCard();
player.moveCards(permanent, Zone.EXILED, source, game);
//create delayed triggered ability
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
new ReturnToBattlefieldUnderYourControlTargetEffect().setText(
"Return it to the battlefield under your control at the beginning of the next end step"
).setTargetPointer(new FixedTarget(card, game))
), source);
return true;
}
@Override
public ArgentSphinxEffect copy() {
return new ArgentSphinxEffect(this);
}
}

View file

@ -1,38 +1,33 @@
package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageControllerEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class AshesToAshes extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact creature");
private static final FilterPermanent filter = new FilterCreaturePermanent("nonartifact creatures");
static {
filter.add(Predicates.not(CardType.ARTIFACT.getPredicate()));
}
public AshesToAshes(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}{B}");
// Exile two target nonartifact creatures. Ashes to Ashes deals 5 damage to you.
this.getSpellAbility().addEffect(new AshesToAshesEffect());
this.getSpellAbility().addEffect(new ExileTargetEffect());
this.getSpellAbility().addTarget(new TargetPermanent(2, filter));
this.getSpellAbility().addEffect(new DamageControllerEffect(5));
}
@ -46,32 +41,3 @@ public final class AshesToAshes extends CardImpl {
return new AshesToAshes(this);
}
}
class AshesToAshesEffect extends OneShotEffect {
public AshesToAshesEffect() {
super(Outcome.Benefit);
staticText = "Exile two target nonartifact creatures";
}
public AshesToAshesEffect(final AshesToAshesEffect effect) {
super(effect);
}
@Override
public AshesToAshesEffect copy() {
return new AshesToAshesEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
UUID exileId = source.getSourceId();
for (UUID permanentId : targetPointer.getTargets(game, source)) {
Permanent target = game.getPermanent(permanentId);
if (target != null) {
target.moveToExile(exileId, "Ashes to Ashes", source, game);
}
}
return true;
}
}

View file

@ -115,7 +115,9 @@ class BaneAlleyBrokerDrawExileEffect extends OneShotEffect {
if (card == null || sourceObject == null) {
return false;
}
if (!card.moveToExile(CardUtil.getExileZoneId(game, source), sourceObject.getName(), source, game)) {
if (!controller.moveCardsToExile(
card, source, game, false, CardUtil.getExileZoneId(game, source), sourceObject.getIdName()
)) {
return false;
}
card.setFaceDown(true, game);
@ -157,7 +159,7 @@ class BaneAlleyBrokerReturnToHandEffect extends OneShotEffect {
}
TargetCardInExile target = new TargetCardInExile(StaticFilters.FILTER_CARD, exile.getId());
target.setNotTarget(true);
player.chooseTarget(outcome, exile,target, source, game);
player.chooseTarget(outcome, exile, target, source, game);
Card card = game.getCard(target.getFirstTarget());
if (card == null) {
return false;

View file

@ -1,20 +1,22 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
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.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class CryptIncursion extends CardImpl {
@ -23,9 +25,8 @@ public final class CryptIncursion extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}");
// Exile all creature cards from target player's graveyard. You gain 3 life for each card exiled this way.
this.getSpellAbility().addTarget(new TargetPlayer());
this.getSpellAbility().addEffect(new CryptIncursionEffect());
this.getSpellAbility().addTarget(new TargetPlayer());
}
private CryptIncursion(final CryptIncursion card) {
@ -36,17 +37,17 @@ public final class CryptIncursion extends CardImpl {
public CryptIncursion copy() {
return new CryptIncursion(this);
}
}
class CryptIncursionEffect extends OneShotEffect {
public CryptIncursionEffect() {
CryptIncursionEffect() {
super(Outcome.Detriment);
staticText = "Exile all creature cards from target player's graveyard. You gain 3 life for each card exiled this way";
staticText = "Exile all creature cards from target player's graveyard. " +
"You gain 3 life for each card exiled this way";
}
public CryptIncursionEffect(final CryptIncursionEffect effect) {
private CryptIncursionEffect(final CryptIncursionEffect effect) {
super(effect);
}
@ -54,24 +55,20 @@ class CryptIncursionEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(source.getFirstTarget());
if (player != null && targetPlayer != null) {
int exiledCards = 0;
for (Card card : targetPlayer.getGraveyard().getCards(game)) {
if (StaticFilters.FILTER_CARD_CREATURE.match(card, game)) {
if (card.moveToExile(null, "", source, game)) {
exiledCards++;
}
}
}
player.gainLife(exiledCards * 3, game, source);
return true;
}
return false;
Cards cards = new CardsImpl(targetPlayer.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game));
player.moveCards(cards, Zone.EXILED, source, game);
int count = cards
.stream()
.map(game.getState()::getZone)
.map(Zone.EXILED::equals)
.mapToInt(x -> x ? 1 : 0)
.sum();
player.gainLife(3 * count, game, source);
return true;
}
@Override
public CryptIncursionEffect copy() {
return new CryptIncursionEffect(this);
}
}

View file

@ -1,11 +1,8 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.Mode;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@ -17,14 +14,18 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author noxx
*
*/
public final class DarkImpostor extends CardImpl {
@ -37,12 +38,16 @@ public final class DarkImpostor extends CardImpl {
this.toughness = new MageInt(2);
// {4}{B}{B}: Exile target creature and put a +1/+1 counter on Dark Impostor.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DarkImpostorExileTargetEffect(), new ManaCostsImpl("{4}{B}{B}"));
Ability ability = new SimpleActivatedAbility(
new DarkImpostorExileTargetEffect(), new ManaCostsImpl("{4}{B}{B}")
);
ability.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance())
.setText("and put a +1/+1 counter on {this}"));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
// Dark Impostor has all activated abilities of all creature cards exiled with it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DarkImpostorContinuousEffect()));
this.addAbility(new SimpleStaticAbility(new DarkImpostorContinuousEffect()));
}
private DarkImpostor(final DarkImpostor card) {
@ -57,11 +62,12 @@ public final class DarkImpostor extends CardImpl {
class DarkImpostorExileTargetEffect extends OneShotEffect {
public DarkImpostorExileTargetEffect() {
DarkImpostorExileTargetEffect() {
super(Outcome.Exile);
staticText = "exile target creature";
}
public DarkImpostorExileTargetEffect(final DarkImpostorExileTargetEffect effect) {
private DarkImpostorExileTargetEffect(final DarkImpostorExileTargetEffect effect) {
super(effect);
}
@ -72,46 +78,43 @@ class DarkImpostorExileTargetEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
MageObject sourceObject = source.getSourceObject(game);
if (permanent != null) {
permanent.moveToExile(null, null, source, game);
if (sourceObject instanceof Permanent) {
((Permanent) sourceObject).imprint(permanent.getId(), game);
}
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (player == null || permanent == null) {
return false;
}
return new AddCountersSourceEffect(CounterType.P1P1.createInstance()).apply(game, source);
}
@Override
public String getText(Mode mode) {
return "exile target creature and put a +1/+1 counter on {this}";
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
if (sourcePermanent == null) {
return player.moveCards(permanent, Zone.EXILED, source, game);
}
return player.moveCardsToExile(
permanent, source, game, true, CardUtil.getExileZoneId(game, source), sourcePermanent.getIdName()
);
}
}
class DarkImpostorContinuousEffect extends ContinuousEffectImpl {
public DarkImpostorContinuousEffect() {
DarkImpostorContinuousEffect() {
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
staticText = "{this} has all activated abilities of all creature cards exiled with it";
}
public DarkImpostorContinuousEffect(final DarkImpostorContinuousEffect effect) {
private DarkImpostorContinuousEffect(final DarkImpostorContinuousEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent perm = game.getPermanent(source.getSourceId());
if (perm != null) {
for (UUID imprintedId : perm.getImprinted()) {
Card card = game.getCard(imprintedId);
if (card != null) {
for (Ability ability : card.getAbilities(game)) {
if (ability instanceof ActivatedAbility) {
perm.addAbility(ability.copy(), source.getSourceId(), game);
}
}
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source));
if (permanent == null || exileZone == null || exileZone.isEmpty()) {
return false;
}
for (Card card : exileZone.getCards(StaticFilters.FILTER_CARD_CREATURE, game)) {
for (Ability ability : card.getAbilities(game)) {
if (ability instanceof ActivatedAbility) {
permanent.addAbility(ability, source.getSourceId(), game);
}
}
}
@ -122,5 +125,4 @@ class DarkImpostorContinuousEffect extends ContinuousEffectImpl {
public DarkImpostorContinuousEffect copy() {
return new DarkImpostorContinuousEffect(this);
}
}

View file

@ -1,18 +1,18 @@
package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CycleTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.keyword.CyclingAbility;
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.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.predicate.Predicates;
@ -20,8 +20,9 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class DecreeOfAnnihilation extends CardImpl {
@ -36,8 +37,7 @@ public final class DecreeOfAnnihilation extends CardImpl {
this.addAbility(new CyclingAbility(new ManaCostsImpl("{5}{R}{R}")));
// When you cycle Decree of Annihilation, destroy all lands.
Ability ability = new CycleTriggeredAbility(new DestroyAllEffect(StaticFilters.FILTER_LANDS), false);
this.addAbility(ability);
this.addAbility(new CycleTriggeredAbility(new DestroyAllEffect(StaticFilters.FILTER_LANDS), false));
}
private DecreeOfAnnihilation(final DecreeOfAnnihilation card) {
@ -52,21 +52,23 @@ public final class DecreeOfAnnihilation extends CardImpl {
class DecreeOfAnnihilationEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterPermanent("");
private static final FilterPermanent filter = new FilterPermanent();
static {
filter.add(Predicates.or(
CardType.ARTIFACT.getPredicate(),
CardType.CREATURE.getPredicate(),
CardType.LAND.getPredicate()));
CardType.LAND.getPredicate()
));
}
public DecreeOfAnnihilationEffect() {
DecreeOfAnnihilationEffect() {
super(Outcome.Detriment);
staticText = "Exile all artifacts, creatures, and lands from the battlefield, all cards from all graveyards, and all cards from all hands";
staticText = "Exile all artifacts, creatures, and lands from the battlefield, " +
"all cards from all graveyards, and all cards from all hands";
}
public DecreeOfAnnihilationEffect(final DecreeOfAnnihilationEffect effect) {
private DecreeOfAnnihilationEffect(final DecreeOfAnnihilationEffect effect) {
super(effect);
}
@ -77,26 +79,24 @@ class DecreeOfAnnihilationEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
permanent.moveToExile(null, "", source, game);
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Cards cards = new CardsImpl();
for (Permanent permanent : game.getBattlefield().getActivePermanents(
filter, source.getControllerId(), source.getSourceId(), game
)) {
cards.add(permanent);
}
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (UUID cid : player.getHand().copy()) {
Card c = game.getCard(cid);
if (c != null) {
c.moveToExile(null, null, source, game);
}
}
for (UUID cid : player.getGraveyard().copy()) {
Card c = game.getCard(cid);
if (c != null) {
c.moveToExile(null, null, source, game);
}
}
if (player == null) {
continue;
}
cards.addAll(player.getHand());
cards.addAll(player.getGraveyard());
}
return true;
return controller.moveCards(cards, Zone.EXILED, source, game);
}
}

View file

@ -1,31 +1,32 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
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.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.card.OwnerIdPredicate;
import mage.game.ExileZone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInExile;
import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author jeffwadsworth
* @author TheElk801
*/
public final class DimensionalBreach extends CardImpl {
@ -34,8 +35,6 @@ public final class DimensionalBreach extends CardImpl {
// Exile all permanents. For as long as any of those cards remain exiled, at the beginning of each player's upkeep, that player returns one of the exiled cards they own to the battlefield.
this.getSpellAbility().addEffect(new DimensionalBreachExileEffect());
this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility(Zone.ALL, new DimensionalBreachReturnFromExileEffect(), TargetController.ANY, false, true, null), new CardsStillInExileCondition(), null));
}
private DimensionalBreach(final DimensionalBreach card) {
@ -50,12 +49,14 @@ public final class DimensionalBreach extends CardImpl {
class DimensionalBreachExileEffect extends OneShotEffect {
public DimensionalBreachExileEffect() {
DimensionalBreachExileEffect() {
super(Outcome.Exile);
staticText = "Exile all permanents.";
staticText = "Exile all permanents. For as long as any of those cards remain exiled, " +
"at the beginning of each player's upkeep, that player returns " +
"one of the exiled cards they own to the battlefield.";
}
public DimensionalBreachExileEffect(final DimensionalBreachExileEffect effect) {
private DimensionalBreachExileEffect(final DimensionalBreachExileEffect effect) {
super(effect);
}
@ -66,75 +67,107 @@ class DimensionalBreachExileEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
MageObject sourceObject = source.getSourceObject(game);
Player controller = game.getPlayer(source.getControllerId());
if (sourceObject != null
&& controller != null) {
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), 0);
if (exileId != null) {
game.getBattlefield().getAllActivePermanents().forEach((permanent) -> {
permanent.moveToExile(exileId, sourceObject.getName(), source, game);
});
return true;
}
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
return false;
Cards cards = new CardsImpl();
game.getBattlefield().getActivePermanents(source.getControllerId(), game).stream().forEach(cards::add);
player.moveCards(cards, Zone.EXILED, source, game);
Set<MageObjectReference> morSet = cards
.getCards(game)
.stream()
.filter(c -> game.getState().getZone(c.getId()) == Zone.EXILED)
.map(c -> new MageObjectReference(c, game))
.collect(Collectors.toSet());
game.addDelayedTriggeredAbility(new DimensionalBreachDelayedTriggeredAbility(morSet), source);
return true;
}
}
class DimensionalBreachReturnFromExileEffect extends OneShotEffect {
class DimensionalBreachDelayedTriggeredAbility extends DelayedTriggeredAbility {
public DimensionalBreachReturnFromExileEffect() {
super(Outcome.PutCardInPlay);
staticText = "For as long as any of those cards remain exiled, at the beginning of each player's upkeep, that player returns one of the exiled cards they own to the battlefield.";
private final Set<MageObjectReference> morSet = new HashSet<>();
DimensionalBreachDelayedTriggeredAbility(Set<MageObjectReference> morSet) {
super(new DimensionalBreachReturnEffect(morSet), Duration.Custom, false, false);
this.morSet.addAll(morSet);
}
public DimensionalBreachReturnFromExileEffect(final DimensionalBreachReturnFromExileEffect effect) {
super(effect);
private DimensionalBreachDelayedTriggeredAbility(final DimensionalBreachDelayedTriggeredAbility ability) {
super(ability);
this.morSet.addAll(ability.morSet);
}
@Override
public DimensionalBreachReturnFromExileEffect copy() {
return new DimensionalBreachReturnFromExileEffect(this);
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return morSet.stream().map(mor -> mor.getCard(game)).anyMatch(Objects::nonNull);
}
@Override
public DimensionalBreachDelayedTriggeredAbility copy() {
return new DimensionalBreachDelayedTriggeredAbility(this);
}
@Override
public boolean isInactive(Game game) {
return morSet.stream().map(mor -> mor.getCard(game)).noneMatch(Objects::nonNull);
}
@Override
public String getRule() {
return "For as long as any of those cards remain exiled, at the beginning of each player's upkeep, " +
"that player returns one of the exiled cards they own to the battlefield.";
}
}
class DimensionalBreachReturnEffect extends OneShotEffect {
private final Set<MageObjectReference> morSet = new HashSet<>();
DimensionalBreachReturnEffect(Set<MageObjectReference> morSet) {
super(Outcome.PutCardInPlay);
this.morSet.addAll(morSet);
}
private DimensionalBreachReturnEffect(final DimensionalBreachReturnEffect effect) {
super(effect);
this.morSet.addAll(effect.morSet);
}
@Override
public DimensionalBreachReturnEffect copy() {
return new DimensionalBreachReturnEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player != null) {
FilterCard filter = new FilterCard("card you own from the Dimensional Breach exile");
filter.add(new OwnerIdPredicate(player.getId()));
TargetCardInExile target = new TargetCardInExile(filter, CardUtil.getExileZoneId(game, source.getSourceId(), 0));
target.setNotTarget(true);
if (target.canChoose(source.getSourceId(), player.getId(), game)) {
if (player.chooseTarget(Outcome.PutCardInPlay, target, source, game)) {
Card card = game.getCard(target.getFirstTarget());
if (card != null
&& player.moveCards(card, Zone.BATTLEFIELD, source, game)) {
return true;
}
}
}
}
return false;
}
}
class CardsStillInExileCondition implements Condition {
@Override
public final boolean apply(Game game, Ability source) {
Player player = game.getPlayer(game.getActivePlayerId());
if (player != null) {
FilterCard filter = new FilterCard();
filter.add(new OwnerIdPredicate(player.getId()));
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), 0);
ExileZone exileZone = game.getExile().getExileZone(exileId);
return (exileZone != null
&& !exileZone.getCards(filter, game).isEmpty());
if (player == null) {
return false;
}
return false;
Cards cards = new CardsImpl(
morSet.stream()
.map(mor -> mor.getCard(game))
.filter(Objects::nonNull)
.filter(c -> c.isOwnedBy(game.getActivePlayerId()))
.collect(Collectors.toSet())
);
if (cards.isEmpty()) {
return false;
}
if (cards.size() > 1) {
TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD);
target.setNotTarget(true);
player.choose(outcome, cards, target, game);
cards.clear();
cards.add(target.getFirstTarget());
}
return player.moveCards(cards, Zone.BATTLEFIELD, source, game);
}
}

View file

@ -1,14 +1,10 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.keyword.DevoidAbility;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.FlyingAbility;
@ -16,21 +12,23 @@ import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetOpponent;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class DimensionalInfiltrator extends CardImpl {
public DimensionalInfiltrator(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.ELDRAZI);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
@ -45,7 +43,7 @@ public final class DimensionalInfiltrator extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// {1}{C}: Exile the top card of target opponent's library. If it's a land card, you may return Dimensional Infiltrator to its owner's hand.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DimensionalInfiltratorEffect(), new ManaCostsImpl("{1}{C}"));
Ability ability = new SimpleActivatedAbility(new DimensionalInfiltratorEffect(), new ManaCostsImpl("{1}{C}"));
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
@ -62,12 +60,13 @@ public final class DimensionalInfiltrator extends CardImpl {
class DimensionalInfiltratorEffect extends OneShotEffect {
public DimensionalInfiltratorEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "Exile the top card of target opponent's library. If it's a land card, you may return Dimensional Infiltrator to its owner's hand";
DimensionalInfiltratorEffect() {
super(Outcome.ReturnToHand);
this.staticText = "exile the top card of target opponent's library. " +
"If it's a land card, you may return {this} to its owner's hand";
}
public DimensionalInfiltratorEffect(final DimensionalInfiltratorEffect effect) {
private DimensionalInfiltratorEffect(final DimensionalInfiltratorEffect effect) {
super(effect);
}
@ -78,24 +77,22 @@ class DimensionalInfiltratorEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player player = game.getPlayer(source.getControllerId());
Player opponent = game.getPlayer(source.getFirstTarget());
MageObject sourceObject = game.getObject(source.getSourceId());
if (opponent == null || controller == null || sourceObject == null) {
if (player == null || opponent == null) {
return false;
}
if (opponent.getLibrary().hasCards()) {
Card card = opponent.getLibrary().getFromTop(game);
if (card != null) {
card.moveToExile(null, "Dimensional Infiltrator", source, game);
if (card.isLand()) {
if (controller.chooseUse(Outcome.Neutral, "Return " + sourceObject.getIdName() + " to its owner's hand?", source, game)) {
new ReturnToHandSourceEffect(true).apply(game, source);
}
}
}
Card card = opponent.getLibrary().getFromTop(game);
if (card == null) {
return false;
}
return true;
player.moveCards(card, Zone.EXILED, source, game);
if (!card.isLand()) {
return true;
}
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
return permanent != null
&& player.chooseUse(outcome, "Return " + permanent.getName() + " to its owner's hand?", source, game)
&& player.moveCards(permanent, Zone.HAND, source, game);
}
}