Warcraft III: MapsModelsSkinsIconsSpellsToolsTutorials
WC3 JASS: Code SnippetsJASS and vJASS Spells and SystemsJass Tutorials
Chat @Discord

Author Topic: LoopCode  (Read 3616 times)

  • Newbie - level 1
  • *
  • Posts: 13
  • WC3 Models: 0
  • WC3 Tutorials: 0
  • WC3 Tools: 0
  • WC3 Maps: 0
  • WC3 Skins: 0
  • WC3 Icons: 0
  • WC3 Spells: 0
  • Reputation: 0
  • Just a Man in the Back
    • View Profile
LoopCode
« on: August 27, 2016, 10:51:21 AM »
LoopCode v1.3

This system allows you to register a code that will run every specified timeout. Note that this system only uses one timer for all registered codes. Therefore, codes with periods indivisible by 0.03125 doesn't run with a constant time interval. Although the difference will not exceed 0.03125, you probably don't want it to be that way. But this will not be much of a problem for codes with low frequency period such as those with timeouts greater than 2 seconds since the difference wouldn't be so noticeable.

In short, this works best for codes with timeout divisible by 0.03125 seconds.

Main Script
Code: jass  [Select]
  1. library LoopCode
  2.  
  3.  
  4.     //! novjass
  5.      ________________
  6.     |                |
  7.     | Written by AGD |
  8.     |________________|
  9.  
  10.     |=====|
  11.     | API |
  12.     |=====|
  13.  
  14.       function interface LoopCode takes nothing returns nothing/*
  15.         - Interface of functions to be registered in the loop
  16.  
  17.     */function RegisterLoopCode takes LoopCode c, real timeout returns boolean/*
  18.         - Registers a code to run every <timeout> seconds and returns a boolean value depending
  19.         on the success of the operation
  20.  
  21.     */function RemoveLoopCode takes LoopCode c returns boolean/*
  22.         - Unregisters a code from the loop and returns a boolean value depending
  23.         on the success of the operation
  24.  
  25.     */function SetCodeTimeout takes LoopCode c, real timeout returns boolean/*
  26.         - Sets a new loop timeout for a code
  27.  
  28.     *///! endnovjass
  29.  
  30.     //======================================================================================
  31.  
  32.     globals
  33.         private constant real TIMEOUT = 0.03125
  34.         private constant boolean AUTO_ADJUST = true
  35.     endglobals
  36.  
  37.     //======================================================================================
  38.  
  39.     globals
  40.         private LoopCode array codes
  41.         private timer Timer = CreateTimer()
  42.         private integer id = 0
  43.         private integer count = 0
  44.         private real array codeTimeout
  45.         private real array elapsed
  46.         private integer array index
  47.         private boolean array check
  48.     endglobals
  49.  
  50.     //======================================================================================
  51.  
  52.     function interface LoopCode takes nothing returns nothing
  53.  
  54.     static if DEBUG_MODE then
  55.         private function Debug takes string msg returns nothing
  56.             call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "|CFFFFCC00[LoopEvent] :|R" + msg)
  57.         endfunction
  58.     endif
  59.  
  60.     private function RunLoop takes nothing returns nothing
  61.         set id = 0
  62.         loop
  63.             set id = id + 1
  64.             set elapsed[id] = elapsed[id] + TIMEOUT
  65.             if elapsed[id] >= codeTimeout[id] then
  66.                 call codes[id].evaluate()
  67.                 set elapsed[id] = elapsed[id] - codeTimeout[id]
  68.             endif
  69.             exitwhen id == count
  70.         endloop
  71.     endfunction
  72.  
  73.     function RegisterLoopCode takes LoopCode c, real timeout returns boolean
  74.         static if AUTO_ADJUST then
  75.             if timeout < TIMEOUT then
  76.                 set timeout = TIMEOUT
  77.                 debug call Debug("Entered code execution timeout is less than the minimum value (" + R2S(TIMEOUT) + "), auto-adjusting timeout to (" + R2S(TIMEOUT) + ")")
  78.             endif
  79.         else
  80.             if timeout < TIMEOUT then
  81.                 debug call Debug("ERROR: Entered code execution timeout is less than the minimum value (" + R2S(TIMEOUT) + ")")
  82.                 return false
  83.             endif
  84.         endif
  85.         if not check[c] then
  86.             debug if timeout - (timeout/TIMEOUT)*TIMEOUT > 0.00 then
  87.                 debug call Debug("WARNING: Entered code timeout is not divisible by " + R2S(TIMEOUT) + ", this code's execution interval will not be even")
  88.             debug endif
  89.             set count = count + 1
  90.             set elapsed[count] = 0.00
  91.             set codeTimeout[count] = timeout
  92.             set codes[count] = c
  93.             set index[c] = count
  94.             set check[c] = true
  95.             if count == 1 then
  96.                 call TimerStart(Timer, TIMEOUT, true, function RunLoop)
  97.                 debug call Debug("There is one code instance registered, starting to run timer")
  98.             endif
  99.             return true
  100.         endif
  101.         debug call Debug("ERROR: Attempt to double register a code")
  102.         return false
  103.     endfunction
  104.  
  105.     function RemoveLoopCode takes LoopCode c returns boolean
  106.         local integer i = index[c]
  107.         if check[c] then
  108.             debug call Debug("Removing a code from the loop")
  109.             set check[c] = false
  110.             set index[codes[count]] = i
  111.             set codes[i] = codes[count]
  112.             set codeTimeout[i] = codeTimeout[count]
  113.             if id >= i then
  114.                 set id = id - 1
  115.             endif
  116.             set count = count - 1
  117.             if count == 0 then
  118.                 call TimerStart(Timer, 0, false, null)
  119.                 debug call Debug("There are no code instances running, stopping timer")
  120.             endif
  121.             return true
  122.         endif
  123.         debug call Debug("ERROR: Attempt to remove a null or an already removed code")
  124.         return false
  125.     endfunction
  126.  
  127.     function SetCodeTimeout takes LoopCode c, real timeout returns boolean
  128.         local integer i = index[c]
  129.         if check[c] then
  130.             static if AUTO_ADJUST then
  131.                 if codeTimeout[i] >= TIMEOUT then
  132.                     set codeTimeout[i] = timeout
  133.                 else
  134.                     set codeTimeout[i] = TIMEOUT
  135.                     debug call Debug("Entered code execution timeout is less than the minimum value (" + R2S(TIMEOUT) + "), auto-adjusting timeout to (" + R2S(TIMEOUT) + ")")
  136.                 endif
  137.                 return true
  138.             else
  139.                 if codeTimeout[i] >= TIMEOUT then
  140.                     set codeTimeout[i] = timeout
  141.                     return true
  142.                 endif
  143.                 debug call Debug("ERROR: Entered code execution timeout is less than the minimum value (" + R2S(TIMEOUT) + ")")
  144.                 return false
  145.             endif
  146.         endif
  147.         debug call Debug("ERROR: Specified code is not registered")
  148.         return false
  149.     endfunction
  150.  
  151.  
  152. endlibrary


