• 🏆 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!

I need your help

Status
Not open for further replies.
Level 5
Joined
Oct 16, 2007
Messages
67
Can you explain me what means that?

Since I don't know how good deep you are into mapping I explain some things.

Warcraft 3 creates Objects in the background for certain variable types. While in the Editor you assign a Value to a variable sometimes in reality you assign a Pointer. You would call it a Reference variable.
So simply explained there are 2 Types of variables By Value and By Reference.

By Value:
  • ByValue
    • Events
    • Conditions
    • Actions
      • -------- Setting a Integer to 5 --------
      • Set VariableSet int1 = 5
      • -------- Setting a second Integer to the value of the first --------
      • Set VariableSet int2 = int1
      • -------- Setting the first Integer +1 --------
      • Set VariableSet int1 = (int1 + 1)
      • -------- Result --------
      • -------- Output: 6 --------
      • Game - Display to (All players) the text: (String(int1))
      • -------- Output: 5 --------
      • Game - Display to (All players) the text: (String(int2))
Both variables are Integer.
You set the Value of int1 into int2.
Then you increment int1 by 1. This has no effect on int2.
Output of int1 is 6.
Output of int2 is 5.

These are value variables, if you set a second variable to the same value you can manipulate them without the other knowing.
These type of variables won't create memory leaks.

By Reference:
  • ByReference
    • Events
      • Time - Elapsed game time is 5.00 seconds
    • Conditions
    • Actions
      • -------- Setting uGroup1 to all Units. --------
      • Set VariableSet uGroup1 = (Units in (Playable map area))
      • -------- Setting uGroup2 to all uGroup2. --------
      • Set VariableSet uGroup2 = uGroup1
      • -------- Clearing uGroup1. --------
      • Unit Group - Remove all units from uGroup1.
      • -------- Result --------
      • -------- Number of Unit in uGroup1: 0 --------
      • Game - Display to (All players) the text: (String((Number of units in uGroup1)))
      • -------- Number of Unit in uGroup2: 0 --------
      • Game - Display to (All players) the text: (String((Number of units in uGroup2)))
Both variables are unit groups. I Placed 10 units on the map!
You set uGroup1 to all units on the map.
Then you set uGroup2 to uGroup1.
Now we clear uGroup1.
Finally we output the amount of units in uGroup1 which ofcourse is 0, we just cleared it.
However, in uGroup2 there are also 0 units.

As we did "Set uGroup2 = uGroup1" it would seem that you have a second unit group containing all unit from the first. This is not the case, both variables contain the same unit group! This is what we call a Reference.


And now, why is that Important?
Reference variables are not removed automaticly by Warcraft 3. You have to do it by Hand.
So if you use Actions like "Pick every unit in ..." and you are not giving it a unit group variable, WC3 will create one. However you can't access this group later and it will remian until your Map ends. This is what we call a memory Leak. Of course unit groups are not the only source. The link I provided in my previous Post should contain most/all the sources of memory leaks and more importantly how to get rid of these leaks.


You have Triggers like this
  • AFK
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • For each (Integer afk) from 1 to 10, do (Actions)
        • Loop - Actions
          • If (((Owner of Circle[afk]) slot status) Equal to Is playing) then do (Set VariableSet AFK_tiempo[afk] = (AFK_tiempo[afk] + 0.01)) else do (Do nothing)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in Tornado_casters) Greater than 0
        • Then - Actions
          • Unit Group - Pick every unit in Tornado_casters and do (Actions)
            • Loop - Actions
              • Set VariableSet Tornado = (Picked unit)
              • Unit Group - Pick every unit in (Units within 250.00 of (Position of Tornado) matching (((Matching unit) belongs to an enemy of (Owner of Tornado).) Equal to True).) and do (Unit - Order Tornado to Night Elf Druid Of The Talon - Cyclone (Picked unit))
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in (Units of type Faerie Dragon)) Greater than 0
        • Then - Actions
          • Unit Group - Pick every unit in (Units of type Faerie Dragon) and do (Actions)
            • Loop - Actions
              • Set VariableSet brazales_runicos_unit = (Picked unit)
              • Unit Group - Pick every unit in (Units within 700.00 of (Position of brazales_runicos_unit) matching (((Matching unit) has buff Anti-Magic Shield (Magic Resistance) (Extra)) Equal to False).) and do (Actions)
                • Loop - Actions
                  • Unit - Order brazales_runicos_unit to Undead Banshee - Anti-magic Shell (Picked unit)
        • Else - Actions
Every 0.01 is already heavy but it shouldn't be too much of a Problem.

Then:
If - Conditions
(Number of units in Tornado_casters) Greater than 0
is excelent. This is no memory leak as Tornado_casters is a group.

But:
If - Conditions
(Number of units in (Units of type Faerie Dragon)) Greater than 0
will create a new unit group every time the trigger runs. This unit group is never Destroyed, so it will remain until your map ends. It won't do much in the beginning, but it will add up with the other memory leaks you have.


In the end, I would guess that memory leaks like that are the reason the map lags later.
 
Level 24
Joined
Jun 26, 2020
Messages
1,852
Since I don't know how good deep you are into mapping I explain some things.

Warcraft 3 creates Objects in the background for certain variable types. While in the Editor you assign a Value to a variable sometimes in reality you assign a Pointer. You would call it a Reference variable.
So simply explained there are 2 Types of variables By Value and By Reference.

By Value:
  • ByValue
    • Events
    • Conditions
    • Actions
      • -------- Setting a Integer to 5 --------
      • Set VariableSet int1 = 5
      • -------- Setting a second Integer to the value of the first --------
      • Set VariableSet int2 = int1
      • -------- Setting the first Integer +1 --------
      • Set VariableSet int1 = (int1 + 1)
      • -------- Result --------
      • -------- Output: 6 --------
      • Game - Display to (All players) the text: (String(int1))
      • -------- Output: 5 --------
      • Game - Display to (All players) the text: (String(int2))
Both variables are Integer.
You set the Value of int1 into int2.
Then you increment int1 by 1. This has no effect on int2.
Output of int1 is 6.
Output of int2 is 5.

These are value variables, if you set a second variable to the same value you can manipulate them without the other knowing.
These type of variables won't create memory leaks.

By Reference:
  • ByReference
    • Events
      • Time - Elapsed game time is 5.00 seconds
    • Conditions
    • Actions
      • -------- Setting uGroup1 to all Units. --------
      • Set VariableSet uGroup1 = (Units in (Playable map area))
      • -------- Setting uGroup2 to all uGroup2. --------
      • Set VariableSet uGroup2 = uGroup1
      • -------- Clearing uGroup1. --------
      • Unit Group - Remove all units from uGroup1.
      • -------- Result --------
      • -------- Number of Unit in uGroup1: 0 --------
      • Game - Display to (All players) the text: (String((Number of units in uGroup1)))
      • -------- Number of Unit in uGroup2: 0 --------
      • Game - Display to (All players) the text: (String((Number of units in uGroup2)))
Both variables are unit groups. I Placed 10 units on the map!
You set uGroup1 to all units on the map.
Then you set uGroup2 to uGroup1.
Now we clear uGroup1.
Finally we output the amount of units in uGroup1 which ofcourse is 0, we just cleared it.
However, in uGroup2 there are also 0 units.

As we did "Set uGroup2 = uGroup1" it would seem that you have a second unit group containing all unit from the first. This is not the case, both variables contain the same unit group! This is what we call a Reference.


And now, why is that Important?
Reference variables are not removed automaticly by Warcraft 3. You have to do it by Hand.
So if you use Actions like "Pick every unit in ..." and you are not giving it a unit group variable, WC3 will create one. However you can't access this group later and it will remian until your Map ends. This is what we call a memory Leak. Of course unit groups are not the only source. The link I provided in my previous Post should contain most/all the sources of memory leaks and more importantly how to get rid of these leaks.


You have Triggers like this
  • AFK
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • For each (Integer afk) from 1 to 10, do (Actions)
        • Loop - Actions
          • If (((Owner of Circle[afk]) slot status) Equal to Is playing) then do (Set VariableSet AFK_tiempo[afk] = (AFK_tiempo[afk] + 0.01)) else do (Do nothing)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in Tornado_casters) Greater than 0
        • Then - Actions
          • Unit Group - Pick every unit in Tornado_casters and do (Actions)
            • Loop - Actions
              • Set VariableSet Tornado = (Picked unit)
              • Unit Group - Pick every unit in (Units within 250.00 of (Position of Tornado) matching (((Matching unit) belongs to an enemy of (Owner of Tornado).) Equal to True).) and do (Unit - Order Tornado to Night Elf Druid Of The Talon - Cyclone (Picked unit))
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in (Units of type Faerie Dragon)) Greater than 0
        • Then - Actions
          • Unit Group - Pick every unit in (Units of type Faerie Dragon) and do (Actions)
            • Loop - Actions
              • Set VariableSet brazales_runicos_unit = (Picked unit)
              • Unit Group - Pick every unit in (Units within 700.00 of (Position of brazales_runicos_unit) matching (((Matching unit) has buff Anti-Magic Shield (Magic Resistance) (Extra)) Equal to False).) and do (Actions)
                • Loop - Actions
                  • Unit - Order brazales_runicos_unit to Undead Banshee - Anti-magic Shell (Picked unit)
        • Else - Actions
