• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Respawn System - v1.0b

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Like
Reactions: FRENGERS and KnnO

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:
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
  • 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

JASS:
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

- Improved creep counting as per KnnO's suggestion.
- Added map name, description and author for demo map.

- 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
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...

Moderator

M

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 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)
 
Level 11
Joined
Aug 11, 2009
Messages
605
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
 
Level 8
Joined
Sep 18, 2011
Messages
195
This function moves group units to <enum> then moves them back to <g> function EnumerateGroup which is nonsense, you can use:
JASS:
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
 
Level 10
Joined
Sep 21, 2007
Messages
517
@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
JASS:
key
and make it constant; this is rather than using stringhash.

Hope i helped, peace
 
JASS:
/*          ======================
            Respawn System - v1.1
            ======================
            
        Coded by:       Mr_Bean ([email protected])
        
    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][email protected][/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.
 
Level 8
Joined
Dec 30, 2011
Messages
134
JASS:
    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!

JASS:
    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:

JASS:
    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:
Level 4
Joined
Jun 6, 2015
Messages
82
Line 1074: Expected end of line

//TESH.alwaysfold=0 <---- This line is covered in blue when I try to save my map after copying your trigger. It worked some days ago. But then suddenly this happens everytime I save.

Edit: I am using Sharpcraft, as I also did when I first implemented your system. It just suddenly stopped working even without making any difference from the time it worked. I am green on this one.
 
Top