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 haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. Ride into the sunset with the 32nd Modeling Contest.
    Dismiss Notice
  4. This adventure has come to an end. Congratulate our heroes in the 16th Mini Mapping Contest Results.
    Dismiss Notice
  5. From the gates of hell, the 5th Special Effect Contest Results have emerged.
    Dismiss Notice
  6. Race against the odds and Reforge, Don't Refund. The 14th Techtree Contest has begun!
    Dismiss Notice
  7. 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.

JPAG - JASS Proper Application Guide

Discussion in 'JASS/AI Scripts Tutorials' started by Bribe, Sep 27, 2011.

  1. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    It should be at least mentionned, since the jass allows to have a global variable and a local variable with the same name, but prioritizes the globals (with recents patchs).

    EDIT :

    Or not
     
    Last edited: Feb 9, 2012
  2. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,158
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    It prioritizes the globals? That doesn't even make sense why they would do that. Epic fail right?
     
  3. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    It could refuse to compile, printing out a script error, or maybe prioritize the locals would make more sense, but they choiced this way.
    The variable shadowing was fixed because we could typecast without a function call, just with variables.

    We all know how blizzard choices how to fix jass bugs, it's most of time for the worst, not the best.
     
  4. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,158
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    I would pay cash if they made a fix to allow "code array" to compile, or even if they fixed the JASS compressor so our file sizes were not so huge.
     
  5. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    Code array woudn't be that useful without a native function ExecuteCode.

    Jass compressor ?
    What do you want mean ?
     
  6. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,158
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Well common.AI has a native "StartThread" (which sadly is not one of the natives that actually works), though I suppose "ExecuteFunc" could still be used though it doesn't work so well with needing string concatenation and all that.

    Code compression meaning that the JASS verbosity really takes up a LOT of map file size. The compression could be better.
     
  7. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,033
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    Code (vJASS):
    struct Code
        static hashtable TABLE

        trigger action

        static method GetFromSelf takes code c returns thistype
            local integer id = GetHandleId(Condition(c))

            local thistype this = LoadInteger(thistype.TABLE, id, 0)

            if (this == 0) then
                set this = thistype.allocate()

                set this.action = CreateTrigger()
                call SaveInteger(thistype.TABLE, id, 0, this)

                call TriggerAddCondition(this.action, Condition(c))
            endif

            return this
        endmethod

        static method Run takes nothing returns nothing
            call TriggerEvaluate(this.action)
        endmethod

        static method onInit takes nothing returns nothing
            set thistype.TABLE = InitHashtable()
        endmethod
    endstruct
     
  8. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    I don't know a thing in ai but i suppose, at least i hope, that StartThread works as intented in an ai script (but maybe the name is senseless comparing to what it does).
    Btw as you know string concatenation is a vJass problem, not a jass one.
    I mean it's unfair to bitching about ExecuteFunc, it even doesn't crash anymore with an invalid string argument, not to mention that is also the slowest way to execute a code.
    Now, i'm not a fan of using strings for functions, since it's error prone and is difficult to maintain, one of the many reason why i hate galaxy (from sc2).

    Jass without verbosity wouldn't be jass, yes it's annoying but it's also what it's making so easy to learn and use.

    Plus i don't think that in a real map the script size really does matter.
     
  9. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,158
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Well StartThread takes a "code" argument and you know what that means.

    Code size in a real map is quite important, a map with a couple dozen GUI spells converted to optimized JASS can cut out 50-100KB of data.
     
  10. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    common.ai natives are not meant to be used in a map script, only in an ai script.

    A script optimizer seems enough, and again comparing to custom models, skins, sounds, and whatever else, it's just negligible most of time.
    What i mean, is that reducing the jass verbosity is clearly not in my blizzard christmas gift wishes.
    We can have jass preprocessors for that.
    Fixing known bugs and implement all the NYI features, plus eventually add some new natives are definetely in my list.

    Too bad i don't believe in miracles.
     
  11. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,158
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Well the common.AI native "StartThread" as well as all but a few of the others doesn't work at all.
     
  12. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    In an ai script ?
     
  13. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,158
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    I dunno how to even use an AI script. Although if those natives work inside of one I think I would use AI scripts to code everything from now on.
     
  14. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    There is 99.9 % of chance that it is a joke but meh :

    I don't think so, you are even more limited than inside a map script (at least some common.j natives don't work inside it).
    Sure there are some cools functions, but most of them can be reproduced in some way or in an other in a map script.

    Plus, for the moment the only way to check if you haven't made any errors (typos or whatever) is to test your ai script ...
    Or maybe jasscraft or such tool can do the checks for you, i dunno.

    In fact if i have to make an ai script, i would use "regular" jass ...

    Here is a random demo ai script that i've stolen from someone, as you can se an ai script is thread based, i don't think you can use the event approach (except probably some directly related to an ai such as your base is attacked), nor timers.

    Code (vJASS):
    //===========================================================================
    // ElfesH
    //===========================================================================

    globals
        integer                 attackWave                 = 1
        integer                 nextDelay                  = 0
        integer                 awGold                     = 0
        integer                 awWood                     = 0
        string                  name                       = "computerElf"
        unit                    u_heros                    = null
    endglobals

    //===========================================================================
    function ReturnPlayerString takes integer i returns string
      if i == 1 then
      return "1"
      elseif i == 2 then
      return "2"
      elseif i == 3 then
      return "3"
      elseif i == 4 then
      return "4"
      elseif i == 5 then
      return "5"
      elseif i == 6 then
      return "6"
      elseif i == 7 then
      return "7"
      elseif i == 8 then
      return "8"
      elseif i == 9 then
      return "9"
      elseif i == 10 then
      return "10"
      elseif i == 11 then
      return "11"
      elseif i == 12 then
      return "12"
      endif
    endfunction

    //===========================================================================
    function InitOptions takes nothing returns nothing
        call SetCampaignAI(  )
        call SetDefendPlayer( false )
        call SetRandomPaths( false )
        call SetTargetHeroes( true )
        call SetPeonsRepair( false )
        call SetHeroesFlee( true )
        call SetHeroesBuyItems( true )
        call SetUnitsFlee( true )
        call SetGroupsFlee( false )
        call SetWatchMegaTargets( false )
        call SetIgnoreInjured( false )
        call SetHeroesTakeItems( true )
        call SetSlowChopping( false )
        call SetCaptainChanges( false )
        call SetSmartArtillery( true )
    endfunction

    //***************************************************************************
    //*
    //*  Heroes
    //*
    //***************************************************************************

    //===========================================================================
    // Stores hero ID and skills
    //===========================================================================
    function SetHero takes integer order, integer heroid returns nothing
        if (order == 1) then
            set hero_id = heroid
            if (heroid == 'Edem') then
                set skills1[ 1] = 'AEmb'
                set skills1[ 2] = 'AEim'
                set skills1[ 3] = 'AEev'
                set skills1[ 4] = 'AEmb'
                set skills1[ 5] = 'AEim'
                set skills1[ 6] = 'AEme'
                set skills1[ 7] = 'AEev'
                set skills1[ 8] = 'AEmb'
                set skills1[ 9] = 'AEim'
                set skills1[10] = 'AEev'
            endif
        endif
    endfunction

    //===========================================================================
    // Selects hero IDs for three possible heroes
    //===========================================================================
    function SelectHeroes takes nothing returns nothing
        local integer roll = GetRandomInt(1,100)
        call SetHero( 1, 'Edem' )
    endfunction

    //===========================================================================
    // Returns the hero skill for the given hero and level
    //===========================================================================
    function ChooseHeroSkill takes nothing returns integer
        local integer curHero = GetHeroId()
        local integer level = GetHeroLevelAI()
       
        if (level > max_hero_level) then
            set max_hero_level = level
        endif
       
        if (curHero == hero_id) then
            return skills1[level]
        elseif (curHero == hero_id2) then
            return skills2[level]
        elseif (curHero == hero_id3) then
            return skills3[level]
        endif
        return 0
    endfunction

    //***************************************************************************
    //*
    //*  Building and Harvesting
    //*
    //***************************************************************************

    //===========================================================================
    // Specifies building priorities for workers
    //===========================================================================

    function BuildPriorities takes nothing returns nothing
        call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )    
    endfunction

    //===========================================================================
    // Specifies harvesting priorities for workers
    //===========================================================================
    function HarvestPriorities takes nothing returns nothing
        local integer mine = TownWithMine()
        local integer allGold = GetUnitCountDone('opeo')
        local integer allWood = GetUnitCountDone('opeo')
        local integer numWorkers
        set numWorkers = 5
        call HarvestGold( 0, numWorkers )
        set numWorkers = 5
        call HarvestWood( 0, numWorkers )
        set numWorkers = 5
        call HarvestGold( 1, numWorkers )
        set numWorkers = 4
        call HarvestWood( 0, numWorkers )
    endfunction

    //===========================================================================
    // Determines all building and harvesting assignments for workers
    //===========================================================================
    function WorkerAssignment takes nothing returns nothing
        loop
           
            // Harvesting
            call ClearHarvestAI(  )
            call HarvestPriorities(  )
           
            // Building
            call InitBuildArray(  )
            call BuildPriorities(  )
           
            call Sleep( 2 )
        endloop
    endfunction

    //===================================
    function ReturnNeutralUnitById takes integer unitID returns unit
        local group g = CreateGroup()
       local unit u = null
       
       call GroupEnumUnitsOfPlayer(g,Player(PLAYER_NEUTRAL_PASSIVE),null)    
        loop
          set u = FirstOfGroup(g)
          exitwhen u == null
          if GetUnitTypeId(u) == unitID then
             return u
          endif
          call GroupRemoveUnit(g, u)
       endloop
       return null
    endfunction
    //===================================
    //==============UNITS================
    //===================================
    function ReturnUnitById takes integer unitID returns unit
        local group g = CreateGroup()
       local unit u = null
       
       call GroupEnumUnitsOfPlayer(g,ai_player,null)    
        loop
          set u = FirstOfGroup(g)
          exitwhen u == null
          if GetUnitTypeId(u) == unitID then
             return u
          endif
          call GroupRemoveUnit(g, u)
       endloop
       return null
    endfunction
    //====================================
    function CreateAttackGroup takes integer unitID returns group
        local integer all
        local integer i
        local unit u
        local group attack

            set i = 0
            set all = GetUnitCountDone(unitID)
            loop
            set u = ReturnUnitById(unitID)
            if (not IsUnitInGroup(u,attack)) then
            call GroupAddUnit(attack,u)
            set i = i + 1
            endif
            exitwhen (i == all)
            endloop
           
            return attack

    endfunction
    //===================================
    //==============HEROS================
    //===================================
    function CreateHeros takes nothing returns unit
       local group g = CreateGroup()
       local unit u = null
       
       call GroupEnumUnitsOfPlayer(g,ai_player,null)    
       loop
          set u = FirstOfGroup(g)
          exitwhen u == null
          if GetUnitTypeId(u) == hero_id then
             return u
          endif
          call GroupRemoveUnit(g, u)
       endloop
       return null
    endfunction
    //===================================
    function WaitHeros takes nothing returns nothing
        loop
          set u_heros = CreateHeros()
          call Sleep(2)
          exitwhen (u_heros != null)
        endloop
    endfunction
    //====================================
    function LGetHerosPercentLife takes nothing returns real
        local real value = GetUnitState(u_heros,ConvertUnitState(0))
        local real maxValue = GetUnitState(u_heros,ConvertUnitState(1))
        return value / maxValue*100
    endfunction
    //====================================
    function LifeNeeded takes nothing returns boolean
        if (LGetHerosPercentLife() < 25) then
         return true
        elseif (LGetHerosPercentLife() > 95) then
         return false
        endif      
    endfunction

    //===================================================================
    function A takes nothing returns nothing
        local group attackgroup = CreateGroup()
        local unit heros
        local unit fontaine = ReturnNeutralUnitById('nfoh')
        local integer random
        local real X
        local real Y = 877.0
        call WaitHeros()
      loop    
        if (LGetHerosPercentLife() < 25 and not IsUnitInRange(u_heros,fontaine,250)) then
           call IssuePointOrder(u_heros,"move",GetUnitX(fontaine),GetUnitY(fontaine))
           loop
           exitwhen IsUnitInRange(u_heros,fontaine,250)==true
           call Sleep(0.5)
           endloop
           loop        
           exitwhen LGetHerosPercentLife() == 100.0
            if IsUnitInRange(u_heros,fontaine,250) == true then
           call IssueImmediateOrder(u_heros,"holdposition")
            else
           call IssuePointOrder(u_heros,"move",GetUnitX(fontaine),GetUnitY(fontaine))
            endif
           call Sleep(0.5)
           endloop
           set random = GetRandomInt(1,3)
            if random == 1 then
             set X = -672.0
            elseif random == 2 then
             set X = 439.0
            elseif random == 3 then
             set X = -567.0
            endif
            call IssuePointOrder(u_heros,"attack",X,Y)
        endif
        if (LGetHerosPercentLife() > 25) then
          if (GetUnitCurrentOrder(u_heros) != OrderId("attack")) then
           call IssuePointOrder(u_heros,"attack",-672.0,Y)
          endif
        endif
           call Sleep(0.5)
      endloop
         endfunction
    //===========================================================================
    // main
    //===========================================================================
    function main takes nothing returns nothing
        call InitAI(  )
        call SetPlayerName( ai_player,(name + "[" + ReturnPlayerString(GetAiPlayer()) + "]") )
        call InitOptions(  )
        call SelectHeroes(  )
        call SetHeroLevels( function ChooseHeroSkill )
       
        call Sleep( 0.1 )
        call StartThread(function WorkerAssignment)
        call StartThread(function A)
        call PlayGame(  )
    endfunction
     
    Last edited: Dec 8, 2011
  15. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    lol
    Code (vJASS):
    function ReturnPlayerString takes integer i returns string
      if i == 1 then
      return "1"
      elseif i == 2 then
      return "2"
      elseif i == 3 then
      return "3"
      elseif i == 4 then
      return "4"
      elseif i == 5 then
      return "5"
      elseif i == 6 then
      return "6"
      elseif i == 7 then
      return "7"
      elseif i == 8 then
      return "8"
      elseif i == 9 then
      return "9"
      elseif i == 10 then
      return "10"
      elseif i == 11 then
      return "11"
      elseif i == 12 then
      return "12"
      endif
    endfunction


    HAHAHAHAHAHHAHHAHAHA

    How funny :>
     
  16. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    I vaguely remember that the author said that I2S don't work in an ai script (i have no clue
    if it's true or not).
    I've suggested a better algorithm (see how i'm smart), but he probably didn't cared :p

    Btw, i'm not off-topic, right ?
     
  17. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,158
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    It's a JASS discussion thread so it's still JASS.
     
  18. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    Btw i've read on w3c.net that most of common.j natives work in an ai script, so i've edited my previous post.
    But seriously if you want serious infos about ai scripts you should check about some tutorials, and/or experienced makers of ai, and not just assume my thoughts, as i know nothing about ai scripts.
     
  19. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    Code (vJASS):
    function LifeNeeded takes nothing returns boolean
        if (LGetHerosPercentLife() < 25) then
         return true
        elseif (LGetHerosPercentLife() > 95) then
         return false
        endif      
    endfunction


    >:eek:
    How does this compile?
    What if I had 50?
     
  20. Troll-Brain

    Troll-Brain

    Joined:
    Apr 27, 2008
    Messages:
    2,372
    Resources:
    1
    JASS:
    1
    Resources:
    1
    pjass won't allow this.
    official editor will compile it.

    If you had 50 it should returns false (but i have not tested)