What happens to JASS?
Introduction
We all have heard of JASS and what it is. Some of us have even used it and are pretty good at coding with it.
This tutorial will explain what happens to the JASS code that you write in WE and how you might take advantage of this "what happens behind the scenes" knowledge.
Limited JASS
Sure- We all know how much more powerful JASS is than GUI triggering. It allows the use of local variables, your own functions, more control over global variables etc...
However, as you get to know JASS, or have some programming background, you'll see that JASS is almost extremely limited in comparison with almost any other programming language. (C, Java, Python, anything)
Especially if you have some C, C++ experience, you'll see that JASS is almost completely different. (well maybe not)
A slice of JASS
To really see what happens behind the the scene, go type in some erroneous code anywhere in the trigger editor ( as custom text/JASS ).
Then try to SAVE the map.
In NewGenEditor (almost everyone uses that now anyways), you'll see that you can move up and down in the code.
What you have in front of you is the complete map script.
JASS isn't just what YOU use to program spells, triggers, systems but it's what Warcraft 3 actually uses code all maps. When people say JASS, it's usually the programming language you can use to make your own scripts but everything in a map is JASS. (Except data like unit attacks, hp, and other things)
So a complete map script. (That has no triggers in it)
This may be the first time you see the function MAIN, plus all these other functions that you have never declared. These are JASS code automatically made for every map.
Here, you'll see that JASS is NOT so different from C =D
IT'S A MAIN FUNCTION!.
That's right. It's a main() function.
Just a review for programmers.
main functions are always the first function executed when the map starts. Nono, it's not a trigger. It's a function that is SUPPOSED to be run when the map starts!
Ever wondered why those InitTrig_XXXXXXX functions ALWAYS run at the start of the map? Here is where the mystery unfolds.
This function was defined way up in the map script.
As of now, the function is empty because there were no triggers in the map when I saved it.
But!
Watch what happens when you actually add triggers.
When you save the map, it automatically ADDS the two InitTrig function from my two triggers and calls it in the InitCustomTriggers function which in turn
was called from the main function which was called when the map started.
So that's the magic behind InitTrig functions which also explains why WE demands a InitTrig in every trigger block that you write.
To sum up everything so far.
So, you learn that the building blocks of your maps aren't triggers, it's FUNCTIONS. Everything about triggers - the actions, and even the conditions are all just functions.
Based on what I know, I don't think there is a tool that allows you to edit the map scripts besides the triggers, but having this sort of fundamental knowledge is useful.
For example, those Map Initialization triggers that we use
Some of us may have taken advantage of the this one-time fire event right at the beginning of this map to initialize values. For example, Save/Load codes. You might initialize the values of the variables by creating a trigger, making it fire with the Map Initialization event, and then add the code as the trigger action that sets up all the variables for you.
NOTE - This does NOT work when manipulating Game elements like units or players. This is strictly for manipulation of things that can be manipulated even before map has loaded. This is before the preplaced units have been placed, and before the players start playing.
Why bother creating the trigger at all, honest? The InitTrig function automatically runs when the map is being loaded, so why not just call the Initialization function from that function?
Make sure the trigger block is titled "INITIALIZE VARS" of course. That way the map script automatically produced will call this InitTrig function.
One more note about what WE does for your triggers and how it changes it into JASS.
Have you also wondered how the InitTrig's always seem to have a global trigger variable available for use? It's not that surprising to see that WE automatically declares a global trigger variable for each trigger block that you create in the Trigger Editor.
Note, trigger variables are handles and handles by themselves don't take up that much memory. When you use the CreateTrigger() function, the trigger is actually created and that takes up more memory.
Wrapping Up
Have fun with this knowledge, whether you knew about it or not. I myself only saw JASS for triggering until I stumbled onto this. There may not be many practical uses for this, but it's always good to know how something works.
Introduction
We all have heard of JASS and what it is. Some of us have even used it and are pretty good at coding with it.
This tutorial will explain what happens to the JASS code that you write in WE and how you might take advantage of this "what happens behind the scenes" knowledge.
Limited JASS
Sure- We all know how much more powerful JASS is than GUI triggering. It allows the use of local variables, your own functions, more control over global variables etc...
However, as you get to know JASS, or have some programming background, you'll see that JASS is almost extremely limited in comparison with almost any other programming language. (C, Java, Python, anything)
Especially if you have some C, C++ experience, you'll see that JASS is almost completely different. (well maybe not)
A slice of JASS
To really see what happens behind the the scene, go type in some erroneous code anywhere in the trigger editor ( as custom text/JASS ).
Then try to SAVE the map.
In NewGenEditor (almost everyone uses that now anyways), you'll see that you can move up and down in the code.
What you have in front of you is the complete map script.
JASS isn't just what YOU use to program spells, triggers, systems but it's what Warcraft 3 actually uses code all maps. When people say JASS, it's usually the programming language you can use to make your own scripts but everything in a map is JASS. (Except data like unit attacks, hp, and other things)
So a complete map script. (That has no triggers in it)
JASS:
globals
// Generated
trigger gg_trg_Melee_Initialization = null
endglobals
//===========================================================================
//
// Just another Warcraft III map
//
// Warcraft III map script
// Generated by the Warcraft III World Editor
// Date: Tue Oct 30 15:36:26 2007
// Map Author: Unknown
//
//===========================================================================
//***************************************************************************
//*
//* Global Variables
//*
//***************************************************************************
function InitGlobals takes nothing returns nothing
endfunction
//***************************************************************************
//*
//* Custom Script Code
//*
//***************************************************************************
//***************************************************************************
//*
//* Triggers
//*
//***************************************************************************
//===========================================================================
function InitCustomTriggers takes nothing returns nothing
endfunction
//===========================================================================
//***************************************************************************
//*
//* Players
//*
//***************************************************************************
function InitCustomPlayerSlots takes nothing returns nothing
// Player 0
call SetPlayerStartLocation( Player(0), 0 )
call SetPlayerColor( Player(0), ConvertPlayerColor(0) )
call SetPlayerRacePreference( Player(0), RACE_PREF_HUMAN )
call SetPlayerRaceSelectable( Player(0), true )
call SetPlayerController( Player(0), MAP_CONTROL_USER )
endfunction
function InitCustomTeams takes nothing returns nothing
// Force: TRIGSTR_002
call SetPlayerTeam( Player(0), 0 )
endfunction
//***************************************************************************
//*
//* Main Initialization
//*
//***************************************************************************
//===========================================================================
function main takes nothing returns nothing
call SetCameraBounds( -3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), -3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), -3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), -3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM) )
call SetDayNightModels( "Environment\\DNC\\DNCLordaeron\\DNCLordaeronTerrain\\DNCLordaeronTerrain.mdl", "Environment\\DNC\\DNCLordaeron\\DNCLordaeronUnit\\DNCLordaeronUnit.mdl" )
call NewSoundEnvironment( "Default" )
call SetAmbientDaySound( "LordaeronSummerDay" )
call SetAmbientNightSound( "LordaeronSummerNight" )
call SetMapMusic( "Music", true, 0 )
call InitBlizzard( )
//! initstructs
//! initdatastructs
call InitGlobals( )
call InitCustomTriggers( )
call RunInitializationTriggers( )
endfunction
//***************************************************************************
//*
//* Map Configuration
//*
//***************************************************************************
function config takes nothing returns nothing
call SetMapName( "Just another Warcraft III map" )
call SetMapDescription( "Nondescript" )
call SetPlayers( 1 )
call SetTeams( 1 )
call SetGamePlacement( MAP_PLACEMENT_USE_MAP_SETTINGS )
call DefineStartLocation( 0, -576.0, -1024.0 )
// Player setup
call InitCustomPlayerSlots( )
call SetPlayerSlotAvailable( Player(0), MAP_CONTROL_USER )
call InitGenericPlayerSlots( )
endfunction
This may be the first time you see the function MAIN, plus all these other functions that you have never declared. These are JASS code automatically made for every map.
Here, you'll see that JASS is NOT so different from C =D
JASS:
function main takes nothing returns nothing
call SetCameraBounds( -3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), -3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), -3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), -3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM) )
call SetDayNightModels( "Environment\\DNC\\DNCLordaeron\\DNCLordaeronTerrain\\DNCLordaeronTerrain.mdl", "Environment\\DNC\\DNCLordaeron\\DNCLordaeronUnit\\DNCLordaeronUnit.mdl" )
call NewSoundEnvironment( "Default" )
call SetAmbientDaySound( "LordaeronSummerDay" )
call SetAmbientNightSound( "LordaeronSummerNight" )
call SetMapMusic( "Music", true, 0 )
call InitBlizzard( )
//! initstructs
//! initdatastructs
call InitGlobals( )
call InitCustomTriggers( )
call RunInitializationTriggers( )
endfunction
IT'S A MAIN FUNCTION!.
That's right. It's a main() function.
Just a review for programmers.
main functions are always the first function executed when the map starts. Nono, it's not a trigger. It's a function that is SUPPOSED to be run when the map starts!
Ever wondered why those InitTrig_XXXXXXX functions ALWAYS run at the start of the map? Here is where the mystery unfolds.
JASS:
call InitCustomTriggers( )
This function was defined way up in the map script.
JASS:
//***************************************************************************
//*
//* Triggers
//*
//***************************************************************************
//===========================================================================
function InitCustomTriggers takes nothing returns nothing
endfunction
As of now, the function is empty because there were no triggers in the map when I saved it.
But!
Watch what happens when you actually add triggers.
JASS:
//***************************************************************************
//*
//* Triggers
//*
//***************************************************************************
//===========================================================================
// Trigger: newtrig
//===========================================================================
function Trig_newtrig_Conditions takes nothing returns boolean
if ( not ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) == true ) ) then
return false
endif
return true
endfunction
function Trig_newtrig_Actions takes nothing returns nothing
call DoNothing( )
endfunction
//===========================================================================
function InitTrig_newtrig takes nothing returns nothing
set gg_trg_newtrig = CreateTrigger( )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_newtrig, Player(0), EVENT_PLAYER_UNIT_DEATH )
call TriggerAddCondition( gg_trg_newtrig, Condition( function Trig_newtrig_Conditions ) )
call TriggerAddAction( gg_trg_newtrig, function Trig_newtrig_Actions )
endfunction
//===========================================================================
// Trigger: haha
//===========================================================================
function Trig_haha_Actions takes nothing returns nothing
call AdjustPlayerStateBJ( 1000, Player(0), PLAYER_STATE_RESOURCE_GOLD )
endfunction
//===========================================================================
function InitTrig_haha takes nothing returns nothing
set gg_trg_haha = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_haha, 2 )
call TriggerAddAction( gg_trg_haha, function Trig_haha_Actions )
endfunction
//===========================================================================
function InitCustomTriggers takes nothing returns nothing
call InitTrig_newtrig( )
call InitTrig_haha( )
endfunction
When you save the map, it automatically ADDS the two InitTrig function from my two triggers and calls it in the InitCustomTriggers function which in turn
was called from the main function which was called when the map started.
So that's the magic behind InitTrig functions which also explains why WE demands a InitTrig in every trigger block that you write.
To sum up everything so far.
- "Trigger blocks" that you create in the map through the trigger editor is actually only a small portion of JASS.
- the Map's code is complete with your JASS for triggers and the maps complete code
So, you learn that the building blocks of your maps aren't triggers, it's FUNCTIONS. Everything about triggers - the actions, and even the conditions are all just functions.
Based on what I know, I don't think there is a tool that allows you to edit the map scripts besides the triggers, but having this sort of fundamental knowledge is useful.
For example, those Map Initialization triggers that we use
Some of us may have taken advantage of the this one-time fire event right at the beginning of this map to initialize values. For example, Save/Load codes. You might initialize the values of the variables by creating a trigger, making it fire with the Map Initialization event, and then add the code as the trigger action that sets up all the variables for you.
NOTE - This does NOT work when manipulating Game elements like units or players. This is strictly for manipulation of things that can be manipulated even before map has loaded. This is before the preplaced units have been placed, and before the players start playing.
Why bother creating the trigger at all, honest? The InitTrig function automatically runs when the map is being loaded, so why not just call the Initialization function from that function?
JASS:
Make sure the trigger block is titled "INITIALIZE VARS" of course. That way the map script automatically produced will call this InitTrig function.
One more note about what WE does for your triggers and how it changes it into JASS.
Have you also wondered how the InitTrig's always seem to have a global trigger variable available for use? It's not that surprising to see that WE automatically declares a global trigger variable for each trigger block that you create in the Trigger Editor.
JASS:
Note, trigger variables are handles and handles by themselves don't take up that much memory. When you use the CreateTrigger() function, the trigger is actually created and that takes up more memory.
Wrapping Up
Have fun with this knowledge, whether you knew about it or not. I myself only saw JASS for triggering until I stumbled onto this. There may not be many practical uses for this, but it's always good to know how something works.