- Joined
- Feb 26, 2008
- Messages
- 892
I don't know if you already have enough JASS tutorials, but I have one that is geared more toward the people who haven't gotten anything up to this point and are looking for a different take on the subject. Anyway, here it is:
By: Ghan_04
Introduction
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 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:
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.
Look at this now:
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:
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?
Now look here:
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:
But where does this go? It goes below the line that creates the trigger like this:
Look here:
This is the part in GUI where you would see Generic Unit Event. Get it?
And this:
This tells the game which trigger gets this event. See the trigger name in there?
Lastly, this:
This is the actual event, which in this case is A unit Dies.
See, it really is too easy.
To find out what events look like, experiment with changing triggers into JASS. Also, JASSCraft is a wonderful source.
Conditions look similar. Let’s look at what the condition Player 1 (Red) slot status equal to Is Playing would look like in JASS:
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:
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:
It goes in between the Events and Actions, so in all, it should look like this:
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
Pretty simple, right? If something is true, do something. Otherwise, do something else. How do you do it in JASS? Look at this:
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. Oh, and for reference, the maximum number of loops before the trigger collapses is approximately 6250. Just so you know. 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:
This does absolutely nothing. Take a look when it returns something, though:
Ooh, look, now when you call that function, it gives you the variable IntegerVariable. Difficult? Don’t make me laugh at you. One more thing to look at, and we’re done. What? Already? Yes.
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? Well, I'm open to questions!
A Concise Introduction to JASS
By: Ghan_04
Introduction
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:
JASS:
function Trig_Blank_JASS_Trigger_Actions takes nothing returns nothing
endfunction
//===========================================================================
function InitTrig_Blank_JASS_Trigger takes nothing returns nothing
set gg_trg_Blank_JASS_Trigger = CreateTrigger( )
call TriggerAddAction( gg_trg_Blank_JASS_Trigger, function Trig_Blank_JASS_Trigger_Actions )
endfunction
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:
JASS:
function Trig_Blank_JASS_Trigger_Actions takes nothing returns nothing
endfunction
Look at this now:
JASS:
//===========================================================================
function InitTrig_Blank_JASS_Trigger takes nothing returns nothing
set gg_trg_Blank_JASS_Trigger = CreateTrigger( )
call TriggerAddAction( gg_trg_Blank_JASS_Trigger, function Trig_Blank_JASS_Trigger_Actions )
endfunction
JASS:
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?
Actions
Now look here:
JASS:
call TriggerAddAction( gg_trg_Blank_JASS_Trigger, function Trig_Blank_JASS_Trigger_Actions )
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:
JASS:
gg_trg_Blank_JASS_Trigger
Now check this out:
JASS:
function Trig_Blank_JASS_Trigger_Actions
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:
JASS:
call KillUnit(GetTriggerUnit())
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.
Events
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:
JASS:
call TriggerRegisterAnyUnitEventBJ( gg_trg_Blank_JASS_Trigger, EVENT_PLAYER_UNIT_DEATH )
But where does this go? It goes below the line that creates the trigger like this:
JASS:
set gg_trg_Blank_JASS_Trigger = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Blank_JASS_Trigger, EVENT_PLAYER_UNIT_DEATH )
Look here:
JASS:
TriggerRegisterAnyUnitEventBJ
This is the part in GUI where you would see Generic Unit Event. Get it?
And this:
JASS:
gg_trg_Blank_JASS_Trigger
This tells the game which trigger gets this event. See the trigger name in there?
Lastly, this:
JASS:
EVENT_PLAYER_UNIT_DEATH
This is the actual event, which in this case is A unit Dies.
See, it really is too easy.
To find out what events look like, experiment with changing triggers into JASS. Also, JASSCraft is a wonderful source.
Conditions
Conditions look similar. Let’s look at what the condition Player 1 (Red) slot status equal to Is Playing would look like in JASS:
JASS:
call TriggerAddCondition( gg_trg_Blank_JASS_Trigger, Condition( function Trig_Blank_JASS_Trigger_Conditions ) )
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:
JASS:
function Trig_Blank_JASS_Trigger_Conditions takes nothing returns boolean
if ( not ( GetPlayerSlotState(Player(0)) == PLAYER_SLOT_STATE_PLAYING ) ) then
return false
endif
return true
endfunction
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:
JASS:
call TriggerAddCondition( gg_trg_Blank_JASS_Trigger, Condition( function Trig_Blank_JASS_Trigger_Conditions ) )
It goes in between the Events and Actions, so in all, it should look like this:
JASS:
set gg_trg_Blank_JASS_Trigger = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Blank_JASS_Trigger, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition( gg_trg_Blank_JASS_Trigger, Condition( function Trig_Blank_JASS_Trigger_Conditions ) )
call TriggerAddAction( gg_trg_Blank_JASS_Trigger, function Trig_Blank_JASS_Trigger_Actions )
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:
JASS:
call Trig_Blank_JASS_Trigger_Actions()
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
Ifs
Pretty simple, right? If something is true, do something. Otherwise, do something else. How do you do it in JASS? Look at this:
JASS:
if udg_BooleanVariable == true then
call DisplayTextToForce(GetPlayersAll(), “Hi!”)
else
call 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.
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:
JASS:
set udg_IntegerVariable = 1
loop
exitwhen udg_IntegerVariable > 5
call DisplayTextToForce(GetPlayersAll(), “Loop Number: “+I2S(udg_IntegerVariable) )
set udg_IntegerVariable = udg_IntegerVariable + 1
endloop
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. Oh, and for reference, the maximum number of loops before the trigger collapses is approximately 6250. Just so you know. Now, onward and upward to returns….
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:
JASS:
function notreallyafunction takes nothing returns nothing
return
endfunction
This does absolutely nothing. Take a look when it returns something, though:
JASS:
function notreallyafunction takes nothing returns integer
return udg_IntegerVariable
endfunction
Ooh, look, now when you call that function, it gives you the variable IntegerVariable. Difficult? Don’t make me laugh at you. 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? Well, I'm open to questions!