• 🏆 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!

Advice please. I'm going to learn JASS...

Status
Not open for further replies.
Level 7
Joined
Sep 9, 2007
Messages
253
I've read that comparing GUI to JASS is bad idea but I think in my case I can't stop myself. When learning these JASS concepts all I can think of is "how does that relate to what I already know in GUI triggers". I think what I need is a tutorial which teaches JASS from the perspective of an advanced GUI user.

I've spent the last 2 days looking at beginner/introductory JASS tutorials and I've learned a few things but there is no way I could implement anything and I still have no broad understanding. This is frustrating because I know that once I do gain that understanding I will learn extremely quickly.


Well all I'm doing is whinging so I guess I should ask some constructive questions...

How Should I organise my code within the GUI trigger interface?
Is it normal to have a list of GUI triggers which have all been converted to code and edited into efficient JASS?
Should I have one trigger at the start which declares all my global variables?

JASS:
call FlushHandleLocals(DamageTrigger)
call DestroyTrigger(DamageTrigger)
call SetHandleHandle(AttackingUnit, "DamageTrig", null)
//Why is the second line purple and the other lines black? What is the difference?
JASS:
call TriggerAddCondition(AttackTrigger, Condition( function AttackTrigger_Conditions))
//Why is there a space after the open bracket?
I'm sure people are always posting with these kinds of questions but I have been unable to find answers. Thanks so much for any advice anyone can offer.
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
Is it normal to have a list of GUI triggers which have all been converted to code and edited into efficient JASS?

No. You should write your code from scratch. Converting GUI trigger to JASS is not a good idea, unless it is for learning purposes.

Why is the second line purple and the other lines black? What is the difference?

Native functions (made by Blizzard) will be coloured. Custom functions ill be coloured black.

Why is there a space after the open bracket?
It is just how GUI gets converted to JASS. The space makes no difference, you can delete it or leave it there. It does take teeny tiny bit more memory to store, but the amount is so small it doesn't matter.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
I hope that you are using JassNewGenPack when learning Jass?
It's usefull to have the function list to see what natives and bj's you can use.
This way it's easyer to learn which functions can accomplish what actions that you would like to perform.

Respectively it's usefull to convert your triggers from GUI to Jass if you want to know for example how a action, event or condition in GUI works. By using the function list you are abled to see exactly what this function does, which other functions it calls and how this is implemented.

This way it's easier to learn how GUI works in Jass. If you know the underlying structure you will start to understand why GUI is inefficient and how much more controll you will have when using Jass over GUI.

If you have any questions about the usage of Jass or if you are having trouble creating something in Jass don't hasitate to post it here and we'll try to elaborate it as simplified as possible. So that it will be easy to understand.
 
Level 7
Joined
Sep 9, 2007
Messages
253
No. You should write your code from scratch. Converting GUI trigger to JASS is not a good idea, unless it is for learning purposes.

OK. So where do I write it? should I convert an empty trigger and then delete Blizzard's code and then start writing my own code? Should all of a map's code be in 1 single area or can I organise it into different empty GUI triggers?

Native functions (made by Blizzard) will be coloured. Custom functions ill be coloured black.

I understand that a native function is one which exists naturally in the game but what exactly constitutes a custom function? I thought they were any function you have written/declared at some point in your code? That example was from http://www.hiveworkshop.com/forums/...80/attack-damage-detection-engine-jass-33123/ and I don't see a custom function called "DamageTrigger" anywhere in that piece of code. He only has "DamageTrigger_Actions" and "DamageTrigger_Conditions". So from where is he calling the custom function "DamageTrigger" if it doesn't exist in his code and if it's not a native function?

I hope that you are using JassNewGenPack when learning Jass?
Yes I am. Thanks for your friendly help guys.
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
should I convert an empty trigger and then delete Blizzard's code and then start writing my own code?

Yes.

Should all of a map's code be in 1 single area or can I organise it into different empty GUI triggers?

You can organize them, it is recommended.

I understand that a native function is one which exists naturally in the game but what exactly constitutes a custom function? I thought they were any function you have written/declared at some point in your code?

That is pretty much it.

That example was from http://www.hiveworkshop.com/forums/...80/attack-damage-detection-engine-jass-33123/ and I don't see a custom function called "DamageTrigger" anywhere in that piece of code. He only has "DamageTrigger_Actions" and "DamageTrigger_Conditions". So from where is he calling the custom function "DamageTrigger" if it doesn't exist in his code and if it's not a native function?

DamageTrigger is a trigger, not a function. He registers events for triggers. When unit takes damage, the triggers run automatically.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Think of a trigger as a group of functions that fire when an event occurs. Think of a function as a group of code that executes when that function is called.

Think of call function as executing a trigger that returns a result. You can pass values into that function and then use those values inside of the function. Modifying those values won't actually change them.

