• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[Solved] Need help with tweaked respawn system

Status
Not open for further replies.
Level 8
Joined
Mar 17, 2016
Messages
133
I'm wondering if someone can help me with my tweaked respawn system, it needs to be specifically made to maintain what I already had implemented before recently made changes (due to adding bribe's unit indexer into the level and no longer being able to use "Set custom value [+1]"). The reason I need it specifically made is the "Engine hackery" I had going on before was imperative to how I want my game to progress.

-'Ancients' are non-respawnable bosses,
-Every unit that is placed in the level editor and not spawned in through triggers or abilities will be respawnable,
-Every unit that is not already placed during the level startup will be non-respawnable, (There are unique locations that will be treated like dungeons, where after a player enters the units will spawn, if you fail they will be removed. These units should not be able to respawn)
-Lastly Player 8 and Neutral hostile are both treated as Neutral Hostile, but with a unique relationship.

So I'm trying to make this respawn work here and keep it leakless, though I need some help.

This is the full trigger sequence:
  • RespawnInitialization
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet Respawn_Timer_Creep = 5.00
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units owned by Neutral Hostile matching ((((Matching unit) is A Hero) Equal to False) and ((((Matching unit) is An Ancient) Equal to False) and ((((Matching unit) is Summoned) Equal to False) and (((Matching unit) is A structure) Equal to False)))).) and do (Actions)
        • Loop - Actions
          • Unit Group - Add (Picked unit) to RespawnUnitGroup
          • Set VariableSet Creep_Point[(Custom value of (Picked unit))] = (Position of (Picked unit))
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units owned by Player 8 (Pink) matching ((((Matching unit) is A Hero) Equal to False) and ((((Matching unit) is An Ancient) Equal to False) and ((((Matching unit) is Summoned) Equal to False) and (((Matching unit) is A structure) Equal to False)))).) and do (Actions)
        • Loop - Actions
          • Unit Group - Add (Picked unit) to RespawnUnitGroup
          • Set VariableSet Creep_Point[(Custom value of (Picked unit))] = (Position of (Picked unit))
  • The Respawn
    • Events
      • Unit - A unit Dies
    • Conditions
      • ((Dying unit) is in RespawnUnitGroup.) Equal to True
    • Actions
      • Wait Respawn_Timer_Creep game-time seconds
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of (Dying unit)) Equal to Neutral Hostile
        • Then - Actions
          • Unit - Create 1 (Unit-type of (Dying unit)) for Neutral Hostile at Creep_Point[(Custom value of (Dying unit))] facing (Random angle) degrees
          • Unit Group - Add (Last created unit) to RespawnUnitGroup
        • Else - Actions
          • Unit - Create 1 (Unit-type of (Dying unit)) for Player 8 (Pink) at Creep_Point[(Custom value of (Dying unit))] facing (Random angle) degrees
          • Unit Group - Add (Last created unit) to RespawnUnitGroup
      • Custom script: call RemoveLocation(udg_Creep_Point[X])
      • Set VariableSet Creep_Point[(Custom value of (Last created unit))] = (Position of (Last created unit))
What I'm wondering is:
Will the "Last created unit" bug, because it is after a "Wait"?
Do I need the "bj_wantdestroygroup"s even though they are being added to a unit group?
Also, I'm not sure how to call upon in game variables through custom code, but this is something I need help with & couldn't find google results:

  • Custom script: call RemoveLocation(udg_Creep_Point["X"])
I want to replace the "X" with whatever the code would be for "Custom value of (dying unit)", so that I can set the new point as the new custom value's # for whichever unit comes next. Or if there's a better method I'm open to that
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,595
1) Replace all instances of Dying unit with Triggering unit.

Triggering unit is treated like a local variable and will retain the unit between the Waits. Always use Triggering Unit whenever possible to make your life easier.

2) Last created unit will never leak and will work fine. You're creating a unit and then immediately referencing "last created unit", which will of course be set to the unit that you just created.

3) You do need "set bj_wantDestroyGroup = true" because whenever you use the "Pick every unit" function you're creating a NEW Unit Group that contains the units that match your filter settings (non-hero, etc). This new Unit Group is separate from RespawnUnitGroup and needs to be destroyed or else it will leak (which you're doing already).

The reason you don't need to destroy RespawnUnitGroup is because you intend to use it for the rest of the game.

The key thing that makes something a Memory Leak is the fact that you've lost reference to it. So these Unit Groups for example, if you don't handle them properly they will remain in the game's memory forever despite the fact that you only needed them once. That's why you need to destroy them using "set bj_wantDestroyGroup" or a Unit Group variable + "Custom script: call DestroyGroup(udg_UnitGroupVar)".

So just think about your own memory. There are things that you need to remember forever, your name for example, and things that you can throw away after you're done with them, a verification code for example, like the ones that you would get texted to your phone to sign into an account. That verification code is no longer needed and is taking up precious memory so of course you forget it. So just like how you manage your own memory, the game needs YOU to manage it's memory.

So you want to make sure that important/re-used things are retained, and temporary things are thrown away (removed/destroyed).

The most common leaks you'll run into when using GUI, ordered from most common to least common (in my opinion):
1) Points (aka Locations)
2) Unit Groups
3) Special Effects
4) Player Groups (aka Forces)

And custom value in jass (custom script) looks like this:
vJASS:
GetUnitUserData(whichUnit)
So you could replace X with:
  • Custom script: call RemoveLocation(udg_Creep_Point[GetUnitUserData(GetTriggerUnit())])
Remember, Custom Script uses Jass (warcraft 3's programming language), so you're essentially writing in code whenever you use it. GUI (the trigger editor that you use) is just Jass hidden behind simple text/buttons, it's basically coding made easy.

So if you're ever curious as to what you should write in Custom script, you can use Edit -> Convert to Custom Text to see what your trigger looks like in Jass (create a copy of the trigger first). You'll see things like Triggering unit change to GetTriggerUnit(), and Custom value change to GetUnitUserData(unit goes here).

Or simply set an Integer variable to be equal to the unit's custom value and reference it like so:
  • Actions
    • Set VariableSet CV = (Custom value of (Triggering unit))
    • Custom script: call RemoveLocation(udg_Creep_Point[udg_CV])
It's a lot easier to reference these things in custom script using global variables.
 
Last edited:
Level 8
Joined
Mar 17, 2016
Messages
133
Geez, you are an actual legend. Done, thank you! Your explanations are very informative and easy to understand, I must say. I've tested everything that needs to happen and all the things I mentioned seem to work perfectly as of now, except for one thing. My units that have the ability "Incinerate" cause the units to not respawn. Any idea what could cause that? Maybe because they don't leave corpses or something?


Also, that's VERY useful information about converting to the custom script language, thank you very much for that!
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,595
Geez, you are an actual legend. Done, thank you! Your explanations are very informative and easy to understand, I must say. I've tested everything that needs to happen and all the things I mentioned seem to work perfectly as of now, except for one thing. My units that have the ability "Incinerate" cause the units to not respawn. Any idea what could cause that? Maybe because they don't leave corpses or something?


Also, that's VERY useful information about converting to the custom script language, thank you very much for that!
Yeah, Incinerate "removes" the unit, which doesn't fire a Dying unit event.
 
Status
Not open for further replies.
Top