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. We have recently started the 16th edition of the Mini Mapping Contest. The theme is mini RPG. Do check it out and have fun.
    Dismiss Notice
  4. Dismiss Notice
  5. The Highway to Hell has been laid open. Come along and participate in the 5th Special Effect Contest.
    Dismiss Notice
  6. 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. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,702
    Resources:
    0
    Resources:
    0
    Yes, because your giving the unit a new order, effectively replacing the current one, which is synonymous to interrupting the current order.
     
  2. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    But you're ordering a dummy to move so it's only the dummy that will have its "stop" order into "move" order.
     
  3. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,206
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    I noticed that set unit x/y is dependent on the unit speed somehow, so it is actually impossible to set the x/y of a unit with 0 move speed.
     
  4. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    I was wondering why...

    This works...using global variable

    Code (vJASS):

    function dada takes nothing returns nothing
        set udg_count = udg_count + 1
        if udg_count == 5 then
            call BJDebugMsg("done")
        else
            call DisplayTextToForce(GetPlayersAll(), ( "Total is " + I2S(udg_count) ) )
        endif
    endfunction
    //===========================================================================
    function InitTrig_counttest1 takes nothing returns nothing
        local trigger y = CreateTrigger(  )
        call TriggerRegisterTimerEventPeriodic( y, 0.50 )
        call TriggerAddAction(y,function dada)
        set y = null
    endfunction
     


    But this doesnt...local variable

    Code (vJASS):

    function dada takes nothing returns nothing
        local integer count
        set count = count + 1
        if count == 5 then
            call BJDebugMsg("done")
        else
            call DisplayTextToForce(GetPlayersAll(), ( "Total is " + I2S(count) ) )
        endif
    endfunction
    //===========================================================================
    function InitTrig_counttest2 takes nothing returns nothing
        local trigger y = CreateTrigger(  )
        call TriggerRegisterTimerEventPeriodic( y, 0.50 )
        call TriggerAddAction(y,function dada)
        set y = null
    endfunction
     


    EDIT:

    BTW how to stop the trigger?, by destroying it or turn it off?...
     
  5. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    Because a local only works within the function. After the function ends, so does the local.
     
  6. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    Ok but isnt it that the count is 'in' the function?...

    also, this is working...

    Or am I just wrong coz this does only runs ONE TIME?...

    Code (vJASS):

    function WodSpell takes nothing returns boolean
        local unit u
        local unit o
        local integer spelllevel
        local integer spelldam
        if GetSpellAbilityId()=='A002' then
            set u = GetTriggerUnit()
            set o = CreateUnit (GetOwningPlayer(u), 'h000', GetUnitX(u), GetUnitY(u), 0)
            set spelllevel = GetUnitAbilityLevel(u, 'A002')
            set spelldam = spelllevel * 5
            call IssuePointOrder(o, "move", GetSpellTargetX(), GetSpellTargetY())
            set u = null
            set o = null
            call DisplayTextToForce(GetPlayersAll(), ( "Damage is " + I2S(spelldam) ) )
        endif
        return false
    endfunction
    //===========================================================================
    function InitTrig_Wind_of_Decay takes nothing returns nothing
        local trigger t = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ      (t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition                (t, Condition(function WodSpell))
        set t = null
    endfunction
     
     
  7. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    I mean that the local isn't passed on to the next call of the function.
     
  8. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    so is it advisable to use global then for this type of situation?...
     
  9. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    Yes it is or the use of a hashtable.

    This is why vJASS is so good as you don't have to create a variable in the variable editor, you just create a new global block and types in the global you want and that's it.
     
  10. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    OMG! I love you baassee, vJASS there is! hehe...
     
  11. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    Or ZINC. Got the same features.
     
  12. 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
    and ZINC makes things shorter, though harder to read...

    Code (vJASS):

    //! zinc

    library Test {

        unit tester, killer;
        real x;

    }

    //! endzinc
     
     
  13. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,206
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    Let's learn how to walk before we run now, shall we?
     
  14. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    1. Do I really need JNGP to play maps with vJASS in it?...
    2. I have a NON vJASS map or map that has no vJASS spell/trigger...so if I use JNGP
    to edit this map or add a vJASS trigger, it is OK?...
    3. When creating a trigger what is BEST to use, local trigger OR gg_trg???...
    4. Where do I put the line thing >>> 'scope' and 'endscope'?...
    5. Can you save local variables to a hashtable and load latter?...
     
  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
    @1: you just need JNGP to edit and save the map...
    @2: yup
    @3: well, if you dont need to reference it again, local, or if you will be using gg_trg, since you're using vJASS, you might just want to have a global trigger variable
    @4: normally, scope at the top of the code, endscope at the end

    Code (vJASS):

    scope A

    /*
     put the codes here
    */


    endscope
     
     
  16. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,702
    Resources:
    0
    Resources:
    0
    1. No.
    2. Yes.
    3. Depends on use. Most of the time you'll only use the local one.
    5. Yes.

    Think of the hashtable as a global variable, the thing that makes the hashtable flexible is that it can index data using a large integer as it's indexer, while jass arrays can't index data with an index higher than 8191.
     
  17. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    thanks...but how about the 5th one?...
    3 more things...

    1. why is this used as a parent key in HT?...

    integer TIMER = StringHash("ho")

    I mean can we use 'besides' integer or besides StringHash OR you can use
    a simple integer number?...well I know childkey requires integer...

    2. "Parent Key" in JASS/vJASS and "Mission key" in GUI?...

    3. Private functions, I had a syntax error, why?...

    Chobibo made the spell, I cant get it to work so I modified some...and
    it's working now...

    For the sake of argument, Im posting the spell here...CREDITS TO CHOBIBO...

    Jass

    Code (vJASS):

    globals
        //===============================================
        //=     CONFIGURATION GLOBALS                   =
        //===============================================
        integer    SPELL_ID    = 'A001'
        real       SPELL_DPS   = 20.00/4
        real       SPELL_DUR   = 06.00
        real       UPDATE_RATE = 01.00/4
        string     SPECIAL_FX  = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeEmbers.mdl"
        string     ATTACH_POINT= "chest"
        //===============================================
     
        //===============================================
        //      SYSTEM ONLY GLOBALS - DO NOT EDIT       =
        //===============================================
        integer    TIMER       = 1 // <<< I just changed this, is it  OK?
        integer    CASTER      = 2
        integer    TARGET      = 3
        integer    DURATION    = 4
        hashtable  HASHTABLE   = InitHashtable()
        //===============================================
     
    endglobals
    //============================================================
    //=     SPELL MAIN                                           =
    //=     When creating DoT spells, you must consider the      =
    //=     following:                                           =
    //=     -caster                                              =
    //=     -target                                              =
    //=     -duration                                            =
    //=     A good DoT spell must be able to distinguish if      =
    //=     the targetted unit already has the DoT debuff, in    =
    //=     order to be able to stack or not stack its effects.  =
    //============================================================
    function onCastCondition takes nothing returns boolean
        return (GetSpellAbilityId()==SPELL_ID)
    endfunction
    function onUpdate takes nothing returns nothing
        local timer t=GetExpiredTimer()
        local integer childkey=GetHandleId(t)
        local unit caster=LoadUnitHandle(HASHTABLE,CASTER,childkey)
        local unit target=LoadUnitHandle(HASHTABLE,TARGET,childkey)
        local real duration=LoadReal(HASHTABLE,DURATION,childkey)-UPDATE_RATE
     
        // We need to check if the debuff has reached it's
        // intended lifetime, if so we remove the data we
        // saved in the hashtable. We also do the same if
        // the target is already dead.
     
        if (duration<0) or IsUnitType(target,UNIT_TYPE_DEAD) then
            // There is no longer any time remaining for the
            // debuff, so we clear the hashtable.
            debug call BJDebugMsg("Destroy debuff timer")
            call RemoveSavedHandle(HASHTABLE,CASTER,childkey)
            call RemoveSavedHandle(HASHTABLE,TARGET,childkey)
            call RemoveSavedReal(HASHTABLE,DURATION,childkey)
            call RemoveSavedHandle(HASHTABLE,TIMER,GetHandleId(target))
            call DestroyTimer(t)
        else
            // There's still timer left for the debuff, so we
            // apply the debuff effect.
            call SaveReal(HASHTABLE,DURATION,childkey,duration)
            call DestroyEffect(AddSpecialEffectTarget(SPECIAL_FX,target,ATTACH_POINT))
            call UnitDamageTarget(caster,target,SPELL_DPS,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_MAGIC,null)
        endif
     
        set t=null
        set caster=null
        set target=null
    endfunction
    function onCast takes nothing returns nothing
        local unit caster=GetTriggerUnit()
        local unit target=GetSpellTargetUnit()
        local integer childkey=GetHandleId(target)
        local timer t
     
        // Check if the unit already has a debuff timer, in
        // this spell's case, I wan't the duration to reset
        // to the maximum duration if the spell is recast
        // on an already debuffed unit.
     
        if (HaveSavedHandle(HASHTABLE,TIMER,childkey)) then
            // The target has a debuff already, we know this
            // because there is already an existing debuff
            // timer for the said unit.
            debug call BJDebugMsg("Target already has buff!")
            set t=LoadTimerHandle(HASHTABLE,TIMER,childkey)
            call SaveReal(HASHTABLE,DURATION,childkey,SPELL_DUR)
        else
            // The target has no debuff yet because there is
            // no beduff timer for it. We create a debuff timer
            // and save to the hashtable the necessary data.
            // These are the caster, the target, the duration,
            // and the debuff timer. You'll notice that the debuff
            // timer is attached to the target unit, this is
            // because we want to associate the unit with the
            // debuff timer, so that when we target an already
            // affected unit, we can reset the debuff duration.
            debug call BJDebugMsg("Target has no buff yet!")
            set t=CreateTimer()
            call SaveTimerHandle(HASHTABLE,TIMER,childkey,t)
            set childkey=GetHandleId(t)
            call SaveReal(HASHTABLE,DURATION,childkey,SPELL_DUR)
            call SaveUnitHandle(HASHTABLE,CASTER,childkey,caster)
            call SaveUnitHandle(HASHTABLE,TARGET,childkey,target)
            call TimerStart(t,UPDATE_RATE,true,function onUpdate)
    endif
     
        set t=null
        set caster=null
        set target=null
    endfunction
    function InitTrig_Damage_Over_Time takes nothing returns nothing
        local trigger t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ  (t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition            (t,Condition(function onCastCondition))
        call TriggerAddAction               (t,function onCast)
        set t = null
    endfunction
     



    EDIT:

    I'm really sorry for my ignorance, but I believe that when somebody reads
    this thread, they will slowly be interested in JASS/vJASS...thanks to all who
    took part on this...
     
  18. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,082
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    private functions require JNGP.
     
  19. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,702
    Resources:
    0
    Resources:
    0
    1. Because StringHash returns a unique integer for a unique string, you could use any integer there as long as your not going to use that same number again for another purpose with the same childkey as the contents would be overwritten. You should read more about hashing if your interested to learn more about the said function.

    2. Blizzard likes to confuse people.

    3. jass is case-sensitive, use private instead of Private.

    Note: I know my coding style sucks :D
     
  20. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,206
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    Scopes and libraries are used to structure your code and to prevent it from interfering with other functions that you might have in your map. Functions and variables inside a scope or library can be declared private, which means that their names will become randomized, and all references to it inside the library will be changed to this new random name, while references outside of it won't. This means that code outside of the library won't know the names of your private members inside.

    This is good when you have a lot of different systems in your map, and possibly with different creators (since you might be using libraries written by someone else). Let's say you want to have this system you just posted in your map, but also a spell made by someone else, which also has the function "onCast". You might not always want to go in and change the name of the function everywhere it is referenced, and even if you would, it could become very confusing to keep a track of all your variable or funciton names. To solve this, you can put each of those systems inside a library, which is basically saying "this function belongs to this system, and that function belongs to that system".

    It would basically look like this:

    Code (vJASS):
    library MySpell

        private function onCast takes nothing returns nothing
            //blah blah blah
        endfunction

        private function TestCast takes nothing returns nothing
            call onCast() //this is legit
        endfunction

    endlibrary

    function TestCast takes nothing returns nothing  //this funciton can have the same name
        call onCast() //this is not legit, because onCast is private to mySpell.
    endfunction

     


    This way, the function onCast can ONLY be referenced by other functions inside the same library, and you are free to use the same name for functions in other scripts.