JASS 101 - How to move from GUI to JASS
The purpose of this chapter is to introduce in the process to start coding in jass using
Jass New Generation Pack (JNGP)Let's start!!
Here we assume that you have installed and configured properly JNGP. If you haven't done this, please refer to this
tutorial.
- Open Jass New Gen Pack

- If you have no map to test it, use the one that started the Editor.
- Open the Trigger Editor in the menu Module > Trigger Editor or simply press F4.
- You will see the following interface:
As you can see any new map will start with a trigger which will start some configurations for a melee style game. The important parts of this trigger are the Events, the Conditions and the Actions - Now to the interesting part. As you may know, GUI is in fact an "cover" for the code inside the editor, so we need to tell the World Editor that we don't want to see this cover. To do that please go to the menu Edit > Convert to Custom Text as shown in the following picture:
- After setting this you will see the following code:
In order to understand it I'd suggest to read it from the bottom to the top. The first thing you will see is that we manage something called functions. All in Jass is a matter of developing functions to be honest. The functions has 3 parts: the name, the input arguments ( takes) and the output argument ( returns) sets the type of data or handle the functions will obtain.
Important tip: From now on you will work in the TESH editor environment . It's important to clarify that the undo and redo in the toolbar are not functional in the text edition, instead you have to right click over the code text and there will be a menu which will offer this feature
in the code.
Trying some GUI code.
Well, we've made some test with an easy code, pretty straight. Now let's try with something more elaborated but simple to understand. As a sample, we'll do a trigger that makes Abominations Deals damage upon death. We clarify that we won't make it leakless or efficient in order to make it readable to see how this will look in Jass.
And here's the GUI for that:
Test
Events
Unit - A unit Dies
Conditions
(Unit-type of (Triggering unit)) Equal to Abomination
Actions
Unit Group - Pick every unit in (Units within 512.00 of (Position of (Triggering unit)) matching (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True)) and do (Actions)
Loop - Actions
Unit - Cause (Triggering unit) to damage (Picked unit), dealing 250.00 damage of attack type Chaos and damage type Acid
And then, let's convert it into Jass. The result is the following:
function Trig_Test_Conditions
takes nothing returns boolean return false
endif
return true
endfunction
function Trig_Test_Func001001003
takes nothing returns boolean endfunction
function Trig_Test_Func001A takes nothing returns nothing
endfunction
function Trig_Test_Actions takes nothing returns nothing
endfunction
//===========================================================================
function InitTrig_Test takes nothing returns nothing
endfunction
As you can see, it generates 5 functions. From bottom to top:
InitTrig_Test,
Trig_Test_Actions,
Trig_Test_Func001A,
Trig_Test_Func001001003 and
Trig_Test_Conditions. The first one will run at map initialization loading the trigger condition and action. the second will execute the actions block. The third will be executed for each unit near to the abomination and it will deal damage to it. The fourth filters all the units which are the enemies of the dying unit. And the fifth will check if the unit is of the type, if true, it will trigger the actions.
So in the end, all this GUI blocks form a long and non easy to read code. And the worst thing is that it does in an inefficient way. You see the long names?? they're done in this way some any function gets unique in the whole code.
How the code is arranged?? at the end, the code is armed in one file which will have a *.j extension. It will be the core of the map and will manage all the internal things in the map.
Now let's talk about the functions itself. Have you noticed that some of them are in cursive and others are in bold? the ones in cursive are functions from a library called
blizzard.j, and the other are from the MAIN library called
common.j and they are called
natives.
The functions that we want to use more are the
natives because they are the fastest in execution and in Jass are the most preferred. Blizzard.j what it does?? well, this library is the connector from GUI to JASS. Most of the code done in blizzard.j is repetitive and does unnecessary steps. that's the reason GUI is slower than coding directly in JASS.
The first optimization
As you see, this code tends to be scary, so let's do a first try to make it look prettier. Let's start with the whole set of functions. You can see that these functions have strange names, that's because they need to be totally different from any other function defined in the triggers. We can do a simplification in that part using a feature offered in vJASS called
Scope. Scopes allow to differentiate the code. All that is inside a scope will be only valid inside the scope unless you define a set of prefixes (this part will be treated later). Meanwhile we'll use this to make it look nice.
scope Test initializer Init
private function Conditions
takes nothing returns boolean return false
endif
return true
endfunction
private function GetEnemies
takes nothing returns boolean endfunction
private function DoDamage takes nothing returns nothing
endfunction
private function Actions takes nothing returns nothing
endfunction
//===========================================================================
private function Init takes nothing returns nothing
endfunction
endscope
Now is more readable: functions have names that let you get clearly its purpose. Scopes allow to define a function that runs at map initialization, very convenient to set variables of that specific part of the trigger. In addition, it provide context to the functions to only the trigger, no matter the name. We achieve this with a new keyword:
private this makes those functions only valid inside the scope, allowing you to write faster your functions and make them more readable for you.
Well, the general optimization is done, now to the functions themselves. Let's start with
Conditions.
Conditions functionprivate function Conditions
takes nothing returns boolean return false
endif
return true
endfunction
I personally don't get why it evaluate too many stuff. If you use
== the result will be a boolean. Comparing a boolean to obtain the same boolean is a waste of code we just simple do this:
private function Conditions
takes nothing returns boolean endfunction
As you see, we passed from 6 line of code to 3 lines. As you see too, it's straight to the point, hence for efficient.
Actions Functionprivate function Actions takes nothing returns nothing
endfunction
Well, this function is pretty straight, so what can be optimized?? well, first of all it leaks variables, that means an object is created but their reference is lost so it keeps alive for the rest of the game without being removed and nullified. For that reason we'll set variables to call them later and remove them when they are not needed anymore. Additionally we have a function
ForgroupBJ this one is a
Blizzard.j function so it has one or more process inside it. In JNGP, in the trigger editor, click on the text area and press CTRL, if you hover the mouse over those BJ functions you'll see they show as an hiperlink. if you click on it you'll see this code:
// If the user wants the group destroyed, remember that fact and clear
// the flag, in case it is used again in the callback.
// If the user wants the group destroyed, do so now.
if (wantDestroy) then
endif
endfunction
What we need actually is the function in line 7. As you see these BJ functions do a lot of unnecessary stuff, and normally they swap arguments to the natives, making most of them slow. Now let's see how it looks the code now using the native
ForGroup():
private function Actions takes nothing returns nothing
set g = null
set u = null
endfunction
Now we have just natives in our code and when we call an object, we can remove and clean the variables properly. And in this using local variables, we've made the code MUI (Multi Unit Instanciable) which means that this will run safely for each units without any collision in their information (we'll talk later about the importance of this).
Init FunctionIn the init function we don't want to create a global variable to store a trigger which won't be used or modified later, in fact in spells we need a code that triggers during all the game. So storing the trigger in a global is a waste of variables, in fact we can make it leak, because we don't need to refer to the trigger later. Here's the original code:
private function Init takes nothing returns nothing
endfunction
And we will change this code into this:
private function Init takes nothing returns nothing
set t = null // we free the variable but not the handle itself... in this case it doesn't matter :)
endfunction
Now we manage the trigger as a local variable, this usage of locals makes easy to port code from one map to another.
To be continued...It's time to move and we're ready to code. Please check for the following tutorial to see about the structure of the code and its features.