diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java index aa23631b709..838e32b83b0 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java @@ -173,21 +173,22 @@ public class ReplacementHandler { game.forEachCardInGame(new Visitor() { @Override public boolean visit(Card crd) { - final Card c = preList.get(crd); + Card c = preList.get(crd); + Zone cardZone = game.getChangeZoneLKIInfo(c).getLastKnownZone(); + + // only when not prelist + if (c == crd && cardZone.is(ZoneType.Battlefield) && event == ReplacementType.Moved && + runParams.containsKey(AbilityKey.LastStateBattlefield) && runParams.get(AbilityKey.LastStateBattlefield) != null) { + Card lastState = ((CardCollectionView) runParams.get(AbilityKey.LastStateBattlefield)).get(crd); + // no LKI found for this card so it shouldn't apply, this can happen during simultaneous zone changes + if (lastState == crd) { + return true; + } + // use the LKI because it has the right RE from the state before the effect started + c = lastState; + } for (final ReplacementEffect replacementEffect : c.getReplacementEffects()) { - Zone cardZone; - // Use "CheckLKIZone" parameter to test for effects that care about where the card was last (e.g. Kalitas, Traitor of Ghet - // getting hit by mass removal should still produce tokens). - if ("True".equals(replacementEffect.getParam("CheckSelfLKIZone"))) { - cardZone = game.getChangeZoneLKIInfo(c).getLastKnownZone(); - if (cardZone.is(ZoneType.Battlefield) && runParams.containsKey(AbilityKey.LastStateBattlefield) && runParams.get(AbilityKey.LastStateBattlefield) != null && !((CardCollectionView) runParams.get(AbilityKey.LastStateBattlefield)).contains(crd)) { - continue; - } - } else { - cardZone = game.getZoneOf(c); - } - // Replacement effects that are tied to keywords (e.g. damage prevention effects - if the keyword is removed, the replacement // effect should be inactive) if (replacementEffect.hasParam("TiedToKeyword")) { diff --git a/forge-gui/res/cardsfolder/d/draugr_necromancer.txt b/forge-gui/res/cardsfolder/d/draugr_necromancer.txt index 61ebdb00a72..db3994be061 100644 --- a/forge-gui/res/cardsfolder/d/draugr_necromancer.txt +++ b/forge-gui/res/cardsfolder/d/draugr_necromancer.txt @@ -2,7 +2,7 @@ Name:Draugr Necromancer ManaCost:3 B Types:Snow Creature Zombie Cleric PT:4/4 -R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.nonToken+OppCtrl | ReplaceWith$ Exile | CheckSelfLKIZone$ True | Description$ If a nontoken creature an opponent controls would die, exile that card with an ice counter on it instead. +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.nonToken+OppCtrl | ReplaceWith$ Exile | Description$ If a nontoken creature an opponent controls would die, exile that card with an ice counter on it instead. SVar:Exile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ ReplacedCard | WithCountersType$ ICE S:Mode$ Continuous | Affected$ Card.OppOwn+counters_GE1_ICE+nonLand | AffectedZone$ Exile | MayPlay$ True | MayPlaySnowIgnoreColor$ True | Description$ You may cast spells from among cards in exile your opponents own with ice counters on them, and you may spend mana from snow sources as though it were mana of any color to cast those spells. DeckNeeds:Type$Snow diff --git a/forge-gui/res/cardsfolder/g/gisa_glorious_resurrector.txt b/forge-gui/res/cardsfolder/g/gisa_glorious_resurrector.txt index dfbf695d861..452733c16e0 100644 --- a/forge-gui/res/cardsfolder/g/gisa_glorious_resurrector.txt +++ b/forge-gui/res/cardsfolder/g/gisa_glorious_resurrector.txt @@ -2,7 +2,7 @@ Name:Gisa, Glorious Resurrector ManaCost:2 B B Types:Legendary Creature Human Wizard PT:4/4 -R:Event$ Moved | ActiveZones$ Battlefield | CheckSelfLKIZone$ True | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.OppCtrl | ReplaceWith$ Exile | Description$ If a creature an opponent controls would die, exile it instead. +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.OppCtrl | ReplaceWith$ Exile | Description$ If a creature an opponent controls would die, exile it instead. SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigChange | TriggerDescription$ At the beginning of your upkeep, put all creature cards exiled with CARDNAME onto the battlefield under your control. They gain decayed. (A creature with decayed can't block. When it attacks, sacrifice it at end of combat.) SVar:TrigChange:DB$ ChangeZoneAll | ChangeType$ Creature.ExiledWithSource | Origin$ Exile | Destination$ Battlefield | GainControl$ True | RememberChanged$ True | SubAbility$ DBPump diff --git a/forge-gui/res/cardsfolder/k/kalitas_traitor_of_ghet.txt b/forge-gui/res/cardsfolder/k/kalitas_traitor_of_ghet.txt index 88deaf294a7..9e339fe7a69 100644 --- a/forge-gui/res/cardsfolder/k/kalitas_traitor_of_ghet.txt +++ b/forge-gui/res/cardsfolder/k/kalitas_traitor_of_ghet.txt @@ -3,7 +3,7 @@ ManaCost:2 B B Types:Legendary Creature Vampire Warrior PT:3/4 K:Lifelink -R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.nonToken+OppCtrl | ReplaceWith$ Exile | CheckSelfLKIZone$ True | Description$ If a nontoken creature an opponent controls would die, instead exile that card and create a 2/2 black Zombie creature token. +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.nonToken+OppCtrl | ReplaceWith$ Exile | Description$ If a nontoken creature an opponent controls would die, instead exile that card and create a 2/2 black Zombie creature token. SVar:Exile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBToken | Defined$ ReplacedCard SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ b_2_2_zombie | TokenOwner$ You A:AB$ PutCounter | Cost$ 2 B Sac<1/Vampire.Other;Zombie.Other/another Vampire or Zombie> | CounterType$ P1P1 | CounterNum$ 2 | SpellDescription$ Put two +1/+1 counters on CARDNAME. diff --git a/forge-gui/res/cardsfolder/l/liesa_forgotten_archangel.txt b/forge-gui/res/cardsfolder/l/liesa_forgotten_archangel.txt index b9102d3c42c..edddd7ef680 100644 --- a/forge-gui/res/cardsfolder/l/liesa_forgotten_archangel.txt +++ b/forge-gui/res/cardsfolder/l/liesa_forgotten_archangel.txt @@ -7,7 +7,7 @@ K:Lifelink T:Mode$ ChangesZone | ValidCard$ Creature.Other+nonToken+YouCtrl | Origin$ Battlefield | Destination$ Graveyard | Execute$ DelTrigReturn | TriggerZones$ Battlefield | TriggerDescription$ Whenever another nontoken creature you control dies, return that card to its owner's hand at the beginning of the next end step. SVar:DelTrigReturn:DB$ DelayedTrigger | Mode$ Phase | Phase$ End Of Turn | Execute$ DBReturn | RememberObjects$ TriggeredNewCardLKICopy | TriggerDescription$ Return that card to its owner's hand at the beginning of the next end step. SVar:DBReturn:DB$ ChangeZone | Defined$ DelayTriggerRememberedLKI | Origin$ Graveyard | Destination$ Hand -R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.OppCtrl | ReplaceWith$ Exile | CheckSelfLKIZone$ True | Description$ If a creature an opponent controls would die, exile it instead. +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.OppCtrl | ReplaceWith$ Exile | Description$ If a creature an opponent controls would die, exile it instead. SVar:Exile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ ReplacedCard DeckHas:Ability$LifeGain Oracle:Flying, lifelink\nWhenever another nontoken creature you control dies, return that card to its owner's hand at the beginning of the next end step.\nIf a creature an opponent controls would die, exile it instead. diff --git a/forge-gui/res/cardsfolder/l/lorcan_warlock_collector.txt b/forge-gui/res/cardsfolder/l/lorcan_warlock_collector.txt index e15def1a18d..68958cdf871 100644 --- a/forge-gui/res/cardsfolder/l/lorcan_warlock_collector.txt +++ b/forge-gui/res/cardsfolder/l/lorcan_warlock_collector.txt @@ -7,6 +7,6 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Graveyard | ValidCard$ Creature SVar:TrigReanimate:AB$ ChangeZone | Cost$ PayLife | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | ChangeNum$ 1 | AnimateSubAbility$ Animate SVar:Animate:DB$ Animate | Defined$ TriggeredCard | Types$ Warlock | Duration$ Permanent SVar:X:TriggeredCard$CardManaCost -R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Warlock.YouCtrl | ReplaceWith$ Exile | CheckSelfLKIZone$ True | Description$ If a Warlock you control would die, exile it instead. +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Warlock.YouCtrl | ReplaceWith$ Exile | Description$ If a Warlock you control would die, exile it instead. SVar:Exile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ ReplacedCard Oracle:Flying\nWhenever a creature card is put into an opponent's graveyard from anywhere, you may pay life equal to its mana value. If you do, put it onto the battlefield under your control. It's a Warlock in addition to its other types.\nIf a Warlock you control would die, exile it instead. diff --git a/forge-gui/res/cardsfolder/m/miserys_shadow.txt b/forge-gui/res/cardsfolder/m/miserys_shadow.txt index 283bc19deba..b1535028d51 100644 --- a/forge-gui/res/cardsfolder/m/miserys_shadow.txt +++ b/forge-gui/res/cardsfolder/m/miserys_shadow.txt @@ -2,7 +2,7 @@ Name:Misery's Shadow ManaCost:1 B Types:Creature Shade PT:2/2 -R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Card.Creature+OppCtrl | CheckSelfLKIZone$ True | ReplaceWith$ Exile | Description$ If a creature an opponent controls would die, exile it instead. +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Card.Creature+OppCtrl | ReplaceWith$ Exile | Description$ If a creature an opponent controls would die, exile it instead. SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard A:AB$ Pump | Cost$ 1 | Defined$ Self | NumAtt$ +1 | NumDef$ +1 | SpellDescription$ CARDNAME gets +1/+1 until end of turn. Oracle:If a creature an opponent controls would die, exile it instead.\n{1}: Misery's Shadow gets +1/+1 until end of turn. diff --git a/forge-gui/res/cardsfolder/n/nemata_primeval_warden.txt b/forge-gui/res/cardsfolder/n/nemata_primeval_warden.txt index 9689cb04dda..306bc6f4493 100644 --- a/forge-gui/res/cardsfolder/n/nemata_primeval_warden.txt +++ b/forge-gui/res/cardsfolder/n/nemata_primeval_warden.txt @@ -3,7 +3,7 @@ ManaCost:2 B G Types:Legendary Creature Treefolk PT:3/4 K:Reach -R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Card.Creature+OppCtrl | CheckSelfLKIZone$ True | ReplaceWith$ Exile | Description$ If a creature an opponent controls would die, exile it instead. When you do, create a 1/1 green Saproling creature token. +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Card.Creature+OppCtrl | ReplaceWith$ Exile | Description$ If a creature an opponent controls would die, exile it instead. When you do, create a 1/1 green Saproling creature token. SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard | SubAbility$ DBImmediateTrigger SVar:DBImmediateTrigger:DB$ ImmediateTrigger | Execute$ TrigToken | TriggerDescription$ If a nontoken creature an opponent controls would die, exile it instead. When you do, create a 1/1 green Saproling creature token. SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_1_1_saproling | TokenOwner$ You diff --git a/forge-gui/res/cardsfolder/r/rayami_first_of_the_fallen.txt b/forge-gui/res/cardsfolder/r/rayami_first_of_the_fallen.txt index fc14e0b4ba7..3c7fe64055d 100644 --- a/forge-gui/res/cardsfolder/r/rayami_first_of_the_fallen.txt +++ b/forge-gui/res/cardsfolder/r/rayami_first_of_the_fallen.txt @@ -2,7 +2,7 @@ Name:Rayami, First of the Fallen ManaCost:1 B G U Types:Legendary Creature Vampire PT:5/4 -R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | CheckSelfLKIZone$ True | ValidLKI$ Creature.nonToken | ReplaceWith$ Exile | Description$ If a nontoken creature would die, exile that card with a blood counter on it instead. +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.nonToken | ReplaceWith$ Exile | Description$ If a nontoken creature would die, exile that card with a blood counter on it instead. SVar:Exile:DB$ ChangeZone | Defined$ ReplacedCard | Origin$ Battlefield | Destination$ Exile | WithCountersType$ BLOOD | WithCountersAmount$ 1 S:Mode$ Continuous | EffectZone$ Battlefield | Affected$ Card.Self | CharacteristicDefining$ True | SharedKeywordsZone$ Exile | SharedRestrictions$ Creature.counters_GE1_BLOOD | AddKeyword$ Flying & First Strike & Double Strike & Deathtouch & Haste & Hexproof & Indestructible & Lifelink & Menace & Protection & Reach & Trample & Vigilance | Description$ As long as an exiled creature card with a blood counter on it has flying, CARDNAME has flying. The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, menace, protection, reach, trample, and vigilance. Oracle:If a nontoken creature would die, exile that card with a blood counter on it instead.\nAs long as an exiled creature card with a blood counter on it has flying, Rayami, First of the Fallen has flying. The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, menace, protection, reach, trample, and vigilance. diff --git a/forge-gui/res/cardsfolder/v/valentin_dean_of_the_vein_lisette_dean_of_the_root.txt b/forge-gui/res/cardsfolder/v/valentin_dean_of_the_vein_lisette_dean_of_the_root.txt index ae689c01407..959ecedc35c 100644 --- a/forge-gui/res/cardsfolder/v/valentin_dean_of_the_vein_lisette_dean_of_the_root.txt +++ b/forge-gui/res/cardsfolder/v/valentin_dean_of_the_vein_lisette_dean_of_the_root.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Vampire Warlock PT:1/1 K:Menace K:Lifelink -R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Card.Creature+nonToken+OppCtrl | CheckSelfLKIZone$ True | ReplaceWith$ Exile | Description$ If a nontoken creature an opponent controls would die, exile it instead. When you do, you may pay {2}. If you do, create a 1/1 black and green Pest creature token with "When this creature dies, you gain 1 life." +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Card.Creature+nonToken+OppCtrl | ReplaceWith$ Exile | Description$ If a nontoken creature an opponent controls would die, exile it instead. When you do, you may pay {2}. If you do, create a 1/1 black and green Pest creature token with "When this creature dies, you gain 1 life." SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard | SubAbility$ DBImmediateTrigger SVar:DBImmediateTrigger:DB$ ImmediateTrigger | Execute$ TrigToken | TriggerDescription$ If a nontoken creature an opponent controls would die, exile it instead. When you do, you may pay {2}. If you do, create a 1/1 black and green Pest creature token with "When this creature dies, you gain 1 life." SVar:TrigToken:AB$ Token | Cost$ 2 | TokenAmount$ 1 | TokenScript$ bg_1_1_pest_lifegain | TokenOwner$ You diff --git a/forge-gui/res/cardsfolder/v/void_maw.txt b/forge-gui/res/cardsfolder/v/void_maw.txt index ffb810857bb..fbbfd591b0d 100644 --- a/forge-gui/res/cardsfolder/v/void_maw.txt +++ b/forge-gui/res/cardsfolder/v/void_maw.txt @@ -3,7 +3,7 @@ ManaCost:4 B B Types:Creature Horror PT:4/5 K:Trample -R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.Other | CheckSelfLKIZone$ True | ReplaceWith$ Exile | Description$ If another creature would die, exile it instead. +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidLKI$ Creature.Other | ReplaceWith$ Exile | Description$ If another creature would die, exile it instead. SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard | SubAbility$ DBRemember | RememberChanged$ True SVar:DBRemember:DB$ Pump | ConditionDefined$ Remembered | ConditionPresent$ Card.inZoneExile | ConditionCompare$ GE1 T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered+ExiledWithSource | Execute$ DBForget