• 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.

[vJASS] Timed Struct System

Status
Not open for further replies.
Level 7
Joined
Apr 30, 2011
Messages
359
PreciseTimer and TimedFunc

Timer Stack Draft (no documenttation):
JASS:
library TimerStack
    
    globals
        private integer       c   = 0
        private integer array r
        
        private integer array t
        
        private integer array nt
        private integer array pt
        private integer array lt
        
        private conditionfunc array cft
        
        private integer       tc  = 0
        private integer array tr
        
        private integer array tn
        private integer array tp
        private integer       tl
        
        private real    array tt
        private real    array trt
        private integer array ttc
        
        private trigger       trg = CreateTrigger()
        private timer         tmr
        private integer       cur
        private real          let
    endglobals
    
    private function GetType takes real time returns integer
        local integer this = tl
        local boolean exit = false
        
        loop
            exitwhen tp [tn [this]] == 0 or exit
            
            if tt [this] == time then
                set exit = true
            else
                set this = tp [this]
            endif
        endloop
        
        if not exit then
            set this = tr [0]
            
            if this == 0 then
                set tc   = tc + 1
                set this = tc
            else
                set tr [0] = tr [this]
            endif
            
            if tl == 0 then
                set tp [this] = 0
            else
                set tp [this] = tl
            endif
            
            set tn  [this] = 0
            set tl         = this
            set tr  [this] = -1
        endif
        
        set tt  [this] = time
        set trt [this] = time
        set ttc [this] = ttc [this] + 1
        
        return this
    endfunction
    
    private function LoseType takes integer this returns nothing
        if tr [this] == -1 then
            set ttc [this] = ttc [this] - 1
            
            if ttc [this] == 0 then
                if tn [this] == 0 then
                    if tp [this] == 0 then
                        set tl = 0
                    else
                        set tl = tp [this]
                        set tn  [tp [this]] = 0
                    endif
                else
                    set tn [tp [this]] = tn [this]
                    set tp [tn [this]] = tp [this]
                endif
                
                set tr [this] = tr [0]
                set tr [0]    = this
                
                set tt  [this] = 0
                set trt [this] = 0 
                set ttc [this] = 0
            endif
        endif
    endfunction
    
    private function RefreshType takes nothing returns nothing
        local integer this = tl
        local real    time = TimerGetElapsed(tmr) - let
        
        set let = TimerGetElapsed(tmr)
        
        loop
            exitwhen tp [tn [this]] == 0
            
            set trt [this] = trt [this] - time
            
            set this = tp [this]
        endloop
    endfunction
    
    private function Expire takes nothing returns nothing
        local integer this = lt [cur]
        
        loop
            exitwhen pt [nt [this]] == 0
            
            call TriggerClearConditions(trg)
            call TriggerAddCondition(trg, cft [this])
            call TriggerEvaluate(trg)
            
            set this = pt [this]
        endloop
        
        call RefreshType()
        set  trt [cur] = tt [cur]
        set  this = tl
        
        loop
            exitwhen tp [tn [this]] == 0
            
            if cur == 0 or trt [cur] > trt [this] then
                set cur = this
            endif
            
            set this = tp [this]
        endloop
        
        set  let = 0
        call DestroyTimer(tmr)
        set  tmr = CreateTimer()
        call TimerStart(tmr, trt [cur], false, function Expire)
    endfunction
    
    private function Create takes real time, code func returns integer
        local integer this = r [0]
        local integer that
        
        if this == 0 then
            set c    = c + 1
            set this = c
        else
            set r [0] = r [this]
        endif
        
        call RefreshType()
        set  t   [this] = GetType(time)
        set  cft [this] = Condition(func)
        
        if lt [t [this]] == 0 then
            set nt    [this]  = 0
            set pt    [this]  = 0
            set lt [t [this]] = this
        else
            set nt    [this]  = 0
            set pt    [this]  = lt [t [this]]
            set lt [t [this]] = this
        endif
        
        set that = tl
        
        loop
            exitwhen tp [tn [that]] == 0
            
            if cur == 0 or trt [cur] > trt [that] then
                set cur = that
            endif
            
            set that = tp [that]
        endloop
        
        set  let = 0
        call DestroyTimer(tmr)
        set  tmr = CreateTimer()
        call TimerStart(tmr, trt [cur], false, function Expire)
        
        return this
    endfunction
    
    private function Destroy takes integer that returns nothing
        local integer this = that
        
        call LoseType(t [this])
        
        if ttc [t [this]] == 0 and cur == t [this] then
            call RefreshType()
            set  this = tl
            set  cur  = 0
            
            loop
                exitwhen tp [tn [this]] == 0
                
                if cur == 0 or trt [cur] > trt [this] then
                    set cur = this
                endif
                
                set this = tp [this]
            endloop
            
            set  let = 0
            call DestroyTimer(tmr)
            set  tmr = CreateTimer()
            call TimerStart(tmr, trt [cur], false, function Expire)
        endif
        
        if nt [that] == 0 then
            if pt [that] == 0 then
                set lt [t [that]] = 0
            else
                set lt  [t [that]] = pt [that]
                set nt [pt [that]] = 0
            endif
        else
            set nt [pt [that]] = nt [that]
            set pt [nt [that]] = pt [that]
        endif
        
        set r   [that] = r [0]
        set r   [0]    = that
        
        set t   [that] = 0
        set cft [that] = null
    endfunction
    
    public module Implement
        static method tsCreate takes real time, code func returns integer
            return Create(time, func)
        endmethod
        
        method tsDestroy takes nothing returns nothing
            call Destroy(this)
        endmethod
    endmodule
