• 🏆 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] Natives and Local variables ...

Status
Not open for further replies.
Level 29
Joined
Mar 10, 2009
Messages
5,016
Hello Hivers!...I'm learning JASS and experimented on local variables...
The trigger below works...but is there something better?...


JASS:
function Trig_Test_Flying_Height_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'ACbl' ) ) then
    endif
    return true
endfunction
function Trig_Test_Flying_Height_Actions takes nothing returns nothing
    local unit target = GetSpellTargetUnit()
    call TriggerSleepAction (10)
    call SetUnitFlyHeightBJ(target, 0.00, 500 )
endfunction
//===========================================================================
function InitTrig_Test_Flying_Height takes nothing returns nothing
    set gg_trg_Test_Flying_Height = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Test_Flying_Height, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Test_Flying_Height, Condition( function Trig_Test_Flying_Height_Conditions ) )
    call TriggerAddAction( gg_trg_Test_Flying_Height, function Trig_Test_Flying_Height_Actions )
endfunction

  • Test Kill Unit
    • Events
      • Unit - A unit Is attacked
    • Conditions
    • Actions
      • Custom script: local unit target = GetTriggerUnit()
      • Custom script: local unit caster = GetAttacker()
      • Custom script: call TriggerSleepAction(10)
      • Custom script: call KillUnit(target)
      • Custom script: set target = null

An expert (forgot his name) said that GUI is limited and cant access all
natives, so my question is this...can you provide an example of native(s) except local that GUI doesnt have?...
 
Last edited:
Level 15
Joined
Oct 16, 2010
Messages
941
As far as natives goes theres:

GetUnitZ(unit WhichUnit?)

and the set lightning Z height

struct capabilities

and alot more

________________

As far as the code goes:

Take away the double negative in the condition, see how it says "if not then return false", that could just be "if then return true"

You should null the local unit variable when you are done with it to free up the memory (set target = null)

Sleeps/waits are very innacurate in jass, making them practically useless. Most jassers use timers instead.

The BJ for SetUnitFlyHeight doesn't do anything different than the native, it just calls the native. So basically you'r going through two functions unnecessarily. Use the native instead (just take the "BJ" off the function name).

________________

As far as your attempt to learn jass goes:

Good luck!
 
JASS:
function Trig_Test_Flying_Height_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'ACbl' ) ) then
    endif
    return true
endfunction

//this could be just this 

function Trig_Test_Flying_Height_Conditions takes nothing returns boolean
    return  GetSpellAbilityId() == 'ACbl' 
endfunction

/*And they say that its better to combine the conditions and actions into the conditions part, for better performance
not sure if you could do the wait part inside the condition though, but its always better to avoid waits anyway

something like this without the wait
*/

function Trig_Test_Flying_Height_Conditions takes nothing returns boolean
    local unit target = GetSpellTargetUnit()
    if GetSpellAbilityId() == 'ACbl'  then
       call SetUnitFlyHeightBJ(target, 0.00, 500 )
    endif
    return true
endfunction

//===========================================================================
function InitTrig_Test_Flying_Height takes nothing returns nothing
    set gg_trg_Test_Flying_Height = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Test_Flying_Height, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Test_Flying_Height, Condition( function Trig_Test_Flying_Height_Conditions ) )
endfunction
 
Level 15
Joined
Oct 16, 2010
Messages
941
so on every function do we really have to remove BJ's?...

If you DL JNGP and look through the function list you'll understand. BJ's are just functions that refer to natives in some way. Sometimes they do nothing and just call the native (making them useless), sometimes they just re-arrange the parameters and call the native (making them useless), and sometimes they call multiple natives to make it so you can get what you need done in just 1 function call (making them good in SOME cases). Not all BJ's are bad, just most are inefficient, useless, and impractical.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Using waits inside boolexpr functions will cause the function to stop executing.

And they say that its better to combine the conditions and actions into the conditions

Because actions start a new thread and conditions don't. I don't like it personally, since I like segregating my code to make em readable.

Oh, some newbie tips, stop using BJ's (Blizzard jass), because:
JASS:
function SetUnitFlyHeightBJ takes unit whichUnit, real newHeight, real rate returns nothing
    call SetUnitFlyHeight(whichUnit, newHeight, rate)
endfunction
It just calls a native function call, and that's pointless, it would also slow down the execution since executing jass non-native functions are slow.
Also, not all BJ's are bad, take ModuloInteger for example.
Try opening the blizzard.j found on the jasshelper folder(if you have one), which contains the jass script written by blizzard.

You also can't do recursions in jass, there's a thread execution limit.

That's all I could add right now.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
so this is suppose to be the true JASS?...

JASS:
function Trig_Test_Flying_Height_Conditions takes nothing returns boolean
    return  GetSpellAbilityId() == 'ACbl' 
endfunction

I have JNGP but I dont use it coz it makes hashtables nearly or completely useless...

I now understand how things work, but what I dont understand is this...

JASS:
//===========================================================================
function InitTrig_Test_Flying_Height takes nothing returns nothing
    set gg_trg_Test_Flying_Height = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Test_Flying_Height, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Test_Flying_Height, Condition( function Trig_Test_Flying_Height_Conditions ) )
    call TriggerAddAction( gg_trg_Test_Flying_Height, function Trig_Test_Flying_Height_Actions )
endfunction

What I do know it's a MUST to have since it initializes triggers, but I dont know how it works...can it be simplified?
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
That's not true jass, rather its a better way of scripting jass, with regards to the previous script. Don't dislike if's, they are useful if used properly.

I have JNGP but I dont use it coz it makes hashtables nearly or completely useless...
It does not. The hashtable is used to attach things to things without using custom attachment systems.

It's important to initialize triggers because, initializers basically tell the engine:
When someone attacks detect it, kay? oh and let me do some stuff to the parties in question.
If you don't initialize triggers, how would it know that you wanted to detect some event.

JASS:
function InitTrig_Test_Flying_Height takes nothing returns nothing
    set gg_trg_Test_Flying_Height = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Test_Flying_Height, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Test_Flying_Height, Condition( function Trig_Test_Flying_Height_Conditions ) )
    call TriggerAddAction( gg_trg_Test_Flying_Height, function Trig_Test_Flying_Height_Actions )
endfunction
Aside from the global variable's horrible name, this trigger is already simple. You could replace the global trigger variable with a local one but you will not be able to reference that trigger outside the initialization function, aside from the trigger's action and condition's thread.
 
JASS:
//Since this is pure JASS, you must stick with the name of the init trigger

function Filterer takes nothing returns boolean
    local unit target = GetSpellTargetUnit()
    if GetSpellAbilityId() == 'ACbl'  then
       call SetUnitFlyHeight(target, 500, 0.00)
    endif
    return true
endfunction

//===========================================================================
function InitTrig_Test_Flying_Height takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Filterer ) )
endfunction

/*
if you will use JNGP, you can do this... and oh, JNGP allows JASS hashtable, only the GUI one is not fully supported
*/

scope Test initializer init

 private function Filterer takes nothing returns boolean
    local unit target = GetSpellTargetUnit()
    if GetSpellAbilityId() == 'ACbl'  then
       call SetUnitFlyHeight(target, 500, 0.00)
       //you can actually set the rate to a higher number so that the height change isn't instant
    endif
    return true
 endfunction


 private function init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Filterer ) )
 endfunction

endscope
 
Level 15
Joined
Oct 16, 2010
Messages
941
JASS:
function InitTrig_Test_Flying_Height takes nothing returns nothing
    set gg_trg_Test_Flying_Height = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Test_Flying_Height, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Test_Flying_Height, Condition( function Trig_Test_Flying_Height_Conditions ) )
    call TriggerAddAction( gg_trg_Test_Flying_Height, function Trig_Test_Flying_Height_Actions )
endfunction

Does the same thing as:

JASS:
function InitTestFlyingHeight takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Trig_Test_Flying_Height_Conditions))
    call TriggerAddAction(t, function Trig_Test_Flying_Height_Actions)
    set t = null
endfunction
 
JASS:
/*
  I merged the actions into the conditions part, coz they say its better  

  Since this is pure JASS, you must stick with the name of the init trigger
*/
function Filterer takes nothing returns boolean
    local unit target = GetSpellTargetUnit()
    if GetSpellAbilityId() == 'ACbl'  then
       call SetUnitFlyHeight(target, 500, 0.00)
    endif
    return true
endfunction

//===========================================================================
function InitTrig_Test_Flying_Height takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Filterer ) )
endfunction

/*
if you will use JNGP, you can do this... and oh, JNGP allows JASS hashtable, only the GUI one is not fully supported
*/

scope Test initializer init

 private function Filterer takes nothing returns boolean
    local unit target = GetSpellTargetUnit()
    if GetSpellAbilityId() == 'ACbl'  then
       call SetUnitFlyHeight(target, 500, 0.00)
       //you can actually set the rate to a higher number so that the height change isn't instant
    endif
    return true
 endfunction


 private function init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Filterer ) )
 endfunction

endscope
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
You could change the name/identifier of those Trig_ things, to anything you like, those are custom/user functions.

Look at Adiktuz's script, it's optimized.

On longer actions however, I don't advise to combine the triggeraction with the triggercondition, as it adds code complexity, but that's just my preference.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
Now that's better...blizzard's convertion of GUI to JASS a 'crap' one lol!...and yeah Im talking about GUI hashtables in JNGP that is completely useless...

the problem with..."local trigger t = CreateTrigger()" is that you cant use it outside like chobibo said...oh well nevermind...

