trying to wrap up my timer system

GFreak45

I didnt slap you, i high 5'd your face.
Reaction score
130
ok, so i got it to compile, then i added the half-way skip for creating a new timer but now im having issues running the timers, i cant seem to figure out where it went wrong, i have included the code and the example i am using to test the code

JASS:
library TimerSync/* v1.00
  */ uses /*
        */optional T32/*

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*                                                                         *
*    API:                                                                 *
*                                                                         *
*    function NewTimer takes real timeout, code c, returns integer        *
*        creates a new timer and returns the integer id of the code       *
*        used to identify where the code is and what timer it is          *
*        attached to                                                      *
*                                                                         *
*    function MinimizeTimerSync takes real sizedesired returns nothing    *
*        deallocates the instances required to reduce the current list    *
*        to the desired size (does overwrite timers when not in debug     *
*        mode but wont when in debug mode and will give an error msg,     *
*        this should only be done when you will create no timers          *
*        for the rest of the game larger than the current size and it     *
*        should only be used to drop to the new max size)                 *
*                                                                         *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    globals/*

===========================================================================
============================== USER SETTINGS ==============================
===========================================================================
*/
        private constant real INIT_SIZE = 40.0
      //this is the initial size of the list, should be a multiple of
      //FIRST_DIMENSION_GAP

        private constant real FIRST_DIMENSION_GAP = 4.0
      //this is the gap between timers in organization in the first
      //dimension, this should be a multiple of SECOND_DIMENSION_GAP

        private constant real SECOND_DIMENSION_GAP = 0.5
      //this is the gap between timers organization in the second
      //dimension, it is best if this small, but it MUST be smaller
      //than or equal to FIRST_DIMENSION_GAP, should be a multiple of
      //COMBINE_GAP

        private constant real COMBINE_GAP = 0.1
      //this is how close the timers must be to each other in order to
      //combine them, it is best if this is small, but it MUST be smaller
      //than or equal to SECOND_DIMENSION_GAP

        private constant boolean USE_T32 = true
      //this should only be false if you DO have Timer32 and DO NOT want
      //to use the same interval but it does not matter at all if you are
      //not using Timer32

        private real INTERVAL = 0.025
      /*this is the interval that it updates the time on the timers left,
        this is only used if Timer32 is not available or USE_T32 is false

===========================================================================
============================ END USER SETTINGS ============================
===========================================================================

      */private real SIZE = INIT_SIZE
    
    endglobals

    //! textmacro VARS takes D
        static real time$D$
        static thistype headLoc$D$
        thistype next$D$
        thistype previous$D$
    //! endtextmacro

    private struct TS extends array
        static integer array codeRecycler
        static integer lastCodeRecycled
        static integer codeListSize
        thistype nextCode
        thistype previousCode
        thistype headCode
        thistype nextCodelist
        thistype previousCodelist
        thistype nextSleep
        thistype previousSleep
        thistype headSleep
        boolexpr thisCode
        boolean waitCode
        thistype codeCDHead
        thistype nextTimer
        thistype previousTimer

        //above this line is the list for the code/managing what timer they are on, after is the rest of the system

        static thistype halfWay
        static real halfWayTime
        static integer halfWayCounter = 2
        boolean timerFire
        debug boolean timerEncapsuled
        trigger trig
        //! runtextmacro VARS("FD")
        //! runtextmacro VARS("SD")
        //! runtextmacro VARS("CD")
        //yup im that lazy <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" />

        static integer array recycleList
        static integer lastRecycled = 0
        static integer listSize = 0

        //below this line is the actual system, above it are the variables

        static method pause takes nothing returns boolean
            call TriggerSleepAction(0.01)
        endmethod

        method deallocateCD takes nothing returns nothing
            set this.nextCD.previousCD = this.previousCD
            set this.previousCD.nextCD = this.nextCD
            call DestroyTrigger(this.trig)
            set this.timerFire = false
            set .recycleList[.lastRecycled] = this
            set .recycleList[this] = 0
            set .lastRecycled = this
        endmethod

        method deallocateSD takes nothing returns nothing
            set this.nextSD.previousSD = this.previousSD
            set this.previousSD.nextSD = this.nextSD
            call DestroyTrigger(this.trig)
            set this.timerFire = false
            set .recycleList[.lastRecycled] = this
            set .recycleList[this] = 0
            set .lastRecycled = this
        endmethod

        method deallocateFD takes nothing returns nothing
            set this.nextFD.previousFD = this.previousFD
            set this.previousFD.nextFD = this.nextFD
            call DestroyTrigger(this.trig)
            set this.timerFire = false
            debug set this.timerEncapsuled = false
            set .recycleList[.lastRecycled] = this
            set .recycleList[this] = 0
            set .lastRecycled = this
        endmethod

        static method allocate takes nothing returns thistype
            local integer this = .recycleList[0]
            if this == 0 then
                debug if .listSize &gt; 8190 then
                debug     call BJDebugMsg(&quot;TimerSync ERROR: you have exceded the maximum timer sync length of &quot;+I2S(R2I(8190 * INTERVAL + 0.5))+&quot; seconds, use a generic timer.&quot;)
                debug     return 0
                debug endif
                set .listSize = .listSize + 1
                return .listSize
            endif
            set .recycleList[0] = .recycleList[this]
            set .recycleList[this] = 0
            return this
        endmethod

        static method extend takes nothing returns nothing
            local thistype this = thistype.allocate()
            local thistype thisSD = this
            local thistype thisCD = this
            local integer a = R2I(FIRST_DIMENSION_GAP/SECOND_DIMENSION_GAP + 0.5) - 1
            local integer b
            if this != 0 then
                set this.nextFD = .headLocFD
                set this.previousFD = .headLocFD.previousFD
                set .headLocFD.previousFD = this
                set this.previousFD.nextFD = this
                set this.nextSD = this
                set this.previousSD = this
                set this.nextCD = this
                set this.previousCD = this
                set this.timerFire = false
                set this.trig = CreateTrigger()
                loop
                    exitwhen a == 0
                    if thisSD != 0 then
                        set thisSD.nextSD = this
                        set thisSD.previousSD = this.previousSD
                        set thisSD.nextSD.previousSD = thisSD
                        set thisSD.previousSD.nextSD = thisSD
                        set b = R2I(SECOND_DIMENSION_GAP + 0.5) - 1
                        set thisCD = thisSD
                        loop
                            exitwhen b == 0
                            if thisCD != 0 then
                                set thisCD.nextCD = thisSD
                                set thisCD.previousCD = this.previousCD
                                set thisCD.nextCD.previousCD = thisCD
                                set thisCD.previousSD.nextCD = thisCD
                                set thisCD.timerFire = false
                                set thisCD.trig = CreateTrigger()
                                set thisCD = thistype.allocate
                            endif
                            set b = b - 1
                        endloop
                        set thisSD = thistype.allocate()
                    endif
                    set a = a - 1
                endloop
                set SIZE = SIZE + FIRST_DIMENSION_GAP
                set .halfWayCounter = .halfWayCounter + 1
                if .halfWayCounter == 4 then
                    set .halfWayCounter = 2
                    set .halfWay = .halfWay.nextFD
                    set .halfWayTime = .halfWayTime + FIRST_DIMENSION_GAP
                endif
            endif
        endmethod

        static if LIBRARY_T32 and USE_T32 then
            private method periodic takes nothing returns nothing
        else
            private static method periodic takes nothing returns nothing
        endif
            set .timeFD = .timeFD + INTERVAL
            set .timeSD = .timeSD + INTERVAL
            set .headLocCD = .headLocCD.nextFD
            if .timeSD &gt;= SECOND_DIMENSION_GAP then
                set .timeSD = 0
                set .headLocSD = .headLocSD.nextSD
                set .headLocCD = .headLocSD
            endif
            if .timeFD &gt;= FIRST_DIMENSION_GAP then
                set .timeFD = 0
                if .headLocFD.nextFD == 0 then
                    set .headLocFD = thistype(0).nextFD
                else
                    set .headLocFD = .headLocFD.nextFD
                endif
                set .headLocSD = .headLocFD
                set .headLocCD = .headLocFD
            endif
            if .headLocCD.timerFire then
                call TriggerEvaluate(.headLocCD.trig)
                call TriggerClearConditions(.headLocCD.trig)
            endif
        endmethod

        static if USE_T32 then
            implement optional T32x
        endif

        private static method onInit takes nothing returns nothing
            local timer t = CreateTimer()
            local integer i = R2I((INIT_SIZE/FIRST_DIMENSION_GAP) + 0.5)
            static if LIBRARY_T32 and USE_T32 then
                set INTERVAL = T32_PERIOD
                call DestroyTimer(t)
            else
                call TimerStart(t, INTERVAL, true, function thistype.periodic)
            endif
            loop
                exitwhen i == 0
                call thistype(0).extend()
                set i = i - 1
            endloop
            set t = null
        endmethod

    endstruct

    function NewTimer takes real timeout, code c returns integer
        local TS this = TS.headLocFD
        local real time = timeout
        debug if timeout &lt;= 8190 * INTERVAL then
            if SIZE &lt; timeout then
                set this = this.previousFD
                set time = time - I2R(R2I(FIRST_DIMENSION_GAP*(I2R(R2I(time/FIRST_DIMENSION_GAP)))))
                loop
                    exitwhen SIZE &gt;= timeout
                    call TS.extend()
                    set this = this.nextFD
                endloop
            endif
            if time &gt;= TS.halfWayTime then
                set time = time - TS.halfWayTime
                set this = TS.halfWay
            endif
            loop
                exitwhen time - FIRST_DIMENSION_GAP &lt; 0.0
                set time = time - FIRST_DIMENSION_GAP
                set this = this.nextFD
            endloop
            loop
                exitwhen time - SECOND_DIMENSION_GAP &lt; 0.0
                set time = time - SECOND_DIMENSION_GAP
                set this = this.nextSD
            endloop
            loop
                exitwhen time - COMBINE_GAP &lt; 0.0
                set time = time - COMBINE_GAP
                set this = this.nextCD
            endloop
            call TriggerAddCondition(TS.headLocCD.trig, Filter(c))
            set this.timerFire = true
            debug set this.nextFD.previousFD.timerEncapsuled = true
            return this
        debug else
        debug     call BJDebugMsg(&quot;TimerSync ERROR: you have exceded the maximum timer sync length of &quot;+I2S(R2I(8190 * INTERVAL + 0.5))+&quot; seconds, use a generic timer.&quot;)
        debug endif
        debug return 0
    endfunction

    function MinimizeTimerSync takes real sizedesired returns nothing
        local TS this = TS.headLocFD.previousFD
        debug local real size = SIZE - sizedesired
        debug local real time = 0.0
        loop
            exitwhen SIZE - FIRST_DIMENSION_GAP &lt;= sizedesired
            debug exitwhen this.timerEncapsuled
            if this.nextCD == this.nextSD.previousSD then
                if this.nextSD == this.nextFD.previousFD then
                    set this = this.previousFD
                    call TS(this.nextFD).deallocateFD()
                    set SIZE = SIZE - FIRST_DIMENSION_GAP
                    debug set time = time + FIRST_DIMENSION_GAP
                else
                    set this = this.nextSD
                    call TS(this.previousSD).deallocateSD()
                endif
            else
                set this = this.nextCD
                call TS(this.previousCD).deallocateCD()
            endif
            set TS.halfWayCounter = TS.halfWayCounter - 1
            if TS.halfWayCounter == 0 then
                set TS.halfWayCounter = 2
                set TS.halfWay = TS.halfWay.previousFD
                set TS.halfWayTime = TS.halfWayTime - FIRST_DIMENSION_GAP
            endif
        endloop
        debug if time + FIRST_DIMENSION_GAP &gt;= size then
        debug     call BJDebugMsg(&quot;TimerSync Message: Successfully reduced the size of the Timer Sync list by &quot;+I2S(R2I(time))+&quot; seconds.&quot;)
        debug else
        debug     call BJDebugMsg(&quot;TimerSync ERROR: You attempted to deallocate &quot;+I2S(this)+&quot; and it currently contains a timer.  You can not do this in debug mode.&quot;)
        debug endif
    endfunction
endlibrary


JASS:
scope Example initializer OnInit

    function ExCall takes nothing returns nothing
        call NewTimer(2.0, function ExCall)
        call BJDebugMsg(&quot;TimerSync Example: Periodic working correctly&quot;)
    endfunction
    
    function ExCallTwo takes nothing returns nothing
        call BJDebugMsg(&quot;TimerSync Example: Normal Timer working correctly&quot;)
    endfunction

    function OnInit takes nothing returns nothing
       call NewTimer(2.0, function ExCall)
       call NewTimer(5.0, function ExCallTwo)
    endfunction
    
endscope
 
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