endlibrary

Timed Function Draft (no documentation) - Interface:
JASS:
library TimedFunc requires /*New*/Table, TimerUtils
    
    globals
        private Table   table
        private integer total
    endglobals
    
    public function interface TimedFunction takes nothing returns boolean defaults false
    
    private function Expire takes nothing returns nothing
        local integer i = GetTimerData(GetExpiredTimer())
        
        if not TimedFunction(table [i]).evaluate() then
            call ReleaseTimer(GetExpiredTimer())
            call table.remove(i)
        endif
    endfunction
    
    public function Start takes real time, TimedFunction func returns nothing
        local integer a = 1
        local integer b = total + 1
        
        local integer i = 0
        
        loop
            exitwhen a == b
            
            if not table.has(a) then
                set i = a
                
                set a = b
            endif
            
            set a = a + 1
        endloop
        
        if i == 0 then
            set total = total + 1
            set i = total
        endif
        
        set table [i] = func
        
        call TimerStart(NewTimerEx(i), time, true, function Expire)
    endfunction
    
    private module Init
        static method onInit takes nothing returns nothing
            set table = Table.create()
        endmethod
    endmodule
    
    private struct Struct extends array
        implement Init
    endstruct
endlibrary

Timed Function Draft (no documentation) - Requires TimerStack:
JASS:
library TimedFunc requires TimerStack
    private struct TS extends array
        implement TimerStack_Implement
    endstruct
    
    struct TF extends array
        private static integer       c
        private static TS      array i
        private static integer array r
        
        static method start takes real time, code func returns integer
            local integer this = r [0]
            
            if this == 0 then
                set c    = c + 1
                set this = c
            else
                set r [0] = r [this]
            endif
            
            set i [this] = TS.tsCreate(time, func)
            
            return this
        endmethod
        
        method stop takes nothing returns nothing
            call i [this].tsDestroy()
            
            set r [this] = r [0]
            set r [0]    = this
        endmethod
    endstruct
endlibrary

Feel free to comment, your suggestions are gladly appreciated!
 
Last edited:
The problem is that you can't simplify this to have less overhead than TimerUtils :/
TimerUtils only recycles timers and provides data attachment, which is exactly what everyone wants.
It's use is extremely simple:

Start:
call TimerStart(NewTimerEx(2), 1, true, function Iterate)

Stop:
call ReleaseTimer(GetExpiredTimer())
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
It provides a heavily weighted syntax shortcut for using timers.

If you wanted to go farther with this, though, I suppose I would start by simplifying the implementation. When people want a timed function they typically want to be able to pass parameters to a function that is executed on a timer (which Warcraft III does not have direct support for).

The only advantage of this would then be that instead of having to use SetTimerData followed by TimerStart you would just do TimedFunc(...). This seems like a minimal improvement at a significant cost of unnecessary operations.
 
