TimedLoop

Scripts

14 years
edited 8 years
All right, after the PeriodicLoopModule failure, this is a simpler version that is less flexible but should work, it is for structs that are exclusive for looping and will conflict with stuff that require you not to call .destroy but another method.

It is a module you implement in a struct to do the whole array+loop thing that we always do in spells. Only that this time you won't have to code it all the time... an example:

Only disadvantage against doing the loop manually is that it will do a function call (not TriggerEvaluate) for each instance in the loop. Differences with things like TT is the OOPness and the lack of TriggerEvaluate, though it uses a timer per struct type, wonder if that's important.

Usage sample
Code (jass) Select
1
struct moveUnit
2
3
    unit u
4
5
    //=====================================================
6
    // You need to code an onTimedLoop method before
7
    // implementing the module.
8
    //
9
    private method onTimedLoop takes nothing returns boolean
10
        //instance's timer expired:
11
        // This will just move a unit's x coordinate with
12
        // a speed of 100 until it reaches 5000.0
13
14
        call SetUnitX(u, GetUnitX(u) + 100.0* TimedLoop_PERIOD )
15
        // notice the use of the TimedLoop_PERIOD constant
16
        // since it may be tweaked by the user...
17
18
19
        if ( GetUnitX(u) >= 5000) then
20
            return TimedLoop_STOP
21
        endif
22
23
     return TimedLoop_CONTINUE
24
25
     //You are free to/should use false and true instead of the
26
     //constants.
27
    endmethod
28
29
    implement TimedLoop //This does the module magic
30
31
    static method create takes unit u returns moveUnit
32
     local moveUnit m= moveUnit.allocate()
33
        set m.u = u
34
        call m.startTimedLoop() //The module works by
35
        // creating a startTimedLoop method that will
36
        // do all the dirty work and end up calling
37
        // .onTimedLoop...
38
        //
39
     return m
40
    endmethod
41
42
endstruct
43
//call moveUnit.create(GetTriggerUnit()) and see...
44


Names are now finished..

The code:
Code (jass) Select
1
library TimedLoop
2
//********************************************************
3
//* TimedLoop
4
//* ---------
5
//*
6
//* Requires jasshelper 0.9.G.1 or greater.
7
//*
8
//*   A library + module that are meant to make those
9
//* array + timer loops easy, yet still faster than
10
//* other alternatives meant to be easy (In other words
11
//* no TriggerEvaluate is involved).
12
//*
13
//* The OOPness is interesting.
14
//*
15
//*  Before implementing TimedLoop
16
//* your struct needs an onTimedLoop method that takes
17
//* nothing and returns boolean, if the method
18
//* returns false, the instance will get removed
19
//* from the loop and destroyed, else it will continue,
20
//* think of it as if the call asks the method a
21
//* question: "Should I continue the loop afterwards?"
22
//*
23
//* Alternatively, if you are not convinced, you may
24
//* use the TimedLoop_CONTINUE and TimedLoop_STOP
25
//* constants in the method's returns.
26
//* 
27
//*   After implementing TimedLoop, you can call
28
//* the startTimedLoop method to add the periodic event
29
//* to that instance, only call it once per instance.
30
//*
31
//* I recommend to call implement just bellow the
32
//* declaration of the onLoop method, else it will
33
//* actually use TriggerEvaluate, which is lame. Remind
34
//* me to implement a topsort in jasshelper.
35
//*
36
//*  If you feel the need to destroy the struct outside
37
//* the loop, well, you'll have to add a flag to it so
38
//* you send a message to onLoop to make it return false.
39
//* A more complicated module to allow that easily would
40
//* come later.
41
//*
42
//********************************************************
43
44
//========================================================
45
// config:
46
47
    globals
48
     public constant real    PERIOD = 0.025
49
     // A lower value and everything using the module will
50
     // look better, yet performance will drop.
51
    endglobals
52
53
//========================================================
54
// implementation:
55
//
56
   globals
57
    public constant boolean STOP     = false
58
    public constant boolean CONTINUE = true
59
   endglobals
60
   
61
   
62
   //===========================  
63
   module TimedLoop
64
   // god bless private module members.
65
   //
66
      private static thistype array V        // The array
67
      private static integer        N = 0    // The count
68
      private static timer          T = null // the timer, one per
69
                                             // struct that implements this
70
      
71
      private static method onExpire takes nothing returns nothing
72
       local integer  n    = 0
73
       local thistype this // yay for odd-sounding syntax constructs
74
       local integer  i    = 0
75
       
76
          loop
77
              exitwhen (i== thistype.N)
78
              set this = .V[i]
79
              if ( this.onTimedLoop() == CONTINUE ) then
80
                  set .V[n] = this
81
                  set n=n+1
82
              else
83
                  call this.destroy()
84
              endif
85
              set i=i+1
86
          endloop
87
          set thistype.N = n
88
          if (n== 0) then
89
              call PauseTimer(.T)
90
          endif
91
                 
92
      endmethod
93
      
94
      public method startTimedLoop takes nothing returns nothing
95
         set .V[.N] = this
96
         set .N=.N + 1
97
         if (.N == 1) then
98
             if (.T == null) then
99
                 set .T = CreateTimer()
100
             endif
101
             call TimerStart(.T, PERIOD, true, function thistype.onExpire)
102
         endif
103
      endmethod
104
     
105
   endmodule
106
107
108
endlibrary