System Key Timers 2

Sim

Forum Administrator
Staff member
Reaction score
534
Edit this thread with Key Timers 2.
 

Cohadar

master of fugue
Reaction score
209
A few advices for KT2:

You can optimize your load function by preloading triggerExecCount

Since triggers are never destroyed, you can create them all on Init
and set exec count to be the same as index of trigger in an array.

GetTriggerExecCount(Trigger) == i should always be true.

When you need to remove a trigger from place you do not swap it with the one on max[id] but only pass conditions
JASS:

if TriggerEvaluate(trig<i>) then
	call TriggerClearConditions(trig<i>)
        call TriggerAddCondition(trig<i>, Conditionz[max[id]])
        call TriggerClearConditions(trig[max[id]])
	set max[id]=max[id]-1
endif
</i></i></i>
 

Jesus4Lyf

Good Idea™
Reaction score
397
Flare>what exactly is different between this and key timers 1, and is it as easy to use?
Yes. Very, very easy to use. For you, and what you need to understand, it equates to this... Exactly the same as Key Timers 1 but with a significantly easier interface. If you want to compare with TT, then it's the same to use but you can specify period.

Basically, instead of calling the textmacro, you use function calls. See the KeyTimers2.w3x example map for details on similarities/differences. Should help. :D

Now that this system is established, I may start releasing some spells for it myself... :shades:

If people want to ask a request or two for different spells, I may give it a shot and post them as examples. :D


>preloading triggerExecCount
Preload as in call it on map init, or is there a call to make to preload the function for something (unfamiliar terminology)?

>GetTriggerExecCount(Trigger) == i should always be true.
In a perfect world. The whole point is to eliminate the array call. Of course, giving triggers unique integers would be fine, if only structs allowed you to specify their id... :banghead:

You have a good idea there, but I would just use your attachment method if I was going to involve arrays anyway. =/

I can't create the triggers on map init btw, because the system won't know what periods are in use or how many triggers to make.
 

Cohadar

master of fugue
Reaction score
209
Actually you can but never mind.
It is true that using attaching would be more sane.
 

Jesus4Lyf

Good Idea™
Reaction score
397
And more efficient for loading, which is what the whole point is - to exclude the array call and just use natives. :shades:

The real way to do it all is have the Add function return an integer (the trigger's unique id which means you'd never have to change the execcount again) which you use as the struct to attach things to, and you just forget all about using struct.create() and struct.destroy(). But that's terrible coding practise, even though it would work and be unbeatable in efficiency.

Edit instead of double post: New example spell created, demonstrating the full power of Key Timers 2: Sandman.
 

Flare

Stops copies me!
Reaction score
662
got a question about using KT with unit groups. im trying to make a spell that knocks back units as a dummy unit encounters them so im gonna add them to a unit group and bla bla bla. if i pick every unit within the group, and do the actions like so

JASS:
//However I pick every unit within unit group
set i.pushunit=(GetUnit ())//that should be GetEnumUnit i think but not totally sure ^^
call Do&lt;insert something here&gt;
//dont have WE open and i forget where my WC disc is so everythings a little unknown


would that (under the assumption that it works with one unit) work so that every unit that should be pushed, will be pushed at the same time, or will it wait until the timer ends before moving the next unit?

also, if it didnt wait until the timer was finished, would the variable overlap within the timer loop, making units stop for no apparent reason?
 

Jesus4Lyf

Good Idea™
Reaction score
397
Just got back from holidays...

Sorry your code is a bit vague. I explained elsewhere how to to something to all units within a certain radius... I'd use that method:
JASS:
local group g=CreateGroup()
local unit t
call GroupEnumUnitsInRange(g,GetUnitX(unit),GetUnitY(unit),distance,null)
	loop
		set t=FirstOfGroup(g)
		exitwhen t==null
		call GroupRemoveUnit(g,t)
		if &lt;CONDITIONS INVOLVING T WHICH IS ENUM UNIT&gt; then
			&lt;DO STUFF TO T WHICH IS ENUM UNIT&gt;
		endif
	endloop
call DestroyGroup(g)
set g=null

Note that these groups aren't reusable as they must remove all units from the group as it is used. However, since I assume you'll pause the units that are sliding, and that they'll slide with the dummy unit (which is not needed, you can just store an x and y in a variable) that they will not leave the radius anyway, and so will be included every time it loops. Using ForGroup is generally a bad idea in my opinion. Sometimes it's the best way though... But I tend to use this instead. Hope that helps, if it doesn't, ask for further help... Sorry that I've been on holidays and stuff, chances are this is out of date for you anyway. :p
 

Hatebreeder

So many apples
Reaction score
381
Just got back from holidays...

Sorry your code is a bit vague. I explained elsewhere how to to something to all units withing a certain radius... I'd use that method:
JASS:
local group g=CreateGroup()
local unit t
call GroupEnumUnitsInRange(g,GetUnitX(unit),GetUnitY(unit),distance,null)
	loop
		set t=FirstOfGroup(g)
		exitwhen t==null
		call GroupRemoveUnit(g,t)
		if &lt;CONDITIONS INVOLVING T WHICH IS ENUM UNIT&gt; then
			&lt;DO STUFF TO T WHICH IS ENUM UNIT&gt;
		endif
	endloop
call DestroyGroup(g)
set g=null

Note that these groups aren't reusable as they must remove all units from the group as it is used. However, since I assume you'll pause the units that are sliding, and that they'll slide with the dummy unit (which is not needed, you can just store an x and y in a variable) that they will not leave the radius anyway, and so will be included every time it loops. Using ForGroup is generally a bad idea in my opinion. Sometimes it's the best way though... But I tend to use this instead. Hope that helps, if it doesn't, ask for further help... Sorry that I've been on holidays and stuff, chances are this is out of date for you anyway. :p

