Just found a perfect bug. It is so brilliant that it almost feels like a designed logic puzzle. Because of that, I'll first post what happened and then the solution in a spoiler.
Here is the code:
// dealDamage( sourcePlayer, damagedObject, damageDealt )
with(argument1)
{
if(variable_local_exists("deathmatch_invulnerable"))
{
if(argument1.deathmatch_invulnerable != 0)
return 0;
}
}
argument1.hp -= argument2;
execute_string( global.dealDamageFunction, argument0, argument1, argument2 );
And here is the error, which occurs when someone is being hit directly with a rocket:
ERROR in
action number 1
of Other Event: User Defined 5
for object Rocket:
In script damageAuto:
In script damageCharacter:
In script dealDamage:
Error in code at line 6:
if(argument1.deathmatch_invulnerable != 0)
^
at position 23: Unknown variable deathmatch_invulnerable
How can this happen? We check whether the variable exists before using!
Here are some tips:
- variable_local_exists is the right function for the job (i.e. it checks if the variable exists in the "current" instance)
- There is no subtle typo involved
- argument1 has the same value inside and outside the with()-block
- This is no "weird instance state" thing where an instance is really already destroyed or something
- The with-block runs for one instance, and it's the correct one (the character which was hit by the rocket)
Maybe you'll figure it out quickly, but otherwise just check here:
The damagedObject (argument1) that was passed in is -2, which is the same as the special value "other".
In the context this code is in (a collision event from rocket with character), that actually does resolve to the correct instance, so the with-block runs for the player who was hit. However, inside a with-block, "other" refers to the instance that was current *outside* the with-block, i.e. the rocket. So while variable_local_exists() checks for the variable in the correct instance, argument1.deathmatch_invulnerable actually tries to access the variable in the rocket instance, and fails.