- Joined
- Dec 19, 2007
- Messages
- 1,234
Is the only way to check if unit has buff or lost it is via checking each and any second? or is there another way to do it? (who won't cause lag each second? )
Check each second.
When the unit receives the buff, add it to the unit group, and check the units in the unit group every second. If the unit no longer has the buff, remove it from the group.
it means for each active buff a trigger will be active, it is extreamly annoying when 4 heroes casted a buff and have a critical time , with mass lags up untill someone dies.
Buff checking is very light. You can check a few hundred units several times a second and it won't be noticeable.
If you don't want to check every second, here is an alternative:
- Register event unit gains buff
- CONSTANT where you track the duration of the buff (copied from your object data)
- Condition: check it is the buff you want
- Action: create a timer, create a trigger, set timer to the duration of the buff, and register event timer elapsed.
- Condition: assert the unit still has the buff (because it was recast), and if it does then destroy the timer (GetElapsedTimer), destroy the trigger (GetTriggeringTrigger) and return
- Action: Do stuff, then destroy trigger and timer
No need to keep an array of the timers and triggers, just destroy them using the Get functions when the timer elapses.
I didn't know there was an event for unit gains buff.
User just needs to account for possible external debuff sources.
library UnitLosesBuff
globals
private unit array freedUnits
//private code array eventHandlers
private trigger array dispelTriggers
endglobals
private function UnitPurged takes nothing returns nothing
endfunction
private function TimerExpires takes nothing returns nothing
local integer timerHandleId = GetHandleId(GetExpiredTimer())
//local code eventHandler = eventHandlers[timerHandleId]
local unit freedUnit = freedUnits[timerHandleId]
local trigger dispelTrigger = dispelTriggers[timerHandleId]
// do an assertion on freedUnit here to make sure it doesn't still have the buff
// call eventHandler
// call RemoveHandles
call DestroyTrigger(dispelTrigger)
call DestroyTimer(GetExpiredTimer())
endfunction
private function Register takes code eventHandler, integer buffDuration, unit unitWithBuff returns nothing
local timer t = CreateTimer()
local trigger trig = CreateTrigger()
call TimerStart(t, buffDuration, false, function TimerExpires)
call TriggerRegisterUnitEvent(trig, unitWithBuff, EVENT_UNIT_SPELL_CAST)
call TriggerAddAction(trig, function UnitPurged)
set freedUnits[GetHandleId(t)] = unitWithBuff
//set eventHandlers[GetHandleId(t)] = function eventHandler
set dispelTriggers[GetHandleId(t)] = trig
endfunction
endlibrary
Scrap what you quoted there, I was doing it wrong with a hashtable.
Well, considering I just want to know if the unit lost or added a buff, and ofc if it was refreshed:Might be difficult to keep doing it without retaining a table of handles though. Could still be doable depending on your actions.
You won't be able to directly pull the unit in question that lost the buff if it was when the timer expired. You'd have to track it somehow, in a hashtable of trigger and unit.
Uh. It MIGHT be doable in GUI, but someone else would have to give it a go. I don't use GUI.
library UnitLosesBuff
globals
// Index: timerHandleId
private unit array freedUnits
// Index: unitHandleId
private timer array freedTimers
private trigger array eventHandlers
private trigger array dispelTriggers
private integer array buffCodes
endglobals
private function UnitPurgedCondition takes nothing returns boolean
local unit castee = GetSpellTargetUnit()
local integer buffCode = buffCodes[GetHandleId(castee)]
if (GetUnitAbilityLevel(castee, buffCode) > 0) then
return false
endif
return true
endfunction
private function UnitPurged takes nothing returns nothing
local unit castee = GetSpellTargetUnit()
local integer casteeId = GetHandleId(castee)
local timer casteeTimer = freedTimers[casteeId]
local integer casteeTimerId = GetHandleId(casteeTimer)
local trigger eventHandler = eventHandlers[casteeId]
// I am assuming here that you WANT your handler to fire if the unit is purged
call TriggerExecute(eventHandler)
call DestroyTrigger(eventHandler)
call DestroyTimer(casteeTimer)
call DestroyTrigger(GetTriggeringTrigger())
set freedUnits[casteeTimerId] = null
set freedTimers[casteeId] = null
endfunction
private function TimerExpires takes nothing returns nothing
local integer timerId = GetHandleId(GetExpiredTimer())
local unit freedUnit = freedUnits[timerId]
local integer freedUnitId = GetHandleId(freedUnit)
local trigger eventHandler = eventHandlers[freedUnitId]
local trigger dispelTrigger = dispelTriggers[freedUnitId]
// As long as the UnitPurged trigger works, this local and the if block won't be needed.
local integer buffCode = buffCodes[freedUnitId]
if (GetUnitAbilityLevel(freedUnit, buffCode) == 0) then
call TriggerExecute(eventHandler)
endif
call DestroyTrigger(eventHandler)
call DestroyTrigger(dispelTrigger)
call DestroyTimer(GetExpiredTimer())
set freedUnits[timerId] = null
set freedTimers[freedUnitId] = null
endfunction
public function Register takes trigger handlerTrigger, integer buffDuration, unit unitWithBuff, integer buffCode returns nothing
local timer buffExpiresTimer
local trigger purgeTrigger = CreateTrigger()
local integer unitId = GetHandleId(unitWithBuff)
if (freedTimers[unitId] == null) then
set freedTimers[unitId] = CreateTimer()
endif
call TimerStart(freedTimers[unitId], buffDuration, false, function TimerExpires)
set freedUnits[GetHandleId(freedTimers[unitId])] = unitWithBuff
call TriggerRegisterUnitEvent(purgeTrigger, unitWithBuff, EVENT_UNIT_SPELL_EFFECT)
call TriggerAddCondition(purgeTrigger, Condition(function UnitPurgedCondition))
call TriggerAddAction(purgeTrigger, function UnitPurged)
set dispelTriggers[unitId] = purgeTrigger
set eventHandlers[unitId] = handlerTrigger
set buffCodes[unitId] = buffCode
endfunction
endlibrary
Time - Every 0.10 seconds of game time
*cringe*
I'm not sure how the handle IDs work. Do I really need to use a hashtable for one column entries? Can I not just use an array with the handleID as the index?
... thats not what I asked
Ugh, I can't make a code array? I can't call a code variable? I can't store them in hashtables? How can I track a function then?
local triggercondition trigcon = TriggerAddCondition(someTrigger, Condition(function myFunction))
call TriggerEvaluate(someTrigger)
call TriggerRemoveCondition(someTrigger, trigcon)
you cant create code arrays but you can create boolexpr arrays (boolexpr are functions that have no parameters and return a boolean)
you can execute them this way:
make sure myFunction returns a boolean (no matter if true or false i believe)JASS:local triggercondition trigcon = TriggerAddCondition(someTrigger, Condition(function myFunction)) call TriggerEvaluate(someTrigger) call TriggerRemoveCondition(someTrigger, trigcon)
you can also use a normal function, save its name as string and call it with ExecuteFunc(String func)
but afaik ExecuteFunc is synced and TriggerEvaluate is not