Creation/Dev/GScript/GScript for Dummies

From Graal Bible

S dummies.png

Preface

Introduction

New Engine GScript for Dummies is a guide designed to aid the learning of the new scripting engine, frequently dubbed 'gscript2'. This guide will explain the basics, such as functions, variables and some Gscript-specific concepts that you will need to know in order to get scripting in no time. The guide is indexed at the top of the page, and by clicking one of the index links, you will be taken to the appropriate section. If you haven't really a clue where to start, then you're probably best reading through the entire guide.

Who is this for?

This is for absolutely anyone who is interested in learning in Gscript. Having some previous knowledge of scripting would be beneficial, but isn't required.

What should I do if I have a problem or a question not covered here?

You can, of course, post your problem on the GraalOnline Forums in the NPC Scripting section. Similarly, you can also contact a member of the Global Scripting Team via Forum PM if you think that you require more direct assistance, although usually forum regulars will be happy to help.

Welcome to GScript

GScript is the scripting language that powers most of the dynamic content provided by GraalOnline. The scripting language is a very useful tool, since it enables you to create a very wide variety of systems, including automated baddies, scripted systems, GUIs.

Glossary of Terms

Through this guide, a number of terms are likely to be used. In case you are not sure exactly what any of the terms mean, you can look them up here!

  • Variable: This is a special type of object that stores data. The data might be a string, an integer, a float, or an array.
  • String: This is a type of data that can be stored in a variable. A string is a collection of letters, numbers and symbols. For example, if you are interested in storing a sentence in a variable, a string is probably your best bet.
  • Integer: This is a type of data that can be stored in a variable. An integer is simply a round number. No decimal places. Positive or negative, it's just a round number.
  • Float: This is a type of data that can be stored in a variable. A float is a number that is not an integer, that may contain decimal places.
  • Function: This is a block of code. A function is a defined routine of instructions that can be ran at any time in a script.
  • Predefined Function: This is a function that is already available in the scripting engine. Such functions are internal, that usually allow mathematical and other variable operations, manipulation of players and such like. You do not need to define a predefined function yourself, since it is already there for you to use!
  • Event Functions: These are functions that are called by the scripting engine automatically based on events happening. For example, one function may be called when a player touches the NPC, and another one might be called when a player enters the level. Note that these event functions are only called if you have written the instructions for them yourself. This will be explained in the Functions section.

Using GScript

So, hopefully by now you have a general idea of what GScript is. Now, it's time to fill you in on how to use GScript. With the help of this guide, hopefully you'll be creating scripts of your own in no time!

Basic concepts

