• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] Learning JASS. Last Question

Status
Not open for further replies.
Level 16
Joined
Mar 3, 2006
Messages
1,564
Learning vJASS

I have asked before how to learn JASS but this will be the last question to ask how to learn JASS.

I am in a dire need of learning JASS but I'm not a programmer, how do I learn JASS. There is JASS manual but I can't learn from it or don't understand how to use it when making JASS. Please, good people of Hiveworkshop point me to where to start JASS and become profesional using it.
 
Last edited:
Level 3
Joined
Aug 9, 2008
Messages
60
Start off by converting GUI triggers into jass, getting rid of all the BJs, and replacing as many globals into locals as possible.

Suggest you get Jass New Gen, it makes vJass very easy.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
  • Initialization
    • Events
      • Map initialization
    • Conditions
    • Actions
When converted to JASS

JASS:
function Trig_Initialization_Actions takes nothing returns nothing
endfunction
//===========================================================================
function InitTrig_Initialization takes nothing returns nothing
    set gg_trg_Initialization = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Initialization, function Trig_Initialization_Actions )
endfunction

Is this a native or BJ ? And where is the event 'Map Initialization' in the JASS code ?
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
I suggest getting Jass NewGen Pack whether you'll use extended JASS (vJass) or not. You can find it on wc3c.net under Resources > Tools. It has syntax highlighting, so you won't need an additional JASS editor.

But I suggest starting with vJass, because you don't have to know regular JASS to start vJass, afaik.

All the BJs will be highlighted with the "evil red color" :p, so you'll notice. Once you've found a BJ, you'll know how to replace it if you move the type cursor to that function and then you can do ctrl + left click on that function. The function list will pop-up and you'll find your way.

TriggerAddAction is a native, for example, but if you convert a generic unit event to JASS, you'll notice it has a BJ suffix (and it's highlighted with red). Most BJs have that suffix, but not all of them.

If you're talking about jasshelper manual, that's considered advanced jass. So don't let it be a surprise that if you're new to the programming scene, jasshelper manual won't learn you anything yet.

I think he's talking about this one :D.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
TriggerAddAction is a native, for example, but if you convert a generic unit event to JASS, you'll notice it has a BJ suffix (and it's highlighted with red). Most BJs have that suffix, but not all of them.

Yes I noticed this when I convert this trigger to JASS:

  • T2JASS
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
JASS:
call TriggerRegisterAnyUnitEventBJ( gg_trg_T2JASS, EVENT_PLAYER_UNIT_DEATH )

In order to make it native, it must be (I think):

JASS:
call TriggerAddEvent(gg_trg_T2JASS,EVENT)
right ?
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
No.

One of the exceptions where BJ's aren't that bad is event registrations. TriggerRegisterAnyUnitEventBJ has following native counterpart:

TriggerRegisterPlayerUnitEvent. However, that event only works on units of a specified player. What TriggerRegisterAnyUnitEventBJ does is loop through all players and register the PlayerUnitEvent for the picked player.

You're also unlucky to have chosen "Map Initialization" as your event, because there's no such event in jass. In jass, you have to check the checkbox at the top of the trigger that reads "map initialization".

