JASS Classroom, Lesson I

Andrewgosu

The Silent Pandaren Helper
Reaction score
716
Lesson I

Before we get started, You should download a professional program do deal with JASS, if You haven’t got one already. I will be using JassCraft, but any other JASS editing program with native list, highlighting and etc. will do just fine, too.

- Declaring variables

To get things started, lets learn how to declare variables. I am sure You are familiar with declaring global variables in GUI – You had to create the variable in the Variable Editor and You could pass the data stored in the variable to any trigger(function); hence the name, global variable.

Problem I: How to set global variables in JASS?


Yes, indeed. In JASS, all global variables have to have an „udg_” (without the quotes, means undefined global variable) prefix to separate them from local variables. Lets say, You create a global variable, point type, in the Variable Editor, named „tmpPoint”. In GUI, one would use the „ Set variable” action to set it.

Code:
 [b]S[/b]et tmpPoint = (Position of (Triggering unit))

But in JASS, it’s a little different – all spaces are replaced with „_” and there is the „udg_” prefix(Note the punctuation, JASS is case sensitive)

Code:
[b]s[/b]et [b]udg_[/b]tmpPoint = GetUnitLoc(GetTriggerUnit())

Also, one can set the global variable anywhere in the function, in the beginning, middle or in the end. This all is fairly easy to remember. Now, lets go to declaring local variables.

Problem II: How to declare local variables?

The syntax for declaring local variables is following,

Code:
 [b]local[/b] variable type variable name = ( expression )

Local variables do not have the „udg_” prefix and all local variables must be defined in the beginning of the function. Also, local variables can only be referenced within the function they were created initially – thus the name, local variables. Local variables are not overwritten, unlike global variables, because they are initialized every time the function is entered.

The syntax for declaring local arrays is following,

Code:
[B]local[/B] variable type [B]array[/B] variable name

Local arrays cannot have an initial value. But the rest, which applied to local variables, applies to local arrays, too – they have to be declared in the beginning of the function and they can only be referenced within the function they were created in.

Code:
function ArrayExample takes nothing returns nothing
    local unit array tmpUnits
    
    set tmpUnits[0] = GetTriggerUnit()
    set tmpUnits[1] = GetSpellTargetUnit()
    call KillUnit(tmpUnits[GetRandomInt( 0, 1 )])
endfunction

Now, Lets change the global point typed variable above into a local one ( You can call Your variables whatever You desire, but, I suggest You to give informative names. It pays off, especially in (very) long functions).

Code:
local location tmpPoint = GetUnitLoc(GetTriggerUnit())

Ehhh, what happened with the point type? Why it suddenly changed into a location?

Note, legal and illegal local variable declerations,

Legal
Code:
function ExampleFunction_Good takes nothing returns nothing
    local unit a = GetTriggerUnit()
      
    call PolledWait(2.5)
    call KillUnit(a)
endfunction

Legal
Code:
function ExampleFunction_Good takes nothing returns nothing
    local unit a 
      
    call PolledWait(2.5)
    set a = GetTriggerUnit()
    call KillUnit(a)
endfunction

Illegal
Code:
function ExampleFunction_Bad takes nothing returns nothing    
    call PolledWait(2.5)
    local unit a = GetTriggerUnit()
    call KillUnit(a)
endfunction

Problem III: What are the variable types in JASS?

As seen above, the point type variable suddenly changed into a location type variable. As a matter of fact, they are the same thing! Only, named differently. GUI uses point, whereas JASS names the point into a location.
At this moment, the little helper - JassCraft - comes into play. Load JassCraft and open the „Common.j” file. The first thing You see, are the native types. Examine the references, e.g „type unit extends widget”. The „unit” there is basically the variable type. You might wonder, where did, for example, Floating Text type dissapear. No worries, it is named „texttag” in JASS.

Some common variable types, which have different names in JASS,

Code:
    GUI                [B][COLOR="RoyalBlue"]JASS[/COLOR][/B]
 
    Point           -  [B][COLOR="RoyalBlue"]location[/COLOR][/B]
    Floating Text   -  [B][COLOR="RoyalBlue"]texttag[/COLOR][/B]
    Unit Group      -  [B][COLOR="RoyalBlue"]group[/COLOR][/B]
    Player Group    -  [B][COLOR="RoyalBlue"]force[/COLOR][/B]
    Region          -  [B][COLOR="RoyalBlue"]rect[/COLOR][/B]
    Special Effect  -  [COLOR="RoyalBlue"][B]effect[/B][/COLOR]

Mini-test for everyone: can You put the right variable type into the brackets?

Code:
function MiniTest takes nothing returns nothing
    local (___) u  = GetTriggerUnit()
    local (___) tt = CreateTextTag()
    local (___) g  = CreateGroup()
    local (___) f  = CreateForce()
    local (___) l  = GetUnitLoc(u)
    local (___) t  = GetTriggeringTrigger()
    local (___) r  = 2.35
    local (___) b  = Condition( function RandomFunction ) //A tough one. ;-)
    local (___) i  = 1 //2 options.
    local (___) e  = AddSpecialEffectTarget( "", u, "origin" ) // :-)
endfunction

- Effective Triggering

I bet You have heard most JASSers saying something along these lines, „Oh the noez, why don’t You optimize your code and get rid of those BJ functions?”, and then wondered, „What the is he talking about?”. Or, heard that You are using too many unneeded function calls. We’ll get into that matter in a second.

Problem IV: What are BJ functions and why they are bad?


BJ (Blizzard Jass) functions are there, because of the Graphical User Interface. They exist because of, … Well, they shouldn’t exist at all! The idea I want to send to You is that stay away from them. Speed is very important in effective triggering and clean JASS offers that. By clean, I mean code which uses native functions. It’s best to explain this with an example. Lets convert the „Unit – Add Ability” into JASS. As You can see, it has a „BJ” suffix. Copy-paste the „UnitAddAbilityBJ” into the native list, in JassCraft, and click on the equivalent found.

Code:
 function UnitAddAbilityBJ takes integer abilityId, unit whichUnit returns boolean
    return UnitAddAbility(whichUnit, abilityId)
endfunction

As You can see, the BJ function is calling another function. Why does it do that? No idea…BJ functions „rule”.:p Anyway, like I said, speed is important in efficient triggering and I bet, that any rookie can tell, that 2 function calls are slower than 1.

Probably You didn’t notice, but there is a catch. Usually, native functions take the same arguments as the BJ one, but in different order(there are exceptions).

Code:
 function [B]UnitAddAbilityBJ[/B] takes [B][COLOR="RoyalBlue"]integer[/COLOR][/B] abilityId, [B][COLOR="YellowGreen"]unit[/COLOR][/B] whichUnit returns boolean
    return UnitAddAbility(whichUnit, abilityId)
endfunction

Code:
native [B]UnitAddAbility[/B] takes [COLOR="YellowGreen"][B]unit[/B][/COLOR] whichUnit, [B][COLOR="RoyalBlue"]integer[/COLOR][/B] abilityId returns boolean

So, to recap, BJ functions are bad, because they usually just call the native function, which makes the coding slower. To distinguish BJ functions from native ones, just search for the BJ suffix(there are few exceptions). To get rid of BJ functions, just use a JASS editing program, copy the BJ function in the native list search and find the native equivalent to the BJ.

A mini-exercise for everyone: can You find the equivalent natives to the BJ functions with the correct argument list?

Code:
 function SetUnitLifeBJ takes unit whichUnit, real newValue returns nothing
    (___)
endfunction

function SetPlayerStateBJ takes player whichPlayer, playerstate whichPlayerState, integer value returns nothing
    //Modify only the gold of a player.
    (___)
endfunction

function UnitRemoveAbilityBJ takes integer abilityId, unit whichUnit returns boolean
    (___)
endfunction

function ModifyHeroStat takes integer whichStat, unit whichHero, integer modifyMethod, integer value returns nothing
    //Lets say You want to modify only the agility of a hero.
    (___)
endfunction

There is another way, to further optimize Your code: variables. I tend to follow this rule: if I have a value, which I needs to be passed to more than 1 function, I set it into a variable. An example, if I may!

Problem V: How to use variables to optimize code?


Code:
function LessFunctionCalls takes nothing returns nothing
    local real x = GetUnitX(GetTriggerUnit())
    local real y = GetUnitY(GetTriggerUnit())
    local real r = GetUnitFacing(GetTriggerUnit())
    local race c = GetUnitRace(GetTriggerUnit())
endfunction

That is not efficient. 4 local variable declarations, which use "Triggering unit". That's clearly too many. Plus, it's slow, because it calls the triggering unit 4 times.

Code:
function LessFunctionCalls takes nothing returns nothing
    local unit a = GetTriggerUnit()
    local real x = GetUnitX(a)
    local real y = GetUnitY(a)
    local real r = GetUnitFacing(a)
    local race c = GetUnitRace(a)
endfunction

Setting the triggering unit into a variable and using the variable in the argument lists makes it more efficient, because there are 3 calls less (Well, actually GetTriggerUnit() is an event response).

Mini-test for all users: can You optimize these pieces of code?

Code:
function LessFunctionCalls takes nothing returns nothing
    local playercolor pc = GetPlayerColor(GetTriggerPlayer())
    local mapcontrol  mc = GetPlayerController(GetTriggerPlayer())
    local real  handicap = GetPlayerHandicap(GetTriggerPlayer())
endfunction

Code:
function LessFunctionCalls takes nothing returns nothing
    call SetItemPosition( i, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()) )
    call SetImagePosition( whichImage, GetUnitX(GetTriggerUnit(), GetUnitY(GetTriggerUnit()), 0 )
    call SetCameraPosition( GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()) )
    call SetTextTagPos( t, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), 200 )
endfunction
 

Andrewgosu

The Silent Pandaren Helper
Reaction score
716
If You make a function, which uses only BJ functions, it's slightly slower than a function which uses only natives. Besides, it's, normally, easier to work with native function instead of BJ functions (Like, natives, which take reals instead of locations - you have to destroy and null the locations afterwards - reals don't need to be nulled nor removed).

Besides, don't You like the knowing Your code is cleaner, better and (a bit) faster than, what GUI can produce?
 

U are a noob

Mega Super Ultra Cool Member
Reaction score
152
If You make a function, which uses only BJ functions, it's slightly slower than a function which uses only natives. Besides, it's, normally, easier to work with native function instead of BJ functions (Like, natives, which take reals instead of locations - you have to destroy and null the location afterwards, reals doesn't need to be nulled).

Besides, don't You like the knowing Your code is cleaner, better and (a bit) faster than, what GUI can produce?
Yea but i thought bjs were use for memory
 
I

IKilledKEnny

Guest
Good lesson, thanks for making it Andrewgosu (I knew already almost everything but very well put). Also I like the way you gave few challenges to keep us busy while reading. I also wrote the challenges' answers if someone had a hard time with them (I wrote them in white so I won't spoil to anyone that wanna try it alone, hope it's ok. :) ) Few comments:

> local variable type variable name = ( expression )

local VariableType variable_name=expression

is more exact but I'm picky. :p

> Mini-test for everyone: can You put the right variable type into the brackets?

Answers in white (just for fun):


1. unit
2. texttage
3. group
4. force
5. location
6. trigger
7. real
8. boolexpr
9. integer / reak
10. effect


> BJ[/b]

Might want to fix that. :)

> Why does it do that? No idea.

It should make it easier to read, and somtimes it does (an good example to where BJs makes functions easier to read it gate opening BJ) ... in this case though it doesn't. :p

> there are few exceptions

"Swapped" is a common exception.

> Mini-test for all users: can You optimize these pieces of code?

Answer in white:


1. Simply create a player local variable (like so:)

local player My_Player=GetTriggerPlayer()

and then instead of using GetTriggerPlayer() in the rest of the locals use My_Player

2. Create a unit local variable

local unit My_Unit=GetTriggerUnit()

and then in the rest of the calls unit My_Unit instead of GetTriggerUnit().


Edit:

> Yea but i thought bjs were use for memory

BJs mostly reduce speed, however, but they also increase trigger's size slightly (you use a function that calls a function instead of one simple function)
 

Andrewgosu

The Silent Pandaren Helper
Reaction score
716
Nah, You cannot escape so easily, with only setting GetTriggerUnit() into a variable in the second task of the 2. mini-test. ;)

