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

Recent Posts

Pages: [1] 2 3 ... 10
1
Codes & Snippets / Re: BoolexprUtils
« Last post by moyack on November 08, 2016, 09:15:32 AM »
simple, but effective ;)

Good job!
2
Codes & Snippets / BoolexprUtils
« Last post by AGD on November 08, 2016, 08:04:14 AM »
True and False BooleanExpressions

Credits goes to Vexorian for the first idea.


Vjass version
Code: jass  [Select]
  1. library BoolexprUtils
  2.  
  3.     globals
  4.         boolexpr BOOLEXPR_TRUE
  5.         boolexpr BOOLEXPR_FALSE
  6.     endglobals
  7.  
  8.     private module Init
  9.  
  10.         private static method filterTrue takes nothing returns boolean
  11.             return true
  12.         endmethod
  13.  
  14.         private static method filterFalse takes nothing returns boolean
  15.             return false
  16.         endmethod
  17.  
  18.         private static method onInit takes nothing returns nothing
  19.             set BOOLEXPR_TRUE = Filter(function thistype.filterTrue)
  20.             set BOOLEXPR_TRUE = Filter(function thistype.filterFalse)
  21.         endmethod
  22.  
  23.     endmodule
  24.  
  25.     private struct S extends array
  26.         implement Init
  27.     endstruct
  28.  
  29. endlibrary

Zinc version
Code: jass  [Select]
  1. //! zinc
  2. library BoolexprUtils {
  3.  
  4.     public boolexpr BOOLEXPR_TRUE, BOOLEXPR_FALSE;
  5.  
  6.     module Init {
  7.         static method onInit() {
  8.             BOOLEXPR_TRUE = Filter(function() -> boolean {return true;});
  9.             BOOLEXPR_FALSE = Filter(function() -> boolean {return false;});
  10.         }
  11.     }
  12.  
  13.     struct S extends array {module Init;}
  14.  
  15. }
  16. //! endzinc
3
Codes & Snippets / Re: UnitRecycler
« Last post by AGD on November 05, 2016, 09:25:50 AM »
Oh, nice to know that you already have conceived the concept a long time ago =D Though the two resources have a bit different approach.
Btw, mine does not account for summoned units and structures yet.
4
Codes & Snippets / Re: UnitRecycler
« Last post by moyack on November 02, 2016, 10:51:45 AM »
Nice!!! a unit recycler system :)

This remembers an old one I did with Damage detection integrated. Here's the link: http://blizzardmodding.info/4529/system-unit-recycler-simple-damage-detection-system/

One thing to know: is this system capable to manage buildings and summoned units?
5
Codes & Snippets / UnitRecycler
« Last post by AGD on November 02, 2016, 03:36:36 AM »
A useful library which allows you to recycle units (even dead ones, but they must leave a corpse), avoiding yet another permanent 0.04kb memory leak for each future CreateUnit() call.


