• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS][System]Timed

Level 31
Joined
Jul 10, 2007
Messages
6,306
Bit Streams

---------------------------------------------

Officially tested to *8000* different timers on a 128 bit stream with 0 lag going in increments starting from 1 bit!

News Count: 2
News Data: 8-27-09 at 9:48pm PST

-News-

Build 1 of the new build is released.

What is going to be changed?
A way to attach data to timers =).

A way to split streams up from the main stream without a loss in speed.

Is this hella fast?
It depends... because everything runs on the main stream, the more variety in timers you have, the more laggy it gets because the main stream has to handle more. If you have 8000 of the fastest possible timer, it'd be faster than 8000 dif timers that are all like 100 seconds (fastest possible might run 32 times a second).

So how will this change?
I'm going to split the main stream into two stream types, these being fast and slow.

What will this do?
It will make timers that won't fire for awhile run only once every once and awhile instead of every time, so instead of every bit, it'll run every 32 bits or something : D.

Will this be faster?
Yes... it should be much faster when I think about it o_O.



So, I split up the streams for the most epic optimization stuff ever!

Maximum Optimization To Smallest Bit Timer-
The smallest bit timer runs on the actual main stream timer making it as fast as a single standard timer o-o, 0 extras.

Small Timers have extra optimization-
With the introduction of the 2 stream types, those being the big stream and the small stream, the small timers that always run on the small stream have various elements that they don't do, meaning that they run faster =). These elements have to do with swapping between the big stream and the small stream. What does this mean? You can go smaller without the performance hit.

Big Timers have extra optimization-
Big timers run on a combo of the big and small streams. The big streams don't run as often (once a second). This means that the main stream doesn't have to process as much code making the entire thing run smoother. When a big timer has less than 1 second left (less, not less than or equal to), it swaps to the small stream, carries out the rest of its time, and then goes back to the big stream. You the user don't have to worry about anything.

Maintain Accuracy, Speed, and Performance on your smallest timers, your small timers, and your big timers =).

Does this run as fast and as well as KT2?
I really don't know. I guess someone will have to test it. My only advice is that the best way to stress test this is by creating "unique" timers. Creating a bundle of the same timer will not add anything to the main stream... you have to create as many smaller streams as possible ^_^. This also has a limit of 8191 unique streams and from there 8191 unique pieces of code. Why? It uses arrays : D.


What is next?
Data Attachment
Syncing to and Desyncing from streams
Getting a code's life
Setting a code's life
Forced release of a stream and regular release of a stream (clear it out and release it or release if empty)
Forced release of Code and regular release of code (release now or release on next run)
Further optimizations? =p


Demo-

Copy this somewhere into the map and hit test map to see a small demonstration of this system.

JASS:
scope Test initializer Initialization
    globals
        private integer stream
    endglobals
    
    private function HelloWorld takes nothing returns nothing
        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Hello World!"))
        call BS_ReleaseCode(stream)
    endfunction
    
    private function Initialization takes nothing returns nothing
        set stream = BS_StreamCode(1.25, function HelloWorld)
    endfunction
endscope

System-
JASS:
/*Utility Information
//===================================================================
Name: Bit Streams
Version: 3.4
Author: Nestharus

Settings:
*///===================================================================
//! textmacro BS_BIT_RATE
    private constant integer BIT_RATE = 128
//! endtextmacro

//! textmacro BS_BIT_MAX
    private constant real BIT_MAX = 1
//! endtextmacro
/*//===================================================================

Description:
Stream: [url]http://en.wikipedia.org/wiki/Stream_(computing[/url])
This runs on a single Stream (timer) that creates various sub streams. The timer
is split into 3 primary streams. When a sub steam on one of the primary streams is
ready to run, its trigger is fired and all the actions on it go off. The actions are
split into two parts. The first part is internal. It is very small and simply prepares
the data for the second part. It also lets the system know exactly what piece of code is
running. The second part is the user part.

The only task a main stream does is go through everything on its stream and increment
it by its interval. While it's doing this, it checks to see if anything has reached its
timeout period or if it needs to move to the opposite stream.

Primary Stream: The primary stream starts the 3 main streams, these being the small stream,
the big stream, and the cleanup stream. The primary stream also increasing the game
time interval and the current bit. A bit is like a clock and it tells the streams
exactly what bit they are on. The primary stream will only run main streams if they
have data on them.

Small Stream: The small stream runs on small interval timers. When a big interval
timer has less than a big stream interval left, it swaps to the small stream
to finish off and then swaps back to the big stream. The small stream interval
is that of the BIT_RATE. The BIT_RATE is how many times per second the small stream
runs. Things have an interval of less than one second stay on the small stream. Things
that have the same interval as the small stream get added to the actual small stream.

Big Stream: The big stream runs bigger intervals. The big stream usually runs once
every second, but this can vary depending on the bitrate. A bitrate of more than one
should have an interval of 1 second on the big stream. A bitrate of one should have an
interval of 2 on the big stream. An bitrate of less than one should have an interval
of BIT*BIT.

Cleanup Stream: This stream rummages through a cleanup array after everything else is
done running. This means that when code is released, it is not cleaned up immediately. If
it were cleaned up immediately, the stream that it would be running on would be fractured.

So, what makes this system better than other systems that do around the same thing?
More features and an easier to use interface
Dynamic optimizations (streams going from big to small to big, always small staying small 
and always big staying big), streams only run when they have something in them, and well, 
the cleanup of course. This can actually run 8000 different streams on my laptop with a 128
bitrate with 0 lag starting at 1 bit and ending at 8000 bits and it can run just about as
well as plain timers when running single streams. There are so many optimizations in this, all
of them dynamic, there is just too much to explain o-o.

There are 3 main types of data associated with a piece of code that is streamed in. 
1.The first is the codeId, which is returned when it is sent in. Worried about having to keep track of it?
No problem, the codeId is accessible whenever the code runs.
2. The next is the data attached to the code, which is optional of course and can be changed at any time.
3. The final is the life of the code (how many times it should run). This life can of course be changed
and the current age of the code can always be retrieved.

So, do you have to do anything strange like with KT2? Do you need to say true here and false there and return
a boolean? Nope. You just run your everyday function in like you would a normal timer and BS does the rest. It
does use trigger conditions, so don't worry, it just converts the code you send into it into condition form.

Requirements: None

Installation: NA

Variables:
-BIT_RATE
    How many times per second the stream runs. The bigger the bit rate,
    the more accurate your timers can be. 128 is a good value and 64 is
    safe.
    
-BIT_MAX
    Suggest 1 for a bit rate of anything higher than one, BIT+BIT for
    1, and BIT*BIT for anything lower than 1.
    
-Main Functions:


Functions:
------------------------------------------------------------------
-BS_StreamCode(interval, code) returns integer
    Streamlines code and returns an id of the code
    local integer myStreamedCode = BS_StreamCode(1, function Hello)
    
-BS_ReleaseCode(codeId) returns nothing
    Will take code out of a stream
    call BS_ReleaseCode(myStreamedCode)

-BS_GET_STREAM_TIME(codeId) returns real
    Takes a code id value and returns the interval of the stream it is
    running on.
    local real timeout = BS_GET_STREAM_TIME(myStreamedCode)

-BS_GET_STREAM(codeId) returns integer
    Takes a code id value and returns the stream id that it is running
    on
    local integer stream = BS_GET_STREAM(myStreamedCode)
    
-BS_GET_ELAPSED_GAME_TIME() returns real
    Will return the current elapsed game time.
    local real gameTime = GetElapsedGameTime()
    
-BS_GET_DATA() returns integer
    Will return data for the current running code

-BS_UpdataData(data) returns nothing
    Will set the data for the current running code
    
-BS_GET_CURRENT_CODE() returns integer
    Will return the current running code
    
-BS_GET_CURRENT_STREAM() returns integer
    Will return the current running stream
    
-BS_GET_CODE_AGE() returns integer
    Will return how many times the code has run

-BS_GET_CODE_LIFE() returns itneger
    Will return how many times the code can run before being released
    
-BS_SetCodeLife(codeId, life)
    sets the life of the code
    
-BS_SetCurrentCodeLife(life)
    sets the life of the current running code
    
-BS_StreamCodeData(interval, code, data) returns integer
    Streamlines code and attaches data to it.
    
-BS_StreamCodeLife(interval, code, life) returns integer
    Streamlines code and sets its life
    
-BS_StreamCodeCombo(interval, code, data, life) returns integer
    Streamlines code and attaches data to it and sets its life
------------------------------------------------------------------*/
//===================================================================

