Difference between revisions of "The Official SCAR Scripting Guide"

From SCAR Divi Manual
Jump to: navigation, search
(Conditions)
(Case Statements)
Line 384: Line 384:
 
       WriteLn('6 or 8');
 
       WriteLn('6 or 8');
 
     end;
 
     end;
     7, 9: WriteLn('7 or 9');
+
     7, 9..11: WriteLn('7 or 9 up to 11');
 
     else WriteLn('Not 1 to 9');
 
     else WriteLn('Not 1 to 9');
 
   end;
 
   end;

Revision as of 15:05, 22 December 2011

This tutorial is under construction, check back later for updates!

Introduction

History

SCAR was originally created by Kaitnieks (Aivars Irmejs) in 2003 with the purpose of replacing his previous creation AutoRune, a program designed to automate tasks in RuneScape. The program rapidly evolved into a very powerful color based macroing application and was used not only for RuneScape, but also to automate other games andtasks not related to gaming. Late 2006 Kaitnieks retired from the scene and passed on the task of developing SCAR to Freddy1990 (Frédéric Hannes), who up to this day still develops SCAR. When the development was passed on, SCAR was renamed to SCAR Divi. Divi is the Latvian word for "two", as now 2 people had developed the program.

Scripting

SCAR has been from the start a scriptable macroign environment. Scripting SCAR is done in a Pascal based language. The syntax of this is very different from C based languages, however, it was originally designed for teaching purposes which makes it very easy to comprehend.

Basics

Distinctions

When thinking about scripting/programming, tehre are a few important distinctions you have to make. There is data and logic. The data in your script originates from values you hardcode into a script or data you get from SCAR's API. This data can be stored in variables, which we'll discuss later on. The logic of your script is the code which makes it work. It is a blueprint for the behavior of your script, it tells it what to do under which circumstances.

Hello World

The first thing you'll want to do when learning any new programming language is create a "Hello World" application. This is an extremely basic script which outputs "Hello World!" in a way the end-user can read it. The reason why you want to do this is to get a basic idea of how your programming environment works. "Hello World!" is a string, this basically means that it's a sequence of characters. The Pascal programming language marks strings by surrounding them with apostrophes. If you want to add an apostrophe to a string, you need to place 2 inside of the string which makes the first one "escape" the second one and add it to the string. For basic output we can use the WriteLn function, which simply outputs text to the debug box in SCAR's main GUI.

Our resulting script looks like this:

program HelloWorld;
begin
  WriteLn('Hello World!');
end.

Output:

Hello World!

The "Hello World!" string we passed to the WriteLn function is surrounded by rounds. When calling any function that takes arguments, in this case the message to output, you have to pass the arguments by placing them in between rounds after the function name and separate them with commas. Except for a few exceptions which we'll see in the future, you should always terminate lines that contain a funciton call witha semicolon. The "begin .. end." clause we see in the script is always the last thing you'll find in your script (everything after "end." is ignored). It represents the entry point of your script, it will be the first thing that is being executed and you call everything else from there. At the top of the script we notice the program line. This line should always be the very first of the script, if you place things above it, it will cause errors. This line simply denotes a name for your script but it is not required to include it in a script, you can simply choose to remove it. Future examples in this guide will not include this line.

Constants

The most basic form of data storage are constants. These are fields in the memory which contain a single data entry and which are denoted by a specific reference name. In SCAR constants can only contain basic data such as strings, numbers and boolean values. A very important thing to note about constants is that they are immutable, which means that they can not be changed. You can only set constants once by manually assigning them a value in your script, they can not be assigned dynamically during runtime.

Constants are defined in the constants sections of a script, there can be multiple of these sections and they have to be defined in the global scope and not in a code section. All constants must have a different name, if they don't, the compiler does not know which is which.

This example shows the simple use of constants:

const
  StringConst = 'Hello World!';
  IntConst = 12345;
  FloatConst = 12.345;
  BoolConst = True;

begin
  WriteLn(StringConst);
  WriteLn(IntConst);
  WriteLn(FloatConst);
  WriteLn(BoolConst);
end.

Output:

Hello World!
12345
12,345
1

Variables

