Scripting Basics

From SA-MP

Jump to: navigation, search

Contents

Starting out

Below is an example of possibly the most basic script you can write:

#include <a_samp>
 
main()
{
	print("hello");
	return 1;
}

The various aspects will be covered in turn but we'll start by looking at the first line.

Include

#include <a_samp>

This basically loads the code from pawno/includes/a_samp.inc into your script, so everything it has you can use. One of the things it has is:

#include <core>
#include <float>
#include <string>
#include <file>
#include <time>
#include <datagram>
#include <a_players>
#include <a_vehicles>
#include <a_objects>
#include <a_sampdb>

This includes all the other files in that directory so by adding that one line you have access to all the functions in SA:MP (more on functions later).

Calls

The next part has two sides of a function call. main() is a function which you write the code for and is called from elsewhere, print(string[]) is a function with the code elsewhere which you call. Currently all this will do is load, print a string (i.e. print "hello" (without the ""s)) to the server console and end. The:

return 1;

Passes a value (1) back to the place which called main to tell it what happened (the exact value passed here doesn't matter but in other places it does). You now have your first (very basic) script. If you select file->new in pawno it will give you a much bigger start point will all the callbacks in (see below), including main (which isn't technically a callback but acts like one).

Statements

The print and return lines have ';' (a semi colon) on them, this just denotes the end of a statement (a statement is a group of one or more functions and operators which together do something, similar to a sentence in common language). Most people put separate statements on separate lines but this is not required, it just makes things clearer, the following is equally valid:

main() { print("hello"); return 1; }

The {}s (braces (curly brackets), not parenthesis (brackets)) enclose a group of statements which should be executed together (like a paragraph in common language). If you did:

main() print("hello"); return 1;

You would get an error because now the "return 1;" statement is not grouped so is not part of main. Braces group a set of statements into a single statement (called a compound statement) and functions have a single statement with them. Without the braces print and return are entirely separate statements, so there's two or them so, as a function can only have a single statement, the second is not in a function, which code can't be.

Functions

A function is basically a chunk of code which does something and can be told to do this thing from somewhere else. It can also pass data about what it did back to the place which told it to run (the place which "called" it).

Calling

print("hello");

As described in Starting out, this calls the function called "print" (defined in a_samp.inc, which is why you need to include it) and tells it to display something in the server console (the word hello).

A function consists of the function name (e.g. print), which tells the system which chunk of code you want to call, and a parameter list, enclosed in ()s after the function name, which pass additional data to the function to help it run. If you didn't have parameters you would need millions of functions:

printa();
printaa();
printab();
printac();
// etc

Functions can have as many parameters as you like, from 0 up (there may be an upper limit but it's at least 128):

printf("hello", 1, 2, 3, 4, 5, 6);

Don't worry about what that function does for now, just that it has 7 parameters, each separated by a comma.

Defining

As well as being able to call existing functions you can also write and call your own:

#include <a_samp>
 
main()
{
	return MyFunction();
}
 
MyFunction()
{
	print("hello");
	return 1;
}

This just does exactly the same as the original code but is arranged differently. When main() is called when the mode is started (it's called automatically) it calls the new custom function called MyFunction(). This function prints the message in the server console then returns the number 1 to main(). main() takes the returned value (1) and then returns it to the server itself (i.e. the place which called main in the first place). As "return MyFunction();" is a single statement you could do:

#include <a_samp>
 
main() return MyFunction();
 
MyFunction()
{
	print("hello");
	return 1;
}

But most people don't for clarity. You can also not use the MyFunction return value at all and do:

#include <a_samp>
 
main()
{
	MyFunction();
	return 1;
}
 
MyFunction()
{
	print("hello");
	return 1;
}

Parameters

Parameters are a type of variable which you don't need to declare as they come from the place which called the function:

#include <a_samp>
 
main()
{
	return MyFunction("hello");
}
 
MyFunction(string[])
{
	print(string);
	return 1;
}

This code still does the same thing but we're now telling MyFunction() what to display. The call passes the string "hello" to the function where it is stored in a variable called string (the [] means it's an array as explained later). The print function is the called, passing the contents of the string variable, we know it's a variable because it doesn't have the "" any more.

Variables

A variable is basically a bit of memory, it's where data is stored and can be changed and read as required. Variables are one or more cells, a cell is 32 bits (4 bytes) big and by default signed so they can store from -2147483648 to 2147483647 (although -2147483648 is poorly defined in PAWN and gives odd results if displayed). A variable made from more than one cell is called an array, strings are a special type of array where each cell holds a character of the string (or 4 characters in packed strings, but they're not covered here).

Declaration

To create a new variable you have to declare it:

new
	myVariable;

This tells the system to create a new variable called myVariable, the initial value of this variable will be 0.

Setting

new
	myVariable = 7;

This declares a new variable and sets it's initial value to 7, so printing the variable now will give 7. To display a variable which isn't a string we need to go back to the printf() function mentioned earlier and do:

new
	myVariable = 7;
printf("%d", myVariable);

Again, for now all you need to know is that this will print the value of myVariable (i.e. 7 at this point) to the server.

new
	myVariable = 7;
printf("%d", myVariable);
myVariable = 8;
printf("%d", myVariable);

That code will print 7, change the value of the variable to 8 and display the new value in the server window too. There are many other things you can do to variables, some are listed below, most are listed elsewhere:

myVariable = myVariable + 4;

Sets the value of myVariable to the old value of myVariable plus 4, i.e. increase it's value by 4. This can also be written as:

myVariable += 4;

Which just means "increase myVariable by 4".

myVariable -= 4;

That will decrease the value by 4.

myVariable *= 4;

That will multiply the value by 4.

myVariable /= 4;

That will divide the value by 4.

Arrays

Declaration

An array is a variable in which you can store multiple pieces of data at once and access them dynamically. An array is declared to a set size at compile time so you need to know how many pieces of data you need to store in advance, a good example of this is the very common MAX_PLAYERS array, this will have one slot for every possibly connected player, so you know data for one player will not interfere with data for another player (more on defines later).

new
	myArray[5];

That code will declare an array 5 slots big, so you can store 5 pieces of normal data at once in that single what you can't do is something like the following:

new
	myVariable = 5,
	myArray[myVariable];

That code looks like it would create an array the size of whatever number is stored in myVariable (here 5 but it could be anything), but you can't do this. In PAWN the memory for variables is assigned when you compile your code, this means arrays are always one size, you can't set the size to anything you like whenever you like.

Accessing

To set a value in an array you need to say which part of the array you want to store the data in, this CAN be done with another variable:

new
	myArray[5];
myArray[2] = 7;

This will declare an array with 5 slots and give the THIRD slot a value of 7, given that variables always start as 0 this will make the values in the array:

0, 0, 7, 0, 0

Why is it not:

0, 7, 0, 0, 0

you're wondering? It's because counting actually starts from the number 0, not 1. Consider the following:

2, 4, 6, 8

If you go through the list then after the number 2 you have already had one number (the 2), this means that if you are counting the numbers by the time you reach the number 4 you are already at one, you're not at one when you reach the 2, you're at zero. Thus the 2 is at position zero and the 4 is at position one, and thus it follows that the 6 is at position two, which is where the 7 in the first example above is. If we label the slots for the first example we get:

0 1 2 3 4
0 0 7 0 0

There are five slots but as you can see, and this is very important, THERE IS NO SLOT FIVE, doing the following could crash your server:

new
	myArray[5];
myArray[5] = 7;

As mentioned above the array index (the index is the slot to which you're writing) can be anything, a number, a variable, or even a function which returns a value.

new
	myArray[5],
	myIndex = 2;
myArray[myIndex] = 7;

Once you have an array and an index you can use that block exactly as if it were any other variable:

myArray[2] = myArray[2] + 1;
myArray[2] += 1;
myArray[2]++;

Example

As mentioned above a common type of array is the MAX_PLAYERS array. MAX_PLAYERS is not a variable, it's a define which is explained later, but for now accept that it is a constant number equal to the max number of players a server can hold (this by default is 200, even if you change the number in your server.cfg file). The following code uses normal variables to hold data for 4 players and do something with those players in a function (for simplicity's sake assume MAX_PLAYERS is 4 for now):

new
	gPlayer0,
	gPlayer1,
	gPlayer2,
	gPlayer3;
 
SetPlayerValue(playerid, value)
{
	if (playerid == 0)
	{
		gPlayer0 = value;
	}
	else if (playerid == 1)
	{
		gPlayer1 = value;
	}
	else if (playerid == 2)
	{
		gPlayer2 = value;
	}
	else if (playerid == 3)
	{
		gPlayer3 = value;
	}
}

See the section on control structures for more information on what's going on there, also note this could be done as a switch but that's less clear for the example and effectively the same code anyway.

Now compare that to using an array with one slot per player, bearing in mind an array index can be any value:

new
	gPlayers[MAX_PLAYERS];
 
SetPlayerValue(playerid, value)
{
	gPlayers[playerid] = value;
}

