• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

local timers and MUI

Status
Not open for further replies.
Level 7
Joined
Aug 19, 2009
Messages
278
Are local timers MUI?

Like i create a timer
JASS:
local timer t
set t = CreateTimer()
call TimerStart(t,5,true,function knockback)

If in those 5 seconds, another timer starts from the same trigger. Will the first one be executed then the second?
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
When you write a variable as the argument of a function, here t in TimerStart, the stuff that the function runs will not be linked to the variable but to an object. It's only that the current (when this line of code is executed) value behind the variable gets used for the function.

So even if you write
JASS:
local timer t
set t = CreateTimer()
call TimerStart(t,5,true,function knockback)
set t = null

the timer will still continue running and expire with a valid timer object.

Now CreateTimer allocates a new timer object, so you always start another one.
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
When you write a variable as the argument of a function, here t in TimerStart, the stuff that the function runs will not be linked to the variable but to an object. It's only that the current (when this line of code is executed) value behind the variable gets used for the function.

So even if you write
JASS:
local timer t
set t = CreateTimer()
call TimerStart(t,5,true,function knockback)
set t = null

the timer will still continue running and expire with a valid timer object.

Now CreateTimer allocates a new timer object, so you always start another one.

not possible to make siomething like this?
JASS:
local timer t
local integer i
set t = CreateTimer()
set i = GetHandleId(t)
set ugd_GlobalTimer[i]=t
call TimerStart(ugd_GlobalTimer[i],5,true,function knockback)
set t = null

or in function i cant destroy the ugd_GlobalTimer[GetHandleId(GetExpiredTimer())]?
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
Any reason why you extract the id out of an object in order to get the object from its id again? Of course, you can destroy the object however you get this object. I do not know what your question aims at.

lets say we talk about a single shoot timer then how could i pass data without hashtable to correct expiration function and destory timer if in expire time function the t (like local timer) not exist since it was declared in another function?
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
What do you think the GetExpiredTimer is that you just wanted to read data from? The expired timer is the timer that you set to run the function. There is no local timer, it's a local timer variable. All object variables are merely pointers to the real thing, the object. When you set t = null, this reference is denied but this does not affect the object that you can get through further variables or functions.
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
What do you think the GetExpiredTimer is that you just wanted to read data from? The expired timer is the timer that you set to run the function. There is no local timer, it's a local timer variable. All object variables are merely pointers to the real thing, the object. When you set t = null, this reference is denied but this does not affect the object that you can get through further variables or functions.

so i can use something like this?
DestroyTimer(expiredtimer())?

timer handle id is a normal number, right? so i can use for indexing the data for expired function like unit[timer handle id], damage[timer handle id] then unit[expiredtimer handle id],damage[expiredtimer handle id]?
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
so i can use something like this?
DestroyTimer(expiredtimer())?

Yes

timer handle id is a normal number, right?

GetHandleId returns an integer. Yes

so i can use for indexing the data for expired function like unit[timer handle id], damage[timer handle id] then unit[expiredtimer handle id],damage[expiredtimer handle id]?

No, because the ids of timers are too great a number. Timers belong to the parent type agents which generally start from 2^20 counting upwards in id. Arrays however only offer slots between 0 and 8190/8191. You could surely subtract this start offset 2^20 but there can be so many agents at a time that it's quite possible exceed 8k and you need to pay attention that you clean up everything properly then, else you would always fetch higher ids. That's why one usually takes hashtable.
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
Yes



GetHandleId returns an integer. Yes



No, because the ids of timers are too great a number. Timers belong to the parent type agents which generally start from 2^20 counting upwards in id. Arrays however only offer slots between 0 and 8190/8191. You could surely subtract this start offset 2^20 but there can be so many agents at a time that it's quite possible to have more than 8k and you need to pay attention to you clean up everything properly then, else you would always fetch higher ids. That's why one usually takes hashtable.

but since hashtable slower than dont slowdown the whole game if u use it for every spell and have alot spell?
i heard about linked list, that dont work? (anyway if for each spell type i use a linked list then could be many variable,no?)

for hashtable also needed unit group and counting etc, could be many useless action only for make something what isnt periodic (like trigger firebolt)
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Hashtable is not so slow but you can take other strategies yes.

A linked list is when one object points to another one, this one to the next and so on. They form a chain where each node knows its follow-up. You can therefore iterate through all instances starting from the head node. Does not mean that there would be no other types of lists though that you can loop as well over.

When you want to run a function periodically at a short intervals like 0.03125, you could think that because it's so frequent, it makes hardly a difference whether you create an expiring timer for each instance or only have one timer that controls all instances every 0.03125 seconds. The single timer method would be cheaper in performance overall of course.

JASS:
function TimerFunction takes nothing returns nothing
    loop over OBJECTS starting from 0
endfunction

function Start takes nothing returns nothing
    set OBJECTS_COUNT = OBJECTS_COUNT + 1

    set OBJECTS[OBJECTS_COUNT] = CreateObject()

    if (OBJECTS_COUNT == 0) then
        call TimerStart(CreateTimer(), 0.03125, true, function TimerFunction)
    endif
endfunction

So, this requires no GetExpiredTimer nor reading out data from it since it's stored globally.

With a longer timer like 8 seconds, you would not want to use one single timer that only fires every 8 seconds because the second instance could be started 2 seconds after the first, so they really should have that offset and not run at the same time. You could either use separate timers where you have to somehow retrieve data from like with hashtable or you start a single timer with an interval that covers both expiration times like 2 seconds here (or first 8 seconds and then switch to 2). So as the first instance launches, it takes 4 iterations to get up to 8 seconds and the second instance arrives another iteration after that. This would naturally require you to keep track of the iterations, countdown/timer setups and therefore you create your own timer execution system kind of. Well, the question is whether this really needs less performance than the other path, is also very dependent on the actual scenario how much instances when appear, what interval etc. And some loss of accuracy.

edit: There is also the old SetTimerData trick, which abuses a bug, but I believe it was slower than hashtable so was deprecated.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Well maybe allocate a big timer stack right in the beginning, so they get consecutive ids.

That was i was talking about the fastest way. But as you mentionned the problem with that : static, you have to know how many timers at max you will use at the same time, or just waste useless handles and memory.
But what i meant is this bug abuse VS TimerUtils ("blue" version) way.
 
Status
Not open for further replies.
Top