This is a system I have been messing around with for the past few days
I just finished it, and have not tested it in-game
If there are any improvements any good vJASS-ers can add to it, that would be awesome
Here is the whole textfile in a JASS tag...
And the system is uploaded as how I originally wrote it as a textfile
I just finished it, and have not tested it in-game
If there are any improvements any good vJASS-ers can add to it, that would be awesome
Here is the whole textfile in a JASS tag...
JASS:
//(Now I'm gonna write up the IndexSystem textmacro, this index system happens to be used with the globals in the system
//So if you don't know how, you shouldn't change it, but if you are good at vJASS and know what your doing, you can change
//it to a struct)
//*The textmacro has been requested to be placed at the top of the script*
//! textmacro IndexSystem takes R
globals
integer $R$_COUNTER = 0
integer $R$_INDEX = -1
integer array $R$_RECYCLE
boolean array $R$_TRACK
endglobals
function Index takes nothing returns integer
local integer ret
if $R$_RECYCLE[0] == 0 then
//Recycle 'bin' is empty
set $R$_INDEX = $R$_INDEX + 1
set $R$_TRACK[$R$_INDEX] = false
return $R$_INDEX
endif
//Not empty
set $R$_COUNTER = $R$_COUNTER - 1
set ret = $R$_RECYCLE[$R$_COUNTER]
set $R$_RECYCLE[$R$_COUNTER] = 0
set $R$_TRACK[ret] = false
return ret
//Returns last recycled index
endfunction
function Recycle takes integer i returns nothing
if $R$_TRACK[i] then
return
endif
set $R$_TRACK[i] = true
set $R$_RECYCLE[$R$_COUNTER] = i
set $R$_COUNTER = $R$_COUNTER + 1
//Sets last recycled index = i
endfunction
//! endtextmacro
library SingleTimerSystem
//! runtextmacro IndexSystem("TimedFunction")
globals
private integer array TimeOut
private integer array Working
private integer array GetStruct
private string array Function
private integer array Stored
private integer Max = 0
private timer T = CreateTimer() //Might bug
//These globals are not private, they are to be used in your called functions
boolean Stop = false
integer Temp_GetStruct
endglobals
private constant function Interval takes nothing returns real
return .01
endfunction
private constant function NumberOfPlaces takes nothing returns integer
return 2
endfunction
//This is a constant that allows you to determine the number of places the system is accurate to
//These you do not need to mess with
private constant function K takes nothing returns integer
return Pow(10,NumberOfPlaces())
endfunction
private constant function Interval2 takes nothing returns integer
return R2I(Interval() * K())
endfunction
prviate function Loop takes nothing returns nothing
local integer i = 0
local integer s
local integer max = Max
loop
exitwhen i == max
set s = Stored[i]
set Working[s] = Working[s] - Interval2()
if Working[s] <= 0 then
set Temp_GetStruct = GetStruct[s]
call ExecuteFunc(Function[s])
//Calls the desired function, with the attached struct as a temporary global integer
//Stop is a temporary global boolean that must be set at the end of each function, true stops the functions
//execution, false continues it
//You don't need to change it to false, just true, the system automatically resets it to false
if Stop or TimeOut[s] == 0 then
set Stored[i] = Stored[Max]
call TimedFunction_Recycle(s)
set Max = Max - 1
if Max == 0 then
call PauseTimer(T)
endif
set i = i - 1
set Stop = false
endif
//Deallocates
//Whether or not the instance had been deallocated, the Working[] is reset to its original timeout in order
//to continue if it is a PeriodicFunction call
set Working[s] = Timeout[s]
endif
set i = i + 1
//Continues loop
endloop
endfunction
function PeriodFunc takes real time, string func, integer struct returns nothing
local integer s = TimedFunction_Index()
set Function[s] = func
set GetStruct[s] = struct
set TimeOut[s] = R2I(time * K())
set Working[s] = R2I(time * K())
set Stored[max] = s
if Max == 0 then
call TimerStart(T, Interval(), true, function Loop)
endif
set Max = Max + 1
endfunction
//This is for calling functions that will be called a number of times each timeout before
//a condition in your function tells the function to stop being called
function TimedFunc takes real time, string func, integer struct returns nothing
local integer s = TimedFunction_Index()
set Function[s] = func
set GetStruct[s] = struct
set TimeOut[s] = 0
set Working[s] = R2I(time * K())
set Stored[max] = s
if Max == 0 then
call TimerStart(T, Interval(), true, function Loop)
endif
set Max = Max + 1
endfunction
//This is for calling functions that will only be called once in a timeout
endlibrary
//Notes
//The stored numbers become stacked when looped, in order to preserve the 'max' stored number, it takes the slot of
//the removed number. This can become tricky, because although the index is preserved, it is not called until the next
//loop, so all I need to do is set i = i - 1, to negate the bottom i + 1, and run the max slot in the same loop
//The purpose of the system is to only use one timer in your whole map, which should make a significant difference in speed
//Although, if you'll notice the code isn't too efficient, so I am gambling on the fact that timers are obscenely large
//You'll notice that included is an index system textmacro, I include it because I like being able to index globals
//without relying on structs
//when calling TimedFunction(), the TimeOut[] is set to 0, so you do not need to include the 'Stop' at the end of the
//function
//Ex.
function IamPeriodic takes nothing returns nothing
local integer dat = Temp_GetStruct
local boolean end = true
if end then
set Stop = true
endif
endfunction
//The periodic functions are assumed to have some sort of condition in which the periodic function stops running
function ImaSingleShotFunction takes nothing returns nothing
local integer dat = Temp_GetStruct
//Actions
//Does not need the 'Stop'
endfunction
//Again, this system totally relies on the fact that timers take up too much memory, this system goes through a seriously
//large number of repetitions in a few seconds (let's say 10 projectiles, for 5 seconds each, equals 5000 loops)
//Whereas using an attachment system might have one-third the loops, but 10 timers are going
//(one-third loops because 10 timers each going at [a common timeout] .035, less than a third, plus the memory for 10 timers)
//If you'd like, you can improve efficiency by changing the interval constant to another number, but remember the first
//restriction, all the timeout numbers must be multiples of that constant, .02 shouldn't be too much of a stretch
//Since many people recommend using .035 as the interval to use for timers, you could use it here if you'd like, although
//that would create
//Added a series of constants to allow for total customization to your maps specifications
//The system will accomodate for approximate timeouts that don't match your interval, although it will not be extremely
//accurate, and if you want to handle extremely small timeouts, I recommend using an attachment system
//As long as when you change the Interval() you remember to change the appropriate number of places the interval
//goes to, the system should work just peachy
//As is, our system has been set with an Interval() of .01, and the number of places .01 goes to is 2, this you probably
//would like to change to something more practical (maybe .02), but I have no computer handy that has WC3 installed and
//cannot test this
//Function names shortened from 'PeriodicFunction' to 'PeriodFunc', 'TimedFunction' to 'TimedFunc'
//Restrictions
//1, Timeouts are only accurate to the decimal place you have set, [Timeouts must be a multiple of the Interval() constant]
//In our example, since we set it to 2 and our timeout is .01
//These examples are...{ .02 Good, .021 Bad, 2.0 Good, 2.01 Good, 2.001 Bad }
//2, Timeouts cannot be lower than the Interval() constant, a little obvious if you understood restrictions #1
//for 0.0 timeouts, use QUICK_TIMER(), using this would just be dumb
//Example Using Periodic Function
struct GoUp
unit u
endstruct
function Increase takes nothing returns nothing
local GoUp d = Temp_GetStruct
local unit u = d.u
local real h = GetUnitFlyHeight(u)
call SetUnitFlyHeight(u, h + 10)
if h+10 >= 1000 then
set d.u = null
call d.destroy()
set Stop = true
endif
endfunction
function IncreaseHeight takes unit u returns nothing
local GoUp d = GoUp.create()
set d.u = u
call PeriodFunc(.02, "Increase", d)
endfunction
//The string is supposed to be the name of the function that will be called, if your using vJASS scopes and librarys, please
//read up on the prefix constants
//Please note that these examples are nonsense, and useless, I needed to make them very quickly, and hence did not make
//anything useful
//Example using Timed Function
struct KillMe
unit u
endstruct
function Kill takes nothing returns nothing
local KillMe d = Temp_GetStruct
call KillUnit(d.u)
set d.u = null
call d.destroy()
endfunction
function KillInTime takes unit u, real time returns nothing
local KillMe d = KillMe.create()
set d.u = u
call TimedFunc(time, "Kill", d)
endfunction
//In this example, you do not need to add the 'Stop'
//Notice, you also do not need to create and destroy any timers, which, if your anything like me, leaves you feeling like
//your missing something
And the system is uploaded as how I originally wrote it as a textfile
Attachments
Last edited: