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.

vJass: Advanced Initialization

Discussion in 'JASS/AI Scripts Tutorials' started by TriggerHappy, Jan 29, 2014.

  1. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,668
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    vJass: Advanced Initialization


    Table of Contents
    1. Introduction
    2. Main and Config
    3. Manual Initialization
    4. Notes

    Introduction
    This tutorial will teach you how to control the order and manner in which code is initialized.

    Generally vJass initializers are ran first, then custom triggers are ran after. However you can't pick the order by default.

    I will show you how this is changeable and how you can also avoid relatively slow ExecuteFunc calls.

    JassHelper (or JNGP) is required.

    Main and Config
    Every map has two core functions it runs on initialization (main and config).

    Inside these functions contains a bunch of generated code that initializes things in your map like custom triggers (InitTrig_Function).

    Typically in vJass you initialize functions by using the
    initializer
    keyword or by a structs onInit method.

    Inside
    function main
    is where JassHelper handles custom initializers by placing an
    ExecuteFunc
    call for each one. For example

    Code (vJASS):


    library Lib initializer onInit
        private function onInit takes nothing returns nothing
        endfunction
    endlibrary

    // adds this to your scripts main function

    function main takes nothing returns nothing
        //..
        call ExecuteFunc("Lib___onInit")
    endfunction
     

    Now, there's nothing wrong with this however maybe you want more control over how things are handled. Not to mention ExecuteFunc calls are significantly slower than normal function calls (*).

    To do this we use the very convenient
    //! inject
    feature which allows you to modify the config and main functions of your maps script. You can read more about the inject command in the JassHelper Manual.

    Before we do anything, lets go over each function.

    Main
    • This function is ran after the config function.
    • If you don't place dovjassinit inside the inject block then JassHelper will throw an error.
    • Responsible for calling functions that create the editors preplaced objects in your map (units, cameras, regions).

      Code (vJASS):

      //! inject main

          /*
          *  dovjassinit places all vJass initializers.
          *  This way you can control what's initialized before or after them.
          */

          //! dovjassinit

          // These initialize preplaced objects in the editor
          call CreateRegions()
          call CreateCameras()
          call CreateAllItems()
          call CreateAllUnits()

          // call InitTrig's
          call InitCustomTriggers()
      //! endinject
       

    Config
    • This function is ran before the main function.
    • Does not allow dovjassinit (will throw error).
    • Requires
      SetPlayers
      and
      InitCustomPlayerSlots
      function calls otherwise your map won't load. Normally the first argument of SetPlayers is the amount of players in the map, however it seems that any number works.
    • Responsible for defining start locations. If the function is overwritten and no
      DefineStartLocation
      calls are made, then
      GetPlayerStartLocation
      will return null.

      Code (vJASS):

      //! inject config
          call SetPlayers(0)
         
          call DefineStartLocation(0, 704.0, - 832.0)

          call InitCustomPlayerSlots()
      //! endinject
       

    Manual Initialization
    We are going to modify "main", not "config" because injecting config doesn't allow dovjassinit.

    For the sake of example, lets say you have a struct

    Code (vJASS):

    struct Data
        static method customInit takes nothing returns nothing
        endmethod
    endstruct
     

    and you want it initialized before everything else. We can do so like this:

    Code (vJASS):

    //! inject main
        call Data.customInit()
        //! dovjassinit
    //! endinject
     

    This proves useful for code optimization (faster execution time) and management.

    If the function is scoped you can simply use the compilation name. You're also likely going to need to call the World Editor generated functions.

    Code (vJASS):

    library Lib
        private function onInit takes nothing returns nothing
        endfunction
        public function Init takes nothing returns nothing
        endfunction
    endlibrary

    //! inject main
        call Lib___onInit() // ___ private
        call Lib_Init() // _ public

        //! dovjassinit

        // These initialize preplaced objects in the editor
        call CreateRegions()
        call CreateCameras()
        call CreateAllItems()
        call CreateAllUnits()

        // call (non-vjass) custom triggers initialization functions
        call InitCustomTriggers()
    //! endinject
     

    There, you have full control over initialization.

    Notes
    • JassHelper likely uses ExecuteFunc to avoid the thread crashing (OP Limit) or to be able to call functions from anywhere in the script.
    • There can only be one inject main/config block per map, so don't include it in public resources. It's meant to allow the map maker to have more control, not give resources initialization priority.
    • If you'd like you can use the config block instead of main for whatever reason.
    • If you're hitting the OP limit with your custom initialization you could split them up across each function.
     
    Last edited: Jan 29, 2014
  2. 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
    wow, this is nice to know... :)
     
  3. Daffa the Mage

    Daffa the Mage

    Map Moderator

    Joined:
    Jan 30, 2013
    Messages:
    7,707
    Resources:
    27
    Packs:
    1
    Maps:
    8
    Spells:
    16
    Tutorials:
    2
    Resources:
    27
    Nice share TriggerHappy! This can prove VERY useful to vjasser.
     
  4. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,668
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    Thanks for the feedback.

    I've reformatted and updated the tutorial with much more information.
     
  5. Hell_Master

    Hell_Master

    Joined:
    Nov 29, 2012
    Messages:
    5,512
    Resources:
    4
    Maps:
    3
    Template:
    1
    Resources:
    4
    Not much of a triggerer or even coder but this tutorial is quite neat and clear on its points. This makes me want to learn more in triggers and possible coding.

    Great job.
     
  6. Daffa the Mage

    Daffa the Mage

    Map Moderator

    Joined:
    Jan 30, 2013
    Messages:
    7,707
    Resources:
    27
    Packs:
    1
    Maps:
    8
    Spells:
    16
    Tutorials:
    2
    Resources:
    27
    there's one thing in my mind, did this trick will force the initialization to run our codes first before the actual initialization?
     
  7. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,033
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    Do not combine inits of different features in the same thread. Splitting them up is entirely the point to render them independent. Not only because of the operation limit but there are other termination reasons. Else you will change one thing in the future and wonder why something else stops working. Yes, you can write custom initializers and a tutorial could show how to encapsulate the function calls in order to check what has been completed/failed to do so for example.
     
  8. DysfunctionaI

    DysfunctionaI

    Joined:
    Mar 6, 2006
    Messages:
    281
    Resources:
    1
    Tutorials:
    1
    Resources:
    1
    Whoa, you can use this to play sounds when a player joins a custom game lobby.
     
  9. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,668
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    I wonder if there's any other tricks ..
     
  10. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,426
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    This is pretty neat if you want good control over your initialization order (useful when you have two triggers registering the same event but you want to make sure one fires before the other). I never really looked into //! inject much, so thanks for the explanations. :) Approved.
     
  11. Pinzu

    Pinzu

    Joined:
    Nov 30, 2007
    Messages:
    1,177
    Resources:
    3
    Spells:
    2
    Tutorials:
    1
    Resources:
    3
    I demand to know how to play Storm Earth and Fire in lobby!
     
  12. WaterKnight

    WaterKnight

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

    //! inject config
        call SetPlayers(1)
       
        call DefineStartLocation(0, 704.0, - 832.0)

        call InitCustomPlayerSlots()

        call PlayMusic("Sound\\Music\\mp3Music\\PH1.mp3")
    //! endinject
     


    Iirc, this can crash sometimes though.
     
  13. Almia

    Almia

    Joined:
    Apr 24, 2012
    Messages:
    4,839
    Resources:
    35
    Spells:
    30
    Tutorials:
    4
    JASS:
    1
    Resources:
    35
    Wow. I should use this.

    +rep
     
  14. BloodDrunk

    BloodDrunk

    Joined:
    May 11, 2012
    Messages:
    1,963
    Resources:
    1
    Maps:
    1
    Resources:
    1
    I myself have no idea how to manipulate this trick(s).
    But as Dysfunctional mentioned, I eould like to know how can I play music when the game is created (e.g. In lobby) and during loading time. Maybe play a sound when player joins?
    Is this possible?
     
  15. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,846
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
  16. Yammamoto

    Yammamoto

    Joined:
    Nov 18, 2013
    Messages:
    22
    Resources:
    1
    Maps:
    1
    Resources:
    1
    I'm trying to play music in the lobby and it is working, but the problem is: for some reason, it is removing one force from the lobby. My map has 2 forces, and all the players from the second force are moved to the first force and thus the second force is removed. Why is this happening? How can I fix it?
     
  17. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,033
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    The config is also controlling the player setup, in conjunction with the war3map.w3i that is. So just copying the above snippet would overwrite it. Take a look at the war3map.j script output that the WE generates without the custom injection, then take that version of the config (with dependencies ofc) and add the sound line.
     
  18. Yammamoto

    Yammamoto

    Joined:
    Nov 18, 2013
    Messages:
    22
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Worked. Thanks!