Hey. This is driving me nuts. I've got a Windwalk spell. When the caster attacks a unit, bonus damage is applied on the first attack + an armor reduction on the target. But I want a buff to appear at the status bar for the debuffed unit.
A0F1 (armor debuff) and B056.
Windwalk active:
Attacked the spider, and armor is properly reduced. But no buff is visible in the status bar.
The spell.
A0F1 (armor debuff) and B056.
Windwalk active:
Attacked the spider, and armor is properly reduced. But no buff is visible in the status bar.
The spell.
vJASS:
scope Nightrunner
globals
private constant integer ID = 'AOwk' //Windwalk
private constant integer BUFFID = 'B03S' //Buff on caster
private constant integer ARMORID = 'A0F1' //Armor reduction ability
private constant real WINDOW = 0.50
private constant real DUR = 10.00
private hashtable ht = null
endglobals
private function WindowExpire takes nothing returns nothing
local timer w = GetExpiredTimer()
local integer wid = GetHandleId(w)
local unit tgt = LoadUnitHandle(ht, wid, 0)
local integer uid
if tgt != null then
set uid = GetHandleId(tgt)
call SaveBoolean(ht, uid, 2, false)
call RemoveSavedHandle(ht, uid, 0)
endif
call FlushChildHashtable(ht, wid)
call DestroyTimer(w)
set tgt = null
set w = null
endfunction
private function MarkWindow takes unit tgt returns nothing
local integer uid = GetHandleId(tgt)
local timer w = LoadTimerHandle(ht, uid, 0)
call SaveBoolean(ht, uid, 2, true)
if w == null then
set w = CreateTimer()
call SaveTimerHandle(ht, uid, 0, w)
call SaveUnitHandle(ht, GetHandleId(w), 0, tgt)
endif
call TimerStart(w, WINDOW, false, function WindowExpire)
set w = null
endfunction
private function ConsumeWindow takes unit tgt returns nothing
local integer uid = GetHandleId(tgt)
local timer w = LoadTimerHandle(ht, uid, 0)
call SaveBoolean(ht, uid, 2, false)
if w != null then
call FlushChildHashtable(ht, GetHandleId(w))
call DestroyTimer(w)
call RemoveSavedHandle(ht, uid, 0)
endif
set w = null
endfunction
private function DebuffExpire takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer tid = GetHandleId(t)
local unit tgt = LoadUnitHandle(ht, tid, 0)
local integer uid
if tgt != null then
call UnitRemoveAbility(tgt, ARMORID)
set uid = GetHandleId(tgt)
call RemoveSavedHandle(ht, uid, 1)
endif
call FlushChildHashtable(ht, tid)
call DestroyTimer(t)
set tgt = null
set t = null
endfunction
private function ApplyDebuff takes unit tgt, integer lvl returns nothing
local integer uid = GetHandleId(tgt)
local timer t = LoadTimerHandle(ht, uid, 1)
if t == null then
set t = CreateTimer()
call SaveTimerHandle(ht, uid, 1, t)
call SaveUnitHandle(ht, GetHandleId(t), 0, tgt)
endif
call UnitAddAbility(tgt, ARMORID)
if lvl < 1 then
set lvl = 1
endif
call SetUnitAbilityLevel(tgt, ARMORID, lvl)
call TimerStart(t, DUR, false, function DebuffExpire)
set t = null
endfunction
private function OnAttacked takes nothing returns boolean
local unit attacker = GetAttacker()
if GetUnitAbilityLevel(attacker, BUFFID) > 0 then
call MarkWindow(GetTriggerUnit())
endif
set attacker = null
return false
endfunction
private function OnDamaged takes nothing returns boolean
local unit tgt = GetTriggerUnit()
local integer uid = GetHandleId(tgt)
local unit src
local integer lvl
if LoadBoolean(ht, uid, 2) and GetEventDamage() > 5.00 then
set src = GetEventDamageSource()
set lvl = GetUnitAbilityLevel(src, ID)
if lvl > 0 then
call ConsumeWindow(tgt)
call ApplyDebuff(tgt, lvl)
endif
set src = null
endif
set tgt = null
return false
endfunction
function TriggerStartNightRunner takes nothing returns nothing
local trigger t
if ht == null then
set ht = InitHashtable()
endif
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED)
call TriggerAddCondition(t, Condition(function OnAttacked))
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DAMAGED)
call TriggerAddCondition(t, Condition(function OnDamaged))
set t = null
endfunction
endscope