A second form of data storage are variables. Variables work like constants in the way that they are denoted by a unique name (which can't clash with names of constants), they can't however be assigned a value directly. All data in varaibles has to be assigned inside of code sections. this means that thye can both be read and written to. Variables can not only hold basic data types, but also abstract data types which we'll take a look at later. They are defined in the variable section in the global scope or a local scope. To define them, you place a colon and the data type after the name of the variable and terminate it with a semicolon. You can also add several variables of the same type to a single declaration by separating them with commas.

In this example we declare 3 variables, 1 of the type string and 2 more of the type Integer, the latter of which holds a whole number:

var
  Str: string;
  i1, i2: Integer;

begin
  Str := 'Hello World!';
  WriteLn(Str);
  i1 := 5;
  i2 := 6;
  WriteLn(i1);
  WriteLn(i2);
end.

Output:

Hello World!
5
6

Types

It is common practice to prefix abstract data types in Pascal with the letter T, most basic types don't have this prefix.

Basic Types

Pascal provides a series of basic data types which are the most basic form of data you can store.

Logical data types:

Name Data Example
Boolean True or False (1 or 0) True,False

Integer data types:

Name Data Example
Byte 0..255 0,1,6,77,98
ShortInt -128..127 -48,-6,0,75,125
Word 0..65535 0,5,96,7768,15568
SmallInt -32768..32767 -2587,-68,0,96,15568
Cardinal 0..4294967295 0,125,16875,4987542,65987423
Integer -2147483648..2147483647 -15266984,-687450,0,4987542,65987423
Int64 -18446744073709551616..18446744073709551615 -15224679526487264,-687458366350,0,78479875757242,659757875777423

Decimal data types:

Name Data Example
Single Single precision floating point value (4 bytes) -2.9,0,5.874
Double Double precision floating point value (8 bytes) -136.236542738,0,4875.56974584
Extended Extended precision floating point value (10 bytes) -136.23654573742738,0,4875.569174537384

Text data types:

Name Data Example
Char A single character a,9,B,!,@
String A string of characters Hello World!
AnsiString An ansi string of characters Hello World!

You should always use the smallest type available that fits your needs, this will optimize your memory usage and overall performance as smaller data types require less cpu cycles to read, write and perform operations on.

Type Aliases

A type can easily be given an alias. You simple assign the type to a new name in the type section which can only be placed in the global scope. Type names can't clash with any other names such as constant ot variable names in your script.

In this example we create an alias for the Integer data type:

type
  MyInt = Integer;

var
  Value: MyInt;

begin
  Value := 123456;
  WriteLn(Value);
end.

Record Types

A record type or structured type is a type that consists out of multiple named fields which can be defined as a different type. An example of this is the TPoint type.

To create a record type, you have to assign a new record to a name in the type section, in it's definition clause, add the fields the same way you would define variables.

In this example we create a simple record type with a single Integer field:

type
  TMyRecord = record
    Field: Integer;
  end;

var
  Value: TMyRecord;

begin
  Value.Field := 123456;
  WriteLn(Value.Field);
end.

Records don't work recursively, which means you can't create a field inside of a record of that same record type.

Enumerations

An enumeration is a collection of named values. This sometimes makes it easier to assign meaning to values rather than using numbers. This is assigned to a type as a comma separated list surrounded by rounds.

In this example we show that enumeration values are stored as simple integer values in the memory:

type
  TMyEnum = (meTest, meTest2);

var
  Value: TMyEnum;

begin
  Value := meTest;
  WriteLn(Value);
  Value := meTest2;
  WriteLn(Value);
end.

An enumeration can hold as many as 256 different values.

Class Types

SCAR provides a whole bunch of class types to use in scripts, you can't define class types yourself though. A class has to be used as an object which is an instance of the class. An object has to be created and freed after you're done using it or it will get stuck in the memory.

This example shows the usage of a TStringList class. This class can hold a string, allow easy access to individual lines of the string and perform operations on it.

var
  Value: TStringList;

begin
  Value := TStringList.Create;
  try
    Value.Text := 'Hello World!';
    WriteLn(Value[0]);
  finally
    Value.Free;
  end;
end.

Conditions

A script can check if a certain condition is met by checking if functions return a specific result or variables contains a specific value. To do this, you need to evaluate a comparison between 2 values and perform an action based on the result of that comparison.

If Statements

If statements can be used to evaluate very simple or very complex statements. The basic concept works like this: "if a comparison returns true, then do something, if it returned false, do something else". Obviously you can check another condition if the first one was not met.

This example shows a vary basic construct with an if statement which checks if a constant equals 5. If you look closely, you'll see that the first WriteLn statement is not terminated with a semicolon, this is an exception that was mentioned earlier in the guide. When you are not using a "begin..end" bloxk in the if statement, which allows you to only execute a single statement, the statement that is followed by else can not have a semicolon at then end.

const
  Const1 = 5;

begin
  if Const1 = 5 then
    WriteLn('Const1 is 5')
  else
    WriteLn('Const1 is not 5');
end.

This example is the same as the previous one with the exception that it contains a "begin..end" block in the if statement. This allows you to execute multiple lines. The "end" keyword should normally be terminated with a semicolon, but it is followed by else, so this is dropped. If you add a "begin..end" after the else keyword, you have to terminate the end with a semicolon.

const
  Const1 = 5;

begin
  if Const1 = 5 then
  begin
    WriteLn('Const1 is 5');
  end else
    WriteLn('Const1 is not 5');
end.

Like the previous example, but with a "begin..end" clause in the else statement.

const
  Const1 = 5;

begin
  if Const1 = 5 then
    WriteLn('Const1 is 5')
  else begin
    WriteLn('Const1 is not 5');
  end;
end.

Comparison Operators

Pascal provides a series of logical operators to evaluate expressions. Previously we used the equals operator to check if 2 values are equal.

This list contains all logical operators. Take in mind that most of these only work on numerical types with the exception of equals and does not equal.

Operator Name Description
= Equals Returns true if 2 values are equal.
<> Does not equal Returns true if 2 values are not equal.
< Smaller than Returns true if the first value is smaller than the second one.
<= Smaller than or equal Returns true if the first value is smaller than or equal to the second one.
> Larger than Returns true if the first value is larger than the second one.
>= Larger than or equal Returns true if the first value is larger than or equal to the second one.

This example shows the use of the <> operator and an if statement that follows an else statement to check a second condition.

const
  Const1 = 4;
  Const2 = 4;

begin
  if Const1 = 5 then
    WriteLn('Const1 is 5')
  else if Const2 <> 6 then
    WriteLn('Const2 is not 6');
end.

Case Statements

Case statements allow you to replace a big amount of if..else statements when using some basic types. The logic of this construct is very simple, you examine a value and then simple check if it matches different cases and provide a code block to execute for each case. You can also execute a single code block in several different cases.

This example shows the many uses of a case statement for an integer value.

const
  Const1 = 4;

begin
  case Const1 of
    1: WriteLn('1');
    2..5: WriteLn('2 up to 5');
    6, 8: begin
      WriteLn('6 or 8');
    end;
    7, 9..11: WriteLn('7 or 9 up to 11');
    else WriteLn('Not 1 to 9');
  end;
end.