I
IKilledKEnny
Guest
Understanding Leaks
~By IKilledKEnny~
I’m tired of seeing so many people having a hard time understanding leaks even after they have read leaks removal tutorials, so I have decided to make a short mini-tutorial about it trying to explain it the clearest way possible.
If you didn’t read yet a leak removing tutorial I suggest warmly you check this, this or this because they are much more informative tutorials, here I’m going to explain everything slower so it would be easier to understand.
In this tutorial we will talk about 3 common leaks which are:
[list
[*] Unit Group (Group) - Can cause serious leaks
[*]Player Group (Force) - Not a huge leak but still considerable one.
[*]Point (Location) - A minor leak, however this is the one that is most frequently created.
[/list]
First of all let’s understand what leaks are. Leaks are a piece of data that is not removed, or overwritten without being removed, what causes the computer to store it in a memory and forces it to remember it until removed, clearing leaks actually removes this piece of information after being used. Clearing leaks is a very powerful tool, and clearing things we plan in using in the future and have no way to re-receive could destroy whole triggers’ functions, however clearing leaks is an important unavoidable thing in World Editor which mustn’t be ignored. Integer, Booleans, strings and reals don’t need to be removed as they take minimal memory space.
Conclusion: A leak is a piece of information that hasn’t been removed and forces to computer to remember it which slows its reaction. The most common things that need to be removed are Groups, Forces and Locations.
So after we understood what leaks are, and how important it is to remove them, the next question is how do we detect them? Lets check this following trigger:
Code:
Events
Unit - A unit Dies
Conditions
Actions
Unit - Move (Triggering unit) instantly to (Center of (Playable map area))
Can you detect here the leak? No? Let’s bold it.
Unit - Move (Triggering unit) instantly to (Center of (Playable map area))
Do you see that? We used a point but we don’t remove it. Let’s move on.
Code:
Events
Time - Every 1.00 seconds of game time
Conditions
Actions
[b]Unit Group - Pick every unit in (Units owned by Player 1 (Red)) and do (Actions)[/b]
Loop - Actions
Unit - Remove (Picked unit) from the game
This is another type of leak. Unit group leak, much deadlier then the point leak. What makes it even worse is the fact that the leak repeats every 1 second. In few minutes or even seconds your game would crush because of this little trigger. Finally let’s have a quick look at forces leaks.
Code:
Events
Time - Every 1.00 seconds of game time
Conditions
Actions
Player Group - Pick every player in (All players) and do (Actions)
Loop - Actions
Player - Add 1 to (Picked player) Current gold
Now you expect me to say it leaks, right? Actually it doesn’t, force all players never leaks, however other forces do leak. So if we change all player to:
(All players controlled by a User player)
We have a serious leak problem.
So, you should get the feeling by now what leaks and what doesn’t. However there is a point I want to make sure you understand. The more the leak repeats itself so it is worse. Thus a leak that will occur every 5 seconds is not nearly as bad as one that repeats every 0.01 seconds.
So we know what are leaks, how to detect them, and when they are the worst. Good. What can we do about it? Well all you need to do is add one minor line and you removed a leak. The first thing you do is open actions, go to -general and pick custom script (Triggers > Actions > -General > Custom Script). When you do that you have a place to type in a command. You might ask yourself, huh? Since when do we use text commands in World Editor?
Well let me tell you a secret, World Editor language, like any other programming language (as far as I know?) is made of text. When you program in World Editor you use a tool called GUI, however it is converted to text, which is called JASS. So when you open custom script you write down a JASS command.
Now the next question we ask is why do we use JASS command and not the GUI version of the command? Well there is a simple answer, not all JASS commands can be found in GUI, and removing leaks actions can’t be found in GUI so we must type them in JASS.
Ok, so now we understand why we have to type down the command and not simply find it in one of GUI’s many charts. But now you must wonder, what do we type? We need to type:
call command(udg_variable’s name[array])
What does that mean? Everything in bold will always be inside what you type (unless you use locals, you don’t need to know what that means now, just keep in mind that if you use local variable you need to remove the udg_).
So the first word is call. Call means we call a native function, which is a function that JASS can recognize. In other words, call starts the remove leak line. Next we put the command. The command is either RemoveLocation when we talk about point, DestroyForce when we talk about player group or DestroyGroup when we talk about a unit group. Next we put in (udg_ and then the variable’s name exactly like it is in the variable editor. If there is an array we type it and wrap it in [] and then to end the line we put a ). Make sure that there are no spaces between anything but the space between call and the command.
Now if you read this carefully you might have seen that you can only remove variable. What this mean? Let’s take our first example.
Code:
Events
Unit - A unit Dies
Conditions
Actions
Unit - Move (Triggering unit) instantly to (Center of (Playable map area))
And we want to remove the leak so we a start typing.
call RemoveLocation(udg_....), but what do we put where there is ….? How do we define the point? We can’t that’s why we have to put it inside a variable. So how would the trigger look like when properly removing the leak? Like this:
Code:
Untitled Trigger 001
Events
Unit - A unit Dies
Conditions
Actions
Set PointVariable = (Center of (Playable map area))
Unit - Move (Triggering unit) instantly to PointVariable
Custom script: call RemoveLocation(udg_PointVariable)
We set a point variable (PointVariable) to the wanted point, do with the point something and then remove it. In the same manner we do with Player Groups and Unit groups while changing variable type and the command after the call to DestroyForce or DestroyGroup.
Let’s see for a second however how can leaks removal destroy a trigger.
Code:
Untitled Trigger 001
Events
Unit - A unit Dies
Conditions
Actions
Set PointVariable = (Center of (Playable map area))
Custom script: call RemoveLocation(udg_PointVariable)
Unit - Move (Triggering unit) instantly to PointVariable
You see what we did here? We remove the point (thus the leak) before we used it. So when we order the unit to move to PointVariable, we removed it already from the computer’s memory, so now he can’t recognize it and it will return null ("nothing" in JASS language), thus the unit will not be moved.
Let’s check quickly the same example when using an array.
Code:
Untitled Trigger 001
Events
Unit - A unit Dies
Conditions
Actions
Set PointVariable[b][1][/b] = (Center of (Playable map area))
Unit - Move (Triggering unit) instantly to PointVariable[B][1][/B]
Custom script: call RemoveLocation(udg_PointVariable[b][1][/b])
Very simple. Again there is no difference between locations, groups and forces but the fact that we change the first word that comes after call.
Important note: YOU MAY NOT destroy a unit group inside itself and the same thing goes to player group. This is ILLIGAL:
Code:
Untitled Trigger 001
Events
Unit - A unit Dies
Conditions
Actions
Set GroupVar = (Units in (Playable map area))
Unit Group - Pick every unit in GroupVar and do (Actions)
Loop - Actions
Unit - Remove (Picked unit) from the game
Custom script: call DestroyGroup(udg_GroupVar)
This is ok:
Code:
Untitled Trigger 001
Events
Unit - A unit Dies
Conditions
Actions
Set GroupVar = (Units in (Playable map area))
Unit Group - Pick every unit in GroupVar and do (Actions)
Loop - Actions
Unit - Remove (Picked unit) from the game
Custom script: call DestroyGroup(udg_GroupVar)
You see? The removing line is OUTSIDE the loop actions.
So you might now say to yourself, huh this is really easy, why didn’t I understand it before? Well it is easy until we reach loop, which makes it a little more complicated, but still very easy once you understand the basics. Let’s start with a little challenge, what do you think out of those 2 would leak?
Code:
Untitled Trigger 001
Events
Unit - A unit Dies
Conditions
Actions
Set GroupVar = (Units in (Playable map area))
Unit Group - Pick every unit in GroupVar and do (Actions)
Loop - Actions
Set PointVariable = (Position of (Picked unit))
Unit - Move (Triggering unit) instantly to PointVariable
Custom script: call RemoveLocation(udg_PointVariable)
Custom script: call DestroyGroup(udg_GroupVar)
Or
Code:
Untitled Trigger 001
Events
Unit - A unit Dies
Conditions
Actions
Set GroupVar = (Units in (Playable map area))
Unit Group - Pick every unit in GroupVar and do (Actions)
Loop - Actions
Set PointVariable = (Position of (Picked unit))
Unit - Move (Triggering unit) instantly to PointVariable
Custom script: call RemoveLocation(udg_PointVariable)
Custom script: call DestroyGroup(udg_GroupVar)
If you thought that the second trigger would leak you are 100% right. Now why does it leak? If you notice we do: pick every unit in all units in the entire map. Thus we are most likely to the see actions inside the loop more then once. What does it mean? It means that rewrite PointVariable for every unit there is on the map, which causes a big leak. And then we remove the PointVariable OUTSIDE the loop, what will remove only the last defined PointVariable, what makes it utterly useless. However when we put the remove leak inside the loop, for each pointvariable we get, we also remove it, what stops the leaks.
JASS
Due do requests I decided to add this section and go over it quickly. First of all let's start with locals. If you started to learn JASS you probably know what local is. However there is a different method of removing locals. What we do is doing the exact same thing but we remove th udg_. udg_ means it is a global variable (user defined global), however when we talk about locals we don't want the computer to think we are talking about a global becuase it is a local variable. So what do we do?
call command(variable's name)
No udg_ as you can see.
Also few JASS commands that might help you.
Integer A in GUI = bj_forLoopAIndex
Integer B in GUI = bj_forLoopBIndex
Player number in GUI = GetConvertedPlayerId(takes player) // Palyers from JASS range from 0=11! 0=1, 1=2 etc. So if you get player's id I suggest you do GetConvertedPlayerId(some player) + 1.
Owner of unit in GUI = GetOwningPlayer(takes unit)
Triggering unit in GUI = GetTriggerUnit() // You must have the ()
Triggering player in GUI = GetTriggerPlayer() // You must have the ()
Lastly when talking about JASS we need to null handles (widgets(units,players,items),boolexprs etc.) this will be done by doing:
set Im_A_Handle = null