There is still time to sign up and receive a assignment, when the time comes.
 
I

IKilledKEnny

Guest
> Nah, You cannot escape so easily, with only setting GetTriggerUnit() into a variable in the second task of the 2. mini-test.

Right, X's and Y's as well, forgot about that. :)

> There is still time to sign up and receive a assignment, when the time comes.

Waiting eagerly for it. :)
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
Nah, You cannot escape so easily, with only setting GetTriggerUnit() into a variable in the second task of the 2. mini-test. ;)
Spoilers:
The most efficient thing to do would probably be to not even set the triggering unit as a variable and just set GetUnitX and GetUnitY for triggering unit as locals; It's about the same amount of code as setting triggering unit AND the x and y as vars and more efficient since you aren't declaring a local and nullifying it later.
so the ultimate would probably be:
function LessFunctionCalls takes nothing returns nothing
local real x = GetUnitX(GetTriggerUnit())
local real y = GetUnitY(GetTriggerUnit())
call SetItemPosition(i,x,y)
call SetImagePosition(whichImage,x,y,0)
call SetCameraPosition(x,y)
call SetTextTagPos(t,x,y,200)
endfunction




BTW ignoring all fake variables in your code that aren't declared, you still have some syntax errors in the lesson. EG:
Code:
GetUnitX(GetTriggerUnit()[COLOR="Red"])[/COLOR]
The entire last block of code is missing crazy amounts of )'s, as an example.
 

Ninja_sheep

Heavy is credit to team!
Reaction score
64
Wow, it's allmost like the tutorials that i read on TH, but this 1 is more... compact.
you should make this into a jass-learning tutorial :)
 

Andrewgosu

The Silent Pandaren Helper
Reaction score
716
BTW ignoring all fake variables in your code that aren't declared, you still have some syntax errors in the lesson. EG:
Code:
GetUnitX(GetTriggerUnit()[COLOR="Red"])[/COLOR]
The entire last block of code is missing crazy amounts of )'s, as an example.

Sorry, yes. I made these by copy-paste, so 1 mistake while copying equals many mistakes when pasting. Fixed now.
 

Doom-Angel

Jass User (Just started using NewGen)
Reaction score
167
k pretty easy (first lesson i guess we still got harder stuff to learn)
here's my mini-test answers: (Spoiler)
Mini-test for everyone: can You put the right variable type into the brackets?
1)unit
2)texttag
3)group
4)force
5)location
6)trigger
7)real
8)boolexpr
9)integer
10)effect

A mini-exercise for everyone: can You find the equivalent natives to the BJ functions with the correct argument list?
1)SetUnitState(whichUnit, UNIT_STATE_LIFE, RMaxBJ(0,newValue))
2)SetPlayerState(whichPlayer, whichPlayerState, GetPlayerState(whichPlayer, whichPlayerState) + delta)
3)UnitRemoveAbility(whichUnit, abilityId)
4)SetHeroAgi(whichHero, value, true)

