System Key Timers 2

Jesus4Lyf

Good Idea™
Reaction score
397
He may have meant that for me. He posted 2 minutes after your post. Your questions are certainly welcome.

>So, I can't pass on Data from one function to a timer, in which I pass on the same Data to a timer from the previous timer?

That... is very hard to understand. Let me get this straight...

Data gets passed to KT_Add attached to Func. Func calls KT_Add attaching either itself again, or something else, attaching the same Data.

Works fine. I think you'll be hard pressed to find obscure restrictions in this system. :)

As said, try it out. KT2 is actually a very neat and pleasant system to use.
 

wraithseeker

Tired.
Reaction score
122
I will once it gets approved at WC3C else I aren't using this as I prefer TimerUtils since it is a universal attaching system for people.
 

Jesus4Lyf

Good Idea™
Reaction score
397
>I will once it gets approved at WC3C

It won't. I was banned there a long time ago. This system is currently unique to TheHelper, and may even remain so.

>I prefer TimerUtils since it is a universal attaching system for people

Each to their own. KT2 is stabler, has a simpler interface, and runs more efficiently. ;)

I respect your right to decide, nonetheless.
 

Sim

Forum Administrator
Staff member
Reaction score
534
> TimerUtils

TimerUtils uses H2I, this doesn't.

If you want to know, in 1 sentence, the main difference between the 2.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Well, that will be the main difference soon. The only other substancial difference at the moment is the first procurement inaccuracy. I intend to fix that in the next version. But honestly, I don't think that's usually an issue. :)

As Vex said, if something was to be faster than TU Red, it would probably involve an alternative to H2I which is very unlikely to exist.

Welcome to KT2. ;)
 

Kenny

Back for now.
Reaction score
202
This is a pretty nice system. I've been "lurking" this thread for a while seeing the various updates made and all that, and I am very impressed by the amount of work you put into it, and by the fact that you support most of your arguments with evidence.

I've heard the issues that many people have with the cons list with this system (moreso the older versions), but i have to say that for someone like me, these cons are hardly noticable if you know what you are doing.

If i used this system, I would be only using a small amount of intervals, such as 0.03125, 0.04, 0.05 and maybe 0.02 if needed, and with these small intervals, the system is not only fast, but easy to use.

However, if I was to replace other systems, I would enjoy being able to use it with 1-2 second intervals, so I'm hoping this update your working on works well :D.

If I ever need to use a timer system for spells I will definately be giving this a try.

Also, im not sure if you have, but you should maybe update Sandman and Sharl to use the latest versions of KT2.

Once again, I'm impressed, nice work!
 

Cohadar

master of fugue
Reaction score
209
I will once it gets approved at WC3C else I aren't using this as I prefer TimerUtils since it is a universal attaching system for people.

Ye I noticed a lot of people are attached to it for no apparent reason.
 

Hatebreeder

So many apples
Reaction score
381
He may have meant that for me. He posted 2 minutes after your post. Your questions are certainly welcome.

>So, I can't pass on Data from one function to a timer, in which I pass on the same Data to a timer from the previous timer?

That... is very hard to understand. Let me get this straight...

Data gets passed to KT_Add attached to Func. Func calls KT_Add attaching either itself again, or something else, attaching the same Data.

Works fine. I think you'll be hard pressed to find obscure restrictions in this system. :)

As said, try it out. KT2 is actually a very neat and pleasant system to use.

The situation I discribed is similar to this... But, whatever, i kinda solved my Problem :3
Thanks.
 

Andrewgosu

The Silent Pandaren Helper
Reaction score
715
Actually, I don't find a reason why this should sit here even longer.

It's proved to be a working and a reliable system so far.

In addition, it's fast, based on the graphs.

Approved.
 

Jesus4Lyf

Good Idea™
Reaction score
397
YAY! Approved again.

The story of KT2 at this point: Submissions --> Graveyard --> Submissions --> Approved --> Graveyard (??) --> Submissions --> Approved.

Although, lol, sorry about the version name. It's KT2 Version 1.5. KT2 is a different system to KT1. I'll have to fix the thread name. :thup:

>Ye I noticed a lot of people are attached to it for no apparent reason.
Mmmmmm. o_O

