Please don’t start by saying that there are already too many of them out there. I’ve seen them. I’ve read them. Most of them are boring. And they don’t make sense. I’m going to try a different approach.
You all have heard of it; it’s JASS, the trigger language of WC3. And, if you think you don’t know it, you’re wrong. If you can use GUI, you can just as easily use JASS. Now, in this tutorial, I’m not going to use 3 pages of advanced JASS code script. I’m going to focus on HOW you should write JASS. What are some of the syntax rules? What do some actions look like in JASS? So, let’s get started….
First, create a trigger (or just look at mine), don’t add anything to it, and convert it to JASS by clicking on it and going to Edit -> Convert to Custom Text. Mine is named Blank JASS Trigger. It should look like this:
This is the basic structure of everything you will do when creating JASS triggers. Now, I’m going to give a brief explanation of what each thing is doing, but first, we need to talk about functions.
Functions and Triggers
Functions are, in the simplest of terms, an action or group of actions. That’s it. No frills involved here. Now, there are 4 types of functions, depending on the arguments they give or return. The function can neither give nor return arguments, it can return but not take arguments, it can take but not return arguments, or it can both take and return arguments.
But, you’re asking, “What does that mean!” Functions that do neither just do the actions inside the function. Pretty simple. Whatever actions that are in the function are executed. If the function takes something, that means you have to give it something to make the function work. Maybe you have to give it an integer so it can do a calculation. If the function returns a value, that means that when the function is done, it gives you something. You may or may not want to use the thing it gives you. But, to have this make more sense, let’s talk about functions that both give and return a value.
Think of a machine where you put something in, the machine does something to it, and something new is spit out the other side. So it is in JASS. You give the function something, it runs it through the actions, then gives something back to you that could be totally different.
Now we can go back to the trigger above. Look at this line:
function Trig_Blank_JASS_Trigger_Actions takesnothingreturnsnothingendfunction
All this does is yell at the game, “Hey! We got some actions here that don’t need anything and don’t give anything. Deal with it!” Then you can put actions below the function Trig_Blank_JASS… blah blah, and above the endfunction. If the function is ending, you don’t want to be putting things after it, right? Easy enough so far? Definitely.
I know it’s a big chunk, but we’ll get through it. First, this whole section is what sets up the trigger. It basically says, “We’ve got a trigger here, and here’s what sets it off, what we need to check and what it does.” As you can see, this is a function in itself. That will pretty much stay the same. It’s what is inside the function that counts. Now, take a look at this:
set gg_trg_Blank_JASS_Trigger = CreateTrigger()
This is what creates the trigger when the map loads up. It tells the game to store another trigger for use. See the name of the trigger here: Blank_JASS_Trigger?
This is what will be run first when the event of the trigger is met. Notice how it says the name of the trigger with this line:
Now check this out:
It’s the name of the function we looked at above! Basically, this is saying, “Run the function named Trig_Blank_JASS_Trigger_Actions.” Want more? Ok, here we go:
Any action must have the word call in front of it. Let's look at a simple action. How about killing a unit? This is what it looks like:
What is this? Well, like I said, it has to have a call. See it? Good. So, what's the rest? Well, KillUnit is the name (in JASS, obviously) of the action. In this case, killing a unit. All you have to do is put which unit is being killed in the parentheses. In this case, we're killing the Triggering Unit. See the GetTriggerUnit()? Simple, right? It's not that hard, right? Of course not. You worried for nothing.
Now, I’m not going to bore you by trying to explain all of the different events and what they look like in JASS. Say I wanted to use the event A unit Dies. If you did that in JASS, it would look like this:
Now, conditions are a little weird. If you create a condition in GUI and convert it to JASS, you will find that it creates its own function just for the condition. This is what the separate function looks like:
function Trig_Blank_JASS_Trigger_Conditions takesnothingreturnsbooleanif(not( GetPlayerSlotState(Player(0)) == PLAYER_SLOT_STATE_PLAYING ))thenreturnfalseendifreturntrueendfunction
Notice it returns a boolean. The trigger wants to know yes or no in answer to the slot status comparison, so it returns either true or false. So, a condition operates almost the same way as an action. It runs a function. But in this case, the function either approves or denys the rest of the trigger. It’s like the guard of the gate. In other words, this function either stops the trigger or lets it continue. Now, this part goes at the bottom with the event:
Just as in GUI, it goes Event, Condition, Action. See them all? Good.
You can have functions that don’t show up at the bottom. Functions can call other functions. Call? What does call mean? Call means that the action or function will be executed. If I said:
I just told it to do that function just like it does at the bottom. When you use call in JASS to call something, it must be in all lower-case.
See the parentheses? That’s where you would put any arguments that the function would take. Since that function takes no arguments, it’s blank. Logical? Certainly, Mr. Spock.
So, how do you write actions in JASS? What if I wanted to kill a unit? Look it up. Just know that every action will have a call in front of it. Create the action in GUI and convert the trigger to JASS. It will show you.
Are you ready to move on to a little bit more advanced material? Come on, the first part was so simple, you won’t have to use but maybe 5 more brain cells to understand this. Ready? Ok, first, we’ll start off by talking about Ifs....
Ifs, Loops, and Returns
Pretty simple, right? If something is true, do something. Otherwise, do something else. How do you do it in JASS? Look at this:
if udg_BooleanVariable == truethencall DisplayTextToForce(GetPlayersAll(), “Hi!”)elsecall DisplayTextToForce(GetPlayersAll(), “Go Away!”)endif
That’s it. Don’t worry about the calls right now, they are actions converted from GUI, but you can look them up if you want. See the if? That’s where you put your condition. Seriously. See the “then” at the end of the line? That tells the game “Hey, we’re done with conditions.” Next line is the action. What do you think the “else” does? How about the endif? Tells the game that the if is done. That was unexpected. You can also use an elseif in place of the else. Ever used ifs inside of other ifs? There you go. All an elseif does is say, "If the condition isn't true, go down here and do another condition comparison." Easy? Good. Now, let’s take a look at loops.
So, loops. Wonderful tools, loops are. They repeat a set of actions for a pre-determined number of ‘loops’. Complicated? No. How about in JASS? Still no. Look:
So. Let’s look at this. See the udg_ part? That means that IntegerVariable was a variable created in the Variable Editor. For the curious, it stands for User Defined Global. That set action sets the IntegerVariable to 1 so it can be used to set the number of loops that will occur. Exitwhen tells the loop when to stop. It stops when the condition is met. What’s the condtion? The variable is greater than 5. We set it at 1 before the loop. We increase it by 1 in the loop itself. How many times will the loop repeat? 5. Greater than 5 would be 6, but it starts at 1, so 6 – 1 = 5. Endloop? Tells the game there are no more actions in that loop. So, with loops, you better have an exitwhen condition, or you’ll be in trouble. Now, onward and upward to returns….
Ever used the Skip Remaining Actions option in GUI? Of course you have. That’s what return does. I’m serious! Wherever you put a return, that’s where the trigger will stop execution. Now, that’s not all, though (boos). If the function is supposed to return something (remember functions above?), that’s where you put it. Take a look:
function notreallyafunction takesnothingreturnsnothingreturnendfunction
This does absolutely nothing. Take a look when it returns something, though:
function notreallyafunction takesnothingreturnsintegerreturn udg_IntegerVariable
Ooh, look, now when you call that function, it gives you the variable IntegerVariable. Difficult? Don’t make me laugh at you. :P One more thing to look at, and we’re done. What? Already? Yes.
The Golden Rule of JASS
Now, JASS has one big rule. There are others, (really?) but this one is one of the most important. Listen carefully. JASS IS CASE-SENSITIVE. So, Call is not the same as call. When you look it up in JASSCraft, get it right! Now, this is only the surface of JASS. But, armed with this knowledge, you can now sally forth to the wild annals of harder, more in-depth tutorials. (What? (Look it up.)) Remember, JASS is just a different way of displaying GUI. Well, that’s about it. Did you have fun? I certainly did. Now, go read a more difficult tutorial and finally understand what is being said!
Feedback welcome. I want to hear all your comments, including, "This tutorial is stupid; you should never have written it." Was this tutorial too easy for you? Go read a harder one. Was it too hard? Quoted for truth:
"Want to learn JASS? take the red pill.. Wanna stay in your comfortable GUI world? take the blue one" ~~ WastedSavior