[Lua] Tips on my Lua code? Respawning creeps with timer

Level 8
Joined
Sep 16, 2016
Messages
227
Hello,

Want to respawn my "creeps" when it dies after 3 seconds and unsure about the best approach. I have the TimerQueue lib, and this is how I do it currently (is it leaking because I don't destroy the timer?)

Lua:
if Debug and Debug.beginFile then Debug.beginFile("Main") end

OnInit.final("Main", function()
    function RaccoonRespawnInit()
        trig = CreateTrigger()
        TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_DEATH)
        TriggerAddAction(trig, function ()
            u = GetDyingUnit()
            uid = GetUnitTypeId(u)
            if uid == FourCC('m000') then
                TimerQueue:callDelayed(3, function ()
                    CreateUnit(Player(11), FourCC('m000'), GetRectRandomX(gg_rct_RaccoonSpawn1), GetRectRandomY(gg_rct_RaccoonSpawn1), 0)
                end)
            elseif uid == FourCC('m001') then
                TimerQueue:callDelayed(3, function ()
                    CreateUnit(Player(11), FourCC('m001'), GetRectRandomX(gg_rct_RaccoonSpawn2), GetRectRandomY(gg_rct_RaccoonSpawn2), 0)
                end)
            end
        end)
    end
    function CreateRaccoonsLoop()
        for i = 1, 12 do
            CreateUnit(Player(11), FourCC('m000'), GetRectRandomX(gg_rct_RaccoonSpawn1), GetRectRandomY(gg_rct_RaccoonSpawn1), 0)
            CreateUnit(Player(11), FourCC('m001'), GetRectRandomX(gg_rct_RaccoonSpawn2), GetRectRandomY(gg_rct_RaccoonSpawn2), 0)
        end
    end

    CreateRaccoonsLoop()
    RaccoonRespawnInit()
end)

if Debug and Debug.endFile then Debug.endFile() end
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
How about taking advantage of how flexible Lua tables are to store all of your data beforehand. You can use the Unit-Type id of your Creeps as the [index] in these Tables to set and get the Unit's associated data. This Raccoon respawn code could easily be remade to work for ALL of your map's creeps:
Lua:
if Debug and Debug.beginFile then Debug.beginFile("Main") end
OnInit.final("Main", function()
 
    -- Creep system variables
    Creep_Player = Player(11)
    Creep_Respawn_Delay = {}
    Creep_Respawn_Region = {}

    function RaccoonRespawnInit()

        -- Register creeps to system
        local u1 = FourCC('m000')
        local u2 = FourCC('m001')
        Creep_Respawn_Delay[u1] = 3.0
        Creep_Respawn_Delay[u2] = 3.0
        Creep_Respawn_Region[u1] = gg_rct_RaccoonSpawn1
        Creep_Respawn_Region[u2] = gg_rct_RaccoonSpawn2

        local trig = CreateTrigger()
        TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_DEATH)
        TriggerAddAction(trig, function()
            local u = GetTriggerUnit()
            local uid = GetUnitTypeId(u)
            if Creep_Respawn_Delay[uid] ~= nil then
                TimerQueue:callDelayed(Creep_Respawn_Delay[uid], function()
                    CreateUnit(Creep_Player, uid, GetRectRandomX(Creep_Respawn_Region[uid]), GetRectRandomY(Creep_Respawn_Region[uid]), 0)
                end)
            end
        end)
    end

    function CreateRaccoonsLoop()
        -- I didn't edit this but it could also use the above variables + be more flexible
        for i = 1, 12 do
            CreateUnit(Player(11), FourCC('m000'), GetRectRandomX(gg_rct_RaccoonSpawn1), GetRectRandomY(gg_rct_RaccoonSpawn1), 0)
            CreateUnit(Player(11), FourCC('m001'), GetRectRandomX(gg_rct_RaccoonSpawn2), GetRectRandomY(gg_rct_RaccoonSpawn2), 0)
        end
    end

    CreateRaccoonsLoop()
    RaccoonRespawnInit()
end)

if Debug and Debug.endFile then Debug.endFile() end
Not sure about the Timer leak stuff, I'd assume an elaborate Timer system would handle all of that for you, especially if it's a One-shot timer.
 