>But, whatever, i kinda solved my Problem :3
Cool. ^_^

Is the system serving you well? :D

>im not sure if you have, but you should maybe update Sandman and Sharl to use the latest versions of KT2.

I'll get around to it. People can just copy/paste versions to upgrade anyway. I make sure of that much, as least. ;)

And thanks for the encouragement, kenny!! :)

Edit: It seems I can't change the thread name.
Can a moderator please change the thread name back to "Key Timers 2"? It seems there's a misunderstanding with my versioning. Key Timers 2 is a DIFFERENT SYSTEM to Key Timers 1, and the version of Key Timers 2 is 1.5. So the thread name should be "Key Timers 2", the name of the system.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Hibernate Timer

After much pacing around today, thinking about how to top off KT2 for higher periods, I have come up with a solution.

Here's the things I considered:
What's is the problem?

Well, KT2 is too inaccurate to be used in a useful way for large periods. The reality is there isn't likely to be heaps of use of large periods, and when there is it's probably only a few instances, tops. Therefore, although speed is desirable, it is not absolutely necessary. I need to bolt on an alternative system to traditional KT2 for when the period is above a certain value, to execute more efficiently and more accurately. KT2 is wonderful for low periods (amazing, even) but something needs to step in if the period used in "Add" is more than about 0.4.

I could simply implement TU Red behind the scenes. I could credit Vexorian for that, and have KT2 default to TU Red without the user caring what's going on. TU Red is rather fast, after all. However, TU Red is not safe and stable. I was even willing to break my no H2I policy for a moment, thinking about this, before I came up with my final solution...

I could implement TU Blue/ABCT behind the scenes, once again crediting Vexorian. But TU Blue/ABCT are not fast. Really they're fairly slow. And let's face it, if I did this, I'd forever have people hacking through my system trying to implement TU Red or raw H2I or whatever else instead. Plus, I'm not a big fan of H2I in general.

I could implement a single, low period timer system that counts down all instances in a loop. This is not efficient, but for high periods, who cares, right? As long as it makes a nice interface... Hmmm. Some people wouldn't be happy with that... But I could even make it "hibernate", as in, stop executing for a while if the next thing to execute is a while away.

... Wait a second...

Welcome to Hibernate Timer, my current solution, to be bolted onto KT2 for periods over about 0.4 seconds (specified by constant). Instead of having a list of things to tick down, Hibernate Timer stores them in a linked-list in the order they need to be fired. So it sets itself to expire when the next item needs it to, fires that, pushes it back in the list as far as it needs to go, then waits to fire the next one. Because of the nature of the way it works, it is unlikely to fire more than one instance at once (unless they're added at the same time, and I've optimised it for that, too) meaning this should actually be faster than KT2 for higher periods. In fact, it should really run quite fast, indeed. And optimisations can be made if it does not. But for now, it's important to get it out there. This prototype system probably doesn't work well for very low periods, which KT2 is good at. And KT2 doesn't work very well for higher periods, which Hibernate Timer is good at. Perfect.

