JASS: A Better Understanding

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
Welcome back to what has turned into a series to tutorials concerning JASS hot off my keyboard.
If you have not journeyed with me before into the realm of JASS, I suggest that you take a look at that past venture here:

JASS: A Concise Introduction

before continuing.
This tutorial will attempt to expand your understanding of what JASS is and enhance your abilities with it. I will endeavor to keep it as simple as I did last time as we move into more advanced concepts.
And I suppose that is what we are talking about in this tutorial.

Concepts.

A scary proposition. I'm not going to be giving you blocks of code with the words, "This chunk of code will do this for you." Not going to happen. The purpose of this tutorial is to make you understand JASS. Not just be able to wield it without knowing what it is. That would be like handing you some big, complicated weapon and saying, "Here! Press the big red button when the enemy gets close!" without even giving you an explanation of what, exactly, it is.

So, let us begin this newest trek.

Introduction (Take Two)

JASS is a programming language. Or, more simply, a language. You use this language to communicate with the computer what you want done. But computers are stupid. They do exactly what you tell them, when you tell them, in the manner that you tell them. And you must tell them what to do in a very specified way.

What does this mean? This means that whenever a computer does something you didn't want it to, it's not the computer's fault. It was, most unfortunately, yours. The programmer's. But don't let you discourage you. This is why you're reading a tutorial, right?

JASS has rules. Very strict rules, too. And you must follow them when telling the computer what to do.
So, let us move onward to telling the computer what to do in a proper manner, shall we?

Functions Revisited
And Boolexprs
We've looked at functions. But we need to look at them even more to fully comprehend what they can do.
Functions allow you to do actions. They are where you put your code.
They can take and return values. Take a look:

JASS:
function SomeFunc takes integer A returns integer
     return A + 5
endfunction


What's going on here? An integer was given, and an integer was returned. The integer that was taken got 5 added to it, and that value was returned. Simple enough? Certainly.

So, what can you do with your brand new function?
Use it.

How, you ask?
Well, let's say you wanted to use some number in a function, and you wanted to add 5 to it.
How about a loop condition? Remember loops?

JASS:
loop
    exitwhen SomeInteger > SomeFunc(5)
    // Do Stuff!
    set SomeInteger = SomeInteger + 1
endloop


What have we here? Our function we looked at above! It takes 5. But, how can it but used in an integer comparison? Take a look. It returns an integer. So, you can use it just like one! What will this function return? 10. 5 goes in, it adds 5, then returns it. 5 + 5 = 10. Easy.

Functions also have other purposes.
You know when you create some condition in your GUI trigger? That's a function.
Try this! Create a new trigger. Add some condition, and convert it to JASS. What do you get? Here's mine:
JASS:

function Trig_Untitled_Trigger_002_Conditions takes nothing returns boolean
    if ( not ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_Untitled_Trigger_002_Actions takes nothing returns nothing
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_002 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_002 = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_Untitled_Trigger_002, Condition( function Trig_Untitled_Trigger_002_Conditions ) )
    call TriggerAddAction( gg_trg_Untitled_Trigger_002, function Trig_Untitled_Trigger_002_Actions )
endfunction


Start at the bottom. There's the function that creates the trigger. Above it is the actions function. And above that is some new function. How does that work? Well, take a look down at the bottom again. See the call TriggerAddCondition line? That adds a condition to the function. The name of the trigger is there, and some thing that says Condition( function Trig_Untitled...). Well, that's the condition. Now look at that function up top.

Just read the first line. See how it returns boolean? That's how it gives you a yes or no for the trigger. It gives the trigger true or false to that condition that you entered. The syntax of that actual condition is there, but see how it returns true or returns false depending on the comparison. That's the key. It gives true or false back to the AddCondition call there at the bottom.

The Condition( function ...) part is a bit tricky. This is what is called a boolexpr. It's an entire condition that is in itself a function. You can store these in boolexpr variables if you wish. Boolexpr functions will always return a boolean. Unfortunately, they cannot take any parameters when used in this manner. JASS will yell at you for trying.


Pick Every Unit Functions and Matching Functions

Ah, yes. Everyone's favorite. Pick Every Unit and Do Actions. Hopefully you know how to eliminate the leaks that come with that. We'll be looking at it in JASS, of course.

So, create some such function and convert it. Here's what I have:

JASS:
function Trig_Untitled_Trigger_002_Func001A takes nothing returns nothing
endfunction

function Trig_Untitled_Trigger_002_Actions takes nothing returns nothing
    call ForGroupBJ( udg_SomeGroup, function Trig_Untitled_Trigger_002_Func001A )
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_002 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_002 = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Untitled_Trigger_002, function Trig_Untitled_Trigger_002_Actions )
endfunction


Again, start at the bottom. There's our trigger starter function. Now look up. There an action in the action function, but it doesn't look like something we want. It says call ForGroupBJ( udg_SomeGroup, function Trig_Untitled...).
What's this? Well, whatever actions you want to do under the Pick Every function go in their own function that is called through the ForGroupBJ function.

This means that actions you want to have happen to each unit goes in the function that is named in the ForGroupBJ call. The way you get the Picked Unit in that function is GetEnumUnit().

The same sort of thing happens with functions that set some group of units or use the Matching keyword are used. Take a look:

JASS:
function Trig_Untitled_Trigger_002_Func001002003 takes nothing returns boolean
    return ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) == true )
endfunction

function Trig_Untitled_Trigger_002_Actions takes nothing returns nothing
    set udg_SomeGroup = GetUnitsInRangeOfLocMatching(500.00, GetRectCenter(GetPlayableMapRect()), Condition(function Trig_Untitled_Trigger_002_Func001002003))
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_002 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_002 = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Untitled_Trigger_002, function Trig_Untitled_Trigger_002_Actions )
endfunction


See the Action function where it's setting the variable? It uses the GetUnitsInRange function and includes a condition just like we saw earlier. Yes, it's a boolexpr. And this function is using it to get the correct units to put into the unit group variable. It tests units, and puts them in the group if they meet the conditions. That's the equivalent of the Matching part of the function in GUI. Pretty simple. Here's the GUI that I used:

Code:
Set SomeGroup = (Units within 500.00 of (Center of (Playable map area)) matching (((Triggering unit) is A structure) Equal to True))


Local and Global Variables - The Shakedown

So, what are they? Well, global variables are the ones in the Variable Editor. You create them there and can use them in any trigger anywhere. They're Global to the entire world that is your map. So, how are local variables different? Well, let's explore that....

Local variables are created in a function and can only be used in that function. A quick example:

JASS:
function SomeFunc takes nothing returns nothing
     local unit SomeUnit = GetTriggerUnit()
endfunction


That creates a local unit variable called SomeUnit, and, for good measure, we set it to the triggering unit, assuming there is one.
You can use this variable in that function, and there's no need for a udg_ prefix! You can use it as-is.
The best thing about local variables is that they can't be overwritten. They only exist the one time the function is called. They act sort of like Triggering Unit in GUI. The same function can be called multiple times, but it won't lose what was stored the first time. That will be key when making spells MUI.

Leaks

With local variables come more leak problems. Any local handle - WHAT!? Handle! Huh!?!

Handles. A handle is basically some object in Warcraft. If you take a look at the basic variable types in JASSCraft, you may see that some extend handle. These things will most likely leak if you use local versions of them. This is because the thing you stored can't ever be accessed again, but it's still in that variable. This also can occur with objects that extend the widget type. You don't really have to know what all of that means, just know these things can leak.

Local units can leak.
So can timers.
Unit Groups leak a bit differently when they are locals.
Locations are the same as Unit Groups.

But these are fairly simple to resolve.

If the object has a destroy function, such as timers, use it first.

call DestroyTimer(SomeTimer)

call RemoveLocation(SomeLocation)

Then, set the variable to null. Like so:

set SomeUnit = null

set SomeGroup = null