Thanks for your answers guys, but 2 last things before I focus to JASS tutorial section...

1. Is this the same in any cases?
InitTrig_Test_Flying_Height "OR" InitTestFlyingHeight

2. Can a local trigger/variable call a global one outside or inside the trigger?


Thanks!...+rep to all except Raven coz I already given him on the other thread :)...
 
Level 15
Joined
Oct 16, 2010
Messages
941
the problem with..."local trigger t = CreateTrigger()" is that you cant use it outside like chobibo said...oh well nevermind...

I myself have never referneced a trigger since i've moved to jass (except in damage detection triggers). You always reference functions not triggers, so I always declare my triggers local and then null them.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
1. Yes, because you're using newgen.
2. Yes, as long as you have a reference/pointer to it.
JASS:
function sample1 takes nothing returns nothing
    local trigger local_trigger=CreateTrigger()
    set global_trigger=local_trigger
endfunction

function sample2 takes nothing returns nothing
    local trigger t=global_trigger
endfunction

Always remember that handles are not copied when assigned to another variable, the variable is just a pointer to the handle.

JASS:
function sample1 takes nothing returns nothing
    local trigger local_trigger=CreateTrigger()
    set global_trigger=local_trigger
    call DestroyTrigger(local_trigger)
endfunction

function sample2 takes nothing returns nothing
    local trigger t=global_trigger // returns null because you already destroyed the trigger.
endfunction

This does not apply to primitive data types (boolean, integer, real and string) though.
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
Now that's better...blizzard's convertion of GUI to JASS a 'crap' one lol!...and yeah Im talking about GUI hashtables in JNGP that is completely useless...

That's probably because in NewGen you aren't supposed to use the standard variable editor. Everything you need can you create within a globals block.

Learn vJASS, it's easier and you learn it faster. And when you learned vJASS, you also automatically learns JASS with a few cons since you have to create a few variables in the variable editor like Hashtables.
 
(as long as its declared above the line which calls it, if ur using the variable editor, you shouldn't have any problems)

This is not true, the postprocessor will place all globals inside global blocks on the top of the script, so basically, you can declare your globals anywhere you want.

@thread OP, this is how a globals block look:

JASS:
globals
    timer MY_TIMER
    unit MY_UNIT
endglobals

It is very comfortable since you don't have to add the "udg_" part in front of your variables. It is a good idea to give your globals upper-case names so that you can separate them from the locals.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
OK guys another questions about functions...

1. Are these the same?...EVENT: Time elapsed 5 seconds...

2. Is (quote 1) 2 triggers or just 1?...

1 said:
JASS:
function Test takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "I'm a test function." )
endfunction
JASS:
Function RunTest takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "Calling the test function..." )
    call Test()
endfunction
OR...
2 said:
JASS:
Function RunTest takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "Calling the test function..." )
endfunction
 
function Test takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "I'm a test function." )
endfunction
 
@1 - I dont understand
@2 - one trigger, two functions

JASS:
//This should be on top because you can only call functions that are on top of the line which calls it
function Test takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "I'm a test function." )
endfunction
  
function RunTest takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "Calling the test function..." )
    call Test()
endfunction
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
OK thanks...

so basically you need to 'call' the 'upper' function everytime you make functions?...

Like...
JASS:
Function R1 takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "blahhhh..." )
endfunction
 
function R2 takes nothing returns nothing
   call DisplayTextToForce( GetPlayersAll(), "blahhhh" )
   call R1()
endfunction 
 
function R3 takes nothing returns nothing
   call DisplayTextToForce( GetPlayersAll(), "blahhhh" )
   call R2()
endfunction 
 
function R4 takes nothing returns nothing
   call DisplayTextToForce( GetPlayersAll(), "blahhhh" )
   call R3()
endfunction
 
not really, you just call a function IF NEEDED... and its functions not Functions
JASS:
/*
   the above code is equivalent to this...
*/

function R1 takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "blahhhh" )
    call DisplayTextToForce( GetPlayersAll(), "blahhhh" )
    call DisplayTextToForce( GetPlayersAll(), "blahhhh" )
    call DisplayTextToForce( GetPlayersAll(), "blahhhh..." )
endfunction
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
Functions are a special programing strucutre. When you call a function it dumps the contense of your registers onto the stack, dumps the function arguments onto the stack and then jumps to the start of the code for the function recalling passed arguments from the stack. Once the function returns (all functions return, just not always with an argument) it will restore all registers and jump back to the instruction after the call. The stack related dumping and recalling is often made automatically as part of the call instruction due to how stupidly complex some of the x86 instructions are (literally doing whole parts of a program over variable number of cycles).

Conditional statements and itteration use raw jump instructions which do not cause stack dumps and are much faster as such. These are used for program flow control basically otherwise you would be limited to prety linear instructions which is not very useful.