Script
Code: jass  [Select]
  1. library UnitRecycler /* v1.3b
  2.  
  3.  
  4.     |=============|
  5.     | Author: AGD |
  6.     |=============|
  7.  
  8.     */requires /*
  9.  
  10.     */ReviveUnit                        /*  http://www.hiveworkshop.com/threads/snippet-reviveunit.186696/
  11.     */UnitDex                           /*  http://www.hiveworkshop.com/threads/system-unitdex-unit-indexer.248209/
  12.     */optional Table                    /*  http://www.hiveworkshop.com/threads/snippet-new-table.188084/
  13.     */optional TimerUtils               /*  http://www.wc3c.net/showthread.php?t=101322
  14.     */optional RegisterPlayerUnitEvent  /*  http://www.hiveworkshop.com/threads/snippet-registerevent-pack.250266/
  15.  
  16.     This system is important because CreateUnit() is one of the most processor-intensive function in
  17.     the game and there are reports that even after they are removed, they still leave some bit of memory
  18.     consumption (0.04 KB) on the RAM. Therefore it would be very helpful if you can minimize unit
  19.     creation or so. This system also allows you to recycle dead units to avoid permanent 0.04 KB memory
  20.     leak for each future CreateUnit() call.                                                                 */
  21.  
  22. //! novjass
  23.  
  24.     [Credits]
  25.         Aniki - For suggesting ideas on further improvements
  26.  
  27.  
  28.     |-----|
  29.     | API |
  30.     |-----|
  31.  
  32.         function GetRecycledUnit takes player owner, integer rawCode, real x, real y, real facing returns unit/*
  33.             - Returns unit of specified ID from the stock of recycled units. If there's none in the stock that
  34.               matched the specified unit's rawcode, it will create a new unit instead
  35.             - Returns null if the rawcode's unit-type is a hero or non-existent
  36.  
  37.       */function GetRecycledUnitEx takes player owner, integer rawCode, real x, real y, real facing returns unit/*
  38.             - Works similar to GetRecycledUnit() except that if the input rawcode's unit-type is a hero, it will
  39.               be created via CreateUnit() instead
  40.             - You can use this as an alternative to CreateUnit()
  41.  
  42.       */function RecycleUnit takes unit u returns boolean/*
  43.             - Recycles the specified unit and returns a boolean value depending on the success of the operation
  44.             - Does nothing to hero units
  45.  
  46.       */function RecycleUnitEx takes unit u returns boolean/*
  47.             - Works similar to RecycleUnit() except that if <u> is not recyclable, it will be removed via
  48.               RemoveUnit() instead
  49.             - You can use this as an alternative to RemoveUnit()
  50.  
  51.       */function RecycleUnitDelayed takes unit u, real delay returns nothing/*
  52.             - Recycles the specified unit after <delay> seconds
  53.  
  54.       */function RecycleUnitDelayedEx takes unit u, real delay returns nothing/*
  55.             - Works similar to RecycleUnitDelayed() except that it calls RecycleUnitEx() instead of RecycleUnit()
  56.  
  57.       */function UnitAddToStock takes integer rawCode returns boolean/*
  58.             - Creates a unit of type ID and adds it to the stock of recycled units then returns a boolean value
  59.               depending on the success of the operation
  60.  
  61. *///! endnovjass
  62.  
  63.     //CONFIGURATION SECTION
  64.  
  65.  
  66.     globals
  67.  
  68. /*      The owner of the stocked/recycled units
  69. */      private constant player OWNER               = Player(15)
  70.  
  71. /*      Determines if dead units will be automatically recycled
  72.         after a delay designated by the <constant function
  73.         DeathTime below>
  74. */      private constant boolean AUTO_RECYCLE_DEAD  = true
  75.  
  76. /*      Error debug message prefix
  77. */      private constant string ERROR_PREFIX        = "|CFFFF0000Operation Failed: "
  78.  
  79.     endglobals
  80.  
  81.     /* The delay before dead units will be recycled in case AUTO_RECYCLE_DEAD == true */
  82.     static if AUTO_RECYCLE_DEAD then
  83.         private constant function DeathTime takes unit u returns real
  84.             /*if <condition> then
  85.                   return someValue
  86.               elseif <condition> then
  87.                   return someValue
  88.               endif                 */
  89.             return 8.00
  90.         endfunction
  91.     endif
  92.  
  93.     /* When recycling a unit back to the stock, these resets will be applied to the
  94.        unit. You can add more actions to this or you can delete this textmacro if you
  95.        don't need it.                                                                       */
  96.         //! textmacro_once UNIT_RECYCLER_RESET
  97.             call SetUnitScale(u, 1, 0, 0)
  98.             call SetUnitVertexColor(u, 255, 255, 255, 255)
  99.             call SetUnitFlyHeight(u, GetUnitDefaultFlyHeight(u), 0)
  100.         //! endtextmacro
  101.  
  102.  
  103.     //END OF CONFIGURATION
  104.  
  105.     /*==== Do not do changes below this line if you're not so sure on what you're doing ====*/
  106.     native UnitAlive takes unit u returns boolean
  107.  
  108.     globals
  109.         private keyword S
  110.         private integer count = 0
  111.         private real unitCampX
  112.         private real unitCampY
  113.         private integer array stack
  114.         private boolean array stacked
  115.     endglobals
  116.  
  117.     private function GetIndex takes integer rawCode returns integer
  118.         static if LIBRARY_Table then
  119.             local integer i = S.table.integer[rawCode]
  120.             if i == 0 then
  121.                 set count = count + 1
  122.                 set S.table.integer[rawCode] = count
  123.                 set i = count
  124.             endif
  125.         else
  126.             local integer i = LoadInteger(S.hash, -1, rawCode)
  127.             if i == 0 then
  128.                 set count = count + 1
  129.                 call SaveInteger(S.hash, -1, rawCode, count)
  130.                 set i = count
  131.             endif
  132.         endif
  133.         return i
  134.     endfunction
  135.  
  136.     static if DEBUG_MODE then
  137.         private function Debug takes string msg returns nothing
  138.             call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "|CFFFFCC00[Unit Recycler]|R " + msg)
  139.         endfunction
  140.     endif
  141.  
  142.     function GetRecycledUnit takes player owner, integer rawCode, real x, real y, real facing returns unit
  143.         local integer i
  144.         if not IsHeroUnitId(rawCode) then
  145.             set i = GetIndex(rawCode)
  146.             if stack[i] == 0 then
  147.                 set bj_lastCreatedUnit = CreateUnit(owner, rawCode, x, y, facing)
  148.                 debug call Debug(GetUnitName(bj_lastCreatedUnit) + " stock is empty, creating new " + GetUnitName(bj_lastCreatedUnit))
  149.             else
  150.                 static if LIBRARY_Table then
  151.                     set bj_lastCreatedUnit = S.hash[i].unit[stack[i]]
  152.                 else
  153.                     set bj_lastCreatedUnit = LoadUnitHandle(S.hash, i, stack[i])
  154.                 endif
  155.                 set stacked[GetUnitId(bj_lastCreatedUnit)] = false
  156.                 call PauseUnit(bj_lastCreatedUnit, false)
  157.                 call SetUnitOwner(bj_lastCreatedUnit, owner, true)
  158.                 call SetUnitPosition(bj_lastCreatedUnit, x, y)
  159.                 call SetUnitFacing(bj_lastCreatedUnit, facing)
  160.                 set stack[i] = stack[i] - 1
  161.                 debug call Debug("Retrieving " + GetUnitName(bj_lastCreatedUnit) + " from stock")
  162.             endif
  163.             debug if bj_lastCreatedUnit == null then
  164.                 debug call Debug(ERROR_PREFIX + "Specified unit-type does not exist")
  165.             debug endif
  166.         else
  167.             debug call Debug(ERROR_PREFIX + "Attemp to retrieve a hero unit")
  168.             return null
  169.         endif
  170.         return bj_lastCreatedUnit
  171.     endfunction
  172.  
  173.     function GetRecycledUnitEx takes player owner, integer rawCode, real x, real y, real facing returns unit
  174.         if not IsHeroUnitId(rawCode) then
  175.             return GetRecycledUnit(owner, rawCode, x, y, facing)
  176.         endif
  177.         debug call Debug("Cannot retrieve a hero unit, creating new unit")
  178.         return CreateUnit(owner, rawCode, x, y, facing)
  179.     endfunction
  180.  
  181.     function RecycleUnit takes unit u returns boolean
  182.         local integer rawCode = GetUnitTypeId(u)
  183.         local integer uDex = GetUnitId(u)
  184.         local integer i
  185.         if not IsHeroUnitId(rawCode) and not stacked[uDex] and u != null then
  186.             set i = GetIndex(rawCode)
  187.             if not UnitAlive(u) and not ReviveUnit(u) then
  188.                 debug call Debug(ERROR_PREFIX + "Unable to recycle unit: Unable to revive dead unit")
  189.                 return false
  190.             endif
  191.             set stacked[uDex] = true
  192.             call PauseUnit(u, true)
  193.             call SetUnitOwner(u, OWNER, true)
  194.             call SetUnitX(u, unitCampX)
  195.             call SetUnitY(u, unitCampY)
  196.             call SetUnitFacing(u, 270)
  197.             call SetWidgetLife(u, GetUnitState(u, UNIT_STATE_MAX_LIFE))
  198.             call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MAX_MANA))
  199.             //! runtextmacro optional UNIT_RECYCLER_RESET()
  200.             set stack[i] = stack[i] + 1
  201.             static if LIBRARY_Table then
  202.                 set S.hash[i].unit[stack[i]] = u
  203.             else
  204.                 call SaveUnitHandle(S.hash, i, stack[i], u)
  205.             endif
  206.             debug call Debug("Successfully recycled " + GetUnitName(u))
  207.             return true
  208.         debug else
  209.             debug if stacked[uDex] then
  210.                 debug call Debug(ERROR_PREFIX + "Attempt to recycle an already recycled unit")
  211.             debug elseif u == null then
  212.                 debug call Debug(ERROR_PREFIX + "Attempt to recycle a null unit")
  213.             debug else
  214.                 debug call Debug(ERROR_PREFIX + "Attempt to recycle a hero unit")
  215.             debug endif
  216.         endif
  217.         return false
  218.     endfunction
  219.  
  220.     function RecycleUnitEx takes unit u returns boolean
  221.         if not RecycleUnit(u) then
  222.             call RemoveUnit(u)
  223.             debug call Debug("Cannot recycle the specified unit, removing unit")
  224.             return false
  225.         endif
  226.         return true
  227.     endfunction
  228.  
  229.     //! textmacro DELAYED_RECYCLE_TYPE takes EX
  230.     private function RecycleTimer$EX$ takes nothing returns nothing
  231.         local timer t = GetExpiredTimer()
  232.         static if LIBRARY_TimerUtils then
  233.             call RecycleUnit$EX$(GetUnitById(GetTimerData(t)))
  234.             call ReleaseTimer(t)
  235.         else
  236.             local integer key = GetHandleId(t)
  237.             static if LIBRARY_Table then
  238.                 call RecycleUnit$EX$(S.hash[0].unit[key])
  239.                 call S.hash[0].remove(key)
  240.             else
  241.                 call RecycleUnit$EX$(LoadUnitHandle(S.hash, 0, key))
  242.                 call RemoveSavedHandle(S.hash, 0, key)
  243.             endif
  244.             call DestroyTimer(t)
  245.         endif
  246.         set t = null
  247.     endfunction
  248.  
  249.     function RecycleUnitDelayed$EX$ takes unit u, real delay returns nothing
  250.         static if LIBRARY_TimerUtils then
  251.             call TimerStart(NewTimerEx(GetUnitId(u)), delay, false, function RecycleTimer$EX$)
  252.         else
  253.             local timer t = CreateTimer()
  254.             static if LIBRARY_Table then
  255.                 set S.hash[0].unit[GetHandleId(t)] = u
  256.             else
  257.                 call SaveUnitHandle(S.hash, 0, GetHandleId(t), u)
  258.             endif
  259.             call TimerStart(t, delay, false, function RecycleTimer$EX$)
  260.             set t = null
  261.         endif
  262.     endfunction
  263.     //! endtextmacro
  264.  
  265.     //! runtextmacro DELAYED_RECYCLE_TYPE("")
  266.     //! runtextmacro DELAYED_RECYCLE_TYPE("Ex")
  267.  
  268.     function UnitAddToStock takes integer rawCode returns boolean
  269.         local unit u
  270.         local integer i
  271.         if not IsHeroUnitId(rawCode) then
  272.             set u = CreateUnit(OWNER, rawCode, unitCampX, unitCampY, 270)
  273.             if u != null then
  274.                 set i = GetIndex(rawCode)
  275.                 call SetUnitX(u, unitCampX)
  276.                 call SetUnitY(u, unitCampY)
  277.                 call PauseUnit(u, true)
  278.                 set stacked[GetUnitId(u)] = true
  279.                 set stack[i] = stack[i] + 1
  280.                 static if LIBRARY_Table then
  281.                     set S.hash[i].unit[stack[i]] = u
  282.                 else
  283.                     call SaveUnitHandle(S.hash, i, stack[i], u)
  284.                 endif
  285.                 debug call Debug("Adding " + GetUnitName(u) + " to stock")
  286.                 return true
  287.             debug else
  288.                 debug call Debug(ERROR_PREFIX + "Attemp to stock a null unit")
  289.             endif
  290.             set u = null
  291.         debug else
  292.             debug call Debug(ERROR_PREFIX + "Attemp to stock a hero unit")
  293.         endif
  294.         return false
  295.     endfunction
  296.  
  297.     static if AUTO_RECYCLE_DEAD then
  298.         private function OnDeath takes nothing returns nothing
  299.             local unit u = GetTriggerUnit()
  300.             if not IsUnitType(u, UNIT_TYPE_HERO) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
  301.                 call RecycleUnitDelayed(u, DeathTime(u))
  302.             endif
  303.             set u = null
  304.         endfunction
  305.     endif
  306.  
  307.     private module Init
  308.  
  309.         static if LIBRARY_Table then
  310.             static TableArray hash
  311.             static Table table
  312.         else
  313.             static hashtable hash = InitHashtable()
  314.         endif
  315.  
  316.         private static method onInit takes nothing returns nothing
  317.             local rect bounds = GetWorldBounds()
  318.             static if AUTO_RECYCLE_DEAD then
  319.                 static if LIBRARY_RegisterPlayerUnitEvent then
  320.                     static if RPUE_VERSION_NEW then
  321.                         call RegisterAnyPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function OnDeath)
  322.                     else
  323.                         call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function OnDeath)
  324.                     endif
  325.                 else
  326.                     local trigger t = CreateTrigger()
  327.                     local code c = function OnDeath
  328.                     local integer i = 16
  329.                     loop
  330.                         set i = i - 1
  331.                         call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_DEATH, null)
  332.                         exitwhen i == 0
  333.                     endloop
  334.                     call TriggerAddCondition(t, Filter(c))
  335.                 endif
  336.             endif
  337.             static if LIBRARY_Table then
  338.                 set hash = TableArray[0x2000]
  339.                 set table = Table.create()
  340.             endif
  341.             // Hides recycled units at the top of the map beyond reach of the camera
  342.             set unitCampX = 0.00
  343.             set unitCampY = GetRectMaxY(bounds) + 1000.00
  344.             call RemoveRect(bounds)
  345.             set bounds = null
  346.         endmethod
  347.  
  348.     endmodule
  349.  
  350.     private struct S extends array
  351.         implement Init
  352.     endstruct
  353.  
  354.  
  355. endlibrary