Level 7
Joined
Oct 11, 2008
Messages
304
hmmm . . . .
then how can i replace the interface thing? (i'm not experienced in handling functions and executing them >.<)

With Modules, like this:

JASS:
module M
    static if thistype.MM.exist then
        call thistype.MM()
    endif
endmodule

struct S extends array
static method MM takes nothing returns nothing
endmethod

implement M
endstruct

Or something like that, too much time without edit :goblin_boom:
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
That would definitely throw a compile error, and I'm really sick of all this extends array crap. The benefits of efficiency are outweighed by the disadvantages in readability. A struct should represent what a struct in most languages represents, and that is a binding of data elements. It also inherits some functionality of classes in that it allows for a constructor and a destructor.

If you want to start extending arrays with your structs because you're worried about efficiency then don't use structs. Use parallel arrays.

Also the abuse of modules is prevalent here because you've given an exact example of why using modules for things they shouldn't be used for is bad. Not only can you not make sense of your own code, but you've implemented it wrong. The above code would throw a syntax error because you have a call outside any method. Failing to make sense of extremely simple code only leads to bad things.
 
Level 7
Joined
Oct 11, 2008
Messages
304
Was just a example Berb...
And about the extends array, is only a habit to write it, no matter if I use custom indexing or if normal vJass struct, it is just a habit.

JASS:
module M
    static method MyRandomMethodForBerb takes nothing returns nothing
        static if thistype.MM.exist then
            call thistype.MM()
        endif
    endmethod
endmodule
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
I came off a bit harsh I think, I apologize.

For the author of the thread, putting that in your timer callback (instead of calling the function interface) would allow you to determine whether or not the method exists and then call it accordingly. May I ask you to show me how you would then implement that sort of idea, being the user who wants to use the system?

The reason I believe this system is not worth it is because it tries to provide an easier syntax to use. If you do things your way then implementation becomes just as hard as using the TimerUtils library itself (if not more confusing). If you use an interface you could have a very simple API for your struct but you would be sacrificing efficiency.

There is no reason for a system that provides the functionality of TimerUtils unless it only provides improvements to what there already is. In this situation, there are no improvements to be made.
 
Last edited:
Executing a boolexpr can only be done safely like this:

JASS:
globals
    private trigger t = CreateTrigger()
endglobals

function Run takes boolexpr b returns nothing
    call TriggerClearConditions(t)
    call TriggerAddCondition(t, b)
    call TriggerEvaluate(t) // fixed. Thanks Berb
endfunction

It's slow, but unlike Function interfaces, at least it doesn't generate lots of garbage
 
Last edited:
Level 7
Joined
Apr 30, 2011
Messages
359
next to do:
- remake TimedStruct
- edit TimedFunc (not requires TimedStruct anymore)

just wait~

EDIT:

- Removed most things in the first post
- Added:
-!- Precise Timer Draft
-!- Timed Function Draft (two versions)
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
I've got to say I don't really see what all the functions are for. This should be a fairly simple API, why are there dozens of functions? At first glance what I think is, "all I want to do is be able to quickly (without unnecessarily sacrificing efficiency) declare a struct with a method that executes actions on a periodic interval".

First. Your Advanced functionality is hideous, requiring the user to implement a handful of modules in a specific order, abstractly declaring actions in between module implementations. There should only be one module you implement.

Second. After reading your TimedFunc code I've got to say what is the point of it? You are using TimerUtils to store data so you can reference which function-interface to evaluate, but your function-interface doesn't provide any means of the user accessing data that he/she had access to when calling the timed function.
 
Level 7
Joined
Apr 30, 2011
Messages
359
yeah you're right :3
i'll update them later . . .

for Precise Timer:
1. i'll keep the idea of 100% accurate timer
2. i'll simplify those hideous things (especially Advanced ones)
3. please note that i removed those unnecessary methods (stop, pause, resume, delay)

for Timed Function:
1. i'll move it to a rather advanced one (using structs indeed)
2. i'll remove that interface thing (since i think it sucks)

and added Single Timer, i should simplify its Advanced version too . . . .
but please check that one, and suggest something ^_^
really thanks for your help, Berb
 
Except the interface on a function interface is way better, and there is a minimal difference in overhead.

The interface is definitely better, but the overhead is 2x code length which is absolute rubbish. The speed difference I don't care about.

Cohadar may be making an update to his revised JassHelper which fixes the issue with ".name" where it writes prototype functions despite only using ExecuteFunc, and if that happens I will strictly use ForForce and ExecuteFunc for all my dynamic function needs.
 
Level 7
Joined
Apr 30, 2011
Messages
359
so . . . .
ExecuteFunc and ForForce is better than .evaluate, .execute, and TriggerEvaluate . . .
and it becomes worse because of that .name issue :3

and are those interfaces will be fixed too ?
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
JASS:
                loop
                    exitwhen a == b
                    
                    if .ptIndex [a] == 0 then
                        set i = a
                        
                        set a = b
                    endif
                    
                    set a = a + 1
                endloop

I'm guessing this loop finds the next available index in your array? I'm pretty sure there are ways to do this without having to do a linear search for open indices.

Whenever one of these structs is destroyed you can store its index in a queue. When an object is trying to be allocated, check to make sure there aren't any indices on the queue that could be used to allocate a new struct.

Hmm.. kind of hard to explain, let me see if I can show you...
 
Level 7
Joined
Apr 30, 2011
Messages
359
JASS:
                loop
                    exitwhen a == b
                    
                    if .ptIndex [a] == 0 then
                        set i = a
                        
                        set a = b
                    endif
                    
                    set a = a + 1
                endloop

I'm guessing this loop finds the next available index in your array? I'm pretty sure there are ways to do this without having to do a linear search for open indices.

Whenever one of these structs is destroyed you can store its index in a queue. When an object is trying to be allocated, check to make sure there aren't any indices on the queue that could be used to allocate a new struct.

Hmm.. kind of hard to explain, let me see if I can show you...

something like .next, .prev, .recycle ?
i knew that, but confused seeing them . . . @.@
 
Interfaces won't get fixed.

ExecuteFunc was benchmarked a few years ago as the "slowest way to execute code", but I have a slower computer than 99% of the people here and ExecuteFunc never causes me any problems, despite me using it all over the place.

The reason ExecuteFunc is good is because:

1) It uses strings, not handles, so RAM usage is considerably less than usual.
2) Strings can be stored into arrays, so you can access them dynamically, unlike the "code" variable.

JASS:
call ExecuteFunc(thistype.myMethod.name) //Will be nice when this doesn't generate as much crap-code as function interfaces do.

The reasons ForForce is good is because:

1) It executes right away, without needing to use TriggerAddCondition.
2) Only uses one "force" handle for the entire duration of the game.
3) Is possibly the fastest way to run code.

The reasons ForForce is bad is because:

1) You can't store "code" into arrays.
2) You can't use TriggerSleepAction-type things inside of it.

JASS:
call ForForce(frc, function thistype.myMethod)

So, basically, ExecuteFunc covers for the things that ForForce can't handle, so between the two you have everything you'll need.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
A function call is really everything you'll ever need. Remember JASS?

overcold_ice, you'll have to forgive me if there is something terminally wrong with what I'm about to post but I'm very tired. The concept would be something like this:

JASS:
            if (queueSize == 0) then
                set ptCount = ptCount + 1
                set ptArray[ptCount] = create()
                set ptArray[ptCount].ptTimer = NewTimer()
            else
                set ptArray[ptQueued[queueHead]] = create()
                set queueHead = queueHead + 1
                set queueSize = queueSize - 1
                set queueHead = queueHead - (queueHead / 8190) * 8190
            endif

Where you've got these members declared:
JASS:
        timer ptTimer
        static thistype array ptArray
        static integer ptCount = 0
    
        static integer array ptQueued [8190]
        static integer queueHead = 0
        static integer queueSize = 0

Something like this for deallocation:

JASS:
        static method ptExpire takes nothing returns nothing
            local integer i = GetTimerData(GetExpiredTimer())
            local integer j
            
            call ReleaseTimer(GetExpiredTimer())
            
            set j = (queueHead + queueSize)
            set j = j - (j / 8190) * 8190
            set ptQueued[j] = i
            set queueSize = queueSize + 1
        endmethod

I'm quite tired right now. I may be missing something vital here. I'll look back at it in the morning.
 
Level 7
Joined
Apr 30, 2011
Messages
359
thanks Berb and Bribe . . .
i got a new information :D

but still not understand with those QueueHead and QueueSize
aren't (j / 8190) * 8190 == j ?
 
j / 8190 * 8190 will only == j if j == 8190.

See, when you divide integers, the result will also be an integer.

So if you divide 1 / 2, what integer will you get? 0.5 is not an integer. So 1 / 2 * 2 will not equal 1.

If you have a programmer's calculator, divide 1 by 2. If the calculator rounded up, you would get 1. If it rounded down, it would equal 0.

Because integers do not round, but simply round down, you can guess what 1 / 2 will be. So 1 / 2 * 2, you will get 0.

Therefore, j / 8190 * 8190, if j is less than 8190, will equal 0, and if it is between 8190 and 8190 * 2, the result will be 8190.

This leads to really cool programming magic which allows you to do things like this:

JASS:
function IsEvenNumber takes integer i returns boolean
    return i == i / 2 * 2
