1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Seek unity between the elements in the 22nd Terraining Contest Poll.
    Dismiss Notice
  3. Seize the moment! The 18th Mini Mapping Contest has commenced.
    Dismiss Notice
  4. Gather 'round - the 20th Icon Contest Poll is out.
    Dismiss Notice
  5. The heavens smile on the old faithful. The 16th Techtree Contest has begun.
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Respawn System - v1.0b

Submitted by Mr_Bean
This bundle is marked as substandard. It may contain bugs, not perform optimally or otherwise be in violation of the submission rules.

Respawn System - v1.0b


By Mr_Bean​


Introduction


This system was originally requested by Peacehagen for his map Rise of the Corruptor ORPG.
He recommended that I upload it because it would help people, which I hope it does!
I added some new features to it and made it as user-friendly as possible.

Features


- Respawn all dead creeps every X seconds, or individual creeps X seconds after they die.
- Specify which players to respawn creeps for.
- Functions which allow the following:

  • Respawn all dead creeps immediately.
  • Respawn all dead creeps owned by a specific player immediately.
  • Pause and resume the system.
  • Reset and restart the system.
  • Count how many creeps there are in total, alive and dead.
- Can create an effect on respawning units.
- Can choose to respawn heroes or not.
- Written in vJASS, can be used in GUI.

Requirements


- JASS NewGen Pack [LINK]
- Latest JASSHelper [LINK]
- TimerUtils by Vexorian (included in demo map)

Available Functions


JASS Version
Code (vJASS):
function RespawnAllCreeps takes nothing returns nothing
function RespawnAllCreepsForPlayer takes player whichPlayer returns nothing
function PauseRespawnSystem takes integer howLong returns nothing
function ResumeRespawnSystem takes nothing returns nothing
function ResetRespawnSystem takes nothing returns nothing
function RestartRespawnSystem takes nothing returns nothing
function GetAliveCreeps takes nothing returns integer
function GetDeadCreeps takes nothing returns integer
function GetTotalCreeps takes nothing returns integer

GUI Version
  • Custom script: call RespawnAllCreeps()
  • Custom script: call RespawnAllCreepsForPlayer(player whichPlayer)
  • Custom script: call PauseRespawnSystem(integer howLong)
  • Custom script: call ResumeRespawnSystem()
  • Custom script: call ResetRespawnSystem()
  • Custom script: call RestartRespawnSystem()
  • Custom script: call GetAliveCreeps()
  • Custom script: call GetDeadCreeps()
  • Custom script: call GetTotalCreeps()

Code


vJASS Code
Code (vJASS):
library RespawnSystem initializer OnInit requires TimerUtils

    //**************************************************\\
    //*** START OF CONFIGURABLES                     ***\\
    //**************************************************\\
   
    globals
   
        // Delay between unit dying and respawning:
        private constant real    RESPAWN_DELAY      = 30.0
        // Respawn all dead units at once? If set to false, units will respawn individually.
        private constant boolean RESPAWN_TOGETHER   = true
        // Show a countdown window to all players:
        private constant boolean SHOW_TIMER_WINDOW  = false
        // Countdown window text (only applicable if SHOW_TIMER_WINDOW = true):
        private constant string  TIMER_WINDOW_TEXT  = "Creeps respawn in:"
        // Respawn heroes:
        private constant boolean RESPAWN_HEROES     = false
        // Effect created on respawning units (set to "" to have no effect):
        private constant string  RESPAWN_EFFECT     = "Abilities\\Spells\\Undead\\RaiseSkeletonWarrior\\RaiseSkeleton.mdl"
        // Attachment point of effect on unit:
        private constant string  EFFECT_ATTACHMENT  = "origin"
       
    endglobals
   
    private function CheckOwner takes nothing returns boolean
        local integer playerId = GetPlayerId(GetOwningPlayer(GetFilterUnit()))
        if /*
       
        //------------------------------------------------------\\
        // Add the players that the system respawns creeps for: \\
        // Remember to subtract 1 from GUI player indexes!      \\
        */
 playerId == 10 or /*    // Player 11 in GUI.        \*
        */
 playerId == 11 or /*    // Player 12 in GUI.        \*
        */
 playerId == 12    /*    // Neutral Hostile in GUI.  \*
        //------------------------------------------------------\\
       
        */
then
            return true
        endif
        return false
    endfunction
   
    //**************************************************\\
    //*** END OF CONFIGURABLES                       ***\\
    //**************************************************\\
   
    globals
        private group       deadCreeps      = CreateGroup()
        private group       creeps          = CreateGroup()
        private group       enumG           = CreateGroup()
        private hashtable   ht              = InitHashtable()
        private timer       respawnTimer
        private timerdialog timerWindow
        private integer     tempInt         = 0
    endglobals
   
    private function Increment takes nothing returns nothing
        set tempInt = tempInt + 1
    endfunction
   
    private function EnumerateGroup takes group g returns integer
        set tempInt = 0
        call ForGroup(g, function Increment)
        return tempInt
    endfunction
   
    //**************************************************\\
    //*** GetTotalCreeps                             ***\\
    //**************************************************\\
   
    function GetTotalCreeps takes nothing returns integer
        return EnumerateGroup(creeps) + EnumerateGroup(deadCreeps)
    endfunction
   
    //**************************************************\\
    //*** GetAliveCreeps                             ***\\
    //**************************************************\\
   
    function GetDeadCreeps takes nothing returns integer
        return EnumerateGroup(deadCreeps)
    endfunction
   
    //**************************************************\\
    //*** GetDeadCreeps                              ***\\
    //**************************************************\\
   
    function GetAliveCreeps takes nothing returns integer
        return EnumerateGroup(creeps)
    endfunction
   
    //**************************************************\\
   
    private function RespawnCreepX takes integer handleId returns nothing
        local real x = LoadReal(ht, handleId, StringHash("x"))
        local real y = LoadReal(ht, handleId, StringHash("y"))
        local real angle = LoadReal(ht, handleId, StringHash("facing"))
        local integer owner = LoadInteger(ht, handleId, StringHash("owner"))
        local integer unitType = LoadInteger(ht, handleId, StringHash("type"))
        local unit creep
       
        set creep = CreateUnit(Player(owner), unitType, x, y, angle)
        call FlushChildHashtable(ht, handleId)
        call DestroyEffect(AddSpecialEffectTarget(RESPAWN_EFFECT, creep, EFFECT_ATTACHMENT))
        set handleId = GetHandleId(creep)
        call SaveReal(ht, handleId, StringHash("x"), GetUnitX(creep))
        call SaveReal(ht, handleId, StringHash("y"), GetUnitY(creep))
        call SaveReal(ht, handleId, StringHash("facing"), GetUnitFacing(creep))
        call SaveInteger(ht, handleId, StringHash("owner"), GetPlayerId(GetOwningPlayer(creep)))
        call SaveInteger(ht, handleId, StringHash("type"), GetUnitTypeId(creep))
       
        call GroupRemoveUnit(deadCreeps, creep)
        call GroupAddUnit(creeps, creep)
       
        set creep = null
    endfunction
   
    //**************************************************\\
    //*** ResumeRespawnSystem                        ***\\
    //**************************************************\\
   
    function ResumeRespawnSystem takes nothing returns nothing
        static if RESPAWN_TOGETHER then
            call ResumeTimer(respawnTimer)
        else
            call BJDebugMsg("|cffff0000Respawn System|r: Cannot use ResumeRespawnSystem when RESPAWN_TOGETHER = false.")
        endif
    endfunction
   
    //**************************************************\\
    //*** PauseRespawnSystem                         ***\\
    //**************************************************\\
   
    function PauseRespawnSystem takes real duration returns nothing
        static if RESPAWN_TOGETHER then
            if duration < 0 then
                call PauseTimer(respawnTimer)
            elseif duration > 0 then
                call PauseTimer(respawnTimer)
                call TimerStart(NewTimer(), duration, false, function ResumeRespawnSystem)
            endif
        else
            call BJDebugMsg("|cffff0000Respawn System|r: Cannot use PauseRespawnSystem when RESPAWN_TOGETHER = false.")
        endif
       
    endfunction
   
    //**************************************************\\
    //*** RespawnAllCreepsForPlayer                  ***\\
    //**************************************************\\
   
    function RespawnAllCreepsForPlayer takes player whichPlayer returns nothing
        local unit temp
       
        set enumG = deadCreeps
       
        loop
            set temp = FirstOfGroup(enumG)
            exitwhen temp == null
           
            if GetOwningPlayer(temp) == whichPlayer then
                call RespawnCreepX(GetHandleId(temp))
            endif
       
            call GroupRemoveUnit(enumG, temp)
       
        endloop
       
    endfunction
   
    private function GroupEnumeration takes nothing returns nothing
        call RespawnCreepX(GetHandleId(GetEnumUnit()))
    endfunction
   
    //**************************************************\\
    //*** RespawnAllCreeps                           ***\\
    //**************************************************\\
   
    function RespawnAllCreeps takes nothing returns nothing
        call ForGroup(deadCreeps, function GroupEnumeration)
    endfunction
   
    //**************************************************\\
    //*** ResetRespawnSystem                         ***\\
    //**************************************************\\
   
    function ResetRespawnSystem takes nothing returns nothing
   
        static if RESPAWN_TOGETHER then
            call TimerStart(respawnTimer, RESPAWN_DELAY, true, function RespawnAllCreeps)
            call PauseTimer(respawnTimer)
        else
            call BJDebugMsg("|cffff0000Respawn System|r: Cannot use ResetRespawnSystem when RESPAWN_TOGETHER = false.")
        endif
       
    endfunction
   
    //**************************************************\\
    //*** RestartRespawnSystem                       ***\\
    //**************************************************\\
   
    function RestartRespawnSystem takes nothing returns nothing
        static if RESPAWN_TOGETHER then
            call TimerStart(respawnTimer, RESPAWN_DELAY, true, function RespawnAllCreeps)
        else
            call BJDebugMsg("|cffff0000Respawn System|r: Cannot use RestartRespawnSystem when RESPAWN_TOGETHER = false.")
        endif
    endfunction

    //**************************************************\\
   
    private function TimerExpiration takes nothing returns nothing
        call RespawnCreepX(GetTimerData(GetExpiredTimer()))
        call ReleaseTimer(GetExpiredTimer())
    endfunction
   
    private function CreepDeath takes nothing returns boolean
        local unit u = GetTriggerUnit()
       
        if IsUnitInGroup(u, creeps) then
            call GroupRemoveUnit(creeps, u)
            call GroupAddUnit(deadCreeps, u)
           
            static if not RESPAWN_TOGETHER then
                call TimerStart(NewTimerEx(GetHandleId(u)), RESPAWN_DELAY, false, function TimerExpiration)
            endif
        endif
       
        set u = null
        return false
    endfunction
   
    private function GroupCreeps takes nothing returns nothing
        local unit temp
        local integer handleId
       
        call GroupEnumUnitsInRect(enumG, bj_mapInitialPlayableArea, Condition(function CheckOwner))
       
        loop
            set temp = FirstOfGroup(enumG)
            exitwhen temp == null
           
            if not IsUnitType(temp, UNIT_TYPE_DEAD) then
                set handleId = GetHandleId(temp)
                call SaveReal(ht, handleId, StringHash("x"), GetUnitX(temp))
                call SaveReal(ht, handleId, StringHash("y"), GetUnitY(temp))
                call SaveReal(ht, handleId, StringHash("facing"), GetUnitFacing(temp))
                call SaveInteger(ht, handleId, StringHash("owner"), GetPlayerId(GetOwningPlayer(temp)))
                call SaveInteger(ht, handleId, StringHash("type"), GetUnitTypeId(temp))
                call GroupAddUnit(creeps, temp)
            endif
           
            call GroupRemoveUnit(enumG, temp)
           
        endloop
       
    endfunction
   
    private function CreateDialog takes nothing returns nothing
        set timerWindow = CreateTimerDialog(respawnTimer)
        call TimerDialogSetTitle(timerWindow, TIMER_WINDOW_TEXT)
        call TimerDialogDisplay(timerWindow, true)
    endfunction
   
    private function OnInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerAddCondition(t, Condition(function CreepDeath))
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
        set t = null
       
        call GroupCreeps()
       
        static if RESPAWN_TOGETHER then
       
            set respawnTimer = CreateTimer()
            call TimerStart(respawnTimer, RESPAWN_DELAY, true, function RespawnAllCreeps)
           
            static if SHOW_TIMER_WINDOW then
                call TimerStart(NewTimer(), 0.01, false, function CreateDialog)
            endif
           
        endif
       
    endfunction
   
