diff --git a/Mage.Sets/src/mage/cards/a/ArgentSphinx.java b/Mage.Sets/src/mage/cards/a/ArgentSphinx.java index 1c978337bee..bbe5400dfe8 100644 --- a/Mage.Sets/src/mage/cards/a/ArgentSphinx.java +++ b/Mage.Sets/src/mage/cards/a/ArgentSphinx.java @@ -35,8 +35,9 @@ 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.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -46,6 +47,7 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -54,7 +56,7 @@ import mage.game.permanent.Permanent; public class ArgentSphinx extends CardImpl { public ArgentSphinx(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); this.subtype.add("Sphinx"); this.power = new MageInt(4); @@ -100,10 +102,10 @@ class ArgentSphinxEffect extends OneShotEffect { if (permanent != null && sourceObject != null) { if (permanent.moveToExile(source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game)) { //create delayed triggered ability - AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility - = new AtTheBeginOfNextEndStepDelayedTriggeredAbility( - new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD)); - game.addDelayedTriggeredAbility(delayedAbility, source); + 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; } } diff --git a/Mage.Sets/src/mage/cards/a/AstralSlide.java b/Mage.Sets/src/mage/cards/a/AstralSlide.java index f5a90e02ffe..db23956a8f6 100644 --- a/Mage.Sets/src/mage/cards/a/AstralSlide.java +++ b/Mage.Sets/src/mage/cards/a/AstralSlide.java @@ -32,17 +32,18 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.CycleAllTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -51,7 +52,7 @@ import mage.target.common.TargetCreaturePermanent; public class AstralSlide extends CardImpl { public AstralSlide(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); // Whenever a player cycles a card, you may exile target creature. If you do, return that card to the battlefield under its owner's control at the beginning of the next end step. Ability ability = new CycleAllTriggeredAbility(new AstralSlideEffect(), true); @@ -90,8 +91,10 @@ class AstralSlideEffect extends OneShotEffect { UUID exileId = UUID.randomUUID(); if (controller.moveCardsToExile(permanent, source, game, true, exileId, sourceObject.getIdName())) { //create delayed triggered ability - AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(exileId, Zone.BATTLEFIELD, false)); - game.addDelayedTriggeredAbility(delayedAbility, source); + Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); + effect.setText("Return that card to the battlefield under its owner's control at the beginning of the next end step"); + effect.setTargetPointer(new FixedTarget(permanent.getId(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); } } return true; diff --git a/Mage.Sets/src/mage/cards/e/EscapePod.java b/Mage.Sets/src/mage/cards/e/EscapePod.java index d552c08980f..3496f99f567 100644 --- a/Mage.Sets/src/mage/cards/e/EscapePod.java +++ b/Mage.Sets/src/mage/cards/e/EscapePod.java @@ -31,16 +31,17 @@ import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -49,7 +50,7 @@ import mage.target.common.TargetControlledCreaturePermanent; public class EscapePod extends CardImpl { public EscapePod(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); // Exile target creature you control. Return that card to the battlefield under its owner's control at the beginning of the next end step. this.getSpellAbility().addEffect(new EscapePodEffect()); @@ -84,8 +85,10 @@ class EscapePodEffect extends OneShotEffect { MageObject sourceObject = game.getObject(source.getSourceId()); if (permanent != null && sourceObject != null) { if (permanent.moveToExile(source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game)) { - AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD, false)); - game.addDelayedTriggeredAbility(delayedAbility, source); + Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); + effect.setText("Return that card to the battlefield under its owner's control at the beginning of the next end step"); + effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); return true; } } diff --git a/Mage.Sets/src/mage/cards/f/Flickerwisp.java b/Mage.Sets/src/mage/cards/f/Flickerwisp.java index db29131435c..c406608cefe 100644 --- a/Mage.Sets/src/mage/cards/f/Flickerwisp.java +++ b/Mage.Sets/src/mage/cards/f/Flickerwisp.java @@ -32,8 +32,9 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -46,6 +47,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -60,7 +62,7 @@ public class Flickerwisp extends CardImpl { } public Flickerwisp(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); this.subtype.add("Elemental"); this.power = new MageInt(3); @@ -104,8 +106,10 @@ class FlickerwispEffect extends OneShotEffect { if (controller != null && permanent != null && sourcePermanent != null) { if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { //create delayed triggered ability - game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( - new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD, false)), source); + Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); + effect.setText("Return that card to the battlefield under its owner's control at the beginning of the next end step"); + effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); return true; } } diff --git a/Mage.Sets/src/mage/cards/i/IdentityThief.java b/Mage.Sets/src/mage/cards/i/IdentityThief.java index bf7ac1ed88b..015f185e49f 100644 --- a/Mage.Sets/src/mage/cards/i/IdentityThief.java +++ b/Mage.Sets/src/mage/cards/i/IdentityThief.java @@ -32,9 +32,10 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CopyEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -50,6 +51,7 @@ import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -64,7 +66,7 @@ public class IdentityThief extends CardImpl { } public IdentityThief(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); this.subtype.add("Shapeshifter"); this.power = new MageInt(0); this.toughness = new MageInt(3); @@ -146,8 +148,10 @@ class IdentityThiefEffect extends OneShotEffect { // Copy exiled permanent game.addEffect(copyEffect, source); // Create delayed triggered ability - game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( - new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD, false)), source); + Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); + effect.setText("Return the exiled card to the battlefield under its owner's control at the beginning of the next end step"); + effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); return true; } } diff --git a/Mage.Sets/src/mage/cards/l/Liberate.java b/Mage.Sets/src/mage/cards/l/Liberate.java index b092ff9a8a9..5ed9c9e7088 100644 --- a/Mage.Sets/src/mage/cards/l/Liberate.java +++ b/Mage.Sets/src/mage/cards/l/Liberate.java @@ -31,16 +31,17 @@ import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -50,7 +51,7 @@ import mage.target.common.TargetControlledCreaturePermanent; public class Liberate extends CardImpl { public Liberate(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); // Exile target creature you control. Return that card to the battlefield under its owner's control at the beginning of the next end step. this.getSpellAbility().addEffect(new LiberateEffect()); @@ -84,8 +85,10 @@ class LiberateEffect extends OneShotEffect { MageObject sourceObject = game.getObject(source.getSourceId()); if (permanent != null && sourceObject != null) { if (permanent.moveToExile(source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game)) { - AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD, false)); - game.addDelayedTriggeredAbility(delayedAbility, source); + Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); + effect.setText("Return that card to the battlefield under its owner's control at the beginning of the next end step"); + effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); return true; } } diff --git a/Mage.Sets/src/mage/cards/m/MystifyingMaze.java b/Mage.Sets/src/mage/cards/m/MystifyingMaze.java index 5cf08a28198..b6bd0b3ac4c 100644 --- a/Mage.Sets/src/mage/cards/m/MystifyingMaze.java +++ b/Mage.Sets/src/mage/cards/m/MystifyingMaze.java @@ -28,13 +28,15 @@ package mage.cards.m; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -47,6 +49,7 @@ import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -61,8 +64,12 @@ public class MystifyingMaze extends CardImpl { } public MystifyingMaze(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},null); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, null); + + // {T}: Add Colorless to your mana pool. this.addAbility(new ColorlessManaAbility()); + + // {4}, {T}: Exile target attacking creature an opponent controls. At the beginning of the next end step, return it to the battlefield tapped under its owner's control. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MystifyingMazeEffect(), new ManaCostsImpl("{4}")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent(filter)); @@ -93,11 +100,14 @@ class MystifyingMazeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null) { - if (permanent.moveToExile(source.getSourceId(), "Mystifying Maze Exile", source.getSourceId(), game)) { + MageObject sourceObject = source.getSourceObject(game); + if (permanent != null && sourceObject != null) { + if (permanent.moveToExile(source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game)) { //create delayed triggered ability - game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( - new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD, true)), source); + Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); + effect.setText("At the beginning of the next end step, return it to the battlefield tapped under its owner's control"); + effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); return true; } } diff --git a/Mage.Sets/src/mage/cards/s/Skybind.java b/Mage.Sets/src/mage/cards/s/Skybind.java index 713b9b3c91a..a464bdd26f9 100644 --- a/Mage.Sets/src/mage/cards/s/Skybind.java +++ b/Mage.Sets/src/mage/cards/s/Skybind.java @@ -31,19 +31,20 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.abilityword.ConstellationAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -58,7 +59,7 @@ public class Skybind extends CardImpl { } public Skybind(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}"); // Constellation — When Skybind or another enchantment enters the battlefield under your control, exile target nonenchantment permanent. Return that card to the battlefield under its owner's control at the beginning of the next end step. Ability ability = new ConstellationAbility(new SkybindEffect(), false); @@ -94,8 +95,10 @@ class SkybindEffect extends OneShotEffect { if (permanent != null && sourcePermanent != null) { if (permanent.moveToExile(source.getSourceId(), sourcePermanent.getName(), source.getSourceId(), game)) { //create delayed triggered ability - AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD)); - game.addDelayedTriggeredAbility(delayedAbility, source); + Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); + effect.setText("Return that card to the battlefield under its owner's control at the beginning of the next end step"); + effect.setTargetPointer(new FixedTarget(getTargetPointer().getFirst(game, source), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SuddenDisappearance.java b/Mage.Sets/src/mage/cards/s/SuddenDisappearance.java index d7735122bbc..4a4581d7c2d 100644 --- a/Mage.Sets/src/mage/cards/s/SuddenDisappearance.java +++ b/Mage.Sets/src/mage/cards/s/SuddenDisappearance.java @@ -27,23 +27,27 @@ */ package mage.cards.s; -import java.util.List; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; +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.common.FilterNonlandPermanent; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPlayer; +import mage.target.targetpointer.FixedTargets; /** * @@ -52,7 +56,7 @@ import mage.target.TargetPlayer; public class SuddenDisappearance extends CardImpl { public SuddenDisappearance(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{5}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{W}"); // Exile all nonland permanents target player controls. Return the exiled cards to the battlefield under their owner's control at the beginning of the next end step. this.getSpellAbility().addEffect(new SuddenDisappearanceEffect()); @@ -88,14 +92,17 @@ class SuddenDisappearanceEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); if (controller != null && sourceObject != null) { - List perms = game.getBattlefield().getAllActivePermanents(filter, source.getFirstTarget(), game); - if (perms.size() > 0) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getFirstTarget(), game)) { - controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); + Set permsSet = new HashSet<>(game.getBattlefield().getAllActivePermanents(filter, source.getFirstTarget(), game)); + if (permsSet.size() > 0) { + controller.moveCardsToExile(permsSet, source, game, true, source.getSourceId(), sourceObject.getIdName()); + Cards targets = new CardsImpl(); + for (Card card : permsSet) { + targets.add(card.getId()); } - AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD)); - game.addDelayedTriggeredAbility(delayedAbility, source); - + Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); + effect.setText("Return the exiled cards to the battlefield under their owner's control at the beginning of the next end step"); + effect.setTargetPointer(new FixedTargets(targets, game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); } return true; } diff --git a/Mage.Sets/src/mage/cards/v/VenserTheSojourner.java b/Mage.Sets/src/mage/cards/v/VenserTheSojourner.java index aa983cc3555..2f134772ffa 100644 --- a/Mage.Sets/src/mage/cards/v/VenserTheSojourner.java +++ b/Mage.Sets/src/mage/cards/v/VenserTheSojourner.java @@ -38,7 +38,7 @@ import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.GetEmblemEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect; import mage.abilities.effects.common.combat.CantBeBlockedAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -74,7 +74,7 @@ public class VenserTheSojourner extends CardImpl { } public VenserTheSojourner(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{3}{W}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{W}{U}"); this.subtype.add("Venser"); this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3)); @@ -127,8 +127,10 @@ class VenserTheSojournerEffect extends OneShotEffect { if (permanent != null) { if (controller.moveCardToExileWithInfo(permanent, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { //create delayed triggered ability - game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( - new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD)), source); + 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(permanent.getId(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); return true; } } diff --git a/Mage.Sets/src/mage/cards/v/VoyagerStaff.java b/Mage.Sets/src/mage/cards/v/VoyagerStaff.java index 287260a2be5..5308eb294e1 100644 --- a/Mage.Sets/src/mage/cards/v/VoyagerStaff.java +++ b/Mage.Sets/src/mage/cards/v/VoyagerStaff.java @@ -33,8 +33,9 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -44,6 +45,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -52,7 +54,7 @@ import mage.target.common.TargetCreaturePermanent; public class VoyagerStaff extends CardImpl { public VoyagerStaff(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); // {2}, Sacrifice Voyager Staff: Exile target creature. Return the exiled card to the battlefield under its owner's control at the beginning of the next end step. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new VoyagerStaffEffect(), new GenericManaCost(2)); @@ -90,8 +92,10 @@ class VoyagerStaffEffect extends OneShotEffect { if (controller != null && creature != null && sourcePermanent != null) { if (controller.moveCardToExileWithInfo(creature, source.getSourceId(), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true)) { //create delayed triggered ability - game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( - new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD, false)), source); + Effect effect = new ReturnToBattlefieldUnderYourControlTargetEffect(); + effect.setText("Return the exiled card to the battlefield under its owner's control at the beginning of the next end step"); + effect.setTargetPointer(new FixedTarget(creature.getId(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); return true; } } diff --git a/Mage.Sets/src/mage/cards/y/YodaJediMaster.java b/Mage.Sets/src/mage/cards/y/YodaJediMaster.java index 90243070b8a..0f6d7935b53 100644 --- a/Mage.Sets/src/mage/cards/y/YodaJediMaster.java +++ b/Mage.Sets/src/mage/cards/y/YodaJediMaster.java @@ -38,7 +38,7 @@ import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GetEmblemEffect; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; -import mage.abilities.effects.common.ReturnFromExileEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; import mage.abilities.keyword.HexproofAbility; @@ -58,6 +58,7 @@ import mage.game.Game; import mage.game.command.Emblem; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -73,7 +74,7 @@ public class YodaJediMaster extends CardImpl { } public YodaJediMaster(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{1}{G}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{G}{U}"); this.subtype.add("Yoda"); this.addAbility(new PlanswalkerEntersWithLoyalityCountersAbility(3)); @@ -108,7 +109,7 @@ class YodaJediMasterEffect extends OneShotEffect { public YodaJediMasterEffect() { super(Outcome.Detriment); - staticText = "Exile another target permanent you own. Return that card to the battlefield under your control at the beggining of your next end step"; + staticText = "Exile another target permanent you own. Return that card to the battlefield under your control at the beginning of your next end step"; } public YodaJediMasterEffect(final YodaJediMasterEffect effect) { @@ -122,8 +123,10 @@ class YodaJediMasterEffect extends OneShotEffect { if (permanent != null && sourcePermanent != null) { if (permanent.moveToExile(source.getSourceId(), sourcePermanent.getName(), source.getSourceId(), game)) { //create delayed triggered ability - AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD)); - game.addDelayedTriggeredAbility(delayedAbility, source); + Effect effect = new ReturnToBattlefieldUnderYourControlTargetEffect(); + effect.setText("Return that card to the battlefield under your control at the beginning of your next end step"); + effect.setTargetPointer(new FixedTarget(permanent.getId(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); return true; } } diff --git a/Mage/src/main/java/mage/abilities/DelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/DelayedTriggeredAbility.java index 15517e64715..a4bef097ef9 100644 --- a/Mage/src/main/java/mage/abilities/DelayedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/DelayedTriggeredAbility.java @@ -1,16 +1,16 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,12 +20,11 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities; import mage.abilities.effects.Effect; @@ -49,6 +48,7 @@ public abstract class DelayedTriggeredAbility extends TriggeredAbilityImpl { public DelayedTriggeredAbility(Effect effect, Duration duration) { this(effect, duration, true); } + public DelayedTriggeredAbility(Effect effect, Duration duration, Boolean triggerOnlyOnce) { this(effect, duration, triggerOnlyOnce, false); } @@ -75,13 +75,25 @@ public abstract class DelayedTriggeredAbility extends TriggeredAbilityImpl { public Boolean getTriggerOnlyOnce() { return triggerOnlyOnce; } - + + /** + * This method is called as the ability is added to the game (not as the + * ability triggers later) + * + * @param game + */ + public void initOnAdding(Game game) { + + } + public void init(Game game) { - for (Effect effect: this.getEffects()) { + for (Effect effect : this.getEffects()) { effect.getTargetPointer().init(game, this); } - }; - + } + + ; + public boolean isInactive(Game game) { return false; } diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 76aa1802bb7..9fd14a95530 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -159,7 +159,6 @@ public abstract class GameImpl implements Game, Serializable { FILTER_LEGENDARY.add(new SupertypePredicate("Legendary")); } - private transient Object customData; protected boolean simulation = false; @@ -1520,10 +1519,11 @@ public abstract class GameImpl implements Game, Serializable { // return addDelayedTriggeredAbility(delayedAbility); DelayedTriggeredAbility newAbility = delayedAbility.copy(); newAbility.newId(); + newAbility.initOnAdding(this); // ability.init is called as the ability triggeres not now. // If a FixedTarget pointer is already set from the effect setting up this delayed ability // it has to be already initialized so it won't be overwitten as the ability triggers - state.addDelayedTriggeredAbility(newAbility); + getState().addDelayedTriggeredAbility(newAbility); return newAbility.getId(); } @@ -1532,10 +1532,11 @@ public abstract class GameImpl implements Game, Serializable { public UUID addDelayedTriggeredAbility(DelayedTriggeredAbility delayedAbility) { DelayedTriggeredAbility newAbility = delayedAbility.copy(); newAbility.newId(); + newAbility.initOnAdding(this); // ability.init is called as the ability triggeres not now. // If a FixedTarget pointer is already set from the effect setting up this delayed ability // it has to be already initialized so it won't be overwitten as the ability triggers - state.addDelayedTriggeredAbility(newAbility); + getState().addDelayedTriggeredAbility(newAbility); return newAbility.getId(); } diff --git a/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java b/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java index 5c8166b9679..9c9a755bcf9 100644 --- a/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java +++ b/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java @@ -41,6 +41,18 @@ public class FixedTarget implements TargetPointer { this.zoneChangeCounter = zoneChangeCounter; } + /** + * Use this to set the target to exactly the zone the target is currently in + * + * @param targetId + * @param game + */ + public FixedTarget(UUID targetId, Game game) { + this.targetId = targetId; + this.initialized = true; + this.zoneChangeCounter = game.getState().getZoneChangeCounter(targetId); + } + public FixedTarget(final FixedTarget fixedTarget) { this.targetId = fixedTarget.targetId; this.zoneChangeCounter = fixedTarget.zoneChangeCounter;