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. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,700
    Resources:
    0
    Resources:
    0
    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).

    Code (vJASS):

    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.
     
  2. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    @Dr Super Good

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

    Code (vJASS):

    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'...
     
  3. 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, Test2 is useless there so just remove it...
     
  4. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,700
    Resources:
    0
    Resources:
    0
    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.
     
  5. 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
    why? because he is trying to learn... he doesn't know that much yet that's why he is asking...
     
  6. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    You beat me to it...Now that my friend is the right answer...thanks...
     
  7. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,700
    Resources:
    0
    Resources:
    0
    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.
     
  8. 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
    I'm not saying that its offending, I was simply speaking out my mind... anyway, never saw the VB part... ^_^
     
  9. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    All you guys are very helpful, nobody is offending somebody here...cheer up chobibo...
     
  10. Raven0

    Raven0

    Joined:
    Oct 16, 2010
    Messages:
    878
    Resources:
    2
    Maps:
    2
    Resources:
    2
    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
     
  11. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    No, I'm 100% Filipino...I use Jasscraft for help/reference...I will switch to JNGP someday...
    Right now, I know a little bit of the structure of JASS as I have been reading tutorials also...
     
  12. Raven0

    Raven0

    Joined:
    Oct 16, 2010
    Messages:
    878
    Resources:
    2
    Maps:
    2
    Resources:
    2
    You should really switch to it right now. You can use the regular WE if you ever wanted to code in GUI (for hashtable support). But for all jass-related coding, you want JNGP.

    It has syntax highlighting, additional capabilities, and comes with a function list that includes the vast majority of all the natives and BJs.
     
  13. baassee

    baassee

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

    So let me explain a little further what DSG meant with the "Skip Remaining Actions" that is in GUI.

    Basic it will look like this:

    Code (vJASS):

    function something takes nothing returns nothing
    local integer i = GetRandomInt(1,2)
    local boolean b = false
    if i == 2 then
    set b = true
    endif
    if b then
    return //this is what in GUI is called, skip remaining actions
    endif
    //it will skip any action below this line so
    call BJDebug("This will not show up if the integer i equals to 2")
    endfunction
     


    Sorry that I didn't align it but I'm just writing at free hand here.

    Yet that was a function that returned nothing what DSG said is that it has a built-in return at the bottom line of the function. So what happens if we have a function that returns something else?

    Code (vJASS):

    function something2 takes nothing returns real
    /* this will not work as there are no
    returns and the function should return
    a real value so this will give you
    a syntax error with JNGP
    */

    endfunction
     


    This below will work as it returns a real variable although the returned value will be 0. as the real has just been declared. Yet we can have all these other real actions for no purpose. Let's give them one.

    Code (vJASS):

    function something3 takes nothing returns real
    local real sum
    local real a = GetRandomReal(5.,10.)
    local real b = (GetRandomReal(0., 50.) / a) + a
    local real c = GetRandomReal(0., 50.) + b - a
    return sum
    endfunction
     


    This will return a completly random value.

    Code (vJASS):

    function something4 takes nothing returns real
    local real sum
    local real a = GetRandomReal(5.,10.)
    local real b = (GetRandomReal(0., 50.) / a) + a
    local real c = GetRandomReal(0., 50.) + b - a
    set sum = a + b + c
    return sum
    endfunction
     
     
  14. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    whoaaa, slowly baassee, Im not there yet...and yes I will use JNGP...
     
  15. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    You should be there now. This is among the very basics of JASS and if you get JNGP, learn vJASS straight away ! :D
     
  16. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    well, I understand a few but not all coz Im loaded now, still have a map to finish, :)...

    EDIT:

    OK Im making a spell, but with GUI to text of course but I changed some lines...

    Is this pure JASS or correct?...

    Code (vJASS):

    function Trig_Blood_Curse_Conditions takes nothing returns boolean
        return ( GetUnitAbilityLevelSwapped('A006', GetTriggerUnit()) > 0 )
        return ( UnitHasBuffBJ(GetTriggerUnit(), 'B000') == false )
    endfunction
    function Trig_Blood_Curse_Actions takes nothing returns nothing
        local unit hero = GetTriggerUnit()
        local location loc = GetUnitLoc(hero)
        call CreateNUnitsAtLoc( 1, 'h001', GetOwningPlayer(hero), loc, bj_UNIT_FACING )
        call UnitAddAbilityBJ( 'A005', GetLastCreatedUnit() )
        call UnitApplyTimedLifeBJ( 1.00, 'BTLF', GetLastCreatedUnit() )
        call SetUnitAbilityLevelSwapped( 'A005', GetLastCreatedUnit(), GetUnitAbilityLevelSwapped('A006', hero ))
        call IssueTargetOrderBJ( GetLastCreatedUnit(), "unholyfrenzy", hero )
        set hero = null
        set loc = null
    endfunction
    //===========================================================================
    function InitTrig_Blood_Curse takes nothing returns nothing
        set gg_trg_Blood_Curse = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Blood_Curse, EVENT_PLAYER_UNIT_ATTACKED )
        call TriggerAddCondition( gg_trg_Blood_Curse, Condition( function Trig_Blood_Curse_Conditions ) )
        call TriggerAddAction( gg_trg_Blood_Curse, function Trig_Blood_Curse_Actions )
    endfunction
     
     
    Last edited: Feb 28, 2011
  17. Fingolfin

    Fingolfin

    Joined:
    Jan 11, 2009
    Messages:
    3,196
    Resources:
    153
    Models:
    143
    Icons:
    1
    Packs:
    4
    Skins:
    2
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    153
    No, that is more like GUI jass.

    First of all, you can check out the function CreateNUnitsAtLoc() in jasscraft or in the JNGP function list. You will notice that it actually works much like a function you would create yourself, and is basically just made by blizzard to fit the parameters you enter in the GUI editor. This is how it looks:

    Code (vJASS):
    function CreateNUnitsAtLoc takes integer count, integer unitId, player whichPlayer, location loc, real face returns group
        call GroupClear(bj_lastCreatedGroup)
        loop
            set count = count - 1
            exitwhen count < 0
            call CreateUnitAtLocSaveLast(whichPlayer, unitId, loc, face)
            call GroupAddUnit(bj_lastCreatedGroup, bj_lastCreatedUnit)
        endloop
        return bj_lastCreatedGroup
    endfunction


    It assumes that you want to create more than one unit, and therefore commences a loop that calls another BJ, CreateUnitAtLocSaveLast(), which is made to store the "last created unit" variable that you can find in GUI. Inside this funciton, you can finally find the native function; "CreateUnit()".

    CreateUnit requires the folowing parameters:

    Code (vJASS):
    native        CreateUnit           takes player id, integer unitid, real x, real y, real face returns unit


    As most things in JASS, it uses x/y values instead of locations, since they are much faster and does not leak (and since they're not handles, you don't even have to null the variables when you're done).

    If instead you replace CreateNUnitsAtLoc with this function, you will get this:

    Code (vJASS):
    local unit u = CreateUnit(GetOwningPlayer(hero), 'h001', GetUnitX(hero), GetUnitY(hero), 0.)


    Now GetLastCreatedUnit will not be saved, and neither will GetLastCreatedGroup, but instead you can use the local handle "u" to reference the unit you just created. Your computer also don't have to take the long way around, calling two other functions before it can call the native that actually creates the unit!

    After this, we have the oh, so vain function UnitAddAbilityBJ().
    This is how it looks:

    Code (vJASS):
    function UnitAddAbilityBJ takes integer abilityId, unit whichUnit returns boolean
        return UnitAddAbility(whichUnit, abilityId)
    endfunction


    As you can see, it merely calls the native and does nothing more!
    Instead, you should change it to this:

    Code (vJASS):
    call UnitAddAbility(u,  'A005')


    And it already looks much more tidy.

    JNGP will show BJ functions in red text as a way of sayong "OH YOU BAD BOY!", informing you that it has a native nested inside it. You can look up all the other functions you have that are displayed in red and see what natives they are calling, and try to replace them with theese, and your code will be much more efficient.


    EDIT: Also notice that your condition is using two returns on top of eachother. This means that the function will ONLY return the first one, since the function automatically ends after returning.
    In other words, it will never check if a unit has the buff 'B000', and only return wether the unit has a certain ability. You should place your "true" return inside an "if" statement instead, and have the "false" return at the end of the function. This means that the condition will return "true" if your "if" statement is passed, and otherwise read the "false" return if the "if" doesn't pass.
     
  18. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,700
    Resources:
    0
    Resources:
    0
    no vjass:
    Code (vJASS):


    //===========================================================================
    //=                             Blood Curse                                 =
    //=                           by mckill 2009                                =
    //===========================================================================

    globals
    //===========================================================================
    //=                         Blood Curse Constants                           =
    //===========================================================================
        constant integer    BC_SPELL_ID             = 'A006'
        constant integer    BC_SPELL_BUFF_ID        = 'B000'
        constant integer    BC_SPELL_DUMMY_SPELL    = 'A005'
        constant integer    BC_SPELL_DUMMY_ORDER_ID = OrderId("unholyfrenzy")
       
        constant integer    BC_SPELL_DUMMY_ID       = 'h001'
    //===========================================================================
    endglobals

    //===========================================================================
    //=                        Blood Curse Conditions                           =
    //===========================================================================
    function BloodCurseCondition takes nothing returns boolean
        return (not (GetUnitAbilityLevel(GetTriggerUnit(),BC_SPELL_ID)==0)) and (not (GetUnitAbilityLevel(GetTriggerUnit(), BC_SPELL_BUFF_ID)==0))
    endfunction
    //===========================================================================

    //===========================================================================
    //=                         Blood Curse Actions                             =
    //===========================================================================
    function BloodCurseAction takes nothing returns nothing
        local unit hero=GetTriggerUnit()
        // Instead of using locations, you could just use reals
        local real posX=GetUnitX(hero)
        local real posY=GetUnitY(hero)
        // I like using variables to easily understand its use, you can inline them for more speed.
        local integer level=GetUnitAbilityLevel(hero,BC_SPELL_DUMMY_SPELL)
        // CreateUnit returns a unit, so we could immediately set it to a local variable/pointer
        local unit dummy=CreateUnit(GetOwningPlayer(hero),BC_SPELL_DUMMY_ID,posX,posY,0)
       
        // Execute the dummy actions.
        call UnitAddAbility(dummy,BC_SPELL_DUMMY_SPELL)
        call SetUnitAbilityLevel(dummy,BC_SPELL_DUMMY_SPELL,level)
        call IssueTargetOrderById(dummy,BC_SPELL_DUMMY_ORDER_ID,hero)
        //==================================================
       
        // Kill the dummy.
        call SetUnitExploded(dummy,true)
        call UnitApplyTimedLife(dummy,'BTLF',1.0)
        //==================================================
       
        // Destroy local handles and remove pointer to objects.
        // Note: You forgot to remove the location in your original script.
        set hero=null
        set dummy=null
    endfunction
    //===========================================================================

    //===========================================================================
    //=                      Blood Curse Initialization                         =
    //===========================================================================
    function InitTrig_Blood_Curse takes nothing returns nothing
        local trigger t=CreateTrigger()

        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_ATTACKED)
        call TriggerAddCondition(t,Condition(function BloodCurseCondition))
        call TriggerAddAction(t,function BloodCurseAction)
       
        // just in case you want the trigger referenced.
        set gg_trg_Blood_Curse=t
    endfunction
    //===========================================================================
     
     
  19. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,059
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Good JASS version:

    Code (vJASS):

    function Blood_Curse_OnAttack takes nothing returns boolean
        local unit hero = GetTriggerUnit()
        local unit dummy
        if (GetUnitAbilityLevel(hero, 'A006') > 0 and GetUnitAbilityLevel(hero, 'B000') == 0) then
            set dummy = CreateUnit(GetTriggerPlayer(), 'h001', GetUnitX(hero), GetUnitY(hero), bj_UNIT_FACING)
            call UnitAddAbility(dummy, 'A005')
            call UnitApplyTimedLife(dummy, 'BTLF', 1.00)
            call SetUnitAbilityLevel(dummy, 'A005', GetUnitAbilityLevel(hero, 'A006'))
            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 Blood_Curse_OnAttack))
        set t = null
    endfunction
     
     
  20. Dr Super Good

    Dr Super Good

    Spell Reviewer

    Joined:
    Jan 18, 2005
    Messages:
    25,617
    Resources:
    3
    Maps:
    1
    Spells:
    2
    Resources:
    3
    You do not cache the ability level of the hero spell.
    To improve integrity, you should use global constants for types which are referenced more than once (like 'A006') as that means 1 change sufices to update all references unlike the current scheeme where bugs could be inroduced if someone forgets to update one of the references.