Create common class for "when target dies this turn" delayed triggers (#9722)

Fixes #9716. Fixes #9719.
This commit is contained in:
Alex W. Jackson 2022-11-04 05:27:56 -04:00 committed by GitHub
parent afb7d75007
commit 10d7acb4b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
74 changed files with 397 additions and 1628 deletions

View file

@ -22,7 +22,7 @@ public final class AcrobaticManeuver extends CardImpl {
// Exile target creature you control, then return that card to the battlefield under its owner's control.
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(", then"));
// Draw a card.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("<br>"));

View file

@ -1,28 +1,25 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.constants.CardType;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import mage.target.TargetPermanent;
/**
*
@ -49,9 +46,14 @@ public final class AdarkarValkyrie extends CardImpl {
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// {T}: When target creature other than Adarkar Valkyrie dies this turn, return that card to the battlefield under your control.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AdarkarValkyrieEffect(), new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent(filter));
DelayedTriggeredAbility delayedAbility = new WhenTargetDiesDelayedTriggeredAbility(
new ReturnFromGraveyardToBattlefieldTargetEffect()
.setText("return that card to the battlefield under your control"),
SetTargetPointer.CARD
);
delayedAbility.setTriggerPhrase("When target creature other than {this} dies this turn, ");
Ability ability = new SimpleActivatedAbility(new CreateDelayedTriggeredAbilityEffect(delayedAbility), new TapSourceCost());
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
@ -64,71 +66,3 @@ public final class AdarkarValkyrie extends CardImpl {
return new AdarkarValkyrie(this);
}
}
class AdarkarValkyrieEffect extends OneShotEffect {
public AdarkarValkyrieEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "When target creature other than {this} dies this turn, return that card to the battlefield under your control";
}
public AdarkarValkyrieEffect(final AdarkarValkyrieEffect effect) {
super(effect);
}
@Override
public AdarkarValkyrieEffect copy() {
return new AdarkarValkyrieEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent == null) { return false; }
DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(new MageObjectReference(permanent, game));
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
}
class AdarkarValkyrieDelayedTriggeredAbility extends DelayedTriggeredAbility {
private final MageObjectReference mor;
public AdarkarValkyrieDelayedTriggeredAbility(MageObjectReference mor) {
super(new ReturnToBattlefieldUnderYourControlTargetEffect(), Duration.EndOfTurn);
this.mor = mor;
setTriggerPhrase("When target creature other than {this} dies this turn, " );
}
public AdarkarValkyrieDelayedTriggeredAbility(final AdarkarValkyrieDelayedTriggeredAbility ability) {
super(ability);
this.mor = ability.mor;
}
@Override
public AdarkarValkyrieDelayedTriggeredAbility copy() {
return new AdarkarValkyrieDelayedTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!((ZoneChangeEvent) event).isDiesEvent()) { return false; }
if (!mor.refersTo(((ZoneChangeEvent) event).getTarget(), game)) { return false; }
// TODO: Must it? Why?
// Must be in the graveyard
if (game.getState().getZone(event.getTargetId()) != Zone.GRAVEYARD) { return false; }
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
return true;
}
}

View file

@ -53,7 +53,7 @@ public class AminatouTheFateshifter extends CardImpl {
// 1: Exile another target permanent you own, then return it to the battlefield under your control.
ability = new LoyaltyAbility(new ExileTargetForSourceEffect(), -1);
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(false));
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect().concatBy(", then"));
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);

View file

@ -104,7 +104,6 @@ class AngelOfCondemnationExileUntilEOTEffect extends OneShotEffect {
//create delayed triggered ability
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false)
.setText("return that card to the battlefield under its owner's control")
.setTargetPointer(new FixedTarget(source.getFirstTarget(), game))
), source);
return true;

View file

@ -3,7 +3,7 @@ package mage.cards.a;
import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@ -21,7 +21,7 @@ public final class AngelicRenewal extends CardImpl {
// Whenever a creature is put into your graveyard from the battlefield, you may sacrifice Angelic Renewal. If you do, return that card to the battlefield.
this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(new DoIfCostPaid(
new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false), new SacrificeSourceCost()), false,
new ReturnFromGraveyardToBattlefieldTargetEffect().setText("return that card to the battlefield"), new SacrificeSourceCost()), false,
StaticFilters.FILTER_PERMANENT_A_CREATURE, true, true));
}

View file

@ -35,7 +35,7 @@ public final class Arcbond extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}");
// Choose target creature. Whenever that creature is dealt damage this turn, it deals that much damage to each other creature and each player.
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new ArcbondDelayedTriggeredAbility(), true, true));
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new ArcbondDelayedTriggeredAbility()));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
@ -64,7 +64,6 @@ class ArcbondDelayedTriggeredAbility extends DelayedTriggeredAbility {
@Override
public void init(Game game) {
super.init(game);
// because target can already be gone from battlefield if triggered ability resolves, we need to hold an own object reference
targetObject = new MageObjectReference(getTargets().getFirstTarget(), game);
if (targetObject != null) {

View file

@ -125,7 +125,6 @@ class AstralDriftEffect extends OneShotEffect {
}
//create delayed triggered ability
Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false);
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;

View file

@ -65,7 +65,6 @@ class AstralSlideEffect extends OneShotEffect {
if (controller.moveCardsToExile(permanent, source, game, true, exileId, sourceObject.getIdName())) {
//create delayed triggered ability
Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false);
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);
}

View file

@ -52,7 +52,7 @@ public final class BattleOfFrostAndFire extends CardImpl {
// III Whenever you cast a spell with converted mana cost 5 or greater this turn, draw two cards, then discard a card.
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, new CreateDelayedTriggeredAbilityEffect(
new BattleOfFrostAndFireTriggeredAbility(), false, false
new BattleOfFrostAndFireTriggeredAbility(), false
));
this.addAbility(sagaAbility);
}

View file

@ -1,9 +1,7 @@
package mage.cards.b;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
@ -11,12 +9,6 @@ import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.SpiritWhiteToken;
import mage.target.common.TargetControlledCreaturePermanent;
@ -30,14 +22,16 @@ public class BlessedDefiance extends CardImpl {
public BlessedDefiance(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
// Target creature you control gets +2/+0 and gains lifelink until end of turn. When that creature dies this turn, create a 1/1 white Spirit creature token with flying.
// Target creature you control gets +2/+0 and gains lifelink until end of turn.
// When that creature dies this turn, create a 1/1 white Spirit creature token with flying.
this.getSpellAbility().addEffect(new BoostTargetEffect(2, 0)
.setText("Target creature you control gets +2/+0"));
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn)
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(LifelinkAbility.getInstance())
.setText("and gains lifelink until end of turn"));
this.getSpellAbility().addEffect(new BlessedDefianceEffect());
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
new WhenTargetDiesDelayedTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken()))
));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
}
private BlessedDefiance(final BlessedDefiance card) {
@ -49,65 +43,3 @@ public class BlessedDefiance extends CardImpl {
return new BlessedDefiance(this);
}
}
class BlessedDefianceEffect extends OneShotEffect {
BlessedDefianceEffect() {
super(Outcome.Benefit);
staticText = "When that creature dies this turn, create a 1/1 white Spirit creature token with flying.";
}
private BlessedDefianceEffect(final BlessedDefianceEffect effect) {
super(effect);
}
@Override
public BlessedDefianceEffect copy() {
return new BlessedDefianceEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent == null) {
return false;
}
game.addDelayedTriggeredAbility(new BlessedDefianceDelayedTriggeredAbility(permanent, game), source);
return true;
}
}
class BlessedDefianceDelayedTriggeredAbility extends DelayedTriggeredAbility {
private final MageObjectReference mor;
BlessedDefianceDelayedTriggeredAbility(Permanent permanent, Game game) {
super(new CreateTokenEffect(new SpiritWhiteToken()), Duration.EndOfTurn, false, false);
this.mor = new MageObjectReference(permanent, game);
}
private BlessedDefianceDelayedTriggeredAbility(final BlessedDefianceDelayedTriggeredAbility ability) {
super(ability);
this.mor = ability.mor;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return mor.refersTo(((ZoneChangeEvent) event).getTarget(), game);
}
@Override
public BlessedDefianceDelayedTriggeredAbility copy() {
return new BlessedDefianceDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When that creature dies this turn, create a 1/1 white Spirit creature token with flying.";
}
}

View file

@ -96,7 +96,6 @@ class BlizzardStrixEffect extends OneShotEffect {
//create delayed triggered ability
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(
new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false)
.setText("Return that card to the battlefield under its owner's control at the beginning of the next end step")
.setTargetPointer(new FixedTarget(source.getFirstTarget(), game))
), source);
return true;

View file

@ -20,7 +20,7 @@ public final class Blur extends CardImpl {
// Exile target creature you control, then return that card to the battlefield under its owner's control.
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(", then"));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
// Draw a card.

View file

@ -1,20 +1,14 @@
package mage.cards.b;
import java.util.UUID;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.ExileGraveyardAllTargetPlayerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.target.Target;
import mage.target.TargetPlayer;
import mage.constants.SetTargetPointer;
import mage.target.common.TargetCreaturePermanent;
/**
@ -26,11 +20,12 @@ public final class BurnAway extends CardImpl {
public BurnAway(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{R}");
// Burn Away deals 6 damage to target creature. When that creature dies this turn, exile all cards from its controller's graveyard.
// Burn Away deals 6 damage to target creature. When that creature dies this turn, exile its controller's graveyard.
this.getSpellAbility().addEffect(new DamageTargetEffect(6));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new BurnAwayDelayedTriggeredAbility(), true));
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new WhenTargetDiesDelayedTriggeredAbility(
new ExileGraveyardAllTargetPlayerEffect().setText("exile its controller's graveyard"), SetTargetPointer.PLAYER
)));
}
private BurnAway(final BurnAway card) {
@ -42,42 +37,3 @@ public final class BurnAway extends CardImpl {
return new BurnAway(this);
}
}
class BurnAwayDelayedTriggeredAbility extends DelayedTriggeredAbility {
public BurnAwayDelayedTriggeredAbility() {
super(new ExileGraveyardAllTargetPlayerEffect(), Duration.EndOfTurn, false);
}
public BurnAwayDelayedTriggeredAbility(BurnAwayDelayedTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.isDiesEvent() && zEvent.getTarget() != null && zEvent.getTargetId().equals(getTargets().getFirstTarget())) {
this.getTargets().clear(); // else spell fizzles because target creature died
Target target = new TargetPlayer();
target.add(zEvent.getTarget().getControllerId(), game);
this.addTarget(target);
return true;
}
return false;
}
@Override
public BurnAwayDelayedTriggeredAbility copy() {
return new BurnAwayDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When that creature dies this turn, exile its controller's graveyard.";
}
}

View file

@ -21,7 +21,7 @@ public final class Cloudshift extends CardImpl {
// Exile target creature you control, then return that card to the battlefield under your control.
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(false));
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect().concatBy(", then"));
}
private Cloudshift(final Cloudshift card) {

View file

@ -21,7 +21,7 @@ public final class ConjurersCloset extends CardImpl {
// At the beginning of your end step, you may exile target creature you control, then return that card to the battlefield under your control.
Ability ability = new BeginningOfYourEndStepTriggeredAbility(new ExileTargetForSourceEffect(), true);
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(false));
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect().concatBy(", then"));
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}

View file

@ -2,24 +2,20 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.target.TargetPermanent;
import java.util.UUID;
@ -40,14 +36,21 @@ public final class Cryptek extends CardImpl {
public Cryptek(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{B}");
this.subtype.add(SubType.NECRON);
this.subtype.add(SubType.WIZARD);
this.subtype.add(SubType.NECRON, SubType.WIZARD);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// {1}{B}, {T}: Choose another target artifact creature you control. When that creature dies this turn, return it to the battlefield tapped under your control.
Ability ability = new SimpleActivatedAbility(
new CreateDelayedTriggeredAbilityEffect(new CryptekTriggeredAbility()), new ManaCostsImpl<>("{1}{B}")
new CreateDelayedTriggeredAbilityEffect(
new WhenTargetDiesDelayedTriggeredAbility(
new ReturnFromGraveyardToBattlefieldTargetEffect(true)
.setText("return it to the battlefield tapped under your control"),
SetTargetPointer.CARD
),
true, "Choose another target artifact creature you control. "
),
new ManaCostsImpl<>("{1}{B}")
);
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPermanent(filter));
@ -63,41 +66,3 @@ public final class Cryptek extends CardImpl {
return new Cryptek(this);
}
}
class CryptekTriggeredAbility extends DelayedTriggeredAbility {
CryptekTriggeredAbility() {
super(new ReturnFromGraveyardToBattlefieldTargetEffect(true), Duration.EndOfTurn, true, false);
}
private CryptekTriggeredAbility(final CryptekTriggeredAbility ability) {
super(ability);
}
@Override
public CryptekTriggeredAbility copy() {
return new CryptekTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
return zEvent.isDiesEvent()
&& this
.getEffects()
.stream()
.map(Effect::getTargetPointer)
.map(targetPointer -> targetPointer.getFirst(game, this))
.anyMatch(zEvent.getTargetId()::equals);
}
@Override
public String getRule() {
return "When that creature dies this turn, return it to the battlefield tapped under your control.";
}
}

View file

@ -23,7 +23,8 @@ public final class Displace extends CardImpl {
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 2, StaticFilters.FILTER_CONTROLLED_CREATURES, false));
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false)
.withReturnNames("those cards", "their owner's"));
.setText(", then return those cards to the battlefield under their owner's control")
);
}
private Displace(final Displace card) {

View file

@ -40,7 +40,7 @@ public final class DisplacerKitten extends CardImpl {
Ability ability = new SpellCastControllerTriggeredAbility(
new ExileTargetForSourceEffect(), StaticFilters.FILTER_SPELL_A_NON_CREATURE, false
);
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(", then"));
ability.addTarget(new TargetPermanent(0, 1, filter));
this.addAbility(ability.withFlavorWord("Avoidance"));
}

View file

@ -40,8 +40,7 @@ public final class EldraziDisplacer extends CardImpl {
// {2}{C}: Exile another target creature, then return it to the battlefield tapped under its owner's control.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetForSourceEffect(), new ManaCostsImpl<>("{2}{C}"));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(true, false)
.withReturnNames("it", "its owner's"));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(true, false, "it").concatBy(", then"));
ability.addTarget(new TargetCreaturePermanent(FILTER));
this.addAbility(ability);
}

View file

@ -46,7 +46,7 @@ public final class EmielTheBlessed extends CardImpl {
// {3}: Exile another target creature you control, then return it to the battlefield under its owner's control.
Ability ability = new SimpleActivatedAbility(new ExileTargetForSourceEffect(), new GenericManaCost(3));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);

View file

@ -21,7 +21,7 @@ public final class Ephemerate extends CardImpl {
// Exile target creature you control, then return it to the battlefield under its owner's control.
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).setText(", then return it to the battlefield under its owner's control"));
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
// Rebound
this.addAbility(new ReboundAbility());

View file

@ -38,7 +38,7 @@ public final class FarTraveler extends CardImpl {
Ability ability = new BeginningOfEndStepTriggeredAbility(
new ExileTargetForSourceEffect(), TargetController.YOU, false
);
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
ability.addTarget(new TargetPermanent(0, 1, filter));
this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(
ability, Duration.WhileOnBattlefield,

View file

@ -36,7 +36,7 @@ public final class FelidarGuardian extends CardImpl {
// When Felidar Guardian enters the battlefield, you may exile another target permanent you control, then return that card to the battlefield under its owner's control.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect(), true);
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(", then"));
ability.addTarget(new TargetControlledPermanent(filter));
this.addAbility(ability);
}

View file

@ -28,8 +28,7 @@ public final class Flicker extends CardImpl {
// Exile target nontoken permanent, then return it to the battlefield under its owner's control.
this.getSpellAbility().addTarget(new TargetPermanent(filter));
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
}
private Flicker(final Flicker card) {

View file

@ -30,7 +30,7 @@ public final class FlickerOfFate extends CardImpl {
// Exile target creature or enchantment, then return it to the battlefield under its owner's control.
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
this.getSpellAbility().addTarget(new TargetPermanent(filter));
}

View file

@ -1,24 +1,14 @@
package mage.cards.g;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.abilities.effects.common.ExileTargetForSourceEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
import mage.target.TargetPermanent;
/**
* @author noxx
@ -38,8 +28,10 @@ public final class GhostlyFlicker extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
// Exile two target artifacts, creatures, and/or lands you control, then return those cards to the battlefield under your control.
this.getSpellAbility().addTarget(new TargetControlledPermanent(2, 2, filter, false));
this.getSpellAbility().addEffect(new GhostlyFlickerEffect());
this.getSpellAbility().addTarget(new TargetPermanent(2, filter));
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect()
.setText(", then return those cards to the battlefield under your control"));
}
private GhostlyFlicker(final GhostlyFlicker card) {
@ -51,47 +43,3 @@ public final class GhostlyFlicker extends CardImpl {
return new GhostlyFlicker(this);
}
}
class GhostlyFlickerEffect extends OneShotEffect {
public GhostlyFlickerEffect() {
super(Outcome.Benefit);
staticText = "Exile two target artifacts, creatures, and/or lands you control, then return those cards to the battlefield under your control";
}
public GhostlyFlickerEffect(final GhostlyFlickerEffect effect) {
super(effect);
}
@Override
public GhostlyFlickerEffect copy() {
return new GhostlyFlickerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
Set<Card> toExile = new HashSet<>();
for (UUID permanentId : targetPointer.getTargets(game, source)) {
Permanent target = game.getPermanent(permanentId);
if (target != null) {
toExile.add(target);
}
}
controller.moveCards(toExile, Zone.EXILED, source, game);
game.getState().processAction(game);
Set<Card> toBattlefield = new HashSet<>();
for (Card card : toExile) {
Zone currentZone = game.getState().getZone(card.getId());
if (Zone.BATTLEFIELD != currentZone && currentZone.isPublicZone()) {
toBattlefield.add(card);
}
}
controller.moveCards(toBattlefield, Zone.BATTLEFIELD, source, game);
return true;
}
return false;
}
}

View file

@ -1,25 +1,15 @@
package mage.cards.g;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.players.Player;
import mage.constants.SetTargetPointer;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
@ -31,9 +21,13 @@ public final class GracefulReprieve extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// When target creature dies this turn, return that card to the battlefield under its owner's control.
DelayedTriggeredAbility ability = new WhenTargetDiesDelayedTriggeredAbility(
new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false),
SetTargetPointer.CARD
);
ability.setTriggerPhrase("When target creature dies this turn, ");
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(ability));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new GracefulReprieveEffect());
}
private GracefulReprieve(final GracefulReprieve card) {
@ -45,99 +39,3 @@ public final class GracefulReprieve extends CardImpl {
return new GracefulReprieve(this);
}
}
class GracefulReprieveEffect extends OneShotEffect {
public GracefulReprieveEffect() {
super(Outcome.Benefit);
this.staticText = "When target creature dies this turn, return that card to the battlefield under its owner's control";
}
public GracefulReprieveEffect(final GracefulReprieveEffect effect) {
super(effect);
}
@Override
public GracefulReprieveEffect copy() {
return new GracefulReprieveEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
DelayedTriggeredAbility delayedAbility = new GracefulReprieveDelayedTriggeredAbility(new MageObjectReference(targetPointer.getFirst(game, source), game));
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
}
class GracefulReprieveDelayedTriggeredAbility extends DelayedTriggeredAbility {
private MageObjectReference target;
public GracefulReprieveDelayedTriggeredAbility(MageObjectReference target) {
super(new GracefulReprieveDelayedEffect(), Duration.EndOfTurn);
this.target = target;
}
public GracefulReprieveDelayedTriggeredAbility(GracefulReprieveDelayedTriggeredAbility ability) {
super(ability);
this.target = ability.target;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (target.refersTo(((ZoneChangeEvent) event).getTarget(), game)) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.isDiesEvent()) {
getEffects().setTargetPointer(new FixedTarget(target.getSourceId()));
return true;
}
}
return false;
}
@Override
public GracefulReprieveDelayedTriggeredAbility copy() {
return new GracefulReprieveDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When target creature dies this turn, return that card to the battlefield under its owner's control.";
}
}
class GracefulReprieveDelayedEffect extends OneShotEffect {
public GracefulReprieveDelayedEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "return that card to the battlefield under its owner's control";
}
public GracefulReprieveDelayedEffect(final GracefulReprieveDelayedEffect effect) {
super(effect);
}
@Override
public GracefulReprieveDelayedEffect copy() {
return new GracefulReprieveDelayedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null);
}
return true;
}
return false;
}
}

View file

@ -38,7 +38,7 @@ public final class HallowedRespite extends CardImpl {
// Exile target nonlegendary creature, then return it to the battlefield under its owner's control. If it entered under your control, put a +1/+1 counter on it. Otherwise, tap it.
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).setText(", then return it to the battlefield under its owner's control"));
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
this.getSpellAbility().addEffect(new HallowedRespiteEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));

View file

@ -38,7 +38,7 @@ public final class IcewindStalwart extends CardImpl {
// Protection Fighting Style When Icewind Stalwart enters the battlefield, exile up to one target non-Warrior creature you control, then return it to the battlefield under its owner's control.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect());
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
ability.addTarget(new TargetPermanent(0, 1, filter));
this.addAbility(ability.withFlavorWord("Protection Fighting Style"));
}

View file

@ -2,7 +2,7 @@ package mage.cards.i;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.ExileTargetForSourceEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@ -21,8 +21,8 @@ public final class IllusionistsStratagem extends CardImpl {
// Exile up to two target creatures you control, then return those cards to the battlefield under their owner's control.
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(false)
.withReturnNames("those cards", "their owner's"));
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false)
.setText(", then return those cards to the battlefield under their owner's control"));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 2,
StaticFilters.FILTER_CONTROLLED_CREATURES, false));

View file

@ -32,9 +32,10 @@ package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealtDamageAndDiedTriggeredAbility;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.FlipSourceEffect;
import mage.cards.CardImpl;
@ -42,14 +43,13 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.WasDealtDamageThisTurnPredicate;
import mage.game.permanent.token.TokenImpl;
import mage.target.common.TargetCreaturePermanent;
/**
* @author LevelX
* @author awjackson
*/
public final class InitiateOfBlood extends CardImpl {
@ -61,8 +61,7 @@ public final class InitiateOfBlood extends CardImpl {
public InitiateOfBlood(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}");
this.subtype.add(SubType.OGRE);
this.subtype.add(SubType.SHAMAN);
this.subtype.add(SubType.OGRE, SubType.SHAMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
@ -70,13 +69,13 @@ public final class InitiateOfBlood extends CardImpl {
this.flipCardName = "Goka the Unjust";
// {T}: Initiate of Blood deals 1 damage to target creature that was dealt damage this turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost());
// When that creature dies this turn, flip Initiate of Blood.
Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost());
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new WhenTargetDiesDelayedTriggeredAbility(
new FlipSourceEffect(new GokaTheUnjust()).setText("flip {this}")
)));
ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
// When that creature is put into a graveyard this turn, flip Initiate of Blood.
this.addAbility(new DealtDamageAndDiedTriggeredAbility(new FlipSourceEffect(new GokaTheUnjust())));
}
private InitiateOfBlood(final InitiateOfBlood card) {
@ -102,13 +101,12 @@ class GokaTheUnjust extends TokenImpl {
addSuperType(SuperType.LEGENDARY);
cardType.add(CardType.CREATURE);
color.setRed(true);
subtype.add(SubType.OGRE);
subtype.add(SubType.SHAMAN);
subtype.add(SubType.OGRE, SubType.SHAMAN);
power = new MageInt(4);
toughness = new MageInt(4);
// {T}: Goka the Unjust deals 4 damage to target creature that was dealt damage this turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(4), new TapSourceCost());
Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(4), new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
}

View file

@ -4,7 +4,7 @@ import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetForSourceEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
@ -62,10 +62,10 @@ class JusticiarsPortalEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
UUID targetId = source.getFirstTarget();
new ExileTargetForSourceEffect().apply(game, source);
new ReturnToBattlefieldUnderYourControlTargetEffect().apply(game, source);
new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).apply(game, source);
ContinuousEffect effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(targetId, game));
game.addEffect(effect, source);
return true;
}
}
}

