- 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?
)
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
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.
For Loop 1-8190
Trigger - Add to Buff <gen> the event (Time - BuffRemoveTimer[(Integer A)] expires)
Unless 8190 events makes no strain on the system ? I don't really know.
Init

Events


Map initialization

Conditions

Actions


For each (Integer LoopA) from 0 to 100, do (Actions)



Loop - Actions




Trigger - Add to RemoveBuff <gen> the event (Time - BuffRemoveTimer[LoopA] expires)
AddBuff

Events


Unit - A unit Starts the effect of an ability

Conditions


(Ability being cast) Equal to CriticalMod

Actions


If (Key Less than 100) then do (Set Key = Key + 1) else do (Set Key = 0)


Set BuffUnit[Key] = (Target unit of ability being cast)


Custom script: if TimerGetRemaining(udg_BuffRemoveTimer[udg_Key]) > 0.00 then


Custom script: call PauseTimer(udg_BuffRemoveTimer[udg_Key])


Custom script: call DestroyTimer(udg_BuffRemoveTimer[udg_Key])


Custom script: endif


For each (Integer LoopA) from 0 to 100, do (Actions)



Loop - Actions




Custom script: if udg_BuffUnit[udg_LoopA] == GetSpellTargetUnit() then




Custom script: set udg_BuffUnit[udg_LoopA] = null




Custom script: exitwhen true




Custom script: endif


Countdown Timer - Start BuffRemoveTimer[Key] as a One-shot timer that will expire in 30.00 seconds
RemoveBuff

Events

Conditions

Actions


Set ExpiredTimer = (Expiring timer)


For each (Integer LoopA) from 0 to 100, do (Actions)



Loop - Actions




Custom script: if udg_ExpiredTimer == udg_BuffRemoveTimer[udg_LoopA] then




Custom script: exitwhen true




Custom script: endif


-------- LoopA = our index now --------


Game - Display to (All players) the text: ((Name of BuffUnit[LoopA]) + lost buff!)


Custom script: set udg_BuffUnit[udg_LoopA] = null
PurgeBuff

Events


Unit - A unit Starts the effect of an ability

Conditions


(Ability being cast) Equal to Purge

Actions


For each (Integer LoopA) from 0 to 100, do (Actions)



Loop - Actions




Custom script: if udg_BuffUnit[udg_LoopA] == GetSpellTargetUnit() then




Custom script: exitwhen true




Custom script: endif


-------- LoopA = our index now --------


Game - Display to (All players) the text: ((Name of BuffUnit[LoopA]) + got buff purged!)


Custom script: set udg_BuffUnit[udg_LoopA] = null
UnitLosesBuffGUI

Events

Conditions

Actions


Set spellCode = (Integer(Bblo))


Set trackedUnit = No unit


Set existingTrigger = Melee Initialization <gen>


Set buffDuration = 8


Custom script: call UnitLosesBuff_Register(udg_existingTrigger, udg_buffDuration, udg_trackedUnit, udg_spellCode)
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
Melee Initialization

Events


Map initialization

Conditions

Actions


Hashtable - Create a hashtable


Set BUFF_HASH = (Last created hashtable)


-------- ---------------------------------------- --------


Custom script: call SaveInteger(udg_BUFF_HASH, 'AUfu', 0, 'BUfa')


Custom script: call SaveStr(udg_BUFF_HASH, 'BUfa', 0, "Frost Armor")


-------- ---------------------------------------- --------


Custom script: call SaveInteger(udg_BUFF_HASH, 'Ainf', 0, 'Binf')


Custom script: call SaveStr(udg_BUFF_HASH, 'Binf', 0, "Inner Fire")
Cast

Events


Unit - A unit Starts the effect of an ability

Conditions

Actions


Custom script: if HaveSavedInteger(udg_BUFF_HASH, GetSpellAbilityId(), 0) then


Set U = (Target unit of ability being cast)


Custom script: set udg_ID = GetHandleId(udg_U)


Set I1 = (Load 0 of ID from BUFF_HASH)


Custom script: call SaveInteger(udg_BUFF_HASH, udg_ID, 100+udg_I1, LoadInteger(udg_BUFF_HASH, GetSpellAbilityId(), 0))


Hashtable - Save (I1 + 1) as 0 of ID in BUFF_HASH


Unit Group - Add U to BUFF_GRP


Trigger - Turn on Loop <gen>


Custom script: endif
Loop

Events


Time - Every 0.10 seconds of game time

Conditions

Actions


Unit Group - Pick every unit in BUFF_GRP and do (Actions)



Loop - Actions




Set U = (Picked unit)




Custom script: set udg_ID = GetHandleId(udg_U)




Set I1 = (Load 0 of ID from BUFF_HASH)




For each (Integer A) from 1 to I1, do (Actions)





Loop - Actions






Set I2 = (Load ((Integer A) + 99) of ID from BUFF_HASH)






Custom script: if GetUnitAbilityLevel(udg_U, udg_I2) == 0 then






Game - Display to Player Group - Player 1 (Red) for 5.00 seconds the text: ((Proper name of U) + ( lost + (Load 0 of I2 from BUFF_HASH)))






If (All Conditions are True) then do (Then Actions) else do (Else Actions)







If - Conditions








I1 Equal to 1







Then - Actions








Hashtable - Clear all child hashtables of child ID in BUFF_HASH








Unit Group - Remove U from BUFF_GRP








If (All Conditions are True) then do (Then Actions) else do (Else Actions)









If - Conditions










(BUFF_GRP is empty) Equal to True









Then - Actions










Trigger - Turn off (This trigger)









Else - Actions







Else - Actions








Hashtable - Save (I1 - 1) as 0 of ID in BUFF_HASH








Hashtable - Save (Load ((Integer A) + 100) of ID from BUFF_HASH) as ((Integer A) + 99) of ID in BUFF_HASH






Custom script: endif
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