6
Codes & Snippets / Re: Resource Preloader
« Last post by AGD on October 28, 2016, 01:03:52 AM »
UPDATED


- Made Table optional
- Added UnitRecycler as an optional requirement
- Upon calling PreloadUnit(), if the unit is not a hero and UnitRecycler is found, the unit will be added to the unit stock instead. Otherwise, it goes with normal preloading.
- dummy unit's movement is disabled to prevent possible game crash.
- You can now preload at any time during the game instead of only during the map initialization
- Significantly optimized the code
- Removed the unnecessary custom function for checking preload duplicates
- Added Table to the library requirements
- Preloading does not anymore happen in a single phase at the GUI Map Initialization
- Resources are now preloaded at the instant you call the preload function
- Other changes
7
Codes & Snippets / Re: Random Iteration
« Last post by moyack on September 04, 2016, 10:22:47 AM »
I just did some small aesthetics for your post. Interesting snippet :)
8
Codes & Snippets / Random Iteration
« Last post by AGD on September 04, 2016, 09:16:22 AM »
This snippet is a replacement to the BJ function GetRandomSubGroup with the advantage of being able to directly enumerate random number of units in a group instead of creating another subgroup of an already existing group. Notice that this is not the same as GroupEnumUnitsInRangeCounted in which case the enumerated units are not random but is based on which units are picked first.


