- Joined
- Oct 13, 2005
- Messages
- 233
Contents
Overview
Introduction to JASS
Lesson 1: A Simple Function
Lesson 2: Variables
Lesson 3: Functions
Lesson 4: If/Then/Else and loop structures
Lesson 5: Triggers in JASS
Lesson 6: Memory Leaks
Lesson 7: Starting a Spell in JASS
Lesson 8: Continuing the Spell
This tutorial series is being made by:
-darkwulfv
-moyack
-wyrmlord
Overview
Have you wanted to learn JASS, but haven't really had enough tutorials to walk you through the basics and beyond? The aim of this series of tutorials is to provide many tutorials to help a new user start from scratch and after going through the tutorials (and practicing a bit after) to have a fairly good understanding of JASS. "Lessons" are meant to be fairly small, and have only a few topics explained at once in an attempt to not overwhelm people trying to learn.
If anything in any of the tutorials isn't explained clearly enough, please say so. We want the tutorials to be as informative as possible, and an unclear point could ruin an entire lesson.
This tutorial series was originally posted at wc3campaigns. We decided to submit the tutorial series here on The Hive because we just recently found out that Daelin was unable to continue his JASS Classroom, so we thought it would be a good idea to have somewhere else for people to look to learn more than what Daelin had taught.
If you are interested, the attachment at the bottom contains all the tutorials in either .doc or .html format.
Good luck, and happy JASSing!
Introduction to JASS
Tutorial 1: Welcome to the world of JASS.
What is JASS?
-JASS is the programming language used by the Wc3 engine.
What is GUI?
-GUI stands for Graphic User Interface. It is the default crap used by the trigger editor, made to make triggering easier. Unfortunatly, Blizzard made it harder. GUI is bad. It uses BJ's (which will be covered later on), inneficient code, and is overall messy and limiting.
Why use JASS? Can't I just use GUI?
-Sure, you can use GUI. It's not recomended anymore, but it's not dead or nothing.
Here are the Pros of JASS:
-Easier to write out
-Faster, more effecient, and no leaks (when done properly that is)
-Breaks many restraints created by GUI
-Doesn't use BJ's (which again is possible when done correctly)
-Neater, easier on the eyes for longer triggers
-Easier to copy/paste, and can be edited in a text editor or 3rd-party editors (such as JASScraft)
-Generally faster to do when you get the hang of it. Much less clicking around.
However, you must be careful with JASS. As great as it is, it must be used correctly. One single mis-type can screw up an entire trigger.
Will it be hard to use?
-If you've programmed anything before, JASS will be much easier. Even if you haven't, its still pretty easy. It'll take some getting used to, and can be frustrating. You may even feel like reverting back to GUI, but don't. This is worth it. Very complex things will obviously be harder, but we're gonna start you off easy.
How do I get JASS in my editor?
-Make a trigger and name it. Then go to Edit -> Convert to Custom Text. This cannot be reversed. Now edit away!
I'm having trouble typing JASS in the WE!
-Use a 3rd party program for some help. JASScraft and Silly JASS Utility are 2 I would suggest for anyone. Both can be found on the site. JASScraft is perfect for editing your new JASS, since it gives function names, native lists, and Take/Return values, plus a good syntax checker, and more. Definatly a must-have.
When I try to save or test, I get a ton of errors!!
-You probably have a typo or two somewhere, or an unexistant function. Check all your code and JASS is VERY case sensitive. If you type an "A" where an "a" should be, you will get an error. Also, check to make sure there aren't other errors. JASScraft can assist you here. That's why we recommend editing your codes in JASScraft. Much much much easier.
So what's the first step to learning JASS?
-Forget everything you know about GUI, except for globals. JASS is far different from GUI, and trying to compare them is a bad idea. However, a good first step is to make some triggers in GUI, then make them JASS. Throw them into JASScraft and have a ball converting BJ's to natives and cleaning leaks. You'll learn fast. It definatly helps the crossover from GUI to JASS.
Ok, I know the basics. Now what?
-If you want to learn more, read ahead to tutorial #2, by Wyrmlord. He'll teach you the basics of functions. Or, you can go ahead and take it alone from here. The choice is yours. Either way, I wish you good luck!
~Darkwulfv
Lesson 1: A Simple Function
Overview
In this lesson, I will go over with you a very simple function example. I will explain everything you will need to know about it and then at the end I will give you a 'challenge'. This challenge contains some content from the next section, so you will be able
to find out your answer in Lesson 2.
Now that you've looked at an introduction to the advantages of JASS, you're probably eager to get started with some code, right? Now, forget GUI (regular 'triggers'), JASS is different from GUI, so I'll be treating
it that way. Now, open up a text editor of some sort such as Notepad (windows) or some other program
depending on your operating system.
Now, I'm going to show some code. It will be a bit confusing at first, but I'll explain it throughout this lesson.
Now, don't put this into the editor yet as it's not complete. First off, I'll start with the first line.
JASS, like many programming languages, is made up of a series of functions. I won't go into detail
on that yet, but for now just know that you are declaring/creating a function.
Now, the next line:
This particular line 'calls' a function. Functions are like actions if you've used GUI before, they execute a command. This particular function puts the text "Hello World" (without the quotes) onto the screen.
Now, the final line is pretty simple, when you declare/create a function it needs to end somewhere, right? This line just tells you that the function ends here.
Now, I've gone over with you a very basic example of JASS, if you wish to test this function in the World Editor, simply:
-Create a new map
-Go to the trigger editor
-Click on the map icon at the top of the list of triggers
-Paste the code in the custom script section.
Now, create a trigger (sorry for the GUI reference), you can make the event whatever you want, I'd suggest that you make it go off whenever you press an arrow key. Now, for the action, just find custom script, and in the box
that it gives you, type:
And there you have it, you can now test the function in the game.
Notice how you call a function in that line. I'm now going to go over the function declarations a bit.
When you call a function, you type 'call <function_name>( <parameter1>, <parameter2>, <parameterN> )'
What this basically says is that you type call, while is followed by the name of the function and parenthesis '()'. If the function needs certain info (known as parameters) you put that specific info inside the parenthesis. Each set of 'info' is separated by a comma ','
This particular function only needed a string (message) to display on the screen. Here's some more info:
When a function has the text 'takes nothing', that means you don't need anything in the parenthesis when calling it.
The return value is a value that the function returns. Like the CreateUnit function returns a unit. If you're confused, don't worry as this will be covered in a later lesson.
Now, feel free to mess around with the HelloWorld function, add more calls to the BJDebugMsg, show whatever text you want. Let me say that for now, the text should be inside quotation marks "like this"
Challenge #1: Modify the HelloWorld function to print out other info:
Here's an example:
This may seem like a waste of time, but the more you use JASS the more familiar it will become.
Good Luck -wyrmlord
Lesson 2: Variables
By: Darkwulfv
What is a variable?
-A variable is sort of like a place holder for a handle or other object. There are 2 types of variables. Local and Global.
What is the difference between Local and Global variables?
-Local variables are variables only usable by the function they’re declared in. These are used for cleaning Memory Leaks (which will be explained later), neatening code, and making script Multi-instanceable.
-Globals are variables which can be accessed by any function, but can also be changed by any function. This can be bad for multi-instanceability (which will now be referred to as MUI), depending. MUI will be discussed later on.
How do I create a local variable?
-There are two ways to creating/setting a variable.
This method creates and sets it in one line, at the beginning of the function.
And this method creates a blank variable, to be set later on in the function.
Hey wait! I want the value to change, does that mean I need a new variable?
-No, not necessarily. All you need to do is put “set your_variable = newvalue
Here’s an example.
Remember though, that old value isn’t set to that variable, so if you want 2 different units, use 2 different variables.
Ok, so I have my local variable. Now what?
-Now, use it! Here’s an example.
-If you notice, KillUnit needs a unit. Now, you can fill this with many things, like GetTriggerUnit(), GetSpellAbilityUnit(), or any function which returns a unit. However, a variable can be a unit, so you can put that there instead. Here’s a side-by-side comparison.
They both work, it's up to you to choose which way you prefer.
What about global variables?
-Global variables are created through the Variable Editor, inside the Trigger Editor. These variables can be used in any function, unlike locals. Example:
This is basically what it means. A variable starting with “udg_” usually means it is global. You can do this sort of thing with locals, but it isn't advised. If you need to refer to the same unit in a different function, there are methods of doing so which will be discussed later. The names of the variables you create are udg_variable_name. Each space in the variable name you enter in should be referred to with an underscore '_'
You mentioned Memory Leaks, what are those?
-Although these will be discussed in full later, it is good that you know now.
So how do I fix Memory Leaks?
I saw an option to make the variable an array. What’s that mean?
-An array is a variable with more than one option, per say. It’s like an index of that variable type, sort of like a library. To access the variables, you must set them to an index number, then retrieve them as such.
Example:
There is an easier way to assign index numbers and null them. It involves integers and loops, and will be shown during the discussion of loops.
Functions can also be fit into those brackets [] to set it to a number; any function that returns an integer or real should cover it.
There you have it! Variables in a nutshell. If you want to see a list of all the variables, open up either common.j in the Patch.mpq file. Or if you're not sure how to do that, get a tool like JassCraft, and on the right side of the screen when you open it up is a search box and a long list. On the bottom of that list is "show options". Click that, and then uncheck everything in the "search for" box except types. You can now click "hide options" and search through the types of variables.
CHALLENGE:
Can you fill in this code with the correct variables? (this does not involve arrays)
The “_”’s represent where something needs to be filled in.
Good luck, and happy JASSing!
~Darkwulfv
Lesson 3: Functions
Overview
In this lesson, I will be going over how to:
1.Create functions
2.Call functions
3.Anything else I can think of
Part 1: Creating a function
Now, you're probably wanting to know how to create functions, right? Well, to create functions, you first need to tell the program that you're creating a function, so you do that by delcaring a function. This is basically telling the program the function's name, what values it needs to get when called, and what it returns. Take a look at this function:
Now, the word 'function' tells the program that you will be declaring a function. The next part of the function is the name of the function. You need to make sure your function has a unique name that no other function has, otherwise you'll get errors when saving a map. Next, you tell the program what the function 'takes' or needs pretty much. This function 'takes' a string, which is basically a message of some sort. After you put the type the function needs, you then have to put a name for it (so you can refer to it inside of your function). Lastly, you tell the program the type the function will return. You could make this a string, integer, real, and so on. However for this example, no value will be returned so we put 'nothing'.
After declaring a function, inside the function you need to put what the function does, otherwise it would be pretty useless. This function simply calls another function using the string value that is needed to call it. Lastly, you need to tell the program when the function ends, you do this by putting 'endfunction' at the end of the function.
Part 2: Calling functions
Now, that may not all make sense, so I'll now explain how you call functions, which should hopefully clear things up a bit. First off, you can call a function in a few different ways, but I'll start by the easiest way, which is using the word 'call'.
This line would call the function I just showed you. When calling a function this way, you need to have the word 'call' followed by the function name which is then followed by parenthesis with the values the function takes inside of them. If a function takes multiple values, they are each separated by a comma ','. It works that same way when declaring functions too (whoops forgot to mention that earlier =P)
Now, I will go over what the return values in functions are. They're pretty simple really, though I don't want anyone to be confused about anything. When a function has a return value, you can set variables that are the same type as the return value to that function. Here's an example:
Now, see that when you set a variable to the return value of a function, you don't need the word 'call'. Also, if you want to pass the return value of a function into another function call, you don't need to put the word 'call' either, as seen with the Player function that was the needed parameter in the GetPlayerName function.
If when and when not to use call are confusing you, let me just say you can only have 1 call in a line, and call can't be used if you have another word before that such as 'set' or you're declaring a local variable.
Also, and this is important when declaring a function, if the function declaration states that the function returns a value, somewhere in the function if must have a line that 'returns' the value, like so:
When a function reaches the line with return on it, it returns the specified value and ends (no code below that line is looked at by Wc3)
There is one last thing you need to know when calling functions, you can only call a function that is above another, since that may not make complete sense, here's an example:
Now, this is only used as a visual example so I can more easily describe what I was saying. You can only call a function that is above the function you are currently in. So, 'SomeOtherFunction' would be able to call 'SomeFunction'. However, 'SomeFunction' wouldn't be able to call 'SomeOtherFunction'.
Challenge Time!
Now, I figure you're wondering why the challenges so far aren't very hard (I'm just assuming that), and that's because we haven't taught you enough for us to really stump you on something. I hope this challenge will make you think more than normal. The following code has a few errors in it, find each error in it. There are 5 errors in the following code, can you find them all?
Good Luck -wyrmlord
Lesson 4: if/then/else and loop structures
Tutorial No 4. if/then/else and loop structures. By Moyack.
These kind of structures are the most important in any programming language. In JASS, these structures are quite versatile and useful.
Let's see the first structure: IF/THEN/ELSE
To work with it, we can write it in this way.
if/then/else structure
Now you understand why I said versatile
As you can see, the conditions must be a function which has to return a boolean variable type (true/false) or a boolean variable. Other interesting feature with the if/then/else structure in JASS, is that it can be used as a multiselection structure too, something very useful in many cases.
In order to ensure the understanding of this structure, This is a small example showing the IF/THEN/ELSE in action
IF/THEN/ELSE example
Here we are using a local variable which will have a value according to the input argument in the function, and then that variable will be returned by the function.
Now let's see the LOOP structure.
Loops in programming are used to make a set of instructions to be executed several times, loops can be classified by finite and infinite. The finite loops are which have a defined a fixed number of repetitive executions, controlled by an exit control. The Infinite loops in the other hand, will execute the script contained in it indefinitely.
The loop structure is as following:
This structure is quite flexible as you can see, because you can put the exitwhen condition in ANY place inside the loop. Let's see an example.
Loop Example
The usage of FirstOfGroup and group functions inside a loop is very common in AOE spells, with them we can do several things to a unit group.
Good luck :
Lesson 5: Triggers in JASS
Overview
Now, if all you've ever known is GUI, you're used to everything being a trigger. GUI is just a system of triggers, but you're probably wondering what exactly is a trigger. This lesson will cover triggers in JASS and how to use them. First, I'd like to tell you exactly what a trigger is.
What is a Trigger?
I'm sure that you know what a trigger is if you've used GUI before, but GUI hides some important things from you. A trigger is really just another object, like a unit or a special effect. What makes triggers useful is that they are able to detect events. Without triggers, you couldn't do too much in the editor without a lot of trouble. Now, here's an example of making a trigger in JASS:\
Now, this may be a bit overwhelming at first, but I'll explain everything well enough so that you should understand. First off, you're going to create a local variable for the trigger. This is fine if you don't need other triggers to run TriggerExecute on this trigger (TriggerExecute is a function that runs a trigger). Now, whenever you create a new trigger, you must use the function CreateTrigger(). It's like using the CreateUnit function to create a unit. Now that you have created a trigger, you'll need to add some things to it so it would be useful. The next line adds an event to the trigger. TriggerRegisterPlayerEvent takes 3 values, which are the trigger you want to add the event to, the player this event applies to, and the specific event. There are many other TriggerRegister... functions which you can experiment with later, but for now this will be fine. The next line adds an action which is basically telling the trigger to call that function when the event happens. Now, I didn't show you the function MyFunction, but you need to know that it must take nothing and return nothing. Now, the final line sets the local variable to null, which is necessary for local variables which are handles so that memory leaks can be prevented. If you don't know what a memory leak is, don't worry about it, they will be covered in a later tutorial.
Okay, now you're probably still using that GUI trigger to run your test functions in the custom script. This JASS trigger does pretty much the exact same thing as the GUI trigger, so you can replace it. Just create a new trigger, and then go to Edit -> Convert to Custom Text. What you will see is something similar to the function shown above, only it's setting a global variable automatically generated by the editor to a trigger and just adding an action. Delete all the code and make a new function that has the name: InitTrig_[insert trigger name here]. So if the name of your trigger was JASSTrigger, you would have your function be: function InitTrig_JASSTrigger takes nothing returns nothing It's important that you name it this way so that it gets called while the map is loading.
Now, if you've noticed, I've left out how to add a condition, oh my! Well, I'll show you how adding conditions work in triggers. Don't convert a GUI trigger to JASS to see how to do conditions, that way is inefficient. There's more code than you really need to use. Let me show you an example:
This might look confusing, it might not. Either way I'm going to review what everything does. First off, I'll review how to set up a function so it can be used as a condition in a trigger. First off, you can name the function whatever you want, but it has to take nothing and return boolean. A boolean value, as you should know, is true/false. This function returns GetTriggerPlayer() == Player(0). You might look at that and be clueless, others might understand it already. The first part gets the player who triggered the event (the player pressing escape). And finally, the == Player(0) part checks if the player is Player(0) (Player 1 (Red)). Since this is a boolean statement, meaning it is either true or false, it can be used as a return value.
Finally, we have the added line in the InitTrig_JASSTrigger function. The function TriggerAddCondition takes a trigger and a boolexpr (boolean expression) . You don't need to know what a boolexpr is yet, all you need to know is that you put Condition(function [insert trigger name here]) and it returns a boolexpr which is used for conditions in triggers.
Challenge
This challenge will require a bit of researching JASS functions, so I recommend you get a tool such as JassCraft. Well, I'll give you three possible challenges. The first challenge will to be to create a trigger in JASS that will run a function that you create (any). After you've messed with that a bit, open up JassCraft or a similar program where you can search JASS functions. You're next challenge will be to create a trigger that will go off whenever you type in "-run" or whatever kind of text message in-game. I'll give you some help in telling you that the function you're looking for to add the event is TriggerRegisterPlayerChatEvent, however it's up to you to figure out how to use it. If you've solved that challenge, then make a trigger that goes off when the message a player types contains the character "-" or whatever letter you choose. In the actions, you will then display the value the message the player typed in. Hints for this challenge are keep using the same function to add the event, only you need to change a value or two. And I suppose it would also be helpful to tell you that the GetEventPlayerChatString can be used to get the string that the player types in.
Good Luck -wyrmlord
Lesson 6: Memory Leaks
Lesson 6: Memory Leaks
By: Darkwulfv, edited by wyrmlord
What is a memory leak?
-A memory leak is caused by bad coding, where a handle that was stored in memory is lost from refrence. Basically, it’s something that got placed in wc3’s memory usage and never got removed, and is unable to be removed.
What does a memory leak do?
-A memory leak adds a little tiny bit of memory usage to Wc3 when it’s running. If enough memory leaks, your map is going to cause some serious lag.
What causes memory leaks?
-When a handle is created, it's stored it in Wc3’s memory. If it is not destroyed or removed when you are done with it, then it stays there, taking up memory.
Well how am I supposed to fix them?
-Well, there are a few ways to do so, depending.
Method #1:
=============================
=============================
The native AddSpecialEffect(…) creates an effect. If you do not destroy this effect with the proper function, it will stay embedded in the memory, and thus take up memory. Now, one leak is terribly insignificant. But if your map made a lot of leaks very often, you would notice a big change.
Here’s a way to fix that leak:
This method goes for anytime you are using a handle(any variable that isn’t a real, integer, boolean, boolexpr, code, or string)
However, the destroying/removing function changes for each type of handle. A list of variable types and how to remove them will be given later for you to refer to.
NOTE: When destroying/removing an object, you are removing/destroying a specific object and not the variable itself. The variable just points to the location in memory where the object is stored.
NOTE: A leak can be defined as an object that is created, not removed, unable to be removed during the game (assuming not removing it is undesired). If it’s only used once (like dummy units, rects, groups, etc.) then remove it. If not, you should leave it. (Like for spells, don’t remove the caster!)
NOTE: All non-handle variables except strings do not leak. String leaks cannot be fixed, but you usually don't need to worry about them.
So memory leaks only apply when you create things?
-WRONG!
A memory leak not only happens when you create things. It also happens when you make a handle-variable, set it to a value, and don’t null it.
Example:
This example wouldn't leak, as the handle variable wasn't set to a value. However, if it had been set to a value, like:
It would leak. To fix this, set your variable to null. (Reals, integers, and booleans cannot be nulled, and don't need to be as the memory they use is automatically removed)
To null a variable, simply put
set yourvariable = null
You don't need to set a variable to null after removing each object. You only need to null it once; this is usually done at the end of a function.
NOTE: To satisfy those wanting to know why handle variables leak (not referring to the object, I'm referring to the variable). When you set a handle equal to a value, the handle points to where that value is stored in memory. It will remain pointing to where that value is stored unless it is set to null (meaning 0, not pointing to a specific place in memory.)
What about globals?
-Since these are always in the memory to begin with, and are always available, they don't count as leaks (and don't need to be nulled).
So uh… What do I do about non-handle variables?
-They don’t leak though, so worry not.
Conclusion:
-Always clean leaks. If you don’t, and there’s enough leaks, you will notice the effects.
Challenge!
-Clean this function of all memory leaks:
Good luck!
Overview
Introduction to JASS
Lesson 1: A Simple Function
Lesson 2: Variables
Lesson 3: Functions
Lesson 4: If/Then/Else and loop structures
Lesson 5: Triggers in JASS
Lesson 6: Memory Leaks
Lesson 7: Starting a Spell in JASS
Lesson 8: Continuing the Spell
This tutorial series is being made by:
-darkwulfv
-moyack
-wyrmlord
Overview
Have you wanted to learn JASS, but haven't really had enough tutorials to walk you through the basics and beyond? The aim of this series of tutorials is to provide many tutorials to help a new user start from scratch and after going through the tutorials (and practicing a bit after) to have a fairly good understanding of JASS. "Lessons" are meant to be fairly small, and have only a few topics explained at once in an attempt to not overwhelm people trying to learn.
If anything in any of the tutorials isn't explained clearly enough, please say so. We want the tutorials to be as informative as possible, and an unclear point could ruin an entire lesson.
This tutorial series was originally posted at wc3campaigns. We decided to submit the tutorial series here on The Hive because we just recently found out that Daelin was unable to continue his JASS Classroom, so we thought it would be a good idea to have somewhere else for people to look to learn more than what Daelin had taught.
If you are interested, the attachment at the bottom contains all the tutorials in either .doc or .html format.
Good luck, and happy JASSing!
Introduction to JASS
Tutorial 1: Welcome to the world of JASS.
What is JASS?
-JASS is the programming language used by the Wc3 engine.
What is GUI?
-GUI stands for Graphic User Interface. It is the default crap used by the trigger editor, made to make triggering easier. Unfortunatly, Blizzard made it harder. GUI is bad. It uses BJ's (which will be covered later on), inneficient code, and is overall messy and limiting.
Why use JASS? Can't I just use GUI?
-Sure, you can use GUI. It's not recomended anymore, but it's not dead or nothing.
Here are the Pros of JASS:
-Easier to write out
-Faster, more effecient, and no leaks (when done properly that is)
-Breaks many restraints created by GUI
-Doesn't use BJ's (which again is possible when done correctly)
-Neater, easier on the eyes for longer triggers
-Easier to copy/paste, and can be edited in a text editor or 3rd-party editors (such as JASScraft)
-Generally faster to do when you get the hang of it. Much less clicking around.
However, you must be careful with JASS. As great as it is, it must be used correctly. One single mis-type can screw up an entire trigger.
Will it be hard to use?
-If you've programmed anything before, JASS will be much easier. Even if you haven't, its still pretty easy. It'll take some getting used to, and can be frustrating. You may even feel like reverting back to GUI, but don't. This is worth it. Very complex things will obviously be harder, but we're gonna start you off easy.
How do I get JASS in my editor?
-Make a trigger and name it. Then go to Edit -> Convert to Custom Text. This cannot be reversed. Now edit away!
I'm having trouble typing JASS in the WE!
-Use a 3rd party program for some help. JASScraft and Silly JASS Utility are 2 I would suggest for anyone. Both can be found on the site. JASScraft is perfect for editing your new JASS, since it gives function names, native lists, and Take/Return values, plus a good syntax checker, and more. Definatly a must-have.
When I try to save or test, I get a ton of errors!!
-You probably have a typo or two somewhere, or an unexistant function. Check all your code and JASS is VERY case sensitive. If you type an "A" where an "a" should be, you will get an error. Also, check to make sure there aren't other errors. JASScraft can assist you here. That's why we recommend editing your codes in JASScraft. Much much much easier.
So what's the first step to learning JASS?
-Forget everything you know about GUI, except for globals. JASS is far different from GUI, and trying to compare them is a bad idea. However, a good first step is to make some triggers in GUI, then make them JASS. Throw them into JASScraft and have a ball converting BJ's to natives and cleaning leaks. You'll learn fast. It definatly helps the crossover from GUI to JASS.
Ok, I know the basics. Now what?
-If you want to learn more, read ahead to tutorial #2, by Wyrmlord. He'll teach you the basics of functions. Or, you can go ahead and take it alone from here. The choice is yours. Either way, I wish you good luck!
~Darkwulfv
Lesson 1: A Simple Function
Overview
In this lesson, I will go over with you a very simple function example. I will explain everything you will need to know about it and then at the end I will give you a 'challenge'. This challenge contains some content from the next section, so you will be able
to find out your answer in Lesson 2.
Now that you've looked at an introduction to the advantages of JASS, you're probably eager to get started with some code, right? Now, forget GUI (regular 'triggers'), JASS is different from GUI, so I'll be treating
it that way. Now, open up a text editor of some sort such as Notepad (windows) or some other program
depending on your operating system.
Now, I'm going to show some code. It will be a bit confusing at first, but I'll explain it throughout this lesson.
JASS:
function HelloWorld takes nothing returns nothing
call BJDebugMsg("Hello World")
endfunction
Now, don't put this into the editor yet as it's not complete. First off, I'll start with the first line.
JASS, like many programming languages, is made up of a series of functions. I won't go into detail
on that yet, but for now just know that you are declaring/creating a function.
Now, the next line:
JASS:
call BJDebugMsg("Hello World")
This particular line 'calls' a function. Functions are like actions if you've used GUI before, they execute a command. This particular function puts the text "Hello World" (without the quotes) onto the screen.
JASS:
endfunction
Now, the final line is pretty simple, when you declare/create a function it needs to end somewhere, right? This line just tells you that the function ends here.
Now, I've gone over with you a very basic example of JASS, if you wish to test this function in the World Editor, simply:
-Create a new map
-Go to the trigger editor
-Click on the map icon at the top of the list of triggers
-Paste the code in the custom script section.
Now, create a trigger (sorry for the GUI reference), you can make the event whatever you want, I'd suggest that you make it go off whenever you press an arrow key. Now, for the action, just find custom script, and in the box
that it gives you, type:
JASS:
call HelloWorld()
And there you have it, you can now test the function in the game.
Notice how you call a function in that line. I'm now going to go over the function declarations a bit.
When you call a function, you type 'call <function_name>( <parameter1>, <parameter2>, <parameterN> )'
What this basically says is that you type call, while is followed by the name of the function and parenthesis '()'. If the function needs certain info (known as parameters) you put that specific info inside the parenthesis. Each set of 'info' is separated by a comma ','
This particular function only needed a string (message) to display on the screen. Here's some more info:
JASS:
function HelloWorld takes nothing returns nothing
When a function has the text 'takes nothing', that means you don't need anything in the parenthesis when calling it.
The return value is a value that the function returns. Like the CreateUnit function returns a unit. If you're confused, don't worry as this will be covered in a later lesson.
Now, feel free to mess around with the HelloWorld function, add more calls to the BJDebugMsg, show whatever text you want. Let me say that for now, the text should be inside quotation marks "like this"
Challenge #1: Modify the HelloWorld function to print out other info:
Here's an example:
JASS:
function HelloWorld takes nothing returns nothing
call BJDebugMsg("Hi, my name is Bob.")
call BJDebugMsg("I am 2 years old!")
//And so on, by the way you can add comments to your code like this
//Basically if you have '//' somewhere on a line, the rest of the line (after the '//') counts as a comment
endfunction
This may seem like a waste of time, but the more you use JASS the more familiar it will become.
Good Luck -wyrmlord
Lesson 2: Variables
By: Darkwulfv
What is a variable?
-A variable is sort of like a place holder for a handle or other object. There are 2 types of variables. Local and Global.
What is the difference between Local and Global variables?
-Local variables are variables only usable by the function they’re declared in. These are used for cleaning Memory Leaks (which will be explained later), neatening code, and making script Multi-instanceable.
-Globals are variables which can be accessed by any function, but can also be changed by any function. This can be bad for multi-instanceability (which will now be referred to as MUI), depending. MUI will be discussed later on.
How do I create a local variable?
-There are two ways to creating/setting a variable.
JASS:
function variable_test takes nothing returns nothing
local unit u = CreateUnit()
endfunction
JASS:
function variable_test takes nothing returns nothing
local unit u
set u = CreateUnit(…..) //Creates a unit and sets the variable to it
endfunction
Hey wait! I want the value to change, does that mean I need a new variable?
-No, not necessarily. All you need to do is put “set your_variable = newvalue
Here’s an example.
JASS:
function variable takes nothing returns nothing
local unit u = CreateUnit(…)
//Other actions
set u = other_unit //other_unit would be some other unit, don't use this example literally!
endfunction
Remember though, that old value isn’t set to that variable, so if you want 2 different units, use 2 different variables.
Ok, so I have my local variable. Now what?
-Now, use it! Here’s an example.
JASS:
function KillUnit takes unit u returns nothing
JASS:
function variable_testA takes nothing returns nothing
local unit u = GetTriggerUnit()
call KillUnit(u)
endfunction
function variable_testB takes nothing returns nothing
call KillUnit(GetTriggerUnit())
endfunction
Naming variablesWhen naming variables, you can't just use any name. First off, the only characters you can use are any letter in the alphabet, any number, and the underscore character (_). The first letter in a variable name must be a letter, after that you can use numbers, letters, and underscores all you want. Let me make it clear that you can not use spaces in a variable name.
-Global variables are created through the Variable Editor, inside the Trigger Editor. These variables can be used in any function, unlike locals. Example:
JASS:
function A takes nothing returns nothing
call KillUnit(udg_u)
endfunction
function B takes nothing returns nothing
call KillUnit(udg_u)
endfunction
You mentioned Memory Leaks, what are those?
-Although these will be discussed in full later, it is good that you know now.
Edit by wyrmlordWhenever a variable, handle, or string is created, the game must set aside space for it to use. To get rid of that space, there are various methods you can use depending on the object. For example, if you had a special effect, you could destroy it and free up any space it was using. Memory leaks occur when an object isn't able to be destroyed, and it will stay in memory until the end of the game. Another example: suppose I create another special effect, and no variable is set to it. The special effect will use up memory (even if it can't be seen), and since it's unable to be destroyed, it will continue to use memory until the end of the game. Local variables that aren't integers, reals, or boolean are like this too. The fix to them is simply setting them equal to null at the end of a function. Strings use up memory as well, but you can't do anything to stop them from doing so.
Edit by wyrmlordMemory leaks will be gone over in a later tutorial. If you're eager to learn about them, by all means skip to the lesson on memory leaks. However, I wouldn't suggest doing any major amounts of coding until you know more about them
-An array is a variable with more than one option, per say. It’s like an index of that variable type, sort of like a library. To access the variables, you must set them to an index number, then retrieve them as such.
Example:
JASS:
function variable_test takes nothing returns nothing
local unit array u
set u[1] = GetTriggerUnit()
set u[2] = GetSpellTargetUnit()
call KillUnit(u[1])
call KillUnit(u[2])
set u[1] = null
set u[2] = null
endfunction
Functions can also be fit into those brackets [] to set it to a number; any function that returns an integer or real should cover it.
Edit by wyrmlordThis is just to have multiple explanations of the same thing, for possibly confused readers. Arrays are basically a lot of variables squeezed into one. To be exact, 8192 variables. To declare an array in JASS, you would do something like this:
The difference is really just adding the word "array" before the variable name. You are unable to set the array to a value on the same line that you create it, keep in mind. Now, you'll need to know how to access each of the 8192 parts of the array. You do that like a normal variable, only you have brackets after the variable with an integer between them, which would be a number from 0 to 8191. If that's a bit confusing, here's an example:JASS:local integer array int_array
I would not recommend using arrays for a purpose as small as this. An array contains 8192 values, no more and no less. For something like this it's like killing a fly with a bazooka. (In other words, don't use arrays unless they are actually needed)JASS:local integer array myIntegers //declaring the integer array set myIntegers[0] = 5 //Setting the 0th slot in the array to 5 set myIntegers[1] = myIntegers[0] + 2 //Setting the 1st slot in the array to the value in the 0th slot in the array + 2 set myIntegers[myIntegers[1]] = 2 //This is just showing that you can use a variable inside the brackets as well, it doesn't have to be an array though
Edit by wyrmlord
There are a few main variable types: integer, real, string, boolean, and handle. I'm sure you know what an integer is, it's a whole number (including negatives) such as: 1, 145, -37. A real is a number with decimal places such as: 3.14, -15.78, 11.1134. A string, as you might already know can be thought of as a message or text: "Hello", "This is a string". A boolean has two values: true or false. A handle, you could say, is a reference to an object such as a unit. You don't direct use the handle type usually, but you use types that extend the handle type. This basically means that they are a specific type of handle. A handle is pretty much anything that isn't an integer, real, string, boolean. Handles include: units, special effects, timers, groups, players, and so on.
Can you fill in this code with the correct variables? (this does not involve arrays)
The “_”’s represent where something needs to be filled in.
JASS:
function variable_challenge takes nothing returns nothing
local ____ _ = GetTriggerUnit()
call KillUnit(_)
set _ = ____
endfunction
Good luck, and happy JASSing!
~Darkwulfv
Lesson 3: Functions
Overview
In this lesson, I will be going over how to:
1.Create functions
2.Call functions
3.Anything else I can think of
Part 1: Creating a function
Now, you're probably wanting to know how to create functions, right? Well, to create functions, you first need to tell the program that you're creating a function, so you do that by delcaring a function. This is basically telling the program the function's name, what values it needs to get when called, and what it returns. Take a look at this function:
JASS:
function DisplayAMessage takes string message returns nothing
call BJDebugMsg(message)
endfunction
Now, the word 'function' tells the program that you will be declaring a function. The next part of the function is the name of the function. You need to make sure your function has a unique name that no other function has, otherwise you'll get errors when saving a map. Next, you tell the program what the function 'takes' or needs pretty much. This function 'takes' a string, which is basically a message of some sort. After you put the type the function needs, you then have to put a name for it (so you can refer to it inside of your function). Lastly, you tell the program the type the function will return. You could make this a string, integer, real, and so on. However for this example, no value will be returned so we put 'nothing'.
After declaring a function, inside the function you need to put what the function does, otherwise it would be pretty useless. This function simply calls another function using the string value that is needed to call it. Lastly, you need to tell the program when the function ends, you do this by putting 'endfunction' at the end of the function.
Part 2: Calling functions
Now, that may not all make sense, so I'll now explain how you call functions, which should hopefully clear things up a bit. First off, you can call a function in a few different ways, but I'll start by the easiest way, which is using the word 'call'.
JASS:
call DisplayAMessage("hello")
This line would call the function I just showed you. When calling a function this way, you need to have the word 'call' followed by the function name which is then followed by parenthesis with the values the function takes inside of them. If a function takes multiple values, they are each separated by a comma ','. It works that same way when declaring functions too (whoops forgot to mention that earlier =P)
Now, I will go over what the return values in functions are. They're pretty simple really, though I don't want anyone to be confused about anything. When a function has a return value, you can set variables that are the same type as the return value to that function. Here's an example:
JASS:
local string player_name = GetPlayerName(Player(0))
Now, see that when you set a variable to the return value of a function, you don't need the word 'call'. Also, if you want to pass the return value of a function into another function call, you don't need to put the word 'call' either, as seen with the Player function that was the needed parameter in the GetPlayerName function.
If when and when not to use call are confusing you, let me just say you can only have 1 call in a line, and call can't be used if you have another word before that such as 'set' or you're declaring a local variable.
Also, and this is important when declaring a function, if the function declaration states that the function returns a value, somewhere in the function if must have a line that 'returns' the value, like so:
JASS:
function TestReturn takes nothing returns integer
return 5
endfunction
When a function reaches the line with return on it, it returns the specified value and ends (no code below that line is looked at by Wc3)
There is one last thing you need to know when calling functions, you can only call a function that is above another, since that may not make complete sense, here's an example:
JASS:
function SomeFunction takes nothing returns nothing
endfunction
function SomeOtherFunction takes nothing returns nothing
endfunction
Now, this is only used as a visual example so I can more easily describe what I was saying. You can only call a function that is above the function you are currently in. So, 'SomeOtherFunction' would be able to call 'SomeFunction'. However, 'SomeFunction' wouldn't be able to call 'SomeOtherFunction'.
Challenge Time!
Now, I figure you're wondering why the challenges so far aren't very hard (I'm just assuming that), and that's because we haven't taught you enough for us to really stump you on something. I hope this challenge will make you think more than normal. The following code has a few errors in it, find each error in it. There are 5 errors in the following code, can you find them all?
JASS:
function Function2 takes nothing returns string
local string message = SomeFunction("Hello World")
endfunction
function SomeFunction takes string returns nothing
local string a message
a message = 'Something is wrong'
call DisplayTextToPlayer(Player(0), 0, 0, a message)
endfunction
Good Luck -wyrmlord
Lesson 4: if/then/else and loop structures
Tutorial No 4. if/then/else and loop structures. By Moyack.
These kind of structures are the most important in any programming language. In JASS, these structures are quite versatile and useful.
Let's see the first structure: IF/THEN/ELSE
To work with it, we can write it in this way.
if/then/else structure
JASS:
if <condition 1 function or variable> then
<Condition 1 script>
elseif <condition 2 function or variable> then
<Condition 2 script>
...
else
<Else condition script>
endif
Now you understand why I said versatile
As you can see, the conditions must be a function which has to return a boolean variable type (true/false) or a boolean variable. Other interesting feature with the if/then/else structure in JASS, is that it can be used as a multiselection structure too, something very useful in many cases.
In order to ensure the understanding of this structure, This is a small example showing the IF/THEN/ELSE in action
IF/THEN/ELSE example
JASS:
function Set_Damage_To_Unit takes integer level returns real
// this example will set the damage amount in a spell, according to a level
// (unit level, ability level, etc)
local real dam
if level < 2 then
set dam = 0
elseif level == 1 then
set dam = 50.
// probably you noticed the point after the number. this is used to indicate the number is a real one.
// Is a good programming practice to do that in order to avoid annoying debugging mistakes.
elseif level == 2 then
set dam = 63.
elseif level == 3 then
set dam = 125.
else
set dam = 125. + 50. * (level - 1)
return dam
endfunction
Here we are using a local variable which will have a value according to the input argument in the function, and then that variable will be returned by the function.
Important noteIf any IF or ELSEIF clauses apply, then the ELSE clause will be avoided. This example function has a bug by purpose, in order to show an IF/THEN/ELSE characteristic. if level = 1, then the first clause will be executed (set dam = 0). Then the second condition will be executed and will be true too (elseif level == 1), then it will execute the second clause (set dam = 50). With that we can see that the IFTHENELSE structure can be used to make data filtering, for instance.
Another Important NoteThe '=' character is used when setting a value, the '==' operator is used when comparing values. In other words, don't do: if x = 5 then... because Wc3 can't read your mind as to what you want it to really do. This line is saying to the computer "if (set x = 5) then..." and I don't think that makes much sense, how about you?
Loops in programming are used to make a set of instructions to be executed several times, loops can be classified by finite and infinite. The finite loops are which have a defined a fixed number of repetitive executions, controlled by an exit control. The Infinite loops in the other hand, will execute the script contained in it indefinitely.
The loop structure is as following:
JASS:
loop
//Here you can put code too :)
exitwhen <condition function or variable>
//your iterative script
endloop
This structure is quite flexible as you can see, because you can put the exitwhen condition in ANY place inside the loop. Let's see an example.
Loop Example
JASS:
function Heal_Unit_Group takes group g returns nothing
// this example will heal all units in a unit group.
local unit u // a local unit variable
loop
set u = FirstOfGroup(g) //Selects the first unit in the group.
exitwhen u == null // the loop will finish when the group will be empty,
// in tother words, when the FirstOfGroup() function returns null
call SetUnitState(u, UNIT_STATE_LIFE, GetUnitState(u, UNIT_STATE_MAX_LIFE))
//sets the life of the selected unit at its maximum.
call GroupRemoveUnit(g, u) // removes the unit from the group
endloop
call DestroyGroup(g) // to avoid group leaks, we must destroy the group variable.
endfunction
The usage of FirstOfGroup and group functions inside a loop is very common in AOE spells, with them we can do several things to a unit group.
Some tips with loops
Sometimes, we want to use the loops as a way to do a mass effect spell. If you want to add special effects inside a loop, there is a big chance the code will lag, in order to avoid that, you should use a TriggerSleepAction() function, which will give to the WC3 engine a small break to process other tasks.
You can create an infinite and unstoppable loop using only the loop and endloop instructions without an exitwhen command.
Exercise.
Create a function which displays all the numbers which can divide perfectly a given number. The function should be in that way:
JASS:function DivideNumbers takes integer n returns nothing // your code here endfunction
For exaple, if we makewe should see on the game screen something like this:JASS:DivideNumbers(12)
1, 2, 3, 4, 6, 12
Lesson 5: Triggers in JASS
Overview
Now, if all you've ever known is GUI, you're used to everything being a trigger. GUI is just a system of triggers, but you're probably wondering what exactly is a trigger. This lesson will cover triggers in JASS and how to use them. First, I'd like to tell you exactly what a trigger is.
What is a Trigger?
I'm sure that you know what a trigger is if you've used GUI before, but GUI hides some important things from you. A trigger is really just another object, like a unit or a special effect. What makes triggers useful is that they are able to detect events. Without triggers, you couldn't do too much in the editor without a lot of trouble. Now, here's an example of making a trigger in JASS:\
JASS:
function InitTrig_JASSTrigger takes nothing returns nothing
local trigger myTrigger = CreateTrigger()
call TriggerRegisterPlayerEvent(myTrigger, Player(0), EVENT_PLAYER_END_CINEMATIC)
call TriggerAddAction(myTrigger, function MyFunction)
set myTrigger = null
endfunction
Now, this may be a bit overwhelming at first, but I'll explain everything well enough so that you should understand. First off, you're going to create a local variable for the trigger. This is fine if you don't need other triggers to run TriggerExecute on this trigger (TriggerExecute is a function that runs a trigger). Now, whenever you create a new trigger, you must use the function CreateTrigger(). It's like using the CreateUnit function to create a unit. Now that you have created a trigger, you'll need to add some things to it so it would be useful. The next line adds an event to the trigger. TriggerRegisterPlayerEvent takes 3 values, which are the trigger you want to add the event to, the player this event applies to, and the specific event. There are many other TriggerRegister... functions which you can experiment with later, but for now this will be fine. The next line adds an action which is basically telling the trigger to call that function when the event happens. Now, I didn't show you the function MyFunction, but you need to know that it must take nothing and return nothing. Now, the final line sets the local variable to null, which is necessary for local variables which are handles so that memory leaks can be prevented. If you don't know what a memory leak is, don't worry about it, they will be covered in a later tutorial.
Okay, now you're probably still using that GUI trigger to run your test functions in the custom script. This JASS trigger does pretty much the exact same thing as the GUI trigger, so you can replace it. Just create a new trigger, and then go to Edit -> Convert to Custom Text. What you will see is something similar to the function shown above, only it's setting a global variable automatically generated by the editor to a trigger and just adding an action. Delete all the code and make a new function that has the name: InitTrig_[insert trigger name here]. So if the name of your trigger was JASSTrigger, you would have your function be: function InitTrig_JASSTrigger takes nothing returns nothing It's important that you name it this way so that it gets called while the map is loading.
Now, if you've noticed, I've left out how to add a condition, oh my! Well, I'll show you how adding conditions work in triggers. Don't convert a GUI trigger to JASS to see how to do conditions, that way is inefficient. There's more code than you really need to use. Let me show you an example:
JASS:
function Condition_Function takes nothing returns boolean
return GetTriggerPlayer() == Player(0)
endfunction
function InitTrig_JASSTrigger takes nothing returns nothing
local trigger myTrigger = CreateTrigger()
call TriggerRegisterPlayerEvent(myTrigger, Player(0), EVENT_PLAYER_END_CINEMATIC)
call TriggerAddCondition(myTrigger, Condition(function Condition_Function))
call TriggerAddAction(myTrigger, function MyFunction)
set myTrigger = null
endfunction
This might look confusing, it might not. Either way I'm going to review what everything does. First off, I'll review how to set up a function so it can be used as a condition in a trigger. First off, you can name the function whatever you want, but it has to take nothing and return boolean. A boolean value, as you should know, is true/false. This function returns GetTriggerPlayer() == Player(0). You might look at that and be clueless, others might understand it already. The first part gets the player who triggered the event (the player pressing escape). And finally, the == Player(0) part checks if the player is Player(0) (Player 1 (Red)). Since this is a boolean statement, meaning it is either true or false, it can be used as a return value.
Finally, we have the added line in the InitTrig_JASSTrigger function. The function TriggerAddCondition takes a trigger and a boolexpr (boolean expression) . You don't need to know what a boolexpr is yet, all you need to know is that you put Condition(function [insert trigger name here]) and it returns a boolexpr which is used for conditions in triggers.
Challenge
This challenge will require a bit of researching JASS functions, so I recommend you get a tool such as JassCraft. Well, I'll give you three possible challenges. The first challenge will to be to create a trigger in JASS that will run a function that you create (any). After you've messed with that a bit, open up JassCraft or a similar program where you can search JASS functions. You're next challenge will be to create a trigger that will go off whenever you type in "-run" or whatever kind of text message in-game. I'll give you some help in telling you that the function you're looking for to add the event is TriggerRegisterPlayerChatEvent, however it's up to you to figure out how to use it. If you've solved that challenge, then make a trigger that goes off when the message a player types contains the character "-" or whatever letter you choose. In the actions, you will then display the value the message the player typed in. Hints for this challenge are keep using the same function to add the event, only you need to change a value or two. And I suppose it would also be helpful to tell you that the GetEventPlayerChatString can be used to get the string that the player types in.
Good Luck -wyrmlord
Lesson 6: Memory Leaks
Lesson 6: Memory Leaks
By: Darkwulfv, edited by wyrmlord
What is a memory leak?
-A memory leak is caused by bad coding, where a handle that was stored in memory is lost from refrence. Basically, it’s something that got placed in wc3’s memory usage and never got removed, and is unable to be removed.
What does a memory leak do?
-A memory leak adds a little tiny bit of memory usage to Wc3 when it’s running. If enough memory leaks, your map is going to cause some serious lag.
What causes memory leaks?
-When a handle is created, it's stored it in Wc3’s memory. If it is not destroyed or removed when you are done with it, then it stays there, taking up memory.
Well how am I supposed to fix them?
-Well, there are a few ways to do so, depending.
Method #1:
=============================
JASS:
function MemoryLeak takes nothing returns nothing
call AddSpecialEffect(…) //Creates a special effect
endfunction
The native AddSpecialEffect(…) creates an effect. If you do not destroy this effect with the proper function, it will stay embedded in the memory, and thus take up memory. Now, one leak is terribly insignificant. But if your map made a lot of leaks very often, you would notice a big change.
Here’s a way to fix that leak:
JASS:
function MemoryLeak takes nothing returns nothing
local effect my_effect = AddSpecialEffect(...) //Create a special effect
call DestroyEffect(my_effect) //Destroys the effect, removing it from memory
set my_effect = null //You have to null local handles at the end of a function, or they leak too
endfunction
//Alternatively, this can be used
function MemoryLeak2 takes nothing
call DestroyEffect(AddSpecialEffect(...))
//Adds a special effect and destroys it all at once. This will still show the animation once for most (not necessarily all) effects, and doesn't require the use of a variable
//However, if you want to see the entire animation, you should wait for the duration of the effect's 'stand' animation
endfunction
This method goes for anytime you are using a handle(any variable that isn’t a real, integer, boolean, boolexpr, code, or string)
However, the destroying/removing function changes for each type of handle. A list of variable types and how to remove them will be given later for you to refer to.
NOTE: When destroying/removing an object, you are removing/destroying a specific object and not the variable itself. The variable just points to the location in memory where the object is stored.
NOTE: A leak can be defined as an object that is created, not removed, unable to be removed during the game (assuming not removing it is undesired). If it’s only used once (like dummy units, rects, groups, etc.) then remove it. If not, you should leave it. (Like for spells, don’t remove the caster!)
NOTE: All non-handle variables except strings do not leak. String leaks cannot be fixed, but you usually don't need to worry about them.
So memory leaks only apply when you create things?
-WRONG!
A memory leak not only happens when you create things. It also happens when you make a handle-variable, set it to a value, and don’t null it.
Example:
JASS:
function MemoryLeak takes nothing returns nothing
local unit u
//actions
endfunction
JASS:
local unit u = GetTriggerUnit()
To null a variable, simply put
set yourvariable = null
You don't need to set a variable to null after removing each object. You only need to null it once; this is usually done at the end of a function.
JASS:
function MemoryLeak takes nothing returns nothing
local group g = CreateGroup()
//Some code
set g = null
endfunction
NOTE: To satisfy those wanting to know why handle variables leak (not referring to the object, I'm referring to the variable). When you set a handle equal to a value, the handle points to where that value is stored in memory. It will remain pointing to where that value is stored unless it is set to null (meaning 0, not pointing to a specific place in memory.)
What about globals?
-Since these are always in the memory to begin with, and are always available, they don't count as leaks (and don't need to be nulled).
So uh… What do I do about non-handle variables?
-They don’t leak though, so worry not.
Conclusion:
-Always clean leaks. If you don’t, and there’s enough leaks, you will notice the effects.
Challenge!
-Clean this function of all memory leaks:
JASS:
function ChallengeTrigger takes nothing returns nothing
local unit u = GetTriggerUnit() //This unit is in the game, it needs to be kept (hint)
local effect SFX = AddSpecialEffect(…)
local group g = CreateGroup()
local unit u2 //this is going to be a dummy unit and should be removed (hint)
local real r = 4
//actions
//(hint) only one of these variables isn’t nulled.
endfunction
Good luck!
Attachments
Last edited: