Tutorial Learning JASS and vJASS

Vestras

Retired
Reaction score
249
Contents:
1.0 - Introduction
2.0 - Basics of a function
2.1 - Operators
2.2 - Declaring locals
2.3 - GUI vs JASS variables
2.4 - JASS and GUI variables
2.5 - Loops
2.5 - Handles
3.0 - vJASS
4.0 - Scopes and Libraries
5.0 - Private and Public members
5.1 - ADD ON - Constants
5.2 - ADD ON - Globals and Structs
6.0 - Goodbye

Introduction
Many people think that JASS is the l33tz00rdz language, this is not true. Basicly, when making GUI, you also create JASS lines. Example:

Code:
Unit - Create 1 Footman for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
is the same as
JASS:


Yes, I know this looks complicated, but it is not. The 1 is the number of units created, the 'hfoo' is the raw code (Go to your object editor, press CTRL + D to view raw codes of units), Player(0) is the player id (Remember, that player 0 is player 1, player 1 is player 2, etc.). GetRectCenter(GetPlayableMapRect()) is where the unit is created, in this case the center of the map (A rect is the same as a region), and finally the bj_UNIT_FACING is the default facing of a unit, in this case, 270.00.

Not to hard when explained, right?

Basics of a function
A function is everything. A function is the same as above. Functions are the things that makes everything run.
This is a native function:
Code:
native UnitApplyTimedLife takes unit whichUnit, integer buffId, real duration returns nothing
(Taken from JASSHelper in Jass NewGen Pack)
And this is a BJ:
JASS:
function UnitApplyTimedLifeBJ takes real duration, integer buffId, unit whichUnit returns nothing
    call UnitApplyTimedLife(whichUnit, buffId, duration)
endfunction