library BS initializer Initialization
    globals
        //! runtextmacro BS_BIT_RATE()
        private constant integer BIT_SIZE = BIT_RATE*BIT_RATE
        private constant real BIT = 1./BIT_RATE
        //! runtextmacro BS_BIT_MAX()
        private real array bits
        private integer array bitIds
        private integer bitIdIndex = -1
        private boolean array streamExists
        private real array bitTable
        private integer array streamCodeCount
        private real gameSeconds = 0
        private real currentBit = 0
        private integer currentStream = 0
        private integer currentRunningCode = 0
        private trigger array streams
        private triggercondition array codeStreams
        private boolexpr array codes
        private integer codeStreamsIndex = 0
        private integer array codeStreamsQueu
        private integer codeStreamsQueuIndex = 0
        private integer array codeStreamId
        private real array codeStream
        private real array codeStreamProcess
        private boolean array streamHasRun
        private integer array smallStreamStack
        private integer array smallStreamStackR
        private integer array bigStreamStack
        private integer array bigStreamStackR
        private integer smallStreamStackIndex = 0
        private integer bigStreamStackIndex = 0
        private integer specialBigStreamStackIndex = 0
        private real array bitFired
        private integer array lastCode
        private integer array nextCode
        private integer array firstCode
        private integer array currentCode
        private integer array codeStack
        private integer array codeStackQueu
        private integer codeStackQueuIndex = 0
        private integer array codePointToStack
        private integer codeStackIndex = 0
        private integer array codeStackLoop
        private boolexpr setupCodeData
        private boolexpr specialSetupCodeData
        private boolexpr specialSetupCodeDataBig
        private integer array codeData
        private integer array toBeReleased
        private integer toBeReleasedIndex = 0
        private integer array codeAge
        private integer array codeLife
        private trigger cleanup = CreateTrigger()
        
        private trigger stream = CreateTrigger()
        private trigger bigStream = CreateTrigger()
        private event streamEvent = TriggerRegisterTimerEvent(stream, BIT, true)
        private boolexpr releaseCode
    endglobals
    
    private function AddStreamToBigStack takes integer id returns nothing
        set bigStreamStackIndex = bigStreamStackIndex + 1
        set bigStreamStack[bigStreamStackIndex] = id
        set bigStreamStackR[id] = bigStreamStackIndex
    endfunction
    
    private function AddStreamToSmallStack takes integer id returns nothing
        set smallStreamStackIndex = smallStreamStackIndex + 1
        set smallStreamStack[smallStreamStackIndex] = id
        set smallStreamStackR[id] = smallStreamStackIndex
    endfunction
    
    private function RemoveStreamFromBigStack takes integer id returns nothing
        set bigStreamStack[bigStreamStackR[id]] = bigStreamStack[bigStreamStackIndex]
        set bigStreamStackR[bigStreamStack[bigStreamStackIndex]] = bigStreamStackR[id]
        set bigStreamStackR[id] = 0
        set bigStreamStackIndex = bigStreamStackIndex - 1
    endfunction
    
    private function RemoveStreamFromSmallStack takes integer id returns nothing
        set smallStreamStack[smallStreamStackR[id]] = smallStreamStack[smallStreamStackIndex]
        set smallStreamStackR[smallStreamStack[smallStreamStackIndex]] = smallStreamStackR[id]
        set smallStreamStackR[id] = 0
        set smallStreamStackIndex = smallStreamStackIndex - 1
    endfunction
    
    private constant function BIG_STREAM takes real currentTime, real time returns boolean
        return (time-currentTime >= 1)
    endfunction
    
    private constant function IN_BIG_STREAM_STACK takes integer id returns boolean
        return (bigStreamStackR[id] > 0)
    endfunction
    
    private constant function IN_SMALL_STREAM_STACK takes integer id returns boolean
        return (smallStreamStackR[id] > 0)
    endfunction
    
    private function AddStreamToStack takes integer id, real currentTime, real time returns nothing
        if (time != currentTime) then
            if BIG_STREAM(currentTime, time) then
                if not IN_BIG_STREAM_STACK(id) then
                    if IN_SMALL_STREAM_STACK(id) then
                        call RemoveStreamFromSmallStack(id)
                    endif
                    call AddStreamToBigStack(id)
                endif
            elseif not IN_SMALL_STREAM_STACK(id) then
                if IN_BIG_STREAM_STACK(id) then
                    call RemoveStreamFromBigStack(id)
                endif
                call AddStreamToSmallStack(id)
            endif
        endif
    endfunction
    
    private function RemoveStreamFromStack takes integer id, real currentTime, real time returns nothing
        if BIG_STREAM(currentTime, time) then
            if IN_BIG_STREAM_STACK(id) then
                call RemoveStreamFromBigStack(id)
            endif
        elseif IN_SMALL_STREAM_STACK(id) then
            call RemoveStreamFromSmallStack(id)
        endif
    endfunction
    
    private function SetupStream takes integer id, real time returns nothing
        set bitIdIndex = bitIdIndex + 1
        set bitIds[bitIdIndex] = id
        set bitTable[id] = time
        set streamExists[id] = true
    endfunction
    
    private function CreateStream takes integer id, real time returns nothing
        set streams[id] = CreateTrigger()
        call SetupStream(id, time)
    endfunction
    
    private constant function GET_BIT_SIZE takes real time returns real
        return time/BIT
    endfunction
    
    private function Time2Id takes real time returns integer
        return R2I(GET_BIT_SIZE(time)-R2I(GET_BIT_SIZE(time)/8191)*8191)
    endfunction
    
    private function FindTime takes integer id, real time returns integer
        loop
            exitwhen bitTable[id] == time or bitTable[id] == 0
            set id = id + 1
        endloop
        return id
    endfunction
    
    private function GetStreamId takes real time returns integer
        local integer id = FindTime(Time2Id(time), time)
        if not streamExists[id] then
            call CreateStream(id, time)
        endif
        return id
    endfunction
    
    private function GetCodeId takes nothing returns integer
        if codeStreamsQueuIndex == 0 then
            set codeStreamsIndex = codeStreamsIndex + 1
            return codeStreamsIndex
        endif
        set codeStreamsQueuIndex = codeStreamsQueuIndex - 1
        return codeStreamsQueu[codeStreamsQueuIndex+1]
    endfunction
    
    private function StreamIntervalCode takes integer codeId, real time, boolexpr c returns triggercondition
        local integer id = GetStreamId(time)
        call AddStreamToStack(id, 0, time)
        set codeStreamId[codeId] = id
        set streamCodeCount[id] = streamCodeCount[id]+1
        set codes[codeId] = And(setupCodeData, c)
        return TriggerAddCondition(streams[id], codes[codeId])
    endfunction
    
    public constant function GET_STREAM_TIME takes integer codeId returns real
        return codeStream[codeId]
    endfunction
    
    public constant function GET_STREAM takes integer codeId returns integer
        return codeStreamId[codeId]
    endfunction
    
    private function ConvertTime takes real time returns real
        local real convertedTime
        local integer roundedTime
        if time > BIT then
            set convertedTime = time/BIT
            set roundedTime = R2I(convertedTime)
            return (R2I(convertedTime-roundedTime+BIT_MAX-.001)+roundedTime)*BIT
        endif
        return BIT
    endfunction
    
    private function GetCodeStream takes real time, boolexpr c, integer codeId returns triggercondition
        if time == BIT then
            set codeStreamId[codeId] = 1
            set codes[codeId] = And(specialSetupCodeData, c)
            return TriggerAddCondition(stream, codes[codeId])
        elseif time == BIT_MAX then
            set codeStreamId[codeId] = 2
            set specialBigStreamStackIndex = specialBigStreamStackIndex + 1
            set codes[codeId] = And(specialSetupCodeDataBig, c)
            return TriggerAddCondition(bigStream, codes[codeId])
        endif
        return StreamIntervalCode(codeId, time, c)
    endfunction
    
    private constant function CHECK_NEXT_CODE takes integer id returns boolean
        return (nextCode[codeStackLoop[id]] > 0)
    endfunction
    
    private function NextCode takes integer id returns integer
        local integer result = codeStackLoop[id]
        if CHECK_NEXT_CODE(id) then
            set codeStackLoop[id] = nextCode[codeStackLoop[id]]
        elseif not CHECK_NEXT_CODE(id) then
            set codeStackLoop[id] = firstCode[id]
        endif
        return codeStack[result]
    endfunction
    
    private function AddToCodeStackQueu takes integer stack returns nothing
        set codeStackQueuIndex = codeStackQueuIndex + 1
        set codeStackQueu[codeStackQueuIndex] = stack
    endfunction
    
    private function RemoveCodeFromStack takes integer id, integer stack returns integer
        local integer recycled = currentCode[id]
        if stack < currentCode[id] then
            set codeStack[stack] = codeStack[currentCode[id]]
            set codePointToStack[codeStack[stack]] = stack
        endif
        set nextCode[lastCode[currentCode[id]]] = 0
        set lastCode[currentCode[id]] = 0
        set currentCode[id] = currentCode[id] - 1
        return recycled
    endfunction
    
    private function RemoveCode takes integer id, integer codeId returns nothing
        call AddToCodeStackQueu(RemoveCodeFromStack(id, codePointToStack[codeId]))
        set codePointToStack[codeId] = 0
    endfunction
    
    private function CodeStackIndex takes integer id returns integer
        if codeStackQueuIndex > 0 then
            set codeStackQueuIndex = codeStackQueuIndex - 1
            return codeStackQueu[codeStackQueuIndex+1]
        endif
        return 0
    endfunction
    
    private function GetCodeStackIndex takes integer id returns integer
        local integer instancedIndex = CodeStackIndex(id)
        if instancedIndex == 0 then
            set codeStackIndex = codeStackIndex + 1
            return codeStackIndex
        endif
        return instancedIndex
    endfunction
    
    private function NewCode takes integer id returns integer
        local integer instancedIndex = GetCodeStackIndex(id)
        set lastCode[instancedIndex] = nextCode[lastCode[currentCode[id]]]
        set nextCode[lastCode[instancedIndex]] = instancedIndex
        set currentCode[id] = instancedIndex
        return instancedIndex
    endfunction
    
    private function StreamCodeList takes integer codeId, integer id returns nothing
        local integer instancedIndex
        if currentCode[id] > 0 then
            set instancedIndex = NewCode(id)
        else
            set instancedIndex = GetCodeStackIndex(id)
            set firstCode[id] = instancedIndex
            set currentCode[id] = instancedIndex
            set lastCode[currentCode[id]] = instancedIndex
            set nextCode[currentCode[id]] = instancedIndex
            set codeStackLoop[id] = firstCode[id]
        endif
        set codeStack[instancedIndex] = codeId
        set codePointToStack[codeId] = instancedIndex
    endfunction
    
    public constant function GET_DATA takes nothing returns integer
        return codeData[currentRunningCode]
    endfunction
    
    public constant function GET_CURRENT_CODE takes nothing returns integer
        return currentRunningCode
    endfunction
    
    public constant function GET_CURRENT_STREAM takes nothing returns integer
        return currentStream
    endfunction
    
    public function UpdateData takes integer data returns nothing
        set codeData[currentRunningCode] = data
    endfunction
    
    public function ReleaseCode takes integer codeId returns nothing
        set toBeReleasedIndex = toBeReleasedIndex + 1
        set toBeReleased[toBeReleasedIndex] = codeId
    endfunction
    
    private function IncCodeAge takes integer currentRunningCode returns boolean
        set codeAge[currentRunningCode] = codeAge[currentRunningCode] + 1
        return (codeLife[currentRunningCode] > 0 and codeAge[currentRunningCode] >= codeLife[currentRunningCode])
    endfunction
    
    private function SetupCodeData takes nothing returns boolean
        set currentRunningCode = NextCode(currentStream)
        if IncCodeAge(currentRunningCode) then
            call ReleaseCode(currentRunningCode)
        endif
        return true
    endfunction
    
    private function SpecialSetupCodeData takes nothing returns boolean
        set currentStream = 1
        call SetupCodeData()
        return true
    endfunction
    
    private function SpecialSetupCodeDataBig takes nothing returns boolean
        set currentStream = 2
        call SetupCodeData()
        return true
    endfunction
    
    public constant function GET_CODE_AGE takes nothing returns integer
        return codeAge[currentRunningCode]
    endfunction
    
    public constant function GET_CODE_LIFE takes nothing returns integer
        return codeLife[currentRunningCode]
    endfunction
    
    private function ReleaseCodeLife takes integer codeId, integer life returns boolean
        if life < 0 then
            set codeLife[codeId] = codeAge[codeId]
            return true
        endif
        return false
    endfunction
    
    public function SetCodeLife takes integer codeId, integer life returns nothing
        if not ReleaseCodeLife(codeId, life) then
            set codeLife[codeId] = life
        endif
    endfunction
    
    public function SetCurrentCodeLife takes integer life returns nothing
        call SetCodeLife(currentRunningCode, life)
    endfunction
    
    public function CatchCode takes nothing returns boolean
        local real time
        local integer id
        local integer codeId
        loop
            exitwhen toBeReleasedIndex == 0
            set codeId = toBeReleased[toBeReleasedIndex]
            set toBeReleasedIndex = toBeReleasedIndex - 1
            set time = GET_STREAM_TIME(codeId)
            if time >= BIT then
                set id = GET_STREAM(codeId)
                call RemoveCode(id, codeId)
                if time == BIT then
                    call TriggerRemoveCondition(stream, codeStreams[codeId])
                elseif time == BIT_MAX then
                    set specialBigStreamStackIndex = specialBigStreamStackIndex - 1
                    call TriggerRemoveCondition(bigStream, codeStreams[codeId])
                else
                    call TriggerRemoveCondition(streams[id], codeStreams[codeId])
                    set streamCodeCount[id] = streamCodeCount[id] - 1
                    if streamCodeCount[id] == 0 then
                        set codeStackLoop[id] = firstCode[id]
                        call RemoveStreamFromStack(id, codeStreamProcess[id], bitTable[id])
                    endif
                endif
                call DestroyBoolExpr(codes[codeId])
                set codeStreams[codeId] = null
                set codes[codeId] = null
                set codeStreamsQueuIndex = codeStreamsQueuIndex + 1
                set codeStreamsQueu[codeStreamsQueuIndex] = codeId
            endif
        endloop
        return true
    endfunction
    
    private function RunBigStream takes integer id returns nothing
        if (codeStreamProcess[bigStreamStack[id]] == bitTable[bigStreamStack[id]]) then
            set codeStreamProcess[bigStreamStack[id]] = 0
            set currentStream = bigStreamStack[id]
            set bitFired[bigStreamStack[id]] = currentBit
            call TriggerEvaluate(streams[bigStreamStack[id]])
        endif
    endfunction
    
    private function RunSmallStream takes integer id returns nothing
        if (codeStreamProcess[smallStreamStack[id]] == bitTable[smallStreamStack[id]]) then
            set codeStreamProcess[smallStreamStack[id]] = 0
            set currentStream = smallStreamStack[id]
            set bitFired[smallStreamStack[id]] = currentBit
            call TriggerEvaluate(streams[smallStreamStack[id]])
        endif
    endfunction
    
    private function IncBigStreamProcess takes integer id, real increase returns nothing
        set codeStreamProcess[bigStreamStack[id]] = codeStreamProcess[bigStreamStack[id]] + increase
    endfunction
    
    private function IncSmallStreamProcess takes integer id returns nothing
        set codeStreamProcess[smallStreamStack[id]] = codeStreamProcess[smallStreamStack[id]] + BIT
    endfunction
    
    private function StreamAddToSmallStack takes integer i returns nothing
        call AddStreamToStack(smallStreamStack[i], codeStreamProcess[smallStreamStack[i]], bitTable[smallStreamStack[i]])
    endfunction
    
    private function StreamAddToBigStack takes integer i returns nothing
        call AddStreamToStack(bigStreamStack[i], codeStreamProcess[bigStreamStack[i]], bitTable[bigStreamStack[i]])
    endfunction
    
    private function SmallStream takes nothing returns boolean
        local integer i = 1
        local integer end = smallStreamStackIndex
        loop
            exitwhen i > end
            call IncSmallStreamProcess(i)
            call RunSmallStream(i)
            if bitTable[smallStreamStack[i]] >= BIT_MAX then
                set streamHasRun[smallStreamStack[i]] = true
                call StreamAddToSmallStack(i)
            endif
            set i = i + 1
        endloop
        return true
    endfunction
    
    private function BigStream takes nothing returns boolean
        local integer i = 1
        local integer end = bigStreamStackIndex
        loop
            exitwhen i > end
            if not streamHasRun[bigStreamStack[i]] then
                call IncBigStreamProcess(i, BIT_MAX)
                call RunBigStream(i)
                call StreamAddToBigStack(i)
            elseif bitTable[bigStreamStack[i]] > 1 then
                call IncBigStreamProcess(i, (BIT_MAX-bitFired[bigStreamStack[i]]))
                call RunBigStream(i)
                set streamHasRun[bigStreamStack[i]] = false
                call StreamAddToBigStack(i)
            else
                set streamHasRun[bigStreamStack[i]] = false
            endif
            set i = i + 1
        endloop
        return true
    endfunction
    
    public constant function GET_ELAPSED_GAME_TIME takes nothing returns real
        return currentBit + gameSeconds
    endfunction
    
    private constant function BIG_STREAM_CHECK takes nothing returns boolean
        return (currentBit == BIT_MAX)
    endfunction

    private function Stream takes nothing returns boolean
        if BIG_STREAM_CHECK() then
            set gameSeconds = gameSeconds + BIT_MAX
        endif
        set currentBit = currentBit - R2I(currentBit) + BIT
        if smallStreamStackIndex > 0 then
            call SmallStream()
        endif
        if BIG_STREAM_CHECK() then
            if bigStreamStackIndex > 0 or specialBigStreamStackIndex > 0 then
                call TriggerEvaluate(bigStream)
            endif
        endif
        if toBeReleasedIndex > 0 then
            call TriggerEvaluate(cleanup)
        endif
        return true
    endfunction
    
    private function ClearCodeData takes integer codeId returns nothing
        set codeData[codeId] = 0
        set codeAge[codeId] = 0
        set codeLife[codeId] = 0
    endfunction
    
    private function AddCodeToStream takes real time, code c returns integer
        local integer codeId = GetCodeId()
        set time = ConvertTime(time)
        set codeStream[codeId] = time
        set codeStreams[codeId] = GetCodeStream(time, Condition(c), codeId)
        call StreamCodeList(codeId, codeStreamId[codeId])
        return codeId
    endfunction
    
    public function StreamCode takes real time, code c returns integer
        local integer codeId = AddCodeToStream(time, c)
        call ClearCodeData(codeId)
        return codeId
    endfunction
    
    public function StreamCodeData takes real time, code c, integer data returns integer
        local integer codeId = StreamCode(time, c)
        set codeData[codeId] = data
        return codeId
    endfunction
    
    public function StreamCodeLife takes real time, code c, integer life returns integer
        local integer codeId = StreamCode(time, c)
        set codeLife[codeId] = life
        return codeId
    endfunction
    
    public function StreamCodeCombo takes real time, code c, integer data, integer life returns integer
        local integer codeId = StreamCode(time, c)
        set codeData[codeId] = data
        set codeLife[codeId] = life
        return codeId
    endfunction
    
    private function Initialization takes nothing returns nothing
        call TriggerAddCondition(bigStream, Condition(function BigStream))
        call TriggerAddCondition(stream, Condition(function Stream))
        set setupCodeData = Condition(function SetupCodeData)
        set specialSetupCodeData = Condition(function SpecialSetupCodeData)
        set specialSetupCodeDataBig = Condition(function SpecialSetupCodeDataBig)
        call TriggerAddCondition(cleanup, Condition(function CatchCode))
        set bitTable[1] = BIT
        set bitTable[2] = BIT_MAX
    endfunction
endlibrary
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Update numero 1 ^_^

Update numero 2 ^_^

Ok, working on a third build that where 1 timer on this should be just about as fast as a regular timer... 2 timers on this should be almost as fast as 1 timer and faster than 2 timers... 10 timers should be faster than 2 timers and almost as fast as 1 timer.

I call it Lucy (no not really) but yea... I had a genius idea for the new build that has never been done. It will have 0 triggers and 1 timer for the ultimate in speed, it'll maintain its current API ^_^.
 
Last edited:
Top