PDA

View Full Version : Learning to script from the basics to becoming an SRL Member



Town
10-20-2007, 12:58 AM
First of all, if you have a question do not PM me. Post here.

Writing your first script.

The first thing you ever see in opening up Scar is:

Program New;
begin
end.

Let's examine this.

Program New;

Program is declare in all (most) scripts and simply declares the names of the script. The world after that, New in this case, is the name of the script. It must be one word and will normally be written something like: Program MyNewScript; Typed with capital letters like that so it can be easily read. Keep readability in mind when scripting, always.

Begin is another important word. Begin declares that a new section of code is starting, or something alongthose lines. It's hard to explain in words so I'll try explaining it in a few examples.

Program New;
begin
WriteLN('0');
begin
WriteLN('1');
begin
WriteLN('2');
end;
WriteLN('3');
end;
WriteLN('4');
end.

The first begin you see starts the program, the last end which will always look like "end." (Pointng out the period) will always end the script. The period will be the last thing you see in every script. The second begin starts a new section of code, kind of like a subsection of the first begin and end. This continues into a third begin and end that is a subsection of the second begin and therefore is still a part of the first begin and end. It isn't as confusing is at may sound now, it's actually very simple once you start to understand further.
You may notice how after each begin I went forward two spaces in the next line and after each end I went backwards two spaces. Those are called standards, I will explain them more later. You may also see the semi-colons after each begin except the last one, that is also standard related, even though the last one is required.
This piece of code is redundant. It will do the same thing as this:

Program New;
begin
WriteLN('0');
WriteLN('1');
WriteLN('2');
WriteLN('3');
WriteLN('4');
end.

If you don't understand why, don't worry. All you need to know is that for each begin you have, you need and end at this point. Everything will be explained in more detail and will fit together as we go on.

/////////////////////////////////////////////////////////////////////////////////////////

This next part is very important, pay attention.

Variables and Constants

A basic variable is much like a variable in algebra but some are more advanced. All you need to know for the time being is that a variable represents something else.

Program New;

var
i: Integer;

begin
i := 500;
end.

There are many things in this script that you do not understand. Let's start with 'var'.

var is how you declare a variable, just like the name suggests. You can only write var once time and declare as many variables as you want. Everything until a begin (or const, or label, or other things you have never heard of) Scar will take as a variable declaration.
In this case, we are declaring an integer. An integer is a whole number, not a fraction. I declared the variable "i" as an integer. Every variable must be one word, it is not case sensitive, it can be more than one letter. In between the variable you are declaring (i) and the type of variable you are declaring it as (an integer) you will always need a colon. After you are done declaring the variable put a semi-colon after the varible type, that is required.
Lastly, I started by script with begin. You must be wondering what ":=" means. Normally, I read it as the word "becomes" because that is what it has always seemed like to me. You can call it whatever you want, all you need to know is that when you write "i := 500" the value of i becomes 500. Then, I end my script with the word end and a period.

An obvious use for an integer is for doing math:

Program New;

var
i: Integer;

begin
i := (500 + 5 * (87 * 48)) div 2; // div stands for divided by and can also be written as /
end.

You may wonder why I put two backslashes before writing a comment. After putting two backslashes in a row like above everything after them on that line becomes a comment. This is great for learned purposes. You can also use { } which can stretch over more than one line until it is stopped:

{This is a comment
This is a comment.
This is a comment
This is the end of the comment}[scar]

That's not all for variables though. The next variable I will talk about is called a string. A string is a group (or string) of letters, numbers, symbols, etc. Look at this script:

[scar]Program New;

var
i: String;

begin
i := 'agi6$$()77svs5s5s&&-';
end.

This time, I declare the variable "i" as a string. When you want to type out a string you always surround it with '' like the script above. I would read my script as, i becomes agi6. . .

A little while ago I used the procedure WriteLN(''); The parameter (which I will get into later) for this procedure is a string. So, using it may look like this:

Program New;

var
i: String;

begin
i := 'agi6$$()77svs5s5s&&-';
WriteLN(i);
end.

You may be thinking, "Hey, I thought he said strings had to be surrounded by ''. Well, it is. If you substitute what i represents into the procedure then it will look like this:
WriteLN('agi6$$()77svs5s5s&&-');

If I had put '' around i when writing the procedure then it would have printed the letter "i", not our variable.

The last variable I will explain to you (there are many more) is a boolean. A boolean is simply true, or false.

Program New;

var
i: Boolean;

begin
i := True;
end.

This may look like a waste of time, but it will be one of the most useful variables in the future. Just keep in mind that the only things it can represent are true and false.

I will also breifly talk about arrays which are more advanced. Arrays are groups of variables all in one. There can be an array of Boolean, array of Integer, etc. The length of an array starts at 0 when you declare it. If you try to edit your array without specifying a length then you will get errors. You can edit the length of an array anytime during the script by using SetArrayLength(NameOfArray, LengthToSet) or set it when you declare the variable by writing array[0..6] of Integer. Here's some examples:

Program New;

var
Bools: Array[0..6] of Boolean;

begin
Bools[0] := True;
Bools[4] := False;
end.

See how I set the length of the array before starting to use it.

Program New;

var
Bools: Array of Boolean;

begin
SetArrayLength(Bools, 7);
Bools[0] := True;
Bools[4] := False;
end.

You can also get the length of an array using GetArrayLength(Array). I'll get into arrays more later, you just have to know they exist.

Now for constants. Constants are declared by "const". They are normally used so that users can declare thing inside you script without looking through the meat of it and messing things up. They are not extremely useful (in my opinion) so I will go through them quickly. Here's an example that you hopefully understand:

Program New;

const
TheConst = 'Yes';

begin
WriteLN(TheConst);
end.

Constants can be integers, strings, booleans, or other variables. Like this:

Program New;

const
TheConst = 5;

begin
TheConst := TheConst * 5;
end.

That will make TheConst 5 times greater than it started, which would be 25 in this case.

/////////////////////////////////////////////////////////////////////////////////////////

It is very early to introduce this, but it goes right along with what I am talking about. It will also be used in every script you will ever right, most likely.

If-Then (Else) statements. I have else in parenthises because it is not always used.

The basis of it is that If (..) is true then it will do something. If it is not true it will do "else", if that is there.

Let's start with a script:

Program New;

var
i: Boolean;
p: String;
z: Integer;

begin
z := 0;
i := True;
p := 'hhggff33';
if (i = True) then
begin
WriteLN(p);
z := z + 24;
end;
end.

In this script I tried to incorporate everything you have learmed so far, so let's review.
In this script, i is a boolean. If you look in the Main Loop (the name for the part of the script between the end. (with a period) and the begin connected with it) then you will see that I said i was true. Just after that I said, if i is true then 'do stuff'. Since i is true it will do those things, if you have been paying attention the you should be able to figure out how to make it not 'do stuff'.
Next, p is a string. I said p is equal to 'hhggff33'. If i is true then it will write hhggff33 into the debug box (The box under the scripting wndow, if you run this script you will know what I am talking about) using the WriteLN procedure.
Also, I declared z as an integer. First I stated that z was equal to 0. If i is true then z will become z + 24. 0 + 24 = 24, so z will become 24 if i is true.
If you do not understand that you need a main begin and a main end. (with a period) in each script then go ahead and start reading back to the beginning. What you may not understand is the second set of begin and end which comes after my If-Then (Else) statement. It starts a new section of code, if you remember. The script will only play that section if i is true. If i is not true then everything inside that begin and end will be skipped. Here's another example:

Program New;

begin
if (not (False)) then
begin
WriteLN('Blah');
end else
begin
WriteLN('Tear');
end;
end.

This time, I did use else. I also did not use any variables.
The word "not" may stick out to you. Not is used to call- If something is not true, then do this. It is pretty simple.
I also used False. False if a boolean. The Opposite of false is true. So, not false will be true and the script will do the first part of the statement.
If you were to change "if (not (False)) then" to "If (False) then" you may see a different outcome. Try it. Since the if (..) then statement was false, it did the else part. It's hard to explain in words but if you read it it should make more sense, if this is true then do this, else do this.

Program New;

begin
if (False) or (True) then
begin
WriteLN('Blah');
end else
begin
WriteLN('Tear');
end;
end.

"or" and "and" can also be used. Or will have it results true if one of the two (or more) is true. And will result true if both are true. You can also do more complex things like:

Program New;

begin
if (False) and (True) or (True) and (False) or (True) then
begin
WriteLN('Blah');
end else
begin
WriteLN('Tear');
end;
end.

It may be easier to read like this, which doesn't effect the script whatsoever:

Program New;

begin
if ((False) and (True)) or ((True) and (False)) or (True) then
begin
WriteLN('Blah');
end else
begin
WriteLN('Tear');
end;
end.

//////////////////////////////////////////////////////////////////////////

Procedures and Functions!

Procedures do something. That is a simple explaination. Look at this:

Program New;

procedure Proc(State: Boolean);
begin
if (not (State)) then
begin
WriteLN('Blah');
end else
begin
WriteLN('Tear');
end;
end;

begin
Proc(True);
end.

First of all, look how I declared that I was calling a procedure. First, I declared that I was calling a procedure, then the name of the procedure, then I stated the parameters of the procedure (I will explain in more detail very soon), then a semi-colon.
Every procedure has a certain number of parameters. These are variables that are used in that procedure but are declared from outside the procedure. In the above procedure, "State" is a boolean. The procedure can do different things depending on whether the boolean entered in that parameter is true or false. Parameters can be any type of variable. You can also have as mani parameters as you want separated by a semi-colon. It would be declared like this, "procedure OuiOui(Oui: Boolean; Non: String);"
Next, look at how the procedure ends. It ends with an "end;" with a semi-colon. Every procedure will end just like that, as apposed to the "end." with a period that will be in your main loop.
Finally, look how I called my procedure. Procedure can be called anywhere in the script after you declare them. In this case, I called it in my main loop by typing the name of the procedure followed by the parameters in parenthesis. If a procedure has more than one parameter then they will be separated by commas, "OuiOui(True, 'Bien sur');".

Here's a more advanced example:

Program New;

var
i: Integer; // Declares the variable.

procedure Proc(State: Boolean); // One parameter
begin
if (not (State)) then
begin
WriteLN('Blah');
end else
begin
WriteLN('Tear');
end;
end;

procedure OuiOui(Oui: Boolean; i: Integer); // Two parameters
begin
if (Oui) then i := i * 15; // If Oui is true then the value of i becomes 15 times what it was
end;

procedure NonNon(var i: Integer); // One parameter, i must be a variable
begin
OuiOui(True, i); // Calls the previous procedure
WriteLN(IntToStr(i)); // You don't know this procedure yet, all it does is change an integer into a string. The parameter in the WriteLN procedure must be a string.
i := i * 15; // The value of i becomes 15 times what it was
end;

begin
i := 5; // The value of i becomes 5
Proc(True); // Calls the first procedure
NonNon(i); // Calls procedure
WriteLN(IntToStr(i)); // You don't know this procedure yet, all it does is change an integer into a string. The parameter in the WriteLN procedure must be a string.
end.

Run that script. You should see that 5 was printed in the debug box from when OuiOui was called and then 75 was printed from later in the NonNon procedure. Now, change "procedure OuiOui(Oui: Boolean; i: Integer);" to "procedure OuiOui(Oui: Boolean; var i: Integer);". You should see that 75 was printed instead of 5 and 1125 was printed instead of 75. That happened because when you call a parameter as a "var" the changes that were made to that variable are carried over to the rest of the script. If the parameter is not called as a var then all changes to that variable in the procedure do not carry over to the rest of the script. In this script, when i was declared as var in OuiOui, the math that took place in that procedure carried into the NonNon procedure. This may take some getting used to, don't get discouraged.

Now for functions. You can think of a procedure as a type of function. A function automatically has a variable called "Result" that can be used in the procedure. To be simple, a function is a procedure that results a value (Even though it is the other way around, a procedure is a function that results nothing). Here:

Program New;

function Proc(State: Boolean): Boolean;
begin
if (not (State)) then
begin
WriteLN('Blah');
Result := True;
end else
begin
WriteLN('Tear');
Result := False;
end;
end;

begin
if (Proc(True)) then WriteLN('Yay');
end.

If the function proc results true then the script will write Yay into the debug box. It can result any variable:

Program New;

function DoubleIt(i: Integer): Integer;
begin
Result := i * 2
end;

begin
if (DoubleIt(6) > 10) then WriteLN('Yay');
end.

While I'm on the subject, >is greater than, < is less than, = is equal to, >= is greater than or equal to, <= is less than or equal to.

Functions and procedures can also have local variables as apposed to global variables. Global variables can be used throughout the script and the value will never reset unless you tell it to. Local variables are variables called inside functions and procedures that save memory and reset each time you exit the procedure. Local variables look like this (you have already seen global variables):

Program New;

procedure News;
var
i: Integer;
begin
i := i + 5;
end;

begin
News;
end.

The variable i can only be used in that procedure, if you want to use it somewhere else then you will have to declare it there too or make it a global variable.

//////////////////////////////////////////////////////////////////////////

Loops!

Loops do something more than once. There are many different ones in Scar. Here's the simplest one:

repeat
Wait(10);
until (False);

A repeat loop will keep repeat until the boolean you specified is true. Any boolean or function that results a boolean can be used. Until (False) will go on forever because false will never be true. Until (True) will only go through once because True will be true the first time through.

Next, while .. do loops.

while not False do
begin
Wait(10);
end;

This will also go on forever. While not False is true, it will continue to wait. The difference between this and a repeat loop is that if the boolean is true before it even enters the loop it will break it before starting. If you remove the "not" from the script above then it will never wait, it will end immediately.

Next, for .. to .. do.

for i := 0 to 19 do
begin
WriteLN(IntToStr(i));
Wait(100);
end;

This loop will repeat 20 times and i will increase by 1 each time. Try it if you want, just make sure you declare i as an integer.

For all of the above loops you can use the word "Break;" to break out of the loop immediately. This would look like this:

for i := 0 to 19 do
begin
WriteLN(IntToStr(i));
if (i = 10) then Break;
Wait(100);
end;

That procedure would repeat 10 (half of an eleventh) times before breaking out of the loop. "Exit;" is used in the same way only it exits an entire procedure or function.

Next, looping procedures.

procedure Okay;
begin
Wait(100);
Okay;
end;

These are fairly complicated loops. This loop will go on forever and if you don't use it correctly you will get stuck in alot of infinate loops while using it.

Make sure to have proper waits in loops. If you are missing them then your script will lag, alot.

//////////////////////////////////////////////////////////////////////////

Cases

Cases can be used like giant if statements. Look at this:

if (This = 'This') then
begin
end else
begin
if (This = 'That') then
begin
end else
begin
if (This = 'Something') then
begin
end;
end;
end;

That could be cleaned up by using a case.

case This of
'This': begin
DoStuff;
end;
'That': begin
DoIt;
end;
'Something': begin
DoAll;
end;
end;

It will always be "case Variable of" and then all of the possible values that the variable could be. A case with a boolan would be smaller:

case Bool of
True: WriteLN('Yes');
False: WriteLN('No');
end;

If you are only doing one function then you do not need a begin and an end. I could have done the same thing with the first example. This is the same as if .. then statements, if you are only doing one procedure then you can type "if (This) then WriteLN('Yes');" without a begin and end.

//////////////////////////////////////////////////////////////////////////

Bitmaps and DTMs

A bitmap is a picture, pretty much. To make a bitmap take a screenshot, cut it down to size, go to Tools --> Picture To String, your Bitmap will appear as a string in the debug box.
A DTM is a collection of points that make up a picture, it consists of one main point and several subpoints branching off from that main point. To make a DTM, get the screen how you want it and go to Tools --> DTM Editor (it will take a screenshot for you), make your main point and make sure your tolerance is high enough (usually around 25-30), continue collecting subpoints, editing the tolerance, and then reselecting the main point before picking your next point, then go to File --> DTM To Text, your DTM will appear as a string in the debug box.

DTMs and bitmaps are declared as integers. Here's an example of a bitmap (not a real bitmap):

Program New;

var
a, x, y: Integer;

begin
a :=BitmapFromString(36, 7, 'AP59JJ39H7A1NFA');
if (FindBitmap(a, x, y)) then WriteLN('Found');
FreeBitmap(a);
end.

A DTM would look the same only it would be "DTMFromString('');" and you would use "FindDTM".
The last procedure I used was FreeBitmap(). That frees the memory that the bitmap was taking up. Bitmaps and DTMs take up alot of memory and can cause alot of lag, when you are done using them make sure to use FreeBitmap() and FreeDTM(). On the other hand, loading and freeing a bitmap repeatedly will also cause lag, make good choices.

//////////////////////////////////////////////////////////////////////////

Commonly Used Functions

I have already told you about WriteLN(''); It is a procedure that prints a string into the debug box.
I used Wait(..) without telling you what it was, but you probably could have guessed. The parameter is an integer and it waits that amount of milliseconds.
I have also already used Random() which results a random number 0 up to 1 less than the integer you entered.
I also briefly explained IntToStr(..), the parameter is an integer and it results as a string. So, IntToStr(4) would turn the integer 4 into the string '4'. Pretty much all types of conversions are possible, StrToInt(''), StrToBool(''), BoolToStr(), etc.
LowerCase('') makes all letters in a string lowercase, Uppercase('') does the opposite.

Keep in mind that by pressing F1 you will get a list of all procedures and functions in Scar.

FindColor(..) is a very commonly used function. The parameters look like, "FindColor(var x, y: Integer; color, X1, Y1, X2, Y2: Integer);". You may notice that multiple parameters are called without adding semi-colons, you can do that when you are using multiple parameters in a role that are the same type of variable.
The x and y are the coordinates where the color is found, as you can see they will always be variables. Next there is the color you are looking for. You can use the Scar built in color picker to pick colors from wherever you want. Then the last 4 parameters are where to look for the color, they should make a box. (X1, Y1) is the first coordinate then (X2, Y2) is the second. (X1, Y1) should be in the top left and (X2, Y2) in the bottem right. If it finds the color it results true.
Here's an example:

begin
if (FindColor(x, y, 0, 5, 5, 20, 20)) then WriteLN('Found it: ' + IntToStr(x) + ', ' + IntToStr(y));
end.

First, make sure you understand how I used FindColor. Next, look how I used WriteLN(''); A "+" in a string just combines the two strings, there are no spaces added in between them so be sure to make them distinguishable if needed. Try messing with coordinates and colors to make sure you understand exactly how it works.

There is also FindColorTolerance, FindColorSpiral, and FindColorSpiralTolerance. Tolerance is a number that increases the range of numbers that could be found instead of having to find an exact match, both of the functions using it have one extra parameter at the end which needs an integer. They can range from 0 to 255. This is helpful because colors in Runescape change. Spiral searches from the center out in a spiral, like the name suggests.

begin
if (FindColorSpiralTolerance(x, y, 230, 5, 5, 20, 20, 25)) then WriteLN('Found it: ' + IntToStr(x) + ', ' + IntToStr(y));
end.

Play with tolerances until you really get a feel for them.

//////////////////////////////////////////////////////////////////////////

Including the SRL.

The SRL is an include, as you should know. It is a compilation of functions including random solvers and other utilities to make scripting easier.
To include the SRL, simply type "{.include SRL\SRL.scar}" the line after you declare the name of your program. Like this:

Program New;
{.include SRL\SRL.scar}

begin
end.

Any include can be included that way, but the SRL will probably be the only one you use. Parts of the SRL not included in the core library will not be loaded without declaring them separately. Just type "{.include ..}" where .. is where the include is located starting from your Includes folder.

//////////////////////////////////////////////////////////////////////////

SRL Functions you will want to know:

FindNormalRandoms; - Procedure that solves (if possible) all randoms. Call it whenever you think you might get a random.
MMouse(x, y, RandX, RandY: Integer); - Procedure that moves the mouse to a point with some random coordinates.
Mouse(x, y, RandX, RandY: Integer; Click: Boolean); - Procedure that moves the mouse to a point with some random coordinates and then clicks left if true or right clicks if false.
FindObj(var x, y: Integer; Text: String; Color, Tolerance: Integer): Boolean - Function that uses a color and an uptext to find an object, results true and x and y coordinates if found.