View file

@ -2,13 +2,14 @@ package mage.cards.k;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.counter.AddCountersControllerEffect;
import mage.abilities.keyword.HasteAbility;
@ -19,9 +20,6 @@ import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
@ -36,8 +34,7 @@ public final class KelsienThePlague extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}{B}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ASSASSIN);
this.subtype.add(SubType.HUMAN, SubType.ASSASSIN);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
@ -54,7 +51,10 @@ public final class KelsienThePlague extends CardImpl {
)));
// {T}: Kelsien deals 1 damage to target creature you don't control. When that creature dies this turn, you get an experience counter.
Ability ability = new SimpleActivatedAbility(new KelsienThePlagueEffect(), new TapSourceCost());
Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost());
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new WhenTargetDiesDelayedTriggeredAbility(
new AddCountersControllerEffect(CounterType.EXPERIENCE.createInstance(), false)
)));
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL));
this.addAbility(ability);
}
@ -97,76 +97,3 @@ enum KelsienThePlagueCount implements DynamicValue {
return "experience counter you have";
}
}
class KelsienThePlagueEffect extends OneShotEffect {
KelsienThePlagueEffect() {
super(Outcome.Benefit);
staticText = "{this} deals 1 damage to target creature you don't control. " +
"When that creature dies this turn, you get an experience counter.";
}
private KelsienThePlagueEffect(final KelsienThePlagueEffect effect) {
super(effect);
}
@Override
public KelsienThePlagueEffect copy() {
return new KelsienThePlagueEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent == null) {
return false;
}
permanent.damage(1, source.getSourceId(), source, game);
game.addDelayedTriggeredAbility(new KelsienThePlagueDelayedTriggeredAbility(permanent.getId()), source);
return true;
}
}
class KelsienThePlagueDelayedTriggeredAbility extends DelayedTriggeredAbility {
private final UUID target;
KelsienThePlagueDelayedTriggeredAbility(UUID target) {
super(new AddCountersControllerEffect(
CounterType.EXPERIENCE.createInstance(), false
), Duration.EndOfTurn, true);
this.target = target;
}
private KelsienThePlagueDelayedTriggeredAbility(KelsienThePlagueDelayedTriggeredAbility ability) {
super(ability);
this.target = ability.target;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!event.getTargetId().equals(target)) {
return false;
}
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.isDiesEvent()) {
return true;
}
return false;
}
@Override
public KelsienThePlagueDelayedTriggeredAbility copy() {
return new KelsienThePlagueDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When that creature dies this turn, you get an experience counter.";
}
}