That will create a global array (see section on scope) with one slot for every player, then the function will assign whatever is in the variable "value" to the slot for the player specified. The firs example was large with only four players, using 4 lines per player, that's 800 lines for 200 players (if can be less but it's still a lot), the second version is a single line no matter how many players you have.

Strings

Basic use

A string is a special type of array, one which is used to hold multiple characters to create a word or sentence or other human readable text. A character is one byte big (although there are extended sets where a character is multiple bytes but these are not well defined in SA:MP) and by default a character takes up one cell (one normal variable or one array slot). Characters are encoded in a system called ASCII, the character "A" is represented by the number 65, telling the system to display a number will give 65, telling the system to display a character will give a capital a. Obviously is a single character takes up a single cell multiple characters (i.e. text) will take up multiple cells, collections of cells, as just explained, are called arrays.

Strings in PAWN (and other languages) are what's called "NULL terminated", this means that when 0 is reached, the string ends. This is not the same as the character "0", represented by the number 48, this is the NULL character, represented by the number 0. This means that you can have a string array 20 cells large but only have a string 3 characters long if the fourth character is the NULL character, signalling the end of the string. You can not however have a string 20 characters long as the NULL character MUST be in the string, so in a 20 cell array you can have a 19 character string and a NULL termination character.

new
	myString[16] = "hello";

That code declares a new string with enough space for a 15 character string and sets it initially to the 5 character string "hello", the double quotes around the text indicate that it's a string. Internally the array will look like:

104 101 108 108 111 0 x x x x x x x x x x

The "x"s mean anything, in this example they will all be 0 but as they're after the null character is doesn't matter what they are, they won't affect the string.

Strings can be manipulated like normal arrays, for example:

new
	myString[16] = "hello";
myString[1] = 97;

Will change the character in slot 1 to the character represented by the number 97 (a lower case "a"), resulting in the string reading "hallo". This can be written much more readably and easy to edit as:

new
	myString[16] = "hello";
myString[1] = 'a';

The single quotes around the "a" mean it's a character, not a string, characters don't need to be NULL terminated as they're only ever one cell long, they can also be used interchangeably with numbers if you know what they represent.

new
	myString[16] = "hello";
myString[1] = '\0';

'\0' is two characters, however the \ is a special character which modifies the next character, \0 means NULL, that code is the same as doing:

new
	myString[16] = "hello";
myString[1] = 0;

But is NOT the same as doing:

new
	myString[16] = "hello";
myString[1] = '0';

The first and second versions will result in the string being simply:

h

The third version will result in the string being:

h0llo

Escape character

As briefly mentioned a backslash is a special character, doing:

'\'

or:

"\"

Will give a compiler error because the \ modifies the next character so those constants will not be ended correctly, this can be used to create characters which can't normally be created, for example:


new
	myString[4] = "\"";

That code will create a string consisting of only a double quote, normally a double quote signals the end of a written string but the backslash makes the double quote immediately after it a part of the string, and the double quote after that ends the string instead. Other special characters are:

\0 NULL character Ends a string.
\n Line feed use \n for a new line in Linux (also works in Windows)
\r Carriage return Use \r\n for a new line in Windows
\\ Backslash Used to put an actual backslash in a string
\' Single quote Used to use an actual single quote as a character in single quotes (use: '\'')
\" Double quotes Used to put an actual double quote in a string
\xNNN; Hex number Used to set the character to the character represented by the hex number specified in place on NNN
\NNN; Number Used to set the character to the character represented by the number specified in place of NNN (see \0)

There are others but those are the main ones.

Tags

Scope

Variable types

Variables are places you can use to store data. In PAWN the variable names are case sensitive, so a variable named "lolhax" is not the same as "LOLHAX" or "lOLhAx" for that matter; variable names must also start with a letter of the alphabet (A-Z)

Integer

This is the default variable type, it is used for storing whole numbers. You must not use numbers with decimal points as they are not whole numbers even if the numbers after the decimal point are all "0" (eg. 5.00) it is still not technically a whole number.

Example

new integer = 1337; // Declares a new integer variable named "integer" and sets it to "1337".
new integer; // Declares a new integer named "integer" with an automatic value of "0".

Possible Usage

if(integer == 1337) { /* Do
    something */ }

Float

Float variables are used to hold decimal places. These are named "floating point" numbers. While declaring a new float variable, prefix the variable name with "Float:".

Example

new Float:fMyFloat; // Declares an empty new float named "fMyFloat".
new Float:fMyFloat = 2.0; // Declares the new float "fMyFloat" and sets it to "2.0".

Possible Usage

SetPlayerPos(playerid, fMyFloat, 2.0, 1400.0);

String

