HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

creep respawn

02-19-2009, 11:10 AM#1
311
I want to add a creep respawn system to my map. I checked the resource section and I found one but its not exactly what I want because its in groups. I want it so anytime I kill a unit that unit will respawn in about 5mins. The way the one in the resource section was set so that every unit in the region needed to die though. Now I guess I could just make really tiny regions for every single creep on my map so the "group" is just 1 guy but I kinda want them spread out randomly when they spawn.

I want it so when I kill a unit that unit will respawn randomly somewhere in that region and every unit to be like that "though maybe some have different respawn times). I dont want it so I need to kill every single unit in the group for it to work
02-19-2009, 02:37 PM#2
darkwulfv
Well the way I did it was I put a rect under each group of creeps (for them to respawn into at random points). At map initialization or very soon after (this requires you have all your creeps pre-placed; you can do so by triggers but the next step will have to be done a little later) group all the units of the creep player. Make sure you apply a filter so things that shouldn't respawn won't be included (they can be done seperately if necessary).

Once you have your group, you'll need a global location array; call it whatever you want. Your next step is to loop through each of the units and assign it a custom value, and put that custom value into an array slot with the unit's location.

So now, you check when a unit dies. If the unit is owned by the creep player, get the unit's custom value and put it in a struct with the location of the unit and its id, and attach that struct to a timer that will go off in whatever amount of time you want the respawn to be. Then in the timer callback simply create a unit of the type that died (make sure that's brought along too) and assign it the custom value of the dead unit and put its location back into the array in that slot.


No gaurentees this is the most optimized method, but it's straight forward and works without lag. (there's a bit of slow down at the beginning of the map because of the large amount of group work but it ends quick).
02-19-2009, 03:16 PM#3
xombie
why don't you have make struct creep that has the necessary data for respawning (spawn point center x, spawn point center y, etc.) and then have a universal onDeath trigger that will take the creep, change the base unit, while keeping the spawn point x. Sorry if this is a little bit confusing I just woke up its hard to type.

Collapse JASS:
struct creep
    unit        unit        = null
    
    real        spawnx
    real        spawny
    
    private trigger    onDeath    = CreateTrigger()

    static method onDeath takes nothing returns nothing
        // Once again the syntax here does not matter, it is specific to your handle
        // tag setting/getting.
        local creep cdata = GetHandleTag(GetTriggeringTrigger())

        // Now, we have to remove the old death trigger because that specific unit is
        // going to be completely removed from the game after death.
        call DestroyTrigger(cdata.onDeath)
        set cdata.onDeath = CreateTrigger()
        
        // I am purposely ignoring the timers here, you will however need a timer to
        // measure the time between dying/respawning, accurately.
        set cdata.unit = CreateUnit(...)
        call TriggerRegisterUnitEvent(cdata.onDeath, cdata.unit, EVENT_UNIT_DEATH)
        call TriggerAddAction(cdata.onDeath, function creep.onDeath)
    endmethod

    static method create takes unit whichUnit, real spawnX, real spawnY returns creep
        local creep cdata = creep.allocate()
        set cdata.unit = whichUnit
        set cdata.spawnx = spawnX
        set cdata.spawny = spawnY

        // Register the specific creep's death event, so you know whenever the method is
        // launched it will be the callback of a creep's death.
        call TriggerRegisterUnitEvent(cdata.onDeath, whichUnit, EVENT_UNIT_DEATH)
        call TriggerAddAction(cdata.onDeath, function creep.onDeath)
        
        // This bit here follows not particular syntax, it is specific to whichever method
        // of attaching structs to handles that you use.
        call SetHandleTag(cdata.onDeath, cdata)

        return cdata
    endmethod
endstruct

This is something I threw together just now. Its missing one major step (the timer factor) just because there are multiple ways in which you could do that as well.
02-19-2009, 10:14 PM#4
311
I dunno JASS is it possible with GUI, or at least JASS thats easy for newbies to read where I just change a few things like spawn time, unit type.

Btw my units will not be preplaced.
It sounds like an easy trigger but I was told waits are bad to use but just to make sure this wont work?

e. unit dies
c dying unit ownd by neautral hostile
c. dying unit in an act 1 unit
c. unit in act 1 zone
a. wait 5mins and spawn random act 1 unit

I dont want lag and was always told wait's cause lag expecially over long periods
02-19-2009, 10:21 PM#5
xombie
Hmm.. its a little bit more work to do in GUI. You should really just skip using GUI because JASS, and then vJass (jassnewgen) is a lot easier to use than GUI in most cases.
02-19-2009, 10:46 PM#6
311
Quote:
Originally Posted by xombie
Hmm.. its a little bit more work to do in GUI. You should really just skip using GUI because JASS, and then vJass (jassnewgen) is a lot easier to use than GUI in most cases.


