При вызове RemoveUnit() у нас остается handle который не будет удален пока на него ссылается что-то, и в таких случаях нельзя определить был ли удален юнит или нет (использовав u == null)
Как пример:
Как пример:
- в случаях когда у нас есть таймер хранящий юнита, юнит может быть удален в промижуток между созданием таймера, и его срабатывании.
- юнит был в какой-то глобальной переменной
Для таких случаев мы можем использовать несколько вариантов определения удален ли юнит:
Вариант #1 (UnitTypeId)
Если юнит был удален в том же потоке, тогда это не сработает
Код
define
IsUnitExist(u) = (u != null and GetUnitTypeId(u) != 0)
IsUnitExist2(u) = (GetUnitTypeId(u) != 0)
IsUnitRemoved(u) = (u == null or GetUnitTypeId(u) == 0)
IsUnitRemoved2(u) = (GetUnitTypeId(u) == 0)
enddefine
Вариант #2 (UnitUserData)
Код
define
UNIT_REMOVED_UUD = -2147483646
IsUnitExist(u) = (u != null and GetUnitUserData(u) != UNIT_REMOVED_UUD)
IsUnitExist2(u) = (GetUnitUserData(u) != UNIT_REMOVED_UUD)
IsUnitRemoved(u) = (u == null or GetUnitUserData(u) == UNIT_REMOVED_UUD)
IsUnitRemoved2(u) = (GetUnitUserData(u) == UNIT_REMOVED_UUD)
RemoveUnit(u) = {
// Не ставим call чтобы можно было использовать "call RemoveUnit(u)"
SetUnitUserData(u, UNIT_REMOVED_UUD)
call Remove##Unit(u)
}
enddefine
Вариант #3 (Способность)
Редактор обьектов
Создаем способность на основе (Предмет +1 атака) и удаляем все бонусы
Код
define
ABILITY_UNIT_REMOVED = 'A000'
IsUnitExist(u) = (u != null and GetUnitAbilityLevel(u, ABILITY_UNIT_REMOVED) == 0)
IsUnitExist2(u) = (GetUnitAbilityLevel(u, ABILITY_UNIT_REMOVED) == 0)
IsUnitRemoved(u) = (u == null or GetUnitAbilityLevel(u, ABILITY_UNIT_REMOVED) != 0)
IsUnitRemoved2(u) = (GetUnitAbilityLevel(u, ABILITY_UNIT_REMOVED) != 0)
RemoveUnit(u) = {
// Не ставим call чтобы можно было использовать "call RemoveUnit(u)"
UnitAddAbility(u, ABILITY_UNIT_REMOVED)
call Remove##Unit(u)
}
enddefine
После реализации одного из способов мы можем спокойно проверить был ли удален юнит через какое-то время, даже если handle не освобожден
(ну или наоборот, использовать IsUnitExist() если нам нужна проверка существует ли юнит)
(ну или наоборот, использовать IsUnitExist() если нам нужна проверка существует ли юнит)
function TimerExpired takes nothing returns nothing
local unit u = LoadUnitHandle(hash, timerId, 0)
// Используем 2 вариацию, если при занесении в хэш мы уверены что там не null
if (IsUnitRemoved2(u)) then
// Юнит удален, чистим u (даже при использовании 1 вариации)
set u = null
return
endif
// ...
set u = null
endfunction
Если вы используете Jass new gen pack(JNGP) включите cJass для define
Ред. makkad
Ред. makkad
Добавил этот способ тоже
Ред. EugeAl
а после фрейма?
Ред. nik5960nik
Функция UnitAddAbility возвращает boolean, в случае успеха выдаёт true
Если выдавать абилку удалённому юниту, функция должна будет выдать false
Можете проверить этот способ?
Аналогично выдают boolean функции SaveUnitHandle в хэш, UnitAddItem, UnitAddType
Триггерно внезапно нельзя юниту добавить 2 одинаковых абилки, хотя с помощью спелбуков или инвентаря всегда пожалуйста, хотя они имеют собственные abilitylist.