• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Trigger] Leak Problem (Trying my best)

Status
Not open for further replies.
Level 5
Joined
Feb 5, 2021
Messages
89
Hello again masters of WC3 Editor!

As i have recently become aware of so many leaks in my game (that i hope can be replayable so leaks or gonna be a massive issue later).

I am trying my best to "fix" the leaks and i have run into a slight problem that i am really unsure how i should take action against.

I am using 3 different triggers where 1 "creates" a point and the other 2 can use it but if you use one of them the other gets nullified, and its player specific so i have 10 players using the same variable and you can see them below all 3 of them, i am just curious if there is a way to "remove" only 1 array of the variable and still have the other 9 use it and then all 10 if the "player" that was removed then uses it again? (if its all nonsense ill elaborate)

  • GoToInventory
    • Events
      • "Any - Player" types a chat message containing -inv as An exact match
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Triggering player) Equal to Player 1 (Red)
        • Then - Actions
          • Set VariableSet LastPortPoint[(Player number of (Triggering player))] = (Position of PlayerHero[(Player number of (Triggering player))])
          • Set VariableSet Inventory1 = (Center of Inventory Player 1 <gen>)
          • Unit - Pause PlayerHero[(Player number of (Triggering player))]
          • Wait 5.00 seconds
          • Selection - Select PlayerHero[(Player number of (Triggering player))] for (Triggering player)
          • Unit - Move PlayerHero[(Player number of (Triggering player))] instantly to Inventory1
          • Unit - Unpause PlayerHero[(Player number of (Triggering player))]
          • Custom script: call RemoveLocation (udg_Inventory1)
        • Else - Actions
  • GoBack
    • Events
      • "Any - Player" types a chat message containing -back as An exact match
    • Conditions
    • Actions
      • Set VariableSet CenterOfCurrentHome = (Center of CurrentHome[(Player number of (Owner of (Entering unit)))])
      • Unit - Move PlayerHero[(Player number of (Triggering player))] instantly to LastPortPoint[(Player number of (Triggering player))]
      • Selection - Select PlayerHero[(Player number of (Triggering player))] for (Triggering player)
      • Set VariableSet LastPortPoint[(Player number of (Triggering player))] = CenterOfCurrentHome
  • LetsGoHome
    • Events
      • "Any - Player" types a chat message containing -Home as An exact match
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
        • Then - Actions
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in (Units currently selected by (Triggering player)) and do (Actions)
            • Loop - Actions
              • If ((Owner of (Picked unit)) Equal to (Triggering player)) then do (Unit - Move (Picked unit) instantly to CenterOfHome[(Player number of (Owner of (Picked unit)))]) else do (Do nothing)
              • Set VariableSet LastPortPoint[(Player number of (Triggering player))] = CenterOfHome[(Player number of (Triggering player))]
        • Else - Actions
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,509
Before worrying about leaks understand that you can't use a Wait like that. The Triggering Player can change to someone else during the 5.00 seconds that the Wait runs.

Luckily, there's a lot of methods for getting around this annoying issue in GUI. The one I recommend people use is this: local udg_

Just make sure that you read and understand it's limitations as there are some things it can't do.

So what you would want to do is "Shadow" the Player Number of your Triggering Player, which means that you store their Player Number in a global variable and "convert" it to a local variable. Then you can reference it safely after the Waits since local variables don't suffer from the issue of being overwritten outside of the current instance of the trigger.

Also, more on topic, you can remove a single index of an array like this:
  • Custom script: call RemoveLocation (udg_LastPortPoint[1])
  • Custom script: call RemoveLocation (udg_LastPortPoint[2])
  • Custom script: call RemoveLocation (udg_LastPortPoint[3])
  • Set Variable PN = Player number of Triggering player
  • Custom script: call RemoveLocation (udg_LastPortPoint[udg_PN])
 
Level 5
Joined
Feb 5, 2021
Messages
89
Aight thanks! never thought about that part i will deffo check out the locals for this!

Though i am also curious if my LastPortPoint creates any leaks in all of this since i set it a couple times but never remove it? :)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,509
Yes, that'll leak the point. The basic rule of thumb, if you set a variable type that can leak (point, unit group, player group) AGAIN before removing the previous one, you've created a leak.

So if you do this:
Set Variable SomePoint = Center of map
Set Variable SomePoint = Position of unit

You've leaked your first setting of SomePoint (Center of map). If you then use Custom script: RemoveLocation() you can only remove the most recent setting of SomePoint, which in this case would be (Position of unit).

The solution:
Set Variable SomePoint = Center of map
Make use of SomePoint -> Remove it
Set Variable SomePoint = Position of unit
Make use of SomePoint -> Remove it

So you need to always make sure that you're maintaining this pattern of removing the point before setting it again. Same goes for other variable types that you only use temporarily.

That being said, understand that this doesn't apply to variables that you want to remain active for the entirety of the game. For example if you stored all of the players in an "ActivePlayers" player group. You would only set this variable once (most likely at the very start of the game), and then you'd never set it ever again. If you wanted to adjust it you could use the Add/Remove player from player group function to dynamically change it without having to set it again.
 
Last edited:
Level 5
Joined
Feb 5, 2021
Messages
89
As i thought, so is there a chance i can "fix" the leak without literally removing the entire variable since i am using the variable as an array for all players to use and store information in?

or is the only fix to make a specific variable for each player in the game?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,509
You'd only be removing that index of the array. So if you remove LastPortPoint[1] then LastPortPoint[2] and the rest of them would still remain active. These are all different points and the RemoveLocation function only focuses on one of them at time. It's not like you're clearing the entire array.

Weird analogy time:
An array is like a dresser with many drawers. You store stuff (points, units, items, etc) inside of these drawers so that you can reference them at a later time. Whenever it comes time to put new stuff in a drawer you have to first Remove the old stuff from it. So you're generally not removing the entire dresser, you're simply removing the contents of one of it's drawers so you can fill it with something new again.

Of course there's some exceptions to this rule. In GUI (the standard trigger editor), Integers, Reals, Booleans, and Strings cannot leak so you can freely overwrite their values with no issues. So you don't need to remove them before setting their values again. In fact, if you try to remove/clear/null them you'll get an error. This holds true for most other variable types as well. So it's really just a handful of variable types that you need to be on top of.

Here are the main leak culprits from most common to least common (based on my experience):
Points, Unit Groups, Special Effects, Player Groups

These are the ones that you should really be looking out for and here's how you clean up each one:
  • Custom script: call RemoveLocation(udg_YourPoint)
  • Custom script: call DestroyGroup(udg_YourUnitGroup)
  • Special Effect - Destroy YourSpecialEffect <--- Most people destroy their effects immediately after creating them using Last created effect (a lot of the times it will still play it's animation)
  • Custom script: call DestroyForce(udg_YourPlayerGroup)

HOWEVER, understand that it's not the end of the world to have some leaks. A few 100 point leaks probably won't be noticeable and your map may function just fine. Don't lose your mind over it too much.
 
Last edited:
Level 5
Joined
Feb 5, 2021
Messages
89
I see! i thank you very much! i think you just saved my head from exploding with your exceptionaly analogies and explanations :D
 
Status
Not open for further replies.
Top