Merge pull request #13088 from magefree/wrong-dies-triggers-fix-2

Dies triggers fixes and improves (bugs like "no trigger on sacrifice cost")
This commit is contained in:
Oleg Agafonov 2024-11-30 17:56:16 +04:00 committed by GitHub
commit 52c4675d97
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
156 changed files with 1338 additions and 408 deletions

View file

@ -1,6 +1,8 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DiscardedByOpponentTriggeredAbility;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
@ -63,6 +65,7 @@ class AjanisLastStandTriggeredAbility extends TriggeredAbilityImpl {
new CreateTokenEffect(new AvatarToken2()),
new SacrificeSourceCost()
), false);
setLeavesTheBattlefieldTrigger(true);
}
private AjanisLastStandTriggeredAbility(final AjanisLastStandTriggeredAbility ability) {
@ -98,4 +101,9 @@ class AjanisLastStandTriggeredAbility extends TriggeredAbilityImpl {
+ "you may sacrifice {this}. "
+ "If you do, create a 4/4 white Avatar creature token with flying.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -1,6 +1,7 @@
package mage.cards.a;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
@ -122,6 +123,7 @@ class AthreosDiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
super(Zone.BATTLEFIELD, effect, optional);
this.filter = filter;
setTriggerPhrase("Whenever " + filter.getMessage() + " dies, ");
setLeavesTheBattlefieldTrigger(true);
}
private AthreosDiesCreatureTriggeredAbility(AthreosDiesCreatureTriggeredAbility ability) {
@ -153,4 +155,9 @@ class AthreosDiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
}
return true;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -80,6 +80,7 @@ class AthreosShroudVeiledTriggeredAbility extends TriggeredAbilityImpl {
AthreosShroudVeiledTriggeredAbility() {
super(Zone.BATTLEFIELD, null, false);
setLeavesTheBattlefieldTrigger(true);
}
private AthreosShroudVeiledTriggeredAbility(final AthreosShroudVeiledTriggeredAbility ability) {

View file

@ -1,6 +1,7 @@
package mage.cards.a;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
@ -60,6 +61,7 @@ class AvacynsCollarTriggeredAbility extends TriggeredAbilityImpl {
public AvacynsCollarTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenEffect(new SpiritWhiteToken()));
setLeavesTheBattlefieldTrigger(true);
}
private AvacynsCollarTriggeredAbility(final AvacynsCollarTriggeredAbility ability) {
@ -91,4 +93,9 @@ class AvacynsCollarTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever equipped creature dies, if it was a Human, create a 1/1 white Spirit creature token with flying.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -1,6 +1,8 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardImpl;
@ -41,6 +43,7 @@ class BereavementTriggeredAbility extends TriggeredAbilityImpl {
BereavementTriggeredAbility() {
super(Zone.BATTLEFIELD, new DiscardTargetEffect(1));
setLeavesTheBattlefieldTrigger(true);
}
private BereavementTriggeredAbility(final BereavementTriggeredAbility ability) {
@ -73,4 +76,9 @@ class BereavementTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a green creature dies, its controller discards a card.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -65,6 +65,7 @@ class BridgeFromBelowAbility extends TriggeredAbilityImpl {
this.filter = filter;
this.withInterveningIf(SourceInGraveyardCondition.instance);
setTriggerPhrase(filter.getMessage());
setLeavesTheBattlefieldTrigger(true); // it's not required for Bridge from Below, but better to keep same code style and verify pass
}
private BridgeFromBelowAbility(final BridgeFromBelowAbility ability) {

View file

@ -1,4 +1,3 @@
package mage.cards.c;
import java.util.UUID;
@ -39,6 +38,7 @@ public final class CallerOfTheClaw extends CardImpl {
// Flash
this.addAbility(FlashAbility.getInstance());
// When Caller of the Claw enters the battlefield, create a 2/2 green Bear creature token for each nontoken creature put into your graveyard from the battlefield this turn.
this.getSpellAbility().addWatcher(new CallerOfTheClawWatcher());
Effect effect = new CreateTokenEffect(new BearToken(), new CallerOfTheClawDynamicValue());

View file

@ -58,6 +58,7 @@ class CarthTheLionTriggeredAbility extends TriggeredAbilityImpl {
super(Zone.BATTLEFIELD, new LookLibraryAndPickControllerEffect(
7, 1, filter, PutCards.HAND, PutCards.BOTTOM_RANDOM));
setTriggerPhrase("Whenever {this} enters or a planeswalker you control dies, ");
setLeavesTheBattlefieldTrigger(true);
}
private CarthTheLionTriggeredAbility(final CarthTheLionTriggeredAbility ability) {

View file

@ -122,10 +122,10 @@ class ChainerNightmareAdeptWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
if (event.getAdditionalReference() == null) {
if (event.getApprovingObject() == null) {
return;
}
morMap.computeIfAbsent(event.getAdditionalReference().getApprovingMageObjectReference(), m -> new HashMap<>())
morMap.computeIfAbsent(event.getApprovingObject().getApprovingMageObjectReference(), m -> new HashMap<>())
.compute(event.getPlayerId(), (u, i) -> i == null ? 0 : Integer.sum(i, -1));
}
}

View file

@ -150,10 +150,10 @@ class ChandraHopesBeaconWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.SPELL_CAST
|| event.getAdditionalReference() == null) {
|| event.getApprovingObject() == null) {
return;
}
MageObjectReference mor = event.getAdditionalReference().getApprovingMageObjectReference();
MageObjectReference mor = event.getApprovingObject().getApprovingMageObjectReference();
Spell spell = game.getSpell(event.getTargetId());
if (mor == null || spell == null) {
return;

View file

@ -194,10 +194,10 @@ class ChissGoriaForgeTyrantWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getAdditionalReference() == null) {
if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getApprovingObject() == null) {
return;
}
MageObjectReference mor = event.getAdditionalReference().getApprovingMageObjectReference();
MageObjectReference mor = event.getApprovingObject().getApprovingMageObjectReference();
Spell spell = game.getSpell(event.getTargetId());
if (mor == null || spell == null) {
return;

View file

@ -33,7 +33,7 @@ public final class Chronozoa extends CardImpl {
// Vanishing 3 (This permanent enters the battlefield with three time counters on it. At the beginning of your upkeep, remove a time counter from it. When the last is removed, sacrifice it.)
this.addAbility(new VanishingAbility(3));
// When Chronozoa is put into a graveyard from play, if it had no time counters on it, create two tokens that are copies of it.
// When Chronozoa dies, if it had no time counters on it, create two tokens that are copies of it.
Effect effect = new CreateTokenCopySourceEffect(2);
effect.setText("create two tokens that are copies of it");
this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DiesSourceTriggeredAbility(effect, false),

View file

@ -237,15 +237,15 @@ class CoramTheUndertakerWatcher extends Watcher {
cardsAllowedToBePlayedOrCast.add(new MageObjectReference(mainCard, game));
return;
}
if (event.getAdditionalReference() == null
|| !MageIdentifier.CoramTheUndertakerWatcher.equals(event.getAdditionalReference().getApprovingAbility().getIdentifier())) {
if (event.getApprovingObject() == null
|| !MageIdentifier.CoramTheUndertakerWatcher.equals(event.getApprovingObject().getApprovingAbility().getIdentifier())) {
return;
}
if (event.getType() == GameEvent.EventType.LAND_PLAYED) {
landPlayedForSource.add(event.getAdditionalReference().getApprovingMageObjectReference());
landPlayedForSource.add(event.getApprovingObject().getApprovingMageObjectReference());
}
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
spellCastForSource.add(event.getAdditionalReference().getApprovingMageObjectReference());
spellCastForSource.add(event.getApprovingObject().getApprovingMageObjectReference());
}
}

View file

@ -226,7 +226,7 @@ class CourtOfLocthwainWatcher extends Watcher {
&& event.getPlayerId() != null) {
decrementCastAvailable(
event.getPlayerId(),
event.getAdditionalReference().getApprovingMageObjectReference()
event.getApprovingObject().getApprovingMageObjectReference()
);
}
}

View file

@ -54,6 +54,7 @@ class DaxosBlessedByTheSunAbility extends TriggeredAbilityImpl {
DaxosBlessedByTheSunAbility() {
super(Zone.BATTLEFIELD, new GainLifeEffect(1));
setLeavesTheBattlefieldTrigger(true);
}
private DaxosBlessedByTheSunAbility(DaxosBlessedByTheSunAbility ability) {

View file

@ -62,6 +62,7 @@ class DeathTyrantTriggeredAbility extends TriggeredAbilityImpl {
DeathTyrantTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken()));
setTriggerPhrase("Whenever an attacking creature you control or a blocking creature an opponent controls dies, ");
setLeavesTheBattlefieldTrigger(true);
}
private DeathTyrantTriggeredAbility(final DeathTyrantTriggeredAbility ability) {
@ -94,7 +95,7 @@ class DeathTyrantTriggeredAbility extends TriggeredAbilityImpl {
}
@Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -1,8 +1,8 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
@ -25,7 +25,6 @@ public final class DeathsPresence extends CardImpl {
public DeathsPresence(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{5}{G}");
// Whenever a creature you control dies, put X +1/+1 counters on target creature you control, where X is the power of the creature that died.
this.addAbility(new DeathsPresenceTriggeredAbility());
}
@ -44,6 +43,7 @@ class DeathsPresenceTriggeredAbility extends TriggeredAbilityImpl {
public DeathsPresenceTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
setLeavesTheBattlefieldTrigger(true);
}
private DeathsPresenceTriggeredAbility(final DeathsPresenceTriggeredAbility ability) {
@ -80,4 +80,9 @@ class DeathsPresenceTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a creature you control dies, put X +1/+1 counters on target creature you control, where X is the power of the creature that died.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -1,6 +1,8 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
@ -91,6 +93,7 @@ class DiabolicServitudeCreatureDiesTriggeredAbility extends TriggeredAbilityImpl
public DiabolicServitudeCreatureDiesTriggeredAbility() {
super(Zone.BATTLEFIELD, new DiabolicServitudeExileCreatureEffect(), false);
setLeavesTheBattlefieldTrigger(true);
}
private DiabolicServitudeCreatureDiesTriggeredAbility(final DiabolicServitudeCreatureDiesTriggeredAbility ability) {
@ -123,6 +126,11 @@ class DiabolicServitudeCreatureDiesTriggeredAbility extends TriggeredAbilityImpl
public String getRule() {
return "When the creature put onto the battlefield with {this} dies, exile it and return {this} to its owner's hand.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class DiabolicServitudeExileCreatureEffect extends OneShotEffect {

View file

@ -1,6 +1,7 @@
package mage.cards.d;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.LoseLifeTargetEffect;
@ -67,6 +68,7 @@ class DiregrafCaptainTriggeredAbility extends TriggeredAbilityImpl {
public DiregrafCaptainTriggeredAbility() {
super(Zone.BATTLEFIELD, new LoseLifeTargetEffect(1), false);
this.addTarget(new TargetOpponent());
this.setLeavesTheBattlefieldTrigger(true);
}
private DiregrafCaptainTriggeredAbility(final DiregrafCaptainTriggeredAbility ability) {
@ -99,4 +101,9 @@ class DiregrafCaptainTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever another Zombie you control dies, target opponent loses 1 life.";
}
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -53,6 +53,7 @@ class DreadhoundTriggeredAbility extends TriggeredAbilityImpl {
public DreadhoundTriggeredAbility() {
super(Zone.BATTLEFIELD, new LoseLifeOpponentsEffect(1));
setTriggerPhrase("Whenever a creature dies or a creature card is put into a graveyard from a library, ");
setLeavesTheBattlefieldTrigger(true);
}
private DreadhoundTriggeredAbility(final DreadhoundTriggeredAbility ability) {

View file

@ -1,5 +1,6 @@
package mage.cards.e;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
@ -97,6 +98,7 @@ class EndlessEvilBounceAbility extends TriggeredAbilityImpl {
public EndlessEvilBounceAbility() {
super(Zone.BATTLEFIELD, new ReturnToHandSourceEffect(false, true));
setLeavesTheBattlefieldTrigger(true);
}
private EndlessEvilBounceAbility(final EndlessEvilBounceAbility effect) {
@ -126,4 +128,9 @@ class EndlessEvilBounceAbility extends TriggeredAbilityImpl {
public String getRule() {
return "When enchanted creature dies, if that creature was a Horror, return {this} to its owner's hand.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -3,6 +3,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
@ -65,6 +66,7 @@ class EnigmaSphinxTriggeredAbility extends TriggeredAbilityImpl {
public EnigmaSphinxTriggeredAbility(Effect effect, boolean optional) {
super(Zone.ALL, effect, optional);
setTriggerPhrase("When {this} is put into your graveyard from the battlefield, ");
setLeavesTheBattlefieldTrigger(true);
}
private EnigmaSphinxTriggeredAbility(final EnigmaSphinxTriggeredAbility ability) {
@ -94,6 +96,11 @@ class EnigmaSphinxTriggeredAbility extends TriggeredAbilityImpl {
}
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class EnigmaSphinxEffect extends OneShotEffect {

View file

@ -201,9 +201,9 @@ class EvelynTheCovetousWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if ((event.getType() == GameEvent.EventType.SPELL_CAST || event.getType() == GameEvent.EventType.LAND_PLAYED)
&& event.getAdditionalReference() != null) {
&& event.getApprovingObject() != null) {
usedMap.computeIfAbsent(
event.getAdditionalReference()
event.getApprovingObject()
.getApprovingMageObjectReference(),
x -> new HashSet<>()
).add(event.getPlayerId());

View file

@ -1,6 +1,8 @@
package mage.cards.f;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.AbilityImpl;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
@ -51,6 +53,7 @@ class FalkenrathNobleTriggeredAbility extends TriggeredAbilityImpl {
super(Zone.BATTLEFIELD, new LoseLifeTargetEffect(1), false);
this.addEffect(new GainLifeEffect(1));
this.addTarget(new TargetPlayer());
setLeavesTheBattlefieldTrigger(true);
}
private FalkenrathNobleTriggeredAbility(final FalkenrathNobleTriggeredAbility ability) {
@ -87,4 +90,9 @@ class FalkenrathNobleTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever {this} or another creature dies, target player loses 1 life and you gain 1 life.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.f;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.CantBlockAbility;
@ -132,10 +131,10 @@ class FlameskullWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.SPELL_CAST
|| event.getAdditionalReference() == null) {
|| event.getApprovingObject() == null) {
return;
}
MageObjectReference mor = event.getAdditionalReference().getApprovingMageObjectReference();
MageObjectReference mor = event.getApprovingObject().getApprovingMageObjectReference();
Spell spell = game.getSpell(event.getTargetId());
if (mor == null || spell == null) {
return;

View file

@ -91,7 +91,7 @@ class GaleaKindlerOfHopeTriggeredAbility extends TriggeredAbilityImpl {
if (!isControlledBy(event.getPlayerId())
|| event.getZone() != Zone.LIBRARY
|| !event
.getAdditionalReference()
.getApprovingObject()
.getApprovingMageObjectReference()
.refersTo(this.getSourceObject(game), game)) {
return false;

View file

@ -162,7 +162,7 @@ class GlimpseTheCosmosWatcher extends Watcher {
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.CAST_SPELL
&& event.hasApprovingIdentifier(MageIdentifier.GlimpseTheCosmosWatcher)) {
Ability approvingAbility = event.getAdditionalReference().getApprovingAbility();
Ability approvingAbility = event.getApprovingObject().getApprovingAbility();
if (approvingAbility != null
&& approvingAbility.getSourceId().equals(event.getSourceId())) {
sourceCards.add(game.getCard(event.getSourceId()));

View file

@ -2,6 +2,8 @@
package mage.cards.g;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
@ -53,6 +55,7 @@ class GraveBetrayalTriggeredAbility extends TriggeredAbilityImpl {
public GraveBetrayalTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
setLeavesTheBattlefieldTrigger(true);
}
private GraveBetrayalTriggeredAbility(final GraveBetrayalTriggeredAbility ability) {
@ -92,6 +95,11 @@ class GraveBetrayalTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a creature you don't control dies, return it to the battlefield under your control with an additional +1/+1 counter on it at the beginning of the next end step. That creature is a black Zombie in addition to its other colors and types.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class GraveBetrayalEffect extends OneShotEffect {
@ -125,7 +133,6 @@ class GraveBetrayalEffect extends OneShotEffect {
}
return false;
}
}
class GraveBetrayalReplacementEffect extends ReplacementEffectImpl {

View file

@ -1,5 +1,6 @@
package mage.cards.g;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
@ -29,7 +30,6 @@ public final class GravePact extends CardImpl {
public GravePact(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{B}{B}");
// Whenever a creature you control dies, each other player sacrifices a creature.
this.addAbility(new GravePactTriggeredAbility());
}
@ -49,6 +49,7 @@ class GravePactTriggeredAbility extends TriggeredAbilityImpl {
public GravePactTriggeredAbility() {
super(Zone.BATTLEFIELD, new GravePactEffect());
setTriggerPhrase("Whenever a creature you control dies, ");
this.setLeavesTheBattlefieldTrigger(true);
}
private GravePactTriggeredAbility(final GravePactTriggeredAbility ability) {
@ -74,6 +75,11 @@ class GravePactTriggeredAbility extends TriggeredAbilityImpl {
}
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class GravePactEffect extends OneShotEffect {

View file

@ -48,6 +48,7 @@ class GutterGrimeTriggeredAbility extends TriggeredAbilityImpl {
public GutterGrimeTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.SLIME.createInstance()), false);
this.addEffect(new GutterGrimeEffect());
setLeavesTheBattlefieldTrigger(true);
}
private GutterGrimeTriggeredAbility(final GutterGrimeTriggeredAbility ability) {
@ -83,6 +84,11 @@ class GutterGrimeTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a nontoken creature you control dies, put a slime counter on {this}, then create a green Ooze creature token with \"This creature's power and toughness are each equal to the number of slime counters on {this}.\"";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class GutterGrimeEffect extends OneShotEffect {

View file

@ -1,6 +1,7 @@
package mage.cards.h;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
@ -51,6 +52,7 @@ class HatefulEidolonTriggeredAbility extends TriggeredAbilityImpl {
HatefulEidolonTriggeredAbility() {
super(Zone.BATTLEFIELD, null, false);
setLeavesTheBattlefieldTrigger(true);
}
private HatefulEidolonTriggeredAbility(final HatefulEidolonTriggeredAbility ability) {
@ -105,4 +107,9 @@ class HatefulEidolonTriggeredAbility extends TriggeredAbilityImpl {
return "Whenever an enchanted creature dies, draw a card for each "
+ "Aura you controlled that was attached to it.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -185,7 +185,7 @@ class HaukensInsightWatcher extends Watcher {
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST || event.getType() == GameEvent.EventType.LAND_PLAYED) {
if (event.hasApprovingIdentifier(MageIdentifier.HaukensInsightWatcher)) {
usedFrom.add(event.getAdditionalReference().getApprovingMageObjectReference());
usedFrom.add(event.getApprovingObject().getApprovingMageObjectReference());
}
}
}

View file

@ -173,12 +173,12 @@ class HedonistsTroveWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.SPELL_CAST
|| event.getAdditionalReference() == null) {
|| event.getApprovingObject() == null) {
return;
}
playerMap
.computeIfAbsent(event.getPlayerId(), x -> new HashSet<>())
.add(event.getAdditionalReference().getApprovingMageObjectReference());
.add(event.getApprovingObject().getApprovingMageObjectReference());
playerMap.get(event.getPlayerId()).removeIf(Objects::isNull);
}

View file

@ -224,7 +224,7 @@ class IanMalcolmChaoticianWatcher extends Watcher {
if (event.getType() == GameEvent.EventType.SPELL_CAST &&
event.hasApprovingIdentifier(MageIdentifier.IanMalcolmChaoticianWatcher)) {
usedMap.computeIfAbsent(
event.getAdditionalReference()
event.getApprovingObject()
.getApprovingMageObjectReference(),
x -> new HashSet<>()
).add(event.getPlayerId());

View file

@ -211,10 +211,10 @@ class IdolOfEnduranceWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
if (event.getAdditionalReference() == null) {
if (event.getApprovingObject() == null) {
return;
}
morMap.computeIfAbsent(event.getAdditionalReference().getApprovingMageObjectReference(), m -> new HashMap<>())
morMap.computeIfAbsent(event.getApprovingObject().getApprovingMageObjectReference(), m -> new HashMap<>())
.compute(event.getPlayerId(), (u, i) -> i == null ? 0 : Integer.sum(i, -1));
}
}

View file

@ -1,7 +1,9 @@
package mage.cards.i;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@ -55,6 +57,7 @@ class InfestedThrinaxTriggeredAbility extends DelayedTriggeredAbility {
InfestedThrinaxTriggeredAbility() {
super(new CreateTokenEffect(new SaprolingToken(), SavedDamageValue.MUCH), Duration.EndOfTurn, false, false);
setLeavesTheBattlefieldTrigger(true);
}
private InfestedThrinaxTriggeredAbility(final InfestedThrinaxTriggeredAbility ability) {
@ -89,4 +92,9 @@ class InfestedThrinaxTriggeredAbility extends DelayedTriggeredAbility {
return "Whenever a nontoken creature you control dies, " +
"create a number of 1/1 green Saproling creature tokens equal to that creature's power.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -94,6 +94,7 @@ class JerrenCorruptedBishopTriggeredAbility extends TriggeredAbilityImpl {
JerrenCorruptedBishopTriggeredAbility() {
super(Zone.BATTLEFIELD, new LoseLifeSourceControllerEffect(1));
this.addEffect(new CreateTokenEffect(new HumanToken()));
setLeavesTheBattlefieldTrigger(true);
}
private JerrenCorruptedBishopTriggeredAbility(final JerrenCorruptedBishopTriggeredAbility ability) {

View file

@ -123,7 +123,7 @@ class KaghaShadowArchdruidWatcher extends Watcher {
public void watch(GameEvent event, Game game) {
if ((GameEvent.EventType.SPELL_CAST.equals(event.getType()) || GameEvent.EventType.LAND_PLAYED.equals(event.getType()))
&& event.hasApprovingIdentifier(MageIdentifier.KaghaShadowArchdruidWatcher)) {
usedFrom.add(event.getAdditionalReference().getApprovingMageObjectReference());
usedFrom.add(event.getApprovingObject().getApprovingMageObjectReference());
}
if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;

View file

@ -44,6 +44,7 @@ class KarmicJusticeTriggeredAbility extends TriggeredAbilityImpl {
KarmicJusticeTriggeredAbility() {
super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true);
this.setLeavesTheBattlefieldTrigger(true);
}
private KarmicJusticeTriggeredAbility(final KarmicJusticeTriggeredAbility ability) {

View file

@ -78,6 +78,7 @@ class KayaTheInexorableTriggeredAbility extends TriggeredAbilityImpl {
public KayaTheInexorableTriggeredAbility() {
super(Zone.ALL, null, false);
this.setLeavesTheBattlefieldTrigger(true);
}
private KayaTheInexorableTriggeredAbility(KayaTheInexorableTriggeredAbility ability) {
@ -107,22 +108,6 @@ class KayaTheInexorableTriggeredAbility extends TriggeredAbilityImpl {
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
Permanent sourcePermanent = null;
if (game.getState().getZone(getSourceId()) == Zone.BATTLEFIELD) {
sourcePermanent = game.getPermanent(getSourceId());
} else {
if (game.checkShortLivingLKI(getSourceId(), Zone.BATTLEFIELD)) {
sourcePermanent = (Permanent) game.getLastKnownInformation(getSourceId(), Zone.BATTLEFIELD);
}
}
if (sourcePermanent == null) {
return false;
}
return hasSourceObjectAbility(game, sourcePermanent, event);
}
@Override
public KayaTheInexorableTriggeredAbility copy() {
return new KayaTheInexorableTriggeredAbility(this);

View file

@ -60,6 +60,7 @@ class KayasGhostformTriggeredAbility extends TriggeredAbilityImpl {
KayasGhostformTriggeredAbility() {
super(Zone.ALL, new ReturnToBattlefieldUnderYourControlAttachedEffect(), false);
setLeavesTheBattlefieldTrigger(true);
}
private KayasGhostformTriggeredAbility(final KayasGhostformTriggeredAbility ability) {

View file

@ -178,9 +178,9 @@ class KessDissidentMageWatcher extends Watcher {
&& event.hasApprovingIdentifier(MageIdentifier.KessDissidentMageWatcher)) {
Spell spell = (Spell) game.getObject(event.getTargetId());
if (spell != null) {
allowingObjects.add(event.getAdditionalReference().getApprovingMageObjectReference());
allowingObjects.add(event.getApprovingObject().getApprovingMageObjectReference());
castSpells.put(new MageObjectReference(spell.getMainCard().getId(), game),
event.getAdditionalReference().getApprovingAbility().getSourceId());
event.getApprovingObject().getApprovingAbility().getSourceId());
}
}
}

View file

@ -170,7 +170,7 @@ class KotoseTheSilentSpiderWatcher extends Watcher {
morMap.values().removeIf(Set::isEmpty);
return;
}
if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getAdditionalReference() == null) {
if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getApprovingObject() == null) {
return;
}
Spell spell = game.getSpell(event.getTargetId());
@ -178,7 +178,7 @@ class KotoseTheSilentSpiderWatcher extends Watcher {
return;
}
morMap.getOrDefault(
event.getAdditionalReference().getApprovingMageObjectReference(), Collections.emptySet()
event.getApprovingObject().getApprovingMageObjectReference(), Collections.emptySet()
).removeIf(set -> set
.stream()
.anyMatch(mor -> mor.getSourceId().equals(spell.getMainCard().getId())

View file

@ -222,10 +222,10 @@ class LobeliaDefenderOfBagEndWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST || event.getType() == GameEvent.EventType.PLAY_LAND) {
if (event.getAdditionalReference() == null) {
if (event.getApprovingObject() == null) {
return;
}
morMap.computeIfAbsent(event.getAdditionalReference().getApprovingMageObjectReference(), m -> new HashMap<>())
morMap.computeIfAbsent(event.getApprovingObject().getApprovingMageObjectReference(), m -> new HashMap<>())
.compute(event.getPlayerId(), (u, i) -> i == null ? 0 : Integer.sum(i, -1));
}
}

View file

@ -1,6 +1,7 @@
package mage.cards.l;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
@ -56,6 +57,7 @@ class LuminousBroodmothTriggeredAbility extends TriggeredAbilityImpl {
LuminousBroodmothTriggeredAbility() {
super(Zone.BATTLEFIELD, new LuminousBroodmothEffect(), false);
setLeavesTheBattlefieldTrigger(true);
}
private LuminousBroodmothTriggeredAbility(final LuminousBroodmothTriggeredAbility ability) {
@ -97,6 +99,11 @@ class LuminousBroodmothTriggeredAbility extends TriggeredAbilityImpl {
return "Whenever a creature you control without flying dies, "
+ "return it to the battlefield under its owner's control with a flying counter on it.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class LuminousBroodmothEffect extends OneShotEffect {

View file

@ -70,6 +70,7 @@ class LyndeCheerfulTormentorCurseDiesTriggeredAbility extends TriggeredAbilityIm
new LyndeCheerfulTormentorReturnCurseEffect()
)
));
setLeavesTheBattlefieldTrigger(true);
}
private LyndeCheerfulTormentorCurseDiesTriggeredAbility(final LyndeCheerfulTormentorCurseDiesTriggeredAbility ability) {
@ -102,8 +103,8 @@ class LyndeCheerfulTormentorCurseDiesTriggeredAbility extends TriggeredAbilityIm
}
@Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
@Override

View file

@ -148,14 +148,14 @@ class MaestrosAscendancyWatcher extends Watcher {
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST
&& event.hasApprovingIdentifier(MageIdentifier.MaestrosAscendencyAlternateCast)
&& event.getAdditionalReference() != null) {
&& event.getApprovingObject() != null) {
playerMap.computeIfAbsent(
event.getAdditionalReference()
event.getApprovingObject()
.getApprovingMageObjectReference(),
x -> new HashSet<>()
).add(event.getPlayerId());
spellMap.computeIfAbsent(
event.getAdditionalReference()
event.getApprovingObject()
.getApprovingMageObjectReference(),
x -> new HashSet<>()
).add(new MageObjectReference(event.getTargetId(), game));

View file

@ -2,6 +2,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
@ -59,6 +60,7 @@ class MagusOfTheBridgeTriggeredAbility extends TriggeredAbilityImpl {
public MagusOfTheBridgeTriggeredAbility() {
super(Zone.BATTLEFIELD, new ExileSourceEffect());
setTriggerPhrase("When a creature is put into an opponent's graveyard from the battlefield, ");
setLeavesTheBattlefieldTrigger(true);
}
private MagusOfTheBridgeTriggeredAbility(final MagusOfTheBridgeTriggeredAbility ability) {
@ -86,4 +88,9 @@ class MagusOfTheBridgeTriggeredAbility extends TriggeredAbilityImpl {
}
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -117,11 +117,11 @@ class MarchOfRecklessJoyWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getAdditionalReference() == null) {
if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getApprovingObject() == null) {
return;
}
morMap.compute(event
.getAdditionalReference()
.getApprovingObject()
.getApprovingMageObjectReference(),
CardUtil::setOrIncrementValue
);

View file

@ -3,6 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
@ -67,6 +68,7 @@ class MarchesaTheBlackRoseTriggeredAbility extends TriggeredAbilityImpl {
public MarchesaTheBlackRoseTriggeredAbility() {
super(Zone.BATTLEFIELD, new MarchesaTheBlackRoseEffect());
setTriggerPhrase("Whenever a creature you control with a +1/+1 counter on it dies, ");
setLeavesTheBattlefieldTrigger(true);
}
private MarchesaTheBlackRoseTriggeredAbility(final MarchesaTheBlackRoseTriggeredAbility ability) {
@ -100,6 +102,11 @@ class MarchesaTheBlackRoseTriggeredAbility extends TriggeredAbilityImpl {
}
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class MarchesaTheBlackRoseEffect extends OneShotEffect {

View file

@ -1,6 +1,7 @@
package mage.cards.m;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
@ -165,6 +166,7 @@ class MariTheKillingQuillCreatureDiesAbility extends TriggeredAbilityImpl {
public MariTheKillingQuillCreatureDiesAbility() {
super(Zone.BATTLEFIELD, new MariTheKillingQuillExileCreatureEffect(), false);
setLeavesTheBattlefieldTrigger(true);
}
private MariTheKillingQuillCreatureDiesAbility(final MariTheKillingQuillCreatureDiesAbility ability) {
@ -202,6 +204,11 @@ class MariTheKillingQuillCreatureDiesAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a creature an opponent controls dies, exile it with a hit counter on it.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class MariTheKillingQuillExileCreatureEffect extends OneShotEffect {

View file

@ -1,5 +1,6 @@
package mage.cards.m;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
@ -50,6 +51,7 @@ class MartyrsBondTriggeredAbility extends TriggeredAbilityImpl {
public MartyrsBondTriggeredAbility() {
super(Zone.BATTLEFIELD, new MartyrsBondEffect());
setLeavesTheBattlefieldTrigger(true);
}
private MartyrsBondTriggeredAbility(final MartyrsBondTriggeredAbility ability) {
@ -88,6 +90,10 @@ class MartyrsBondTriggeredAbility extends TriggeredAbilityImpl {
return "Whenever {this} or another nonland permanent you control is put into a graveyard from the battlefield, each opponent sacrifices a permanent that shares a card type with it.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class MartyrsBondEffect extends OneShotEffect {

View file

@ -1,8 +1,10 @@
package mage.cards.m;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
@ -77,6 +79,7 @@ class MassacreGirlDelayedTriggeredAbility extends DelayedTriggeredAbility {
MassacreGirlDelayedTriggeredAbility() {
super(new BoostAllEffect(-1, -1, Duration.EndOfTurn, true), Duration.EndOfTurn, false);
setLeavesTheBattlefieldTrigger(true);
}
private MassacreGirlDelayedTriggeredAbility(final MassacreGirlDelayedTriggeredAbility ability) {
@ -103,4 +106,9 @@ class MassacreGirlDelayedTriggeredAbility extends DelayedTriggeredAbility {
public String getRule() {
return "Whenever a creature dies this turn, each creature other than {this} gets -1/-1 until end of turn";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -2,6 +2,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.Effect;
@ -52,6 +53,7 @@ class MassacreWurmTriggeredAbility extends TriggeredAbilityImpl {
MassacreWurmTriggeredAbility() {
super(Zone.BATTLEFIELD, new LoseLifeTargetEffect(2));
setTriggerPhrase("Whenever a creature an opponent controls dies, ");
setLeavesTheBattlefieldTrigger(true);
}
private MassacreWurmTriggeredAbility(final MassacreWurmTriggeredAbility ability) {
@ -81,4 +83,9 @@ class MassacreWurmTriggeredAbility extends TriggeredAbilityImpl {
}
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -79,6 +79,7 @@ class MillicentRestlessRevenantTriggeredAbility extends TriggeredAbilityImpl {
MillicentRestlessRevenantTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenEffect(new SpiritWhiteToken()));
setLeavesTheBattlefieldTrigger(true);
}
private MillicentRestlessRevenantTriggeredAbility(final MillicentRestlessRevenantTriggeredAbility ability) {
@ -124,8 +125,12 @@ class MillicentRestlessRevenantTriggeredAbility extends TriggeredAbilityImpl {
}
@Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} else {
return super.isInUseableZone(game, sourceObject, event);
}
}
@Override

View file

@ -4,6 +4,8 @@ package mage.cards.m;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
@ -60,6 +62,7 @@ class MimicVatTriggeredAbility extends TriggeredAbilityImpl {
MimicVatTriggeredAbility() {
super(Zone.BATTLEFIELD, new MimicVatEffect(), true);
setLeavesTheBattlefieldTrigger(true);
}
private MimicVatTriggeredAbility(final MimicVatTriggeredAbility ability) {
@ -105,6 +108,11 @@ class MimicVatTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return AbilityWord.IMPRINT.formatWord() + "Whenever a nontoken creature dies, you may exile that card. If you do, return each other card exiled with {this} to its owner's graveyard.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class MimicVatEffect extends OneShotEffect {

View file

@ -3,6 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.TrampleAbility;
@ -47,6 +48,7 @@ class MolderBeastTriggeredAbility extends TriggeredAbilityImpl {
public MolderBeastTriggeredAbility() {
super(Zone.BATTLEFIELD, new BoostSourceEffect(2, 0, Duration.EndOfTurn), false);
setLeavesTheBattlefieldTrigger(true);
}
private MolderBeastTriggeredAbility(final MolderBeastTriggeredAbility ability) {
@ -74,4 +76,9 @@ class MolderBeastTriggeredAbility extends TriggeredAbilityImpl {
public MolderBeastTriggeredAbility copy() {
return new MolderBeastTriggeredAbility(this);
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -146,8 +146,8 @@ class MuldrothaTheGravetideWatcher extends Watcher {
private void addPermanentTypes(GameEvent event, Card mageObject, Game game) {
if (mageObject != null
&& event.getAdditionalReference() != null
&& MageIdentifier.MuldrothaTheGravetideWatcher.equals(event.getAdditionalReference().getApprovingAbility().getIdentifier())) {
&& event.getApprovingObject() != null
&& MageIdentifier.MuldrothaTheGravetideWatcher.equals(event.getApprovingObject().getApprovingAbility().getIdentifier())) {
UUID playerId = null;
if (mageObject instanceof Spell) {
playerId = ((Spell) mageObject).getControllerId();
@ -155,10 +155,10 @@ class MuldrothaTheGravetideWatcher extends Watcher {
playerId = ((Permanent) mageObject).getControllerId();
}
if (playerId != null) {
Set<CardType> permanentTypes = sourcePlayedPermanentTypes.get(event.getAdditionalReference().getApprovingMageObjectReference());
Set<CardType> permanentTypes = sourcePlayedPermanentTypes.get(event.getApprovingObject().getApprovingMageObjectReference());
if (permanentTypes == null) {
permanentTypes = EnumSet.noneOf(CardType.class);
sourcePlayedPermanentTypes.put(event.getAdditionalReference().getApprovingMageObjectReference(), permanentTypes);
sourcePlayedPermanentTypes.put(event.getApprovingObject().getApprovingMageObjectReference(), permanentTypes);
}
Set<CardType> typesNotCast = EnumSet.noneOf(CardType.class);
for (CardType cardType : mageObject.getCardType(game)) {

View file

@ -51,6 +51,7 @@ class MycoidShepherdTriggeredAbility extends TriggeredAbilityImpl {
public MycoidShepherdTriggeredAbility() {
super(Zone.BATTLEFIELD, new GainLifeEffect(5), true);
setLeavesTheBattlefieldTrigger(true);
}
private MycoidShepherdTriggeredAbility(final MycoidShepherdTriggeredAbility ability) {
@ -91,4 +92,9 @@ class MycoidShepherdTriggeredAbility extends TriggeredAbilityImpl {
public MycoidShepherdTriggeredAbility copy() {
return new MycoidShepherdTriggeredAbility(this);
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -121,7 +121,7 @@ class NashiMoonSagesScionWatcher extends Watcher {
morMap.values().removeIf(Set::isEmpty);
return;
}
if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getAdditionalReference() == null) {
if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getApprovingObject() == null) {
return;
}
Spell spell = game.getSpell(event.getTargetId());
@ -129,7 +129,7 @@ class NashiMoonSagesScionWatcher extends Watcher {
return;
}
morMap.getOrDefault(
event.getAdditionalReference().getApprovingMageObjectReference(), Collections.emptySet()
event.getApprovingObject().getApprovingMageObjectReference(), Collections.emptySet()
).removeIf(set -> set
.stream()
.anyMatch(mor -> mor.getSourceId().equals(spell.getMainCard().getId())

View file

@ -3,6 +3,7 @@ package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
@ -55,6 +56,7 @@ class NecroskitterTriggeredAbility extends TriggeredAbilityImpl {
public NecroskitterTriggeredAbility() {
super(Zone.BATTLEFIELD, new ReturnToBattlefieldUnderYourControlTargetEffect(), true);
setLeavesTheBattlefieldTrigger(true);
}
private NecroskitterTriggeredAbility(final NecroskitterTriggeredAbility ability) {
@ -92,4 +94,9 @@ class NecroskitterTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a creature an opponent controls with a -1/-1 counter on it dies, you may return that card to the battlefield under your control.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -3,6 +3,7 @@ package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.common.DoIfCostPaid;
@ -55,6 +56,7 @@ class NetherTraitorTriggeredAbility extends TriggeredAbilityImpl {
NetherTraitorTriggeredAbility(){
super(Zone.GRAVEYARD, new DoIfCostPaid(new ReturnSourceFromGraveyardToBattlefieldEffect(), new ColoredManaCost(ColoredManaSymbol.B)));
setLeavesTheBattlefieldTrigger(true);
}
private NetherTraitorTriggeredAbility(final NetherTraitorTriggeredAbility ability) {
@ -94,4 +96,9 @@ class NetherTraitorTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever another creature is put into your graveyard from the battlefield, you may pay {B}. If you do, return {this} from your graveyard to the battlefield.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -1,5 +1,6 @@
package mage.cards.n;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
@ -72,6 +73,7 @@ class NimDeathmantleTriggeredAbility extends TriggeredAbilityImpl {
NimDeathmantleTriggeredAbility() {
super(Zone.BATTLEFIELD, new NimDeathmantleEffect(), false);
setLeavesTheBattlefieldTrigger(true);
}
private NimDeathmantleTriggeredAbility(final NimDeathmantleTriggeredAbility ability) {
@ -108,6 +110,11 @@ class NimDeathmantleTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a nontoken creature is put into your graveyard from the battlefield, you may pay {4}. If you do, return that card to the battlefield and attach {this} to it.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class NimDeathmantleEffect extends OneShotEffect {

View file

@ -136,7 +136,7 @@ class OneWithTheMultiverseWatcher extends Watcher {
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST
&& event.hasApprovingIdentifier(MageIdentifier.OneWithTheMultiverseWatcher)) {
usedFrom.add(event.getAdditionalReference().getApprovingMageObjectReference());
usedFrom.add(event.getApprovingObject().getApprovingMageObjectReference());
}
}

View file

@ -1,6 +1,7 @@
package mage.cards.o;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.keyword.LifelinkAbility;
@ -51,6 +52,7 @@ class OrahSkyclaveHierophantTriggeredAbility extends TriggeredAbilityImpl {
OrahSkyclaveHierophantTriggeredAbility() {
super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect());
setLeavesTheBattlefieldTrigger(true);
}
private OrahSkyclaveHierophantTriggeredAbility(final OrahSkyclaveHierophantTriggeredAbility ability) {
@ -94,4 +96,9 @@ class OrahSkyclaveHierophantTriggeredAbility extends TriggeredAbilityImpl {
return "Whenever {this} or another Cleric you control dies, return target Cleric card " +
"with lesser mana value from your graveyard to the battlefield.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -70,6 +70,7 @@ class PatronOfTheVeinCreatureDiesTriggeredAbility extends TriggeredAbilityImpl {
public PatronOfTheVeinCreatureDiesTriggeredAbility() {
super(Zone.BATTLEFIELD, new PatronOfTheVeinExileCreatureEffect(), false);
setLeavesTheBattlefieldTrigger(true);
}
private PatronOfTheVeinCreatureDiesTriggeredAbility(final PatronOfTheVeinCreatureDiesTriggeredAbility ability) {
@ -107,6 +108,11 @@ class PatronOfTheVeinCreatureDiesTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a creature an opponent controls dies, exile it and put a +1/+1 counter on each Vampire you control.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class PatronOfTheVeinExileCreatureEffect extends OneShotEffect {

View file

@ -64,6 +64,7 @@ class PeltCollectorTriggeredAbility extends TriggeredAbilityImpl {
PeltCollectorTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()));
setLeavesTheBattlefieldTrigger(true);
}
private PeltCollectorTriggeredAbility(PeltCollectorTriggeredAbility ability) {

View file

@ -44,9 +44,7 @@ public final class PhantasmalImage extends CardImpl {
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// You may have Phantasmal Image enter the battlefield as a copy of any creature
// on the battlefield, except it's an Illusion in addition to its other types and
// it has "When this creature becomes the target of a spell or ability, sacrifice it."
// You may have Phantasmal Image enter the battlefield as a copy of any creature on the battlefield, except it's an Illusion in addition to its other types and it has "When this creature becomes the target of a spell or ability, sacrifice it."
Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, phantasmalImageApplier);
effect.setText(effectText);
this.addAbility(new EntersBattlefieldAbility(effect, true));

View file

@ -1,5 +1,6 @@
package mage.cards.p;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
@ -97,6 +98,7 @@ class PiasRevolutionTriggeredAbility extends TriggeredAbilityImpl {
public PiasRevolutionTriggeredAbility() {
super(Zone.BATTLEFIELD, new PiasRevolutionReturnEffect(), false);
setTriggerPhrase("Whenever a nontoken artifact is put into your graveyard from the battlefield, ");
setLeavesTheBattlefieldTrigger(true);
}
private PiasRevolutionTriggeredAbility(final PiasRevolutionTriggeredAbility ability) {
@ -127,4 +129,9 @@ class PiasRevolutionTriggeredAbility extends TriggeredAbilityImpl {
}
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -1,5 +1,6 @@
package mage.cards.p;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
@ -40,6 +41,7 @@ class ProperBurialTriggeredAbility extends TriggeredAbilityImpl {
public ProperBurialTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
setLeavesTheBattlefieldTrigger(true);
}
private ProperBurialTriggeredAbility(final ProperBurialTriggeredAbility ability) {
@ -76,4 +78,9 @@ class ProperBurialTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a creature you control dies, you gain life equal to that creature's toughness.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -57,6 +57,7 @@ class PsychomancerTriggeredAbility extends TriggeredAbilityImpl {
this.setTriggerPhrase("Whenever {this} or another nontoken artifact you control is put " +
"into a graveyard from the battlefield or is put into exile from the battlefield, ");
this.withFlavorWord("Harbinger of Despair");
this.setLeavesTheBattlefieldTrigger(true);
}
private PsychomancerTriggeredAbility(final PsychomancerTriggeredAbility ability) {

View file

@ -62,6 +62,7 @@ class PurgatoryTriggeredAbility extends TriggeredAbilityImpl {
PurgatoryTriggeredAbility() {
super(Zone.BATTLEFIELD, new PurgatoryExileEffect(), false);
setLeavesTheBattlefieldTrigger(true);
}
private PurgatoryTriggeredAbility(final PurgatoryTriggeredAbility ability) {
@ -103,6 +104,11 @@ class PurgatoryTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a nontoken creature is put into your graveyard from the battlefield, exile that card.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class PurgatoryExileEffect extends OneShotEffect {

View file

@ -159,12 +159,12 @@ class RadiantScrollwielderWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getAdditionalReference() == null) {
if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getApprovingObject() == null) {
return;
}
morMap.put(
new MageObjectReference(event.getSourceId(), game),
event.getAdditionalReference().getApprovingMageObjectReference()
event.getApprovingObject().getApprovingMageObjectReference()
);
}

View file

@ -1,6 +1,7 @@
package mage.cards.r;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.CardImpl;
@ -52,6 +53,7 @@ class RemembranceTriggeredAbility extends TriggeredAbilityImpl {
RemembranceTriggeredAbility() {
super(Zone.BATTLEFIELD, null, true);
setLeavesTheBattlefieldTrigger(true);
}
private RemembranceTriggeredAbility(final RemembranceTriggeredAbility ability) {
@ -92,4 +94,9 @@ class RemembranceTriggeredAbility extends TriggeredAbilityImpl {
"you may search your library for a card with the same name as that creature, " +
"reveal it, put it into your hand, then shuffle.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -63,6 +63,7 @@ class ReyhanLastOfTheAbzanTriggeredAbility extends TriggeredAbilityImpl {
public ReyhanLastOfTheAbzanTriggeredAbility() {
super(Zone.BATTLEFIELD, null, true);
setLeavesTheBattlefieldTrigger(true);
}
private ReyhanLastOfTheAbzanTriggeredAbility(final ReyhanLastOfTheAbzanTriggeredAbility ability) {

View file

@ -1,6 +1,7 @@
package mage.cards.r;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
@ -65,6 +66,7 @@ class RhukHexgoldNabberTriggeredAbility extends TriggeredAbilityImpl {
RhukHexgoldNabberTriggeredAbility() {
super(Zone.BATTLEFIELD, new RhukHexgoldNabberEffect(), true);
setLeavesTheBattlefieldTrigger(true);
}
private RhukHexgoldNabberTriggeredAbility(final RhukHexgoldNabberTriggeredAbility ability) {
@ -110,6 +112,15 @@ class RhukHexgoldNabberTriggeredAbility extends TriggeredAbilityImpl {
return "Whenever an equipped creature you control other than {this} attacks or dies, " +
"you may attach all Equipment attached to that creature to {this}.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
} else {
return super.isInUseableZone(game, sourceObject, event);
}
}
}
class RhukHexgoldNabberEffect extends OneShotEffect {

View file

@ -1,6 +1,7 @@
package mage.cards.r;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
@ -70,6 +71,7 @@ class RienneAngelOfRebirthTriggeredAbility extends TriggeredAbilityImpl {
RienneAngelOfRebirthTriggeredAbility() {
super(Zone.BATTLEFIELD, new RienneAngelOfRebirthEffect(), false);
setLeavesTheBattlefieldTrigger(true);
}
private RienneAngelOfRebirthTriggeredAbility(final RienneAngelOfRebirthTriggeredAbility ability) {
@ -109,6 +111,11 @@ class RienneAngelOfRebirthTriggeredAbility extends TriggeredAbilityImpl {
return "Whenever another multicolored creature you control dies, " +
"return it to its owner's hand at the beginning of the next end step.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class RienneAngelOfRebirthEffect extends OneShotEffect {

View file

@ -1,5 +1,6 @@
package mage.cards.s;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl;
@ -40,6 +41,7 @@ class SacredGroundTriggeredAbility extends TriggeredAbilityImpl {
SacredGroundTriggeredAbility() {
super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect());
setLeavesTheBattlefieldTrigger(true);
}
private SacredGroundTriggeredAbility(final SacredGroundTriggeredAbility ability) {
@ -75,4 +77,9 @@ class SacredGroundTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a spell or ability an opponent controls causes a land to be put into your graveyard from the battlefield, return that card to the battlefield.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -4,6 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.keyword.FlyingAbility;
@ -46,9 +47,11 @@ public final class Sangromancer extends CardImpl {
}
class SangromancerFirstTriggeredAbility extends TriggeredAbilityImpl {
SangromancerFirstTriggeredAbility() {
super(Zone.BATTLEFIELD, new GainLifeEffect(3), true);
setTriggerPhrase("Whenever a creature an opponent controls dies, ");
setLeavesTheBattlefieldTrigger(true);
}
private SangromancerFirstTriggeredAbility(final SangromancerFirstTriggeredAbility ability) {
@ -75,6 +78,11 @@ class SangromancerFirstTriggeredAbility extends TriggeredAbilityImpl {
}
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class SangromancerSecondTriggeredAbility extends TriggeredAbilityImpl {

View file

@ -1,6 +1,7 @@
package mage.cards.s;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
@ -56,6 +57,7 @@ class ScrapTrawlerTriggeredAbility extends TriggeredAbilityImpl {
super(Zone.BATTLEFIELD, new ReturnToHandTargetEffect());
getEffects().get(0).setText("return to your hand target artifact card in your graveyard with lesser mana value");
setTriggerPhrase("Whenever {this} or another artifact you control is put into a graveyard from the battlefield, ");
setLeavesTheBattlefieldTrigger(true);
}
private ScrapTrawlerTriggeredAbility(final ScrapTrawlerTriggeredAbility ability) {
@ -90,4 +92,9 @@ class ScrapTrawlerTriggeredAbility extends TriggeredAbilityImpl {
}
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -1,6 +1,7 @@
package mage.cards.s;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
@ -45,12 +46,13 @@ class ScrapheapTriggeredAbility extends TriggeredAbilityImpl {
return new ScrapheapTriggeredAbility(this);
}
private ScrapheapTriggeredAbility(final ScrapheapTriggeredAbility ability){
super(ability);
}
public ScrapheapTriggeredAbility(){
super(Zone.BATTLEFIELD, new GainLifeEffect(1));
setLeavesTheBattlefieldTrigger(true);
}
private ScrapheapTriggeredAbility(final ScrapheapTriggeredAbility ability){
super(ability);
}
@Override
@ -76,4 +78,9 @@ class ScrapheapTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever an artifact or enchantment is put into your graveyard from the battlefield, you gain 1 life.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -2,6 +2,7 @@ package mage.cards.s;
import mage.MageInt;
import mage.MageItem;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.keyword.SurveilEffect;
import mage.abilities.keyword.MenaceAbility;
@ -53,6 +54,7 @@ class SeerOfStolenSightTriggeredAbility extends TriggeredAbilityImpl {
SeerOfStolenSightTriggeredAbility() {
super(Zone.BATTLEFIELD, new SurveilEffect(1));
setTriggerPhrase("Whenever one or more artifacts and/or creatures you control are put into a graveyard from the battlefield, ");
setLeavesTheBattlefieldTrigger(true);
}
private SeerOfStolenSightTriggeredAbility(final SeerOfStolenSightTriggeredAbility ability) {
@ -85,4 +87,9 @@ class SeerOfStolenSightTriggeredAbility extends TriggeredAbilityImpl {
.map(Controllable::getControllerId)
.anyMatch(this::isControlledBy);
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -142,10 +142,10 @@ class SerpentsSoulJarWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
if (event.getAdditionalReference() == null) {
if (event.getApprovingObject() == null) {
return;
}
morMap.computeIfAbsent(event.getAdditionalReference().getApprovingMageObjectReference(), m -> new HashMap<>())
morMap.computeIfAbsent(event.getApprovingObject().getApprovingMageObjectReference(), m -> new HashMap<>())
.compute(event.getPlayerId(), (u, i) -> i == null ? 0 : Integer.sum(i, -1));
return;
}

View file

@ -193,7 +193,7 @@ class SerraParagonWatcher extends Watcher {
|| event.getType() == GameEvent.EventType.LAND_PLAYED)
&& event.hasApprovingIdentifier(MageIdentifier.SerraParagonWatcher)) {
map.computeIfAbsent(
event.getAdditionalReference()
event.getApprovingObject()
.getApprovingMageObjectReference(),
x -> new HashSet<>()
).add(event.getPlayerId());

View file

@ -59,6 +59,7 @@ class ShardOfTheVoidDragonTriggeredAbility extends TriggeredAbilityImpl {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)));
setTriggerPhrase("Whenever an artifact is put into a graveyard from the battlefield or is put into exile from the battlefield, ");
withFlavorWord("Matter Absorption");
setLeavesTheBattlefieldTrigger(true);
}
private ShardOfTheVoidDragonTriggeredAbility(final ShardOfTheVoidDragonTriggeredAbility ability) {

View file

@ -1,6 +1,7 @@
package mage.cards.s;
import mage.MageInt;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
@ -145,6 +146,7 @@ class ShelobChildOfUngoliantTriggeredAbility extends TriggeredAbilityImpl {
super(Zone.BATTLEFIELD, effect);
this.addWatcher(new ShelobChildOfUngoliantWatcher());
this.setTriggerPhrase("Whenever another creature dealt damage this turn by a Spider you controlled dies, ");
setLeavesTheBattlefieldTrigger(true);
}
private ShelobChildOfUngoliantTriggeredAbility(final ShelobChildOfUngoliantTriggeredAbility ability) {
@ -185,6 +187,11 @@ class ShelobChildOfUngoliantTriggeredAbility extends TriggeredAbilityImpl {
}
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class ShelobChildOfUngoliantEffect extends OneShotEffect {

View file

@ -1,5 +1,6 @@
package mage.cards.s;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
@ -40,6 +41,7 @@ class SlagstoneRefineryTriggeredAbility extends TriggeredAbilityImpl {
SlagstoneRefineryTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenEffect(new PowerstoneToken(), 1, true));
setLeavesTheBattlefieldTrigger(true);
}
private SlagstoneRefineryTriggeredAbility(final SlagstoneRefineryTriggeredAbility ability) {
@ -79,4 +81,9 @@ class SlagstoneRefineryTriggeredAbility extends TriggeredAbilityImpl {
return "Whenever {this} or another nontoken artifact you control is put into a graveyard from the battlefield " +
"or is put into exile from the battlefield, create a tapped Powerstone token.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -2,6 +2,8 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
@ -56,6 +58,7 @@ class SlayersPlateTriggeredAbility extends TriggeredAbilityImpl {
public SlayersPlateTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenEffect(new SpiritWhiteToken()));
setLeavesTheBattlefieldTrigger(true);
}
private SlayersPlateTriggeredAbility(final SlayersPlateTriggeredAbility ability) {
@ -87,4 +90,9 @@ class SlayersPlateTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever equipped creature dies, if it was a Human, create a 1/1 white Spirit creature token with flying.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -1,5 +1,6 @@
package mage.cards.s;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
@ -68,6 +69,7 @@ class SporogenesisTriggeredAbility extends TriggeredAbilityImpl {
SporogenesisTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateTokenEffect(new SaprolingToken(), new SporogenesisCount()), false);
setLeavesTheBattlefieldTrigger(true);
}
private SporogenesisTriggeredAbility(final SporogenesisTriggeredAbility ability) {
@ -104,6 +106,11 @@ class SporogenesisTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a creature with a fungus counter on it dies, create a 1/1 green Saproling creature token for each fungus counter on that creature.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class SporogenesisCount implements DynamicValue {

View file

@ -54,6 +54,7 @@ class SyrKonradTheGrimTriggeredAbility extends TriggeredAbilityImpl {
SyrKonradTheGrimTriggeredAbility() {
super(Zone.BATTLEFIELD, new DamagePlayersEffect(1, TargetController.OPPONENT));
setLeavesTheBattlefieldTrigger(true);
}
private SyrKonradTheGrimTriggeredAbility(final SyrKonradTheGrimTriggeredAbility ability) {
@ -95,8 +96,8 @@ class SyrKonradTheGrimTriggeredAbility extends TriggeredAbilityImpl {
}
@Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
@Override

View file

@ -67,6 +67,7 @@ class TaekoThePatientAvalancheTriggeredAbility extends TriggeredAbilityImpl {
super(Zone.BATTLEFIELD, new ScryEffect(1, false));
this.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance()).concatBy("and"));
this.setTriggerPhrase("Whenever another creature you control leaves the battlefield, if it didn't die, ");
setLeavesTheBattlefieldTrigger(true);
}
private TaekoThePatientAvalancheTriggeredAbility(final TaekoThePatientAvalancheTriggeredAbility ability) {

View file

@ -3,6 +3,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
@ -71,6 +72,7 @@ class TheScorpionGodTriggeredAbility extends TriggeredAbilityImpl {
public TheScorpionGodTriggeredAbility() {
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), false);
setLeavesTheBattlefieldTrigger(true);
}
private TheScorpionGodTriggeredAbility(final TheScorpionGodTriggeredAbility ability) {
@ -105,6 +107,11 @@ class TheScorpionGodTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a creature with a -1/-1 counter on it dies, draw a card.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class TheScorpionGodEffect extends OneShotEffect {

View file

@ -112,6 +112,7 @@ class TheSkullsporeNexusTrigger extends TriggeredAbilityImpl {
TheSkullsporeNexusTrigger() {
super(Zone.BATTLEFIELD, null, false);
setLeavesTheBattlefieldTrigger(true);
}
private TheSkullsporeNexusTrigger(final TheSkullsporeNexusTrigger ability) {
@ -170,8 +171,8 @@ class TheSkullsporeNexusTrigger extends TriggeredAbilityImpl {
}
@Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, event, game);
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -3,6 +3,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
@ -65,6 +66,7 @@ class TianaShipsCaretakerTriggeredAbility extends TriggeredAbilityImpl {
TianaShipsCaretakerTriggeredAbility() {
super(Zone.BATTLEFIELD, new TianaShipsCaretakerEffect(), true);
setTriggerPhrase("Whenever an Aura or Equipment you control is put into a graveyard from the battlefield, ");
setLeavesTheBattlefieldTrigger(true);
}
private TianaShipsCaretakerTriggeredAbility(final TianaShipsCaretakerTriggeredAbility ability) {
@ -98,6 +100,11 @@ class TianaShipsCaretakerTriggeredAbility extends TriggeredAbilityImpl {
}
return false;
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class TianaShipsCaretakerEffect extends OneShotEffect {

View file

@ -124,10 +124,10 @@ class UnluckyWitnessWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.SPELL_CAST
|| event.getAdditionalReference() == null) {
|| event.getApprovingObject() == null) {
return;
}
MageObjectReference mor = event.getAdditionalReference().getApprovingMageObjectReference();
MageObjectReference mor = event.getApprovingObject().getApprovingMageObjectReference();
Spell spell = game.getSpell(event.getTargetId());
if (mor == null || spell == null) {
return;

View file

@ -62,6 +62,7 @@ class VerdantSuccessionTriggeredAbility extends TriggeredAbilityImpl {
VerdantSuccessionTriggeredAbility() {
super(Zone.BATTLEFIELD, null, true);
setLeavesTheBattlefieldTrigger(true);
}
private VerdantSuccessionTriggeredAbility(final VerdantSuccessionTriggeredAbility ability) {
@ -98,6 +99,11 @@ class VerdantSuccessionTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever a green nontoken creature dies, that creature's controller may search their library for a card with the same name as that creature, put it onto the battlefield, then shuffle.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}
class VerdantSuccessionEffect extends OneShotEffect {

View file

@ -114,7 +114,7 @@ class VesuvanShapeshifterEffect extends OneShotEffect {
if (copyFromCreature != null) {
game.copyPermanent(Duration.Custom, copyFromCreature, copyToCreature.getId(), source, new VesuvanShapeShifterFaceUpCopyApplier());
source.getTargets().clear();
game.processAction(); // needed to get effects ready if copy happens in replacment and the copied abilities react of the same event (e.g. turn face up)
game.processAction(); // needed to get effects ready if copy happens in replacement and the copied abilities react of the same event (e.g. turn face up)
return true;
}
}

View file

@ -3,6 +3,7 @@ package mage.cards.v;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
@ -48,6 +49,7 @@ class VillageCannibalsTriggeredAbility extends TriggeredAbilityImpl {
public VillageCannibalsTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()));
setTriggerPhrase("Whenever another Human creature dies, ");
setLeavesTheBattlefieldTrigger(true);
}
private VillageCannibalsTriggeredAbility(final VillageCannibalsTriggeredAbility ability) {
@ -74,4 +76,9 @@ class VillageCannibalsTriggeredAbility extends TriggeredAbilityImpl {
return permanent != null && permanent.isCreature(game) && permanent.hasSubtype(SubType.HUMAN, game)
&& !permanent.getId().equals(this.getSourceId());
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

View file

@ -57,6 +57,7 @@ class VindictiveVampireTriggeredAbility extends TriggeredAbilityImpl {
public VindictiveVampireTriggeredAbility(Zone zone, Effect effect) {
super(zone, effect, false);
setTriggerPhrase("Whenever another creature you control dies, ");
setLeavesTheBattlefieldTrigger(true);
}
private VindictiveVampireTriggeredAbility(final VindictiveVampireTriggeredAbility ability) {
@ -69,17 +70,8 @@ class VindictiveVampireTriggeredAbility extends TriggeredAbilityImpl {
}
@Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
Permanent sourcePermanent;
if (game.getState().getZone(getSourceId()) == Zone.BATTLEFIELD) {
sourcePermanent = game.getPermanent(getSourceId());
} else {
sourcePermanent = (Permanent) game.getPermanentOrLKIBattlefield(getSourceId());
}
if (sourcePermanent == null) {
return false;
}
return hasSourceObjectAbility(game, sourcePermanent, event);
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
@Override

View file

@ -3,6 +3,8 @@
package mage.cards.v;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.Card;
@ -40,8 +42,10 @@ public final class ViridianRevel extends CardImpl {
}
class ViridianRevelTriggeredAbility extends TriggeredAbilityImpl {
ViridianRevelTriggeredAbility() {
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), true);
setLeavesTheBattlefieldTrigger(true);
}
private ViridianRevelTriggeredAbility(final ViridianRevelTriggeredAbility ability) {
@ -75,4 +79,9 @@ class ViridianRevelTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever an artifact is put into an opponent's graveyard from the battlefield, you may draw a card.";
}
@Override
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
}
}

Some files were not shown because too many files have changed in this diff Show more