endlibrary

Changelogs


v1.0b (33 June 2012)
- Improved creep counting as per KnnO's suggestion.
- Added map name, description and author for demo map.

v1.0 (22 June 2012)
- Initial release.

Credits


- Peacehagen for requesting the system and encouraging me to upload it.
- Vexorian for TimerUtils.

Contact


If you find any bugs in the system or if something is unclear in the documentation, please let me know!
- Email
- Private Message

Keywords:
respawn, system, respawn system, creep, mr_bean, peacehagen
Contents

Respawn System (Map)

Reviews
Moderator
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. 12:09, 17th Jul 2012 Magtheridon96: Instead of using the ForGroup function to figure out the number of units, you can keep track of the number of units dead and alive by yourself using...
  1. 12th Dec 2015
    IcemanBo: Too long as NeedsFix. Rejected.

    12:09, 17th Jul 2012
    Magtheridon96:

    Comments
    • Instead of using the ForGroup function to figure out the number of units, you can keep track of the number of units dead and alive by yourself using a couple of integers.
    • ResumeTimer -> TimerStart because it's faster :p
    • Instead of using those StringHash functions, you can use constant integers, or as the others suggested, keys.
    • CheckOwner can be shortened to 2 lines. You just need to return the conditions of the if statement. (
      return playerId == 10 or playerId == 11 or playerId == 12
      )
     
  2. Almia

    Almia

    Joined:
    Apr 24, 2012
    Messages:
    4,842
    Resources:
    35
    Spells:
    30
    Tutorials:
    4
    JASS:
    1
    Resources:
    35
    can you post the triggers sir?
     
  3. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Done. Code uploaded.
     
  4. Almia

    Almia

    Joined:
    Apr 24, 2012
    Messages:
    4,842
    Resources:
    35
    Spells:
    30
    Tutorials:
    4
    JASS:
    1
    Resources:
    35
    i thought you put the gui version :D
     
  5. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    It's written in vJASS, but you can obviously use GUI actions (custom scripts).
     
  6. Almia

    Almia

    Joined:
    Apr 24, 2012
    Messages:
    4,842
    Resources:
    35
    Spells:
    30
    Tutorials:
    4
    JASS:
    1
    Resources:
    35
    ohh okay ill test it tomorrow
     
  7. Peacehagen

    Peacehagen

    Joined:
    Aug 11, 2009
    Messages:
    507
    Resources:
    0
    Resources:
    0
    I recommend this system, very easy to use (and i have 0 jass knowledge) and works perfectly. All other i have tried have had an issue that some units did not respawn but this solved it :)

    5/5
     
  8. KnnO

    KnnO

    Joined:
    Sep 18, 2011
    Messages:
    156
    Resources:
    3
    Icons:
    1
    Maps:
    1
    Spells:
    1
    Resources:
    3
    This function moves group units to <enum> then moves them back to <g>
    function EnumerateGroup
    which is nonsense, you can use:
    Code (vJASS):

    private function Inc takes nothing returns nothing
          set /*a temp private global integer*/ count = count + 1
    endfunction

    function EnumerateGroup takes group g returns integer
          call ForGroup(g,function Inc)
          retun count
    endfunction
     

    But I am not sure If you are using it that way because it is faster or something...are you? or because you don't want an extra function and an extra variable? IDK

    Everything else is fine I guess
     
  9. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Update:
    Uploaded version 1.0b:
    - Fixed creep counting as per KnnO's suggestion.
    - Added map name, description and author for the demp map.

    @KnnO: Thanks man! I guess I'm just too used to using FirstOfGroup loops in spells. Much appreciated.
     
  10. KnnO

    KnnO

    Joined:
    Sep 18, 2011
    Messages:
    156
    Resources:
    3
    Icons:
    1
    Maps:
    1
    Spells:
    1
    Resources:
    3
    Well I saw your user title so I think you are better than me with coding :p

    No problem Mr_Bean987, I am glad I could help!
     
  11. Diehard@Azeroth

    Diehard@Azeroth

    Joined:
    Sep 21, 2007
    Messages:
    483
    Resources:
    1
    Spells:
    1
    Resources:
    1
    @Mr_Bean987, First of all nice API you got there :) Alright lets get down to business. Instead of using hashtables, i suggest you use a struct and store the handle id of the unit on its respective timer when it dies. If you still insist on using hashtables, then i suggest you use the variable type
    Code (vJASS):
    key
    and make it constant; this is rather than using stringhash.

    Hope i helped, peace
     
  12. -Kobas-

    -Kobas-

    Joined:
    Jan 17, 2010
    Messages:
    5,892
    Resources:
    28
    Icons:
    1
    Tools:
    2
    Maps:
    10
    Spells:
    4
    Template:
    5
    Tutorials:
    6
    Resources:
    28
    Yeah key will generate random unique number and using is as constant will increase "security" even more.

    StringHash is something we do in GUI, use integers in jass, it's faster.
     
  13. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Can you please give me an example of how I should use
    key
    ...

    If I were to use structs, would I create a new instance for each creep? Is this more efficient than hashtables?
     
  14. -Kobas-

    -Kobas-

    Joined:
    Jan 17, 2010
    Messages:
    5,892
    Resources:
    28
    Icons:
    1
    Tools:
    2
    Maps:
    10
    Spells:
    4
    Template:
    5
    Tutorials:
    6
    Resources:
    28
    Code (vJASS):
    /*          ======================
                Respawn System - v1.1
                ======================
               
            Coded by:       Mr_Bean (mrbean987789@gmail.com)
           
        Introduction:
        -------------
    This system was originally requested by Peacehagen for his map Rise of the Corruptor ORPG.
    He recommended that I upload it because it would help people, which I hope it does!
    I added some new features to the system and made it as user-friendly as possible.
    This system only works for units that are on the map as soon as the game starts.
    Feel free to contact me if something is not clear, or if you find bugs.

        Installation:
        -------------
    > Copy this trigger.
    > Copy the "TimerUtils" trigger (if you don't have it already).
    > Configure the "Configurables" section in this trigger as desired.

        Available Functions:
        --------------------
    > RespawnAllCreeps()
        - Immediately respawns all dead creeps.
        - Does not affect countdown timer.

    > RespawnAllCreepsForPlayer(player whichPlayer)
        - Immediately respawns all dead creeps for a specified player.
        - Does not affect countdown timer.

    > PauseRespawnSystem(real howLong)
        - If all creeps respawn together, you can use this to pause the system.
        - The parameter is how long it is paused for. Use any negative number to pause it forever (until you resume again). Using 0 means no pause.
        - Can only use if RESPAWN_TOGETHER = true.

    > ResumeRespawnSystem()
        - This will resume the system.
        - Only works if you used PauseRespawnSystem with a negative number (like PauseRespawnSystem(-1)).
        - Can only use if RESPAWN_TOGETHER = true.
       
    > ResetRespawnSystem()
        - This will pause the system and reset the countdown.
        - Needs to be unpaused with ResumeRespawnSystem().
        - Can only use if RESPAWN_TOGETHER = true.
       
    > RestartRespawnSystem()
        - This will reset the respawn countdown.
        - Will not pause the system.
        - Can only use if RESPAWN_TOGETHER = true.

    > GetAliveCreeps()
        - Returns how many creeps are alive.
       
    > GetDeadCreeps()
        - Returns how many creeps are dead.
       
    > GetTotalCreeps()
        - Returns how many creeps there are in total.
       
        Contact:
        --------
    > [email]mrbean987789@gmail.com[/email]
    > Mr_Bean987 on the HiveWorkshop.com

    */

    library RespawnSystem initializer OnInit requires TimerUtils

        //**************************************************\\
        //*** START OF CONFIGURABLES                     ***\\
        //**************************************************\\
       
        globals
       
            /* hashtable keys */
            private constant key key_x
            private constant key key_y
            private constant key key_facing
            private constant key key_owner
            private constant key key_type
            /* end hashtable keys */

            // Delay between unit dying and respawning:
            private constant real    RESPAWN_DELAY      = 30.0
            // Respawn all dead units at once? If set to false, units will respawn individually.
            private constant boolean RESPAWN_TOGETHER   = false
            // Show a countdown window to all players:
            private constant boolean SHOW_TIMER_WINDOW  = false
            // Countdown window text (only applicable if SHOW_TIMER_WINDOW = true):
            private constant string  TIMER_WINDOW_TEXT  = "Creeps respawn in:"
            // Respawn heroes:
            private constant boolean RESPAWN_HEROES     = false
            // Effect created on respawning units (set to "" to have no effect):
            private constant string  RESPAWN_EFFECT     = "Abilities\\Spells\\Undead\\RaiseSkeletonWarrior\\RaiseSkeleton.mdl"
            // Attachment point of effect on unit:
            private constant string  EFFECT_ATTACHMENT  = "origin"
           
        endglobals
       
        private function CheckOwner takes nothing returns boolean
            local integer playerId = GetPlayerId(GetOwningPlayer(GetFilterUnit()))
            if /*
           
            //------------------------------------------------------\\
            // Add the players that the system respawns creeps for: \\
            // Remember to subtract 1 from GUI player indexes!      \\
            */
     playerId == 10 or /*    // Player 11 in GUI.        \*
            */
     playerId == 11 or /*    // Player 12 in GUI.        \*
            */
     playerId == 12    /*    // Neutral Hostile in GUI.  \*
            //------------------------------------------------------\\
           
            */
    then
                return true
            endif
            return false
        endfunction
       
        //**************************************************\\
        //*** END OF CONFIGURABLES                       ***\\
        //**************************************************\\
       
        globals
            private group       deadCreeps      = CreateGroup()
            private group       creeps          = CreateGroup()
            private group       enumG           = CreateGroup()
            private hashtable   ht              = InitHashtable()
            private timer       respawnTimer
            private timerdialog timerWindow
            private integer     tempInt         = 0
        endglobals
       
        private function Increment takes nothing returns nothing
            set tempInt = tempInt + 1
        endfunction
       
        private function EnumerateGroup takes group g returns integer
            set tempInt = 0
            call ForGroup(g, function Increment)
            return tempInt
        endfunction
       
        //**************************************************\\
        //*** GetTotalCreeps                             ***\\
        //**************************************************\\
       
        function GetTotalCreeps takes nothing returns integer
            return EnumerateGroup(creeps) + EnumerateGroup(deadCreeps)
        endfunction
       
        //**************************************************\\
        //*** GetAliveCreeps                             ***\\
        //**************************************************\\
       
        function GetDeadCreeps takes nothing returns integer
            return EnumerateGroup(deadCreeps)
        endfunction
       
        //**************************************************\\
        //*** GetDeadCreeps                              ***\\
        //**************************************************\\
       
        function GetAliveCreeps takes nothing returns integer
            return EnumerateGroup(creeps)
        endfunction
       
        //**************************************************\\
       
        private function RespawnCreepX takes integer handleId returns nothing
            local real    x        = LoadReal(   ht, handleId, key_x)
            local real    y        = LoadReal(   ht, handleId, key_y)
            local real    angle    = LoadReal(   ht, handleId, key_facing)
            local integer owner    = LoadInteger(ht, handleId, key_owner)
            local integer unitType = LoadInteger(ht, handleId, key_type)
            local unit    creep
           
            set creep = CreateUnit(Player(owner), unitType, x, y, angle)
            call FlushChildHashtable(ht, handleId)
            call DestroyEffect(AddSpecialEffectTarget(RESPAWN_EFFECT, creep, EFFECT_ATTACHMENT))
            set handleId = GetHandleId(creep)
            call SaveReal(   ht, handleId, key_x, GetUnitX(creep))
            call SaveReal(   ht, handleId, key_y, GetUnitY(creep))
            call SaveReal(   ht, handleId, key_facing, GetUnitFacing(creep))
            call SaveInteger(ht, handleId, key_owner, GetPlayerId(GetOwningPlayer(creep)))
            call SaveInteger(ht, handleId, key_type, GetUnitTypeId(creep))
           
            call GroupRemoveUnit(deadCreeps, creep)
            call GroupAddUnit(creeps, creep)
           
            set creep = null
        endfunction
       
        //**************************************************\\
        //*** ResumeRespawnSystem                        ***\\
        //**************************************************\\
       
        function ResumeRespawnSystem takes nothing returns nothing
            static if RESPAWN_TOGETHER then
                call ResumeTimer(respawnTimer)
            else
                call BJDebugMsg("|cffff0000Respawn System|r: Cannot use ResumeRespawnSystem when RESPAWN_TOGETHER = false.")
            endif
        endfunction
       
        //**************************************************\\
        //*** PauseRespawnSystem                         ***\\
        //**************************************************\\
       
        function PauseRespawnSystem takes real duration returns nothing
            static if RESPAWN_TOGETHER then
                if duration < 0 then
                    call PauseTimer(respawnTimer)
                elseif duration > 0 then
                    call PauseTimer(respawnTimer)
                    call TimerStart(NewTimer(), duration, false, function ResumeRespawnSystem)
                endif
            else
                call BJDebugMsg("|cffff0000Respawn System|r: Cannot use PauseRespawnSystem when RESPAWN_TOGETHER = false.")
            endif
           
        endfunction
       
        //**************************************************\\
        //*** RespawnAllCreepsForPlayer                  ***\\
        //**************************************************\\
       
        function RespawnAllCreepsForPlayer takes player whichPlayer returns nothing
            local unit temp
           
            set enumG = deadCreeps
           
            loop
                set temp = FirstOfGroup(enumG)
                exitwhen temp == null
               
                if GetOwningPlayer(temp) == whichPlayer then
                    call RespawnCreepX(GetHandleId(temp))
                endif
           
                call GroupRemoveUnit(enumG, temp)
           
            endloop
           
        endfunction
       
        private function GroupEnumeration takes nothing returns nothing
            call RespawnCreepX(GetHandleId(GetEnumUnit()))
        endfunction
       
        //**************************************************\\
        //*** RespawnAllCreeps                           ***\\
        //**************************************************\\
       
        function RespawnAllCreeps takes nothing returns nothing
            call ForGroup(deadCreeps, function GroupEnumeration)
        endfunction
       
        //**************************************************\\
        //*** ResetRespawnSystem                         ***\\
        //**************************************************\\
       
        function ResetRespawnSystem takes nothing returns nothing
       
            static if RESPAWN_TOGETHER then
                call TimerStart(respawnTimer, RESPAWN_DELAY, true, function RespawnAllCreeps)
                call PauseTimer(respawnTimer)
            else
                call BJDebugMsg("|cffff0000Respawn System|r: Cannot use ResetRespawnSystem when RESPAWN_TOGETHER = false.")
            endif
           
        endfunction
       
        //**************************************************\\
        //*** RestartRespawnSystem                       ***\\
        //**************************************************\\
       
        function RestartRespawnSystem takes nothing returns nothing
            static if RESPAWN_TOGETHER then
                call TimerStart(respawnTimer, RESPAWN_DELAY, true, function RespawnAllCreeps)
            else
                call BJDebugMsg("|cffff0000Respawn System|r: Cannot use RestartRespawnSystem when RESPAWN_TOGETHER = false.")
            endif
        endfunction

        //**************************************************\\
       
        private function TimerExpiration takes nothing returns nothing
            call RespawnCreepX(GetTimerData(GetExpiredTimer()))
            call ReleaseTimer(GetExpiredTimer())
        endfunction
       
        private function CreepDeath takes nothing returns boolean
            local unit u = GetTriggerUnit()
           
            if IsUnitInGroup(u, creeps) then
                call GroupRemoveUnit(creeps, u)
                call GroupAddUnit(deadCreeps, u)
               
                static if not RESPAWN_TOGETHER then
                    call TimerStart(NewTimerEx(GetHandleId(u)), RESPAWN_DELAY, false, function TimerExpiration)
                endif
            endif
           
            set u = null
            return false
        endfunction
       
        private function GroupCreeps takes nothing returns nothing
            local unit temp
            local integer handleId
           
            call GroupEnumUnitsInRect(enumG, bj_mapInitialPlayableArea, Condition(function CheckOwner))
           
            loop
                set temp = FirstOfGroup(enumG)
                exitwhen temp == null
               
                if not IsUnitType(temp, UNIT_TYPE_DEAD) then
                    set handleId = GetHandleId(temp)
                    call SaveReal(   ht, handleId, key_x, GetUnitX(temp))
                    call SaveReal(   ht, handleId, key_y, GetUnitY(temp))
                    call SaveReal(   ht, handleId, key_facing, GetUnitFacing(temp))
                    call SaveInteger(ht, handleId, key_owner, GetPlayerId(GetOwningPlayer(temp)))
                    call SaveInteger(ht, handleId, key_type, GetUnitTypeId(temp))
                    call GroupAddUnit(creeps, temp)
                endif
               
                call GroupRemoveUnit(enumG, temp)
               
            endloop
           
        endfunction
       
        private function CreateDialog takes nothing returns nothing
            set timerWindow = CreateTimerDialog(respawnTimer)
            call TimerDialogSetTitle(timerWindow, TIMER_WINDOW_TEXT)
            call TimerDialogDisplay(timerWindow, true)
        endfunction
       
        private function OnInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerAddCondition(t, Condition(function CreepDeath))
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
            set t = null
           
            call GroupCreeps()
           
            static if RESPAWN_TOGETHER then
           
                set respawnTimer = CreateTimer()
                call TimerStart(respawnTimer, RESPAWN_DELAY, true, function RespawnAllCreeps)
               
                static if SHOW_TIMER_WINDOW then
                    call TimerStart(NewTimer(), 0.01, false, function CreateDialog)
                endif
               
            endif
           
        endfunction
       
    endlibrary


    There is no need for struct, btw, I must suggest that you make timer library optional, so you can use this system even without it.
    I say this because I myself code in that way to minimize number of external libraries I use.

    For example Table library is really awesome but using it in your map only because of 1 spell is ridiculous, where it can be replaced with indexing or single hash, but when you speak about 10 spells 1 table will certainly become more powerful than 10 hashtables.
     
  15. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    But then how can I respawn a specific creep when it dies without attaching its handle id to a timer?
     
  16. -Kobas-

    -Kobas-

    Joined:
    Jan 17, 2010
    Messages:
    5,892
    Resources:
    28
    Icons:
    1
    Tools:
    2
    Maps:
    10
    Spells:
    4
    Template:
    5
    Tutorials:
    6
    Resources:
    28
    Then you create timers yourself :)
     
  17. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    But how do I attach data to a timer? Sorry, I've gotten so used to TimerUtils ;)
     
  18. -Kobas-

    -Kobas-

    Joined:
    Jan 17, 2010
    Messages:
    5,892
    Resources:
    28
    Icons:
    1
    Tools:
    2
    Maps:
    10
    Spells:
    4
    Template:
    5
    Tutorials:
    6
    Resources:
    28
    You don't all you need is timer handle :)
    then when it expires you detect it again.
    local integer id = GetHandleId(GetExpiredTimer())
     
  19. KhaosMachine

    KhaosMachine

    Joined:
    Dec 30, 2011
    Messages:
    117
    Resources:
    6
    Spells:
    6
    Resources:
    6
    Older
    Original
    Code (vJASS):
        private function Increment takes nothing returns nothing
            set tempInt = tempInt + 1
        endfunction
       
        private function EnumerateGroup takes group g returns integer
            set tempInt = 0
            call ForGroup(g, function Increment)
            return tempInt
        endfunction


    Loop is more efficient than call a function for every unit!

    Optimized
    Code (vJASS):
        private function EnumerateGroup takes group g returns integer
            local unit picked
            set tempInt = 0
            loop
                set picked = FirstOfGroup(g)
                exitwhen picked == null
                call GroupRemoveUnit(g, picked)
                set tempInt = tempInt + 1
            endloop
            return tempInt
        endfunction


    Ohh! lol :p then:

    Code (vJASS):

        globals
            private group TempGroup = CreateGroup()
        endglobals

        private function EnumerateGroup takes group g returns integer
            local unit picked
            set TempGroup = g
            set tempInt = 0
            loop
                set picked = FirstOfGroup(TempGroup)
                exitwhen picked == null
                call GroupRemoveUnit(TempGroup, picked)
                set tempInt = tempInt + 1
            endloop
            return tempInt
        endfunction
     
    Last edited: Jul 18, 2012