View file

@ -1,20 +1,12 @@
package mage.cards.m;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.Spirit32Token;
import mage.target.common.TargetCreaturePermanent;
@ -28,9 +20,12 @@ public final class MakeYourMark extends CardImpl {
public MakeYourMark(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R/W}");
// Target creature gets +1/+0 until end of turn. When that creature dies this turn, create a 3/2 red and white Spirit creature token.
// Target creature gets +1/+0 until end of turn.
// When that creature dies this turn, create a 3/2 red and white Spirit creature token.
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0));
this.getSpellAbility().addEffect(new MakeYourMarkEffect());
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
new WhenTargetDiesDelayedTriggeredAbility(new CreateTokenEffect(new Spirit32Token()))
));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
@ -43,65 +38,3 @@ public final class MakeYourMark extends CardImpl {
return new MakeYourMark(this);
}
}
class MakeYourMarkEffect extends OneShotEffect {
MakeYourMarkEffect() {
super(Outcome.Benefit);
staticText = "When that creature dies this turn, create a 3/2 red and white Spirit creature token.";
}
private MakeYourMarkEffect(final MakeYourMarkEffect effect) {
super(effect);
}
@Override
public MakeYourMarkEffect copy() {
return new MakeYourMarkEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent == null) {
return false;
}
game.addDelayedTriggeredAbility(new MakeYourMarkDelayedTriggeredAbility(permanent, game), source);
return true;
}
}
class MakeYourMarkDelayedTriggeredAbility extends DelayedTriggeredAbility {
private final MageObjectReference mor;
MakeYourMarkDelayedTriggeredAbility(Permanent permanent, Game game) {
super(new CreateTokenEffect(new Spirit32Token()), Duration.EndOfTurn, false, false);
this.mor = new MageObjectReference(permanent, game);
}
private MakeYourMarkDelayedTriggeredAbility(final MakeYourMarkDelayedTriggeredAbility ability) {
super(ability);
this.mor = ability.mor;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return mor.refersTo(((ZoneChangeEvent) event).getTarget(), game);
}
@Override
public MakeYourMarkDelayedTriggeredAbility copy() {
return new MakeYourMarkDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When that creature dies this turn, create a 3/2 red and white Spirit creature token.";
}
}

View file

@ -23,7 +23,7 @@ public final class MomentaryBlink extends CardImpl {
// Exile target creature you control, then return it to the battlefield under its owner's control.
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
// Flashback {3}{U}
this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{3}{U}")));

View file

@ -77,7 +77,6 @@ class MystifyingMazeEffect extends OneShotEffect {
if (permanent.moveToExile(source.getSourceId(), sourceObject.getIdName(), source, game)) {
//create delayed triggered ability
Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(true, false);
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;

View file

@ -42,7 +42,7 @@ public final class N1Starfighter extends CardImpl {
// Whenever N-1 Starfighter deals combat damage to a player, you may pay {1}{W/U}. If you do,
// exile another target creature you control, then return that card to the battlefield under its owner's control.
DoIfCostPaid doIfCostPaid = new DoIfCostPaid(new ExileTargetForSourceEffect(), new ManaCostsImpl<>("{1}{W/U}"));
doIfCostPaid.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(","));
doIfCostPaid.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(", then"));
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(doIfCostPaid, false);
ability.addTarget(new TargetControlledCreaturePermanent(filter));

View file

@ -40,7 +40,7 @@ public final class NephaliaSmuggler extends CardImpl {
// {3}{U}, {tap}: Exile another target creature you control, then return that card to the battlefield under your control.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetForSourceEffect(), new ManaCostsImpl<>("{3}{U}"));
ability.addCost(new TapSourceCost());
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(false));
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect().concatBy(", then"));
ability.addTarget(new TargetControlledCreaturePermanent(filter));
this.addAbility(ability);
}