Actually, I use that method for Stuff like "IsUnitEnemy(...) == true" in an If then else statement in the loop.
Since (At least of my knowledge) there is no System, where I can pass though Data from one struct, to a non-timer, non-dialog, non-trigger function (In this case, some Condition Function).
 

emjlr3

Change can be a good thing
Reaction score
395
that is what globals are for
 

0zaru

Learning vJASS ;)
Reaction score
60
Instead use a ForGroup call (Use a global variable,It must work if there are no waits (And you must not have waits since you use timers :p)). You can get a struct from a ForGroup callback with a get from GetTriggeringTrigger().
 

Jesus4Lyf

Good Idea™
Reaction score
397
... That's a really good point. You'll be able to load the struct from the ForGroup call just like from the timer trigger, using the GetTriggerExecCount thing. I still prefer using the FirstOfGroup loop over the ForGroup call though. It's just nicer in my opinion to keep everything in one chunk of code. More linear.
 

Jesus4Lyf

Good Idea™
Reaction score
397
I'd like to inform people of a not-so-important discovery.

Calling a function that returns a value from an array is FASTER than calling GetTriggerExecCount(GetTriggeringTrigger()).

That's right. It turns out my method was slower all along. I have updated KT2 accordingly. Additionally, I have done two other efficiency updates (the first of which can be applied to nearly all systems for efficiency gains). Instead of using local variables, use globals and pretend they're locals.

Bench tests have concluded that:

JASS:
local integer j=2

takes twice as long to execute as
JASS:
globals
integer J
endglobals
...
set J=2


Additionally, when reading the same value from an array 4 times, it is more efficient to store that value temporarily in a global, and refence that instead. If you read it 3 times, it is much the same, but slightly less efficient with the global (within 5% speed, off memory). If you read it 2 times, it is less efficient to store it first. I've applied this to optimize also.

KT2 is now significantly faster than it was before. If you apply the new version to Sharl and Sandman (keeping in mind to change GetExec(trig) thingie to KT_GetData()) then they don't lag at all. Which is amazing, imho. They're both full 3D MUI spells which micro manage between 40 and 400 pieces.

Anyway, KT2 Version 1.1 released. :)
 

Sim

Forum Administrator
Staff member
Reaction score
534
Wow, that is impressive Jesus. :)

Ungraveyarded. I'm using keytimers2 in my new spell and must say it is really efficient. Setting your own period is really a great feature, along with this system's efficiency brings it pretty high on my useful systems list. This system is really neat.

Plus, I was using the old version...

Any comments before I move this into the systems section?
 

Sim

Forum Administrator
Staff member
Reaction score
534
.

Any comments before I move this into the systems section?

As I said, this timer system is really neat.

> bench tested them, explained how they work, and written a report on them. Here it is:

That's a first! And you might want to write a tutorial on that, too. ;)

Impressive work. Definitely.

Approved.

EDIT: merged posts.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Benchmarked! Timer Systems in Warcraft III.

Took a year (originally released Christmas, 2007) and went through the graveyard and back to get approved, but it's back and now comes with detailed documentation.

I've gone through the trouble of downloading a selection of timer systems, analysed how they work, bench tested them, explained how they work, and written a report on them. I sincerely recommend that everyone goes and takes a look at it. The documentation is on the second post on the first page.

Go to that post

Note by Daxtreme - Message to users replying in this thread: Please DO NOT reduce this thread into any kind of flamewar over benchtests. Thanks.

Better preventing than reacting!
 

emjlr3

Change can be a good thing
Reaction score
395
would like to see some benchmarks comparing TimerUtils, and perhaps HSAS or one of the other more popular attachment methods.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Then benchmarks you will see.

I didn't bother bench testing the attaching method, for obvious reasons.
But in case those reasons aren't obvious, it's basically because it's insignificant compared to how fast the loop executes (100 to 1 kind of thing). More on the theory of that in my report; Timer Systems in Warcraft III.

The computer I tested them on had a reboot since the first tests, obviously, so I also re-benched KT2 for comparison, but even KT2's first result beats them all...

Anyway, using the same test as in my report (and I intend to update the report with these soon enough):

KT2 <3: ~32,000 executions per second.
TimerUtils Red: ~30,100 executions per second.
TimerUtils Blue: ~26,500 executions per second.
HSAS (used on a timer): ~24,800 executions per second.
I swear it's the fastest!: ~31,400 executions per second.

Ok. I want you all to note something. The "I swear it's the fastest!" test. That was me using:
JASS:
set FastFood[H2I(t)-0x100000]=Data

and
JASS:
local integer i=FastFood[H2I(GetExpiredTimer())-0x100000]


Key Timers 2 is faster. :nuts:
Key Timers 1 is in the vacinity of twice as fast.
Not to mention both are far, far more stable.
At this point in time, I can't imagine ever suggesting anyone use anything else. Except for 0.0 period timers.

There is a version 1.2 of KT2 coming some time, by the way. It won't improve the loop speed, just needs a little cleanup. :)

Edited: Version 1.01 of Timer Systems in Warcraft III has been released, including these results and their original test maps.

Edited again: Did another bench of TT, too. It averaged 31,900. Consistent with previous results. It's not just margin of error.
 
Reaction score
91
You'd better go an post this at wc3c.net, to increase popularity that is. ^^
Seems a decent system, though I have no idea how it would be faster than 0x100000 substraction since that is supposed to be the fastest...
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top