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

Complete list of things that leak

Level 17
Joined
Jun 17, 2007
Messages
1,433

Complete list of things that leak


This is a complete list of everything that leaks. I haven't found a complete tutorial elsewhere, so I decided to write my own.

  1. Unit Groups
  2. Locations
  3. Special Effects
  4. Player Groups
  5. Misc.

Unit Groups



GUI


Creating groups leaks, and thus we must find a way to prevent that. There is two options. The first of which is putting this line before using any group

  • Custom script: set bj_wantDestroyGroup=true
However, that will destroy the group instantly after that use. That's where the other option comes in; setting the group to a variable and then destroying the variable.

  • Set Group = (Units in (Playable map area))
    • Unit Group - Pick every unit in Group and do (Actions)
      • Loop - Actions
        • Unit - Remove (Picked unit) from the game
    • Custom script: call DestroyGroup(udg_Group)

JASS


JASS:
function GroupExample takes nothing returns nothing
  local group g = CreateGroup()
    local unit f
    call GroupEnumUnitsInRange(x, y, 150, null)
    loop
        set f = FirstOfGroup(g)
        exitwhen f == null
        call KillUnit(f)
        call GroupRemoveUnit(g, f)
    endloop
    call DestroyGroup(g)
endfunction

As you can see, groups in JASS aren't much of a problem. However, using a null boolexp also leaks. This can be solved two ways (one being clearly more ideal). The first of which is using a global boolexp that is always going to return true in place of null.

JASS:
function TrueBoolexpr takes nothing returns boolean
return true
endfunction

The other alternative is using the enum function to perform your actions. It might not make much sense, so here's an example:

JASS:
function BE takes nothing returns boolean
    call RemoveUnit(GetFilterUnit())
    return false
endfunction

function GroupExample takes nothing returns nothing
    local group g = CreateGroup()
    call GroupEnumUnitsInRange(x, y, 150, Filter(function BE))
    call DestroyGroup(g)
endfunction

Locations


GUI


Locations (points) leak, and must be removed. They can be avoided all together in most situations for those who use JASS. Unfortunately, GUI users are not as lucky, and are forced to deal with them. Storing and removing a location variable is quite simple.


  • Set Loc = (Center of (Playable map area))
    • Unit - Create 1 Footman for Player 1 (Red) at Loc facing Default building facing (270.0) degrees
    • Custom script: call RemoveLocation(udg_Loc)
Point with polar offset leaks twice, so you'll need two variables to deal with that.

  • Set Loc = (Position of (Triggering unit))
  • Set Loc2 = (Loc offset by 256.00 towards 0.00 degrees)
  • Unit - Create 1 Footman for Player 1 (Red) at Loc2 facing Default building facing (270.0) degrees
  • Custom script: call RemoveLocation(udg_Loc)
  • Custom script: call RemoveLocation(udg_Loc2)

JASS


JASS opens the user to the world of coordinates. This allows them to almost avoid the use of locations entirely.


JASS:
call CreateUnit(Player(0), 'h000', GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), 270)

With the use of coordinates, we can easily shave off two lines. Easy, right? Locations can be converted to coordinates, and vice-versa.

JASS:
native Location takes real x, real y returns location

JASS:
native GetLocationX takes location whichLocation returns real
native GetLocationY takes location whichLocation returns real

It's also worth noting how to use 'Point with Polar Offset' in JASS.

JASS:
    local real x2 = x + dist * Cos(angle * bj_DEGTORAD)
    local real y2 = y + dist * Sin(angle * bj_DEGTORAD)

x2 and y2 become your x and y coordinates, with x and y the source coordinates.

Special Effects


GUI


Special effects leak, but they are by far the easiest to remove, without requiring any variable. They can be destroyed instantly, and in most cases will still play the animation.

  • Special Effect - Create a special effect at (Center of (Playable map area)) using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
  • Special Effect - Destroy (Last created special effect)

JASS