View file

@ -38,7 +38,7 @@ public final class OjiTheExquisiteBlade extends CardImpl {
// Whenever you cast your second spell each turn, exile up to one target creature you control, then return it to the battlefield under its owner's control.
ability = new CastSecondSpellTriggeredAbility(new ExileTargetForSourceEffect());
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
ability.addTarget(new TargetControlledCreaturePermanent(0, 1));
this.addAbility(ability);
}

View file

@ -1,21 +1,13 @@
package mage.cards.o;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.token.EldraziHorrorToken;
import mage.target.common.TargetCreaturePermanent;
@ -30,8 +22,10 @@ public final class OtherworldlyOutburst extends CardImpl {
// Target creature gets +1/+0 until end of turn. When that creature dies this turn, create a 3/2 colorless Eldrazi Horror creature token.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0, Duration.EndOfTurn));
this.getSpellAbility().addEffect(new OtherworldlyOutburstEffect());
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0));
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
new WhenTargetDiesDelayedTriggeredAbility(new CreateTokenEffect(new EldraziHorrorToken()))
));
}
private OtherworldlyOutburst(final OtherworldlyOutburst card) {
@ -43,67 +37,3 @@ public final class OtherworldlyOutburst extends CardImpl {
return new OtherworldlyOutburst(this);
}
}
class OtherworldlyOutburstEffect extends OneShotEffect {
public OtherworldlyOutburstEffect() {
super(Outcome.UnboostCreature);
this.staticText = "When that creature dies this turn, create a 3/2 colorless Eldrazi Horror creature token";
}
public OtherworldlyOutburstEffect(final OtherworldlyOutburstEffect effect) {
super(effect);
}
@Override
public OtherworldlyOutburstEffect copy() {
return new OtherworldlyOutburstEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
game.addDelayedTriggeredAbility(new OtherworldlyOutburstDelayedTriggeredAbility(source.getFirstTarget()), source);
return true;
}
}
class OtherworldlyOutburstDelayedTriggeredAbility extends DelayedTriggeredAbility {
private final UUID target;
public OtherworldlyOutburstDelayedTriggeredAbility(UUID target) {
super(new CreateTokenEffect(new EldraziHorrorToken()), Duration.EndOfTurn);
this.target = target;
}
public OtherworldlyOutburstDelayedTriggeredAbility(OtherworldlyOutburstDelayedTriggeredAbility ability) {
super(ability);
this.target = ability.target;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(target)) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.isDiesEvent()) {
return true;
}
}
return false;
}
@Override
public OtherworldlyOutburstDelayedTriggeredAbility copy() {
return new OtherworldlyOutburstDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When that creature dies this turn, create a 3/2 colorless Eldrazi Horror creature token.";
}
}

View file

@ -42,7 +42,7 @@ public final class PegasusGuardian extends AdventureCard {
// Rescue the Foal
// Exile target creature you control, then return that card to the battlefield under its owner's control.
this.getSpellCard().getSpellAbility().addEffect(new ExileTargetForSourceEffect());
this.getSpellCard().getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
this.getSpellCard().getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(", then"));
this.getSpellCard().getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
}

View file

@ -1,25 +1,21 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.card.OwnerIdPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetCreaturePermanent;
@ -32,8 +28,13 @@ public final class Reincarnation extends CardImpl {
public Reincarnation(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}{G}");
// Choose target creature. When that creature dies this turn, return a creature card from its owner's graveyard to the battlefield under the control of that creature's owner.
this.getSpellAbility().addEffect(new ReincarnationEffect());
// Choose target creature. When that creature dies this turn, return a creature card
// from its owner's graveyard to the battlefield under the control of that creature's owner.
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
new WhenTargetDiesDelayedTriggeredAbility(new ReincarnationEffect(), SetTargetPointer.CARD),
true,
"Choose target creature. "
));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
@ -50,8 +51,8 @@ public final class Reincarnation extends CardImpl {
class ReincarnationEffect extends OneShotEffect {
public ReincarnationEffect() {
super(Outcome.Benefit);
this.staticText = "Choose target creature. When that creature dies this turn, return a creature card from its owner's graveyard to the battlefield under the control of that creature's owner";
super(Outcome.Detriment);
staticText = "return a creature card from its owner's graveyard to the battlefield under the control of that creature's owner";
}
public ReincarnationEffect(final ReincarnationEffect effect) {
@ -65,94 +66,22 @@ class ReincarnationEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
DelayedTriggeredAbility delayedAbility = new ReincarnationDelayedTriggeredAbility(targetPointer.getFirst(game, source));
game.addDelayedTriggeredAbility(delayedAbility, source);
Player controller = game.getPlayer(source.getControllerId());
Player owner = game.getPlayer(game.getOwnerId(getTargetPointer().getFirst(game, source)));
if (controller == null || owner == null) {
return false;
}
FilterCreatureCard filter = new FilterCreatureCard("a creature card from " + owner.getName() + "'s graveyard");
filter.add(new OwnerIdPredicate(owner.getId()));
TargetCardInGraveyard target = new TargetCardInGraveyard(filter);
target.setNotTarget(true);
if (target.canChoose(controller.getId(), source, game)
&& controller.chooseTarget(outcome, target, source, game)) {
Card card = game.getCard(target.getFirstTarget());
if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null);
}
}
return true;
}
}
class ReincarnationDelayedTriggeredAbility extends DelayedTriggeredAbility {
private UUID target;
public ReincarnationDelayedTriggeredAbility(UUID target) {
super(new ReincarnationDelayedEffect(target), Duration.EndOfTurn);
this.target = target;
}
public ReincarnationDelayedTriggeredAbility(ReincarnationDelayedTriggeredAbility ability) {
super(ability);
this.target = ability.target;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(target)) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.isDiesEvent()) {
return true;
}
}
return false;
}
@Override
public ReincarnationDelayedTriggeredAbility copy() {
return new ReincarnationDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When that creature dies this turn, return a creature card from its owner's graveyard to the battlefield under the control of that creature's owner.";
}
}
class ReincarnationDelayedEffect extends OneShotEffect {
private final UUID target;
public ReincarnationDelayedEffect(UUID target) {
super(Outcome.Detriment);
this.target = target;
this.staticText = "return a creature card from its owner's graveyard to the battlefield under the control of that creature's owner";
}
public ReincarnationDelayedEffect(final ReincarnationDelayedEffect effect) {
super(effect);
this.target = effect.target;
}
@Override
public ReincarnationDelayedEffect copy() {
return new ReincarnationDelayedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = (Permanent) game.getLastKnownInformation(target, Zone.BATTLEFIELD);
if (permanent != null && controller != null) {
Player player = game.getPlayer(permanent.getOwnerId());
if (player != null) {
FilterCreatureCard filter = new FilterCreatureCard("a creature card from " + player.getName() + "'s graveyard");
filter.add(new OwnerIdPredicate(player.getId()));
Target targetCreature = new TargetCardInGraveyard(filter);
targetCreature.setNotTarget(true);
if (targetCreature.canChoose(controller.getId(), source, game)
&& controller.chooseTarget(outcome, targetCreature, source, game)) {
Card card = game.getCard(targetCreature.getFirstTarget());
if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, false, true, null);
}
}
return true;
}
}
return false;
}
}

View file

