- Joined
- Aug 4, 2006
- Messages
- 357
Basically, using a unit's life to detect if it's dead is a bad idea because a dead unit's life can still be modified when it is dead.
The best way to detect dead units is to use this library (requires vJASS):
(Special thanks to azlier for showing me this)
I also included the DoesUnitExist function, since that seems to be a useful and popular check that not many people know about.
Plain JASS alternative (put this in your trigger editor map header):
The best way to detect dead units is to use this library (requires vJASS):
(Special thanks to azlier for showing me this)
JASS:
library dead
//returns true if the unit is alive. requires JassHelper
// to declare the AI native "UnitAlive" as a JASS native, so that
// we can use it in the trigger editor. If you trigger in vJASS,
// you should DEFINITELY use this since it is the only way to be
// sure that a unit is alive.
native UnitAlive takes unit id returns boolean
//returns true if the unit is dead. inline friendly.
function UnitDead takes unit u returns boolean
return not UnitAlive(u)
endfunction
//returns true if the unit exists in the game. inline friendly.
function DoesUnitExist takes unit u returns boolean
return GetUnitTypeId(u) != 0
endfunction
endlibrary
Plain JASS alternative (put this in your trigger editor map header):
JASS:
//returns true if the unit exists in the game
function DoesUnitExist takes unit u returns boolean
return GetUnitTypeId(u) != 0
endfunction
//returns true if the unit is dead (or does not exist)
function IsUnitDead takes unit u returns boolean
return IsUnitType(u, UNIT_TYPE_DEAD) or not DoesUnitExist(u)
endfunction
Summary
How do you detect if a unit is dead? Check if the unit’s life is less than .405, right? Wrong. There is only one way to tell if a unit is actually dead (or not alive):
Stuff like
Why?
When a live unit's health goes anywhere below 0.405, it becomes dead. Its health is set to 0.000 and its unittype becomes UNIT_TYPE_DEAD. Once the unit is dead, its life can still be changed by triggers. This serves no practical purpose that I know of, and it does not revive the unit if its life is set above 0.405. However, this can result in bugs if you rely on using the unit's health to tell if it is dead or not. For example, if you forget to have a triggered AOE heal spell filter out dead units, it can heal a bunch of corpses. This would result in all of your other triggered spells thinking that the corpses are "alive." Then imagine the corpses being accidentally knocked back, frozen, meat-hooked, etc. Regardless of whether or not one spell remembers to check for dead units, it should not screw up all of your other spells.
So, the obvious solution is to use the unit's unittype. This unittype is updated automatically whenever the unit is killed, exploded, revived, etc. Unfortunately, IsUnitType returns false when the unit does not exist, meaning we could think a non-existent unit is alive. To make my function work for removed/null units, I also check if the unit's type id is 0. Now units that are null or no longer exist are considered "dead." No matter what mistakes you make, this function will always tell you whether a unit is dead or not.
Some of you may want to verify the above information. For that reason, I have provided the map that I used to test things. In it, you will find a peasant whose basic information is displayed. You can damage, heal, and revive the peasant to see how the information changes. To damage the peasant, type "-damage x" where x is a real number. To heal the peasant, type "-heal x" where x is a real number. I disabled the peasant's health regeneration for testing purposes. To revive the peasant, use the paladin's skill. A zeppelin and necromancer are provided for further testing.
Please do NOT give me credits for this function. I do not know who first used unittype to detect dead units. I first saw it somewhere on wc3c and am only posting it here for the benefit of the community.
I did, however, do all the research on this topic and create the String library used in the test map.
Despite the small size of this function, I found it important enough to be in its own thread rather than in Small Code Snippets. After all, nearly every spell and map needs to detect dead units.
How do you detect if a unit is dead? Check if the unit’s life is less than .405, right? Wrong. There is only one way to tell if a unit is actually dead (or not alive):
JASS:
function IsUnitDead takes unit u returns boolean
return IsUnitType(u, UNIT_TYPE_DEAD) or GetUnitTypeId(u) == 0
endfunction
GetUnitState(yourUnit, UNIT_STATE_LIFE) < 0.405
or GetWidgetLife(yourUnit) < .405
can and will cause bugs.Why?
When a live unit's health goes anywhere below 0.405, it becomes dead. Its health is set to 0.000 and its unittype becomes UNIT_TYPE_DEAD. Once the unit is dead, its life can still be changed by triggers. This serves no practical purpose that I know of, and it does not revive the unit if its life is set above 0.405. However, this can result in bugs if you rely on using the unit's health to tell if it is dead or not. For example, if you forget to have a triggered AOE heal spell filter out dead units, it can heal a bunch of corpses. This would result in all of your other triggered spells thinking that the corpses are "alive." Then imagine the corpses being accidentally knocked back, frozen, meat-hooked, etc. Regardless of whether or not one spell remembers to check for dead units, it should not screw up all of your other spells.
So, the obvious solution is to use the unit's unittype. This unittype is updated automatically whenever the unit is killed, exploded, revived, etc. Unfortunately, IsUnitType returns false when the unit does not exist, meaning we could think a non-existent unit is alive. To make my function work for removed/null units, I also check if the unit's type id is 0. Now units that are null or no longer exist are considered "dead." No matter what mistakes you make, this function will always tell you whether a unit is dead or not.
Some of you may want to verify the above information. For that reason, I have provided the map that I used to test things. In it, you will find a peasant whose basic information is displayed. You can damage, heal, and revive the peasant to see how the information changes. To damage the peasant, type "-damage x" where x is a real number. To heal the peasant, type "-heal x" where x is a real number. I disabled the peasant's health regeneration for testing purposes. To revive the peasant, use the paladin's skill. A zeppelin and necromancer are provided for further testing.
Please do NOT give me credits for this function. I do not know who first used unittype to detect dead units. I first saw it somewhere on wc3c and am only posting it here for the benefit of the community.
I did, however, do all the research on this topic and create the String library used in the test map.
Despite the small size of this function, I found it important enough to be in its own thread rather than in Small Code Snippets. After all, nearly every spell and map needs to detect dead units.
Attachments
Last edited: