• 🏆 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] Does this leak?

Status
Not open for further replies.
Level 2
Joined
Oct 7, 2017
Messages
11
I'm trying to make a trigger that keeps track of a players total value. (current gold+gold cost of each unit he controls.
  • PlayerValueHuman
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Player Group - Pick every player in player1red and do (Actions)
        • Loop - Actions
          • -------- Gold --------
          • Set ValuePlayer[(Player number of (Picked player))] = ((Picked player) Current gold)
          • -------- Footmen --------
          • Set ValueUnitGroup[(Player number of (Picked player))] = (Units owned by (Picked player) of type Footman)
          • Set ValuePlayer[(Player number of (Picked player))] = (ValuePlayer[(Player number of (Picked player))] + ((Number of units in ValueUnitGroup[(Player number of (Picked player))]) x 135))
          • -------- Peasant --------
          • Set ValueUnitGroup[(Player number of (Picked player))] = (Units owned by (Picked player) of type Peasant)
          • Set ValuePlayer[(Player number of (Picked player))] = (ValuePlayer[(Player number of (Picked player))] + ((Number of units in ValueUnitGroup[(Player number of (Picked player))]) x 75))
I plan on adding the ValuePlayer variable to a multiboard.
I set player 1 red = to the player group: player1red in another trigger during map initialization

Now does this leak? is there a better way to do this?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
The GUI function "(Units owned by (Picked player) of type Footman)" leaks a handle ID. This is due to the local declared local handle variable reference counter leak on return bug.
JASS:
function GetUnitsOfPlayerAndTypeId takes player whichPlayer,integer unitid returns group
    local group g = CreateGroup()
    set bj_groupEnumTypeId = unitid
    call GroupEnumUnitsOfPlayer(g, whichPlayer, filterGetUnitsOfPlayerAndTypeId)
    return g
endfunction
As such even if the group is destroyed the handle ID used by the group cannot ever be recycled and hence leaks.
 
Level 2
Joined
Oct 7, 2017
Messages
11
Thank you.
Is there a better way to set ValueUnitGroup without leaking? Like using a hashtable or something, although it seems like I would run into the same problem.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
Is there a better way to set ValueUnitGroup without leaking? Like using a hashtable or something, although it seems like I would run into the same problem.
One could define a custom version of the function that does not leak by using a global or argument declared local variable to return the value rather than a local declared local variable.
 
is there a better way to do this?
The field "Point-Value" inside Object Editor might be quite useful in this case: set it for each unit and loop all units of the player counting up the Point-value (integer).


you could try another approach without groups, when an unit enters the map increase for example "ValuePlayerUnits[playerindex]" by the value of the unit.
When it dies reduce "ValuePlayerUnits[playerindex]".

The bad side of this approach is you need to calc in some effects (if they appear in your map)
RemoveUnit, won't trigger the death Event so you need to reduce the value before using it.
Ownership changes, needs to update the value of both players.
Transformations have to update "ValuePlayerUnits[playerindex]" on transformation and on turning back, if the value differs.
Enters Playerable map events can produce some bugs, if you have dozens of it, can be solved by only using 1 control trigger having the event and calling the other ones.​

The Good side is: you have the value of the playerUnits precaled and just have to read it.

inside the periodic trigger -> ((Picked player) Current gold) + ValuePlayerUnits[picked player]​
 
Level 15
Joined
Mar 25, 2016
Messages
1,327
Instead of (Units owned by (Picked player) of type Footman) you can use
(Units owned by (Picked player) matching (unit type of (matching unit) equal to Footman))

instead of recreating the group every time, you can instead add units to a group when they enter the map and remove them once they die. If you do this you should restructure the trigger a little bit.
Let's say the unit group "MapUnits" contains all units on the map that are relevant for the player value.
Then you can use this trigger:
  • PlayerValue
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Set ValuePlayer[(Player number of (Picked player))] = ((Picked player) Current gold)
      • Unit Group - Pick every unit in MapUnits and do (Actions)
        • Loop - Actions
          • Set Owner = (Owner of (Picked unit))
          • Set OwnerNumber = (Player number of Owner)
          • -------- calculate value of picked unit --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Unit-type of (Picked unit)) Equal to Footman
            • Then - Actions
              • Set UnitValue = 135
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit-type of (Picked unit)) Equal to Peasant
                • Then - Actions
                  • Set UnitValue = 75
                • Else - Actions
          • Set ValuePlayer[OwnerNumber] = (ValuePlayer[OwnerNumber] + UnitValue)
For "calculate value of picked unit" it is preferred to use a hashtable mapping for increased performance and readability. A lot of if-then-else blocks are not as efficient and the trigger becomes really big. The advantage of this approach is, that you do not need to create unit groups all the time.

If the value of a unit resembles its gold cost you can directly get the gold cost of a unit, if you use JassHelper:
JASS:
native GetUnitGoldCost      takes integer unitid                        returns integer
 
Status
Not open for further replies.
Top