Last edited:
Level 8
Joined
Sep 16, 2016
Messages
227
How about taking advantage of how flexible Lua tables are to store all of your data beforehand. You can use the Unit-Type id of your Creeps as the [index] in these Tables to set and get the Unit's associated data. This Raccoon respawn code could easily be remade to work for ALL of your map's creeps:
Lua:
if Debug and Debug.beginFile then Debug.beginFile("Main") end
OnInit.final("Main", function()
 
    -- Creep system variables
    Creep_Player = Player(11)
    Creep_Respawn_Delay = {}
    Creep_Respawn_Region = {}

    function RaccoonRespawnInit()

        -- Register creeps to system
        local u1 = FourCC('m000')
        local u2 = FourCC('m001')
        Creep_Respawn_Delay[u1] = 3.0
        Creep_Respawn_Delay[u2] = 3.0
        Creep_Respawn_Region[u1] = gg_rct_RaccoonSpawn1
        Creep_Respawn_Region[u2] = gg_rct_RaccoonSpawn2

        local trig = CreateTrigger()
        TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_DEATH)
        TriggerAddAction(trig, function()
            local u = GetDyingUnit()
            local uid = GetUnitTypeId(u)
            if Creep_Respawn_Delay[uid] ~= nil then
                TimerQueue:callDelayed(Creep_Respawn_Delay[uid], function()
                    CreateUnit(Creep_Player, uid, GetRectRandomX(Creep_Respawn_Region[uid]), GetRectRandomY(Creep_Respawn_Region[uid]), 0)
                end)
            end
        end)
    end

    function CreateRaccoonsLoop()
        -- I didn't edit this but it could also use the above variables + be more flexible
        for i = 1, 12 do
            CreateUnit(Player(11), FourCC('m000'), GetRectRandomX(gg_rct_RaccoonSpawn1), GetRectRandomY(gg_rct_RaccoonSpawn1), 0)
            CreateUnit(Player(11), FourCC('m001'), GetRectRandomX(gg_rct_RaccoonSpawn2), GetRectRandomY(gg_rct_RaccoonSpawn2), 0)
        end
    end

    CreateRaccoonsLoop()
    RaccoonRespawnInit()
end)

if Debug and Debug.endFile then Debug.endFile() end
Not sure about the Timer leak stuff, I'd assume an elaborate Timer system would handle all of that for you, especially if it's a One-shot timer.

Omg thanks for the improved code, it looks nice, I will use this.

As for the timer, I use this one [Lua] - TimerQueue & Stopwatch

Do you think I have to destroy the timer after its done, since not a destroyed timer could leak?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
This code here:
Lua:
TimerQueue:callDelayed
Is doing a lot of technical stuff "behind the scenes" which you can see for yourself in the Documentation & Code section on that thread.

But from what I can gather the system only expects you to destroy a Timer if you created it yourself, which it mentions in the Overview:
Instantiability

The above example used :callDelayed() directly on the TimerQueue class.
That works just fine and will satisfy most use cases, but sometimes it's just more convenient to create separate TimerQueues for dfferent things:

tq = TimerQueue.create()
tq:callDelayed(5., print, "tq is a separate TimerQueue instance")

Creating a TimerQueue instance enables you to pause(), :resume(), :reset() and :destroy() the instance as a whole.

The important thing to note, which you are NOT doing, is written here:
Creating a TimerQueue instance enables you to pause(), :resume(), :reset() and :destroy() the instance as a whole.
You're calling "directly on the TimerQueue class" which means that, assuming I'm correct, the system will handle the one-shot timer for you. I don't think it even Creates/Destroys a new Timer, it just reuses an existing one.
 
Last edited:
Level 8
Joined
Sep 16, 2016
Messages
227
This code here:
Lua:
TimerQueue:callDelayed
Is doing a lot of technical stuff "behind the scenes" which can see for yourself in the Documentation & Code section on that thread.

But from what I can gather the system only expects you to destroy a Timer if you created it yourself, which it mentions in the Overview:


The important thing to note, which you are NOT doing, is written here:

You're calling "directly on the TimerQueue class" which means that, assuming I'm correct, the system will handle the one-shot timer for you. I don't think it even Creates/Destroys a new Timer, it just reuses an existing one.
Omg thank you Uncle, bless you <3
 
Top