Scripting Tutorial

Probably the most common situation faced by newbies is this:
You've played around with the AGS Editor, made a basic game and it all works fine. Now, you want to start using more advanced features by using scripting - but where to start?


The Basics

Right, we'll start off by doing something very simple - displaying a message to the player when they click the Look icon on a hotspot. (Of course, you don't actually need to use a script to do this, a simple Display Message interaction command would work just as well).

So, fire up the editor and load in a room. If you don't have one, load a room from the demo game, it'll work just as well. Add a new hotspot, and click its Interactions button. Add the "Look at hotspot" event, in the same way as you would to add a normal Display Message command. Now, change the response to "Run Script".

Click the "Edit Script" button, and the text editor should appear containing something like this:

// script for hotspot1: LOOK AT HOTSPOT     

Lines beginning with // are comments - AGS will ignore them, they are just there to help you remember what your script is doing. You can add your own comments to your script by starting the line with the // symbol.


Functions Explained

Each different command you can use in the script is called a function. The name of all the available functions is listed in the Scripting part of the manual, which also tells you how to use them.

We want to display a message to the player, so we want the Display function. Looking this up in the manual gives us the definition:

Display (string message, ...)
  Displays a message to the screen. It will be displayed in  
  the standard message box, and centred in the middle of
  the screen. (description continues...)

The key point here is the part of the first line inside the brackets. This is called the parameter list and defines what parameters you give to the function.  A parameter is a number or some text that the function uses to decide what to do.
Each parameter is listed, separated by commas. They can be one of the following:

So, we know that our Display function needs a string and an optional parameter. The function description goes on to explain that the optional parameter is used for advanced things like displaying variable values, so we can ignore it for now.

To make our script call the function we write its name, then the parameters inside brackets, and finally a semicolon. This is very important, as without the semicolon the script won't compile. Also, note that we DO NOT write the parameter type (eg. "string" or "int"). So, we can add this line to our script:

Display("Hello from the script.");   

In the script editor it will look like this:

  // script for hotspot1: LOOK AT HOTSPOT     
  Display("Hello from the script.");

Now, press Alt-F, X to exit the editor, and press Yes when it asks to save changes. Click the Save Room button on the Room menu to compile the script. If all is well the room will save, otherwise you will get an error message.

Run the game, look at the hotspot and see it display your message.


Instances

The AGS script language is now object-based. What this means is that many commands are operated on a particular thing in the game. You should not confuse object-based with room objects, they are entirely different things. There is an instance for each character in the game, each object in the room, each hotspot, and so on.

The name by which you access an instance in the script is given in the editor as the item's Script O-Name. For example, assuming our main character's script name is EGO, then his instance name will be  cEgo .

To perform a command on something, you type its Script O-Name followed by a dot, followed by the command name. When you type the dot, the AGS Editor will automatically pop up a list of the available commands:


The script editor's auto-complete

You then choose the appropriate command, and place any parameters in brackets, like we did above with the Display command. For example:

  // script for hotspot1: LOOK AT HOTSPOT     
  cEgo.AddInventory(iKey);

This will add the Key to the EGO character's inventory. If you look up AddInventory in the manual, you'll find it takes two parameters, an InventoryItem * and an optional int. The InventoryItem* means that you need to supply the Script O-Name of the inventory item; this is something you can set in the script editor.
The optional int means that there is an extra parameter which you can supply if you want to, but you don't have to. In this case it allows you to specify where in the character's inventory list the new item should be added, but we're not concerned with that right now.

As well as all the individual character instances such as cEgo, there is a special instance called player. This always corresponds to the current player character, so if you just want to perform a command on the player character (especially useful in games where the player can control different characters) then you can use the player instance to do so.


Command Sequences

What we've done so far has been fairly pointless, since it could have been done in the interaction editor. The main power of the script lies in its ability to process a sequence of function calls.

For example, suppose we want the player to be given a pink poster when they look at the hotspot, as well as displaying the message. Assuming we have inventory item 2 set up to be the poster with the Script O-Name of iPoster (see the manual for how to do this), the script enables us to easily do both.
Our final script will look like this:

  // script for hotspot1: LOOK AT HOTSPOT     
  Display("Hello from the script.");
  cEgo.AddInventory(iPoster);

Note that the script system is case sensitive, so writing for example  addinventory(iposter);  will not work.

The script commands are processed from top to bottom in the order that you write them, so writing something like:

  Display("Why did the chicken cross the road?");    
  Display("Because he was bored.");    

will mean that the player gets the two messages in the order you specified.


Recap

So, did you remember these vital points:


Variables

One of the script's main advantages is its ability to use variables. A variable is an area of memory storage that contains a value, which you can check and change with your script.

To declare a variable, you write the variable type, followed by the variable name, then a semicolon. The type is either "int", "string" or "float", and the name can be anything you like - it is what you will use to refer to it later. For example,

  int my_counter;    

The variable name can only contain letters A-Z, a-z and the underscore _ character.

You need to declare a variable before you can use it, so that the compiler can spot any mistakes and knows what type of things you can store in it.