@ -1,10 +1,8 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.BecomesTappedAttachedTriggeredAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.counter.AddCountersControllerEffect;
import mage.abilities.keyword.EnchantAbility;
@ -13,12 +11,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetArtifactPermanent;
@ -37,7 +30,12 @@ public final class RelicPutrescence extends CardImpl {
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
Ability ability = new EnchantAbility(auraTarget);
this.addAbility(ability);
this.addAbility(new RelicPutrescenceAbility());
// Whenever enchanted artifact becomes tapped, its controller gets a poison counter.
this.addAbility(new BecomesTappedAttachedTriggeredAbility(
new AddCountersControllerEffect(CounterType.POISON.createInstance(), true),
"enchanted artifact"
));
}
public RelicPutrescence (final RelicPutrescence card) {
@ -48,43 +46,4 @@ public final class RelicPutrescence extends CardImpl {
public RelicPutrescence copy() {
return new RelicPutrescence(this);
}
}
class RelicPutrescenceAbility extends TriggeredAbilityImpl {
public RelicPutrescenceAbility() {
super(Zone.BATTLEFIELD, new AddCountersControllerEffect(CounterType.POISON.createInstance(), true));
}
public RelicPutrescenceAbility(final RelicPutrescenceAbility ability) {
super(ability);
}
@Override
public RelicPutrescenceAbility copy() {
return new RelicPutrescenceAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.TAPPED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent enchantment = game.getPermanent(sourceId);
if (enchantment != null && enchantment.getAttachedTo() != null) {
if (event.getTargetId().equals(enchantment.getAttachedTo())) {
return true;
}
}
return false;
}
@Override
public String getRule() {
return "Whenever enchanted artifact becomes tapped, its controller gets a poison counter.";
}
}

View file

@ -5,22 +5,17 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetForSourceEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.TargetPermanent;
/**
*
@ -46,8 +41,9 @@ public final class RestorationAngel extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Restoration Angel enters the battlefield, you may exile target non-Angel creature you control, then return that card to the battlefield under your control
Ability ability = new EntersBattlefieldTriggeredAbility(new RestorationAngelEffect(), true);
ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, false));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect(), true);
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect().concatBy(", then"));
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
@ -60,40 +56,3 @@ public final class RestorationAngel extends CardImpl {
return new RestorationAngel(this);
}
}
class RestorationAngelEffect extends OneShotEffect {
public RestorationAngelEffect() {
super(Outcome.Exile);
staticText = "you may exile target non-Angel creature you control, then return that card to the battlefield under your control";
}
public RestorationAngelEffect(final RestorationAngelEffect effect) {
super(effect);
}
@Override
public RestorationAngelEffect copy() {
return new RestorationAngelEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
if (permanent != null && sourcePermanent != null) {
int zcc = permanent.getZoneChangeCounter(game);
controller.moveCards(permanent, Zone.EXILED, source, game);
Card card = game.getCard(permanent.getId());
if (card != null
&& card.getZoneChangeCounter(game) == zcc + 1
&& game.getState().getZone(card.getId()) == Zone.EXILED) {
return controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
}
}
return false;
}
}

View file

@ -32,7 +32,7 @@ public final class RuinGhost extends CardImpl {
// {W}, {T}: Exile target land you control, then return it to the battlefield under your control.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetForSourceEffect(), new ManaCostsImpl<>("{W}"));
ability.addCost(new TapSourceCost());
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(false));
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(false, "it").concatBy(", then"));
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND));
this.addAbility(ability);
}

View file

@ -1,23 +1,19 @@
package mage.cards.r;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.ComparisonType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.constants.SetTargetPointer;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCreaturePermanent;
@ -32,8 +28,13 @@ public final class RushedRebirth extends CardImpl {
public RushedRebirth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{G}");
// Choose target creature. When that creature dies this turn, search your library for a creature card with lesser mana value, put it onto the battlefield tapped, then shuffle.
this.getSpellAbility().addEffect(new RushedRebirthEffect());
// Choose target creature. When that creature dies this turn, search your library for a
// creature card with lesser mana value, put it onto the battlefield tapped, then shuffle.
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
new WhenTargetDiesDelayedTriggeredAbility(new RushedRebirthEffect(), SetTargetPointer.PERMANENT),
true,
"Choose target creature. "
));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
@ -50,9 +51,8 @@ public final class RushedRebirth extends CardImpl {
class RushedRebirthEffect extends OneShotEffect {
RushedRebirthEffect() {
super(Outcome.Benefit);
staticText = "choose target creature. When that creature dies this turn, " +
"search your library for a creature card with lesser mana value, " +
super(Outcome.PutCreatureInPlay);
staticText = "search your library for a creature card with lesser mana value, " +
"put it onto the battlefield tapped, then shuffle";
}
@ -67,71 +67,12 @@ class RushedRebirthEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
if (permanent == null) {
return false;
}
game.addDelayedTriggeredAbility(new RushedRebirthDelayedTriggeredAbility(permanent, game), source);
return true;
FilterCreatureCard filter = new FilterCreatureCard("creature card with lesser mana value than " + permanent.getIdName());
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, permanent.getManaValue()));
return new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true).apply(game, source);
}
}
class RushedRebirthDelayedTriggeredAbility extends DelayedTriggeredAbility {
private static final class RushedRebirthPredicate implements Predicate<Card> {
private final Permanent permanent;
private RushedRebirthPredicate(Permanent permanent) {
this.permanent = permanent;
}
@Override
public boolean apply(Card input, Game game) {
return input.getManaValue() < permanent.getManaValue();
}
}
private final MageObjectReference mor;
RushedRebirthDelayedTriggeredAbility(Permanent permanent, Game game) {
super(makeEffect(permanent), Duration.EndOfTurn, false, false);
this.mor = new MageObjectReference(permanent, game);
}
private RushedRebirthDelayedTriggeredAbility(final RushedRebirthDelayedTriggeredAbility ability) {
super(ability);
this.mor = ability.mor;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
return zEvent.isDiesEvent() && mor.refersTo(zEvent.getTarget(), game);
}
private static Effect makeEffect(Permanent permanent) {
FilterCard filter = new FilterCreatureCard(
"creature card with lesser mana value than " + permanent.getIdName()
);
filter.add(new RushedRebirthPredicate(permanent));
return new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true);
}
@Override
public RushedRebirthDelayedTriggeredAbility copy() {
return new RushedRebirthDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When that creature dies this turn, search your library for a creature card " +
"with lesser mana value, put it onto the battlefield tapped, then shuffle.";
}
}

View file

@ -1,7 +1,7 @@
package mage.cards.s;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@ -39,7 +39,7 @@ public final class SacredGround extends CardImpl {
class SacredGroundTriggeredAbility extends TriggeredAbilityImpl {
SacredGroundTriggeredAbility() {
super(Zone.BATTLEFIELD, new ReturnToBattlefieldUnderYourControlTargetEffect());
super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect());
}
SacredGroundTriggeredAbility(final SacredGroundTriggeredAbility ability) {
@ -60,10 +60,10 @@ class SacredGroundTriggeredAbility extends TriggeredAbilityImpl {
public boolean checkTrigger(GameEvent event, Game game) {
if (game.getOpponents(this.getControllerId()).contains(game.getControllerId(event.getSourceId()))) {
ZoneChangeEvent zce = (ZoneChangeEvent) event;
if (Zone.BATTLEFIELD == zce.getFromZone() && Zone.GRAVEYARD == zce.getToZone()) {
if (zce.isDiesEvent()) {
Permanent targetPermanent = zce.getTarget();
if (targetPermanent.isLand(game) && targetPermanent.isControlledBy(getControllerId())) {
getEffects().get(0).setTargetPointer(new FixedTarget(targetPermanent.getId(), game.getState().getZoneChangeCounter(targetPermanent.getId())));
if (targetPermanent.isLand(game) && targetPermanent.isOwnedBy(getControllerId())) {
getEffects().get(0).setTargetPointer(new FixedTarget(targetPermanent, game));
return true;
}
}

View file

@ -1,45 +1,43 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterCreaturePermanent;
import mage.constants.CardType;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author Plopman
* @author awjackson
*/
public final class SaffiEriksdotter extends CardImpl {
public SaffiEriksdotter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SCOUT);
this.subtype.add(SubType.HUMAN, SubType.SCOUT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Sacrifice Saffi Eriksdotter: When target creature is put into your graveyard from the battlefield this turn, return that card to the battlefield.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SaffiEriksdotterEffect(), new SacrificeSourceCost());
Target target = new TargetCreaturePermanent(new FilterCreaturePermanent());
ability.addTarget(target);
Ability ability = new SimpleActivatedAbility(
new CreateDelayedTriggeredAbilityEffect(new SaffiEriksdotterDelayedTriggeredAbility()),
new SacrificeSourceCost()
);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
@ -53,44 +51,15 @@ public final class SaffiEriksdotter extends CardImpl {
}
}
class SaffiEriksdotterEffect extends OneShotEffect {
class SaffiEriksdotterDelayedTriggeredAbility extends WhenTargetDiesDelayedTriggeredAbility {
public SaffiEriksdotterEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "When target creature is put into your graveyard this turn, return that card to the battlefield";
}
public SaffiEriksdotterEffect(final SaffiEriksdotterEffect effect) {
super(effect);
}
@Override
public SaffiEriksdotterEffect copy() {
return new SaffiEriksdotterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
DelayedTriggeredAbility delayedAbility = new SaffiEriksdotterDelayedTriggeredAbility(new FixedTarget(this.getTargetPointer().getFirst(game, source)));
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
}
class SaffiEriksdotterDelayedTriggeredAbility extends DelayedTriggeredAbility {
protected FixedTarget fixedTarget;
public SaffiEriksdotterDelayedTriggeredAbility(FixedTarget fixedTarget) {
super(new ReturnToBattlefieldUnderYourControlTargetEffect(), Duration.EndOfTurn);
this.getEffects().get(0).setTargetPointer(fixedTarget);
this.fixedTarget = fixedTarget;
public SaffiEriksdotterDelayedTriggeredAbility() {
super(new ReturnFromGraveyardToBattlefieldTargetEffect().setText("return that card to the battlefield"), SetTargetPointer.CARD);
setTriggerPhrase("When target creature is put into your graveyard from the battlefield this turn, ");
}
public SaffiEriksdotterDelayedTriggeredAbility(final SaffiEriksdotterDelayedTriggeredAbility ability) {
private SaffiEriksdotterDelayedTriggeredAbility(final SaffiEriksdotterDelayedTriggeredAbility ability) {
super(ability);
this.fixedTarget = ability.fixedTarget;
}
@Override
@ -98,20 +67,8 @@ class SaffiEriksdotterDelayedTriggeredAbility extends DelayedTriggeredAbility {
return new SaffiEriksdotterDelayedTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (((ZoneChangeEvent) event).isDiesEvent()) {
if (fixedTarget.getFirst(game, this).equals(event.getTargetId())) {
if (this.isControlledBy(event.getPlayerId())) {
return true;
}
}
}
return false;
return this.isControlledBy(game.getOwnerId(event.getTargetId())) && super.checkTrigger(event, game);
}
}

View file

@ -1,27 +1,23 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DestroySourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.IslandwalkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.PermanentIdPredicate;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author MarcoMarin
* @author awjackson
*/
public final class SandalsOfAbdallah extends CardImpl {
@ -29,18 +25,13 @@ public final class SandalsOfAbdallah extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
// {2}, {tap}: Target creature gains islandwalk until end of turn. When that creature dies this turn, destroy Sandals of Abdallah.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilityTargetEffect(new IslandwalkAbility(), Duration.EndOfTurn), new ManaCostsImpl<>("{2}"));
Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(new IslandwalkAbility()), new GenericManaCost(2));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(
new WhenTargetDiesDelayedTriggeredAbility(new DestroySourceEffect())
));
this.addAbility(ability);
//If the following doesn work, Alternatively do //Target target = ability.getTargets()
//target.setTargetTag(1);
//then later do: filter.add(new AnotherTargetPredicate(1));
FilterCreaturePermanent filter = new FilterCreaturePermanent();
//hopefully a null pointer wont break anything before the ability is activated :-S
filter.add(new PermanentIdPredicate(ability.getFirstTarget()));
this.addAbility(new DiesCreatureTriggeredAbility(new SacrificeSourceEffect(), false, filter, true));
}
private SandalsOfAbdallah(final SandalsOfAbdallah card) {

View file

@ -1,22 +1,12 @@
package mage.cards.s;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.constants.SetTargetPointer;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
@ -30,7 +20,13 @@ public final class SearingBlood extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{R}");
// Searing Blood deals 2 damage to target creature. When that creature dies this turn, Searing Blood deals 3 damage to that creature's controller.
this.getSpellAbility().addEffect(new SearingBloodEffect());
this.getSpellAbility().addEffect(new DamageTargetEffect(2));
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
new WhenTargetDiesDelayedTriggeredAbility(
new DamageTargetEffect(3, true, "that creature's controller"),
SetTargetPointer.PLAYER
)
));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
@ -43,101 +39,3 @@ public final class SearingBlood extends CardImpl {
return new SearingBlood(this);
}
}
class SearingBloodEffect extends OneShotEffect {
public SearingBloodEffect() {
super(Outcome.Damage);
this.staticText = "{this} deals 2 damage to target creature. When that creature dies this turn, {this} deals 3 damage to that creature's controller";
}
public SearingBloodEffect(final SearingBloodEffect effect) {
super(effect);
}
@Override
public SearingBloodEffect copy() {
return new SearingBloodEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
DelayedTriggeredAbility delayedAbility = new SearingBloodDelayedTriggeredAbility(source.getFirstTarget());
game.addDelayedTriggeredAbility(delayedAbility, source);
return new DamageTargetEffect(2).apply(game, source);
}
}
class SearingBloodDelayedTriggeredAbility extends DelayedTriggeredAbility {
private UUID target;
public SearingBloodDelayedTriggeredAbility(UUID target) {
super(new SearingBloodDelayedEffect(target), Duration.EndOfTurn);
this.target = target;
}
public SearingBloodDelayedTriggeredAbility(SearingBloodDelayedTriggeredAbility ability) {
super(ability);
this.target = ability.target;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(target)) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
return zEvent.isDiesEvent();
}
return false;
}
@Override
public SearingBloodDelayedTriggeredAbility copy() {
return new SearingBloodDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When that creature dies this turn, {this} deals 3 damage to that creature's controller.";
}
}
class SearingBloodDelayedEffect extends OneShotEffect {
protected UUID target;
public SearingBloodDelayedEffect(UUID target) {
super(Outcome.Damage);
this.target = target;
}
public SearingBloodDelayedEffect(final SearingBloodDelayedEffect effect) {
super(effect);
this.target = effect.target;
}
@Override
public SearingBloodDelayedEffect copy() {
return new SearingBloodDelayedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = (Permanent) game.getLastKnownInformation(target, Zone.BATTLEFIELD);
if (permanent != null) {
Player player = game.getPlayer(permanent.getControllerId());
if (player != null) {
MageObject sourceObject = source.getSourceObject(game);
player.damage(3, source.getSourceId(), source, game);
return true;
}
}
return false;
}
}