Pretty easy. That should do it for your leaks.
Integers, reals, booleans, and some types like that do not need to be destroyed or nulled, so no need to worry about them! Hold on. Only one section left to go!


BJs

Remember that ForGroupBJ that we looked at earlier? That is a BJ function, hence the two letters there at the end. This stands for Blizzard JASS. Unfortunately for us, GUI uses a lot of these, and they can be inefficient.
Take a look at this:

JASS:
SetUnitAbilityLevelSwapped(integer abilcode, unit whichUnit, integer level)


This is a BJ function. It doesn't say BJ, but you can find out by looking in JASSCraft to see if that function calls another function. If it says native, though, it's not a BJ.
All this does is change the order of the parameters of the native function.
Here's the native:

JASS:
SetUnitAbilityLevel(unit whichUnit, integer abilcode, integer level)


See that? All the one above does is call this one with the things in the right place. Isn't that inefficient? It calls the first one, then the second one. When you're writing JASS, try to avoid these kinds of silly functions that make unnecessary calls.


Conclusion

So! How do you feel? Beat? Perhaps. But if you go over this tutorial a few times, I'm sure you can learn a few things. Remember this is the second tutorial in this series. I do not think it will be the last. I hope you enjoyed it, at least a little, and I'll see you back here for the next one!

The next tutorial will cover optimization as one of its topics. Just to give you something to look forward to!
 

ZiggyMcjoney

Data editor?! AAAHHHHH!
Reaction score
95
Excellent! This arrived on the day after I decided to start learning JASS :p.

Well done, this should be a good reference for me ;d.
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
A great tutorial. Haha, I'm going to make an optimization tutorial. >:O

Well, I was thinking about it for a few days, so ~reserve~ :D

jk, but this tutorial is great. Also, you should probably just mention that the only deficiency of BJs is that they are slower than natives. And some have some sort of error like a leak or desyncy code. xD

Also, I don't think you mentioned (or it is unclear) that you can't use local variables outside of the function.

Nothing else to comment other than that, good job and +rep if I can. ;)
 

emjlr3

Change can be a good thing
Reaction score
395
wrote with bone heads in mind, gj
 

Sim

Forum Administrator
Staff member
Reaction score
534
You might want to add in stuff about loops. They're useful for beginners!

Great tutorial by the way. :D

EDIT: Wow. I did read through it fast. Never noticed. :p

Nevermind then.
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
> wrote with bone heads in mind

Indeed. Or people who need a different perspective.

> You might want to add in stuff about loops.

Did you read my first tutorial? :p
Loops are there. Along with Ifs and Returns.
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
JASS:
function Bump takes Thread T returns nothing
     call SetThreadPosition(T, 1)
     call CreatePost(T, Ghan_04)
endfunction


JASS:
call Bump(GetTriggingThread())
 

Larcenist

REP: Respect, Envy, Prosperity?
Reaction score
211
This tutorial made me give JASS another shot, for the 5th time or something. So I read it, then though that I'm ready for some spell making, succeeded to make 3 spells which didn't do anything and finally realised that it's not good to forget the "endloop" at the end of your loops.

I guess I'm condemned to a lifetime of GUI triggering. Good tutorial though, now I've increased my JASS-knowledge by a noticable amount.
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
SUPER Bump

It's been awhile, but I'm bringing this back to see if I might be able to get it approved. :D
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Free BUMP!

Maybe you could include a short definition of "null". Simply put:

Nulling clears the data stored within the variable. Once nulled, it refers to nothing rather than the previous data it was holding.

;)

Seems good to meh other than that!
 

The Helper

Necromancy Power over 9000
Staff member
Reaction score
1,701
5 Star Bump

5 Star Bump!

This tutorial only has 2 ratings. Please consider reviewing this tutorial and giving a rating. Thanks!
 

WolfieeifloW

WEHZ Helper
Reaction score
372
Again Ghan_04;
A great tutorial.
And yet again, [del]it makes[/del] you make the user feel a part of the tutorial.
Waiting for the third tutorial in your "series"!
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top