Initially, your variable will have the value 0. Optionally, you can set the starting value within the declaration, like this:

  int my_counter = 5;    

which would set it to contain the value 5 initially instead.

Variable Scope

An unfortunate side effect of the script's attempt to emulate the 'C' language is variable scope. In short, this means that you need to place your variable definitions OUTSIDE all the interaction event handlers, otherwise their values will keep getting reset.

So, to declare a variable for use by one of the room interaction scripts, you need to edit the overall room script (Room Editor, Edit Script).  

When you click that button, you will see the text editor containing all the scripts you have written for the room so far. You need to add your variable declaration to the top of the file, before any of the "function" lines. So, it should look something like:

// room text script file
int my_counter;

function hotspot1_a() {
  // script for hotspot1: LOOK AT HOTSPOT     
  Display("Hello from the script");
}

(rest of file follows)

No script commands can be placed before the first function line - just variable declarations are allowed there. 

Changing variables

You can change the value of a variable very easily in the script - simply write the variable name, the equals sign, then the new value, followed by the semicolon. So:

  my_counter = 10;    

will change the value of our variable to be 10.

You can add to and subtract from a variable using the += and -= operators. So, to add 3 to the current value of my_counter, do the following:

  my_counter += 3;    

Checking variables

Obviously we need a way to find out what value our variable contains, otherwise it's useless. We do this using conditional statements, called if statements. An if statement looks like this:

  if (my_counter == 5) {   
    my_counter = 0;
  }    

what this means is, if my_counter contains the value 5, then the script inside the { } brackets will be run (which in this case changes the value of my_counter to zero).
If my_counter does not equal 5, the script inside the brackets is skipped and execution carries on from after the } .

Note the double-equals in the if statement. In an "if" statement, you ALWAYS use the double-equals operator, which compares the two values. If you used a single equals it would set the value instead, which will yield some strange results.

The == is called an operator, because it performs an operation on the two values. The following basic operators are available:

Putting it into practice

Now let's do something useful with our variable. Suppose that we want to have different messages every time the player looks at the hotspot. So, the first time they look it will describe it, then if they look again they get a different message describing something in more detail. Our code will want to look something like this:

  // script for hotspot1: LOOK AT HOTSPOT     
  if (my_counter == 0) {
    Display("You see a bookshelf.");
  }
  if (my_counter == 1) {
    Display("Looking closer, you see a book called Hamlet.");  
  }
  if (my_counter == 2) {
    Display("There is also a book called Harry Potter.");
  }
  if (my_counter == 3) {
    Display("There is nothing else of interest on the shelf.");  
  }
  if (my_counter < 3) {
    my_counter += 1;
  }

my_counter starts off set to 0, so the first time this Look script is called, it will run the first Display command, but not the others. Then, since 0 is less than 3, it will increase my_counter by 1, and since 0+1 = 1 it now holds the value 1.
Once the player has seen all the messages (my_counter == 3), it no longer increases the value so if they click again they will keep getting the final message.

Global variables made easy

Sometimes, you may want to set a variable value that can be shared between a room script and your global script. For this purpose, 300 GlobalInts are available. You use the script functions SetGlobalInt and GetGlobalInt to access them, see their manual descriptions for more information.  


Functions that return a value

When reading function descriptions in the manual, you will notice that some of them say they return a value. For example,

IsGamePaused ()
  Returns 1 if the game is currently paused, or 0 otherwise.  

You use these much as you would use a literal value such as "9". For example, you can do:

  // Put the return value into our variable  
  my_counter = IsGamePaused();  

  // Test the return value directly
  if (IsGamePaused() == 0) {
    my_counter += 5;
  }

Be sure to remember the parenthesis ().


Common Shortcuts

The script system has a few nice shortcuts for common tasks which you will find yourself using but I haven't used so far so as not to confuse matters.

Firstly, the ++ and -- operators increase and decrease the variable by 1, respectively. So, the last part of our previous script could have been written:

  if (my_counter < 3) {     
    my_counter ++;
  }

Also, the { } brackets are only needed if you are using more than one command inside them. Since we have only one command, the "my_counter++;" line, we can remove the { } completely and just be left with:

  if (my_counter < 3)      
    my_counter ++;

However, this can lead to mistakes in scripts so I would advise always using the brackets anyway until you are very comfortable with the system.

Finally, if you want to test whether a value is zero or not, you can just write it as follows:

  if (my_counter)      
    Display("counter is non-zero");    

which is equivalent to:

  if (my_counter != 0)      
    Display("counter is non-zero");    


Summary

We've covered the basics, so that hopefully you can now write a script of your own. There are many more advanced features that the system can do, but this should be enough to get you started. 

When you're ready, feel free to proceed to the Tutorial Chapter 2 - The Patronising Text Returns which covers more advanced topics.

Enjoy AGS!

Page created 6 June 2002; updated 23 April 2005. Copyright (c) 2002-2005 Chris Jones.
Browser Based Help. Published by chm2web software.
1