WC3JASS Jass Theory & Questions
One map, one Timer


Not sure if this should be here or in Jass Theory. But anyway.

I have tried to see if it is possible to use just one timer for one map (in my case; all: attackfunctions, timed effects, spells, calculation for time before a projectile reaches its destination etc with just one timer) and got inspired by the (not as efficient as they say) KT2. Now, KT2 have been successfully used in a number of things, but it could not handle the attacked-triggered functions well at all. So I tried my own way to make something using the KT2 ideas (tick-periods with a period time of 0.00125 seconds and register functions as triggers in initialisations and so on) However, My idea was using a loop inside the function triggered by the timer to find the first function that should ran, then let that function call a continuer to check for next etc until al functions that should run at the moment have been executed. Check code

Code: jass  [Select]
  2. /*Don't use/check this code, I got a WAY faster one further down in this thread*/
  3. library TimeralaRV
  4. globals
  5.     constant timer SMALLTIMER = CreateTimer()
  6.     constant timer LARGETIMER = CreateTimer() /*This timmer is added due to experiements with one low-freqency timer and one high-freqency timer*/
  7.     constant integer SMALLTIMERARRAY = 80
  8.     constant integer LARGETIMERARRAY = 180
  9.     constant real SMALLTIMEOUT = 0.00125
  10.     constant real LARGETIMEOUT = 0.2
  11.     integer SmallTimerWhichArray = 0
  12.     integer LargeTimerWhichArray = 0
  13.     boolean array SmallTimerArrayUsed[SMALLTIMERARRAY]
  14.     integer array SmallTimerArrayTicksLeft[SMALLTIMERARRAY]
  15.     trigger array SmallTimerArrayTrigger[SMALLTIMERARRAY]
  16.     unit array SmallTimerArrayDealer[SMALLTIMERARRAY]
  17.     unit array SmallTimerArrayReci[SMALLTIMERARRAY]
  18.     boolean array LargeTimerArrayUsed[LARGETIMERARRAY]
  19.     integer array LargeTimerArrayTicksLeft[LARGETIMERARRAY]
  20.     trigger array LargeTimerArrayTrigger[LARGETIMERARRAY]
  21. endglobals
  23. function TimeRunSmall takes nothing returns nothing
  24. local integer i = 0
  25. local boolean b = FALSE
  26. if SmallTimerArrayTicksLeft[0] == 1 then
  27.     call TriggerExecute(SmallTimerArrayTrigger[0])
  28.     set SmallTimerArrayTicksLeft[0] = 0
  29.     set SmallTimerArrayUsed[0] = FALSE
  30. else
  31.     if SmallTimerArrayTicksLeft[0] != 0 then
  32.         set SmallTimerArrayTicksLeft[0] = SmallTimerArrayTicksLeft[0] - 1
  33.     endif
  34.     loop
  35.         exitwhen b == TRUE
  36.         set i = i + 1
  37.         if SmallTimerArrayTicksLeft[i] == 1 then
  38.             set SmallTimerWhichArray = i
  39.             call TriggerExecute(SmallTimerArrayTrigger[i])
  40.             set SmallTimerArrayTicksLeft[i] = 0
  41.             set SmallTimerArrayUsed[i] = FALSE
  42.             set b = TRUE
  43.         else
  44.             if SmallTimerArrayTicksLeft[0] != 0 then
  45.                 set SmallTimerArrayTicksLeft[i] = SmallTimerArrayTicksLeft[i] - 1
  46.             endif
  47.             if i > SMALLTIMERARRAY then
  48.                 set b = TRUE
  49.             endif
  50.         endif
  51.     endloop
  52. endif
  53. endfunction
  56. function NextFunction takes nothing returns nothing /* A bit simplified, in reality I would need a simple way of determine if it should use the small or the large timer, but it is not relevant for the moment*/
  57. local integer i = SmallTimerWhichArray + 1
  58. local boolean b
  59. if SmallTimerArrayTicksLeft[i] == 1 then
  60.     call TriggerExecute(SmallTimerArrayTrigger[0])
  61.     set SmallTimerArrayTicksLeft[i] = 0
  62.     set SmallTimerArrayUsed[i] = FALSE
  63. else
  64.     if SmallTimerArrayTicksLeft[i] != 0 then
  65.         set SmallTimerArrayTicksLeft[i] = SmallTimerArrayTicksLeft[i] - 1
  66.     endif
  67.     loop
  68.         exitwhen b == TRUE
  69.         set i = i + 1
  70.         if SmallTimerArrayTicksLeft[i] == 1 then
  71.             set SmallTimerWhichArray = i
  72.             call TriggerExecute(SmallTimerArrayTrigger[i])
  73.             set SmallTimerArrayTicksLeft[i] = 0
  74.             set SmallTimerArrayUsed[i] = FALSE
  75.             set b = TRUE
  76.         else
  77.             if SmallTimerArrayTicksLeft[0] != 0 then
  78.                 set SmallTimerArrayTicksLeft[i] = SmallTimerArrayTicksLeft[i] - 1
  79.             endif
  80.             if i > SMALLTIMERARRAY then
  81.                 set b = TRUE
  82.             endif
  83.         endif
  84.     endloop
  85. endif
  86. endfunction
  88. endlibrary
However, when the NextFunction code is executed, the game shuts of. I don't know if it just is a protection against looping or if it actually creates an infinitive-loop here somewhere..

If someone have another way of using a singletimer for everything, or could tell me that their efficiency ain't much to talk about, I would like to hear ^^ (:

This topic isn't really a superimportant one for me, it's more a theory-question in that aspect.


This approach is very good in fact, because you reduce the handle count considerably. But this can bring issues in relation to the chances to have running at the same time several elements.

For example in my project PoC,  I did this approach and I had in some cases lags due too many instances happening at the same time (AI vs AI attacking each other with full army) this implied to use several timers (3 - 6) timers running at the same time distributing the load of the custom spells.

I separated them in this way:

1 timer for stuff with low frequency (period of 0.5s)
1 timer for hero abilities (high frequency)
1 timer for unit abilities (high frequency)

The load of the game was reduced.


Hmm, I dunno man, but don't you think it will just cause the game to be slow?


No, I run in my map 6 timers during all the game. Waht it makes slow the game is the amount of code running, like looping a big aount of data.

I remember when I used timerutils and from time to time the game got slowed, that's because it generates a lot of timers running at the same time. Timerutils works fine in AOS or games where custom spells and system not exceed more than 100 events or codes running at the same time.


I would really like to see the code of that function, cause, as said in another thread by me, I am using a jass-scripted attackfunction, which means that it have to handle the max-number of units on the map hitting a target at the same time (10players with a max of 12units inc. summons + 2computerplayers in dota or ts style, to be sure that I never reach the max-amount, I estimate about 200 timers would be needed JUST FOR THE ATTACKS in my current approach. With that, I estimated a max of about 150-200 timers for the spells/timed effects/some other misc stuff. Now, it have to be a very massive thing when all timers would be active at the same time, but still, 300-400 timers running can't be good on performance...

Now, as I said, by some reason, the wc3 wants to shut down if I register more than one attackfunction to the timer, probably cause it recognises some kind of loop, cause it SHOULD not run the exact same function with the exact same data in all infinity, but, well, it sure looks so..
You PoC aren't protected right? Would it be ok if I downloaded it and took some inpiration from your time-functions? (:

Off-topic question; It seems to me that you, Moyack, uses struct quite a lot, now, what I wonder is, are they in some way faster than array-variables, or do u just use them to simplifie code for you?