Before I actually bolt this modification on, I'd like to a few opinions. So here is the code. Do not take this and start using it in your map directly, please. Although it would actually work (and probably quite well) you'll be better off just using it through KT2 when it comes out. I repeat, this is not an official release of anything. You'll notice the interface is exactly the same, and it will run invisibly inside KT2 once added.
JASS:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ HT ~~ Hibernate Timer ~~ By Jesus4Lyf ~~ PROTOTYPE ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//  What the hell is this?
//		 - This is a prototype system for higher periods, to be bolted onto KT2.
//		 - DO NOT USE THIS ON IT'S OWN! Except for testing.
//
//	=Pros=
//		 - It&#039;s awesome. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite7" alt=":p" title="Stick Out Tongue    :p" loading="lazy" data-shortname=":p" />
//		 - Very accurate period expiration!
//		 - Theoretically faster than KT2 version 1.5 for periods above about 0.3 seconds.
//
//	=Cons=
//		 - It&#039;s slower than KT2 for periods below about 0.3.
//
//	Functions:
//		THIS IS JUST A PROTOTYPE! REMEMBER THAT! UNOFFICIAL SYSTEM BE WARNED.
//		 - HT_Add(userFunc, struct, period)
//		 - HT_GetData returns the struct
//
//		 - userFunc is to be a user function that takes nothing and return boolean.
//		   It will be executed by the system every period until it returns true.
//
//		 - HT_GetData is to be used inside func, it will return struct passed to
//		   to the Add function.
//
//  How to import:
//		 - Create a trigger named HT.
//		 - Convert it to custom text and replace the whole trigger text with this.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library HT initializer HTinit
    globals
        private constant real MarginOfError=0.01
    endglobals
    
    // Rawr!
    globals
        private timer HT_Timer=CreateTimer()
        private timer HT_Moderator=CreateTimer()
        private real HT_Time=0.0
        private HTnode HT_Top
    endglobals
    
    globals
        private HTnode newHTnode
    endglobals
    struct HTnode
        HTnode prev // Make sure to link this before use
        HTnode next // Make sure to link this before use
        real period
        real firewhen // = HT_Time at creation
        trigger trig
        integer data
        static method new takes code func, integer data, real period returns HTnode
            set newHTnode=HTnode.create()
            if newHTnode.trig==null then
                set newHTnode.trig=CreateTrigger()
            else
                call TriggerClearConditions(newHTnode.trig)
            endif
            call TriggerAddCondition(newHTnode.trig,Condition(func))
            set newHTnode.data=data
            set newHTnode.period=period
            set newHTnode.firewhen=HT_Time
            return newHTnode
        endmethod
        method link takes HTnode prev, HTnode next returns nothing
            set prev.next=this
            set next.prev=this
            set this.next=next
            set this.prev=prev
        endmethod
        method unlink takes nothing returns nothing
            set this.prev.next=this.next
            set this.next.prev=this.prev
        endmethod
        method autolink takes HTnode start returns nothing
            loop
                if start.next==0 then
                    call this.link(start,0)
                    return
                endif
                if start.next.firewhen &gt; this.firewhen then
                    call this.link(start,start.next)
                    return
                endif
                set start=start.next
            endloop
        endmethod
    endstruct
    
    globals//locals
        private HTnode HT_handlenode
        private HTnode HT_handlenext
    endglobals
    private function HT_Handler takes nothing returns nothing
        set HT_handlenode=HT_Top
        set HT_handlenext=HT_handlenode.next
        loop
            set HT_handlenode=HT_handlenext
            exitwhen HT_handlenode==0 // Pause timer, nothing left to fire.
            set HT_handlenext=HT_handlenode.next
            if HT_handlenode.firewhen&lt;=HT_Time+MarginOfError then
                if TriggerEvaluate(HT_handlenode.trig) then
                    call HT_handlenode.unlink()
                    call HT_handlenode.destroy()
                else
                    set HT_handlenode.firewhen=HT_handlenode.firewhen+HT_handlenode.period
                    call HT_handlenode.unlink()
                    call HT_handlenode.autolink(HT_handlenode.prev)
                endif
            else
                // More to fire, but not yet.
                call TimerStart(HT_Timer,HT_handlenode.firewhen-HT_Time,false,function HT_Handler)
                return
            endif
        endloop
    endfunction
    
    public function GetData takes nothing returns integer
        return HT_handlenode.data
    endfunction
    
    globals//locals
        private HTnode HT_addnode
    endglobals
    public function Add takes code func, integer data, real period returns nothing
        set HT_addnode=HTnode.new(func, data, period)
        set HT_addnode.firewhen=HT_Time+period
        call HT_addnode.autolink(HT_Top)
        if HT_Top.next==HT_addnode then
            call TimerStart(HT_Timer,period,false,function HT_Handler)
        endif
    endfunction
    private function HT_ModeratorLoop takes nothing returns nothing
        set HT_Time=HT_Time+MarginOfError
    endfunction
    private function HTinit takes nothing returns nothing
        call TimerStart(HT_Moderator,MarginOfError,true,function HT_ModeratorLoop)
        set HT_Top=HTnode.create()
        set HT_Top.prev=0
        set HT_Top.next=0
        set HT_Top.firewhen=0.0
    endfunction
endlibrary
Oh, and the interface for KT2 will not change at all. Just another 2 cons or so will be shaved off. ;)
 

Jesus4Lyf