Strings are storage places for characters (letters and/or symbols). Strings must be placed into an array, this is so each cell can hold a letter - you must specify an extra cell for the string identifier "0".

Examples

new szMyString[7] = "String"; // 7 is the amount of cells needed to hold the each letter in the string as well as the string identifier.
new szMyString[7];
szMyString[0] = 'S';
szMyString[1] = 't';
szMyString[2] = 'r';
szMyString[3] = 'i';
szMyString[4] = 'n';
szMyString[5] = 'g';
szMyString[6] = 0;

Usual Usage

new szMyString[128];

Possible Usage

SendClientMessage(playerid, 0xFFFFFFAA, szMyString);

Boolean

Used for true or false results. True is equal to 1 and false is equal to 0. New booleans default to false.

Examples

new bool:boolname;

Possible Usage

if(boolname == true) { /* Do something */ }

Enumerations

In a typeless language, we might assign a different purpose to some array elements than to other elements in the same array. PAWN supports enumerated constants with an extension that allows it to mimic some functionality that other languages implement with structures or records.

Examples

enum player_enum
{
  name[40],
  Float:health,
  money
}

Possible Usage

new player[player_enum];
  GetPlayerName(playerid, player[name],sizeof(player[name]);
  GetPlayerHealth(playerid, player[health]);
  player[money] = GetPlayerMoney(playerid);

So, we have a single structured variable, containing a string, a float and an integer. We could also add sub-arrays to it, for example to store the player's weapons and ammo. Usually we have more than one player, so we need an array (read below for information about arrays):

new player[MAX_PLAYERS][player_enum];
  for (new i=0; i<MAX_PLAYERS; i++) {
    GetPlayerName(i, player[i][name],sizeof(player[i][name]);
    GetPlayerHealth(i, player[i][health]);
    player[i][money] = GetPlayerMoney(i);
  }

Now we have all player's info contained in one array.

Array

Arrays are large storage places for data to be stored - they are like virtual tables. An array can contain integer, float, or boolean data. When you access your array, you need to start at cell 0 (NOT cell 1), and count up to one less than the array's size.

One-dimensional array

A one-dimensional array is a single row split into the specified amount of cells.

new onedimensionalarray[CELLS];

Example

new onedimensionarray[5] = {4, 6, 7, 9, 2}; // The "5" contained in the [] states how many cells there are for data to be stored in. 
onedimensionarray[0] = 4; // Cell 0 contains the integer '4'. 
onedimensionarray[4] = 2; // Cell 4 contains the integer '2'. 
// Cell 5 does not exist, because the computer counts starting at 0 instead of 1.

Possible Use

new randomnumber = random(sizeof(onedimensionalarray)); // Gets random number for cell.
printf("Random number is: %d", onedimensionalarray[random]); // Uses random number to select a cell.

Notes About Confusion

One-Dimensional arrays can easily be confused with strings. In fact, strings are a special kind of one-dimensional arrays, with some restrictions like a trailing 0, or a special way to write them using "quotes". Also, when using enumerations, you get very similar looking results, as they all use square braces.

Yet it is important you are able to differ between all of them. Their internal meaning is totally different, also confusing the terms 'array' and 'string' can lead to totally different opinions, as arrays are usually 'groups of values' and strings represent text and nothing else. Enums on the other hand only use an array-like notation, but instead of numeric indices you have self-defined keywors, and not all fields in an enum-structure need to be of the same type.

Two-dimensional array

Two dimensional array allows you to have many columns and rows. When you assign them, you must fill in all rows and columns - you can't specify 5 rows in the brackets, and only assign 3 of them.

new twodimensionalarray[ROWS][COLLUMNS];

Example

new Float:twodimensionarray[4][3] = {
{3.0, 4.5, 5.76}, // Row 0
{10.85, 76.34, 23.54}, // Row 1
{2.32, 10.23, 80.2}, // Row 2
{6.6666, 45.3, 32.64} // Row 3 (notice how there isn't a comma at the end of these brackets)
};

Possible Usage

SetPlayerPos(playerid, twodimensionalarray[2][2], twodimensionalarray[3][1], twodimensionalarray[2][0]);

Three-dimensional array - Two-dimensional array string

new treedimensionalarray[ROWS][COLUMNS][Z];

Two-dimensional array string

new twodimensionalarraystring[ROWS][COLUMNS][256]; //for a string with a max length of 255, excluding NULL byte

Control Structures

Main article: Control Structures

Control structures determine program flow. They can execute code or not based on the contents of variables, the returns of functions and other things. They can also do things repeatedly if need be.

This article is a stub. You can help SA-MP by expanding it.

Personal tools
In other languages