Back to Mechstorm.

Mechstorm's Complete Map Making Tutorial or MCM for Short. Covering Mechwarrior4, Mechwarrior4:BK and Mechwarrior4:Mercs. If you have any questions feel free to drop by our Mechstorm Editor/Scripting help Forum after you have registered on our forums.

Back to MCM Menu

Updated Jan 23 2005

ABL scripts explained.

This is the hardest chapter to write because I personally do not know everything about abl scripting. Most people do consider me the expert but to be honest I merely get by with my scripts. All I can do is guide you through the basics. I have avoided writing a scripting tutorial until now because I know there are holes in my knowledge. This is also the reason why I will be maintaining this tutorial and updating it. At this point I should thank Von and Paladlin for helping me learn the abl scripting in the first place. You may not know this but these two guys put in a lot of time with Mechstorm to help us figure it out. Remeber this as you read through this chapter. This will be a long chapter :)

Step 1: File formats and common rules.

Lets start by showing what an empty script looks like, we will include all the basic elements that must exist in all scripts but none of the code that makes it do the interesting stuff. This is stuff you need to know and once learnt you will be able to identify the code that actually does the work from the formating code abl requires. I'll start by making a blank script called myscript.

The following script has everything every script must have in order to work but in itself does nothing. If your scripts are missing any part of this, then it won't work.

Here is the empty script. I'll explain what sections are later in this part of the tutorial.

fsm myscript: integer;

const
#include_ <content\ABLScripts\mwconst.abi>

type
#include_ <content\ABLScripts\mwtype.abi>

var

function init;
code
endfunction;

state startState;
code
endstate;

state deadState;
code
orderDie;
endstate;

endfsm.

Step 2: FSM and EndFSM

The two lines we are concerned about here are

fsm myscript: integer;

and

endfsm.

The first line has one special requirement you must remember. The word between fsm and the : interger; is a name for your script, something like mybots, or myturrets will do here. This is what mw4 will use to identify your script with and as such it must not be the same name you used in other scripts for the same map. So put something original in there. The line is ended with a semi-colon. ; is a semi-colon.

You will notice several lines end this way throughout this chapter, a missing semi colon is normally the cause of unexplained errors so remember to check you have placed them correctly.

"If" commands do not need the semi colon at the end of the line but the endif command does. So you need to be aware that even this rule has exceptions. You may also notice the Code command has not semi colon either.

The second line says Endfsm.

Notice the full stop at the end of the command endfsm, this is also important. Endfsm takes no extra arguments. It is simply used as written above in all cases so it's easy to remember.

The two lines mentioned here mark the beginning and end of a script.

Step 3:Const & Types

The lines which look like these ones below are from the script above and are required items. They must exist in all your scripts and are never edited. So simply paste them in and forget about them.

const
#include_ <content\ABLScripts\mwconst.abi>

type
#include_ <content\ABLScripts\mwtype.abi>

Both read in the contents of other scripts found in your mechwarrior folder that allow various commands to work. You can even add your own by adding an include line to point to your own abi file but thats for as later section and is considered and advanced topic.

Step 4: Var

Vars are a scripts meet and two veg, the very heart of most scripts. If you do not understand what a Variable or Var is then you will always be hopeless at 99% of all scripted programing languages.

So what I am about describe applies equally well to so many programing languages that learning them now may well help you when you try and make mods for other games.

Vars must be declared near the top of your script, this means you have to tell Mechwarrior a word in your script is a Var and tell it what type of Var it is. I'll cover var types further down, dont worry about those just yet. All vars do the same job, its just some companies like to give them certain roles such as storing numbers or storing characters. None of which is important to you right now.

Now a Var is used to store information, imagine if you will that you want your script to remember a time of day. So you think of a good name, lets call our var timeofday, we could call it bigfatwobblyones because the name does not matter as long as its an original name.

Now we use our new Var in our script and in the morning we ask what time it is and put the answer in the timeofday var for safe storage. Later at dinner time was ask is it the same time as it was in the morning (computers are stupid, they ask these questions) so we check the current time against the timeofday var and find its not the same time. So we put the current time in to the timeofday var and overwrite the old timeofday information it used to keep safe for us. So the new timeofday information remains accurate.

The reason why vars are so useful is because the name never changes but the information the name keeps safe for us can be changed as many times as we like. Can you imagine asking what time it is when you have to list every possibly time it could be instead of just updating one var to do the same job ?

EG without vars you would have to do this.

is noon the same as 1am

is noon the same as 2am

is noon the same as 3am