Code: jass  [Select]
  1. library RandomIteration
  2.  
  3.     globals
  4.         private group tempGroup = CreateGroup()
  5.         private integer unitCount
  6.     endglobals
  7.  
  8.     private function EnumUnits takes nothing returns boolean
  9.         call GroupAddUnit(tempGroup, GetFilterUnit())
  10.         set unitCount = unitCount + 1
  11.         return false
  12.     endfunction
  13.  
  14.     function EnumRandomUnitsInRangeCounted takes group g, real x, real y, real radius, integer limit returns nothing
  15.         local real chance
  16.         local unit u
  17.         call GroupEnumUnitsInRange(g, x, y, radius, Filter(function EnumUnits))
  18.         set chance = I2R(limit)/I2R(unitCount)
  19.         loop
  20.             set u = FirstOfGroup(tempGroup)
  21.             exitwhen u == null or limit == 0
  22.             call GroupRemoveUnit(tempGroup, u)
  23.             if GetRandomReal(0, 1) <= chance then
  24.                 call GroupAddUnit(g, u)
  25.                 set limit = limit - 1
  26.             endif
  27.         endloop
  28.         set u = null
  29.     endfunction
  30.  
  31.     function EnumRandomUnitsInRectCounted takes group g, rect r, integer limit returns nothing
  32.         local real chance
  33.         local unit u
  34.         call GroupEnumUnitsInRect(g, r, Filter(function EnumUnits))
  35.         set chance = I2R(limit)/I2R(unitCount)
  36.         loop
  37.             set u = FirstOfGroup(tempGroup)
  38.             exitwhen u == null or limit == 0
  39.             call GroupRemoveUnit(tempGroup, u)
  40.             if GetRandomReal(0, 1) <= chance then
  41.                 call GroupAddUnit(g, u)
  42.                 set limit = limit - 1
  43.             endif
  44.         endloop
  45.         set u = null
  46.     endfunction
  47.  
  48. endlibrary