Sample Script
Code: jass  [Select]
  1. scope MySpell initializer Init
  2.  
  3.     globals
  4.         private constant real TIMEOUT = 0.03125
  5.         private integer maxIndex = 0
  6.         private real array elapsed
  7.     endglobals
  8.  
  9.     private function Loop takes nothing returns nothing
  10.         local integer index = 0
  11.         loop
  12.             set index = index + 1
  13.             if elapsed < 10 then
  14.                 set elapsed[index] = elapsed[index] + TIMEOUT
  15.             else
  16.                 set elapsed[index] = elapsed[maxIndex]
  17.                 set maxIndex = maxIndex - 1
  18.                 set index = index - 1
  19.                 if maxIndex == 0 then
  20.                     call RemoveLoopCode(LoopCode.Loop)
  21.                 endif
  22.             endif
  23.             exitwhen index == maxIndex
  24.         endloop
  25.     endfunction
  26.  
  27.     private function OnCast takes nothing returns boolean
  28.         // Setup spell data and oncast effects
  29.         set maxIndex = maxIndex + 1
  30.         set elapsed[maxIndex] = 0.00
  31.         call RegisterLoopCode(LoopCode.Loop, TIMEOUT)
  32.         return false
  33.     endfunction
  34.  
  35.     private function Init takes nothing returns nothing
  36.         local trigger t = CreateTrigger()
  37.         call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
  38.         call TriggerAddCondition(t, FIlter(function OnCast))
  39.     endfunction
  40.  
  41. endscope


Changelogs
v1.3
- Fixed a minor error concerning the index of a registered code in the RunLoop not being decremented by 1 when a code is removed from the loop.

v1.2
- Replaced TriggerEvaluate() with .evaluate() through the use of function interface
- Added an option to the configuration whether or not the system will automatically adjust the code timeout in case the entered timeout is lesser than the minimum supported timeout
- Removed the requirement Table. Instead, uses arrays which were made possible through using interface functions as the index.

v1.1
- Fixed the bug regarding the incorrect unregistering and re-registering codes to the loop
- Uses a TableArray instead of two separate tables

v1.0
- Initial release

Feedback will be appreciated.
« Last Edit: September 07, 2016, 10:51:14 PM by AGD »

 

Blizzard Modding Information Center Starcraft II Modding Information Center Wacraft III Modding Information Center WC3JASS.com - The JASS Vault Chronicles of Darkness - A Warcraft III mod Jetcraft - A Starcraft II mod Troll Smash - A Warcraft III Arena
  Mod DB - Change the Game Power of Corruption - A Warcraft III altered melee map Chaos Realm - The world of Game modders and wc3 addicts Follow us on Facebook!!