Good Idea™
Reaction score
397
Tell me about it.

I will after this, I think.

Edit: Discovered some nasties with the Hibernate Timer prototype. :p

Edit: Updated Hibernate Timer (the thing I'm bolting onto KT2 soon, hopefully).

Trying to debug thoroughly before it enters KT2. HT still can't run Sandman... And although it's not designed to, it should in theory.

Edit: Fixed Hibernate Timer. It now seems ready to bolt onto KT2. Any final thoughts on it? (It seems I like to pretend that people may have read and/or understood it.)
JASS:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ HT ~~ Hibernate Timer ~~ By Jesus4Lyf ~~ PROTOTYPE ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//  What the hell is this?
//		 - This is a prototype system for higher periods, to be bolted onto KT2.
//		 - DO NOT USE THIS ON IT&#039;S OWN! Except for testing.
//
//	=Pros=
//		 - It&#039;s awesome.
//		 - Very accurate period expiration!
//		 - Theoretically faster than KT2 version 1.5 for periods above about 0.3 seconds.
//
//	=Cons=
//		 - It&#039;s slower than KT2 for periods below about 0.3.
//
//	Functions:
//		THIS IS JUST A PROTOTYPE! REMEMBER THAT! UNOFFICIAL SYSTEM BE WARNED.
//		 - HT_Add(userFunc, struct, period)
//		 - HT_GetData returns the struct
//
//		 - userFunc is to be a user function that takes nothing and return boolean.
//		   It will be executed by the system every period until it returns true.
//
//		 - HT_GetData is to be used inside func, it will return struct passed to
//		   to the Add function.
//
//  How to import:
//		 - Create a trigger named HT.
//		 - Convert it to custom text and replace the whole trigger text with this.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library HT initializer HTinit
    globals
        private constant real MarginOfError=0.01
    endglobals
    
    // Rawr!
    globals
        private timer HT_Moderator=CreateTimer()
        private real HT_Time=0.0
        private HTnode HT_Top
    endglobals
    
    globals
        private HTnode newHTnode
    endglobals
    struct HTnode
        HTnode prev // Make sure to link this before use
        HTnode next // Make sure to link this before use
        real period
        real firewhen // = HT_Time at creation
        trigger trig
        integer data
        static method new takes code func, integer data, real period returns HTnode
            set newHTnode=HTnode.create()
            if newHTnode.trig==null then
                set newHTnode.trig=CreateTrigger()
            endif
            call TriggerAddCondition(newHTnode.trig,Condition(func))
            set newHTnode.data=data
            set newHTnode.period=period
            set newHTnode.firewhen=HT_Time
            return newHTnode
        endmethod
        method link takes HTnode prev, HTnode next returns nothing
            set prev.next=this
            set next.prev=this
            set this.next=next
            set this.prev=prev
        endmethod
        method unlink takes nothing returns nothing
            set this.prev.next=this.next
            set this.next.prev=this.prev
        endmethod
        method autolink takes HTnode start returns nothing
            loop
                if start.next==0 then
                    call this.link(start,0)
                    return
                endif
                if start.next.firewhen &gt; this.firewhen then
                    call this.link(start,start.next)
                    return
                endif
                set start=start.next
            endloop
        endmethod
    endstruct
    
    globals//locals
        private HTnode HT_handlenode
        private HTnode HT_handlenext
    endglobals
    private function HT_Handler takes nothing returns nothing
        set HT_handlenode=HT_Top
        set HT_handlenext=HT_handlenode.next
        loop
            set HT_handlenode=HT_handlenext
            exitwhen HT_handlenode==0 // Pause timer, nothing left to fire.
            set HT_handlenext=HT_handlenode.next
            if HT_handlenode.firewhen&lt;HT_Time+MarginOfError then
                if TriggerEvaluate(HT_handlenode.trig) then
                    call HT_handlenode.unlink()
                    call TriggerClearConditions(HT_handlenode.trig)
                    call HT_handlenode.destroy()
                else
                    set HT_handlenode.firewhen=HT_handlenode.firewhen+HT_handlenode.period
                    call HT_handlenode.unlink()
                    call HT_handlenode.autolink(HT_handlenode.prev)
                    if HT_handlenext==0 then
                        set HT_handlenext=HT_handlenode
                    endif
                endif
            else
                // More to fire, but not yet.
                return
            endif
        endloop
    endfunction
    
    public function GetData takes nothing returns integer
        return HT_handlenode.data
    endfunction
    
    globals//locals
        private HTnode HT_addnode
    endglobals
    public function Add takes code func, integer data, real period returns nothing
        set HT_addnode=HTnode.new(func, data, period)
        set HT_addnode.firewhen=HT_Time+period
        call HT_addnode.autolink(HT_Top)
        //if HT_Top.next==HT_addnode then
        //  //Old start timer stuff
        //endif
    endfunction
    private function HT_ModeratorLoop takes nothing returns nothing
        set HT_Time=HT_Time+MarginOfError
        if HT_Top.next.firewhen&lt;HT_Time then
            call HT_Handler()
        endif
    endfunction
    private function HTinit takes nothing returns nothing
        call TimerStart(HT_Moderator,MarginOfError,true,function HT_ModeratorLoop)
        set HT_Top=HTnode.create()
        set HT_Top.prev=0
        set HT_Top.next=0
        set HT_Top.firewhen=0.0
    endfunction
endlibrary
 

Jesus4Lyf

Good Idea™
Reaction score
397
KT2 Version 1.6.0 Release!

YAYYYY!

Released Version 1.6.0. :D

KT2 no longer suffers from the first period procurement inaccuracy that people have kept commenting on from time to time, it has error messages for invalid periods with a mismatch of up to 0.001 seconds, and it no longer has a maximum period.

KT2 is still the absolute fastest timer system (at the time of this post) for periods below 0.3 where it is necessary, and thereafter it's still fast, but also fires within 0.01 of when the period should expire. These constants are changable, but I don't recommend changing them.

What's the point?
KT2 is now not only overall the fastest timer system in existance (at the time of this post, and unless you're purposely trying to break it), but has a brilliantly nice interface, next to no limitations, and when compared to a normal timer system, the differences should be utterly invisible.

As for me, I'll probably take a break from updating it for a little while, as I've acomplished all I intend to at this point. Thanks to everyone who has helped it get to where it is now. :thup:

So what are you waiting for? Get into KT2! ;)

PS. Any requests for help with spells and things involving this system, etc, are welcome. :cool:
 

wraithseeker

Tired.
Reaction score
122
Is this still better then TimerUtils and why?

Maybe you should list a number of Pros and Cons for diehard fans of TimerUtils to switch over to.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Hmm. I'll let you know that I'm reluctant to do it, but I suppose I might as well. I'll try to be unbiased, but I did write KT2.
For periods of 0.3 and higher (waits, and very infrequent timed effects):
  • Measuring speed is too difficult and irrelevant because both of these systems distribute the processing time anyway.
  • KT2 is safer than TU red.
  • Both TU blue and KT2 are perfectly stable, and which is safer is debatable.
  • I haven't compared the add/remove call speed between KT2 and TU but TU is probably faster.
  • The interface of KT2 is faster to code with (opinion).
  • In KT2, there is a variable amount of processing done when periods over 0.3 tick.
For periods below 0.3 (timed effects in spells, etc):
  • KT2 is (on average) faster than TU red (see graphs).
  • KT2 is much faster than TU blue (see graphs).
  • KT2 is safer than TU red.
  • Both TU blue and KT2 are perfectly stable, and which is safer is debatable.
  • KT2 has slower add/remove calls than TU (haven't actually bench tested, but this is a reasonable assumption).
  • The interface of KT2 is faster to code with.
I want you to understand that really for periods over 0.3 it doesn't matter what you use, in terms of speed. It's up to preference as to what you like to code with. So KT2's objective is to allow you to use the same clean interface and stability and still run reasonably quickly (but TU red should be faster). But for periods under 0.3 there is no reason I can imagine not to use KT2. It's awesome for that.

Personally? I think I'm going to switch everything to KT2. Even hard coded struct/stack loops, in most cases. :cool:

PS. For many statements I've made, if you try hard enough to break them, you can. This is all subjective. My statements are aimed at realistic use. At the end of the day, choose whatever system you like. Opinions are opinions. :)
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top