Once you hit 12 you still have to do the other 12 hours of the day. Its long winded and painful. Your scripts would be huge without vars. So Vars are your best friends.

A good use for Vars in Mechwarrior is to store data your going to use lot or want to change later. Vars can hold characters or numbers and you can add numbers together or create new sentences out of odd words. Very clear stuff.

For example remember your algibra lessons at school ?

Well Vars can be used exactly the same way.

Var = Var + 1

IF var was 3 before then it would 4 after that line was executed.

Lets look at some examples of Mechwarrior 4 Var's.

Now it is important for you to learn the roles Microsoft have assigned to different vars. So pay attention :)

Static interger examples

static integer Team1;
static integer Team2;
static integer Team1_Timer;
static integer Team2_Timer;
static integer general_Timer;
static integer Radius;

Static integer vars tend to hold numbers mostly

Static ObjectID examples

static ObjectID Nav_center;
static ObjectID Team1Hill;
static ObjectID Team2Hill;
static ObjectID Team1_Dropzone;
static ObjectID Team2_Dropzone;

ObjectID vars hold names of items you place in the map editor. EG Dropzone1, Bigbuilding002 etc etc.

Static Boolean Examples

static boolean Team1_In;
static boolean Team2_In;

Boolean Vars are used to store no or yes, 0 or 1. 0 meaning no, 1 meaning yeas

Static Real Examples

static real minDelay;
static real maxDelay;

Real vars are usually vars that hold numbers containing a decimal point. Or floating integers if your a programer.

Enternal Interger Example

eternal integer Playermech;

External vars are declared in abi files that your script must link to in order to make use of a vast array of commands, not just Playermech. Playermech is used in single player to always refer to the player him self.

More Detailed explaination of Mechwarrior 4 Vars

Typical use of Static interger vars would seem to be for declaring names you will be using in your scripts. This doesn't match the information for the integer but I have never seen the devteam use the char var to do it either. So all my scripts use the integer var for declaring names and these seem to work.

ObjectID vars refer to objects on your map. Typical use for these is to name buidlings and mechs that actually exist on your map for use in your script. So if you're talking about a real object, you always refer to it using ObjectID. Later in the chapter you will see ObjectID being referred to again and again. The information about the var will be valid for those parts of this tutorial too. Just remember all ObjectID's refer to real objects in all cases.

