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

[Solved] Stop point leak

Status
Not open for further replies.
Level 12
Joined
May 16, 2020
Messages
660
Hi, I'm pretty sure that this trigger leaks a point variable (as it's being overwritten over and over), but I'm not sure how to fix it.
Can anyone please a) confirm this leaks and b) suggest how to fix it please?

  • Water Jet
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Water Jet
    • Actions
      • Set VariableSet WaterJet_Index = (WaterJet_Index + 1)
      • Set VariableSet WaterJet_Caster[WaterJet_Index] = (Triggering unit)
      • Set VariableSet WaterJet_Target[WaterJet_Index] = (Target unit of ability being cast)
      • Set VariableSet WaterJet_Level[WaterJet_Index] = (Level of Water Jet for WaterJet_Caster[WaterJet_Index])
      • Set VariableSet WaterJet_Point[WaterJet_Index] = (Position of WaterJet_Caster[WaterJet_Index])
      • -------- --------
      • Special Effect - Create a special effect at WaterJet_Point[WaterJet_Index] using Abilities\Weapons\WaterElementalMissile\WaterElementalMissile.mdl
      • Set VariableSet WaterJet_SFX[WaterJet_Index] = (Last created special effect)
      • Special Effect - Set Height of WaterJet_SFX[WaterJet_Index] to: ((Position - Z of WaterJet_SFX[WaterJet_Index].) + 60.00)
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • WaterJet_Index Equal to 1
        • Then - Actions
          • Countdown Timer - Start WaterJet_Timer as a Repeating timer that will expire in 0.03 seconds
          • Trigger - Turn on Water Jet Loop <gen>
        • Else - Actions
  • Water Jet Loop
    • Events
      • Time - WaterJet_Timer expires
    • Conditions
    • Actions
      • For each (Integer WaterJet_Integer) from 1 to WaterJet_Index, do (Actions)
        • Loop - Actions
          • Set VariableSet WaterJet_PointOld = WaterJet_Point[WaterJet_Integer]
          • Set VariableSet WaterJet_PointTarget = (Position of WaterJet_Target[WaterJet_Integer])
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between WaterJet_PointOld and WaterJet_PointTarget) Greater than 65.00
            • Then - Actions
              • -------- MOVE MISSILE --------
              • Set VariableSet WaterJet_Point[WaterJet_Integer] = (WaterJet_PointOld offset by 60.00 towards (Angle from WaterJet_PointOld to WaterJet_PointTarget) degrees.)
              • Custom script: set udg_WaterJet_Z = GetLocationZ(udg_WaterJet_Point[udg_WaterJet_Integer])
              • Special Effect - Set Position of WaterJet_SFX[WaterJet_Integer] to x: (X of WaterJet_Point[WaterJet_Integer]), y: (Y of WaterJet_Point[WaterJet_Integer]), z: (WaterJet_Z + 60.00)
            • Else - Actions
              • -------- HIT --------
              • Special Effect - Destroy WaterJet_SFX[WaterJet_Integer]
              • -------- --------
              • Set VariableSet WaterJet_CV = (Custom value of WaterJet_Caster[WaterJet_Integer])
              • Set VariableSet WaterJet_TargetIllusion[WaterJet_CV] = WaterJet_Target[WaterJet_Integer]
              • -------- --------
              • Set VariableSet Illusion_Caster = WaterJet_Caster[WaterJet_Integer]
              • Set VariableSet Illusion_Player = (Owner of Illusion_Caster)
              • Set VariableSet Illusion_DamageDealt = 0.25
              • Set VariableSet Illusion_DamageTaken = 4.00
              • Set VariableSet Illusion_Duration = (2.00 x (Real(WaterJet_Level[WaterJet_Integer])))
              • Set VariableSet Illusion_AppearCustomized = True
              • Set VariableSet Illusion_AppearPoint = (Position of WaterJet_Target[WaterJet_Integer])
              • Set VariableSet Illusion_AppearFacing = (Angle from Illusion_AppearPoint to WaterJet_PointTarget)
              • Set VariableSet Illusion_Custom = WaterJet
              • Trigger - Run IllusionCreate <gen> (checking conditions)
              • Trigger - Turn on Water Jet Order <gen>
              • -------- --------
              • Unit - Cause WaterJet_Caster[WaterJet_Integer] to damage WaterJet_Target[WaterJet_Integer], dealing (50.00 + (50.00 x (Real(WaterJet_Level[WaterJet_Integer])))) damage of attack type Spells and damage type Magic
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (WaterJet_Target[WaterJet_Integer] is alive) Equal to True
                • Then - Actions
                  • Unit - Create 1 Dummy (Fly/Speed 0) for Neutral Passive at WaterJet_PointOld facing Default building facing degrees
                  • Set VariableSet WaterJet_Dummy = (Last created unit)
                  • Unit - Add Water Jet (Dummy) to WaterJet_Dummy
                  • Ability - Set Ability: (Unit: WaterJet_Dummy's Ability with Ability Code: Water Jet (Dummy))'s Real Level Field: Movement Speed Reduction (%) ('Cri1') of Level: 0 to (0.10 x (Real(WaterJet_Level[WaterJet_Integer])))
                  • Unit - Order WaterJet_Dummy to Undead Necromancer - Cripple WaterJet_Target[WaterJet_Integer]
                  • Unit - Add a 0.50 second Generic expiration timer to WaterJet_Dummy
                • Else - Actions
              • -------- --------
              • Custom script: call RemoveLocation(udg_WaterJet_Point[udg_WaterJet_Integer])
              • -------- --------
              • Set VariableSet WaterJet_Caster[WaterJet_Integer] = WaterJet_Caster[WaterJet_Index]
              • Set VariableSet WaterJet_Target[WaterJet_Integer] = WaterJet_Target[WaterJet_Index]
              • Set VariableSet WaterJet_Level[WaterJet_Integer] = WaterJet_Level[WaterJet_Index]
              • Set VariableSet WaterJet_Point[WaterJet_Integer] = WaterJet_Point[WaterJet_Index]
              • Set VariableSet WaterJet_SFX[WaterJet_Integer] = WaterJet_SFX[WaterJet_Index]
              • -------- --------
              • Set VariableSet WaterJet_Index = (WaterJet_Index - 1)
              • Set VariableSet WaterJet_Integer = (WaterJet_Integer - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • WaterJet_Index Equal to 0
                • Then - Actions
                  • Countdown Timer - Pause WaterJet_Timer
                  • Trigger - Turn off (This trigger)
                • Else - Actions
          • Custom script: call RemoveLocation(udg_WaterJet_PointOld)
          • Custom script: call RemoveLocation(udg_WaterJet_PointTarget)
 
Last edited:
Level 3
Joined
Nov 11, 2021
Messages
28
Methinks:
Generally, you could always free point before set-var and ensure a point copy on set-var.
For locally cross referenced variables, if you do not want to copy on set-var, you could save all written points to an array and free all of them at the end. (IMO it is a worse choice)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,540
I believe WaterJet_Point[WaterJet_Integer] is overwriting it's value and creating leaks but that's under the assumption that this trigger even works in the first place. From my understanding, when you Remove WaterJet_PointOld which is pointing to WaterJet_Point[] both of these Points will get Removed. Doesn't this break the whole trigger since there's no longer a Point to reference in future cycles? I've run into this issue before and I don't see why it'd be any different here.

The issue here:
  • Set VariableSet WaterJet_PointOld = WaterJet_Point[WaterJet_Integer]
Is that you're not creating a new Point (Location). You're telling WaterJet_PointOld to be a reference to WaterJet_Point[WaterJet_Integer].

It's not much different than this:
  • Unit - Create 1 unit...
  • Set Variable UnitA = (Last created unit)
  • Set Variable UnitB = UnitA
  • Unit - Kill UnitB
Both UnitA AND UnitB are killed here, because they're the same unit. So what I'm trying to say is that WaterJet_PointOld IS WaterJet_Point[Waterjet_Integer] when you Set it like that. If you Remove one then you'll Remove both.


Anyway, a solution.

Set WaterJet_PointOld like this:
  • Custom script: set udg_WaterJet_PointOld = Location( GetLocationX(udg_WaterJet_Point[WaterJet_Integer]), GetLocationY(udg_WaterJet_Point[WaterJet_Integer]) )

Or alternatively an offset should work:
  • Set Variable WaterJet_PointOld = (WaterJet_Point[WaterJet_Integer] offset by 0.0, 0.0)
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Thanks Uncle. The trigger does work as intended (see attachment, use the murloc hero in the middle), but I just think it leaks.

The proposed solution confuses me however:
Set WaterJet_PointOld like this:
  • page.gif
    Custom script: set udg_WaterJet_PointOld = Location( GetLocationX(udg_WaterJet_Point[WaterJet_Integer]), GetLocationY(udg_WaterJet_Point[WaterJet_Integer]) )

Isn't this the same as
  • Set VariableSet WaterJet_PointOld = WaterJet_Point[WaterJet_Integer]
?

And what do you mean with this:
Or alternatively an offset should work:
  • set.gif
    Set Variable WaterJet_PointOld = (WaterJet_Point[WaterJet_Integer] offset by 0.0, 0.0)

Ain't I doing this with this?:
  • Set VariableSet WaterJet_Point[WaterJet_Integer] = (WaterJet_PointOld offset by 60.00 towards (Angle from WaterJet_PointOld to WaterJet_PointTarget) degrees.)



And btw, would you be able to explain why this point definition never created an illusion at the Target's place
  • Set VariableSet Illusion_AppearPoint = (Position of WaterJet_PointTarget)

...but this did?:
  • Set VariableSet Illusion_AppearPoint = (Position of WaterJet_Target[WaterJet_Integer])
The point is not getting deleted during the trigger, so I never understood why it wouldn't work...
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,540
I answered all of your questions. Read my post again :p

These two things are completely different:
  • Set Variable WaterJet_PointOld = WaterJet_Point[WaterJet_Integer]
  • Set Variable WaterJet_PointOld = (WaterJet_Point[WaterJet_Integer] offset by 0.0, 0.0)
The first doesn't create a new Point (location), you're simply creating a new reference to WaterJet_Point[].
The second DOES create a new Point (location).

This is how you create a Point in Jass:
JASS:
set TempPoint = Location(0, 0)
// Locations store x/y coordinates
This is what you're doing:
JASS:
set TempPoint = Location(x, y)
set TempPointOld = TempPoint
TempPointOld doesn't create a new Location, it simply directs you to TempPoint. This makes it useless.

I'm still confused as to how your trigger works based on this logic. Regardless, either of my suggested solutions should fix the leak.

Edit Edit Edit: What your trigger should look like. I made 3 changes:
  • Water Jet Loop
    • Events
      • Time - WaterJet_Timer expires
    • Conditions
    • Actions
      • For each (Integer WaterJet_Integer) from 1 to WaterJet_Index, do (Actions)
        • Loop - Actions
          • Set VariableSet WaterJet_PointOld = (WaterJet_Point[WaterJet_Integer] offset by (0.00, 0.00))
          • Set VariableSet WaterJet_PointTarget = (Position of WaterJet_Target[WaterJet_Integer])
          • Custom script: call RemoveLocation (udg_WaterJet_Point[udg_WaterJet_Integer])
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between WaterJet_PointOld and WaterJet_PointTarget) Greater than 65.00
            • Then - Actions
              • -------- MOVE MISSILE --------
              • Set VariableSet WaterJet_Point[WaterJet_Integer] = (WaterJet_PointOld offset by 60.00 towards (Angle from WaterJet_PointOld to WaterJet_PointTarget) degrees.)
              • Custom script: set udg_WaterJet_Z = GetLocationZ(udg_WaterJet_Point[udg_WaterJet_Integer])
              • Special Effect - Set Position of WaterJet_SFX[WaterJet_Integer] to x: (X of WaterJet_Point[WaterJet_Integer]), y: (Y of WaterJet_Point[WaterJet_Integer]), z: (WaterJet_Z + 60.00)
            • Else - Actions
              • -------- HIT --------
              • Special Effect - Destroy WaterJet_SFX[WaterJet_Integer]
              • -------- --------
              • Set VariableSet WaterJet_CV = (Custom value of WaterJet_Caster[WaterJet_Integer])
              • Set VariableSet WaterJet_TargetIllusion[WaterJet_CV] = WaterJet_Target[WaterJet_Integer]
              • -------- --------
              • Set VariableSet Illusion_Caster = WaterJet_Caster[WaterJet_Integer]
              • Set VariableSet Illusion_Player = (Owner of Illusion_Caster)
              • Set VariableSet Illusion_DamageDealt = 0.25
              • Set VariableSet Illusion_DamageTaken = 4.00
              • Set VariableSet Illusion_Duration = (2.00 x (Real(WaterJet_Level[WaterJet_Integer])))
              • Set VariableSet Illusion_AppearCustomized = True
              • Set VariableSet Illusion_AppearPoint = (Position of WaterJet_Target[WaterJet_Integer])
              • Set VariableSet Illusion_AppearFacing = (Angle from Illusion_AppearPoint to WaterJet_PointTarget)
              • Set VariableSet Illusion_Custom = WaterJet
              • Trigger - Run IllusionCreate <gen> (checking conditions)
              • Trigger - Turn on Water Jet Order <gen>
              • -------- --------
              • Unit - Cause WaterJet_Caster[WaterJet_Integer] to damage WaterJet_Target[WaterJet_Integer], dealing (50.00 + (50.00 x (Real(WaterJet_Level[WaterJet_Integer])))) damage of attack type Spells and damage type Magic
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (WaterJet_Target[WaterJet_Integer] is alive) Equal to True
                • Then - Actions
                  • Unit - Create 1 Dummy (Fly/Speed 0) for Neutral Passive at WaterJet_PointOld facing Default building facing degrees
                  • Set VariableSet WaterJet_Dummy = (Last created unit)
                  • Unit - Add Water Jet (Dummy) to WaterJet_Dummy
                  • Ability - Set Ability: (Unit: WaterJet_Dummy's Ability with Ability Code: Water Jet (Dummy))'s Real Level Field: Movement Speed Reduction (%) ('Cri1') of Level: 0 to (0.10 x (Real(WaterJet_Level[WaterJet_Integer])))
                  • Unit - Order WaterJet_Dummy to Undead Necromancer - Cripple WaterJet_Target[WaterJet_Integer]
                  • Unit - Add a 0.50 second Generic expiration timer to WaterJet_Dummy
                • Else - Actions
              • -------- --------
              • Set VariableSet WaterJet_Caster[WaterJet_Integer] = WaterJet_Caster[WaterJet_Index]
              • Set VariableSet WaterJet_Target[WaterJet_Integer] = WaterJet_Target[WaterJet_Index]
              • Set VariableSet WaterJet_Level[WaterJet_Integer] = WaterJet_Level[WaterJet_Index]
              • Set VariableSet WaterJet_Point[WaterJet_Integer] = WaterJet_Point[WaterJet_Index]
              • Set VariableSet WaterJet_SFX[WaterJet_Integer] = WaterJet_SFX[WaterJet_Index]
              • -------- --------
              • Set VariableSet WaterJet_Index = (WaterJet_Index - 1)
              • Set VariableSet WaterJet_Integer = (WaterJet_Integer - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • WaterJet_Index Equal to 0
                • Then - Actions
                  • Countdown Timer - Pause WaterJet_Timer
                  • Trigger - Turn off (This trigger)
                • Else - Actions
          • Custom script: call RemoveLocation(udg_WaterJet_PointOld)
          • Custom script: call RemoveLocation(udg_WaterJet_PointTarget)

Things I changed:
Adjusted the Old point to use an offset, MOVED* the RemoveLocation action to after you Set Old point, and removed the RemoveLocation action from HIT:
  • Set VariableSet WaterJet_PointOld = (WaterJet_Point[WaterJet_Integer] offset by (0.00, 0.00))
  • Custom script: call RemoveLocation (udg_WaterJet_Point[udg_WaterJet_Integer])
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,540
I edited my post like 5x after making some mistakes, just a heads up. It should be good now.

Also, one minor thing I noticed was the Illusion stuff you were doing. Is Turning on/off the Water Jet Order trigger like that MUI? I imagine that'd cause problems if multiple illusions were created at around the same time.
 
Level 12
Joined
May 16, 2020
Messages
660
Thank you so much, that works!

Also, one minor thing I noticed was the Illusion stuff you were doing. Is Turning on/off the Water Jet Order trigger like that MUI? I imagine that'd cause problems if multiple illusions were created at around the same time.

I had the same fear, but after testing it with multiple heroes and it seems to work. I think in this particular case it works because all of these instances are essentially instantaneous (albeit within different triggers). But I will keep an eye out for errors there.
 
Status
Not open for further replies.
Top