9
Codes & Snippets / InvulnerabilityChecker
« Last post by AGD on September 04, 2016, 12:09:44 AM »
A simple snippet used to check if a unit is invulnerable. False positives from mana shields are also accounted for.

Code: jass  [Select]
  1. library InvulnerabilityChecker
  2.  
  3.     function CheckInvulnerability takes unit u returns boolean
  4.         local real origHP = GetWidgetLife(u)
  5.         local real origMP = GetUnitState(u, UNIT_STATE_MANA)
  6.         local boolean check
  7.         call UnitDamageTarget(u, u, 0.01, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
  8.         set check = GetWidgetLife(u) == origHP and GetUnitState(u, UNIT_STATE_LIFE) == origMP
  9.         call SetWidgetLife(u, origHP)
  10.         call SetUnitState(u, UNIT_STATE_MANA, origMP)
  11.         return check
  12.     endfunction
  13.  
  14. endlibrary
10
Codes & Snippets / TimerIndexer v1.2
« Last post by AGD on September 03, 2016, 10:49:40 PM »
Useful system especially in making an MUI spell which uses timers. Instead of saving the spell data in a hashtable with the handleid of the timer as the parent key, you can just use normal arrays with the timerid as the index. This also allows you to pass custom data (integer) to timers.

System Features:
  • Indexed timers (Array safe, 1-8190 but can also be customized to be 8190+) NEW
  • Timer custom data (integer) attachment [NEW]
  • Timer double free protection
  • Automatic timer replacement (Useful safety feature which automatically replaces timers belonging to this system with a timer of the same timerid and handleid when destroyed)
Timer Indexer v1.2
Code: jass  [Select]
  1. library TimerIndexer //v1.2
  2.  
  3.  
  4. //! novjass
  5.      ________________
  6.     |                |
  7.     | Written by AGD |
  8.     |________________|
  9.  
  10.  
  11.     |=====|
  12.     | API |
  13.     |=====|
  14.  
  15.         function GetTimer takes nothing returns timer/*
  16.         - Allocates a new usable timer from the stock
  17.  
  18.       */function GetTimerEx takes integer i returns timer/*
  19.         - Retrieves a new usable timer from the stock and initializes
  20.           its custom integer data to <i>
  21.  
  22.       */function GetTimerById takes integer i returns timer/*
  23.         - Retrieves a timer of ID <i> from the stock but returns
  24.           null if that timer is not free
  25.  
  26.       */function FreeTimer takes timer t returns nothing/*
  27.         - Releases the timer back to the stock
  28.  
  29.       */function GetTimerId takes timer t returns integer/*
  30.         - Returns the index of the timer
  31.  
  32.       */function GetTimerData takes timer t returns integer/*
  33.         - Returns the custom integer data attached to the timer
  34.  
  35.       */function SetTimerData takes timer t, integer i returns nothing/*
  36.         - Attaches a custom integer data to the timer
  37.  
  38.       */function IsTimerStocked takes timer t returns boolean/*
  39.         - Checks if the timer is free
  40.  
  41.       */function GetTimerFlag takes timer t returns boolean/*
  42.         - Checks if the timer is included in this system's timer stock
  43.  
  44. *///! endnovjass
  45.  
  46.     globals
  47. /*
  48.         Determines the total number of timers on the stock          */
  49.         private constant integer TIMER_STOCK_SIZE = 8190
  50.  
  51. /*      Determines the delay of timer replacement in case a
  52.         timer belonging to the stock is accidentally destroyed
  53.         Note that this value should be greater than the time
  54.         delay of the handleId recycling which is approximately
  55.         0.0050000 ( It's not advised to change this anyway )        */
  56.         private constant real REPLACE_DELAY = 0.0050001
  57.  
  58.     endglobals
  59.  
  60.     //================================================================
  61.  
  62.     globals
  63.         private timer array T[TIMER_STOCK_SIZE]
  64.         private timer tempTimer
  65.         private integer START_HANDLE
  66.         private integer destroyed
  67.         private integer current
  68.         private integer pitStop
  69.         private integer this
  70.         private integer array recycler[TIMER_STOCK_SIZE]
  71.         private integer array data[TIMER_STOCK_SIZE]
  72.         private boolean dont = false
  73.         private boolean array isTimerStocked[TIMER_STOCK_SIZE]
  74.     endglobals
  75.  
  76.     static if DEBUG_MODE then
  77.         private function Debug takes string msg returns nothing
  78.             call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "|CFFFFCC00[Timer Indexer]|R : " + msg)
  79.         endfunction
  80.     endif
  81.  
  82.     function GetTimerId takes timer t returns integer
  83.         return GetHandleId(t) - START_HANDLE
  84.     endfunction
  85.  
  86.     function GetTimerData takes timer t returns integer
  87.         return data[GetTimerId(t)]
  88.     endfunction
  89.  
  90.     function SetTimerData takes timer t, integer i returns nothing
  91.         set data[GetTimerId(t)] = i
  92.     endfunction
  93.  
  94.     function IsTimerStocked takes timer t returns boolean
  95.         return isTimerStocked[GetTimerId(t)]
  96.     endfunction
  97.  
  98.     function GetTimerFlag takes timer t returns boolean
  99.         return GetTimerId(t) > 0 and GetTimerId(t) <= TIMER_STOCK_SIZE
  100.     endfunction
  101.  
  102.     function GetTimer takes nothing returns timer
  103.         set this = recycler[0]
  104.         set recycler[0] = recycler[this]
  105.         if isTimerStocked[this] then
  106.             set isTimerStocked[this] = false
  107.             debug call Debug("Retrieving Timer [" + I2S(this) + "] from stock")
  108.             return T[this]
  109.         endif
  110.         debug call Debug("ERROR: No free timers available, creating a temporary timer.")
  111.         return CreateTimer()
  112.     endfunction
  113.  
  114.     function GetTimerById takes integer i returns timer
  115.         if isTimerStocked[i] then
  116.             debug call Debug("Retrieving Timer [" + I2S(i) + "] from stock")
  117.             return T[i]
  118.         endif
  119.         debug if i < 1 or i > TIMER_STOCK_SIZE then
  120.             debug call Debug("ERROR: Specified timer ID is out of bounds")
  121.         debug else
  122.             debug call Debug("ERROR: Timer [" + I2S(i) + "] is not free")
  123.         debug endif
  124.         return null
  125.     endfunction
  126.  
  127.     function GetTimerEx takes integer i returns timer
  128.         set tempTimer = GetTimer()
  129.         set data[GetTimerId(tempTimer)] = i
  130.         return tempTimer
  131.     endfunction
  132.  
  133.     function FreeTimer takes timer t returns nothing
  134.         local integer i = GetTimerId(t)
  135.         if not isTimerStocked[i] and GetTimerFlag(t) then
  136.             call TimerStart(t, 0, false, null)
  137.             set isTimerStocked[i] = true
  138.             set data[i] = 0
  139.             set recycler[i] = recycler[0]
  140.             set recycler[0] = i
  141.             debug call Debug("Releasing Timer [" + I2S(i) + "] back to the stock")
  142.         elseif not GetTimerFlag(t) then
  143.             call DestroyTimer(t)
  144.             debug call Debug("ERROR: Freed timer does not belong to the stack, destroying timer")
  145.         debug else
  146.             debug call Debug("ERROR: Attempt to double-free Timer [" + I2S(i) + "]")
  147.         endif
  148.     endfunction
  149.  
  150.     private function Replace takes nothing returns nothing
  151.         local integer i = destroyed
  152.         set T[i] = CreateTimer()
  153.         if GetTimerId(T[i]) == i then
  154.             set isTimerStocked[i] = true
  155.             debug call Debug("Timer [" + I2S(GetTimerId(T[i])) + "] was replaced")
  156.         else
  157.             debug call Debug("ERROR: Unable to replace Timer [" + I2S(i) + "]")
  158.             set dont = true
  159.             call DestroyTimer(T[i])
  160.             set dont = false
  161.             set T[i] = null
  162.         endif
  163.         call FreeTimer(GetExpiredTimer())
  164.     endfunction
  165.  
  166.     private function OnDestroy takes timer t returns nothing
  167.         local integer i = GetTimerId(t)
  168.         local trigger trig
  169.         if not dont and GetTimerFlag(t) then
  170.             set T[i] = null
  171.             set isTimerStocked[i] = false
  172.             set destroyed = i
  173.             call DestroyTimer(null)
  174.             call TimerStart(GetTimer(), REPLACE_DELAY, false, function Replace)
  175.             debug call Debug("WARNING: Timer [" + I2S(i) + "] got destroyed!")
  176.             set trig = null
  177.         endif
  178.     endfunction
  179.  
  180.     hook DestroyTimer OnDestroy
  181.  
  182.     private function Delegate takes nothing returns nothing
  183.         local integer i = current
  184.         loop
  185.             set i = i + 1
  186.             set T[i] = CreateTimer()
  187.             set isTimerStocked[i] = true
  188.             set recycler[i] = i + 1
  189.             if i == TIMER_STOCK_SIZE then
  190.                 debug call Debug("Total number of timers created: " + I2S(i))
  191.                 debug call Debug("Timer stock count is complete")
  192.                 return
  193.             endif
  194.             exitwhen i == current + pitStop
  195.         endloop
  196.         set current = i
  197.         call Delegate.evaluate()
  198.     endfunction
  199.  
  200.     private module M
  201.         private static method onInit takes nothing returns nothing
  202.             local integer i = 1
  203.             if TIMER_STOCK_SIZE <= 8190 then
  204.                 set pitStop = TIMER_STOCK_SIZE
  205.             else
  206.                 set pitStop = 1000
  207.             endif
  208.             set recycler[TIMER_STOCK_SIZE] = 0
  209.             set recycler[0] = 1
  210.             set recycler[1] = 2
  211.             set T[i] = CreateTimer()
  212.             set START_HANDLE = GetHandleId(T[i]) - 1
  213.             set isTimerStocked[i] = true
  214.             loop
  215.                 set i = i + 1
  216.                 set T[i] = CreateTimer()
  217.                 set isTimerStocked[i] = true
  218.                 set recycler[i] = i + 1
  219.                 exitwhen i == pitStop
  220.             endloop
  221.             set current = i
  222.             if TIMER_STOCK_SIZE > current then
  223.                 call Delegate.evaluate()
  224.             debug else
  225.                 debug call Debug("Total number of timers created: " + I2S(i))
  226.                 debug call Debug("Timer stock count is complete")
  227.             endif
  228.         endmethod
  229.     endmodule
  230.  
  231.     private struct S extends array
  232.         implement M
  233.     endstruct
  234.  
  235. endlibrary


Changelogs
v1.2
- Added more functionalities such as attaching custom timer data, now the system comprises all but is not limited to the main functionalities of Vexorian's TimerUtils
- Optimized the code especially in the part in updating the timer stack
- Fixed some bugs

v1.1
- Added the possibility for users to configure the timer stock size above 8190
- Some fixes

v1.0
- First Release
Pages: [1] 2 3 ... 10
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!!