It is important to remember a couple of very basic, but very important concepts when using GScript.

  • All statements (that is, function calls, writing to variables) must end in a semicolon (that's a ;). This simply tells the engine that the current statement has finished. You must remember to include it, or the engine will throw errors at you when it does not realise that you have finished a statement before it moves onto the next one.

Functions

A function, like mentioned in the Glossary of Terms, is a defined block of instructions. Practically everything you do in GScript will rely on functions. First, let's look at how you can define a function.

Defining a function

The syntax for defining a function is, in fact, very simple. Let's look at an example.

function myFunction()
{
  // code
}

The first thing to identify is the 'function' keyword. This tells the scripting engine that you're going to define a function. This is absolutely necessary in defining functions of any kind yourself.

Second, you'll notice a name - 'myFunction'. This is the bit where you specify the name of the function that you're defining. This can be anything, providing that it doesn't contain strange symbols (usually an underscore '_' is the best suited symbol to split up function names with, since other symbols can cause errors).

Thirdly, you'll see (). This is a convention that is later used for parameters, but for now, that's not important. Just stick () on the end of your name for now.

Finally, you'll see { and }. These are braces, and define exactly what the function contains. Anything inside the braces is code that is specific to the function. If it's inside the braces for that function, it'll run when you call that function. Very simple.

Function scopes

A fairly important concept is the idea of scopes. As demonstrated before, anything inside the { and } of a function means that it's a part of the function. Now, imagine that the entire script is like a hallway, and behind every door, is a function. When you walk into a room and close the door behind you, you are in a fairly closed space. This is true of functions.

Some types of variable, when set inside a function, are placed in the function's 'local' scope. This simply means that the variable is available for use inside the function, but not outside of the function. The 'global' scope is where other types of variable are stored, for example, variables that need to be accessible in all functions. This will be explained further in the variables section.

Calling a function

Now you've created your function, it's there to be used. Anywhere inside your script, you can call this function using the following method:

myFunction();

Note that the 'function' keyword is not present because we are not defining a function, we are just calling one. Now, the moment the scripting engine hits a function call, any code that you put inside of your function will run. Let's use the following example:

function myFunction()
{
  player.chat = "Hello!";
}

This is a very basic function that just sets the player's chat text. Let's call the function.

myFunction();

Suddenly, the player's chat will be set to "Hello!". By calling the function, you've told the engine to run the code inside of that function - in this case, setting the player's chat.

Return values

A function execution can return a value to where the function was called. This is how a lot of Graal's built-in functions work: by returning the value.

Take the following example, which will return the value of timevar2 (a built-in variable which counts how many seconds it has been since 1st January 1970):

function getTime()
{
  return timevar2;
}

When you call the function, like so:

this.time = getTime();

... then this.time will be set to the value of timevar2.

It is very important to remember that the return function immediately ends the function's execution. Therefore:

function foo()
{
  player.chat = "Foo";
  return;
  player.chat = "Bar";
}

player.chat = "Bar"; won't be executed because of return; being used.

Variables

Now, you've seen how functions work. The next very important part is using variables. As you have read in the glossary of terms, a variable is simply a sort of object that stores information.

Variables have three important factors: name, type and value.

Name

Every variable must have a unique name. This is how you will access the value that is stored inside of the variable whenever you want to use it.

Type

Every variable also has a type. In GScript, there is a clever little system in place for variables called 'variants'. This sounds complicated, but is in fact also very simple. It simply means that the variable's type adjusts itself in order to suit the sort of data that it contains.

For example, if you make the value of a variable "Hello!", then the variable automatically becomes a string, and simply because you assigned it a value of a string. In GScript, all string values must be enclosed in "speechmarks".

What about a number? You don't even need to use speechmarks for numbers - you just type the number! Simple, no? When you do so, the variable automatically becomes either an integer or a float type in order to suit the number that you just put in it.

Value

As already established, this is simply the information/data that the variable contains.

Why variables are useful

Variables are incredibly useful for a number of reasons. They allow you to:

  • Store a value that you plan to repeatedly use in your script. If you change the value of the variable, then the script uses the new value in every place the variable is used.
  • Keep a value saved for when you want it later. If you take the player's chat text and want to save it, then you can use a variable.
  • Manipulate a value. There are many predefined functions available in the scripting engine that will allow you to modify and use the value that is stored inside a variable; for example, mathematical operations.

Setting a variable

Setting the value of a variable is even simpler than defining a function. Let's use an example.

myVariable = "Hello!";
myVariable = 3;

Looking at this, it's easy to see the logic here.

  • First, the engine is taking the variable name - in this case, "myVariable".
  • Second, it is identifying the assignment operator (=). Simply, the engine has so far established that you want "myVariable" to equal something.
  • Finally, it is taking the value that you want to set the variable's value to, and setting it.

In our example, we initially set the variable "myVariable" to "Hello!". This turns the variable automatically into a string. However! Immediately after, we have rewritten the value of "myVariable" with the number 3. Since there are no decimal places, the variable suddenly becomes an integer.

Reading a variable

Any time you want to get a variable's value and use it, you simply write the name of the variable. This is best explained while using a Conditional Check.

Conditional Checks

For your script to even be remotely useful, you're going to have to check something somewhere. For example, if you want the script to only respond to a player saying "Foo", then you're going to have to use a conditional check.

There is another operator, called the comparison operator. It's two equals signs stuck together (==), and just instructs the engine to compare the two values. If the two values are the same, then it'll return TRUE. If they are different, it'll return FALSE.

This is simple enough. Observe the following example:

myVariable = "excellent";

We've set the variable 'myVariable' to "excellent".

myVariable == "excellent"

This time, we're checking to see if 'myVariable' equals "excellent". Since it does, this statement will evaluate to be TRUE.

myVariable == "fabulous"

Now, we're checking to see if 'myVariable' equals "fabulous". It clearly doesn't, since we set it's value to "excellent" instead. As a result, this statement returns FALSE.

Working with if () checks

Now, conditional checks alone are no good to you in a complex script. You'll need to actually use the result of your conditional checks to make a difference in what happens during the execution of the script.

To do this, you use an 'if' statement. 'if' is a very simple operator (it doesn't get complicated yet!) that simply runs one thing if the statement you give it is true, and optionally runs another thing if it isn't.

Since using examples so far has been the common way, let's see one here. We'll even include a bit of what you've learned already:

function myFunction()
{
  myVariable = "excellent";

  if (myVariable == "excellent")
  {
    player.chat = "Hooray! The values match.";
  }
    else
  {
    player.chat = "The values don't match.";
  }
}

Now. The first thing about an if statement is giving it something to check. The statement "myVariable ==" alone will return either one of two values - TRUE (1, one) or FALSE (0, zero).

An if () statement by itself will only check if something is true. If not, it'll ignore it. If you put an else in, like in the above example, that code will be run in the case of a failure.

Storing the result of a conditional check

Now, as previously mentioned, a comparison (==) will only produce either true or false. If you want to store the value of a conditional check for use later, then you can assign the result to a variable, instead of using it in an if () check now.

this.variable = (myVariable == "excellent");

... saves the result of the check into this.variable. So later, you can do:

if (this.variable)
{
  // code
}

... to see if the check was successful. Similarly, you can do:

if (!this.variable)
{
  // code
}

... to see if the check failed.

Manipulating data

Data can be manipulated in various ways. For example, you can modify parts of a string. You can apply math functions to a number. This section explains those sorts of functions.

Basic math

GScript allows you to perform basic operations like add, subtract, multiply, divide, etc. However, GScript does not use functions for this. Instead, it has a set of "operators".

Examine the following examples:

this.result = 3 + 4; // addition (sets this.result to 7 in this case)
this.result = 3 - 4; // subtraction (sets this.result to -1 in this case)
this.result = 3 * 4; // multiplication (sets this.result to 12 in this case)
this.result = 3 / 4; // division (sets this.result to 0.75 in this case)

Note how the operators are between two values: the value to start with, and then the value to operate with. The use of an operator returns a value in the same way as other comparisons, so let's take this example:

if ((3 - 4) == -1)
{
  // code
}

This statement evaluates to be true, because 3 - 4 does, in fact, equal -1.

Priority order

If you're doing complex operations, it is important to ensure that your priority order is correct. In it's most basic mathematic form, the default order of operations is the following:

  • B - Brackets
  • O - Order
  • D - Division
  • M - Multiplication
  • A - Addition
  • S - Subtraction

That means that in a complex expression, multiplication takes priority order over addition, and that a part of the expression surrounded by brackets will always be calculated first.

Brackets are very useful because it allows you to specify the order of operations. Consider this example:

this.result = (3 * 4) / (2 * 3);

... is calculated in this order:

  • First, 3 is multiplied by 4:
this.result = 12 / (2 * 3);
  • Second, 2 is multiplied by 3:
this.result = 12 / 6;
  • Finally, 12 is divided by 6:
this.result == 2

Slightly more complex operators

There are another set of operators which allow for basic math manipulation on a variable. These allow you to add and subtract to a number variable, without having to perform the expression yourself. For example:

this.result += 3;

... is the same as doing:

this.result = this.result + 3;

Similarly:

this.result -= 3;

... is the same as doing:

this.result = this.result - 3;

The increment and decrement operators are as follows:

  • += - add to
  • -= - subtract to
  • *= - multiply by
  • /= - divide by

Occasionally it is useful to just add or subtract one to a variable. There are operators to do this, too.

this.var ++;

... is the same as doing:

this.var = this.var + 1;

Also:

this.var --;

... is the same as doing:

this.var = this.var - 1;

Understanding booleans

Booleans are, plainly and simply, true or false values. They don't do anything else.

this.value = true;
this.value = false;

Technically, true is the same as 1, and false is the same as 0, but the keywords are here to tidy things up a bit. Booleans are very useful because they help to control how your script operates. Now, as you know, a conditional check will produce a true or false result. For example:

3 == 3

... produces true, because 3 equals three.

3 == 2

... produces false, because 3 doesn't equal 2.

Understanding Objects

No one can call them self a true Graal scripter until they have a firm grasp on the concept of objects. Basically, in GSCript, all items of a given type - players, NPCs, levels, Gui Controls, etc - act in the same way. Objects of the same type give you the same kinds of data, and can even be controlled in the same way.

Let's say you wanted to access some kind of data from the Control-NPC. It turns out that the Control-NPC itself is an object. All you have to do is create an object which represents the Control-NPC. After the object is created, you can use variables from it, or execute commands as if it were that NPC. For example:

temp.controlnpc = findnpc("Control-NPC");  //Creates an object references the Control-NPC
this.player_data = temp.controlnpc.player_data;  //Copies data from the Control-NPC to the current NPC.
temp.controlnpc.onCreated(); //Executes the onCreated function through the Control-NPC

You can even use the object directly:

this.where_is_waldo = findnpc("Waldo").level.name;

Here, the 'Waldo' npc is being called directly. As you can see, the NPC's level is also an object! Finding Waldo has never been so easy.

Players work the same way (they are also objects):

temp.p = findplayerbycommunityname("Stefan");
temp.p.chat = "Hi! I'm playing Graal!";

This script would find the player with the community name 'Stefan' and set his chat to 'Hi! I'm playing Graal!'. Also, no matter how you got the player object, everything works the same way:

findplayer("napo_p2p").say2("EAAAGLE!");
allplayers[3].chat = "How appropriate.  You fight like a cow.";
players[i].setlevel2("jail.nw", 30, 30);

In fact, most everything within GScript is some type of object! That weapon you're using to wreak havoc on your enemies? Why, that's a TServerWeapon. Those bullets hitting your foes? TProjectile. That level you've been jailed in one too many times? TServerLevel. You can access all of these objects with GScript. If you decide to be more ambitious, you can even create your own.