Think of a local variable as a global variable that only exists within a function. It is created when the function is called and destroyed when the function ends. When values are passed into a function, those values are stored into local variables that are declared in the takes list, which is why changing those variable values within the function won't change the values that were passed in.


Think of a timer as a trigger that only has 1 function and executes that function every time it expires.
 
Level 7
Joined
Sep 9, 2007
Messages
253
DamageTrigger is a trigger, not a function. He registers events for triggers. When unit takes damage, the triggers run automatically.


So what is happening here?
JASS:
call FlushHandleLocals(DamageTrigger)
He is calling something that is neither a native nor custom function. You say It's a trigger.... so he is calling a trigger which he has created temporarily by setting into a local variable? Would this essentially be the same as:

  • Trigger - Run DamageTrigger <gen> (checking conditions)


Think of a local variable as a global variable that only exists within a function. It is created when the function is called and destroyed when the function ends.

If locals are destroyed at the end of their function then what is the point of nulling them in this piece of code?

JASS:
function DamageTrigger_Actions takes nothing returns nothing
    local unit AttackedUnit = GetTriggerUnit()
    local unit AttackingUnit = GetEventDamageSource()
    local trigger DamageTrigger = GetTriggeringTrigger()
    call FlushHandleLocals(DamageTrigger)
    call DestroyTrigger(DamageTrigger)
    call SetHandleHandle(AttackingUnit, "DamageTrig", null)
    //Here come the actions you want originally with the attacked/attacking unit.
    call UnitDamageTarget(AttackingUnit, AttackedUnit, GetEventDamage(), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null)
    set DamageTrigger = null
    set AttackingUnit = null
    set AttackedUnit = null
endfunction
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
If locals are destroyed at the end of their function then what is the point of nulling them in this piece of code?

JASS:
function DamageTrigger_Actions takes nothing returns nothing
    local unit AttackedUnit = GetTriggerUnit()
    local unit AttackingUnit = GetEventDamageSource()
    local trigger DamageTrigger = GetTriggeringTrigger()
    call FlushHandleLocals(DamageTrigger)
    call DestroyTrigger(DamageTrigger)
    call SetHandleHandle(AttackingUnit, "DamageTrig", null)
    //Here come the actions you want originally with the attacked/attacking unit.
    call UnitDamageTarget(AttackingUnit, AttackedUnit, GetEventDamage(), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null)
    set DamageTrigger = null
    set AttackingUnit = null
    set AttackedUnit = null
endfunction

Because the local variables will point to a destroyed instance if they are not being nulled. Basically that will take up space.
Some locals do not need to be nulled. Those local variables are non-handle variables such as: booleans, strings, integers and reals.
Any other local variables are handles and should be nulled in order to improve efficiency.

Now that you know what a handle is, you can get a unique ID of a handle with:
JASS:
call GetHandleId(handle)
Where handle is any handle. Such as units, triggers, basically anything except booleans strings integers and reals.
This is a unique id given to each handle, which can be usefull in many ways.

So what is happening here?
Jass:

JASS:
call FlushHandleLocals(DamageTrigger)

He is calling something that is neither a native nor custom function. You say It's a trigger.... so he is calling a trigger which he has created temporarily by setting into a local variable? Would this essentially be the same as:

  • Trigger - Run DamageTrigger <gen> (checking conditions)

Take a look here:
http://www.wc3c.net/showthread.php?t=83340
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Because the local variables will point to a destroyed instance if they are not being nulled.

That doesn't even make any sense... it is because the ref counter for the handles will not go down until you specifically null the variables pointing to them. When the locals are deallocated in the function, they are only deallocated. The reference counters aren't modified.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
That doesn't even make any sense... it is because the ref counter for the handles will not go down until you specifically null the variables pointing to them. When the locals are deallocated in the function, they are only deallocated. The reference counters aren't modified.

0.o Sorry, that is new to me. Thanks for explaining...
My mistake.

EDIT:
http://wiki.thehelper.net/wc3/Memory_Leaks#Handle_Reference_Leak said:
Agents in Jass are reference counted. Because local variables don't lower their value's reference count when the variables stop existing (i.e. when the function instance ends), they must be manually set to point to something else before that in order to lower the reference count. Null can be used as the new value, as its reference count won't increase nor will it be destroyed, because it isn't an existing object. If an agent's reference count never reaches 0 after destruction, its handle will never be recycled.

Returning a local agent will not lower the reference count, and returning ends a function's execution. A global must be used to take the value of the local agent. The agent must then be nulled, and the global returned.

I still don't understand what the reference count exactly is... Would you care to elaborate?
 
Last edited:
Level 7
Joined
Sep 9, 2007
Messages
253
It's just I read in a tutorial that they should be declared before any other code. I guess I just need to learn how and when the code is parsed. Does the game parse all JASS scripts upon map initialisation and then functions are called when triggers call them. If that's the case does it technically matter where you declare globals? I'll probably just create them in GUI.
 
Status
Not open for further replies.
Top