1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. The Lich King demands your service! We've reached the 19th edition of the Icon Contest. Come along and make some chilling servants for the one true king.
    Dismiss Notice
  4. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  5. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  6. The results are out! Check them out.
    Dismiss Notice
  7. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  8. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  9. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[JASS] Natives and Local variables ...

Discussion in 'Triggers & Scripts' started by mckill2009, Feb 26, 2011.

  1. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    well, Im not at vJass yet...Bribe's explanation has more sense to me...

    what I dont understand is when you create local triggers, it cannot be used outside, right?...so is it better to use "gg_trg_name"???...of course it depends on the situation...
     
  2. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,701
    Resources:
    0
    Resources:
    0
    The simple answer is, if you want to modify the trigger, perhaps you wanted to destroy or pause it, you need to use a global variable. If you don't want to modify it any longer, then there is no point of remembering where the said object is in memory.

    You can't use local variables outside the function instance that declared them. When you call a function, a private space is provided for the function, after the execution of the said function, all that was inside that private space is removed, that's why local variables can no longer be used outside the function instance that declared it. Also, creating a trigger isn't the same as declaring a variable, the trigger handle is stored somewhere else and is independent of both global and local variables.

    Code (vJASS):

    function Taho takes nothing returns nothing
        call CreateTrigger()
    endfunction
     


    Look at the code above, the CreateTrigger function creates a trigger handle in memory, which consumes memory, but we didn't reference it by using a variable, hence it is unreferenced and we cannot retrieve it from memory (imagine having to call a friend and forgetting his name, how would you call him? Hey ass!). This trigger in memory isn't useful, it just lies there and consumes space, we also can't remove it because the engine forgot where he put the trigger. That is called a memory leak.

    Memory leaks exists not only in jass, but also on other programming languages, even in our brains lol. If you forgot something, that's a memory leak, or Alzheimer's[?].
     
    Last edited: Mar 1, 2011
  3. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,051
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    No vJass, no problem.

    Code (vJASS):

    constant function BloodCurseSpell takes nothing returns integer
        return 'A006'
    endfunction

    constant function BloodCurseBadBuff takes nothing returns integer
        return 'B000'
    endfunction

    constant function BloodCurseDummyId takes nothing returns integer
        return 'h001'
    endfunction

    constant function BloodCurseDummySpell takes nothing returns integer
        return 'A005'
    endfunction

    function BloodCurseOnAttack takes nothing returns boolean
        local unit hero = GetTriggerUnit()
        local unit dummy
        if (GetUnitAbilityLevel(hero, BloodCurseSpell()) > 0 and GetUnitAbilityLevel(hero, BloodCurseBadBuff()) == 0) then
            set dummy = CreateUnit(GetTriggerPlayer(), BloodCurseDummyId(), GetUnitX(hero), GetUnitY(hero), bj_UNIT_FACING)
            call UnitAddAbility(dummy, BloodCurseDummySpell())
            call UnitApplyTimedLife(dummy, 'BTLF', 1.00)
            call SetUnitAbilityLevel(dummy, BloodCurseDummySpell(), GetUnitAbilityLevel(hero, BloodCurseSpell()))
            call IssueTargetOrder(dummy, "unholyfrenzy", hero)
            set dummy = null
        endif
        set hero = null
        return false
    endfunction

    //===========================================================================
    function InitTrig_Blood_Curse takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED)
        call TriggerAddCondition(t, Condition(function BloodCurseOnAttack))
        set t = null
    endfunction
     
     
  4. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    Ok now I'm confused again...

    some codes has...

    "function BloodCurseSpell takes nothing returns integer"
    "constant function BloodCurseSpell takes nothing returns integer"
    "scope function BloodCurseSpell takes nothing returns integer"
    "native function BloodCurseSpell takes nothing returns integer"

    what are those?, constant, native, scope etc...and more???...
     
  5. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,051
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    native, scope, those are vJass. "constant function" is just a convention when writing in plain JASS to let users know that variable will always return the same thing.

    function...
    endfunction

    loop
    endloop

    if...
    endif

    Those are just blocks of code.
     
  6. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    Those functions returns the id of the spells in the object editor. Search them up yourself and press CTRL + D and you will see the 4 digit ID of your ability. Every single object in the object editor has one, check it out yourself.

    In gui you're probably familiar with ability variables or unittype variables. In JASS those aren't necessary and in JASS we use Integers instead, put the 4 digit id between two 'yoid' and it will return the id of your object.

    The constant stands for, constant. It will always return the same value all the time and therefore I *think* it will have better performance if you put them as constants. Seems like Bribe's answer was better :D

    Native, in JASS there are two things about functions. Functions from the Blizzard.j and natives from the common.j (two files within the war3 mpq file). The natives are pure functions made in C which cannot be simplyfied no more. BJs are usually a bunch of natives collected together or even worse, they can be calling the real function straight away. Like
    PauseUnitBJ
    , it looks like this when you look up this function

    Code (vJASS):

    function PauseUnitBJ takes boolean pause, unit whichUnit returns nothing
        call PauseUnit(whichUnit, pause)
    endfunction
     


    So it calls the real native straight away. Vex's optimizer fixes loads of these but not all so basic in JASS, do not use BJs but there are a few exceptions.
    Like
    TriggerRegisterAnyUnitEventBJ
    which is constantly used in spellmaking. Or
    GroupPickRandomUnit
    , useless to remake as the output will be exactly the same.

    Scopes are things we use in vJASS so if you're not going to learn that, I will not explain that.

    Btw these

    Does not exist.
     
  7. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    Yeah I know the CTRL D already and their codes...Im just asking what are those and it cleared my mind a bit...
     
  8. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    Good now start learn some moar :D
     
  9. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,192
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    C? I thought JASS was based on LUA? :S
     
  10. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,051
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    WarCraft III and LUA are totally different things. LUA is something used with Jass NewGen Pack and other gaming mods.
     
  11. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,701
    Resources:
    0
    Resources:
    0
    Lua is usually used for the scripting of game configurations. IIRC, warcraft 3's engine was written in C++ not C. I liked the alpha version better...
     
  12. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,051
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    I heard the Alpha version of Death & Decay was something out of this world!
     
  13. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,701
    Resources:
    0
    Resources:
    0
    I've only seen it in videos though. Alpha's special effects were better, the building scaling was realistic, it wasn't RTS, more like an Action RPG kind of game.
     
  14. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    Ok, here's another topic...

    I've noticed that Hash GUI is this:
    child key, parent key and Hash

    But in JASS, it's reverse:
    Hash first, the Parent and the child

    my questions is this, is this ALWAYS the case? to save and load?...

    Also I've experimented this:

    Code (vJASS):

    function hashon takes nothing returns nothing
        local unit attacker = GetAttacker()
        local hashtable hash1 = InitHashtable()
        local integer ID = GetHandleId(attacker)
        call SaveUnitHandle(hash1, StringHash("unit"), ID, attacker)
        call KillUnit(LoadUnitHandle(hash1, StringHash("unit"), ID))
        set attacker = null
        //Is this the correct null?, or should I put also:
        // set hash1 = null
        // set ID = null
    endfunction
    //===========================================================================
    function InitTrig_Hashtest takes nothing returns nothing
        local trigger trigtest = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ(trigtest, EVENT_PLAYER_UNIT_ATTACKED)
        call TriggerAddAction(trigtest, function hashon )
        set trigtest = null
    endfunction
     


    so is the trigger correct?...
     
  15. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    yeah, anyway if you have NewGen, it will guide you...

    but why create a local hash?
     
  16. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    just a test :)...
     
  17. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,701
    Resources:
    0
    Resources:
    0
    You don't need to null integers and other basic data types (boolean, real, string).
     
  18. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    This.

    You only need to null local handles, never globals.

    Basic the Hash should be a global variable + forget about converted GUI crap. Never use BJs.
     
  19. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,701
    Resources:
    0
    Resources:
    0
    You should also null global handles that point to destroyed objects, so that the destroyed object's handleId can be recycled.
     
  20. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    Ok guys, this is the one I made...falling corpses from the sky...

    Take note that most of the functions are in GUI...I know it's not really
    good but is it FAIR?...coz I'm just appying the one I know...


    • Fallen Corpse Bombardment
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Fallen Corpse Bombardment
      • Actions
        • Set FCB_Pt[1] = (Target point of ability being cast)
        • Set FCB_Unit = (Triggering unit)
        • Custom script: set udg_FCB_Level = GetUnitAbilityLevelSwapped('A02M', udg_FCB_Unit)
        • Unit - Create 1 Dummy (caster-for all) for (Owner of FCB_Unit) at FCB_Pt[1] facing Default building facing degrees
        • Custom script: set udg_FCB_Dummy = GetLastCreatedUnit()
        • Custom script: set udg_FCB_ID = GetHandleId(udg_FCB_Dummy)
        • Unit - Add Falling Corpse Bom (FCB SP1) to FCB_Dummy
        • Unit - Set level of Falling Corpse Bom (FCB SP1) for FCB_Dummy to FCB_Level
        • Hashtable - Save Handle OfFCB_Pt[1] as (Key fcbloc) of FCB_ID in Hash_01
        • Custom script: call SaveInteger(udg_Hash_01, StringHash("fcblevel"), udg_FCB_ID, udg_FCB_Level)
        • Custom script: call SaveUnitHandle(udg_Hash_01, StringHash("fcbcaster"), udg_FCB_ID, udg_FCB_Unit)
        • Custom script: call SaveReal(udg_Hash_01, StringHash("fcbdur"), udg_FCB_ID, 6.00)
        • Unit Group - Add FCB_Dummy to FCB_Grp
        • Custom script: call EnableTrigger(gg_trg_Fallen_Corpse_Bombardment_Loop)


    • Fallen Corpse Bombardment Loop
      • Events
        • Time - Every 0.30 seconds of game time
      • Conditions
      • Actions
        • Unit Group - Pick every unit in FCB_Grp and do (Actions)
          • Loop - Actions
            • Custom script: set udg_FCB_Dummy = GetEnumUnit()
            • Custom script: set udg_FCB_ID = GetHandleId(udg_FCB_Dummy)
            • Custom script: set udg_FCB_Unit = LoadUnitHandle(udg_Hash_01, StringHash("fcbcaster"), udg_FCB_ID)
            • Custom script: set udg_FCB_Timer = LoadReal(udg_Hash_01, StringHash("fcbdur"), udg_FCB_ID)
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • (FCB_Unit is alive) Equal to True
                • FCB_Timer Greater than 0.00
              • Then - Actions
                • Custom script: call SaveReal(udg_Hash_01, StringHash("fcbdur"), udg_FCB_ID, udg_FCB_Timer - 0.3)
                • Set FCB_Pt[1] = (Load (Key fcbloc) of FCB_ID in Hash_01)
                • Set FCB_Pt[2] = (FCB_Pt[1] offset by (Random real number between 50.00 and 250.00) towards (Random real number between 0.00 and 360.00) degrees)
                • Unit - Create 1 Falling Corpse for (Owner of FCB_Unit) at FCB_Pt[2] facing Default building facing degrees
                • Custom script: set udg_FCB_CorpseFalling = GetLastCreatedUnit()
                • Custom script: set udg_FCB_CorpseID = GetHandleId(udg_FCB_CorpseFalling)
                • Custom script: set udg_FCB_Level = LoadInteger(udg_Hash_01, StringHash("fcblevel"), udg_FCB_ID)
                • Custom script: set udg_FCB_Dam = udg_FCB_Level
                • Custom script: call SaveInteger(udg_Hash_01, StringHash("fcb2level"), udg_FCB_CorpseID, udg_FCB_Dam)
                • Custom script: call SaveUnitHandle(udg_Hash_01, StringHash("fcbcaster2"), udg_FCB_CorpseID, udg_FCB_Unit)
                • Animation - Change (Last created unit) flying height to 0.00 at 1000.00
                • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
                • Custom script: call RemoveLocation(udg_FCB_Pt[2])
              • Else - Actions
                • Custom script: call RemoveLocation(udg_FCB_Pt[1])
                • Custom script: call ExplodeUnitBJ(udg_FCB_Dummy)
                • Custom script: call UnitApplyTimedLifeBJ( 0.01, 'BTLF', udg_FCB_Dummy )
                • Unit Group - Remove FCB_Dummy from FCB_Grp
                • Hashtable - Clear all child hashtables of child FCB_ID in Hash_01
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • (FCB_Grp is empty) Equal to True
                  • Then - Actions
                    • Trigger - Turn off (This trigger)
                  • Else - Actions


    • Fallen Corpse Bombardment Dies
      • Events
        • Unit - A unit Dies
      • Conditions
        • (Unit-type of (Triggering unit)) Equal to Falling Corpse
      • Actions
        • Custom script: set udg_FCB_CorpseFalling = GetTriggerUnit()
        • Custom script: set udg_FCB_CorpseID = GetHandleId(udg_FCB_CorpseFalling)
        • Custom script: set udg_FCB_Dam = LoadInteger(udg_Hash_01, StringHash("fcb2level"), udg_FCB_CorpseID)
        • Custom script: set udg_FCB_Unit = LoadUnitHandle(udg_Hash_01, StringHash("fcbcaster2"), udg_FCB_CorpseID)
        • Set FCB_Pt[3] = (Position of (Triggering unit))
        • Special Effect - Create a special effect at FCB_Pt[3] using Abilities\Spells\Other\Stampede\StampedeMissileDeath.mdl
        • Special Effect - Destroy (Last created special effect)
        • Custom script: set bj_wantDestroyGroup = true
        • Unit Group - Pick every unit in (Units within 100.00 of FCB_Pt[3] matching ((((Matching unit) belongs to an enemy of (Owner of FCB_Unit)) Equal to True) and (((Matching unit) is alive) Equal to True))) and do (Actions)
          • Loop - Actions
            • Unit - Cause FCB_Unit to damage (Picked unit), dealing (15.00 x (Real(FCB_Dam))) damage of attack type Chaos and damage type Divine
        • Custom script: call RemoveLocation(udg_FCB_Pt[3])
        • Hashtable - Clear all child hashtables of child FCB_CorpseID in Hash_01
        • Unit - Remove (Triggering unit) from the game