View file

@ -31,7 +31,7 @@ public final class SettleBeyondReality extends CardImpl {
// Exile target creature you control, then return it to the battlefield under its owner's control.
Mode mode = new Mode(new ExileTargetForSourceEffect());
mode.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
mode.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
mode.addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addMode(mode);
}

View file

@ -68,7 +68,6 @@ class SkybindEffect extends OneShotEffect {
if (permanent.moveToExile(source.getSourceId(), sourcePermanent.getName(), source, game)) {
//create delayed triggered ability
Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false);
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;

View file

@ -28,7 +28,7 @@ public final class SoulCollector extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever a creature dealt damage by Soul Collector this turn dies, return that card to the battlefield under your control.
this.addAbility(new DealtDamageAndDiedTriggeredAbility(new ReturnToBattlefieldUnderYourControlTargetEffect().setText("return that card to the battlefield under your control")));
this.addAbility(new DealtDamageAndDiedTriggeredAbility(new ReturnToBattlefieldUnderYourControlTargetEffect()));
// Morph {B}{B}{B}
this.addAbility(new MorphAbility(new ManaCostsImpl<>("{B}{B}{B}")));

View file

@ -50,7 +50,7 @@ public final class Soulherder extends CardImpl {
Ability ability = new BeginningOfEndStepTriggeredAbility(
new ExileTargetForSourceEffect(), TargetController.YOU, true
);
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(", then"));
ability.addTarget(new TargetControlledCreaturePermanent(filter));
this.addAbility(ability);
}

View file

@ -69,7 +69,7 @@ class SuddenDisappearanceEffect extends OneShotEffect {
targets.add(card.getId());
}
Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, true);
effect.setText("Return the exiled cards to the battlefield under their owner's control at the beginning of the next end step");
effect.setText("Return the exiled cards to the battlefield under their owner's control");
effect.setTargetPointer(new FixedTargets(targets, game));
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source);
}

View file

@ -34,7 +34,7 @@ public final class TeleportationCircle extends CardImpl {
// At the beginning of your end step, exile up to one target artifact or creature you control, then return that card to the battlefield under its owner's control.
Ability ability = new BeginningOfYourEndStepTriggeredAbility(new ExileTargetForSourceEffect(), false);
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(", then"));
ability.addTarget(new TargetPermanent(0, 1, filter));
this.addAbility(ability);
}

View file

@ -59,7 +59,7 @@ public final class ThassaDeepDwelling extends CardImpl {
new ExileTargetForSourceEffect(),
TargetController.YOU, false
);
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect());
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect().concatBy(", then"));
ability.addTarget(new TargetPermanent(
0, 1, filterOther, false
));

View file

@ -44,7 +44,7 @@ public final class TheRavensWarning extends CardImpl {
// II Whenever one or more creatures you control with flying deal combat damage to a player this turn,
// look at that player's hand and draw a card.
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_II, new CreateDelayedTriggeredAbilityEffect(
new TheRavensWarningTriggeredAbility(), false, false
new TheRavensWarningTriggeredAbility(), false
));
// III You may put a card you own from outside the game on top of your library.

View file