Triggers are also something "difficult" to work with if you're new to jass. Basically, a trigger is an object. Events are registered to triggers. Once registered they cannot be removed, hence why you don't add events (and don't remove events) but register them.
Conditions and actions can be added and removed though. A big difference with a GUI trigger is that in jass you can add as many actions to a trigger as you want, while in GUI you can only add one action (which consists of all sub-actions you see in GUI).
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
No.

One of the exceptions where BJ's aren't that bad is event registrations. TriggerRegisterAnyUnitEventBJ has following native counterpart:

TriggerRegisterPlayerUnitEvent. However, that event only works on units of a specified player. What TriggerRegisterAnyUnitEventBJ does is loop through all players and register the PlayerUnitEvent for the picked player.

So this is better than the native function:
JASS:
call TriggerRegisterPlayerEvent(TRIGGER,PLAYER,EVENT)


A big difference with a GUI trigger is that in jass you can add as many actions to a trigger as you want, while in GUI you can only add one action (which consists of all sub-actions you see in GUI).

So all the list of actions are considered as on action.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
JNGP is almost a vital tool to do JASS, as it really makes it easier. Better global control allows you to use globals for tasks easier. Library and scopes allow better naming of code. Finally the native list allows for easier finding of needed natives. Also the syntax checker is less fail than WE's normal one, and so will not crash if you do some kinds of errors and will do correct reports of invalid lines.
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
So this is better than the native function:
JASS:
call TriggerRegisterPlayerEvent(TRIGGER,PLAYER,EVENT)

Yeah, but you have to understand why. TriggerRegisterPlayerEvent can only register one player per call, so what TriggerRegisterAnyUnitEventBJ is it registers the event for all players (through a loop).

So all the list of actions are considered as on action.

Yeah. People who work in GUI have a different concept of a trigger. They think that a trigger is something that in fact is some kind of a "folder" where you can have multiple triggers.

For example:

JASS:
function Trig_Initialization_Actions takes nothing returns nothing
endfunction
//===========================================================================
function InitTrig_Initialization takes nothing returns nothing
    set gg_trg_Initialization = CreateTrigger( )
    call TriggerAddAction( gg_trg_Initialization, function Trig_Initialization_Actions )
endfunction

Now I have only one trigger, but I can do this:

JASS:
function T_Actions takes nothing returns nothing
endfunction

function Trig_Initialization_Actions takes nothing returns nothing
endfunction
//===========================================================================
function InitTrig_Initialization takes nothing returns nothing
    local trigger t = CreateTrigger()
    set gg_trg_Initialization = CreateTrigger( )
    call TriggerAddAction( gg_trg_Initialization, function Trig_Initialization_Actions )

    call TriggerRegisterPlayerUnitEvent(t, ...)
    call TriggerAddAction(t, function T_Actions)
endfunction

Now I have two triggers, each running independently on one another.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
JNGP means Jass New Generation Pack.

Ok, I tried it and found it a useful tool as it explain how BJs work with native.

As Eleandor says about the register event:

JASS:
function TriggerRegisterAnyUnitEventBJ takes trigger trig, playerunitevent whichEvent returns nothing
    local integer index
    set index = 0
    loop
        call TriggerRegisterPlayerUnitEvent(trig, Player(index), whichEvent, null)
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
endfunction

The BJ seems to check for every unit owned by player. But what if I used the native that is used in the BJ loop. What is the difference between them if I used them for a certain player and don't want to cycle through all players, which will be better to use BJ or native ?
 
Last edited:
Level 12
Joined
Jul 27, 2008
Messages
1,181
TriggerRegisterAnyUnitEventBJ = any unit event (very useful, also better than 12 or so events to avoin one BJ
TriggerRegisterPlayerUnitEvent = any unit belonging to player event.

You need 12 TriggerRegisterPlayerUnitEvent to do what one TriggerRegisterAnyUnitEventBJ does, so its not inefficient in this case.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Starquizer, you can set a local to anything you wish as long as it is the same type as the local. Eg, you can set a unit local to anything that has a unit value, like CreateUnit, another variable, or even with a bug (which is unsafe) an integer represntation of a unit.

The BJ for all players event creates about 16 events (12 for players and 4 for extra NPC players). Thus for efficency I advise only creating events for players who the event will have an affect. EG, if your map only uses players 1-4 and the neutrals, it is pointless making events for players 5-12, thus you can save 8 events and thus 8 handle indexes.

This however is known as exessive efficency seeking. Generally it is advisable to do this when you have finished your map and are perfecting it.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
globals is easier to handle but is known to have an extremely small chance to cause problems.

Global variables have no problems, your code does.

when it is better to use local above global and use globals above of locals ?

Anyway, it's pretty obvious when to use locals and when to use globals:
- When your code can run multiple instances at the same time, always use locals.
- When your code runs only once at a time, you can use globals or locals, whatever is move convenient for that trigger.

A code can run multiple instances at the same time by using a wait (TriggerSleepAction() and his friends), or by using a timer (executefunc() (or whatever was the name) too?).
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
JASS:
globals
 unit u = gg_unit_hpea_0000
 location p = OffsetLocation(GetRectCenter(GetPlayableMapRect()), 256.00, 1024.00)
 
endglobals
function Trig_Melee_Initialization_Actions takes nothing returns nothing
//   local unit u = gg_unit_hpea_0000
//   local location p = OffsetLocation(GetRectCenter(GetPlayableMapRect()), 256.00, 1024.00)
    call IssuePointOrderLocBJ( u, "move", p )
endfunction
//===========================================================================
function InitTrig_Melee_Initialization takes nothing returns nothing
    set gg_trg_Melee_Initialization = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Melee_Initialization, function Trig_Melee_Initialization_Actions )
endfunction

Why this script gives me an error ? Is there a problem with the globals or must I write the script in the Custom Script Code area.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
gg_unit_hpea_0000 is not initialized when you copy the value into u
BJs dont work when initializing globals.


Does it work with natives ? if so then what is the native of:

JASS:
call IssuePointOrderLocBJ( u, "move", p )

When I used the JNGP I found the previous BJ function as this:

JASS:
function IssuePointOrderLocBJ takes unit whichUnit, string order, location whichLocation returns boolean
    return IssuePointOrderLoc( whichUnit, order, whichLocation )
endfunction


<<ADDED>>

I want to pick every unit within 512 radius of a position and do some action, like ,for example, killing them or changing their ownership, what is the native functions for this. I have written this:

JASS:
function Trig_jass_Actions takes nothing returns nothing
    local group g
    call GroupEnumUnitsInRange( g , 0 , 0 , 512 , null )
endfunction
//===========================================================================
function InitTrig_jass takes nothing returns nothing
    set gg_trg_jass = CreateTrigger(  )
    call TriggerRegisterPlayerEvent(gg_trg_jass, Player(0), EVENT_PLAYER_END_CINEMATIC)
    call TriggerAddAction( gg_trg_jass, function Trig_jass_Actions )
endfunction

But this will pick every unit in g group (which is empty) within 512 range from 0,0 point.
 
Last edited:
Level 16
Joined
Mar 3, 2006
Messages
1,564
The group has to be created first. Use the line
JASS:
    local group g = CreateGroup()

JASS:
function Trig_jass_Actions takes nothing returns nothing
    local group g = CreateGroup()
    call GroupEnumUnitsInRange( g , 0 , 0 , 512 , null )
endfunction

in the function
JASS:
GroupEnumUnitsInRange( g , 0 , 0 , 512 , null )
the group g is the group that the 512 In-Range units will be added to OR it is the group which the function will pick units from ?

Now about adding an action:
I want to pick every unit within 512 and kill them, do I say KillUnit(g) ?
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
JASS:
loop
    exitwhen firstofgroup(g)==null
    call killunit(firstofgroup(g))
    call groupremoveunit(firstofgroup(g))
endloop


So it will be:

JASS:
function Trig_jass_Actions takes nothing returns nothing
    local group g
    call GroupEnumUnitsInRange( g , 0 , 0 , 512 , null )
  loop
    exitwhen firstofgroup(g)==null
    call killunit(firstofgroup(g))
    call groupremoveunit(firstofgroup(g))
  endloop
endfunction
//===========================================================================
function InitTrig_jass takes nothing returns nothing
    set gg_trg_jass = CreateTrigger(  )
    call TriggerRegisterPlayerEvent(gg_trg_jass, Player(0), EVENT_PLAYER_END_CINEMATIC)
    call TriggerAddAction( gg_trg_jass, function Trig_jass_Actions )
endfunction

That will result in killing the units within 512 of 0,0 when I press [ESC]

============================================================

But I don't know why or how to put the

firstofgroup(g) in a variable first.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Use your brain?

JASS:
function Trig_jass_Actions takes nothing returns nothing
    local group g
    local unit u
    call GroupEnumUnitsInRange(g,0,0,512,null)
    
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        call GroupRemoveUnit(u)

        call KillUnit(u)
    endloop

    call DestroyGroup(g)
    set g = null
endfunction
//===========================================================================
function InitTrig_jass takes nothing returns nothing
    set gg_trg_jass = CreateTrigger( )
    call TriggerRegisterPlayerEvent(gg_trg_jass, Player(0), EVENT_PLAYER_END_CINEMATIC)
    call TriggerAddAction( gg_trg_jass, function Trig_jass_Actions )
endfunction
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
JASS:
GroupRemoveUnit(u)

What does this function do ?

<<EDIT>>

And by the way this function takes group and unit so it should be
JASS:
GroupRemoveUnit(g,u)
but I still don't know what does this function do ?

Sorry about that, I coded it free hand off memory.

The whole point of it is to go through the units in the loop without calling another function, so the loop does it's actions as long as there are units in the group referring to the first, and removing that first at the end of the actions.

And also, make sure you have the right CaPiTaLiZaTiOn since it matters in jass.
 
Level 15
Joined
Jul 19, 2007
Messages
618
boolexpr is another type which extends the handle (object) it is used to pick units which are matching condition (for example only kill structures...)

however the code people here showed you causes leaks and is slow!

JASS:
globals
    filterfunc Dummy_Filter = null
endglobals

constant function NonLeakingFilter takes nothing returns boolean
    return true
endfunction

function KillEnumUnits takes nothing returns nothing
    call KillUnit(GetEnumUnit())
endfunction

function Trig_jass_Actions takes nothing returns nothing
    local group g = CreateGroup()
    call GroupEnumUnitsInRange( g , 0. , 0. , 512., Dummy_Filter )
    call ForGroup(g, function KillEnumUnits)
    call DestroyGroup(g)
    set g = null
endfunction
//===========================================================================
function InitTrig_jass takes nothing returns nothing
    set gg_trg_jass = CreateTrigger( )
    call TriggerRegisterPlayerEvent(gg_trg_jass, Player(0), EVENT_PLAYER_END_CINEMATIC)
    call TriggerAddAction( gg_trg_jass, function Trig_jass_Actions )
    set Dummy_Filter = Filter(function NonLeakingFilter)
endfunction

thats the way its done! ForGroup is a fast native function (not coz its native but coz it uses foreach loop in c++) which is like 16x faster then in jass (or even more)! i just know with my testing that loops are a so slow that its not to talk about them...

and that boolexpr filter was leaking each time you pick units in the group... however even my code is not fully leakless... coz when u add unit to group it is a leak... currently there are is no possible way to do fully leakless groups... that is until 1.23b patch is out ill release my top coded librarys which will contain fully leakless groups and perfect leakless damage detection (as well as melee / spell damage detection) + many more!

however for now i think that for u best way is to start with vjass insted of jass... in my option jass is way to harder then vjass...

Greets!
~Dark Dragon
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
JASS:
globals
    filterfunc Dummy_Filter = null
endglobals

What is the function of this; can't I simply add null.
-----------------------------------------------------------------------
JASS:
constant function NonLeakingFilter takes nothing returns boolean
return true
endfunction

And also what is the purpose of this function ?
-----------------------------------------------------------------------
JASS:
function KillEnumUnits takes nothing returns nothing
call KillUnit(GetEnumUnit())
endfunction

Also I am a bit confused with this part and how it is executed in the next function:
JASS:
call ForGroup(g, function KillEnumUnits)
-----------------------------------------------------------------------
however for now i think that for u best way is to start with vjass insted of jass... in my option jass is way to harder then vjass...

Greets!
~Dark Dragon

Isn't vJASS a complementary for JASS; I mean I must learn JASS functions first and what they do then learn vJASS. To my understanding vJASS don't add any new functions but just organize the JASS script and rewite it in a good way that can be read by the game with better script execution. (Correct if my understanding to vJASS is wrong)
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
Yes you are right, vJass is simply a preprocessor of jass (the custom utils compile it into "real" jass when you save your map), but vJass makes things so much easier that many people prefer to learn it at the same time as jass. I tried to do this, but I started simple (globals block, libs), and made my way to the important stuff (structs, scopes)
 
Level 15
Joined
Jul 19, 2007
Messages
618
JASS:
globals
    filterfunc Dummy_Filter = null
endglobals

What is the function of this; can't I simply add null.
-----------------------------------------------------------------------
JASS:
constant function NonLeakingFilter takes nothing returns boolean
return true
endfunction

And also what is the purpose of this function ?
-----------------------------------------------------------------------
JASS:
function KillEnumUnits takes nothing returns nothing
call KillUnit(GetEnumUnit())
endfunction

Also I am a bit confused with this part and how it is executed in the next function:
JASS:
call ForGroup(g, function KillEnumUnits)
-----------------------------------------------------------------------


Isn't vJASS a complementary for JASS; I mean I must learn JASS functions first and what they do then learn vJASS. To my understanding vJASS don't add any new functions but just organize the JASS script and rewite it in a good way that can be read by the game with better script execution. (Correct if my understanding to vJASS is wrong)

this global block defines a new variable of type filterfunc and it points to that dummy filter which returns true!

what it does is make you pick units with a proper filter insted of null which will create a leak!


that ForGroup() function takes group, code arguments and what it does is loop through all units in group in a fast way and executed given (code) function n times and GetEnumUnit is a function which will return all of this units which are in group!


nop you dont need to first learn jass coz all that jass has vjass has to. vjass is fare more easy to learn as it allows you to declare your own function which will be initialized at map load and such! make functions private...

note all that jass has vjass has to! so you have nothing to lose you can only gain! and its about you where you want to start and where to end ;)

so for start learn functions, variables (local) and scopes!

JASS:
scope MyFirst initializer Init

    private function Init takes nothing returns nothing
        call BJDebugMsg( "|cff32cd32Hello World!!!|r" )
    endfunction

endscope

Thats for beggining! scope declares an list of code which is used for a single fully done order of code! like the spell, all spells code is in one scope and one scope has a few functions, globals...

private keyword means that something is only accessible in the scope you are currently coding in.

initializer tells that the function is executed at map startup

so test the map and enjoy!
 
Status
Not open for further replies.
Top