So why use calls and not normal jumps? Well calls to functions do not disturbe registers and as such allow you to run code without caring what is currently loaded in the processor. This allows the creation of more predictable code and is great for improving maintainability.

Thus jass only lets you use calls and restricts jump based structures to within a function.

A good use of a function is in a Recycle Timer system where by you can call a function to deposit and retreive a blank timer. These functions may be used dozens of times in many systems through your map and so prevent duplication of the same core code as well as allow you to maintain all instances of the code if you find a bug (like a typo which I am sure you know will be comman as grass in a field when programming).

A bad use of a function is in your example code as you are prety much using it to break appart a linear process into different chunks wasting time and making maintence harder (as each function does not have a clear purpose).

JASS is rather retarded however... You can not call functions below the caller function and doing so will throw a syntax error. This is not a physical restriction of your computer and almost all languages (java, C, C++) allow you to do that. This is probably due to how the compiler works for jass (no preprocessing) as it has to compile on map load.

I do not think jass supports itterative functions (where a function calls itself) which again is a perfectly valid behaviour in computer science which most languages support. Be warned that this causes huge strain on the stack and can easilly make your code prone to stack overflow errors in the case of it becomming too nested.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
OK if a function is not called, does it mean..."Skip remaining actions" in GUI???...

And if I do like this, will it still work?...

JASS:
function Test1 takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "one" )
endfunction
 
function Test2 takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "two" )
endfunction
 
function Test3 takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "three" )
    call Test1
endfunction

I know this can be merged like what Adiktuz said but Im just curious if this
will work or not?...can Test3 call Test1?...
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
OK if a function is not called, does it mean..."Skip remaining actions" in GUI???...

No, why the hell should it? That does not even make sense.

A function can call any number of functions (within the op limit restrictions) and they will be executed linearly line for line (next to when flow control statements change the current line or skip some lines).

The Skip remaining actions is a return statement. All functions must return and can return at any time (which ignores all code below the return). By default, functions that return nothing will return automatically at the endfunction line. Functions that return a type need to have atleast 1 line that returns tha type. Making a function skip a return will probably crash the game. A function can only return 1 type and 1 value. In real progamming languages you can bundle data together in objects or structs and return a pointer to that to allow multiple pieces of different data to be returned.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
You can call a function as long as it is declared before the function that calls it, or if the function is calling is itself (recursion).

JASS:
function A takes nothing returns nothing
    call DisplayTextToPlayer(GetLocalPlayer(),0,0,"Function A executed")
endfunction

function B takes nothing returns nothing
    call DisplayTextToPlayer(GetLocalPlayer(),0,0,"Function B executed")
endfunction

function Caller takes nothing returns nothing
    call A() // This is valid, function A is declared before this function
    call B() // This is valid, function B is declared before this function
    call C() // This is invalid, function C is declared after this function
endfunction

function C takes nothing returns nothing
   call DisplayTextToPlayer(GetLocalPlayer(),0,0,"Function C executed")
   call C() // This is valid, C is calling itself
endfunction

EDIT: Dr Super Good's explanation about functions are better.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
@Dr Super Good

Perhaps Im not clear of what I meant about skipping actions...what I mean is this...

JASS:
function Test1 takes nothing returns nothing
   call DisplayTextToForce( GetPlayersAll(), "one" )
endfunction
 
function Test2 takes nothing returns nothing
   call DisplayTextToForce( GetPlayersAll(), "two" )
endfunction
 
function Test3 takes nothing returns nothing
   call DisplayTextToForce( GetPlayersAll(), "three" )
   call Test1
endfunction

so function Test2 is useless right? coz no one calls it...so that's what I mean of skipping actions, useless so it should be removed anyway?...


@chobibo

Yeah I understand that now...Adiktuz explained it already...but thanks for
clarifying that a function can call 'itself'...
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Yes, but why would you even bother typing a useless function?

Also, because of jass' limitations, it would be wise to use as less functions as possible.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
why? because he is trying to learn... he doesn't know that much yet that's why he is asking...

Sorry, don't misunderstand, I was under the assumption that he already knew how functions work, since he mentioned earlier that he knows visual basic, that's why I was asking him why he was typing a function that he won't use.

I didn't mean to offend, I wasn't trying to be an ass.
 
Level 15
Joined
Oct 16, 2010
Messages
941
he mentioned earlier that he knows visual basic

He's probably american and took a VB class in high school. I did the same, and can say that it doesn't teach you #$%# about programming. Our high schools also have 3d modeling classes that don't teach you #$*% about 3d modeling, animation classes that don't teach you #@$& about animation, and computer 2d-art classes that don't teach you %*#@ about computer 2d-art

Are you using JNGP right now? Because jasshelper would really help the learning process
 
Status
Not open for further replies.
Top