You probably came here thinking "Oh I can learn JASS in 15 minutes thanks to this guy!". Well, sorry to burst your bubble, because it's not as simple as that. It's going to take about one full day of nonstop searching and learning to learn it all, and that's only if you really really crunch it all in. I'm sure you don't because you'll overload yourself and not learn anything.
So, you came here to learn JASS. Let's start with the basics.
Functions
What are functions? Well, a function is like a mini-trigger. Here's an example of a function:
Code:
function TestFunction takes nothing returns nothing
call DisplayTextToForce( GetPlayersAll(), "Hello World!" )
endfunction
Right now I'm sure that means nearly nothing to you. Especially if you're here reading this. Now this is what it does: It displays the text "Hello World!" to all players in the game.
Let's break it up and analyze it.
Code:
function TestFunction takes nothing returns nothing
Now this is how it works "function" declares a new function. TestFunction is just the name of the function. "takes nothing" refers to any resources it takes in order to run. "returns nothing" refers to anything it returns to the function that called this function unless it's for conditions or actions. In conditions, it will only run the actions block if returned true. In actions, it will be used in Loops, If/Then/Else, and anything else you find it useful for.
Code:
call DisplayTextToForce( GetPlayersAll(), "Hello World!" )
The word "call" does just what it says, it calls an action to run. In this case it's DisplayTextToForce(). The parameters are put in between the parentheses. One parameter is GetPlayersAll(), which gets every player that's currently playing. Then a comma separates it from the second parameter which happens to be text. We know this because of the quotation marks (""). Quotations mean text and apostrophes mean integers for UnitID's and ItemID's.
Does just what it says, ends the function. The End. Yep, that's what it does.
Now let's see the structure of a trigger:
Code:
function Trig_JASS_test_Actions takes nothing returns nothing
call DisplayTextToForce( GetPlayersAll(), "This is a message" )
endfunction
//===========================================================================
function InitTrig_JASS_test takes nothing returns nothing
set gg_trg_JASS_test = CreateTrigger( )
call TriggerRegisterPlayerEventEndCinematic( gg_trg_JASS_test, Player(0) )
call TriggerAddAction( gg_trg_JASS_test, function Trig_JASS_test_Actions )
endfunction
Now from looking you can probably figure most of the parts from what you've learned above. Something new is that it adds an event and action to the trigger. Well, if you look into the part to add actions, it refers to the function above it. This is important: Functions can only call functions declared ABOVE that function. The above example works because Trig_JASS_test_Actions is declared above InitTrig_JASS_test.
Code:
set gg_trg_JASS_test = CreateTrigger( )
"set" is setting a variable, in this case a global, to create a new trigger. That's what "set" does. It sets a variable to something.
Calling a function is easier than it sounds. You just pick up your cell and dial 1-800-func-<func number>. Nah, just kidding. It goes like this:
Code:
function Msg takes string s returns nothing
call DisplayTextToForce( GetPlayersAll(), s )
endfunction
function ShowMessage takes nothing returns nothing
call Msg("This is a message!")
endfunction
function ShowSum takes integer a, integer b returns nothing
local integer r=a+b
call Msg("r= "+I2S(r))
endfunction
function Trig_JASS_test_Actions takes nothing returns nothing
call ShowMessage()
call ShowSum(33,45)
endfunction
Just like I said earlier, you need to make sure the called function is either in the map header or above the function. Then you need to add in parameters as show above. Just use the examples and they're pretty self explanatory.
Functions that return values are just the same:
Code:
function <Function Name> takes <argument list> returns <Return type>
When a function is declared to return a value, you must use the return statement:
return(<value>)
or
return <value>
But this return statement MUST be the last line of the function.
Variables
Variables are symbols that refer to s piece of information that can be set and reset over and over.
Here is an example of a function that uses a local variable. In GUI you used Globals. We'll get into the differences later.
Code:
function Test takes nothing returns nothing
local string a
set a = "This is the string variable 'a'"
call DisplayTextToForce( GetPlayersAll(), a )
endfunction
Now, you can see me declaring a local variable using "local string a". "local" tells the game you're declaring a local variable. "string" tells it's a string. "a" is the name of the variable. Under that, you see me set it to a value. When you declare variables, it's best to set them to values as you declare them like so:
Code:
function Test takes nothing returns nothing
local string a = "This is the string variable 'a'"
call DisplayTextToForce( GetPlayersAll(), a )
endfunction
As you can see, it's a full line shorter. This can enhance your code ten-fold if used properly.
The difference between locals and globals is that locals can only be used in the functions its declared in and the functions called by that function. Globals can be used anywhere but if you set it to another value, it will overwrite it deleting any references to the previous data creating a leak because you deleted the reference but not the data.
To declare a Global Variable, you go into the map header and do this:
Code:
globals
...
<VARIABLE TYPE> <VARIABLE NAME> [= VALUE]
<ARRAY TYPE> array <ARRAY NAME>
...
endglobals
Just like locals except you have globals and endglobals. Globals must be referred to like this: udg_<VARIABLE NAME>. "udg" stands for User Defined Global. You can also declare it in the Variable Editor (Ctrl + B), but what's the fun in that?
With locals you need to nullify them. Any variables that are set must be nulled, with the exception of units, integers, and reals.
So in order to nullify strings you do this:
Code:
function Test takes nothing returns nothing
local string a = "This is the string variable 'a'"
call DisplayTextToForce( GetPlayersAll(), a )
set a = ""
endfunction
Note: You must have set a value to a variable before you access it.
If you try accessing a variable without a value, the trigger will just stop and not do anything past the point with the variable in question.
Now, it's the same with integers, reals, units, locations, etc.
Arrays are easy in JASS. Here's how you declare them:
Code:
function Test takes nothing returns nothing
local string array a
set a[1] = "This is part one of variable 'a'"
set a[2] = "This is part two of variable 'a'"
call DisplayTextToForce( GetPlayersAll(), a[1] )
call DisplayTextToForce( GetPlayersAll(), a[2] )
set a[1] = "'
set a[2] = ""
endfunction
Comparisons are easy too!
Here's how you do it:
Code:
function ComparisonTest takes nothing returns boolean
return ( IsUnitAlly( GetEnumUnit(), Player(0) ) )
endfunction
Now, it will return true if the unit GetEnumUnit is an ally of Red (Player 0 <-- That's only in JASS), or false if it's an enemy. GetEnumUnit is Picked Unit in GUI, so that means you'd use this as a condition. Player(0) means Red. In JASS player numbers start from 0 not 1. This is important.
If/Then/Else and Loops
JASS programming wouldn't be programming without If/Then/Else and Loops. Here's how I/F/T's work:
If we want an action to be done, only if a condition is true, we use an if statement:
Code:
if <boolean> then
...actions...
endif
When the boolean value is true, the actions are executed.
Code:
function Trig_JASS_test_Actions takes nothing returns nothing
if true then
call DisplayTextToForce( GetPlayersAll(), "Is true" )
endif
endfunction
The result will be Is true.
But:
Code:
function Trig_JASS_test_Actions takes nothing returns nothing
if false then
call DisplayTextToForce( GetPlayersAll(), "Is true" )
endif
endfunction
Will show no result.
From now we will use this function:
Code:
native GetRandomInt takes integer lowBound, integer highBound returns integer
Which results a random number between lowBound and highBound.
I decided that the best way to show how statements work in JASS is by having fun using problems from the first lessons of an Algorithm Class.
Given the numbers a and b between 1 and 10. Show the major number. If they are equal say so
Code:
function Msg takes string s returns nothing
call DisplayTextToPlayer(Player(0),0,0, s )
endfunction
function Trig_JASS_test_Actions takes nothing returns nothing
local integer a=GetRandomInt(1,10)
local integer b=GetRandomInt(1,10)
call Msg("a="+I2S(a))
call Msg("b="+I2S(b))
if (a>b) then
call Msg(I2S(a)+" is the greater number")
endif
if b>a then
call Msg(I2S(b)+" is the greater number")
endif
if (a==b) then
call Msg("they are the same number")
endif
endfunction
NOTE: If the game is choosing the same numbers every time, you have to go to File\prefferences\Test map and disable the Fixed Random Seed option.
Note that a>b is between () and b>a isn't, it doesn't matter if you use () or not, unless you want something to be evaluated before, but using the comparision inside () seems easier to read and In theory should make the compiler parse it faster.
In game press Escape. The result is going to be different every time.
For example:
a=4
b=6
6 is the greater number
or
a=7
b=5
7 is the greater number
or even:
a=3
b=3
they are the same number.
else
There is another way to use if and it is when you combine it with an else statement:
Code:
if <boolean> then
..then actions..
else
..else actions..
endif
The else actions will be executed when the boolean is false. If the boolean is true, then the 'then actions' are executed.
Given a number from 1 to 100 determine if it is a multiple of 2
Code:
function Msg takes string s returns nothing
call DisplayTextToPlayer(Player(0),0,0, s )
endfunction
function Trig_JASS_test_Actions takes nothing returns nothing
local integer a=GetRandomInt(1,100)
local integer div=(a / 2)
call Msg("a="+I2S(a))
if (div*2==a) then
call Msg(I2S(a)+" is a multiple of 2")
else
call Msg(I2S(a)+" isn't a multiple of 2")
endif
endfunction
Explanation, a / 2 is integer division between a and 2 , if you multiply the result by 2 a number will appear, if it is the same as a then a was a multiple.
48/2=24 ; 24*2=48
9/2=4 ; 4*2=8
elseif
There is also chance for having to use elseif inside an if statement
Code:
if <boolean0> then
..actions..
elseif <boolean1> then
..actions..
elseif <boolean2> then
..actions..
···
else
..actions..
endif
An if may have as many elseif as you want, I think there is a limit but it was something like 26. It may also not have any elseif statements. The else statement is optional. Because of logical reasons, an if block is unable to have more than 1 else statement.
When first boolean is not true, will evaluate the second boolean, if it is not true it will evaluate the third and so and so until the else statement or the endif statement.
Whenever it finds a true value it will execute the actions and forget the rest of the contents of that if statement.
Given a number from 0 to 10 , display its literal name.
Code:
function Msg takes string s returns nothing
call DisplayTextToPlayer(Player(0),0,0, s )
endfunction
function Trig_JASS_test_Actions takes nothing returns nothing
local integer a=GetRandomInt(1,100)
call Msg("a="+I2S(a))
if (a==0) then
call Msg("zero")
elseif (a==1) then
call Msg("one")
elseif (a==2) then
call Msg("two")
elseif (a==3) then
call Msg("three")
elseif (a==4) then
call Msg("four")
elseif (a==5) then
call Msg("five")
elseif (a==6) then
call Msg("six")
elseif (a==7) then
call Msg("seveb")
elseif (a==8) then
call Msg("eight")
elseif (a==9) then
call Msg("nine")
else
call Msg("ten")
endif
endfunction
The result is something like:
a=1
one
or
a=7
seven
Loops
What if you have to repeat something? and you don't have time to type all that stuff, or you don't know how many times you have to repeat it?
JASS only has one loop statement:
Code:
loop
..actions..
exitwhen <boolean1>
..actions..
exitwhen <boolean2>
..actions..
exitwhen <boolean3>
...
endloop
Every action inside loop and endloop will be repeated until any of the exitwhen statements gets a true value.
loop ... endloop statments may have as many exitwhen statements as you want, they even might have no exitwhen statement at all (This should be combined with waits, else the game will freeze for some time and halt the process)
And the exitwhen statement might be anywhere as long as it is inside the loop.. endloop block.
By now you should be able to figure it out by yourself.
The End
Note: Some parts were taken from other tutorials on
The Helper because they could explain it better than I could.
~Sevion