Every 0.01 is already heavy but it shouldn't be too much of a Problem.

Then:
If - Conditions
(Number of units in Tornado_casters) Greater than 0
is excelent. This is no memory leak as Tornado_casters is a group.

But:
If - Conditions
(Number of units in (Units of type Faerie Dragon)) Greater than 0
will create a new unit group every time the trigger runs. This unit group is never Destroyed, so it will remain until your map ends. It won't do much in the beginning, but it will add up with the other memory leaks you have.


In the end, I would guess that memory leaks like that are the reason the map lags later.

Oh, I see, thx for that, one more thing, the part of:

Unit Group - Pick every unit in (Units within 250.00 of (Position of Tornado) matching (((Matching unit) belongs to an enemy of (Owner of Tornado).) Equal to True).) and do (Unit - Order Tornado to Night Elf Druid Of The Talon - Cyclone (Picked unit))

Does also counts as memory leak?
 
Level 5
Joined
Oct 16, 2007
Messages
67
Oh, I see, thx for that, one more thing, the part of:

Unit Group - Pick every unit in (Units within 250.00 of (Position of Tornado) matching (((Matching unit) belongs to an enemy of (Owner of Tornado).) Equal to True).) and do (Unit - Order Tornado to Night Elf Druid Of The Talon - Cyclone (Picked unit))

Does also counts as memory leak?

Units within 250.00 of - Group leak
(Position of Tornado) - Location leak

I'm also not sure if the cyclone realy can cast on more then 1 unit a time with this trigger, I haven't took a look into your abilitys.
 
Last edited:
Level 24
Joined
Jun 26, 2020
Messages
1,852
Units within 250.00 of - Group leak
(Position of Tornado) - Location leak

I'm also not sure if the cyclone realy can cast on more then 1 unit a time with this trigger, I haven't took a look into your abilitys.

Thx, and the cyclone can be cast multiple times if you set the cooldown to 0 and the time of the animations of the caster to 0.
 
Level 5
Joined
Oct 16, 2007
Messages
67
@Lartin One more question: Are there memory leaks if I use hash tables?

I'm not 100% sure, but if you don't flush child keys in tables if you no longer use them that will definetly be a data trash.
I always clear handles I saved into the Hashtable (group, locations etc.) if I no longer need them but never checked if someone has tested if thats necessary.

You also don't have to fix every memory leak, but you should fix it in code that runs a lot.
 
Level 24
Joined
Jun 26, 2020
Messages
1,852
@Lartin And another question: What happen if I use the action "Wait for condition" when the condition includes memory leak?
I made something like this:

  • Trigger
    • Events
    • Conditions
    • Actions
      • Set VariableGroup=Group
      • Trigger - Turn on (Confirmer)
      • Wait until(Number of units in VariableGroup equal to 0), checking every 0.10 seconds
      • Trigger - Turn off (Confirmer)
      • Custom script: call DestroyGroup(udg_VariableGroup)
  • Confimer
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Custom script: call DestroyGroup(udg_VariableGroup)
      • Set VariableGroup=Group
 
Level 5
Joined
Oct 16, 2007
Messages
67
@Lartin And another question: What happen if I use the action "Wait for condition" when the condition includes memory leak?
I made something like this:

  • Trigger
    • Events
    • Conditions
    • Actions
      • Set VariableGroup=Group
      • Trigger - Turn on (Confirmer)
      • Wait until(Number of units in VariableGroup equal to 0), checking every 0.10 seconds
      • Trigger - Turn off (Confirmer)
      • Custom script: call DestroyGroup(udg_VariableGroup)
  • Confimer
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Custom script: call DestroyGroup(udg_VariableGroup)
      • Set VariableGroup=Group

Wait for condition creates an endless loop with an exit condition which is your condition and a wait of your choosen time behind it.
So if it would be a memory leak (in your example it's not) then it would create a new one every time your time expires.

Your Trigger should work memory leak free.
 
Status
Not open for further replies.
Top