Merge pull request #2315 from tool4ever/checkselflki

Better fix for CheckSelfLKIZone
This commit is contained in:
Anthony Calosa
2023-01-27 19:44:43 +08:00
committed by GitHub
11 changed files with 24 additions and 23 deletions

View File

@@ -173,21 +173,22 @@ public class ReplacementHandler {
game.forEachCardInGame(new Visitor<Card>() { game.forEachCardInGame(new Visitor<Card>() {
@Override @Override
public boolean visit(Card crd) { 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()) { 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 // Replacement effects that are tied to keywords (e.g. damage prevention effects - if the keyword is removed, the replacement
// effect should be inactive) // effect should be inactive)
if (replacementEffect.hasParam("TiedToKeyword")) { if (replacementEffect.hasParam("TiedToKeyword")) {

View File

@@ -2,7 +2,7 @@ Name:Draugr Necromancer
ManaCost:3 B ManaCost:3 B
Types:Snow Creature Zombie Cleric Types:Snow Creature Zombie Cleric
PT:4/4 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 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. 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 DeckNeeds:Type$Snow

View File

@@ -2,7 +2,7 @@ Name:Gisa, Glorious Resurrector
ManaCost:2 B B ManaCost:2 B B
Types:Legendary Creature Human Wizard Types:Legendary Creature Human Wizard
PT:4/4 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 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.) 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 SVar:TrigChange:DB$ ChangeZoneAll | ChangeType$ Creature.ExiledWithSource | Origin$ Exile | Destination$ Battlefield | GainControl$ True | RememberChanged$ True | SubAbility$ DBPump

View File

@@ -3,7 +3,7 @@ ManaCost:2 B B
Types:Legendary Creature Vampire Warrior Types:Legendary Creature Vampire Warrior
PT:3/4 PT:3/4
K:Lifelink 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:Exile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBToken | Defined$ ReplacedCard
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ b_2_2_zombie | TokenOwner$ You 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. 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.

View File

@@ -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. 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: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 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 SVar:Exile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ ReplacedCard
DeckHas:Ability$LifeGain 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. 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.

View File

@@ -7,6 +7,6 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Graveyard | ValidCard$ Creature
SVar:TrigReanimate:AB$ ChangeZone | Cost$ PayLife<X> | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | ChangeNum$ 1 | AnimateSubAbility$ Animate SVar:TrigReanimate:AB$ ChangeZone | Cost$ PayLife<X> | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | ChangeNum$ 1 | AnimateSubAbility$ Animate
SVar:Animate:DB$ Animate | Defined$ TriggeredCard | Types$ Warlock | Duration$ Permanent SVar:Animate:DB$ Animate | Defined$ TriggeredCard | Types$ Warlock | Duration$ Permanent
SVar:X:TriggeredCard$CardManaCost 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 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. 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.

View File

@@ -2,7 +2,7 @@ Name:Misery's Shadow
ManaCost:1 B ManaCost:1 B
Types:Creature Shade Types:Creature Shade
PT:2/2 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 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. 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. Oracle:If a creature an opponent controls would die, exile it instead.\n{1}: Misery's Shadow gets +1/+1 until end of turn.

View File

@@ -3,7 +3,7 @@ ManaCost:2 B G
Types:Legendary Creature Treefolk Types:Legendary Creature Treefolk
PT:3/4 PT:3/4
K:Reach 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: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: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 SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_1_1_saproling | TokenOwner$ You

View File

@@ -2,7 +2,7 @@ Name:Rayami, First of the Fallen
ManaCost:1 B G U ManaCost:1 B G U
Types:Legendary Creature Vampire Types:Legendary Creature Vampire
PT:5/4 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 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. 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. 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.

View File

@@ -4,7 +4,7 @@ Types:Legendary Creature Vampire Warlock
PT:1/1 PT:1/1
K:Menace K:Menace
K:Lifelink 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: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: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 SVar:TrigToken:AB$ Token | Cost$ 2 | TokenAmount$ 1 | TokenScript$ bg_1_1_pest_lifegain | TokenOwner$ You

View File

@@ -3,7 +3,7 @@ ManaCost:4 B B
Types:Creature Horror Types:Creature Horror
PT:4/5 PT:4/5
K:Trample 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: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 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 T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered+ExiledWithSource | Execute$ DBForget