@ -8,7 +8,7 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.Card;
@ -105,7 +105,7 @@ class ThunderkinAwakenerEffect extends OneShotEffect {
if (controller != null && creatureCard != null) {
// Return that card to the battlefield tapped and attacking
Effect effect = new ReturnToBattlefieldUnderYourControlTargetEffect(false, true, true);
Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect(true, true);
effect.setTargetPointer(new FixedTarget(creatureCard.getId()));
effect.apply(game, source);

View file

@ -1,35 +1,23 @@
package mage.cards.t;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.FightTargetsEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
/**
* Time to Feed has two targets: a creature an opponent controls and a creature you control.
* If only one of those creatures is a legal target when Time to Feed tries to resolve, the
* creatures won't fight and neither will deal or be dealt damage. However, you'll still gain
* 3 life when the creature you don't control dies that turn, even if it was the illegal target as Time to Feed resolved.
* If only one of those creatures is a legal target when Time to Feed tries to resolve,
* the creatures won't fight and neither will deal or be dealt damage. If the creature
* you don't control is the illegal target, you won't gain life when it dies.
* If neither creature is a legal target when Time to Feed tries to resolve, the spell will
* be countered and none of its effects will happen.
* If the first target creature dies that turn, you'll gain 3 life no matter what caused the creature to die or who controls the creature at that time.
@ -41,19 +29,20 @@ public final class TimeToFeed extends CardImpl {
public TimeToFeed(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}");
// Choose target creature an opponent controls. When that creature dies this turn, you gain 3 life.
this.getSpellAbility().addEffect(new TimeToFeedTextEffect());
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
new WhenTargetDiesDelayedTriggeredAbility(new GainLifeEffect(3)),
true,
"Choose target creature an opponent controls. "
));
// Target creature you control fights that creature.
Effect effect = new FightTargetsEffect();
effect.setText("Target creature you control fights that creature. " +
"<i>(Each deals damage equal to its power to the other.)</i>");
this.getSpellAbility().addEffect(effect);
Target target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE);
this.getSpellAbility().addTarget(target);
this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
}
private TimeToFeed(final TimeToFeed card) {
@ -65,70 +54,3 @@ public final class TimeToFeed extends CardImpl {
return new TimeToFeed(this);
}
}
class TimeToFeedTextEffect extends OneShotEffect {
public TimeToFeedTextEffect() {
super(Outcome.Detriment);
this.staticText = "Choose target creature an opponent controls. When that creature dies this turn, you gain 3 life";
}
public TimeToFeedTextEffect(final TimeToFeedTextEffect effect) {
super(effect);
}
@Override
public TimeToFeedTextEffect copy() {
return new TimeToFeedTextEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent creature = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (creature == null) {
return false;
}
DelayedTriggeredAbility ability = new TimeToFeedDiesTriggeredAbility(creature.getId(), creature.getZoneChangeCounter(game));
new CreateDelayedTriggeredAbilityEffect(ability, false).apply(game, source);
return true;
}
}
class TimeToFeedDiesTriggeredAbility extends DelayedTriggeredAbility {
private final UUID watchedCreatureId;
private final int zoneChangeCounter;
public TimeToFeedDiesTriggeredAbility(UUID watchedCreatureId, int zoneChangeCounter) {
super(new GainLifeEffect(3), Duration.EndOfTurn, false);
this.watchedCreatureId = watchedCreatureId;
this.zoneChangeCounter = zoneChangeCounter;
setTriggerPhrase("When that creature dies this turn, ");
}
public TimeToFeedDiesTriggeredAbility(final TimeToFeedDiesTriggeredAbility ability) {
super(ability);
this.watchedCreatureId = ability.watchedCreatureId;
this.zoneChangeCounter = ability.zoneChangeCounter;
}
@Override
public TimeToFeedDiesTriggeredAbility copy() {
return new TimeToFeedDiesTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!((ZoneChangeEvent) event).isDiesEvent() || !event.getTargetId().equals(watchedCreatureId)) {
return false;
}
Permanent creature = (Permanent) game.getLastKnownInformation(watchedCreatureId, Zone.BATTLEFIELD);
return creature.getZoneChangeCounter(game) == this.zoneChangeCounter;
}
}

View file

@ -1,26 +1,19 @@
package mage.cards.t;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.abilities.keyword.SupportAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.constants.SetTargetPointer;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.CounterAnyPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.target.TargetPermanent;
import java.util.UUID;
@ -42,8 +35,18 @@ public final class TogetherForever extends CardImpl {
this.addAbility(new SupportAbility(this, 2, false));
// {1}: Choose target creature with a counter on it. When that creature dies this turn, return that card to its owner's hand.
Ability ability = new SimpleActivatedAbility(new TogetherForeverEffect(), new GenericManaCost(1));
ability.addTarget(new TargetCreaturePermanent(filter));
Ability ability = new SimpleActivatedAbility(
new CreateDelayedTriggeredAbilityEffect(
new WhenTargetDiesDelayedTriggeredAbility(
new ReturnFromGraveyardToHandTargetEffect()
.setText("return that card to its owner's hand"),
SetTargetPointer.CARD
),
true, "Choose target creature with a counter on it. "
),
new GenericManaCost(1)
);
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
@ -56,107 +59,3 @@ public final class TogetherForever extends CardImpl {
return new TogetherForever(this);
}
}
class TogetherForeverEffect extends OneShotEffect {
public TogetherForeverEffect() {
super(Outcome.Benefit);
this.staticText = "Choose target creature with a counter on it. When that creature dies this turn, return that card to its owner's hand.";
}
public TogetherForeverEffect(final TogetherForeverEffect effect) {
super(effect);
}
@Override
public TogetherForeverEffect copy() {
return new TogetherForeverEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
DelayedTriggeredAbility delayedAbility = new TogetherForeverDelayedTriggeredAbility(targetPointer.getFirst(game, source));
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
}
class TogetherForeverDelayedTriggeredAbility extends DelayedTriggeredAbility {
private UUID target;
public TogetherForeverDelayedTriggeredAbility(UUID target) {
super(new TogetherForeverDelayedEffect(target), Duration.EndOfTurn);
this.target = target;
}
public TogetherForeverDelayedTriggeredAbility(TogetherForeverDelayedTriggeredAbility ability) {
super(ability);
this.target = ability.target;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(target)) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.isDiesEvent()) {
return true;
}
}
return false;
}
@Override
public TogetherForeverDelayedTriggeredAbility copy() {
return new TogetherForeverDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When that creature dies this turn, return that card to its owner's hand";
}
}
class TogetherForeverDelayedEffect extends OneShotEffect {
private final UUID target;
public TogetherForeverDelayedEffect(UUID target) {
super(Outcome.PutCreatureInPlay);
this.target = target;
this.staticText = "return that card to its owner's hand";
}
public TogetherForeverDelayedEffect(final TogetherForeverDelayedEffect effect) {
super(effect);
this.target = effect.target;
}
@Override
public TogetherForeverDelayedEffect copy() {
return new TogetherForeverDelayedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = (Permanent) game.getLastKnownInformation(target, Zone.BATTLEFIELD);
if (controller != null
&& permanent != null) {
Player player = game.getPlayer(permanent.getOwnerId());
if (player != null) {
Card card = game.getCard(target);
if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) {
return player.moveCards(card, Zone.HAND, source, game);
}
return true;
}
}
return false;
}
}

View file

@ -8,7 +8,7 @@ import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.keyword.HasteAbility;
@ -18,7 +18,7 @@ import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.common.FilterCreatureCard;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
@ -37,17 +37,15 @@ public final class TorrentOfSouls extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B/R}");
// Return up to one target creature card from your graveyard to the battlefield if {B} was spent to cast Torrent of Souls. Creatures target player controls get +2/+0 and gain haste until end of turn if {R} was spent to cast Torrent of Souls.
Target targetCreature = new TargetCardInYourGraveyard(0, 1, new FilterCreatureCard("target creature card in your graveyard"));
Target targetPlayer = new TargetPlayer();
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new ReturnToBattlefieldUnderYourControlTargetEffect(),
new ReturnFromGraveyardToBattlefieldTargetEffect(),
ManaWasSpentCondition.BLACK, "Return up to one target creature card from your graveyard to the battlefield if {B} was spent to cast this spell"));
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new TorrentOfSoulsEffect(),
ManaWasSpentCondition.RED, "Creatures target player controls get +2/+0 and gain haste until end of turn if {R} was spent to cast this spell"));
this.getSpellAbility().addTarget(targetCreature);
this.getSpellAbility().addTarget(targetPlayer);
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 1, StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD));
this.getSpellAbility().addTarget(new TargetPlayer());
this.getSpellAbility().addEffect(new InfoEffect("<i>(Do both if {B}{R} was spent.)</i>"));

View file

@ -58,7 +58,7 @@ public final class TriadOfFates extends CardImpl {
ability.addCost(new TapSourceCost());
target = new TargetCreaturePermanent(filterCounter);
ability.addTarget(target);
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false, "it").concatBy(", then"));
this.addAbility(ability);
// {B}, {T}: Exile target creature that has a fate counter on it. Its controller draws two cards.

View file

@ -1,23 +1,14 @@
package mage.cards.v;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.constants.SetTargetPointer;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
/**
@ -30,10 +21,13 @@ public final class VirulentWound extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}");
// Put a -1/-1 counter on target creature.
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.M1M1.createInstance(), Outcome.UnboostCreature));
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.M1M1.createInstance()));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
// When that creature dies this turn, its controller gets a poison counter.
this.getSpellAbility().addEffect(new VirulentWoundEffect());
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new WhenTargetDiesDelayedTriggeredAbility(
new AddCountersTargetEffect(CounterType.POISON.createInstance()).setText("its controller gets a poison counter"),
SetTargetPointer.PLAYER
)));
}
private VirulentWound(final VirulentWound card) {
@ -45,100 +39,3 @@ public final class VirulentWound extends CardImpl {
return new VirulentWound(this);
}
}
class VirulentWoundEffect extends OneShotEffect {
public VirulentWoundEffect() {
super(Outcome.UnboostCreature);
this.staticText = "When that creature dies this turn, its controller gets a poison counter";
}
public VirulentWoundEffect(final VirulentWoundEffect effect) {
super(effect);
}
@Override
public VirulentWoundEffect copy() {
return new VirulentWoundEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
game.addDelayedTriggeredAbility(new VirulentWoundDelayedTriggeredAbility(source.getFirstTarget()), source);
return true;
}
}
class VirulentWoundDelayedTriggeredAbility extends DelayedTriggeredAbility {
private UUID target;
public VirulentWoundDelayedTriggeredAbility(UUID target) {
super(new VirulentWoundDelayedEffect(target), Duration.EndOfTurn);
this.target = target;
}
public VirulentWoundDelayedTriggeredAbility(VirulentWoundDelayedTriggeredAbility ability) {
super(ability);
this.target = ability.target;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(target)) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.isDiesEvent()) {
return true;
}
}
return false;
}
@Override
public VirulentWoundDelayedTriggeredAbility copy() {
return new VirulentWoundDelayedTriggeredAbility(this);
}
@Override
public String getRule() {
return "When that creature dies this turn, its controller gets a poison counter.";
}
}
class VirulentWoundDelayedEffect extends OneShotEffect {
protected UUID target;
public VirulentWoundDelayedEffect(UUID target) {
super(Outcome.Damage);
this.target = target;
}
public VirulentWoundDelayedEffect(final VirulentWoundDelayedEffect effect) {
super(effect);
this.target = effect.target;
}
@Override
public VirulentWoundDelayedEffect copy() {
return new VirulentWoundDelayedEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = (Permanent) game.getLastKnownInformation(target, Zone.BATTLEFIELD);
if (permanent != null) {
Player player = game.getPlayer(permanent.getControllerId());
if (player != null) {
player.addCounters(CounterType.POISON.createInstance(1), source.getControllerId(), source, game);
return true;
}
}
return false;
}
}

View file

@ -28,7 +28,7 @@ public final class WickerWarcrawler extends CardImpl {
this.addAbility(new AttacksOrBlocksTriggeredAbility(
new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(
new AddCountersSourceEffect(CounterType.M1M1.createInstance(), true)
), false, false).setText("put a -1/-1 counter on it at end of combat"), false
), false).setText("put a -1/-1 counter on it at end of combat"), false
).setTriggerPhrase("Whenever {this} attacks or blocks, "));
}

View file

@ -38,7 +38,7 @@ public final class WispweaverAngel extends CardImpl {
// When Wispweaver Angel enters the battlefield, you may exile another target creature you control, then return that card to the battlefield under its owner's control.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect(), true);
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false));
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(", then"));
ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, false));
this.addAbility(ability);
}

View file

@ -2,9 +2,8 @@ package mage.cards.x;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.common.delayed.WhenTargetDiesDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
@ -13,10 +12,7 @@ import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
@ -24,6 +20,7 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.XiraBlackInsectToken;
import mage.target.TargetPermanent;
@ -47,8 +44,7 @@ public final class XiraTheGoldenSting extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}{G}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.INSECT);
this.subtype.add(SubType.ASSASSIN);
this.subtype.add(SubType.INSECT, SubType.ASSASSIN);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
@ -58,11 +54,10 @@ public final class XiraTheGoldenSting extends CardImpl {
// Haste
this.addAbility(HasteAbility.getInstance());
// Whenever Xira, the Golden Sting attacks, put an egg counter on another target creature without an egg counter on it. When that creature dies, if it has an egg counter on it, draw a card and create a 1/1 black Insect creature token with flying.
// Whenever Xira, the Golden Sting attacks, put an egg counter on another target creature without an egg counter on it.
// When that creature dies, if it has an egg counter on it, draw a card and create a 1/1 black Insect creature token with flying.
Ability ability = new AttacksTriggeredAbility(new AddCountersTargetEffect(CounterType.EGG.createInstance()));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(
new XiraTheGoldenStingTriggeredAbility(), true
));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new XiraTheGoldenStingTriggeredAbility()));
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
@ -77,11 +72,12 @@ public final class XiraTheGoldenSting extends CardImpl {
}
}
class XiraTheGoldenStingTriggeredAbility extends DelayedTriggeredAbility {
class XiraTheGoldenStingTriggeredAbility extends WhenTargetDiesDelayedTriggeredAbility {
XiraTheGoldenStingTriggeredAbility() {
super(new DrawCardSourceControllerEffect(1), Duration.Custom, true, false);
this.addEffect(new CreateTokenEffect(new XiraBlackInsectToken()));
super(new DrawCardSourceControllerEffect(1), Duration.Custom, SetTargetPointer.NONE);
this.addEffect(new CreateTokenEffect(new XiraBlackInsectToken()).concatBy("and"));
setTriggerPhrase("When that creature dies, if it has an egg counter on it, ");
}
private XiraTheGoldenStingTriggeredAbility(final XiraTheGoldenStingTriggeredAbility ability) {
@ -93,27 +89,15 @@ class XiraTheGoldenStingTriggeredAbility extends DelayedTriggeredAbility {
return new XiraTheGoldenStingTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (this.getEffects()
.stream()
.map(Effect::getTargetPointer)
.map(targetPointer -> targetPointer.getFirst(game, this))
.noneMatch(event.getTargetId()::equals)) {
return false;
}
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
return permanent != null && permanent.getCounters(game).containsKey(CounterType.EGG);
Permanent permanent = ((ZoneChangeEvent) event).getTarget();
return permanent != null && permanent.getCounters(game).containsKey(CounterType.EGG) && super.checkTrigger(event, game);
}
@Override
public String getRule() {
return "When that creature dies, if it has an egg counter on it, " +
"draw a card and create a 1/1 black Insect creature token with flying.";
public boolean isInactive(Game game) {
int zccdiff = game.getState().getZoneChangeCounter(mor.getSourceId()) - mor.getZoneChangeCounter();
return zccdiff > 1 || zccdiff > 0 && game.getState().getZone(mor.getSourceId()) != Zone.GRAVEYARD;
}
}

View file

@ -56,14 +56,7 @@ public abstract class DelayedTriggeredAbility extends TriggeredAbilityImpl {
*
* @param game
*/
public void initOnAdding(Game game) {
}
public void init(Game game) {
for (Effect effect : this.getEffects()) {
effect.getTargetPointer().init(game, this);
}
}
public boolean isInactive(Game game) {

View file

@ -0,0 +1,84 @@
package mage.abilities.common.delayed;
import mage.MageObjectReference;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.constants.Duration;
import mage.constants.SetTargetPointer;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
/**
* @author awjackson
*/
public class WhenTargetDiesDelayedTriggeredAbility extends DelayedTriggeredAbility {
protected MageObjectReference mor;
private final SetTargetPointer setTargetPointer;
public WhenTargetDiesDelayedTriggeredAbility(Effect effect) {
this(effect, SetTargetPointer.NONE);
}
public WhenTargetDiesDelayedTriggeredAbility(Effect effect, SetTargetPointer setTargetPointer) {
this(effect, Duration.EndOfTurn, setTargetPointer);
}
public WhenTargetDiesDelayedTriggeredAbility(Effect effect, Duration duration, SetTargetPointer setTargetPointer) {
super(effect, duration, true);
this.setTargetPointer = setTargetPointer;
setTriggerPhrase("When that creature dies" + (duration == Duration.EndOfTurn ? " this turn, " : ", "));
}
public WhenTargetDiesDelayedTriggeredAbility(final WhenTargetDiesDelayedTriggeredAbility ability) {
super(ability);
this.mor = ability.mor;
this.setTargetPointer = ability.setTargetPointer;
}
@Override
public WhenTargetDiesDelayedTriggeredAbility copy() {
return new WhenTargetDiesDelayedTriggeredAbility(this);
}
@Override
public void init(Game game) {
mor = new MageObjectReference(getFirstTarget(), game);
getTargets().clear();
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (!zEvent.isDiesEvent()) {
return false;
}
Permanent permanent = zEvent.getTarget();
if (mor == null || !mor.refersTo(permanent, game)) {
return false;
}
switch (setTargetPointer) {
case CARD:
// card in graveyard
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
break;
case PERMANENT:
// LKI of permanent
getEffects().setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game)));
break;
case PLAYER:
// LKI permanent's controller
getEffects().setTargetPointer(new FixedTarget(permanent.getControllerId()));
break;
}
return true;
}
}