for you guys ya, I dont understand it most of the time, the trigger you posted I wouldnt know how to set the timer for respawn or if I need to add units to a group or region, I thank you for posting all of it, and trying very hard to help me, but its like typing in chinese symbols and expecting me to read it lol

the trigger I posted wont work? it sounds like something so easy that I would not need JASS. as the respawnd unit would not need to face a certain way, I kinda dont care if its even the same unit, I think I might just do a "random act 1 guy" kinda deal


what about this would this lag?work?(I would try it but wont be home for a bit)

e every 10secs of game time
c units in region act 1 is less then 30
a create 1 random act1 unit

only thing that sux is I would need so many regions since I dont want the final act 1 guys spawning at the start of act 1, so I think I would need like 20regions just for act 1

thanks again for all the help
02-19-2009, 11:02 PM#7
xombie
No no, don't feel pressured. I don't expect you to understand it if you can't. I'm not trying to impose.
02-20-2009, 02:58 AM#8
moyack
This code automatically respawn units that were placed in WE. If it's a normal player, it will respawn at 3 seconds, if it's a creep, it will respawn it 40 seconds later.

Modify it at your needs.

Collapse JASS:
// Revive dead units
scope Revive initializer init

globals
    private constant real  time = 3.
    private          group G    = CreateGroup()
endglobals

private struct data
    unit u
    real x
    real y
    real f
    static integer index = 0
    
    static method Add takes nothing returns boolean
        local data D = data.allocate()
        set D.u = GetFilterUnit()
        set D.x = GetUnitX(D.u)
        set D.y = GetUnitY(D.u)
        set D.f = GetUnitFacing(D.u)
        set data.index = integer(D)
        return true
    endmethod
    
    static method GetData takes unit u returns data
        local integer i = 1
        loop
            exitwhen i > data.index
            if u == data(i).u then
                return data(i)
            endif
            set i = i + 1
        endloop
        return data(0)
    endmethod
endstruct

private function Actions takes nothing returns nothing
    local data D = data.GetData(GetTriggerUnit())
    local player p = GetOwningPlayer(D.u)
    local integer id = GetUnitTypeId(D.u)
    if GetPlayerId(p) < 12 then
        call TriggerSleepAction(3.)
    else
        call TriggerSleepAction(40.)
    endif
    call RemoveUnit(D.u)
    set D.u = CreateUnit(p, id, D.x, D.y, D.f)
endfunction 

//===========================================================================
private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddAction(t, function Actions)
    set t = null
    call GroupEnumUnitsInRect(G, GetWorldBounds(), Condition(function data.Add))
endfunction

endscope
02-21-2009, 09:36 AM#9
311
Quote:
Originally Posted by moyack
This code automatically respawn units that were placed in WE. If it's a normal player, it will respawn at 3 seconds, if it's a creep, it will respawn it 40 seconds later.

Modify it at your needs.

Collapse JASS:
// Revive dead units
scope Revive initializer init

globals
    private constant real  time = 3.
    private          group G    = CreateGroup()
endglobals

private struct data
    unit u
    real x
    real y
    real f
    static integer index = 0
    
    static method Add takes nothing returns boolean
        local data D = data.allocate()
        set D.u = GetFilterUnit()
        set D.x = GetUnitX(D.u)
        set D.y = GetUnitY(D.u)
        set D.f = GetUnitFacing(D.u)
        set data.index = integer(D)
        return true
    endmethod
    
    static method GetData takes unit u returns data
        local integer i = 1
        loop
            exitwhen i > data.index
            if u == data(i).u then
                return data(i)
            endif
            set i = i + 1
        endloop
        return data(0)
    endmethod
endstruct

private function Actions takes nothing returns nothing
    local data D = data.GetData(GetTriggerUnit())
    local player p = GetOwningPlayer(D.u)
    local integer id = GetUnitTypeId(D.u)
    if GetPlayerId(p) < 12 then
        call TriggerSleepAction(3.)
    else
        call TriggerSleepAction(40.)
    endif
    call RemoveUnit(D.u)
    set D.u = CreateUnit(p, id, D.x, D.y, D.f)
endfunction 

//===========================================================================
private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddAction(t, function Actions)
    set t = null
    call GroupEnumUnitsInRect(G, GetWorldBounds(), Condition(function data.Add))
endfunction

endscope