Mini-test for all users: can You optimize these pieces of code?
1)function LessFunctionCalls takes nothing returns nothing
local player p = GetTriggerPlayer()
local playercolor pc = GetPlayerColor(p)
local mapcontrol mc = GetPlayerController(p)
local real handicap = GetPlayerHandicap(p)
endfunction

2)function LessFunctionCalls takes nothing returns nothing
local unit u = GetTriggerUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
call SetItemPosition( i, x, y )
call SetImagePosition( whichImage, x, y, 0 )
call SetCameraPosition( x,y)
call SetTextTagPos( t, x, y,200 )
endfunction

i hope i got it all right :p
 
I

IKilledKEnny

Guest
> Doom-Angle

2)AdjustPlayerStateBJ(value - oldValue, whichPlayer, whichPlayerState) <== White text here

You still got an BJ there :p, also not the complete function if I recall correctly.

For second code look at post 7 in this theard.

Andrewgosu, when are you planning to send over the assignment?
 

Doom-Angel

Jass User (Just started using NewGen)
Reaction score
167
k thx Kenny i went deeper and found the non BJ one and also removed code tags since i couldn't hide it totally with code tag
 
I

IKilledKEnny

Guest
My bad for the second code, I ment post 7 (and 8). It's better to get the reals in locals as well.
 

XXXconanXXX

Cocktails anyone?
Reaction score
284
Please don't make a thread for every lesson. That'll get extremely annoying. This one's okay for now, but having 7 different threads for the same thing isn't necessary.
 

waaaks!

Zinctified
Reaction score
255
heres my answers...

Mini-test for everyone: can You put the right variable type into the brackets?
Code:
function MiniTest takes nothing returns nothing
    local unit u  = GetTriggerUnit()
    local texttag tt = CreateTextTag()
    local group g  = CreateGroup()
    local force f  = CreateForce()
    local location l  = GetUnitLoc(u)
    local trigger? t  = GetTriggeringTrigger()
    local real r  = 2.35
    local boolexpr b  = Condition( function RandomFunction ) //A tough one. ;-)
    local integer i  = 1 //2 options.
    local effect? e  = AddSpecialEffectTarget( "", u, "origin" ) // :-)
endfunction

Mini-test for all users: can You optimize these pieces of code?
Code:
function LessFunctionCalls takes nothing returns nothing
    local player p = GetTriggerPlayer()
    local playercolor pc = GetPlayerColor(p)
    local mapcontrol  mc = GetPlayerController(p)
    local real  handicap = GetPlayerHandicap(p)
endfunction

function LessFunctionCalls takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local integer  n = 200
    call SetItemPosition( i, GetUnitX(u), GetUnitY(u) )
    call SetImagePosition( whichImage, GetUnitX(u, GetUnitY(u), 0 )
    call SetCameraPosition( GetUnitX(u), GetUnitY(u) )
    call SetTextTagPos( t, GetUnitX(u), GetUnitY(u), n )
endfunction
 

Andrewgosu

The Silent Pandaren Helper
Reaction score
716
Andrewgosu, when are you planning to send over the assignment?

On Tuesday.

Please don't make a thread for every lesson. That'll get extremely annoying. This one's okay for now, but having 7 different threads for the same thing isn't necessary.

I thought that too, but, this lesson grew into something so monstrous (even I didn't expect to make it so large, as it explains quite simple things), that I didn't feel like to jam it into the "JASS Classroom" sign-up thread.
 
I

IKilledKEnny

Guest
> On Tuesday.

Great, thanks.

> that I didn't feel like to jam it into the "JASS Classroom" sign-up thread

I agree with you however we got already 3 JASS classrooms (your's, mine's and Tom Jone's) each got about 6-8 lessons.

7*3=21

21 theards is... alot. :eek: So I think it's better to keep the lessons in the sign-up theard. Anyway that's what I'm going to do, even if it a little messy... I'll probably ask an admin to clean it or somthing like that.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top