EffectSource(): something of unexpected relevance
Posted: 10 Aug 2012, 12:19
I discovered the functionality of the EffectSource() function only recently, and I realized that I had a ton of cards to fix after that, so I want to make those discoveries public and well explained.
Do you remember that bug that I found a few days after the release of DotP2013? I bounced Timbermaw Larva to its owner's hand in response to its triggered ability, then the opponent played it again and it had the pumping as it had always been on the battlefield. Same goes for Liliana's Shade, which has been reported on the Wizards forums.
Look at the code for Liliana's Shade (conveniently indented because the original code was all on the same line):
The right way to handle this kind of effects, where a card modifies its own characteristics until end of turn, is with EffectSource(). The reason is that EffectSource() works the same way as a "CardPtr": after being automatically initialized during the processing of the ability, it gets deleted if the card changes zone. That's exactly what we want in this case. When our Timbermaw Larva or Liliana's Shade or whatever gets bounced back to hand, Object() still points at the card, while EffectSource() doesn't, so the effect gets nullified.
This also means that you have to be a little more careful when the zone change is planned to happen. Let's take the trigger for the undying mechanic as example:
To all the DotP2013 modders: I hope this has been helpful. Check your cards and make sure that you follow those guidelines.
Do you remember that bug that I found a few days after the release of DotP2013? I bounced Timbermaw Larva to its owner's hand in response to its triggered ability, then the opponent played it again and it had the pumping as it had always been on the battlefield. Same goes for Liliana's Shade, which has been reported on the Wizards forums.
Look at the code for Liliana's Shade (conveniently indented because the original code was all on the same line):
- Code: Select all
<CONTINUOUS_ACTION layer="7C">
local characteristics = Object():GetCurrentCharacteristics()
characteristics:Power_Add( 1 )
characteristics:Toughness_Add( 1 )
</CONTINUOUS_ACTION>
- Code: Select all
<CONTINUOUS_ACTION layer="7C">
if EffectSource() ~= nil then
EffectSource():GetCurrentCharacteristics():Power_Add( 1 )
EffectSource():GetCurrentCharacteristics():Toughness_Add( 0 )
end
</CONTINUOUS_ACTION>
The right way to handle this kind of effects, where a card modifies its own characteristics until end of turn, is with EffectSource(). The reason is that EffectSource() works the same way as a "CardPtr": after being automatically initialized during the processing of the ability, it gets deleted if the card changes zone. That's exactly what we want in this case. When our Timbermaw Larva or Liliana's Shade or whatever gets bounced back to hand, Object() still points at the card, while EffectSource() doesn't, so the effect gets nullified.
This also means that you have to be a little more careful when the zone change is planned to happen. Let's take the trigger for the undying mechanic as example:
- Code: Select all
<TRIGGER value="ZONECHANGE_BEGIN" simple_qualifier="self" to_zone="ZONE_GRAVEYARD" from_zone="ZONE_IN_PLAY">
if (Object():CountCounters( MTG():PlusOnePlusOneCounters() ) == 0) then
EffectDC():Protect_CardPtr(COMPARTMENT_ID_EFFECT_SOURCE)
return true
else
return false
end
</TRIGGER>
To all the DotP2013 modders: I hope this has been helpful. Check your cards and make sure that you follow those guidelines.