good news is this works good enough, I didnt want preplaced unit's because of my random attributes I was doing but I guess im just going to have to live with it. Also I rather them spawn "kinda in the same spot" but still random like it be cool if it was within 1000 range or somthing but still good enough.
Only 1 problem I have and hope you will take the time to fix it or tell me how. Since you have it set for player also this means when I die I get revived :(, I dont want this, I guess I could just set the player version to 9999999 but i think it might revive me later on in the game, and I will have 2heros. Also I dont want my bosses to revive. Hope you can help me with the player/boss issue reviving, dont worry about the range of the spawn because it would probably cause more problems for me because of how my map is set up like act 1 is kinda near act 3, and its blockd off by trees and pathing blockers completly, but "spawn unit within 1000range of where it died" might cause lowbies to spawn all over act 3
02-22-2009, 01:47 PM#10
311
anyway to stop it from respawning my units? or bosses?
02-22-2009, 02:03 PM#11
moyack
Could you define exactly how you want to respawn your units?
02-22-2009, 03:15 PM#12
311
I have 5 zones in my map all 5 are side by side but each are blocked by pathing blockers so you cant get to ther other zones in anyway possible except by teleporitng when you beat an ealier zone. The reason why I mention this is because this means an act 1 guy is pretty close to an act 2 guy because there's only 1 line of pathing blockers/site blockers between act 1/2 so if 1 guy is on the far right and the guy from act 2 is on far left, then they are going to be side by side, even though you wont see him.

This would be the ultimate of what I would want but I dont think its possible from what I been hearing
-not having pre placed units
-when I kill a unit it will respawn 5mins later
-when they respawn its within either a region(would be best) or a range of where the unit 1st was
-will not respawn me or other players only cpu stuff
-will not respawn bosses(would like this to be specific units because I thought about of just make it not respawn hero's but I might add random lowbie heros around the area as stronger units


that would be best but since I dont think the non preplaced units is possible, and I dont want you to take 100hours just to help me on a map thats probably not going to be played by more then 20people

just having your trigger not respawn player units or hero's would be good, but the respawning in a region is definatly a big big big bonus :)



also if it makes it any easier the dying unit dont even need to be the same it can be a list it dont matter like if I have 7units in the start of act 1 region and 1 of them dies any of those 7 will be revived(im not sure if this makes it harder or not) I just thought it be easier because its not specific unit then
02-23-2009, 11:13 AM#13
311
well after all the talk of don't use waits no matter what because its massive lag I thought id try it just to see and I let the map run for 1hour with 5 of my units killing the same units over and over, over a 3sec respawn timer, and didnt seem to lag at all, and everything spawned correctly.

1question though how can I get a region to be of dying unit? is it possible? thats all I would like changed now, and I got a perfect trigger :)

I want something like this
create 1 unit type of "dying unit" at "random point in region of dying unit"



random point in region of dying unit
^^^^^^^^anyway to get something similar to this?
02-23-2009, 02:39 PM#14
holyadvocate
Quote:
Originally Posted by 311
well after all the talk of don't use waits no matter what because its massive lag I thought id try it just to see and I let the map run for 1hour with 5 of my units killing the same units over and over, over a 3sec respawn timer, and didnt seem to lag at all, and everything spawned correctly.

1question though how can I get a region to be of dying unit? is it possible? thats all I would like changed now, and I got a perfect trigger :)

I want something like this
create 1 unit type of "dying unit" at "random point in region of dying unit"



random point in region of dying unit
^^^^^^^^anyway to get something similar to this?


This is what you want, in GUI...

In this trigger, i used a Unit Type variable array, which you would need to set at the beginning of the map (-General, Set Varable)

If you want a specific position for each creep, rather than a random point in a region near their point of death, I suggest you look at Blizzards code in Funny Bunny's Egg Hunt (TFT, Scenario)

Trigger:
Creep Respawn
Collapse Events
Unit - A unit Dies
Collapse Conditions
(Owner of (Triggering unit)) Equal to Neutral Hostile
Collapse Actions
Wait 2.00 seconds
Unit - Create 1 Creeps[(Random integer number between 1 and 5)] for (Owner of (Triggering unit)) at (Random point in (Region centered at (Position of (Triggering unit)) with size (500.00, 500.00))) facing Default building facing degrees
02-23-2009, 10:16 PM#15
xombie
Trigger:
Creep Respawn
Collapse Events
Unit - A unit Dies
Collapse Conditions
(Owner of (Triggering unit)) Equal to Neutral Hostile
Collapse Actions
Wait 2.00 seconds
Unit - Create 1 Creeps[(Random integer number between 1 and 5)] for (Owner of (Triggering unit)) at (Random point in (Region centered at (Position of (Triggering unit)) with size (500.00, 500.00))) facing Default building facing degrees

This wouldn't work, hence why TriggerSleepAction (also known as "Wait") is not a good option. The reason for this is it kills the thread that is being used, so "Triggering unit" would no longer work.