Special effects are even easier to destroy in JASS than they are in GUI. It doesn't even required an extra line.


JASS:
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl",x,y))

Player Groups


Player groups also leak, but are easier to deal with than unit groups. This is because (All Players) does not leak (bj_FORCE_ALL_PLAYERS in JASS). A variable can be assigned and than destroyed, just as with locations and groups.

  • Set PG = (All allies of Player 1 (Red))
    • Player Group - Pick every player in PG and do (Actions)
      • Loop - Actions
        • Player - Change color of (Picked player) to Red, Changing color of existing units
    • Custom script: call DestroyForce(udg_PG)
If your forces are setup transition numerically with no skips, there is an alternative to even using player groups. That might not have made much sense, so I'll give an example.

Force 1:
Player 1
Player 2
Player 3
Force 2:
Player 4
Player 5
Player 6

The above example work perfectly.

Force 1:
Player 1
Player 2
Player 6
Force 2:
Player 4
Player 5
Player 3

The above example will not work.

To avoid the force, use a loop:

  • For each (Integer A) from 1 to 3, do (Actions)
    • Loop - Actions
      • Player - Change color of (Player((Integer A))) to Red, Changing color of existing units
JASS has no major advantages of GUI when dealing with forces, so it's not really mentioning that.

Misc.


Sounds


Sounds also leak. Prevent this by destroying them similar to the way locations are destroyed.

  • Sound - Play (Last played sound)
    • Sound - Destroy (Last played sound)

Local handle variables


When using local handle variables in JASS, they cause a small leak. A handle is everything except real, string, integer, and boolean. If I'm not mistaken, this only occurs if the handle is ever destroyed or removed from the game. This means that if you are certain a handle will never cease to exist, it's safe not to null the variable. Althought players are handles, they should never need to be nulled.

JASS:
local unit u = GetTriggerUnit()
call SetUnitFacing(u, 270)
call SetUnitFlyHeight(u, 300, 50)
set u = null

This tutorial is basically done. I'll make any improvements that are required. There's bound to be a few, as I'm fairly tired while writing this.
 
Last edited by a moderator:
Level 24
Joined
Feb 28, 2007
Messages
3,480
Formatting works very well. There are no major (or any at all) grammatical and/or spelling errors. It covers something that many people desperately need to learn :)P) and is overall very nice. This has been done before, yes, but I'd say this one is the best of it kind, at least on the Hive, which is what matters. I think this is ready for approval.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
That one doesn't include null boolexprs, local handle variables, the avoidance of forces (player groups), or ways of dealing with them in JASS.
Destroying groups isn't good in the first place.

--

This tutorial misses the vast majority of problems, and only addresses the easiest/most well known ones which are fairly well explained already. If anything would be helpful, a more in-depth description for those learning Jass might be it.
 
Level 11
Joined
Feb 22, 2006
Messages
752
I think Eleandor touched on this: Destroying sounds is not necessary if the sounds are from the sound editor. In fact, destroying the sounds prevents them from ever being played again. The only reason you would want to destroy sounds from the sound editor is if you are certain you will never need to use that particular sound again in the map.

You only need to destroy sounds when you use any of the CreateSound() functions repeatedly before playing the sounds.

Also, your JASS method of destroying special effects has a drawback. If the effect path leads to a model with specified animations, the death animation of the effect will be the one that is shown. So you might want to mention if you want such effects to show an animation besides the death animation (or stick around for an extended period of time), you need to save the effect to a variable and destroy it later.

Finally, boolexpr handles must also be destroyed or else they leak. There's really no way around this using pure GUI (since using null boolexpr leaks also!). In JASS simply save them to a local or something and destroy them after use. If you have vJASS then it becomes even simpler. Just take advantage of free global declaration and only create the boolexpr ONCE at initialization and save it to a global.
 

Deleted member 219079

D

Deleted member 219079

Since when has null boolexpr leaked?
 
Top