They does the same thing, only that the BJ is slower. (In JNGP (Jass NewGen Pack), BJ are red and natives purple. Why is a BJ slower, and what is a BJ? Well, a BJ is slower because it calls a native function, and a BJ is a totally useless function made by Blizzard. (Well, some BJs are really nice though.) GUI uses BJs. There is some BJs who are usefull though. Nonfunction BJs (such as the bj_lastCreatedUnit instead of GetLastCreatedUnit(), bj_mapInitialPlayableArea instead of GetPlayableMapRect() and so on), but the most usefull BJ is probably the BJDebugMsg. This is used by the most JASSers to find out bugs, and basicly it displays a message to all players. This can be used for finding out which functions runs and which doesn't.

Yes, this is rather complicated, but don't hesitate with reading it again.
When you use a function, you always need the call before the function name, and when you have typed the function name, you create a ( , then type in the arguments, and when done, you create a ). Wolla, you created an argument! Example:call UnitApplyTimedLife(GetTriggerUnit(), 'BTLF', 2.00)
1. This is where you call. 2. The function name. 3. The (. 4. The unit I want to have timed life. 5. The raw code of the buff, just use this always. 6.The real which shows have long the timed life is. 7. The end ).

Now, many functions takes Arguements, such as the UnitApplyTimedLife functions. Example:
JASS:
call UnitApplyTimedLife(The first one(GetTriggerUnit()) is the unit arguement, the second one('BTLF') is an integer raw code, and the last one(2.00) is a real arguement)


Most systems uses arguements (Check out my Knockback System. When you call the function KS_SingleKnock(...) Everything inside the () is arguements. The unit being knocked back, the range and so on)

Now, functions can also return.
The GetTriggerUnit() doesn't take arguements, but it returns a unit. If it didn't return the unit, the function would do nothing. When you refer to GetTriggerUnit(), it returns a unit for the function, so that the functions knows which unit to take.

Got it? Great! Then let's move on!

Operators
The operators are as following:
not = When used in an if/then/else, it can be used to "negativize", meaning that if you put a not, it will if the condition is not then do etc., etc.
== represents Equal To.
!= represents Not Equal To.
> represents Greater Than.
>= represents Greater Than Or Equal To.
< represents Less Than.
<= represents Less Than Or Equal To.

These are mostly used in if/then/elses. Example:
JASS:
function testif takes nothing returns nothing
if not MyBoolean == true then
   call DoNothing // Just used in this example, do <b>never</b> use DoNothing. It&#039;s a BJ that does nothing.
 endif // Always use endif when you end your if/then/else. Else it will cause a syntax error.
endfunction

This is executed if not my Boolean is true. So this will actually happen when my Boolean is everything else than true.

Got it? Then let's go on.

Declaring locals
Locals are variables that can only be used in that function they are declared in. Example:
JASS:
function declaring takes nothing returns nothing
local integer testint = 1
endfunction

function syntaxerror takes nothing returns nothing
set testint = 2
endfunction


Now, this would give us a JASShelper error: "Undeclared variable testint", because testint doesn't excist in the function syntaxerror.

Globals are the brother of locals. They can be used in any function, and will cause errors if another local, global or function is declared with the same name as the global. Unless they are private or public, of course. (More about this later on)
GUI variables are globals.

REMEMBER: Locals always need to be in top of the function(s), and globals needs to be inside a globals statement. Example:
Code:
globals
unit testunit
endglobals

NOTICE - variables with arrays cannot be initialized!

GUI vs JASS variables
Many people go wrong about this. In WEU, in your GUI create variables box, there is a () where there stands the variables name in JASS. Now, I think (correct me if I'm wrong) that you can also see this in JASSCraft.

Example:
In JASS, unittypes are types such as heroes, structures. (These are declared with UNIT_TYPE_HERO) And in GUI, unittypes are things such as peasants, footmans etc. I'll leave this for you.

Loops
Loops can be used for many things, and is the same as a GUI
JASS:
For each (Integer A) from 1 to 10, do (Actions)
    Loop - Actions

Well, you need a little bit more lines. Example:

JASS:
function MyTestLoop takes nothing returns nothing
   local integer StartLoop = 1
   local integer EndLoop = 10
     
     loop
       exitwhen StartLoop &gt; EndLoop
         call UnitApplyTimedLife(GetTriggerUnit(), &#039;BTLF&#039;, 2.00)
       set StartLoop = StartLoop + 1
     endloop
endfunction


That's a loop.

Now, there are more complex versions of a loop. In GUI, it's normally just from one integer to another, here you can do it with every single condition with the exitwhen. In many spells, they use a loop for damaging instead of damaging a point (if they don't want allies to be damaged), because sometimes damaging groups can cause problems on macs.

Well, this is the loop they use:

JASS:
function Damage takes nothing returns nothing
   local group g = (This is just your group)
   local unit u // We do not set this one yet
     loop
       set u = FirstOfGroup(g)
       exitwhen u == null
          call UnitDamageTarget(...)
       call GroupRemoveUnit(g, u)
     endloop
endfunction


Got it? Great!

Handles
Now, this is the hard piece;

JASS:


These are reals. When you are done with your trigger, and are about to clear leaks, these do not leaks, but because they are kind of "native handles". Now, this leaks:



Why? This is why:

locations extends handles!

EVERY SINGLE LOCAL THAT EXTENDS A HANDLE NEEDS TO BE REMOVED AND NULLED. ELSE IT WILL LEAK.
It is very important that you understant exactly this. Why? Because too many leaks can cause server splits.

Well, I can tell you which locals that doesn't extends a handle.

reals
integers
booleans
string

(How to find out if a local extends a handle? Most people uses JASSCraft)
These are basicly the locals that doesn't extend a handle.

(You can't null or destroy strings, you when cleaning strings, just do
set MyString = ""
)

If you get this, then you clearly are able to move on to vJASS. If not, read everything all over.

vJASS
vJASS is an extended JASS language which are available in JNGP. If you write vJASS in normal WE, your WE will crash and your map become unplayable and unopenable.

vJASS are great because of these "things":

It got public members.
It got private members.
It got scopes.
It got libraries.

You will learn about this later on.

JNGP is downloadable here: http://wc3campaigns.net/showthread.php?t=90999

Scopes and Libraries.
A Scope is mostly used for spells, but can be used for everything, though libraries are most appreciated for systems.

Example:

JASS:
scope MySpell
  private function Actions takes nothing returns nothing
  endfunction
endscope


private and public members are only available in scopes and libraries. (A member is something put before the function keyword. (Can also be other things, such as globals))

You can have a scope inside a scope. Example:
JASS:
scope Test1
   scope Test2
   endscope
endscope


But you cannot have a library inside a library. Example:
JASS:
library Test1
   library Test2
   endlibrary
library


A library is placed in the map header when compiling (saving) the map in wc3, (the map's script), so a trigger inside a library doesn't need an InitTrig.

A library can have requirements. The only thing the requirements does, is that before the map can save, you need the required libraries. This is good for making people remembering subsystems.

Now, a scope can have initializers. They actually does the same things as InitTrigs, just that you can name your InitTrig everything you like.
NOTICE - Libraries can actually have initializers too!
Example:

JASS:
scope Test initializer haha

function haha takes nothing returns nothing
   set gg_trg_Test = CreateTrigger()
endfunction

endscope


This would do the exact same thing as a normal InitTrig.

And then there are requires/uses/needs:

JASS:
library Test initializer haha uses (Could be requires or needs too) MySystem

function haha takes nothing returns nothing
   set gg_trg_Test = CreateTrigger()
endfunction

endscope

The requires/uses/needs is mostly for making people have one syntax error than many when they don't got the used library.

Got it? Then we go on to the purpose of libraries and scopes, the members.

Private and Public members.
JASS:
scope MyTestScope

public function Test takes nothing returns nothing
endfunction

endscope


JASSHelper said:
The way private work is actually by automatically prefixing scopename(random digit)__ to the identifier names of the private members
Example:

JASS:
scope MySpell

private function Actions takes nothing returns nothing
endfunction

endscope


Get it? It's actually the same with public members, just that a public member isn't generated randomly. It will be generated to <YourScopeOrLibraryName>_<YourFunctionName>. This is mostly used for systems where you call a function.

Simple, isn't it?

Constants
Now, constants are mostly used for conditions, global variables (see lower down) and returning-functions. Well, a constant basicly makes the function/variable non-editable throughout the game.

Globals and Structs
Globals
Before vJASS, you had to use functions for every single thing, such as raw codes. So you had to make a gigantic function, just for returning a raw code. Pretty unpractical. Now, with vJASS, you can use globals, example:
JASS:
globals
   constant integer AbilityRawCode     = &#039;A000&#039;
endglobals

Simplifies the whole process a lot, right? It does the same thing - returns a value.
Structs
Structs are basicly integers, but can be used to store data in. This is where Struct Attaching Systems gets into the picture. Structs are used to store in, like, we maybe had a unit named caster in it, a unit named target in it and a timer. Like this:
JASS:
scope MySpell

private struct MyData
  unit caster
  unit target
  timer tim
endstruct

endscope


Okay? Now, when using structs, you can do various things, but in this example we will use local structs and SAS (Struct Attaching Systems). This time we'll use TimerUtils by Vexorian.

JASS:
scope MySpell

private struct MyData
  unit caster
  unit target
  timer tim
endstruct

private function TimerActions takes nothing returns nothing
  <b>local MyData d = GetTimerData(GetExpiredTimer())</b>
  // Do actions with d.target here...
endfunction

private function Actions takes nothing returns nothing
  <b>local MyData d = MyData.create()</b> // This is always needed. When &quot;initializing&quot; a struct, you must do that!
  set d.caster = GetTriggerUnit()
  set d.target = GetSpellTargetUnit()
  set d.tim = <b>NewTimer()</b>
   <b>call SetTimerData(d.tim, d)</b>
       call TimerStart(d.tim, 0.03, true, function TimerActions)
endfunction

endscope

NOTICE - Inside structs, there can be methods, but I do not know much about that, so I suggest you reading the JASSHelper Manual by Vexorian.

Now, the bolded lines are those who you should be paying attention to.
local MyData d = MyData.create() - This is where you create your MyData struct, so you can use it in your function. The MyData parts must always be the same as your struct name.

call SetTimerData(d.tim, d) - This is where we set the data which should be attached to the specified timer, d.tim. d.tim is the timer argument, and d is our struct.

local MyData d = GetTimerData(GetExpiredTimer()) - This is where we recieve our data. We cannot use d.tim here, because we haven't created the struct when it compiles, so it gives us syntax errors. It must always be GetExpiredTimer().

Got it? Great!

Goodbye
Well, I hope you learned something from this tutorial. I look forward to reviewing any of you JASS spells!
 

Flare

Stops copies me!
Reaction score
662
Would it not be a good idea to fix the stuff that had been pointed out in the other forums you submitted this before submitting it here? Alot of the things that require fixing are long-outstanding...

And (maybe I'm the only one who thinks this but) it's difficult to take a tutorial seriously, or follow it, when you have grammatical mistakes throughout
There is some BJs who are usefull though
is -> are (is = singular, are = plural)
who -> which
usefull -> useful

It got public members.
It got private members.
It got scopes.
It got libraries.
got -> has

(There are a few more I saw earlier, but can't find them again right now - I'll find them later when I have more time)

So you had to make a gigantic function
This
JASS:
constant function SpellId takes nothing returns integer
  return &#039;A000&#039;
endfunction

is a gigantic function?

The requires/uses/needs is mostly for making people have one syntax error than many when they don't got the used library.
Ahm... what? Can you explain what you're trying to say there?
 

Forty

New Member
Reaction score
6
maybe use the
JASS:
-tags for better readability?

and i dont think it will help the people too much. its just too much information at once.
 

Romek

Super Moderator
Reaction score
964
> functions are everything
Not really.

You also start explaining BJ's when the person reading hardly knows what a function is.

> Check out my Knockback System
Ahh great Idea. Lets just go straight into massive long codes.

> If you write vJASS in normal WE, your WE will crash and your map become unplayable and unopenable.
Wtf? At worst, it'll crash.

It seems like you explain some arguments for a few [2] functions, then go into the more complicated stuff.

This isn't good at all.
Oh, and use JASS tags instead of Code tags.
 

Vestras

Retired
Reaction score
249
Would it not be a good idea to fix the stuff that had been pointed out in the other forums you submitted this before submitting it here? Alot of the things that require fixing are long-outstanding...

Well, yes. Too late :( I'm just gonna update this one along with the others.

> maybe use the
JASS:
-tags for better readability?

and i dont think it will help the people too much. its just too much information at once.

Fixed. Well, JASS is a big piece of text <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite7" alt=":p" title="Stick Out Tongue    :p" loading="lazy" data-shortname=":p" />

&gt; Not really.

You also start explaining BJ&#039;s when the person reading hardly knows what a function is.

So?

&gt; Ahh great Idea. Lets just go straight into massive long codes.

It was just an example..

&gt; Wtf? At worst, it&#039;ll crash.

My maps became unopenable.

&gt; It seems like you explain some arguments for a few [2] functions, then go into the more complicated stuff.

The same thing as JASSHelper.

&gt; This isn&#039;t good at all.

Just because of those small things?
 

Flare

Stops copies me!
Reaction score
662
It was just an example..
Go for short, simple examples (find a particular code snippet around the forums that you like, PM the author asking for permission to use it, then use that as your example of a function that takes and/or returns values). Take AndrewGosu's IsPositionPathable snippet for example - it's very short (only 7 lines, as opposed to 150 :p), it demonstrates how a function can take and return values and it's carrying out a fairly simple 'job' rather than sliding units here, there and everywhere, you know?

The same thing as JASSHelper.
I assume you're talking about the JASSHelper manual? If so, Vexorian probably assumed (apologies if I'm wrong :eek:) that the reader has some sort of knowledge of JASS beforehand (since knowing vJASS without knowing JASS isn't much good :p) whereas you shouldn't be making this assumption since you're trying to teach people about JASS -AND- vJASS if the thread title is correct

Also (just a cosmetic change to the tutorial's layout):
Would be nice if you added the 'section number' before each heading, increased the size of each heading, centred the headings (possibly) and added an extra line or two between each section (possibly) e.g.
1.0 -Introduction
La di da, let's introduce the tutorial, what's gonna be discussed in the tutorial, bla bla bla


2.0 - Basics of a function
La di da, now we're going to talk about the basics of a function, how you declare them, how you use them, and some typical things that are associated with functions


2.1 - Operators
I'm sure you get the picture by now
And one more la di da, bla bla bla, just for good measure :D
(Alternatively, instead of increasing the heading size, you could bold and underline it)

As it is right now, it just seems very monotonous apart from the odd colour change - there's nothing that makes it hugely obvious that you're moving into the next section (since nothing is different apart from the font)

And your section numbers are a bit messed up - why are operators and local declaration in the same 'main section' if you go by their number? Same with loops and pretty much everything else in 2.X
 

Romek

Super Moderator
Reaction score
964
> This isn't good at all.

Just because of those small things?

Not only.
Just generally. I think it's too complicated for newbies and too basic for probies.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • 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 The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top