Add new methods to Target and TargetPointer to help generate card rules text. Currently only used by ExileUntilSourceLeavesEffect

This commit is contained in:
Alex W. Jackson 2022-09-04 05:15:12 -04:00
parent c6e1ce6697
commit addfd5166e
38 changed files with 156 additions and 208 deletions

View file

@ -63,11 +63,7 @@ public final class AngelOfCondemnation extends CardImpl {
this.addAbility(ability);
// {2}{W}, {T}, Exert Angel of Condemnation: Exile another target creature until Angel of Condemnation leaves the battlefield.
ability = new SimpleActivatedAbility(
new ExileUntilSourceLeavesEffect("")
.setText("Exile another target creature until {this} leaves the battlefield"),
new ManaCostsImpl<>("{2}{W}")
);
ability = new SimpleActivatedAbility(new ExileUntilSourceLeavesEffect(), new ManaCostsImpl<>("{2}{W}"));
ability.addCost(new TapSourceCost());
ability.addCost(new ExertSourceCost());
ability.addTarget(new TargetCreaturePermanent(filter));

View file

@ -15,8 +15,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
/**
@ -25,12 +24,6 @@ import mage.target.TargetPermanent;
*/
public final class AngelOfSanctions extends CardImpl {
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent();
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public AngelOfSanctions(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
@ -42,8 +35,8 @@ public final class AngelOfSanctions extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Angel of Sanctions enters the battlefield, you may exile target nonland permanent an opponent controls until Angel of Sanctions leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
ability.addTarget(new TargetPermanent(filter));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(), true);
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -1,4 +1,3 @@
package mage.cards.b;
import java.util.UUID;
@ -10,8 +9,7 @@ import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
/**
@ -20,18 +18,12 @@ import mage.target.TargetPermanent;
*/
public final class BanishingLight extends CardImpl {
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent();
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public BanishingLight(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// When Banishing Light enters the battlefield, exile target nonland permanent an opponent controls until Banishing Light leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
ability.addTarget(new TargetPermanent(filter));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
}

View file

@ -8,8 +8,7 @@ import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import java.util.UUID;
@ -20,18 +19,12 @@ import java.util.UUID;
*/
public final class BorrowedTime extends CardImpl {
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent();
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public BorrowedTime(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// When Borrowed Time enters the battlefield, exile target nonland permanent an opponent controls until Borrowed Time leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
ability.addTarget(new TargetPermanent(filter));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
}

View file

@ -32,8 +32,8 @@ public final class BrutalCathar extends CardImpl {
// When this creature enters the battlefield or transforms into Brutal Cathar, exile target creature an opponent controls until this creature leaves the battlefield.
Ability ability = new TransformsOrEntersTriggeredAbility(
new ExileUntilSourceLeavesEffect("creature an opponent controls"), false
).setTriggerPhrase("Whenever this creature enters the battlefield or transforms into {this}, ");
new ExileUntilSourceLeavesEffect(), false
).setTriggerPhrase("When this creature enters the battlefield or transforms into {this}, ");
ability.addTarget(new TargetOpponentsCreaturePermanent());
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -1,4 +1,3 @@
package mage.cards.c;
import java.util.UUID;
@ -13,8 +12,7 @@ import mage.abilities.keyword.FlashAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
/**
@ -23,12 +21,6 @@ import mage.target.TargetPermanent;
*/
public final class CastOut extends CardImpl {
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent();
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public CastOut(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
@ -36,8 +28,8 @@ public final class CastOut extends CardImpl {
this.addAbility(FlashAbility.getInstance());
// When Cast Out enters the battlefield, exile target nonland permanent an opponent controls until Cast Out leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
ability.addTarget(new TargetPermanent(filter));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -42,11 +42,7 @@ public final class CircleOfConfinement extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// When Circle of Confinement enters the battlefield, exile target creature an opponent controls with mana value 3 or less until Circle of Confinement leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ExileUntilSourceLeavesEffect("")
.setText("exile target creature an opponent controls with mana value 3 " +
"or less until {this} leaves the battlefield")
);
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -11,6 +11,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
import mage.target.TargetPermanent;
@ -20,7 +21,7 @@ import mage.target.TargetPermanent;
*/
public final class CitizensArrest extends CardImpl {
private static final FilterCreatureOrPlaneswalkerPermanent filter = new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker an opponent controls");
private static final FilterPermanent filter = new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker an opponent controls");
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
@ -30,7 +31,7 @@ public final class CitizensArrest extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}");
// When Citizen's Arrest enters the battlefield, exile target creature or planeswalker an opponent controls until Citizen's Arrest leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect("creature or planeswalker"));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -10,8 +10,7 @@ import mage.abilities.keyword.ConvokeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
/**
@ -20,12 +19,6 @@ import mage.target.TargetPermanent;
*/
public final class ConclaveTribunal extends CardImpl {
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent();
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public ConclaveTribunal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
@ -33,13 +26,9 @@ public final class ConclaveTribunal extends CardImpl {
this.addAbility(new ConvokeAbility());
// When Conclave Tribunal enters the battlefield, exile target nonland permanent an opponent controls until Conclave Tribunal leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ExileUntilSourceLeavesEffect(filter.getMessage())
);
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(
new OnLeaveReturnExiledToBattlefieldAbility())
);
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
}

View file

@ -12,9 +12,10 @@ import mage.abilities.keyword.RenownAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.target.common.TargetNonlandPermanent;
import mage.target.TargetPermanent;
/**
*
@ -22,7 +23,7 @@ import mage.target.common.TargetNonlandPermanent;
*/
public final class ConstableOfTheRealm extends CardImpl {
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent("other nonland permanent");
private static final FilterPermanent filter = new FilterNonlandPermanent("other target nonland permanent");
static {
filter.add(AnotherPredicate.instance);
@ -40,10 +41,8 @@ public final class ConstableOfTheRealm extends CardImpl {
this.addAbility(new RenownAbility(2));
// Whenever one or more +1/+1 counters are put on Constable of the Realm, exile up to one other target nonland permanent until Constable of the Realm leaves the battlefield.
Ability ability = new OneOrMoreCountersAddedTriggeredAbility(new ExileUntilSourceLeavesEffect("").setText(
"exile up to one other target nonland permanent until {this} leaves the battlefield"
));
ability.addTarget(new TargetNonlandPermanent(0, 1, filter, false));
Ability ability = new OneOrMoreCountersAddedTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(0, 1, filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
}

View file

@ -33,7 +33,7 @@ import java.util.UUID;
*/
public final class GelatinousCube extends CardImpl {
private static final FilterPermanent filter = new FilterOpponentsCreaturePermanent("non-Ooze creature");
private static final FilterPermanent filter = new FilterOpponentsCreaturePermanent("non-Ooze creature an opponent controls");
static {
filter.add(Predicates.not(SubType.OOZE.getPredicate()));
@ -47,7 +47,7 @@ public final class GelatinousCube extends CardImpl {
this.toughness = new MageInt(3);
// Engulf When Gelatinous Cube enters the battlefield, exile target non-Ooze creature an opponent controls until Gelatinous Cube leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability.withFlavorWord("Engulf"));

View file

@ -32,11 +32,7 @@ public final class GlassCasket extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{W}");
// When Glass Casket enters the battlefield, exile target creature an opponent controls with converted mana cost 3 or less until Glass Casket leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ExileUntilSourceLeavesEffect("")
.setText("exile target creature an opponent controls with mana value 3 " +
"or less until {this} leaves the battlefield")
);
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -28,7 +28,7 @@ public final class GraspOfFate extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}");
// When Grasp of Fate enters the battlefield, for each opponent, exile up to one target nonland permanent that player controls until Grasp of Fate leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect("")
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect()
.setTargetPointer(new EachTargetPointer())
.setText("for each opponent, exile up to one target nonland permanent that player controls until {this} leaves the battlefield")
);

View file

@ -30,10 +30,7 @@ public final class GraspingGiant extends CardImpl {
this.addAbility(VigilanceAbility.getInstance());
// Whenever Grasping Giant becomes blocked by a creature, exile that creature until Grasping Giant leaves the battlefield.
Ability ability = new BecomesBlockedByCreatureTriggeredAbility(
new ExileUntilSourceLeavesEffect("")
.setText("exile that creature until {this} leaves the battlefield"), false
);
Ability ability = new BecomesBlockedByCreatureTriggeredAbility(new ExileUntilSourceLeavesEffect(), false);
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
}

View file

@ -9,8 +9,7 @@ import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
/**
@ -19,23 +18,13 @@ import mage.target.TargetPermanent;
*/
public final class HieromancersCage extends CardImpl {
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent();
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public HieromancersCage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
// When Hieromancer's Cage enters the battlefield, exile target nonland permanent an opponent controls until Hieromancer's Cage leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ExileUntilSourceLeavesEffect(filter.getMessage())
);
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(
new OnLeaveReturnExiledToBattlefieldAbility())
);
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
}

View file

@ -11,7 +11,7 @@ import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.StaticFilters;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -26,18 +26,12 @@ import java.util.UUID;
*/
public final class IxalansBinding extends CardImpl {
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent();
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public IxalansBinding(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
// When Ixalan's Binding enters the battlefield, exile target nonland permanent an opponent controls until Ixalan's Binding leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
ability.addTarget(new TargetPermanent(filter));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -12,9 +12,8 @@ import mage.abilities.hint.common.PartyCountHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import java.util.UUID;
@ -24,12 +23,6 @@ import java.util.UUID;
*/
public final class JourneyToOblivion extends CardImpl {
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent();
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public JourneyToOblivion(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}");
@ -39,8 +32,8 @@ public final class JourneyToOblivion extends CardImpl {
).addHint(PartyCountHint.instance));
// When Journey to Oblivion enters the battlefield, exile target nonland permanent an opponent controls until Journey to Oblivion leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
ability.addTarget(new TargetPermanent(filter));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
}

View file

@ -16,8 +16,7 @@ import mage.constants.AbilityWord;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import java.util.UUID;
@ -27,13 +26,6 @@ import java.util.UUID;
*/
public final class LeylineBinding extends CardImpl {
private static final FilterPermanent filter
= new FilterNonlandPermanent("nonland permanent an opponent controls");
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public LeylineBinding(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{5}{W}");
@ -46,8 +38,8 @@ public final class LeylineBinding extends CardImpl {
).setAbilityWord(AbilityWord.DOMAIN).addHint(DomainHint.instance));
// When Leyline Binding enters the battlefield, exile target nonland permanent an opponent controls until Leyline Binding leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
ability.addTarget(new TargetPermanent(filter));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
}

View file

@ -40,8 +40,7 @@ public final class LunarchInquisitors extends CardImpl {
this.nightCard = true;
// When this creature transforms into Lunarch Inquisitors, you may exile another target creature until Lunarch Inquisitors leaves the battlefield.
Ability ability = new TransformIntoSourceTriggeredAbility(new ExileUntilSourceLeavesEffect("")
.setText("exile another target creature until {this} leaves the battlefield"), true);
Ability ability = new TransformIntoSourceTriggeredAbility(new ExileUntilSourceLeavesEffect(), true);
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -45,7 +45,7 @@ public final class OnThinIce extends CardImpl {
this.addAbility(ability);
// When On Thin Ice enters the battlefield, exile target creature an opponent controls until On Thin Ice leaves the battlefield.
ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect("creature"));
ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetOpponentsCreaturePermanent());
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -17,7 +17,9 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -36,6 +38,12 @@ import java.util.stream.Collectors;
*/
public final class PhantomSteed extends CardImpl {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another target creature you control");
static {
filter.add(AnotherPredicate.instance);
}
public PhantomSteed(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
@ -48,9 +56,8 @@ public final class PhantomSteed extends CardImpl {
this.addAbility(FlashAbility.getInstance());
// When Phantom Steed enters the battlefield, exile another target creature you control until Phantom Steed leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect("")
.setText("exile another target creature you control until Phantom Steed leaves the battlefield"));
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -34,11 +34,7 @@ public final class PortableHole extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{W}");
// When Portable Hole enters the battlefield, exile target nonland permanent an opponent controls with mana value 2 or less until Portable Hole leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ExileUntilSourceLeavesEffect("")
.setText("exile target nonland permanent an opponent controls with mana value 2 " +
"or less until {this} leaves the battlefield")
);
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -12,9 +12,8 @@ import mage.abilities.keyword.FlashAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.common.FilterNonlandPermanent;
import mage.target.common.TargetNonlandPermanent;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
/**
*
@ -22,12 +21,6 @@ import mage.target.common.TargetNonlandPermanent;
*/
public final class PrayerOfBinding extends CardImpl {
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanent an opponent controls");
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public PrayerOfBinding(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
@ -35,11 +28,10 @@ public final class PrayerOfBinding extends CardImpl {
this.addAbility(FlashAbility.getInstance());
// When Prayer of Binding enters the battlefield, exile up to one target nonland permanent an opponent controls until Prayer of Binding leaves the battlefield. You gain 2 life.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect("nonland permanent")
.setText("exile up to one target nonland permanent an opponent controls until {this} leaves the battlefield"));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
ability.addEffect(new GainLifeEffect(2));
ability.addTarget(new TargetNonlandPermanent(0, 1, filter, false));
ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_OPPONENTS_PERMANENT_NON_LAND));
this.addAbility(ability);
}

View file

@ -32,9 +32,7 @@ public final class PrisonRealm extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// When Prison Realm enters the battlefield, exile target creature or planeswalker an opponent controls until Prison Realm leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ExileUntilSourceLeavesEffect(filter.getMessage())
);
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -22,7 +22,7 @@ import mage.target.TargetPermanent;
*/
public final class SealAway extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature");
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature an opponent controls");
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
@ -36,7 +36,7 @@ public final class SealAway extends CardImpl {
this.addAbility(FlashAbility.getInstance());
//When Seal Away enters the battlefield, exile target tapped creature an opponent controls until Seal Away leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -1,4 +1,3 @@
package mage.cards.s;
import java.util.UUID;
@ -11,9 +10,7 @@ import mage.abilities.keyword.FlashAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
/**
*
@ -21,12 +18,6 @@ import mage.target.common.TargetCreaturePermanent;
*/
public final class StasisSnare extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public StasisSnare(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}{W}");
@ -34,8 +25,8 @@ public final class StasisSnare extends CardImpl {
this.addAbility(FlashAbility.getInstance());
// When Stasis Snare enters the battlefield, exile target creature an opponent controls until Stasis Snare leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
ability.addTarget(new TargetCreaturePermanent(filter));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetOpponentsCreaturePermanent());
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
}

View file

@ -1,4 +1,3 @@
package mage.cards.t;
import java.util.UUID;
@ -21,7 +20,7 @@ import mage.target.TargetPermanent;
*/
public final class ThopterArrest extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("artifact or creature");
private static final FilterPermanent filter = new FilterPermanent("artifact or creature an opponent controls");
static {
filter.add(Predicates.or(
@ -35,7 +34,7 @@ public final class ThopterArrest extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// When Thopter Arrest enters the battlefield, exile target artifact or creature an opponent controls until Thopter Arrest leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(filter));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);

View file

@ -16,7 +16,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -31,24 +30,20 @@ import mage.util.CardUtil;
*/
public final class TouchTheSpiritRealm extends CardImpl {
private static final FilterPermanent filter = StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE;
public TouchTheSpiritRealm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// When Touch the Spirit Realm enters the battlefield, exile up to one target artifact or creature until
// Touch the Spirit Realm leaves the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage())
.setText("exile up to one target " + filter.getMessage()
+ " until {this} leaves the battlefield"));
ability.addTarget(new TargetPermanent(0, 1, filter, false));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
// Channel - {1}{W}, Discard Touch the Spirit Realm: Exile target artifact or creature.
// Return it to the battlefield under its owner's control at the beginning of the next end step.
Ability channelAbility = new ChannelAbility("{1}{W}", new TouchTheSpiritRealmEffect());
channelAbility.addTarget(new TargetPermanent(filter));
channelAbility.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE));
this.addAbility(channelAbility);
}

View file

@ -1,4 +1,3 @@
package mage.cards.t;
import java.util.UUID;
@ -13,8 +12,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
/**
*
@ -22,12 +20,6 @@ import mage.target.common.TargetCreaturePermanent;
*/
public final class TrapjawTyrant extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public TrapjawTyrant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
@ -35,9 +27,9 @@ public final class TrapjawTyrant extends CardImpl {
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// Enrage Whenever Trapjaw Tyrant is dealt damage, exile target creature your opponent controls until Trapjaw Tyrant leaves the battlefield.
Ability ability = new DealtDamageToSourceTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()), false, true);
ability.addTarget(new TargetCreaturePermanent(filter));
// Enrage Whenever Trapjaw Tyrant is dealt damage, exile target creature an opponent controls until Trapjaw Tyrant leaves the battlefield.
Ability ability = new DealtDamageToSourceTriggeredAbility(new ExileUntilSourceLeavesEffect(), false, true);
ability.addTarget(new TargetOpponentsCreaturePermanent());
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
this.addAbility(ability);
}

View file

@ -42,6 +42,7 @@ public class EmbalmTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aSanctions);
addTarget(playerA, yOx);
setChoice(playerA, true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -81,10 +82,12 @@ public class EmbalmTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aSanctions);
addTarget(playerA, yOx);
setChoice(playerA, true);
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, dBlade);
addTarget(playerB, aSanctions);
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Embalm");
addTarget(playerA, wKnight);
setChoice(playerA, true);
setStopAt(1, PhaseStep.END_TURN);
execute();
@ -126,11 +129,13 @@ public class EmbalmTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aSanctions);
addTarget(playerA, yOx);
setChoice(playerA, true);
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, dBlade, aSanctions);
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Embalm");
addTarget(playerA, wKnight);
setChoice(playerA, true);
castSpell(1, PhaseStep.END_TURN, playerB, dBlade, aSanctions);