Boolean vars are great, we use these as switches and for part of the logical operation (don't you love it when I use those words) of your scripts. Boolean may seem like some mysterious programming term to most of you but for us it simply means true or false. You get to choose what it means in the functions part of your script. So if you have not given it a true or false meaning you will get a error. So just remember, until you tell the script what the boolean var you entered means, even the script doesn't know. You see its a simple switch, like on or off, true or false. It can only ever have one of two meanings and we use the meaning you have given it for example, to check to see if Mr Diashi has arrived at location X or if Location X still exists. If these are true, we can change the meaning of the boolean var to something else or have our script only kill your best mate if under conditions you have defined. Like a crossroads. Go left if you're running a race, change the sign post to right if you're not. Then the race leaders will be going the wrong way. So learn to use this var as it's very handy indeed. Remember, it only means true or false, it won't change sign posts on its own or blow up a mech, other commands do that if the value of this boolean is correct. You say if it is in the script.

Real var's tend to be used to call var's the devteam use all the time in their scripts, probably because they are written in to the mw4 exe and cannot be changed. The typical value of any number contained in a real var will have a decimal point in it. Remember your maths lesson from schools. moving that nasty point back or forth to factors of ten. Confusing for most of us but actually very simple. The map editor itself uses floating point numbers for fog setting to get values less than 1. EG 0.5 is a light mist. 0.9 is a dense fog. Same thing here. The vars name may have a special meaning, like how fast can a mech fire but the number it contains will contain a decimal point. EG mindelay = 0.5, it is the 0.5 that makes this a real var and not an integer var. The very existence of the decimal point is enough to do that. So just think of it as a number with a decimal point in it and let the real vars name tell you what it does for the script. The devteam have used some nice descriptive names to help you here so it really is not that bad.

Here is the complete list of available var's and their meanings taken from the devteams abl_orders doc. Some of this only started working properly in MW4 Mercs. The Camera Var is a good example.

integer a basic integer, whole numbers
real a basic floating point number
boolean a boolean that can be true or false
char a single character
ObjectID a reference to an object in the world
LocPoint a location in the world (3d point)
TimerID a reference to a timer in the mission 0-31 only
CameraID a reference to a camera
PlayerID a reference to a player

Step 5: Functions

Whilst Var's tell the script about the names you intend to use in your scripts, the function section initialises them so the script can actually use them. A phonebook matches a persons name with a telephone number. The function part does the same thing but it matches your var names with names the game will understand. Here are some examples.

These are vars from the one of the previous steps in this tutorial. Lets match up the vars with the lines they require in your functions section.

Vars Function entry required for var
static integer Team1; Team1 = TeamObjectID(1);
static integer Radius; radius = 200;
static integer Team1_Timer; Team1_Timer = gti_timer_1;
static boolean Team1_In; Team1_In = false;
static ObjectID Nav_center; Nav_Center = ena_Nav_center;

TeamObjectID(1); , gti_timer_1 are both specially reserved names for items the game uses. The game knows exactly what these are but it doesn't know what your names mean until you tell it in the functions section. The boolean var contain a false value in functions as you can see and the interger for radius contains a value I made up myself. In this case it's the radius around the hill in TKO2H's where points can be scored. Thanks to that line, I just use the word radius everywhere instead of 200, this means if I edit the radius value in the functions section then all references to radius will also be changed with no need for me to go through the entire script to do it. That's another good use for functions and vars you may want to consider using. A typical functions section would look like this.

function init;
code
// Changeable Vars
SetCustomBucketName("Team King of 2 Hills");
radius = 200; // just change this to change the detection radius of all zones.
AddCustomBucketParameter(Bucket_FRIENDLY_KILLS,-500);
AddCustomBucketParameter(Bucket_SUICIDES,-500);
AddCustomBucketParameter(Bucket_ENEMY_DAMAGE_INFLICT, 1);
AddCustomBucketParameter(Bucket_ENEMY_KILLS, 50);
AddCustomBucketParameter(Bucket_FRIENDLY_DAMAGE_INFLICT,-1);

// Leave these Alone
Settimer(gti_timer_1,0);
Settimer(gti_timer_2,0);
Team1 = TeamObjectID(1);
Team2 = TeamObjectID(2);
Max_Score_Holder = 50;

Team1_Timer = gti_timer_1;
Team2_Timer = gti_timer_2;

Team1_In = false;
Team2_In = false;

Team1hill = ena_Team_1_Hill;
Team2hill = ena_Team_2_Hill;
Team1_Dropzone = ena_Team1_Dropzone;
Team2_Dropzone = ena_Team2_Dropzone;
Nav_Center = ena_Nav_center;

SetFlagsEnabled(FLAGS_HIDE);
TrackBucket(Bucket_CUSTOM,0,true);
AddStandardBuckets;

endfunction;

You can see a lot of stuff I have not explained in this, you can also see how you setup scoring using the devteams score buckets. We will deal with this in its own section later. For now though, cross reference the steps above with this, you will start to see a pattern and start to learn how var's and the functions operate.

Functions differ in that you can assign 1 var to a mini program and run that mini program just by typing the vars name on its own anywhere in your script.

Also like FSM, the function has start and end commands that you must use.

function NAME;

And

Endfunction;

Where name is a name of your choice, though function init should be used to setup all the basic stuff used by your script.

Also note that every single line inside your function ends with a semi colon eg ; except the command code which never ever has a semi colon after it. You will see code mentioned in the following sections but basically it is always used as it is, it never contains an argument. It is also the first command you write after your function name; and state name; .States will be covered later.

// = Comments

Another thing we see above which has not been explained yet is the lines starting with //. These are what programmers call comments. If you put // before any line, then that line is ignored when the script is run. You can use a comment to remove a line that contains an error without deleting the line. Please put instructions inside your scripts for other programmers to read or simply use it to label the script to make things easier to find for your own benefit.

Step 6: States

States are the places that hold the main parts of your script, most of the business end of scripts happens in states. They are therefore vital to scripts if you wish to have your scripts do anything at all.

Three states are required by a script, State Startstate, Your own state and State deadstate. The startstate is executed once and then the script moves to other states. The dead state is only used when the object the script is attached to is dead or nonfuctional. It exists in gametype scripts which cannot die for one reason. You can stop the script executing using the command orderdie in the deadstate. This is the only place you should use the command orderdie.

Your own state is where you put your own code to run the bot or gametype the way you want to run it. You can have several states all linked using the trans command if you wanted too.

All states use the same layout, the name of the state may change but the same commands are required. For example.

state startState;
code
endstate;

Notice the semicolons again at the end of state startstate and endstate. Also notice that like fsm and functions, states are also started with a command, in this case the command state and ended with a command, in this case endstate. You should be getting some idea of how to create your scripts by now. So it's time to move on to the really neat stuff.