endfunction

Or even this:

JASS:
function IsNumberDivisibleByNumber takes integer nu, integer by returns boolean
    return nu == nu / by * by
endfunction
 
Ok, I'm a little busy at the moment, but I will give you a few miscellaneous tips:

1) You don't need more than one boolean for the static if (If Basic == false, do advanced code, else do basic code)
2) ModuleNamesAreTypicallyWrittenJustLikeThisSentence notlikethisone.
3) The problem with PreciseTimer is that it creates a timer per struct instance :/
A better way to do this is to create a timer per struct OR ONE TIMER for the entire map.
(You'll loop over a linked list of instances)
4) This indexing isn't really the best because it has O(n) complexity when it should have O(1):

JASS:
                local integer a = 1
                local integer b = .ptTotal + 1
                
                local integer i = 0
                
                loop
                    exitwhen a == b
                    
                    if .ptIndex [a] == 0 then
                        set i = a
                        
                        set a = b
                    endif
                    
                    set a = a + 1
                endloop
                
                if i == 0 then
                    set .ptTotal = .ptTotal + 1
                    set i = .ptTotal
                endif

This, would be an alternative:

Dynamic Indexing
JASS:
private static integer ic = 0
private static integer array rn

JASS:
//allocate like this:
local thistype this = rn[0]
if this == 0 then
    set ic = ic + 1
    set this = ic
else
    set rn[0] = rn[this]
endif

JASS:
// deallocate like this:
set rn[this] = rn[0]
set rn[0] = this

What it does is use a recycler to store used instances instead of looping over all instances to find an empty one.

5) There's no destroy method declared inside the PreciseTimer module. The user might not want you to call destroy :/
You should only call a method called "ptDeallocate" or something like that to deallocate the instance and nulls the timer

6) Just a tip, exitwhen statements don't exit the loops until you actually reach them
Your current indexing system won't work, it would just crash the thread and kill all current executions in the same trigger/timer function call stack.

7) TimedFunc isn't the most useful system of the year :/
Honestly, it can be replaced with an even lighter TimerStart call :X

8) The trigger version of TimedFunc doesn't function right ;/
(Destroying the triggers)