View file

@ -1,10 +1,12 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.util.CardUtil;
/**
@ -13,9 +15,8 @@ import mage.util.CardUtil;
*/
public class ExileUntilSourceLeavesEffect extends OneShotEffect {
public ExileUntilSourceLeavesEffect(String targetName) {
public ExileUntilSourceLeavesEffect() {
super(Outcome.Removal);
this.staticText = "exile target " + targetName + " an opponent controls until {this} leaves the battlefield";
}
public ExileUntilSourceLeavesEffect(final ExileUntilSourceLeavesEffect effect) {
@ -29,13 +30,10 @@ public class ExileUntilSourceLeavesEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent == null) {
return false;
}
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
// If Banishing Light leaves the battlefield before its triggered ability resolves, the target permanent won't be exiled.
// (2021-03-19)
if (game.getPermanent(source.getSourceId()) == null) {
if (permanent == null) {
return false;
}
@ -45,4 +43,12 @@ public class ExileUntilSourceLeavesEffect extends OneShotEffect {
}
return effect.apply(game, source);
}
@Override
public String getText(Mode mode) {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
return "exile " + getTargetPointer().describeTargets(mode.getTargets(), "that creature") + " until {this} leaves the battlefield";
}
}

View file

@ -438,6 +438,13 @@ public final class StaticFilters {
FILTER_OPPONENTS_PERMANENT.setLockedFilter(true);
}
public static final FilterNonlandPermanent FILTER_OPPONENTS_PERMANENT_NON_LAND = new FilterNonlandPermanent("nonland permanent an opponent controls");
static {
FILTER_OPPONENTS_PERMANENT_NON_LAND.add(TargetController.OPPONENT.getControllerPredicate());
FILTER_OPPONENTS_PERMANENT_NON_LAND.setLockedFilter(true);
}
public static final FilterCreaturePermanent FILTER_OPPONENTS_PERMANENT_CREATURE = new FilterOpponentsCreaturePermanent();
static {

View file

@ -88,6 +88,8 @@ public interface Target extends Serializable {
void updateTarget(UUID targetId, Game game);
String getDescription();
String getMessage();
String getTargetName();

View file

@ -97,6 +97,24 @@ public abstract class TargetImpl implements Target {
this.maxNumberOfTargets = maxNumberOftargets;
}
@Override
public String getDescription() {
// target description for ability text
StringBuilder sb = new StringBuilder();
if (getNumberOfTargets() != 1 || getMaxNumberOfTargets() != 1) {
if (getNumberOfTargets() < getMaxNumberOfTargets() && getMaxNumberOfTargets() != Integer.MAX_VALUE) {
sb.append("up to ");
}
sb.append(CardUtil.numberToText(getMaxNumberOfTargets()));
sb.append(' ');
}
if (!isNotTarget() && !getTargetName().contains("target")) {
sb.append("target ");
}
sb.append(getTargetName());
return sb.toString();
}
@Override
public String getMessage() {
// UI choose message

View file

@ -6,6 +6,7 @@ import mage.cards.Card;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Targets;
import java.util.*;
@ -117,4 +118,9 @@ public class FirstTargetPointer extends TargetPointerImpl {
}
return permanent;
}
@Override
public String describeTargets(Targets targets, String defaultDescription) {
return targets.isEmpty() ? defaultDescription : targets.get(0).getDescription();
}
}

View file

@ -6,6 +6,7 @@ import mage.cards.Card;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Targets;
import java.util.*;
@ -114,4 +115,9 @@ public class SecondTargetPointer extends TargetPointerImpl {
}
return null;
}
@Override
public String describeTargets(Targets targets, String defaultDescription) {
return targets.size() < 2 ? defaultDescription : targets.get(1).getDescription();
}
}

View file

@ -3,6 +3,7 @@ package mage.target.targetpointer;
import mage.abilities.Ability;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Targets;
import mage.util.Copyable;
import java.io.Serializable;
@ -37,6 +38,16 @@ public interface TargetPointer extends Serializable, Copyable<TargetPointer> {
*/
Permanent getFirstTargetPermanentOrLKI(Game game, Ability source);
/**
* Returns description of targets for ability text
*
* @param targets
* @param defaultText
*/
default String describeTargets(Targets targets, String defaultDescription) {
return defaultDescription;
}
/**
* Store text to target pointer (usefull to keep data for specific trigger, e.g. selected target name for rules)
*

View file

@ -6,6 +6,7 @@ import mage.cards.Card;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Targets;
import java.util.*;
@ -118,4 +119,9 @@ public class ThirdTargetPointer extends TargetPointerImpl {
}
return null;
}
@Override
public String describeTargets(Targets targets, String defaultDescription) {
return targets.size() < 3 ? defaultDescription : targets.get(2).getDescription();
}
}