| 
        
       | 
      
        
          
              | 
              | 
           
          
              | 
              | 
              | 
           
          
              | 
            
              
                
                  
                    
                      
                        | World Editor FAQ: Custom Text | 
                       
                     
                   | 
                 
                
                  
                    
                      
                        
                          
                            
                              
                                Q: 
                               | What is custom text?
                                 
                             |  
                              | 
                                A: | 
                              Custom text (also known as JASS) is the programming language that all Warcraft 3 maps
                                run on. All the triggers created using the graphical user interface are
                                automatically translated into custom text when your map is saved. This includes triggers
                                added by 3rd party programs. Creeps, regions, and sound variables (actually stings) are
                                all translated into custom text as well. There are 3 ways to use custom text.Use
                                  the trigger action "Custom Script" to use a single line.
                                You can directly edit the text of a trigger using "Edit->Convert to Custom text".
                                Click on the very top entry in the list of triggers. There you can add your own
                                  global variables or functions.
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | What can I do in custom text that I can't do with the graphical user interface?
                                
                                 
                             |  
                              | 
                                A: | 
                              You can use local variables, call the same function from multiple places, and use all
                                of the functions included in the game (you can use most of them without custom text). In
                                addition custom text triggers will work with any editor. In general you use converted
                                triggers for math then single custom script lines for local variables and functions not
                                in the GUI. | 
                             
                           
                          
                          
                            
                              
                                Q: 
                               | How do I use local variables in the GUI? 
                                 
                             |  
                              | 
                                A: | 
                              Create a local variable with the same name and type as a global variable. The GUI will
                                allow you to select the global variable from the list as normal, but when the script
                                compiles, it will actually refer to the local variable instead.
                                
  
                                To create the local variable use a single line of custom text at the start of your
                                function like this:
                                
  
                                "Custom script: local integer udg_i"
                                
  
                                This would correspond to the global integer "i". Be careful with this, because the
                                variable is local to the function and not the trigger. Triggers often
                                contain multiple functions, especially since conditions are always seperate functions.
                                To get around this you can assign the local variable to a second global variable before
                                you enter the new function.
                                
  
                                You can only use one local variable this way per function. If you try to override with 2
                                locals at once they will both refer to the same variable. I have no idea why.
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | How do I figure out what order string to give a unit? 
                                 
                             |  
                              | 
                                A: | 
                              This trigger will give you the string of any order you give a unit: 
                                Display Order Strings
     Events
         Unit - A unit Is issued an order targeting an object
         Unit - A unit Is issued an order targeting a point
         Unit - A unit Is issued an order with no target
     Conditions
     Actions
         Game - Display to (All players) the text: (String((Issued order))) 
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | How do I use a leaderboard? 
                                 
                             |  
                              | 
                                A: | 
                              
                                Create a leaderboard. (don't do this step at map initialization)
                                Add players to the leaderboard.
                                Update the values you want displayed on the leaderboard.There are two ways to
                                  keep the values updated. If you are displaying something like gold or number of units
                                  in an area, then you can update the leaderboard every few seconds using the new gold
                                  count or number if units in area. If you are displaying something like number of
                                  rounds won or lives left, then you will need to keep track of the number separately.
                                  Use an array with one entry per player. Every time an event happens that would change
                                  the value, first update the array, then update the leaderboard with the current value
                                  of the array. For a "kills" leaderboard you can copy go here: http://www.elilz.com/demomaps.html
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | How do I make a hero selection system, like in Aeon of Strife or Hero Arena
                                  maps?
                                 
                             |  
                              | 
                                A: | 
                              The easiest way to select heroes is a trigger like this (you only need the one
                                trigger).event: A unit is issued an order targetting an object.
                                condition: ((target unit of issued order) is a hero) equal to true
                                condition: (ordered unit) type is equal to 
                                condition: owner of (target unit of issued order) is equal to (neutral passive)
                                action: create a unit of type (unit type of (target unit of issued order)) for
                                  player (owner of (ordered unit)) at ()
                                action: kill (ordered unit)
                                (optional) action: remove (target unit of issued order)
                                (optional) action: create item of type (ankh) and give it to (last created unit)
                                (optional) action: pan camera for (owner of (ordered unit)) to (location of unit
                                  (last created unit))Then place your heroes and change their owner to neutral
                                  passive. You will probably need to add a message at the start of your map telling your
                                  players how to choose a hero. You can add "Circle of Power" units under your heroes if
                                  you want but they are only there to look pretty.
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | How do I choose a random region, sound, item type, or something similar?
                                 
                             |  
                              | 
                                A: | 
                              Make an array of each possible value, then use a random number as an index into that
                                array. For example:Set MySoundArray<1> = BoneyardWhat1 
                                Set MySoundArray<2> = Credits 
                                Set MySoundArray<3> = LadyVashjYes1 
                                Sound - Play MySoundArray<(Random integer number between 1 and 3)>
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | How can I make something happen, but only for a single player? 
                                 
                             |  
                              | 
                                A: | 
                              Create a player variable named "LocalPlayer". Then run this trigger:
                                
Initialize LocalPlayer
    Events
        Map initialization
    Conditions
    Actions
        Custom script:   set udg_LocalPlayer = GetLocalPlayer()
                                Unlike all other variables in your map, this variable will be DIFFERENT for each person
                                playing the game. This means that if you use this variable in the condition part on an
                                "if" statement, you can make the game run differently for each player. If you create a
                                unit, kill a unit, or otherwise change the game state for one person and not for
                                another, then those players will disconnect from each other.
                                
  
                                If you play a sound, create a quest, or similar, the game state will not change and
                                nobody will disconnect. For example:
                                
Play Sound On Death
    Events
        Unit - A unit Dies
    Conditions
    Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                (Owner of (Dying unit)) Equal to LocalPlayer
            Then - Actions
                Sound - Play L01Arthas07  at 100.00% volume, attached to (Dying unit)
            Else - Actions
                                This will play a sound only for the owner of the dying unit.
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | I want to run a function for each member of a group, and I want to have a wait
                                  statement in that function. How do I do that? 
                                 
                             |  
                              | 
                                A: | 
                              
                                If you just use a "PickEveryX" function, then the wait statement will not work
                                  correctly. Every action after the wait will be skipped. This is because the actions
                                  inside the "pick" block are assigned to a seperate function and a pointer to that
                                  function is passed to the "pick" function. As a result the trigger will not be set up
                                  properly for sleeping within the block.
                                  
  
                                If you want the actions to happen at the same time for each memeber of the group,
                                  then put all the actions inside your "pick" block in a second trigger. Then inside the
                                  pick block, call your second trigger. "Picked Unit" and similar variables will be set
                                  properly.
                                  
  
                                If you do the member choosing yourself (pick a member from the group, run function,
                                  remove it, repeat), then the wait statement will work correctly. In this case it will
                                  wait to finish one member of the group before going on to the next.
                                  
  
                                  Not that none of this applies to "For Each Integer..." loops. There the wait will be
                                  executed just like any other action in the loop.
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | How do I get the level of a unit for use in a trigger?
                                 
                             |  
                              | 
                                A: | 
                              There is no "level of unit" trigger function. The best work-around would be to use the
                                Point-Value of Unit function instead, and set the point value for all relevant units via
                                the Object Editor. | 
                             
                           
                          
                            
                              
                                Q: 
                               | How do I create creeps and have them drop items like in the orc campaign?
                                 
                             |  
                              | 
                                A: | 
                              Open up the orc campaign and see. Extract the Orc expansion campaign maps from
                                war3xlocal.mpq (see the Import/Export section for how) and look at the triggers in the
                                2nd map. It has a system to spawn creeps and drop items when they die.  | 
                             
                           
                          
                            
                              
                                Q: 
                               | How can I keep the camera centered on a unit, while still letting the player use
                                  the minimap? 
                                 
                             |  
                              | 
                                A: | 
                              This trigger will force the camera to follow a unit around. The camera will slide to
                                keep up with the unit, which looks a little nicer than the normal "lock camera to unit"
                                trigger. Since the camera is not techincally locked, the player will be able to use the
                                minimap normally, and can pull the camera away for a very short period of time.
                                Center Camera
    Events
        Time - Every 0.30 seconds of game time
    Actions
        Camera - Pan camera for Player 1 (Red) to (Position of Spell Breaker 0000 ) over 0.50 seconds
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | Do regions have to be rectangles? 
                                 
                             |  
                              | 
                                A: | 
                              No. "rect" variables have to be rectangles. "region" variables can be made up of
                                multiple rects, so they can make any shape. The GUI sometimes uses regions and sometimes
                                uses rects, but it calls both regions.So basically it would be really complicated
                                to use but you could use the real "regions" if you wanted to. You can find the
                                appropriate functions by extracting common.j  | 
                             
                           
                          
                            
                              
                                Q: 
                               | Do I have to delete points and unit groups? What does "set bjWantDestroyGroup =
                                  true" mean? 
                                 
                             |  
                              | 
                                A: | 
                              You should not use bjWantDestroyGroup, I'll explain why it exists at the end.
                                
  
                                Any time you create an object in a trigger it will exist until you destroy it or the map
                                ends.
                                
  
                                You can think of them all as being similar to units. Imagine you have a trigger that
                                creates a unit, then attaches a special effect to that unit. When your trigger ends, you
                                still have a unit with a special effect attached. If you run this trigger many times,
                                you will end up with many units with special effects attached. The same thing happens
                                for a point. You create a random point in a region, then attach a special effect to that
                                point. When the trigger ends you still have a point and a special effect. If you run
                                this trigger many times you will end up with many points and many special effects. In
                                both cases you will need to destroy the points, units, and special effects if you don't
                                want them to build up.
                                
  
                                Variables are not objects, they are handles for objects. You assign a point to a
                                variable the same way you would assign a unit.
                                
  
                                If you want to create a unit, use it for something, and then destroy it, then you will
                                need to store that unit in a variable so you can access it later:
                                
  
                                1. create a unit 
                                2. store that unit in [variable] 
                                3. do something to unit in [variable] 
                                4. remove unit in [variable] 
                                
  
                                If you do this every time you create a unit, then units won't build up over time. Points
                                follow the same rules. Create your point, assign it to a variable, do something with it,
                                and then destroy it. Otherwise they will build up over time.
                                
  
                                The problem is that the GUI functions skip steps 2 and 4. They create a group and use
                                it, but without ever assigning it to a variable or destroying it.
                                
  
                                Blizzard people figured out the problem, but they couldn't find a good solution (I'm not
                                making this up, Brett told us earlier). They could decompose every "each unit in group"
                                function in every Blizzard map, but that would take forever. What they wanted to do was
                                make the "each unit in group" function destroy the group that it was using. They
                                couldn't do that exactly though, because the group may not be temporary! If you have a
                                group variable chances are you don't want your group destroyed every time you use a for
                                each function on it. What they did instead was sort of a cross between the two
                                approaches. They modified the for each function to delete the group that was passed to
                                it ONLY IF "bjWantDestroyGroup == true". Then all they had to do was set
                                bjWantDestroyGroup before every "for each unit" function that did NOT use a group
                                variable.
                                
  
                                If you are making a map from scratch then don't do this! Do exactly the same thing as
                                for units and points. Make a unit group variable named "TempGroup", and do the 4 step
                                process above.
                                
  
                                However if your map is short and your triggers don't run very often you probably don't
                                care. If you only leak 1000 points during your entire map then it won't really matter.
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | How do I make different background music play during my map?
                                
                                 
                             |  
                              | 
                                A: | 
                              This is referring to the random music that plays throughout the map, there is already
                                information on playing a specific song at a specific point earlier in this FAQ. Let's
                                say you have a map where everyone is Human but you want to have some Orc and Undead
                                music play as well, or you have a whole list of custom songs you want played randomly.
                                
  
                                You need to use the trigger action: Sound - Set Music List.
                                
  
                                Unfortunately, while this action is available in the GUI, it can only be used in custom
                                text (JASS) because the paramater it takes, the list of music, doesn't have any way to
                                specify it in the GUI. It's still pretty easy to do though, even if you don't know a
                                thing about JASS or custom text. Here's what you do:
                                
  
                                1. Make a trigger called Setup Music.
                                2. Add an action to your Melee Initialization trigger to run the Setup Music trigger
                                (that way the map will start out with one of your song choices right away).
                                3. Add the Sound - Set Music List command to the Setup Music trigger, but just leave the
                                Music paramater as it is.
                                4. Convert the Setup Music trigger to custom text.
                                5. Look in the trigger for the part that says ("Music").
                                6. Replace Music with a list of songs you want to play seperated by a semicolon (;).
                                
  
                                Each song built into the game (both TFT and ROC) is in the format of
                                Sound\\Music\\mp3Music\\SongName.mp3. Imported songs are going to be
                                war3mapImported\\SongName.mp3. So, an example of this command would look like:
                                
  
                                call SetMapMusicRandomBJ(
                                "Sound\\Music\\mp3Music\\OrcX1.mp3;Sound\\Music\\mp3Music\\NightElfX1.mp3;Sound\\Music\\mp3Music\\ArthasTheme.mp3"
                                )
                                
  
                                Now there's one problem with this. Even though you can make the list as long as you want
                                in the editor, the string will be cut short in the actual game (I'm assuming it's at 255
                                characters but I haven't confirmed this). This means two things: first, that it will
                                only actually play the first bunch of songs in the list, and second, that after a few
                                songs it will stop playing music altogether for the rest of the map (this is because it
                                attempts to play a song who's name was cut off halfway through it when the string was
                                cut short). If you only want to play 3-5 songs it's probably not going to happen, but if
                                you want to play more, you'll need an alternative.
                                
  
                                To get around this, add an Event to your Setup Music trigger that is Timer - Periodic
                                Event every 200 seconds. Now in the trigger itself, make several of the random music
                                commands like above each with a different set of 3-4 songs. Then, at the beginning of
                                the actions assign a variable to a random number between 1 and the number of song sets
                                you have. Then using if statements, have it run one of the song lists based on what
                                random number was picked. This way every few minutes the map will change the set of
                                random songs, so that all of your songs eventually have a random chance of being played.
                                
  
                                Don't worry, when the set of songs changes it doesn't stop playing the current song, it
                                waits until the current song is finished before using the new song list. The transition
                                will be smooth and unnoticable, you won't be able to tell the difference between doing
                                it this way and having just one song list.
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | How do I make a building cancel training a unit?
                                
                                 
                             |  
                              | 
                                A: | 
                              Use the custom text function:
                                
call IssueImmediateOrderById( udg_buildingUnit, 0x000d0008 )
 
                                If you have a global unit variable called buildingUnit, then the preceding line will
                                cancel a unit being trained by buildingUnit. You can use the same technique to cancel
                                upgrades or research.
                               | 
                             
                           
                          
                            
                              
                                Q: 
                               | How do I kill all the units and share all the gold for a player who leaves the
                                  game?
                                 
                             |  
                              | 
                                A: | 
                              Use this trigger:
                                
Melee Initialization
    Events
        Player - Player 1 (Red) leaves the game
        Player - Player 2 (Blue) leaves the game
        Player - Player 3 (Teal) leaves the game
        ...
    Conditions
    Actions
        Set tempPlayerGroup = (All allies of (Triggering player))
        Player Group - Remove (Triggering player) from tempPlayerGroup
        Set tempInteger = (Number of players in tempPlayerGroup)
        -------- We want to avoid dividing by zero if there are no allies left. --------
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                tempInteger Greater than 0
            Then - Actions
                Set tempInteger = (((Triggering player) Current gold) / tempInteger)
                Player Group - Pick every player in tempPlayerGroup and do (Actions)
                    Loop - Actions
                        Player - Add tempInteger to (Picked player) Current gold
            Else - Actions
        -------- Destroy the player group once we are done with it. --------
        Custom script:   call DestroyForce( udg_tempPlayerGroup )
        -------- Now kill all the leaving player's units. --------
        Set tempUnitGroup = (Units owned by (Triggering player))
        Unit Group - Pick every unit in tempUnitGroup and do (Actions)
            Loop - Actions
                Unit - Explode (Picked unit)
        -------- Destroy the unit group once we are done with it. --------
        Custom script:   call DestroyGroup( udg_tempUnitGroup )
                               | 
                             
                           
                         | 
                       
                     
                   | 
                 
               
             | 
           
          
              | 
              | 
              | 
           
          
              | 
              | 
           
         
       |