9) SingleTimer has the potential to bug ;x
Also, it's pretty slow in comparison to CTL and other systems :/
You can force the user to define a constant integer for the interval of the timer called INTERVAL
and you can use that instead of expecting the user to add an interval parameter to the function
call :D (You'd need to make a module-based API though, just like CTL)
You'd have to loop over a linked list of instances instead of an indexed array.
LinkedLists can be pulled off pretty easily:

JASS:
private static integer array next
private static integer array prev

JASS:
//add to list
set next[this] = 0
set prev[this] = prev[0]
set next[prev[0]] = this
set prev[0] = this

JASS:
//remove from list
set prev[next[this]] = prev[this]
set next[prev[this]] = next[this]
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
The queue is an array (8190 in size). The head evaluates where in the queue the "head" is so that values can be extracted from there, and then the head would move up farther, until getting to the end of the list where it would go back to the first index. It's a nice way of implementing a queue using an array.
 
Level 7
Joined
Apr 30, 2011
Messages
359
@ Bribe:
really thanks for explaining again :D

@ Magtheridon:
1. need 2, because both can be used at once (not in a single struct tough)
2. i want to create a module-syntax like jass' syntax (function-endfunction, etc), but if it really shouldn't be done, then i'll rename them
3. yeah, currently thinking of TimerStack (1 timer for all timer instances), and maybe it can be 1 timer for a map :D
4. still learning :3 (really doesn't understand ur code at all)
5. alright . . .
6. so, it'll exit when it meet the exitwhen line?
7. later i'll remake it again~
8. will be fixed in the next version . . . (i'm not that experienced in triggers-handling)
9. another confusing things . . . . could someone elaborate those things @.@

@ Berb:
alright i'll try to explain this myself . . .

JASS:
    // instantly use the recycled index
    set ptArray[ptQueued[queueHead]] = create()
    
    // basically these two doesn't change anything in deallocation
    // since: (head + size) == (head + 1 + size - 1)
    // use next head
    set queueHead = queueHead + 1
    // size is reduced . . .
    set queueSize = queueSize - 1
    
    // this will change
    // filter the new head, if it's 8190 then it goes back to 0
    set queueHead = queueHead - (queueHead / 8190) * 8190
    
    // so, this sytem use 0 - 8189 index, not 1 - 8190 (i like this one)

JASS:
    // current head + current size
    set j = (queueHead + queueSize)
    
    // filter the new head-ex, if it's 8190 it goes back to 0
    set j = j - (j / 8190) * 8190
    
    // assign it
    set ptQueued[j] = i
    // the size changes of course
    set queueSize = queueSize + 1

am i right?
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Looks like you've got the logic.

Basically what its doing is using an array as a queue. You only need one queue per type of struct being implemented into.

The queue effectively stores which indices are available to be "re-taken" because they have been cleared. If the queue has not had any indices added to it, then you need to pull one off of the array and use that. Then, once that is cleared, you can put it into the queue to notify the system that the index has already been used and can be used again when ready.

The reason for shifting the head forward is so that we don't have to shift the entire array left whenever we extract the head of the array.

This should prevent you from having to search for an index that is available to be used, which is potentially an O(n) algorithm. This should operate in constant time.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Well the queue should start at 0 because it's just an array of integers pointing to indices of another array. If you want to make it go up to 8190 then you could just replace 8190 with 8191. What I do effectively ensures that the queue's array index is always between 0 and the maximum array value, otherwise you're likely to get errors.

I'm afraid you're wanting to reserve the index 0 in the queue for something, which wouldn't make any sense. A queue is not a data structure for doing that. It would likely just make the solution uglier.
 
Level 7
Joined
Apr 30, 2011
Messages
359
Well the queue should start at 0 because it's just an array of integers pointing to indices of another array. If you want to make it go up to 8190 then you could just replace 8190 with 8191. What I do effectively ensures that the queue's array index is always between 0 and the maximum array value, otherwise you're likely to get errors.

I'm afraid you're wanting to reserve the index 0 in the queue for something, which wouldn't make any sense. A queue is not a data structure for doing that. It would likely just make the solution uglier.

alright . . .
i'll try to implement what i have got for the next version :D
so much thanks, +rep to all . . .

this thread isn't solved yet :3
 
Level 7
Joined
Apr 30, 2011
Messages
359
UPDATED:
- reworked and combined PreciseTimer and SingleTimer into TimerStack
- TimerStack allows you to combine 8190 timers into 1 timer
- As i said before, the system only use 1 timer for 8190 timers, and 1 trigger for all its members


if there's something wrong please say it, since i haven't tested it . . .
please review my new system ^_^
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Well it looks terribly confusing. I have to say I don't have any idea what the internal system does right now. I'm going to say, maybe it might be a good idea to make your variable names a little more sensible.

Could you really come back to that in a couple of months and understand what its doing?

--
Just tried to read through it a little more carefully and I'm still lost. I guess... good job? See if it works. Haha.
 
Level 7
Joined
Apr 30, 2011
Messages
359
Well it looks terribly confusing. I have to say I don't have any idea what the internal system does right now. I'm going to say, maybe it might be a good idea to make your variable names a little more sensible.

Could you really come back to that in a couple of months and understand what its doing?

--
Just tried to read through it a little more carefully and I'm still lost. I guess... good job? See if it works. Haha.

yay~
please test it somehow, because i can't, since i haven't got a mouse (sucks)
well . . .

JASS:
    globals
        // Timer Section
        private integer       c   = 0           // timer instance count
        private integer array r                 // timer's recycle bin
        
        private integer array t                 // timer's type
        
        private integer array nt                // next timer
        private integer array pt                // previous timer
        private integer array lt                // last timer
        
        private conditionfunc array cft         // timer's action
        
        // Timer Type Section
        private integer       tc  = 0           // type count
        private integer array tr                // type's recycle bin
        
        private integer array tn                // next type
        private integer array tp                // previous type
        private integer       tl                // last type
        
        private real    array tt                // type's time
        private real    array trt               // type's remaining time
        private integer array ttc               // type's instance count
        
        // Trigger and Timer Section
        private trigger       trg = CreateTrigger() // the trigger
        private timer         tmr               // the timer
        private integer       cur               // current running timer type
        private real          let               // last elapsed time
    endglobals
those are the long terms for the variables
please test/review it ^_^
 
Timer2 is a RAM-savvy system which sacrifices speed for low handle count. Each struct which implements the module "Timer2" will have *one* dedicated timer to it.

This kind system is not efficient for people who are using low periods like < 0.3, but for periods of 1 second or greater the speed loss is pretty negligible. I will probably be using Timer2 for my imminent WarChasers 2 update.
 
Status
Not open for further replies.
Top