View file

@ -14,28 +14,28 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect {
protected DelayedTriggeredAbility ability;
protected boolean copyTargets;
protected boolean initAbility;
protected String rulePrefix;
public CreateDelayedTriggeredAbilityEffect(DelayedTriggeredAbility ability) {
this(ability, true);
}
public CreateDelayedTriggeredAbilityEffect(DelayedTriggeredAbility ability, boolean copyTargets) {
this(ability, copyTargets, false);
this(ability, copyTargets, "");
}
public CreateDelayedTriggeredAbilityEffect(DelayedTriggeredAbility ability, boolean copyTargets, boolean initAbility) {
public CreateDelayedTriggeredAbilityEffect(DelayedTriggeredAbility ability, boolean copyTargets, String rulePrefix) {
super(ability.getEffects().getOutcome(ability));
this.ability = ability;
this.copyTargets = copyTargets;
this.initAbility = initAbility;
this.rulePrefix = rulePrefix;
}
public CreateDelayedTriggeredAbilityEffect(final CreateDelayedTriggeredAbilityEffect effect) {
super(effect);
this.ability = effect.ability.copy();
this.copyTargets = effect.copyTargets;
this.initAbility = effect.initAbility;
this.rulePrefix = effect.rulePrefix;
}
@Override
@ -56,9 +56,6 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect {
}
}
}
if (initAbility) {
delayedAbility.init(game);
}
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
@ -69,7 +66,7 @@ public class CreateDelayedTriggeredAbilityEffect extends OneShotEffect {
return staticText;
}
if (ability.getRuleVisible()) {
return ability.getRule();
return rulePrefix + ability.getRule();
} else {
return "";
}

View file

@ -20,8 +20,6 @@ public class ReturnToBattlefieldUnderOwnerControlTargetEffect extends OneShotEff
private boolean tapped;
protected boolean returnFromExileZoneOnly;
private String returnName = "that card";
private String returnUnderControlName = "its owner's";
/**
* @param returnFromExileZoneOnly see https://github.com/magefree/mage/issues/5151
@ -29,28 +27,20 @@ public class ReturnToBattlefieldUnderOwnerControlTargetEffect extends OneShotEff
* return exiled card - true
*/
public ReturnToBattlefieldUnderOwnerControlTargetEffect(boolean tapped, boolean returnFromExileZoneOnly) {
this(tapped, returnFromExileZoneOnly, "that card");
}
public ReturnToBattlefieldUnderOwnerControlTargetEffect(boolean tapped, boolean returnFromExileZoneOnly, String description) {
super(Outcome.Benefit);
this.tapped = tapped;
this.returnFromExileZoneOnly = returnFromExileZoneOnly;
updateText();
staticText = "return " + description + " to the battlefield " + (tapped ? "tapped " : "") + "under its owner's control";
}
public ReturnToBattlefieldUnderOwnerControlTargetEffect(final ReturnToBattlefieldUnderOwnerControlTargetEffect effect) {
super(effect);
this.tapped = effect.tapped;
this.returnFromExileZoneOnly = effect.returnFromExileZoneOnly;
this.returnName = effect.returnName;
this.returnUnderControlName = effect.returnUnderControlName;
updateText();
}
// TODO: This does not generate correct text, the ", then" should be from .concatBy, see Angelic Renewal for a card with incorrect text
private void updateText() {
this.staticText = ", then return " + this.returnName
+ " to the battlefield" + (tapped ? " tapped" : "")
+ " under " + this.returnUnderControlName + " control";
}
@Override
@ -92,11 +82,4 @@ public class ReturnToBattlefieldUnderOwnerControlTargetEffect extends OneShotEff
}
return false;
}
public ReturnToBattlefieldUnderOwnerControlTargetEffect withReturnNames(String returnName, String returnUnderControlName) {
this.returnName = returnName;
this.returnUnderControlName = returnUnderControlName;
updateText();
return this;
}
}

View file

@ -20,17 +20,13 @@ import java.util.UUID;
public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffect {
private boolean returnFromExileZoneOnly;
private boolean tapped;
private boolean attacking;
private String returnName = "that card";
private String returnUnderControlName = "your";
public ReturnToBattlefieldUnderYourControlTargetEffect() {
this(false);
}
public ReturnToBattlefieldUnderYourControlTargetEffect(boolean returnFromExileZoneOnly) {
this(returnFromExileZoneOnly, false, false);
this(returnFromExileZoneOnly, "that card");
}
/**
@ -38,31 +34,15 @@ public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffe
* return it or that card - false
* return exiled card - true
*/
public ReturnToBattlefieldUnderYourControlTargetEffect(boolean returnFromExileZoneOnly, boolean tapped, boolean attacking) {
public ReturnToBattlefieldUnderYourControlTargetEffect(boolean returnFromExileZoneOnly, String description) {
super(Outcome.Benefit);
this.returnFromExileZoneOnly = returnFromExileZoneOnly;
this.tapped = tapped;
this.attacking = attacking;
updateText();
staticText = "return " + description + " to the battlefield under your control";
}
public ReturnToBattlefieldUnderYourControlTargetEffect(final ReturnToBattlefieldUnderYourControlTargetEffect effect) {
super(effect);
this.returnFromExileZoneOnly = effect.returnFromExileZoneOnly;
this.tapped = effect.tapped;
this.attacking = effect.attacking;
this.returnName = effect.returnName;
this.returnUnderControlName = effect.returnUnderControlName;
updateText();
}
private void updateText() {
this.staticText = ", then return " + returnName + " to the battlefield under " + returnUnderControlName + " control"
+ (tapped ? " tapped" : "")
+ (tapped && attacking ? " and" : "")
+ (attacking ? " attacking" : "");
}
@Override
@ -98,23 +78,11 @@ public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffe
} else {
cardsToBattlefield.addAll(getTargetPointer().getTargets(game, source));
}
for (Card card : cardsToBattlefield.getCards(game)) {
if (controller.moveCards(card, Zone.BATTLEFIELD, source, game, tapped, false, false, null)) {
if (attacking) {
game.getCombat().addAttackingCreature(card.getId(), game);
}
}
if (!cardsToBattlefield.isEmpty()) {
controller.moveCards(cardsToBattlefield.getCards(game), Zone.BATTLEFIELD, source, game, false, false, false, null);
}
return true;
}
return false;
}
public ReturnToBattlefieldUnderYourControlTargetEffect withReturnNames(String returnName, String returnUnderControlName) {
this.returnName = returnName;
this.returnUnderControlName = returnUnderControlName;
updateText();
return this;
}
}

View file

@ -28,7 +28,7 @@ public class AddCountersControllerEffect extends OneShotEffect {
super(Outcome.Benefit);
this.counter = counter.copy();
this.enchantedEquipped = enchantedEquipped;
staticText = "its controller gets " + counter.getDescription();
staticText = (enchantedEquipped ? "its controller gets " : "you get ") + counter.getDescription();
}
public AddCountersControllerEffect(final AddCountersControllerEffect effect) {

View file

@ -1985,10 +1985,7 @@ public abstract class GameImpl implements Game {
newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(source.getSourceId()));
newAbility.setSourcePermanentTransformCount(this);
}
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
newAbility.init(this);
getState().addDelayedTriggeredAbility(newAbility);
return newAbility.getId();
}