Of course there are at least a hundred more functions in the SRL but these are some you will want to start with.

//////////////////////////////////////////////////////////////////////////

Writing Your First Simple Script!!!

You now have the tools to begin writing your first Scar script. It can be as complex as you want it to be. Here are some things you will want (Pretty much taken from the How To Become an SRL Member tutorial by Boreas):

Standards: I have already talked about them some. Here's the real list: http://www.kaitnieks.com/scar/scriptingsta/

Multiple Players: Multiple player scripts are simple using the SRL. You will need:

A declare players procedure (using the SRL player array):

procedure DeclarePlayers;
begin

HowManyPlayers :=2; // Must match number of players in the array
NumberOfPlayers(HowManyPlayers);

Players[0].Name :=''; // Add as many players as you want
Players[0].Pass :='';
Players[0].Nick :='';
Players[0].Active:=True;

Players[1].Name :='';
Players[1].Pass :='';
Players[1].Nick :='';
Players[1].Active:=True;
end;

All variables that can be used can be located in Players.scar in your Includes\SRL\SRL\Core folder.

Then, call your DeclarePlayers procedure in the main loop (or called indirectly in the main loop, like in a SetupScript procedure):

begin
DeclarePlayers;
repeat
repeat
// Your script stuff
until (not (LoggedIn)) or (FeelLikeSwitchingPlayers);
NextPlayer(LoggedIn);
until (false);
end.

The function LoggedIn will result true if you are logged in. It is always a good idea to have if (not (LoggedIn)) then Exit; at the beginning of every function and also inside loops, sometimes some other places too. The procedure NextPlayer will log into the next active player.

Progress Reports: Keep track of your progress in other procedures and then use WriteLN('')'s to display the progress in the debug box.

At this point, you should have the tools to write your first SRL script. Learn by making mistakes, go write a script.

-- If you think I'm pretty good at writing tutorials I plan on doing another few intermediate-advanced ones as far as writing forms, making your own types, advanced array stuffs. Maybe I'm bad at writing tutorials, I guess that's your decision :)

Timer
10-20-2007, 01:08 AM
Very Nice, Well Explained, ( If I'm Allowed To Rep++ ( LOL :D ) )

yamaha317
10-21-2007, 03:11 AM
Great Tut i already know most stuff from begginers tuts but you went over some beginner/intermediate stuff that are not in the intermediate tuts thanks =) ++rep

lanky_dude1
11-10-2007, 12:16 AM
Great beginner Tut, realy helped

Raskolnikov
11-10-2007, 01:06 AM
Great Tut, helped sooooo much. Rep++

big boy6
11-17-2007, 10:43 PM
finaly iv been looking for ever for this!

danman1212
12-31-2007, 06:22 AM
this helped me understand scr thx so much!

yukarg
12-31-2007, 07:21 AM
Very nice man, just another one of Town's great creations! ++Rep!

Richard
12-31-2007, 08:33 PM
Great script mate.

Have you made any intermediate tutorials yet, I think yours would be best :D

penguII
01-19-2008, 02:14 PM
Thanks alot, this gave me an great introduction into the world of the scar ;) :).

Btw?. Is there a special reason why scar isnt case sensitive ?

Town
01-19-2008, 07:59 PM
It's easier for people new to programming. No Pascal based languages are case sensitive.

ZaSz
01-19-2008, 09:27 PM
Nice Job, Really gets you the idea of scripting. ++Rep minus ++Rep = 0Rep.

armin
03-05-2008, 02:36 AM
Awsome Tut, Thanks lots.:D

WhoCares357
03-13-2008, 01:29 AM
I'm glad you finally came up with your own tut. Good job.

Ghostman
07-30-2008, 12:37 AM
nice Tut, very well explained

m4g3owns
08-14-2008, 07:30 AM
Very helpful im slowly learning how to do some decent scripting and soon ill have my own script running, thanks for this :)

AzulDrake
08-22-2008, 09:48 AM
Thanx for this tut, help alot :)