SRL Archive - Outdated Tutorials

All-In-One SCAR Scripting Tutorial!


Coh3n

2009-08-21 04:17:43

Coh3n’s All-In-One SCAR Scripting Tutorial!
For the beginners to the advanced color scripters…
This tutorial was last updated on October 21st, 2009.


1. Introduction:

Hello, and welcome to the largest tutorial I will probably ever write!

During this guide you will learn many different scripting techniques, commands, and habits that I’ve picked up during my time here at SRL. These elements will guide you to making a well written Runescape script that can last for hours. :)

I have assembled this guide from my own knowledge and from many different tutorials around the forums. I have explained everything in this tutorial to the best of my ability, but if something is unclear, please, don't hesitate to post on this thread and either myself, or someone else will give you a detailed response as soon as possible.

Throughout the guide, I will be taking you through the different concepts step by step, starting with the basics. Although you do not require any previous knowledge of SCAR to understand this tutorial, it will obviously be very helpful.

Before continuing through this guide, you need to make sure you have installed SCAR and SRL properly. If you don't know how to do this, you can follow this tutorial to do so -> How to install/setup SCAR! I also suggest that as you read this tutorial, do the exercises as they are taught to you, that way you will have a much higher percentage of understanding and remembering what you're being taught. I also suggest experimenting with the concepts along the way such as playing with the numbers, the statements, just use your imagination! ;)

[BANANA]Note* This is a rather large tutorial, so if you are looking for something specific, please use Ctrl + F and search for what you want.[/BANANA]

2. Table of Contents:
  1. Introduction
  2. Table of Contents
  3. For the Beginner (This guide is for SCAR, if you're using Simba, see THE Beginner's Simba Tutorial)
    • SCAR - The Basics
      • Knowing SCAR
      • The Basic Variables
      • Procedures and Functions
      • Constants and Variables
      • Putting it all Together
    • Standards
    • Scripting Tips/Hints
      • Built-In Functions List
      • The SCAR Manuals
      • HotKeys
      • The "Tab" Button
    • SCAR Statements
      • If..Then..Else Statements
      • Cases
      • Loops
        • Internal Commands
        • Repeat..Until
        • While..Do
        • For..To..Do
      • Putting it all Together
    • DeclarePlayers
    • Failsafes
    • Antiban and AntiRandoms
  4. For the Intermediate
    • Basic Arrays
    • Item Finding
      • Bitmaps
      • DTMs
    • Object Finding
      • FindColor
      • FindObject
    • Autocoloring
    • Walking
      • DDTMs
      • Radial Walking
      • Symbol Finding
      • Using All Three Methods
    • Multiplayer
  5. For the Advanced
    • ColorToleranceSpeed
    • Advanced Arrays
      • TIntegerArray and TExtendedArray
      • TStringArray
      • TPointArray and T2DPointArray
        • Introduction to the WizzyPlugin
    • Custom Autocoloring
    • Types
      • With..Do Statements
  6. Recommended Reads
  7. Credits
  8. Conclusion

The headings for each scripting level (table of contents 3-5), have been made into a link specifically for your convenience. ;) Also, please feel free to point out any grammar/spelling mistakes I most likely made at some point throughout the guide. And please don't hesitate to tell me if something is unclear. I will gladly expand or better explain a specific part of the tutorial. Also, don't be afraid to post here with any questions you may have!

Coh3n

2009-08-21 04:18:47

Back To Top

NOTE: This guide is for SCAR ONLY. Some thing may still work in Simba, but for a more in-depth Simba-only guide, check out THE Beginner's Simba Tutorial.


3. For the Beginner:

In this section of the guide you will learn the absolute basics of coding in SCAR. You will learn the basic variables, and a very useful command known as "The Writeln Command." :eek: You will also learn what makes a RuneScape script work, and keep working for long periods of time.

SCAR - The Basics:

Knowing SCAR:

When you open SCAR, you will notice a blank script that looks like this:

program New;
begin
end.
The "program New;" part is what your script will be called. The program can be changed to whatever fits your interest. For example, you could change it to "Bobs_Amazing_Woodcutter" or "JoesMiner". Notice the "_" used instead of " ", this is because in any programming language, there cannot be spaces in names. This includes the names of procedures and functions (more on that later).

The "begin..end." is called your Main Loop. SCAR will read the code in your main loop as your script and run is as you please. If you would like SCAR to run a function or procedure, you have to include them in your main loop. More on script structure later.

Over on the right, you have the "Functions List". Currently, it is most likely just an empty white box. If you open any script, you'll be able to see a list of the different function, in this box. This becomes extremely useful for easy navigation when you script becomes super awesome and exceeds 1000 lines. :D

At the bottom of the SCAR window you'll see a white box. This is called the "Debug Box". Any errors you may have with yours or someone else's script, will come up in this box. You may or may not have it, but there should be another, smaller, white box to the right of the debug box. This is called the "Report Box", and you can just ignore it for now.

The Basic Variables:

This was taken straight out of the SCAR Manual, I couldn't have explained it better myself.



Procedures and Functions:

Procedures and functions are similar, yet different. Functions return a variable such as a boolean or an integer, while a procedure doesn't return a variable, it just does what it's told.

To start off, I am going to explain to you the structure of functions and procedures using the following example:

function IntToStr(i: LongInt): String;
  1. The function part is where it determines whether a function or a procedure is going to be used. If a procedure was going to be used, it would take place of "function"..
  2. Following function, is the name of the procedure/function. In this case, the name is "IntToStr", which stands for Integer To String, and simply converts an integer to a string.
  3. Inside the parentheses, we have the parameters of the procedure/function. In this example, there is one parameter, i. As you can see, i is declared as a LongInt, which is the same thing as an integer.
  4. Following the closed brackets is the Result of the function. In this case, the result is a string. However, the result can be whatever fits your needs (i.e. String, Integer, Boolean). Remember that this part is always left out of procedures.



procedure Writeln(s : String);
The Writeln procedure is a very useful procedure that can tell you why your script worked or why it didn't work. It is used a lot in a process called "Debugging" which simply means - removing all the bugs from your script so everything works well.

Try this:


program HelloWorld;

procedure WriteInDebugBox;
begin
Writeln('Hello world!');//Notice the ';' at the end of the line. Make sure you have that at the end of each line, otherwise you will most likely get an error.
end;
{Notice the ';'. This must be at the end of every procedure/function in your script.
Only the "End" in your Main Loop should be followed by a '.' to signal the end of the the script.}

begin
WriteInDebugBox;//See how I call the procedure in my main loop? Without this step, the script wouldn't do anything.
end.

Now when you hit run, do you see the "Hello world!" in the debug box? That is probably one of the simplest scripts you're going to see. You can change "Hello world!" to anything that you want to see in the debug box. Do you see how that is a procedure, and doesn't return any variables?

Try this:

program HelloWorld;

function WriteInDebugBox: Integer;
begin
Result := 10;//Because the function returns an integer, there is a variable "Result" that needs to be used.
Writeln(IntToStr(Result));//Because Result is an integer, and Writeln requires a string, we use IntToStr, which means "Integer to String".
end;

begin
WriteInDebugBox;
end.

Now when you hit run, you should see "10" in the debug box. Do you see the difference between a procedure and a function? It may not seem like much of a difference now, but once you get into more advanced scripting techniques, it will make a huge difference in your script.

Constants and Variables:

Constants are usually declared at the beginning of your script, and remain constant throughout your whole script, no matter where you use them, hence the name. They are declared like this, and can be used in any procedure/function throughout your script:


program New;

const
Logs = 100;

begin
end.
Pretty simple I'd say. :)

Variables can be declared in two different ways:
  1. Globally - means you would declare it at the top of your script, and can be used throughout many different procedures/functions.
  2. Locally - means you would declare it inside a procedure/function and would only use it for that procedure/function.

program New;

//Globally.
var
Logs : Integer;

//Locally.
function WriteInDebugBox: Integer;
var
B : Boolean;
begin
//I can use "B" in this function only.
//I can use "Logs" in this function as well as other functions/procedures.
end;

procedure SayHello;
begin
//I can use "Logs" in this procedure as well as in the above function.
end;

begin
end.
Not too hard, is it?

Putting it all Together:

Now that you've learned the absolute basics, we are going to make a small script, tying everything together. Exciting, isn't it?


program BeginnerScript;

var//Declareing variables globally.
Logs : Integer;
Exp : Extended;

const//Declareing constants.
NumOfLogs = 500;//Notice that NumOfLogs is an integer.
TreeToCut = 'Magic';//Notice that TreeToCut is a string.

procedure HowManyLogs;//Using a procedure.
begin
Logs := 250;//This is how we ASSIGN a variable. Remember this. ;)
Exp := 195.5;
Writeln('We have chopped ' + IntToStr(Logs) + ' logs this session!');//Notice we can use the variable "Logs" because it's declared globally.
Wait(500);//This is new, but don't worry. This is a simple procedure that waits the given time in milliseconds. (1000ms = 1s)
Writeln('We want to chop ' + IntToStr(NumOfLogs) + ' logs.');//Notice the '+'. This is required if you are going to Writeln a constant or variable.
Wait(500);
Writeln('We are chopping ' + TreeToCut + ' trees!');
Wait(500);
Writeln('We have gained ' + FloatToStr(Logs * Exp) + ' xp this session!');
//You are probably wondering what FloadToStr is. Well, it is used to turn extended integers into strings. It works the same as IntToStr.
end;

function WeAreBored: String;//Using a function.
var//Declareing variables locally.
S : String;
begin
Result := 'What are we going to do now?';//Notice that "Result" is a string because the function outputs a string.
S := 'We are very bored chopping all these logs!';
Wait(500);
Writeln(S);//Notice no "IntToStr" because the variable "S" is already a string.
Wait(500);
Writeln(Result);
Wait(500);
end;

begin//Don't forget to put your procedures/functions in the main loop!
ClearDebug;//This procedure just clears the debug box when you click run.
HowManyLogs;
WeAreBored;
end.//Notice the '.', signalling the end of the script.
If there is something about that script that you don't understand, don't panic! Try looking back over the section you don't understand.

You may ask what the point of a function like this would be. Well, this function could be used if you were going to make a progress report for your script. A progress report is something that is usually added to every script that keeps track of what the script has done. For example, how many logs it has chopped, or how many fish it has caught.

If you successfully made the latter script, when you hit run, your debug box should say this:

We have chopped 250 logs this session!
We want to chop 500 logs.
We are chopping Magic trees!
We have gained 48875 xp this session!
We are very bored chopping all these logs!
What are we going to do now?
Successfully executed

Congratulations! You have just made your first working script! Yay! :D

Standards:

A simple definition of standards is the way you write your code. Having good standards is extremely useful for debugging and readability. Anyone that reads your script will thank you for having good standards. I urge you to develop good standards as soon as you start scripting, so you get used to it faster, and don't have to change the way you code later.

There are many different rules you should follow when writing your code. They are as follows:
  1. When you intent, it will be two spaces. You can do this by hitting the "Tab" button on your keyboard, or simply hitting the space bar twice.
  2. Your script margins are set to 80 characters and is marked in SCAR with a line straight down the right side of the scripting page. Try not to exceed that margin.
  3. The begin statement appears on its own line, and end statement always matches the begin statement by columns. For example:

  4. begin
    if Condition then//Notice the intent after a "begin" statement.
    begin//Notice how the begin lines up with "if" in columns.
    DoThis;
    end else
    begin
    DoThis;
    end;
    end;
    Notice how all the begins and ends line up in columns. Also, you're probably wondering what the "if Condition then" is. Well, don't panic, it's called an if..then..else statement, and you'll learn more on that later. But, notice how the begin after the if..then..else statement is lined up with "if" in columns. Most people make the mistake of intending the "begin" after an if..then..else statement, which makes their code harder to read.
  5. Try not to combine two or more statements on one line. Each statement gets it's own line.
  6. Use semicolons at the end of all your lines. Exceptions would be at the end of var, begin, then, else, repeat, do and before else (see the above example if you don't know what I mean).
  7. Always use spaces after commas and arithmetical signs. This is also a common mistake with most scripts, and it really bugs me when people don't do this. It makes the script much harder to read without the spaces. Here is an example:

  8. I := (5 * 4 + 3);
    HowManyLogs(1, 5, 10);
  9. You should never have a white space on the inside of parenthesis. Example:

  10. if (I = 100) or (K = 50) then
    DoThis(DoThis);
  11. SCAR bolds keywords such as "begin, end, procedure, function, etc." These words should be entirely lowercase as it looks much better. :)
  12. The names of procedures and functions should always begin with a capital letter and be camel-capped for easier readability. Example:

  13. procedure WalkToBank;
  14. The names of procedures/functions/variables/constants should be given names meaningful to their content. A name like DoStuff is not meaningful, but name WalkToBank is. This includes a function's parameters (see below for explanation on parameters).
  15. Where possible, parameters/variables of the same type should be combined into one statement. For example:

  16. var
    Logs, Ores, Fish : Integer;

    function WalkToBank(I, J, K : Integer; L, M, N : String): Boolean;
    //The "(I, J, K : Integer; L, M, N : String)" are called the "parameters" of the procedure/function.
  17. Boolean variable names must be descriptive enough so that their meanings of True and False values will be clear.
  18. When you declare a variable, they are put on the next line after the var statement, and are indented. Example:

  19. var
    Logs : Integer;
  20. Try to declare variables locally as much as possible to avoid confusion within the script.

There, you should now have a good knowledge of SCAR standards, and have no excuses for unreadable code. :D For a more in depth look on standards, take a look at this useful thread -> SCAR Script Official Standards.

Scripting Tips/Hints:

In this section of the tutorial, you will learn independent ways of answering your scripting questions, so you don't have to post on the forums. You will learn how to utilize SCAR so that you can script faster and more efficient.

Built-In Functions List:

As you learn to script, there will be countless times when you'll ask yourself, "Is there a function that will do this?", "Is there a procedure that will do that?". Well SCAR/SRL has a lot of built in functions and procedures, chances are there is one that does what you want.

When you open SCAR, click the mouse on a blank line and hit Ctrl + Space. A list of all the functions you can use should come up. However, the list is extremely long, and it would take forever to scroll through, examining each part. So, as you start typing something, the list will get smaller and only show the functions/procedures that begin with what you typed. For example, if I wanted to find a color, but I didn't know what to use, I would type:

function FindColor
And hit Ctrl + Space, and a list should come up, looking like this:



Notice how it shows all the possible functions/procedures that start with "FindColor". It also shows that function's parameters, so you know what to include when calling that function. Pretty nifty, huh? :rolleyes:

The SCAR Manual:

Now, if you use the built-in functions list, chances are you will see something, and have no idea what it does. This is what the SCAR Manual, and the SCAR Online Manual is for.

To open:
  • The SCAR Manual, all you have to do is hit F1, while SCAR is open.
  • The Online Manual, Ctrl + F1.

The SCAR Manual is a very large manual, you will want to search for what you want. You can do this simply by hitting Ctrl + F and type in what you are looking for. The Online Manual is also very large, but it is written in a format made for easy navigation. Just navigate to the page you want, and you're good to go. :)

Each procedure/function is described with it's parameters, and a brief description of what it does. For example:
function FindColor(var x, y: Integer; color, xs, ys, xe, ye: Integer): Boolean;
Find color in box specified by xs, ys, xe, ye starting from left to right. Returns True if color found, the coordinates of the color if found is put in x,y.


Now you know how to use the SCAR Manual. You should search through this to find what you're looking for. Only if you can't find it, should you post on the forums. :)

Hotkeys:

Hotkeys are very simple to understand. They are just keyboard shortcuts that allow you to do certain things in SCAR. For example: F1 is a hotkey to open the SCAR Manual.

Useful hotkeys:

  • Run -> Ctrl + Alt + R
  • Pause -> Ctrl + Alt + A
  • Stop -> Ctrl + Alt + S
  • Pick color -> Ctrl + Alt + P
  • Add Tab -> Ctrl + T
  • Save -> Ctrl + S

That is just a list of the most useful hotkeys. To find out what other hotkeys SCAR has, just look through the different pull-down menus in SCAR. By pull-down menus I mean:


The "Tab" Button:

As you continue scripting, the tab button will become your best friend. It allows you to move multiple lines of code incredibly fast. It also can indent a line a million spaces if needed.

Example a is taken directly from Macro_FTW's tutorial, as I really like how he explained it (It's not it quote tags because I didn't like how it looked).

"a) Getting 'up to speed'. If your current line is at an indent of 2 spaces, and it's supposed to be at 10 spaces, have no fear. You don't need to spam the space bar multiple times; the tab button brings your indent to the nearest indent in the current procedure that is greater than your current one. So, if I had the most incorrectly formatted [procedure/function] possible:

procedure MiniMethod;
begin
writeln('hi');
if(2<9)then
begin
writeln('I write good.');
end;
If you wanted to get Writeln('I write good'); flush with begin, then you would tab three times (the first [tab would be flush] with if(2<9)then, second [would be flush with] Writeln('Hi'), [and the third flush with] begin), as opposed to spamming the "space" key like a squirrel on caffeine. No offense intended to the squirrels of the world." (Macro_FTW)

b) Probably the most useful aspect of the tab button is the fact that you can move 100s of lines of code all at once. Nothing feels worse than when you need to move 300 lines of code ahead 2 spaces and you hit the space bar twice at every line. Say I want to move this code ahead two spaces to squire proper standards:

procedure HelloWorld;
begin
Writeln('Hello world!');
Wait(500);
Writeln('How is the world doing today?');
Wait(500);
end;
I would highlight the code in between the begin..end nest and hit Tab. My code now looks like this:

procedure HelloWorld;
begin
Writeln('Hello world!');
Wait(500);
Writeln('How is the world doing today?');
Wait(500);
end;
See? Doesn't that look much better? :) Now, Tab moves the code ahead two spaces, but what if you want to move your code back two spaces? Well, this can be achieved by highlighting the code you want to move, and hitting Shift + Tab. Try it yourself.

Just use these simple tips and you'll learn more, faster. Again, only post on the forums as a last resort. You learn much more if you look for things yourself! For a little more in-depth tutorial on scripting shortcuts see -> Not-so-well known SCAR shortcuts.

SCAR Statements:

If..Then..Else Statements:

If..Then..Else statements are what make scripts, scripts. They can perform checks to make sure the script is doing what it's suppose to do, and if it's on the wrong course, do something else to correct the course. Here is a small breakdown of an if..then..else statement:

if Condition then//Condition can be any variable check, i.e. Boolean, integer, string, extended.
begin//Notice the 'begin' after the 'if..then'. This is ALWAYS needed if you are going to perform more than 1 action.
Action1;
Action2;
end else//'end' ends Action1/Action2. 'else' means it will do Action3/Action4 IF the Condition is not true.
begin
Action3;
Action4;
end;

if Condition then
Action1//Notice there is no ';' and no 'begin'. Neither are needed if you are performing ONLY 1 action after an if..then statement. If you put a ';' it will result in an "Identifier expected" error.
else//Notice that there's no 'end', that's because there's no 'begin' we have to end.
Action2;
Now that is a pretty simple example, but you should understand how to write an if..then..else statement. Here is a little more complicated example that actually does something:


program IfThenElseTutorial;

function IfThenElse: Boolean;
var
i : Integer;
e : Extended;
begin
Result := True;
i := 15;
e := 45.5;
if Result then
Writeln('Result is true!')
else
Writeln('Result is false.');

if (i = 10) then
begin
Wait(500);
Writeln('i = 10');
end else
begin
Wait(500);
Writeln('i <> 10, it = ' + IntToStr(i) + '.')//Remember "IntToStr" from earlier?
end;

if (i = 15) and (e = 45.5) then//'and' means both conditions must be met.
begin
Wait(500);
Writeln('i + e = ' + FloatToStr(i + e));//Remember "FloadToStr" from earlier?
end else
Writeln('i <> 15 or e <> 45.5');
end;

begin
IfThenElse;
end.
I know that looks like a lot, but examine it line by line. If some part of that is confusing, just look back over that section of the tutorial, or break down the script into sections. If you successfully wrote this script, when you press run, your debug box should read:

Result is true!
i <> 10, it = 15.
i + e = 60.5
Successfully executed


There, it's not so hard, is it? Try playing around with the variables to get a visual of what exactly if..then..else statements do. You now fully understand what an if..then..else statement is and how to use them! :)

Cases:

Cases are used for a more efficient way of writing long and confusing code. Here is a simple breakdown of a case:

case Condition of//Like if..then..else statements, Condition can be any variable.
Option1 : begin//Notice the begin..end nest for more than 1 Action, just like an if..then..else statement.
Action1;
Action2;
end;
Option2 : Action3;//Notice a begin..end nest is not needed because it is only one action.
else
Action4;//If the Condition is not true, it will do Action4, just line an if..then..else statement.
end;
Here is an example of the long and confusing code I was talking about. Be sure to not skip over this little bit as there is something new in the script. :p

procedure WhichSport(Sport : String);//Notice the parameter I added so I can call different "Sports" later on.
begin
if Lowercase(Sport) = 'hockey' then
Writeln('The sport is ' + Sport + '.');
if Lowercase(Sport) = 'soccer' then
Writeln('The sport is ' + Sport + '.');
if Lowercase(Sport) = 'basketball' then
Writeln('The sport is ' + Sport + '.');
if Lowercase(Sport) = 'baseball' then
Writeln('The sport is ' + Sport + '.');
if Lowercase(Sport) = 'rugby' then
Writeln('The sport is ' + Sport + '.');
if Lowercase(Sport) = 'football' then
Writeln('The sport is ' + Sport + '.');
end;

begin
WhichSport('Hockey');//Notice how I called the procedure with the parameter I made. It can be whichever sport you want.
end.
You are probably wondering what "Lowercase" is. Well…
From: SCAR Manual

function Lowercase(s: string): string;
Returns the specified string in lowercase.

This means that if you set the Sport parameter as 'hOcKeY', it will still recognize it as 'hockey'. This is handy to use in parts of your script that other people will fill out, such as DeclarePlayers(more on that later), because no matter how they write it, the script will still run.

Now, the above script is not very pretty is it? It's also very difficult to read. So, we use a case, which would make the procedure look like this:

procedure WhichSport(Sport : String);
begin
case Lowercase(Sport) of
'hockey': Writeln('HOCKEY!');
'soccer': Writeln('SOCCER!');
'basketball': Writeln('BASKETBALL!');
'baseball': Writeln('BASEBALL');
'rugby': Writeln('RUGBY!');
'football': Writeln('FOOTBALL!');
else
Writeln('Sport is not in the selection!');
end;
end;

begin
WhichSport('HoCkEy');//Notice how I spelled "hockey" with capital letters. It is still recognized as "hockey".
end.
Using a case not only makes your code look better, but it shortens it up quite a bit. I suggest playing with the variable Sport, so you get a better understanding of cases. Now, if you successfully made that script, when you hit run, the debug box should read:

Successfully compiled (51 ms)
HOCKEY!
Successfully executed


Congratulations! You now know how to use a case to make your code shorter, more efficient, and and look better!

Loops:

Using loops effectively can make or break a script, whether it is for RuneScape or any other program. In SCAR, there are three different types of loops:
  • Repeat..Until
  • While..Do
  • For..To..Do
Now, I'm guessing you have no idea what those are, but don't worry, they will be explained below.

Internal Commands:

From: Nava2
It is important to remember, that with ALL LOOPS, they will continue till they are done if they are not told to stop. That is why they are called Loops, they repeat.


Thanks Nava for that awesome little explanation. Now, there will be times that a condition is met or not met and you want the loop to break, continue, or exit, hence the three internal loop commands:
  1. Break;
    • The Break; command is probably the command you will be using most as when it is called, it "breaks" out of the loop and continues with the script.
  2. Continue;
    • Continue is a useful command when used properly. When called, it stops the loop where it is and continues from the beginning of the loop.
  3. Exit;
    • Exit is most commonly used in loops, but can be used otherwise. When called, Exit exits out of the loop and the procedure/function, and continues along with the script.

These commands are especially useful because they prevent the cause of what we call "endless loops". Nothing looks more like autoing then when your character is standing in the same place repeating the same thing over and over again, accomplishing nothing.

Repeat..Until:

Repeat..Until loops are the easiest loop to understand and use, and will be used many times throughout your scripts. What it does is pretty straight forward - it repeats and action until it is told to stop. Simple as that. Here is a simple breakdown of the loop:

repeat//The 'repeat' acts like a 'begin', so 'begin' is not needed after 'repeat'.
Action1;//A repeat..until loop can have as many different Actions in them as needed.
Action2;
until(Condition(s));{The 'until' acts like an 'end', so 'end' is not needed before 'until'.
You can have more than one Condition. Each condition is usually separated by 'and'/'or'.}
Here is a nice, simple example that clearly shows what a repeat..until loop is all about:

procedure RepeatExample;
var
NumOfWaits : Integer;
begin//Although 'repeat' acts like a 'begin', 'begin' is still needed here to signal the start of the procedure.
repeat
Wait(500);
Inc(NumOfWaits);//Here's something new. 'Inc();' simply adds 1 to the NumOfWaits variable. If you don't understand, you will once you run the script. :)
Writeln('We have waited ' + IntToStr(NumOfWaits) + ' times.');
until(NumOfWaits = 5);//When the script waits 5 times, it will stop.
end;

begin
ClearDebug;
RepeatExample;
end.
Pretty simple, no? The more you script, the more uses you will find for repeat..until loops, and the better you will get with them. If you successfully made the above script, your debug box should look something like this:
We have waited 1 times.
We have waited 2 times.
We have waited 3 times.
We have waited 4 times.
We have waited 5 times.
Successfully executed

Congratulations, you have learned what repeat..until loop is, and how to use it! An example of a time where you could use a repeat..until loop is when opening a bank. You can repeatedly try to open the bank until your character has logged out, or it has tried more than 10 times.

While..Do:

While..Do loops act almost exactly the same as repeat..until loops, only they are set up differently. The difference is that repeat..until loops will execute the command at least once, no matter what, whereas a while..do loop may not execute the command at all. To be honest, it doesn't really matter which one you use. They do basically the same thing, and as you become more experienced in scripting, you will know when to use which statement. If at some point in your script you use both statements, it shows everyone that you know a little more. Here is a simple breakdown of the loop:

while Opposite(Condition) do//For a while..do loop, you have to set the Condition to the OPPOSITE of what you want.
begin//Again, notice the begin/end for more than one action.
Action1;
Action2;
end;

while Opposite(Condition) do
Action1;//Again, since it's only one Action, no begin..end nest is needed.
Here is an easy example, that should clearly show you how to use a while..do loop.

procedure WhileDoExample;
var
Count : Integer;
begin
while (Count <> 5) do//See how the condition is the opposite of what you want? You want the script to end when Count = 5, so while Count doesn't equal 5, do this.
begin
Inc(Count);
Wait(500);
Writeln('The count is ' + IntToStr(Count) + '.');
end;
end;

begin
ClearDebug;
WhileDoExample;
end.
In my opinion, a while..do loop is slightly more advanced than a repeat..until loop, simply because it is a little shorter, and requires some thinking to come up with the opposite condition. If you wrote the above example properly, when you press run, your debug box should look like this:
Successfully compiled (48 ms)
The count is 1.
The count is 2.
The count is 3.
The count is 4.
The count is 5.
Successfully executed

Well there you go, you now know how to effectively use a while..do loop. A while..do loop is most commonly used in woodcutting scripts. It is set up so while your character is chopping, the script does some AntiBan. :eek: AntiBan? What's that? Don't worry, you will learn all about AntiBan later.

For..To..Do:

For..To..Do loops are the most complicated of the three loops, and can be used in the simplest functions, as well as the most advanced functions. Here is a simple breakdown of the loop:

for (Var Assignment/Start Integer) to (Finsih Integer) do //For..To..Do loops increase the variable integer by one each time through the loop.
begin
Action1;
Action2;
end;

for (Var Assignment/Start Integer) to (Finish Integer) do
Action1;
Confused? If so, examine this little example carefully, and you should understand the basis of For..To..Do loops.

procedure ForToDoExample;
var
i : Integer;
begin
for i := 0 to 5 do//Notice the assignment mentioned earlier? The assignment is the ":=".
begin
Wait(500);
Writeln('The variable i = ' + IntToStr(i) + '.');
end;
end;

begin
ClearDebug;
ForToDoExample;
end.
The same type of procedure can be written using both repeat..until and while..do loops. However, for..to..do loops are much more advanced and makes for a faster script. If you managed to understand for..to..do loops, you are well on your way to becoming an awesome scripter. Successfully writing the above script results in the debug box looking like this:
The variable i = 0.
The variable i = 1.
The variable i = 2.
The variable i = 3.
The variable i = 4.
The variable i = 5.
Successfully executed

If you made it through that, well done! If not, re-read the parts you don't understand because there is no point in moving on to more advanced material if you don't understand the basics.

Putting it all Together:

In this section of the tutorial, you will learn how to make a script using all the different SCAR statements, including having some statements inside other statements. Exciting, no? In this example, I have combined all the different types of statements. Be sure to examine it carefully and make sure you understand everything you are reading:

program PuttingItAllTogether;

var//Remeber declaring a var globally so it can be used in any function/procedure.
Times : Integer;

procedure AllStatements;
var//Remember to declare variables locally whenever possible.
i, ii : Integer;
e : Extended;
b : Boolean;
s : String;
begin
for i := 0 to 3 do
begin
Writeln('');//This just puts a space in the debug box, so the result doesn't look so messy.
Writeln('When i = ' + IntToStr(i) + '...');
case i of
1: e := 5.5;
2: begin
Wait(500);
s := ' Isn''t this a good example? =P';
end;
3: b := True;
else
Writeln(' The value of i is not in the case.');//This line will come in the debug box when i = 0 because '0' is not set in the case.
end;

if (i = 3) then
Writeln(s);//Because I have (i = 3), it will only Writeln(s); when i is equal to 3.

if (e = 5.5) then
Writeln(' The value of e = 5.5.')
else
Writeln(' The value of e <> 5.5.');//Since e is assinged a variable when i = 1, it will Writeln this line until i is 1.

if b then
Writeln(' Boolean is true!')//Since the boolean isn't assigned to true until i = 3, it is automatically set to false, unless told otherwise.
else
Writeln(' Boolean is false.');

while (ii < 2) and (i > 2) do//Because I have (i > 2) it will only do this part when i = 3.
begin
Wait(500);
Inc(ii);
Writeln(' The value of ii = ' + IntToStr(ii) + '.');
end;
end;
end;

begin
ClearDebug;
repeat
AllStatements;
Inc(Times);
until(Times >= 2);//Because you repeated the procedure twice, you should get the same text in the debug box twice.
end.
I know that looks like a lot, and most likely it will be confusing to you, but don't give up. If there is something you don't understand, look back to that section of the tutorial. Remember that you have to be patient when learning how to script, you aren't going to understand everything the first time, just ask Nava about what I was like when I first started scripting. ;)

If you understand the above script, and managed to write it successfully, when you hit run, the debug box should get spammed by a bunch of words. When finished, it should look like this:

When i = 0...
The value of i is not in the case.
The value of e <> 5.5.
Boolean is false.

When i = 1...
The value of e = 5.5.
Boolean is false.

When i = 2...
The value of e = 5.5.
Boolean is false.

When i = 3...
Isn't this a good example? =P
The value of e = 5.5.
Boolean is true!
The value of ii = 1.
The value of ii = 2.

When i = 0...
The value of i is not in the case.
The value of e <> 5.5.
Boolean is false.

When i = 1...
The value of e = 5.5.
Boolean is false.

When i = 2...
The value of e = 5.5.
Boolean is false.

When i = 3...
Isn't this a good example? =P
The value of e = 5.5.
Boolean is true!
The value of ii = 1.
The value of ii = 2.
Successfully executed
Congratulations! You now know the basics of scripting in SCAR. You now have enough knowledge of SCAR for me to introduce you to what it takes to make a working RuneScape macro. For a more detailed tutorial on the many statements in SCAR, visit -> Guide on the Many Statements in SCAR!

DeclarePlayers:

The first thing you should know about making script run for RuneScape is about the DeclarePlayers. DeclarePlayers is where you set up your RuneScape account. For example, the username, password, how many logs to cut, how many loads to bank. Obviously those are just a few examples, but the possibilities are endless.

Now, remember at the start of the guide when I said you needed to download SRL properly? Well here is why… SRL is comprised of all sorts of functions available for you to use. Each of them make it easier for autoing in RuneScape. In order to use these handy functions, you have to include SRL in your script.

program New;
{.include SRL\SRL.scar}//Be sure to add this to ALL your scripts!

begin
SetupSRL;//You also have to call this in your mainloop.
end.
There, now you can use any functions in the SRL folder without problems. :) Declare players is usually set up something like this:

program DeclarePlayers;
{.include SRL\SRL.scar}

procedure DeclarePlayers;
begin
HowManyPlayers := 1;//Change this if you have more than one player, this requires the script to have multiplayer. (More on that later ;))
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0;//Means the player you want to start with.

Players[0].Name := '';
Players[0].Pass := '';
Players[0].Nick := '';
Players[0].Active := True;//Use this player?
Players[0].Pin := '';//Bank pin. Leave blank if you don't have one.
Players[0].Integers[0] := 1000;//Ores to mine?
Players[0].Strings[1] := 'iron';//Which ore to mine?
end;

begin
ClearDebug;
SetupSRL;
DeclarePlayers;//Calls the procedure.
LoginPlayer;//Logs your player into the game.
end.
Not to difficult, is it?

Now, to make your DeclarePlayers look better and more advanced, it can be written using a with..do statement. A with..do statement is explained in the the "For the Advanced" part of this tutorial, as it includes some advanced techniques, but all you need to know for now is what I did to get from the above procedure to this procedure:

program DeclarePlayers;
{.include SRL\SRL.scar}

procedure DeclarePlayers;
begin
HowManyPlayers := 1;
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0;

with Players[0] do
begin
Name := '';
Pass := '';
Nick := '';
Active := True;
Pin := '';
Integers[0] := 1000;//These can be anything you wish to impliment into your script.
Strings[1] := 'iron';
Booleans[1] := True;
end;
end;

begin
ClearDebug;
SetupSRL;
DeclarePlayers;//Calls the procedure.
LoginPlayer;//Logs your player into the game.
end.
Doesn't that look much better? Do you understand how I used the with..do statement? Wonderful! Since you now have a DeclarePlayers procedure, lets make our player log in, shall we? Fill out the DeclarePlayers accordingly (with your username/password/nickname), drag your crosshairs onto the RS window, and hit play! Your player should login, then the script should execute.

Congratulations! You now know how to login a player using SCAR!

Failsafes:

Failsafes are an essential in ALL scripts made for RuneScape. Failsafes are what make the script last for hours without error. Failsafes are made using if..then..else statements. Basically, failsafes work like this:

if Condition1 then
Action1//Notice there is no semicolon because it's only one action, followed by an 'else' statement. Remember?
else
if Condition2 then
Action2
else
if Condition3 then
Action3
else
if Condition4 then
Action4;//See how there is a semicolon now because it is not followed by an 'else' statement.
See how there is always another procedure or "failsafe" to run if the one before it fails. The chances of all four procedures failing isn't very high, hence why some scripts can run for hours - they have awesome failsafes!

Now, before you rush ahead and read the next example, there are a few things I need to explain that will be in the example. If you looked at it already, you probably asked yourself "MSX1? What's that?". Well those variables are the box in which you are searching for the color specified in FindColor. There are four different boxes that have been made and implemented into SRL for your scripting convenience. They are as follows:
  1. MS - Main Screen - The main RuneScape playing screen.
  2. MM - MiniMap - The RuneScape minimap in the top right corner of the RS screen.
  3. MI - Main Inventory - You inventory box on the right of the RS window, below the minimap.
  4. MC - Main Chat - The RS Chat box at the bottom on the RS window.
Now, to search in one of these boxes, all you have to do is write the two letters, followed by X1, Y1, X2, Y2. If you don't understand, you will after you read this example:

program Failsafes;
{.include SRL/SRL.scar}

procedure FailsafeExample;
var
x, y : Integer;
begin
if FindColor(x, y, 2167538, MSX1, MSY1, MSX2, MSY2) then//If the color (2167538) is found, the coordinates of where it was found is stored in the variables (x, y).
MMouse(x, y, 4, 4)//Moves the mouse to x, y. The 4, 4, is the randomness of where the mouse moves because no person can move the mouse to the exact same spot every time. =P
else
begin
Wait(1000);//Remember 1000ms = 1s.
Writeln('First FindColor failed, trying second...');
if FindColor(x, y, 3652378, MMX1, MMY1, MMX2, MMY2) then
Mouse(x, y, 4, 4, True)//This moves AND left clicks the mouse with randomness 4, 4. If you set 'True' to 'False' is would right click the mouse.
else
begin
Wait(1000);
Writeln('Second FindColor failed, trying third...');
if FindColor(x, y, 4981245, MIX1, MIY1, MIX2, MIY2) then
MMouse(x, y, 4, 4)
else
begin
Wait(1000);
Writeln('Third FindColor failed, trying forth...');
if FindColor(x, y, 6478356, MCX1, MCY1, MCX2, MCY2) then
Mouse(x, y, 4, 4, True)
else
begin
Wait(1000);
Writeln('Forth FindColors failed, logging out.');
Logout;//This is pretty straight forward, it logs your player out.
end;
end;
end;
end;
end;//There are so many 'end's because each begin has to have an end, otherwise you will get an "Identifier expected..." error.

begin
ClearDebug;
FailsafeExample;
end.
Now, I made that example to purposely fail, so you would get the idea of how a failsafe works. Do you understand what they do? Do you understand how to move the mouse, how to click the mouse? Do you understand how to declare which box you want to look in? If you successfully wrote the above script, when you hit play, the debug box should read:
First FindColor failed, trying second…
Second FindColor failed, trying third…
Third FindColor failed, trying forth…
Forth FindColors failed, logging out.
Successfully executed


Excellent! You are now finished learning all about failsafes.

Antiban and AntiRandoms:

Antiban and AntiRandoms are also an essential to ALL RuneScape scripts. The definitions should be pretty straight forward, but I'll explain them anyhow.
  • Antiban - Procedures/functions that prevent your character from getting banned. Antiban makes your character look more "human-like".
  • AntiRandoms - Procedures/Functions that solve the many RuneScape random events. Don't panic! All the solvable random events are already implimented into SRL. The part you have to do to make your script solve random events is actually very simple.

Antiban:

Almost all Antiban procedures are made using a case statement. There are also several antiban procedures already in SRL. All we have to do is put a few of them together, and away we are.

First, I want you to go to your SRL folder and open Antiban.scar (Includes/SRL/SRL/core/Antiban.scar). See how there are several antiban procedures? If you want to know what they do, click the one you want on the functions list, scroll up a bit, and you will see a description of the procedure, and how to use it. Here is an example of a typical antiban procedure:

procedure Antiban;
begin
case Random(70) of//Random(80) generates a random integer from 0 to 70.
0: RandomRClick;
1: HoverSkill(Skill: String; Click: Boolean);
2: PickUpMouse;
3: SayCurrentLevels(Which: String);
4: RandomMovement;
5: BoredHuman;
6: ExamineInv;
end;{The reason I used Random(70), even though there are only 7 antiban procedures is because if you antiban too much,
you will look like a bot. You want to antiban approx. once every ten times it is called}
end;
Antiban procedures can be as basic or as advanced as you want them. The more advanced, the better, obviously. Everytime the above procedure is called in your script, if the result from Random(80) equals 0-6, then it will do the corresponding antiban procedure. Neat, huh?

AntiRandoms:

Knowing the definition, I'm sure you are thinking it's going to be extremely difficult to implement random event solving in your script. Well, you thought wrong. :p It is actually very, very simple. The first thing you should do is add this little piece of code to you DeclarePlayers procedure:

Players[0].BoxRewards := ['Xp', 'mote', 'ostume', 'oins', 'aphire', 'ssence'];
{Any other rewards can easily be added. This line will randomly choose one of the options when a reward box is opened. The 'Xp' option is the option to get a gene lamp.
If you are wondering why there is '' around each option, it is because they are strings, and that's how strings are declared, remember? Also, a positive to having that in your DeclarePlayers procedure is that the user of the script can choose different rewards for different players. Now, on to what we need to write as a procedure. Here is an example of a common AntiRandoms procedure and when it may be called:

procedure AntiRandoms;
begin
FindNormalRandoms;//Everytime this is called, SCAR will search to see if your character is inside a random event room.
LampSkill := 'woodcutting';//If you set the script to choose an experience lamp from a random event box, it will use the exp on the woddcutting skill.
end;

procedure ChopTrees;
begin
//Chopping trees code here.
while IsChopping do//IsChopping isn't an actual function, it is one I made up for this example, so don't go try using it in one of your scripts. ;)
begin
Antiban;//This is an example of when you would call an antiban procedure.
AntiRandoms;//Call AntiRandoms while your character is chopping down a tree.
end;
end;
See? I bet that's much easier than you expected. So basically, while your character is hacking away at a tree, the script will continually search for random events, so if you happen to end up in one, the script can solve it without problems. I highly recommend you put FindNormalRandoms is almost all of your procedures so that no matter where you get sucked into a random event, your script can still solve it.

If you have made it his far and understand everything I've taught you so far, congratulations! You now know all the basics to SCAR and what it takes to make a working script for RuneScape. Before moving on, I would suggest playing around with the different elements of SCAR you have learned so far, just so you get a better feel of what it's all about. Now, move on to the "For the Intermediate" section of the tutorial… or are you scared? :rolleyes:

Coh3n

2009-08-21 04:19:52

Back To Top

4. For the Intermediate:

In this section of the tutorial you will learn many different things about SCAR and making a working RuneScape scripts. You will learn this such as arrays, item finding, walking in RS, object finding, and many more! Since you already know all of the basics to SCAR, this part of the tutorial should be a lot easier to understand. Thank goodness, eh?

Basic Arrays:

Arrays are an extremely useful way of coding that makes your scripts work efficiently while keeping them looking neat and tidy. There are two types of arrays:
  • Static - the length or the array cannot be changed throughout your script.
  • Dynamic - the length of the array can be changed as many times as you wish.
Like any other variable, arrays must be declared globally or locally. Different types of arrays are declared differently.

Static:

Again, static arrays are static because the length remains constant throughout the whole script. Here is how a static array is declared:

var
Logs : Array[1..10] of Integer;//Notice how the array is of integers. Arrays can be of any variable you wish.
The "[1..10]" is called the "array range" or "array length". This means that there will be 10 parts in the array. Just like if I said Array[1..100] there would be 100 parts in the array. Simple, no?

Dynamic:

Dynamic arrays are dynamic because the length can be changed multiple times throughout your script with a simple little command. Dynamic arrays are declared like this:
var
Logs : Array of String;
Remember how I said the length can be changed with a simple command? Well, before you use a dynamic array, you need to set the length. You can set the length by using this simple command:

SetArrayLength(Logs, 10);//Notice the first parameter is the name of the array, and the second parameter is the length.
If you wanted to use the array again later in the script with a different length, all you would have to say is:

SetArrayLength(Logs, 15);
That's not too difficult, is it? So now you know what the two different types of arrays are and how to declare them. But, how do we use them?

Using Arrays:

Using arrays is a simple concept, and since you are an intermediate scripter now, you should be able to understand it no problem. :D Here is a simple breakdown of an array:

var
NameOfArray : Array[Start Integer..Finish Enteger] of Variable;//Variable can be anything you want. (i.e. integer, string, point.)
NameOfArray : Array of Variable;

begin
SetArrayLength(NameOfArray: Variant, Length: Integer);//For DYNAMIC arrays only! Variant simply means it can be any variable type.

NameOfArray[Start Integer] := Variant;//Variant is whatever you declared the array as. (i.e. if you said Array of Integer;, Variant would be an integer.)
NameOfArray[Finish Integer] := Variant;
end;
Not too difficult I hope. There is something you need to remember if you are working with dynamic arrays. The "Start Integer" ALWAYS starts at '0' and goes up. So if you set the array length to '1', the length would actually be 2 because it includes '0', understand?

If that breakdown seemed to be confusing, take a look at the following example, and you should understand arrays much better:

program Arrays;

procedure ArrayExample(TheArray: String);//Notice the parameter 'TheArray'.
var
Number : Array[0..4] of Integer;
Word : Array of String;
i : Integer;
begin
case Lowercase(TheArray) of//Depending on what you write for TheArray, it will do one of the 3 procedures. Remember learning that back in the beginner section?
'number': begin
Number[0] := 2645;//These numbers can be replaced with any number you wish.
Number[1] := 7482;
Number[2] := 1968;
Number[3] := 4357;
Number[4] := 5682;

for i := 0 to 2 do//Notice that it will only write the first 3 parts of the array.
begin
Wait(500);
Writeln('The number is ' + IntToStr(Number[i]) + '.');//Notice how it writes the number, depending on what you put for the parameter 'i'.
end;
end;

'word': begin
SetArrayLength(Word, 5);//Always be sure to set the array length with working with dynamic arrays.
Word[0] := 'Zero';//These words can be replaced with any word/sentence you wish.
Word[1] := 'One';
Word[2] := 'Two';
Word[3] := 'Three';
Word[4] := 'Four';

for i := 2 to 3 do
begin
Wait(500);
Writeln('The word is the number ' + Lowercase(Word[i]) + '.');
end;
end;
else
Writeln('TheArray is not in the case statement!');//You should always use an 'else' statement like this when working with cases.
end;
end;

begin
ClearDebug;
ArrayExample('Number');//Understand how to declare is properly, with the right number of parameters?
ArrayExample('Word');
Wait(500);
end.
You may have noticed I've added in different elements you learned in the beginner's section. I've done this so you will be introduced to different ways of using all the things you learned so far. I will be doing this for the rest of the tutorial, so be aware. :p If you successfully wrote the above script, when you hit run, the debug box should look something like this:
The number is 2645.
The number is 7482.
The number is 1968.
The word is the number two.
The word is the number three.
Successfully executed

There, you now know how to use arrays, excellent work! :D

Item Finding:

Now, this is the section where you will be learning a lot of different things at once, so take it slow, make sure you understand everything you're doing before moving on. From now until the end of the intermediate section, I will be using examples that actually work for RuneScape. Aren't you happy to hear that? :)

[BANANA]I can't stress this enough, before moving on, make sure your SRL is up to date, otherwise some of these example may not work. [/BANANA]


Item finding can be used for many different things such as checking if your character is wielding a hatchet, or to count how many logs you have in you inventory. There are many different ways of finding items in RS, but I'm going to be teaching you about the two most common and most accurate ways of doing it. There are two options you have:
  • Bitmaps
  • DTMs
In the newer versions of SCAR, Bitmaps are faster than DTMs, but often people find it easier to work with DTMs. The choice is yours.

Bitmaps:

Bitmaps are just pictures that SCAR can store as strings, so they can be used for whatever is needed. In RS scripting, Bitmaps are most commonly used to find items in your inventory, or in your bank. For my example, I'm going to show you how to make a bitmap of a Willow log, and click it in your inventory.

Before we actually make the Bitmap, we have to setup our script to load it properly. We can do this by making a function that loads the bitmap:

var
Logs : Integer;//Each bitmap is used like an integer, but they are stored as strings. Therefore we declare it as an integer.
//Also, we declare it globally so we can use it in other functions later on.

function LoadBitmaps: Integer;//Notice the function returns an integer. This is because bitmaps are integers, understand?
begin
Logs: Result :=//Bitmap here. You will learn what goes here shortly, don't worry. ;)
end;
Pretty simple I'd say.

Now what I want you to do is load RS and log into your RuneScape account. Make sure you have a Willow log in your inventory, and take a screenshot of your RS screen. If you don't know how to take a screenshot, follow these steps:
  • Find the "Print Screen" key on you keyboard. It is usually hiding in the upper right corner. One my keyboard it says "PrtSc".
  • Once you have found the key, open the window you wish to take a screenshot of. In this case, it would be the RS window.
  • Hit the key while the RS window is open, and there you go, you took a screenshot!
Once you have taken your screenshot, I want you to take the following steps to make your bitmap:
  1. Open SCAR.
  2. Go to Tools > Picture To String. A small window should come up called "Bitmap Loader".
  3. Hit "Paste", and the image of your RS screen will come up.
  4. Scroll to your inventory, so the Willow log is in view. Make the window larger if you have to.
  5. Click the "+" button (to the right of the "Mask Editor" button) 5 times to zoom in closer to the object. Make sure the Willow log is in view.
  6. Click and drag a small box (approx. 5 x 5 pixels) in the middle of the image of the Willow log.
  7. Name your bitmap in the space at the bottom of the window. You should now have a screen that looks something like this:
  8. [BANANA][/BANANA]
Click "Ok", and you should see something in your debug box that looks something like this (yours may be longer or shorter, depending on how big of box you made from the willow log):
  LogBMP := BitmapFromString(5, 5, 'beNpzkIzwVyAShfjIQUggCvCQ' + 
'9XGRtjUXc7KWACJ3B0l3AM9zEjg=');
Excellent! You successfully made your first bitmap! Now highlight and hit Ctrl + C to copy the bitmap from the debug box. Remember the function we made to load your bitmap? Well… paste your bitmap into that function. You should now have a function that looks like this:

function LoadBitmaps: Integer;
begin
LogBMP: Result := BitmapFromString(5, 5, 'beNpzkIzwVyAShfjIQUggCvCQ' +//Notice how I used the variable "Result".
'9XGRtjUXc7KWACJ3B0l3AM9zEjg=');
end;
Very simple. I would suggest using a function like that to load bitmaps, only of you have more than one bitmap, otherwise you can use the bitmap locally (like the the example to come).

There, you have learned how to make and load bitmaps. Easy. Now, loading the bitmap doesn't really do anything for anyone. So, we are going to make a script that will click the log in your inventory. Excited? Sorry, you will have to wait just a little longer. Darn, eh?

Before you can make the script, you need to know what function to use to find the bitmap, otherwise you will never find it. ;) Here is a list of the finding bitmap functions we will be working with, straight from the SCAR Manual:
function FindBitmap(Bitmap: Integer; var x, y: Integer): Boolean;
Search for the bitmap in client window. If found coordinates are returned in x,y. bitmap contains handle to bitmap generated by LoadBitmap.

function FindBitmapTolerance(Bitmap: Integer; var x, y: Integer; Tol: Integer): Boolean;
Works like FindBitmap but with a tolerance parameter for finding any similar colored bitmap. Tolerance is used to find a colored bitmap in range of the bitmap you are looking for. The greater color range you want, the higher the tolerance parameter should be.

function FindBitmapIn(Bitmap: Integer; var x, y: Integer; x1, y1, x2, y2: Integer): Boolean;
Search for the bitmap in coordinates specified by x1, y1, x2, y2. Bitmap contains handle to bitmap generated by LoadBitmap.

function FindBitmapToleranceIn(Bitmap: Integer; var x, y: Integer; x1, y1, x2, y2: Integer; Tol: Integer): Boolean;
Works like FindBitmapIn but with a tolerance parameter for finding any similar colored bitmap. Tolerance is used to find a colored bitmap in range of the bitmap you are looking for. The greater color range you want, the higher the tolerance parameter should be.

Each function finds a bitmap, but they all have different a element. I hope you can understand the difference between each of them without me having to explain them individually. I will, however, explain what is meant by Tol:
  • Tol or Tolerance is an integer (as you can see from the above explanations), and the higher the integer the wider range of colors SCAR is going to look for. For example, if I set the tolerance to 5, SCAR will find much less colors than if I was to set the tolerance to 15.

Since FindBitmapToleranceIn is the fastest and most accurate, we will use it to find the logs. The reason it is fast is because it will look for the bitmap in a specified box, instead of the whole screen. The reason it is more accurate is because you can adjust the tolerance, understand? Good. The following example will open your inventory, attempt to find the Willow log, and click it:

program ClickWillowLogs;
{.include SRL/SRL.scar}//Remember to include this in ALL of your scripts if you want to use functions from SRL.

function ClickLogs: Boolean;
var
Logs, x, y : Integer;{Declared locally this time because we are only using it in this function. :)
We also need to declare 'x, y' so that the coordinates of the bitmap can be stored in them}
begin
Logs := BitmapFromString(5, 5, 'beNpzkIzwVyAShfjIQUggCvCQ' +
'9XGRtjUXc7KWACJ3B0l3AM9zEjg=');
GameTab(tab_Inv);//GameTab stands for all the different tabs in the RS interface. "(tab_Inv)" clicks on the inventory tab. A full list of the gametabs can be found in Gametab.scar in your SRL folder.
if FindBitmapToleranceIn(Logs, x, y, MIX1, MIY1, MIX2, MIY2, 15) then//Remember that MI = Main Inventory.
begin
Writeln('Found Willow log bitmap!');
MMouse(x, y, 4, 4);//Moves the mouse to the bitmap. Remember MMouse from earlier?
if IsUpText('illow') then//Checks the uptext of the object. Uptext is the text in the upper left corner of the RS main screen.
begin
Wait(200 + Random(100));//You should always have a random wait after checking an uptext because the uptext doesn't appear at the millisecond you mouse over the object.
Mouse(x, y, 0, 0, True);//No randomness is needed because the mouse is already on the object.
Result := True;//Make the result true after it has clicked the logs.
end else
Writeln('Couldn''t find the correct uptext of the logs.');
end else
Writeln('Couldn''t find the log bitmap');
FreeBitmap(Logs);//You MUST include this line. This frees the bitmap, otherwise it will say loaded and make your script much slower.
end;

begin
ClearDebug;
SetupSRL;//Don't forget this line in ANY of your RS scripts!
ActivateClient;//This is needed so the script switches to the RS window. If you have a DeclarePlayers procedure, it is not needed, as it is already built in.
Wait(1000 + Random(500));//This is just in case of possible lag, that SCAR has time to switch to the RS client.
if ClickLogs then//The condition will be true if it clicks the log. See the connection between that and the actual function?
Writeln('We have clicked the Willow logs!')
else
Writeln('We have not clicked the Willow logs.');
end.
Before you anxiously run the script to see if it works, I highly recommend you read through it carefully and make sure you understand everything. Also before you press run, I would suggest the following:
  • Your character has to be logged in, otherwise it won't work.
  • Have a GameTab other than the inventory open, so you get a better idea of what the GameTab function does.
  • Close all unnecessary applications to prevent possible lag.
If you managed to write the above script without problems the script should switch to the RS client, open the inventory, and click on the Willow log, then stop, and your debug box should look something like this:
SRL Compiled in 15 msec
Found Willow log bitmap!
We have clicked the Willow logs!
Successfully executed


[BANANA]I can't stress this enough, make sure you ALWAYS free your bitmaps! Otherwise, it will slow your script/computer down tremendously![/BANANA]


Congratulations! You have successfully learned how to find and click items in RuneScape. Now that you understand how to use bitmaps, I suggest that you make a couple different bitmaps of different items to get a better feel of how to do them. Now, DTMs are used almost exactly the same as bitmaps. It's making them that is different.

DTMs:

DTM is an acronym for Deformable Template Model. Since SCAR has a built-in DTM editor, and every item in RS has a black outline, we can make DTMs very easily. Since in the Bitmap section of the tutorial, we learned how to click an item in the inventory, for this example, we will learn how to find a DTM of leather boots and withdraw a them from the bank. Sound good?

Like bitmaps, if you are going to use multiple DTMs, it is best to make a function that loads them:

var
Boots : Integer;

function LoadDTMs: Integer;
begin
Boots: Result :=//DTM here.
end;
Now I would like you to take another screenshot of your character with a pair of leather boots in the bank. Once you've taken the screenshot, I would like you to do the following:
  • Open SCAR.
  • Go to Tools > DTM Editor… A window should have popped up called "Deformable Template Model Editor".
  • Go to Edit > Paste Image. The screenshot you just took should come up.
  • Make the window bigger until you can see the Leather Boots.

Now you are ready to make your DTM. Follow these steps carefully to successfully make a DTM:
  1. Click on a part of the Leather Boots that is it's main color. In this case, the color would be brown. If you are not sure what color your mouse is on, look in the top left corner of the window for a zoomed in version of where your mouse is. This allows you to easily see which color you are on. After you click the color you want you should see a very small flashing dot where you clicked. This is going to be your main point.
  2. Now, click on 3-4 points on the black outline of the Leather Boots. Again, use the zoomed in image if you have to. The area around the Leather Boots should look something like this:


[BANANA][/BANANA]


Also, look in the top right of the window, you should see a box, with sets of numbers in it, like this:

[BANANA][/BANANA]


There are three numbers in each set. The first number is the x-coordinate of the color picked, the second number is the y-coordinate, and the third number is the color. The first set of numbers is your main point, and the remaining 3-4 sets are your sub points. The color you picked for each of your sub points should be exactly the same, 65536 (black). If they aren't, click on the set that has the different color and hit delete, and re-pick the point.

Once you have done this, you will see a whole list of things on the right side of the window. Do the following:
  1. Make sure the area size is 0. We will define this later.
  2. Set the tolerance to whatever you like, I usually use 15 for DTMs.
  3. Set the "Parent" to your main point. When it asks for the "Parent" it means the main color.
  4. It is up to you whether you save it or not. I recommend you do, in case you want to use it again later, then you don't have to remake it.
  5. Go to File > DTM To Text, and close the window. You should now see some code in the debug box that looks like this:
DTM := DTMFromString('78DA634C6362604865644006F6DA2A0CFC401' + 
'A24FA1F0818F3806AF250D540646124904E06AA2925A02604A8A6' +
'80809A44A09A684C35FC486A00608A08C5');
Looks a lot like a bitmap doesn't it? I told you they weren't very different. Like you did with the bitmap, copy and paste your DTM into your LoadDTM function. Now you know how to make and load a DTM, although loading should have been review as it is done the same way for bitmaps.

Unlike for bitmaps, there is only one function from the SCAR Manual you need to know to find your DTM:

function FindDTM(DTM: Integer; var x, y: Integer; x1, y1, x2, y2: Integer): Integer;
Use DTM to find object on client window. x1, y1, x2, y2 specifies box to search in, x, y returns coordinates if found.

Now I'm going to take you through an example that will withdraw the Leather Boots from your bank, and equip them. A lot of it will be similar to the bitmaps example, but there will be a few new functions you'll learn:

program DTMsExample;
program DTMsExample;
{.include SRL/SRL.scar}//Remember to include this in ALL of your scripts if you want to use functions from SRL.

function EquipBoots: Boolean;
var
Boots, x, y : Integer;//Again, declared locally. Remember why?
begin
Boots := DTMFromString('78DA634C6362604865644006F6DA2A0CFC401' +
'A24FA1F0818F3806AF250D540646124904E06AA2925A02604A8A6' +
'80809A44A09A684C35FC486A00608A08C5');
if FindDTM(Boots, x, y, MSX1, MSY1, MSX2, MSY2) then//Remember MS = Main Screen.
begin
Writeln('Found Leather Boots!');
MMouse(x, y, 4, 4);
if IsUpText('eather') then
begin
Wait(80 + Random(100));//Without this wait, it most likely won't find the uptext.
Mouse(x, y, 0, 0, False);//Remeber that "False" means it will right click.
if ChooseOption('5') then//ChooseOption is a useful function that when you right click on something in RS, it will choose the specified string option if available.}
begin
CloseWindow;//This will close the bank screen window.
Wait(200 + Random(100));
if FindDTM(Boots, x, y, MIX1, MIY1, MIX2, MIY2) then//Notice that the same DTM can be used to find it in the inventory.
begin
Mouse(x, y, 4, 4, True);//This will click on the boots again, equipping them.
Writeln('We have clicked the Leather Boots, checking to see if they are equipped...');
Wait(1000 + Random(500));//It's always good to have random waits in random places in your script.
GameTab(tab_Equip);//Opens the equipment gametab to check if the boots got equipped.
Result := FindDTM(Boots, x, y, MIX1, MIY1, MIX2, MIY2);//See how the Result is a boolean? It will be true if it chooses the correct option.
if Result then//Checks if the Result is true.
Logout//If it finds the boots equipped, it will logout.
else
begin
Writeln('Couldn''t find boots DTM in equiptment interface, logging out.');
Logout;
end;//Notice that if no matter what goes wrong, IF something goes wrong, it will tell me what went wrong, and log out.
end else
begin
Writeln('Couldn''t find boots DTM in inventory, logging out.');
Logout;
end;
end else
begin
Writeln('Couldn''t choose the option to withdraw 5, logging out...');
Logout;
end;
end else
begin
Writeln('Couldn''t find the uptext, loggin out.');
Logout;
end;
end else
begin
Writeln('Couldn''t find the boots DTM, logging out.');
end;
FreeDTM(Boots);//Remember to ALWAYS free your DTMs!
end;

begin
ClearDebug;
SetupSRL;//Don't forget this line in ANY of your RS scripts!
ActivateClient;
Wait(1000 + Random(500));
if EquipBoots then
Writeln('Boots are equipped! Logging out.')
else
begin
Writeln('Couldn''t equip the boots, loggin out...');
Logout;
end;
end.
You may think that looks like a lot at once, but if you read it carefully, you should already know most of it. I was just showing you that you can use the same DTM more than once in the same procedure, and look for it in different spots on the screen. That procedure can be written EXACTLY the same, but with bitmaps. If you are up for the challenge, give it a try. :D

Now before you anxiously rush and run the script, make sure you fully understand the script. Also before you run it, you have to do the following:
  • Make sure your character is logged in, has the bank screen open, and the Leather Boots visible in the bank.
  • Drag the SCAR cross hairs and select the RS window.
If you fully understood and wrote the above script, when you hit run, it should withdraw 5 pairs of boots, exit the bank screen, equip one of those pairs of boots, logout, and the debug box should read:

SRL Compiled in 15 msec
Found Leather Boots!
We have clicked the Leather Boots, checking to see if they are equipped…
Boots are equipped! Logging out.
Successfully executed


[BANANA]I can't stress this enough, make sure you ALWAYS free your DTMs! Otherwise, it will slow your script/computer down tremendously![/BANANA]


Congratulations! You now know how to make and use DTMs. You also learned how to click items, and withdraw them from the bank. Now, before moving on, I suggest you try and write a script that withdraws… let's say a couple pieces of armor… and equip them. That may seem hard, but it can easily be done with the elements you have learned so far I know you can do it!

Object Finding:

Object finding is a must in almost every script, as it is most commonly used to find objects on the main screen such as trees or mining rocks. Without some form of decent object finding, you can't expect your script to work for more than 5 minutes. I'm going to be teaching you about two different methods of object finding:
  • Using FindColor functions/procedures.
  • Using FindObject functions/procedures.
Once you get into more advanced FindColor functions, they are faster and more accurate than FindObject functions, in my opinion.

FindColor:

Using FindColor is pretty straight forward - SCAR attempts to find a specified color. For this example example, we are going to find and click a normal tree, sound fun? We will be working with the following four functions. Here is the list, straight from the SRL Manual:

function FindColor(var x, y: Integer; color, xs, ys, xe, ye:Integer): Boolean;
Find color in box specified by xs, ys, xe, ye starting from left to right. Returns True if color found, the coordinates of the color if found is put in x,y.

function FindColorTolerance(var x, y: Integer; color, xs, ys, xe, ye: Integer; Tolerance: Integer): Boolean;
Works like the regular FindColor function but with a tolerance parameter for finding any similar color. Tolerance is used to find a color in range of the color you are looking for. The greater color range you want, the higher the tolerance parameter should be.

function FindColorSpiral(var x, y: Integer; color, xs, ys, xe, ye: Integer): Boolean;
Find color in box specified by xs, ys, xe, ye but start from x,y.

function FindColorSpiralTolerance(var x, y: Integer; color, xs, ys, xe, ye: Integer; Tolerance: Integer): Boolean;
Works like the regular FindColorSpiral but with a tolerance parameter for finding any similar color. Tolerance is used to find a color in range of the color you are looking for. The greater color range you want, the higher the tolerance parameter should be.

Again, each function has something that is a little different, and if you read them carefully, it should be self explanatory. We are going to be using FindColorSpiralTolerance because it includes all the elements from all four functions. Now, in the descriptions above, it tells you the difference between FindColor and FindColorSpiral, but I'm going to give you another definition.
  • FindColorSpiral - In the definition above, it says… "but start from x, y". This means that SCAR will start searching for the color at the coordinates you specified for x and y. And the spiral means it will search in a spiral motion outward from x, y.
  • For example, if we wanted to search for a tree that is closest to our character, we would say something like this:

    var
    x, y : Integer;
    begin
    x := MSCX;
    y := MSCY;
    FindColorSpiral(x, y, Color, MSX1, MSY1, MSX2, MSY2);
    //*Note that this:
    FindColorSpiral(MSCX, MSCY, Color, MSX1, MSY1, MSX2, MSY2);
    //would not work, because FindColorSpiral requires variables, and MSCX/Y are constants. Therefore, we need to declare them as variables (x := MSCX).
    end;
There are two things you should know about the latter example:
  • MSC stands for Main Screen Center. This means that SCAR will search outward from the middle of the RS main screen. In other words, it will search starting from where your character is, so it will find the tree closest to your character first.
  • The parameter "Color" can be whatever color you picked using SCAR's color picker. If you don't know how to pick a color using SCAR, follow these steps:
    • Open up SCAR, and make the window about half the size of your monitor, and drag it to one side of the screen.
    • Do the same with your RS screen (or whichever screen you want to pick the color from), except move it to the opposite side of the screen that you moved SCAR too. You should have something that looks like this:
    • [BANANA][/BANANA]
    • Now, using the SCAR color picking icon:
    • [BANANA][/BANANA]
      Pick the color you want. Just click the icon, and then click on the color you want. After you click the color, is should pop up in your debug box:
      Color Picked: 1787389 at (1254, 302)
    • Now what you would do is copy and paste that color (1787389) into your FindColorProcedure, like so:

    • FindColorSpiral(x, y, 1787389, MSX1, MSY1, MSX2, MSY2);
      Not so hard, is it?
Now that you know how to pick the color, and how to start searching from the middle of the main screen, we are going to make a function that returns true, IF it finds and clicks a normal tree. Like I said earlier, we are going to use FindColorSpiralTolerance:

program FindColorExample;
{.include SRL/SRL.scar}

function ClickTree: Boolean;
var
x, y : Integer;
begin
if not LoggedIn then Exit;//This is a simple failsafe that will prevent your script from running if your character is not logged in. It should be included in ALL your procedures/functions.
x := MSCX;
y := MSCY;
if FindColorSpiralTolerance(x, y, 4685428, MSX1, MSY1, MSX2, MSY2, 10) then//Notice how the result will return true if it finds the color.
//*Note that you should pick a color from the tree that ISN'T too close to the grass color.
begin
Writeln('Found tree!');
MMouse(x, y, 4, 4);
Wait(200 + Random(100));//Remember to wait before checking the uptext.
if IsUpText('ree') then//Remember to not include the capital letter of the tree name.
begin
Mouse(x, y, 0, 0, True);
Result := True;
end else
Writeln('Couldn''t find the uptext of the tree.');
end else
Writeln('Couldn''t find the color of the tree.');
end;

begin
ClearDebug;
SetupSRL;
ActivateClient;
Wait(1000 + Random(500));//Remember you should give it time to activate the RS client.
if ClickTree then
Writeln('Clicked tree!')
else
Writeln('Didn''t click tree. :(');
end.
I know I've said this 100 times throughout this tutorial, but before you eagerly press run, make sure you understand what is going on. You also have to make sure that:
  • Your character is logged in, and has a normal tree within view.
  • Have a hatchet in your inventory or wielded if you actually want to chop down the tree.
  • You've dragged the crosshairs over the RS window.
If you wrote that script without problems, your debug box should read something like this:
SRL Compiled in 15 msec
Found tree!
Clicked tree!
Successfully executed

If you cannot get it to work, a common problem is that the color you have picked is simply not good, and you would have to repick the color. Congratulations, you have learned how to find objects in RS using FindColor functions. Before moving on, I would suggest you attempt to find some other objects, just to better understand the functions.

FindObject:

Using FindObject functions is a lot like FindColor functions, but you can be more specific on the properties of the object (i.e. uptext, color). However, the FindObject functions aren't part of SCAR, they are part of SRL, meaning the list is located in your core SRL folder. Open up Object.scar for a full list of FindObject functions (SCAR 3.21/Includes/SRL/SRL/core/Object.scar).

In this guide, I'm going to introduce you to two of the FindObject functions, simply because they are the most commonly used. Here are the two functions, straight from Object.scar:

{*******************************************************************************
function FindObj(var cx, cy: Integer; Text: string; Color, Tol: Integer): Boolean;
By: Starblaster100
Description: Finds Object
*******************************************************************************}

{*******************************************************************************
function FindObjCustom(var cx, cy: Integer; Text: TStringArray; Color: TIntegerArray; Tol: Integer): Boolean;
By: Starblaster100
Description: Finds Object with custom amount of colors and custom amount of Uptext
Example: FindObjCustom(x, y, ['att', 'ack'], [123456, 345678], 5);
*******************************************************************************}
If you can't see the difference, it is that FindObjectCustom can have more than one color, or more than one uptext, making it more accurate, while FindObj can only have one color, and one uptext choice. Given what I have used for previous examples, can you guess what I'm going to use for this one? But before we do that, I am going to explain the structure of FindObjCustom:

FindObjCustom(x, y, ['att', 'ack'], [123456, 345678], 5);
  • Firstly, the x and y parameters will store the coordinates of where the object is found.
  • The ['att', 'ack'] is the uptext of the object. Notice how there is more than one? That makes it more likely to find the object. The reason there are "[]" around it is because it is a TStringArray (more about adavnced arrays in the advanced section), but you don't have to worry about what that is right now, you just have to know to put square brackets around the uptexts.
  • The [123456, 345678] part is the colors. Like uptext, you can have multiple colors, making it more accurate. And like the uptext there are square brackets because the colors are a TIntegerArray (again, more on that later). And again, you just have to know to put square brackets around the colors.
  • The 5 should be pretty obvious, the tolerance of the colors.
The main thing I wanted to tell you about that example is the square brackets bit, because if you forget to include them, you will get an "Invalid number of parameters" error.

In this example, just to do something different we are going to find and click a copper rock.

program FindObjExample;
{.include SRL/SRL.scar}

function MineCopper: Boolean;
var
x, y : Integer;
begin
if not LoggedIn then Exit;
if FindObjCustom(x, y, ['ine', 'ocks'], [4879522, 4220300], 5) then//Notice how I used "[]".
begin
Writeln('Found copper rock!');
Mouse(x, y, 0, 0, True);//MMouse and uptext check isn't needed becaue it's already built into FindObjCustom, understand?
Result := True;//Returns true of the copper ore was clicked.
end else
Writeln('Couldn''t find the copper rock.');
end;
//Notice that we didn't use MSCX or MSCY. This is because FindObjCustom automatically starts searching from the center. :)
begin
ClearDebug;
SetupSRL;
ActivateClient;
if MineCopper then
Writeln('Mined copper ore!')
else
Writeln('Didn''t mine copper ore.');
end.

By now, I shouldn't have to tell you to make sure you understand everything before automatically hitting play, should I? If there is something you don't understand, look back on that part in the tutorial to try and understand it better. Before you press play, make sure you have:
  • Logged in to your account.
  • Have a copper rock in view.
  • Have a pickaxe in equipped or in your inventory (optional).
  • Drag the corsshairs over the RS window.
A successful run of that script will result with the following in your debug box:
SRL Compiled in 0 msec
Found copper rock!
Mined copper ore!
Successfully executed

Like I've said countless other times throughout this tutorial, try finding another object to get a better feel of the functions. Congratulations! You now know two different ways of finding and clicking objects.

Walking:

During this part of the tutorial we are going to learn how to walk on the minimap using various methods. Map walking can be incorporated into almost any script, whether it is a PowerChopper or a script that banks Willows in Draynor. The three types of walking methods you will be learning are starting from the most accurate first:
  • DDTM
  • Raidal Walking
  • Symbol Finding
Each method works just fine, but some aren't as reliable. For example, DDTMs are more reliable than Raidal Walking and Symbol Finding, but Radial Walking is more reliable than Symbol Finding, understand? (if that makes any sense at all).

DDTMs:

DDTM stands for Dynamic Deformable Template Model, and it used almost exactly like normal DTMs. It is dynamic because the information (i.e. color, tolerance, size) can all be changed throughout your script to make it fit your needs.

Making Your DDTM:

For this example, we will be walking out of Varrock west bank, and we will be using the DDTM Editor by Nielsie95, which is in your Scripting Tools folder. First thing, open the DDTM Editor. Now, I'm not going to explain the different elements of the DDTM Editor just yet, because they should be self-explanatory as most of them are the same as in the DTM Editor. Once the DDTM Editor is open, I want you to do the following:
  1. Take a screenshot of your RS character standing anywhere in the Varrock west bank, make sure the road is visible.
  2. Open the DDTM editor and go to Image > Paste, and you should see your RS screen there.
  3. Scroll to where you can see the minimap.
  4. Pick your main point somewhere on the Varrock road (just like in making a normal DTM).
  5. Pick 3-4 subpoints around your main point, and you should end up with something looking like this:
  6. [BANANA][/BANANA]
  7. Now, remember in the DTM Editor where it had the coordinates of the color you picked + the color itself (in the top right corner)? Well, in the DDTM editor it is the exact same, EXCEPT, all the colors should be the same.
  8. One the right, there is a spot to set the "Area Size". Set it to 1. If it is 0, it has no area to search in. ;) This part may be obvious, but the larger the area size, the better chance SCAR has of finding the DDTM, but it also increases the chance of lag, to be aware.
  9. Once you have done this, go to file > DDTM to Text. A window should come up, with a function in it that looks like this:

  10. function SetDDTM: Integer;
    var
    dtmMainPoint: TDTMPointDef;
    dtmSubPoints: Array [0..4] of TDTMPointDef;
    TempTDTM: TDTM;
    begin
    dtmMainPoint.x := 926;
    dtmMainPoint.y := 400;
    dtmMainPoint.AreaSize := 1;
    dtmMainPoint.AreaShape := 0;
    dtmMainPoint.Color := 8357514;
    dtmMainPoint.Tolerance := 0;

    dtmSubPoints[0].x := 926;
    dtmSubPoints[0].y := 400;
    dtmSubPoints[0].AreaSize := 1;
    dtmSubPoints[0].AreaShape := 0;
    dtmSubPoints[0].Color := 8357514;
    dtmSubPoints[0].Tolerance := 0;

    dtmSubPoints[1].x := 932;
    dtmSubPoints[1].y := 394;
    dtmSubPoints[1].AreaSize := 1;
    dtmSubPoints[1].AreaShape := 0;
    dtmSubPoints[1].Color := 8357514;
    dtmSubPoints[1].Tolerance := 0;

    dtmSubPoints[2].x := 939;
    dtmSubPoints[2].y := 399;
    dtmSubPoints[2].AreaSize := 1;
    dtmSubPoints[2].AreaShape := 0;
    dtmSubPoints[2].Color := 8357514;
    dtmSubPoints[2].Tolerance := 0;

    dtmSubPoints[3].x := 916;
    dtmSubPoints[3].y := 398;
    dtmSubPoints[3].AreaSize := 1;
    dtmSubPoints[3].AreaShape := 0;
    dtmSubPoints[3].Color := 8357514;
    dtmSubPoints[3].Tolerance := 0;

    dtmSubPoints[4].x := 911;
    dtmSubPoints[4].y := 407;
    dtmSubPoints[4].AreaSize := 1;
    dtmSubPoints[4].AreaShape := 0;
    dtmSubPoints[4].Color := 8357514;
    dtmSubPoints[4].Tolerance := 0;

    TempTDTM.MainPoint := dtmMainPoint;
    TempTDTM.SubPoints := dtmSubPoints;
    Result := AddDTM(TempTDTM);
    end;
There, you have successfully made your first DDTM. There are most likely some parts of the latter example that you don't understand, that's why I'm going to explain the different parts the best I can.

First off, this little part here:

dtmSubPoints[0].x := 926;
dtmSubPoints[0].y := 400;
Is the subpoint's x and y coordinates, pretty straight forward I'd say. You should also know that when the DDTM is found, it's coordinates are stored in a small area around the mainmpoint's x/y coordinates, and that is where SCAR will click.

Next, this part:

dtmSubPoints[0].AreaSize := 1;
dtmSubPoints[0].AreaShape := 0;
The AreaSize is also pretty straight forward, the larger the size, the larger area SCAR will search for the DDTM. The AreaShape is just the shape of the area to look in. The different options are available in the DDTM Editor. "1" is most commonly used as it is a rectangle.

Finally this small part:

dtmSubPoints[4].Color := 8357514;
dtmSubPoints[4].Tolerance := 0;
Is pretty straight forward, the color of the subpoint, and the tolerance of the color.

Using Your DDTM:

Now, in the above example, you may notice that all the colors are the same, and all the tolerances are 0. Since they are they same, the DDTM is just like a normal, static, DTM. So, in order to make a DDTM dynamic, we have to adjust the color and the color's tolerance. To do so, I want you to follow these steps:
  1. The first step in making your DDTM dynamic is to use what is called Autocoloring. This allows us to find the color we want each time the DDTM is called, thus making it dynamic. If you open Autocolor.scar in the core folder (SCAR 3.21/Includes/SRL/SRL/core/Autocolor.scar), you will see a while list of autocolor functions available for you to use.
  2. If there is a color that you want, but it is not in Autocolor.scar, there is always the option to make your own, but that won't be introduced until the Advanced section of the tutorial. What I want you to do is make a local variable in your SetDDTM function, and assign FindVarrockRoadColor to it like so:

    function SetDDTM: Integer;
    var
    dtmMainPoint: TDTMPointDef;
    dtmSubPoints: Array [0..4] of TDTMPointDef;
    TempTDTM: TDTM;
    RoadColor : Integer;//Like this.
    begin
    RoadColor := FindVarrockRoadColor;//Notice how we used FindVarrockRoadColor because that's exactly what we are trying to do, walk to the Varrock road.
    //The rest of the DDTM code here.
  3. Next what you want to do is replace the color of the MainPoint, and all the SubPoints with RoadColor, like this:

  4. dtmMainPoint.Color := RoadColor;
    There, you now have made your DDTM dynamic!
  5. Although your DDTM is now dynamic, that is not all you should do. Remember how we set the Tolerance to 0? Well, chances are that's not going to work so well. Therefore, we are also going to make the Tolerance dynamic.
  6. In order to do this, we need to make a global variable called DDTMTolerance, like so:

    program DDTMExample;
    {.include SRL/SRL.scar}

    var
    DDTMTolerance : Integer;
    //The rest of your script here.
    The reason we make it global, instead of local is because we are going to be using it in our SetDDTM function, and assigning it to an integer in our walking function.
  7. Once you have made your variable, I want you to replace the tolerance in your MainPoint and all your SubPoints with DDTMTolerance, just like this:

  8. dtmMainPoint.Tolerance := DDTMTolerance;
    There, you have now made both your DDTM's color and tolerance dynamic, and you should have a script that looks something like this:

    program DDTMExample;
    {.include SRL/SRL.scar}

    var
    DDTMTolerance : Integer;

    function SetDDTM: Integer;
    var
    dtmMainPoint: TDTMPointDef;
    dtmSubPoints: Array [0..4] of TDTMPointDef;
    TempTDTM: TDTM;
    RoadColor : Integer;
    begin
    RoadColor := FindVarrockRoadColor;
    dtmMainPoint.x := 926;
    dtmMainPoint.y := 400;
    dtmMainPoint.AreaSize := 1;
    dtmMainPoint.AreaShape := 0;
    dtmMainPoint.Color := RoadColor;
    dtmMainPoint.Tolerance := DDTMTolerance;

    dtmSubPoints[0].x := 926;
    dtmSubPoints[0].y := 400;
    dtmSubPoints[0].AreaSize := 1;
    dtmSubPoints[0].AreaShape := 0;
    dtmSubPoints[0].Color := RoadColor;
    dtmSubPoints[0].Tolerance := DDTMTolerance;

    dtmSubPoints[1].x := 932;
    dtmSubPoints[1].y := 394;
    dtmSubPoints[1].AreaSize := 1;
    dtmSubPoints[1].AreaShape := 0;
    dtmSubPoints[1].Color := RoadColor;
    dtmSubPoints[1].Tolerance := DDTMTolerance;

    dtmSubPoints[2].x := 939;
    dtmSubPoints[2].y := 399;
    dtmSubPoints[2].AreaSize := 1;
    dtmSubPoints[2].AreaShape := 0;
    dtmSubPoints[2].Color := RoadColor;
    dtmSubPoints[2].Tolerance := DDTMTolerance;

    dtmSubPoints[3].x := 916;
    dtmSubPoints[3].y := 398;
    dtmSubPoints[3].AreaSize := 1;
    dtmSubPoints[3].AreaShape := 0;
    dtmSubPoints[3].Color := RoadColor;
    dtmSubPoints[3].Tolerance := DDTMTolerance;

    dtmSubPoints[4].x := 911;
    dtmSubPoints[4].y := 407;
    dtmSubPoints[4].AreaSize := 1;
    dtmSubPoints[4].AreaShape := 0;
    dtmSubPoints[4].Color := RoadColor;
    dtmSubPoints[4].Tolerance := DDTMTolerance;

    TempTDTM.MainPoint := dtmMainPoint;
    TempTDTM.SubPoints := dtmSubPoints;
    Result := AddDTM(TempTDTM);
    end;
  9. But now we need to make a function that will find and click your DDTM. Now, the following example has a few new strategies and functions that may be hard to follow, but I'm sure you're up for the challenge:

  10. program DDTMExample;
    {.include SRL/SRL.scar}

    var
    DDTMTolerance : Integer;

    function SetDDTM: Integer;
    var
    dtmMainPoint: TDTMPointDef;
    dtmSubPoints: Array [0..4] of TDTMPointDef;
    TempTDTM: TDTM;
    RoadColor : Integer;
    begin
    RoadColor := FindVarrockRoadColor;
    dtmMainPoint.x := 926;
    dtmMainPoint.y := 400;
    dtmMainPoint.AreaSize := 1;
    dtmMainPoint.AreaShape := 0;
    dtmMainPoint.Color := RoadColor;
    dtmMainPoint.Tolerance := DDTMTolerance;

    dtmSubPoints[0].x := 926;
    dtmSubPoints[0].y := 400;
    dtmSubPoints[0].AreaSize := 1;
    dtmSubPoints[0].AreaShape := 0;
    dtmSubPoints[0].Color := RoadColor;
    dtmSubPoints[0].Tolerance := DDTMTolerance;

    dtmSubPoints[1].x := 932;
    dtmSubPoints[1].y := 394;
    dtmSubPoints[1].AreaSize := 1;
    dtmSubPoints[1].AreaShape := 0;
    dtmSubPoints[1].Color := RoadColor;
    dtmSubPoints[1].Tolerance := DDTMTolerance;

    dtmSubPoints[2].x := 939;
    dtmSubPoints[2].y := 399;
    dtmSubPoints[2].AreaSize := 1;
    dtmSubPoints[2].AreaShape := 0;
    dtmSubPoints[2].Color := RoadColor;
    dtmSubPoints[2].Tolerance := DDTMTolerance;

    dtmSubPoints[3].x := 916;
    dtmSubPoints[3].y := 398;
    dtmSubPoints[3].AreaSize := 1;
    dtmSubPoints[3].AreaShape := 0;
    dtmSubPoints[3].Color := RoadColor;
    dtmSubPoints[3].Tolerance := DDTMTolerance;

    dtmSubPoints[4].x := 911;
    dtmSubPoints[4].y := 407;
    dtmSubPoints[4].AreaSize := 1;
    dtmSubPoints[4].AreaShape := 0;
    dtmSubPoints[4].Color := RoadColor;
    dtmSubPoints[4].Tolerance := DDTMTolerance;

    TempTDTM.MainPoint := dtmMainPoint;
    TempTDTM.SubPoints := dtmSubPoints;
    Result := AddDTM(TempTDTM);
    end;

    function WalkOutOfBank: Boolean;
    var
    TheDDTM, x, y : Integer;//The reason "TheDDTM" is declared as an integer is because the function SetDDTM returns an integer.
    begin
    if not LoggedIn then Exit;//Remember to put this at the beginning of all your functions/procedures.
    SetRun(True);//This will turn your run, simple as that.
    DDTMTolerance := 5;//Notice how we set the INITIAL DDTMTolerance to 5.
    TheDDTM := SetDDTM;//Notice how we declare the variable "TheDDTM" as the SetDDTM function.
    repeat//This is going to repeatly try and find the DDTM if it is not found the first time.
    if not DTMRotated(TheDDTM, x, y, MMX1, MMY1, MMX2, MMY2) then//Notice how we use DTMRotated this time. This is because the MiniMap may not be on the same angle of which you made you DDTM. This allows it to find the DDTM, now matter which angle the MM is at.
    begin//Notice in the above line (69) we used "if not...". Simply means if it doesn't find the DDTM it will do what's in this begin..end nest.
    Writeln('Didn''t find DDTM, increasing tolerance...');
    IncEx(DDTMTolerance, 5);//IncEx works like Inc, except it will increase by a set integer, rather than increase by only one. In this case, we increase the tolerance by 5 each time the DDTM is not found.
    FreeDTM(TheDDTM);//ALWAYS remember to free the DDTM! We free it here because it will reload each time the loop repeats, so therefore, we need to free it each time the loop repeats.
    TheDDTM := SetDDTM;//We set it here because it will reset everytime the loop repeats.
    end else//This is to tell it what to do if it finds the DDTM.
    begin
    Writeln('Found Varrock road!');
    Mouse(x, y, 4, 4, True);
    Result := True;//Set the result to true because SCAR clicked the DDTM.
    Break;//Make sure it breaks out of the loop if the DDTM is found, otherwise it will click the DDTM every time it is found until the tolerance is 50.
    end;
    until((DDTMTolerance >= 50) or not LoggedIn);//Notice how it will repeatedly try to find the DDTM until the tolerance is greater or equal to 50, or your account has logged out, or it the DDTM has been found.
    DDTMTolerance := 5;//We do this to reset the DDTM's tolerance, incase we decide to use it again later in the script.
    FreeDTM(TheDDTM);//This frees the DDTM if it is found. ALWAYS remember to free the DDTM!
    end;

    begin
    ClearDebug;
    SetupSRL;
    ActivateClient;
    if WalkOutOfBank then//Remember to include your function in you main loop. =P
    Writeln('Walking out of the bank.')
    else
    Writeln('Couldn''t walk out of the bank.');
    end.
    Again, make sure you read all my comments, and understand everything in the script before you try testing. You should also know that in a particular walking procedure such as this, it would be a perfect time to call FindNormalRandoms. However, remember how I said you will get an "Out of Range…" error if you didn't include a DeclarePlayers procedure. Well, that is exactly why I didn't include FindNormalRandoms, because there is no DeclarePlayers procedure, understand? Once you understand everything, and you think you've made the script properly, make sure you do the following before hitting run:
    • Log in your player.
    • Have your player stand in the Varrcok west bank. Be sure your DDTM is visible on the map.
    • Click and drag the SCAR crosshairs over the RS window.
  11. If you ran the script successfully, your debug box should read something like this:

  12. SRL Compiled in 16 msec
    Found Varrock road!
    Walking out of the bank.
    Successfully executed
    Congratulations! You have now learned how to make, load, and click your DDTMs! You've learned the most accurate way of walking in RuneScape using color methods.

Declaring Multiple DDTMs:

Since you know how to make and use a single DDTM, I thought I would teach you now to load multiple DDTMs in the same function, and have the option to load only one at a time. This section of the tutorial is not difficult at all, you should have no problems following along. :)

What we are going to do is use a case statement to load two DDTMs, and using a parameter to determine which of the two we want to find. The example I am going to use will load the DDTM associated with the parameter "WalkNumber", and will allow us to walk from the Varrock west bank towards Barbarian Village.

To make your second DDTM, do it just like we did in the "Making Your DDTM" part of the tutorial. Your DDTM should look something like this:

[BANANA][/BANANA]


Notice how I'm standing in the area where we would walk to the first DDTM. Doing this will allow us to see the second DDTM after walking to the first. The following example has both the DDTMs in the same function, and are both used in the walking towards Barbarian Village:

program DDTMExample;
{.include SRL/SRL.scar}

var
DDTMTolerance : Integer;

function SetDDTM(WalkNumber: Integer): Integer;//Notice the parameter "WalkNumber".
var
dtmMainPoint: TDTMPointDef;
dtmSubPoints: Array of TDTMPointDef;//Notice how I took out the [0..4], this is so we can set the length of each DDTM differently.
TempTDTM: TDTM;
RoadColor : Integer;
begin
RoadColor := FindVarrockRoadColor;
case WalkNumber of//Notice the case statement dependant on what the parameter "WalkNumber" is assined to.
0: begin//Notice that if i = 0, it will load the first DDTM.
SetArrayLength(dtmSubPoints, 5);//Don't forget to set the array length, otherwise you will get an "Out of Range..." error!
dtmMainPoint.x := 926;
dtmMainPoint.y := 400;
dtmMainPoint.AreaSize := 1;
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := RoadColor;
dtmMainPoint.Tolerance := DDTMTolerance;

dtmSubPoints[0].x := 926;
dtmSubPoints[0].y := 400;
dtmSubPoints[0].AreaSize := 1;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := RoadColor;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 932;
dtmSubPoints[1].y := 394;
dtmSubPoints[1].AreaSize := 1;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := RoadColor;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 939;
dtmSubPoints[2].y := 399;
dtmSubPoints[2].AreaSize := 1;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := RoadColor;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 916;
dtmSubPoints[3].y := 398;
dtmSubPoints[3].AreaSize := 1;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := RoadColor;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 911;
dtmSubPoints[4].y := 407;
dtmSubPoints[4].AreaSize := 1;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := RoadColor;
dtmSubPoints[4].Tolerance := DDTMTolerance;
end;

1: begin//Notice that if i = 1, it will load the second DDTM.
SetArrayLength(dtmSubPoints, 5);
dtmMainPoint.x := 913;
dtmMainPoint.y := 388;
dtmMainPoint.AreaSize := 1;//Remember to make the AreSize = 1.
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := RoadColor;//Remember to replace the color with the autocoloring function.
dtmMainPoint.Tolerance := DDTMTolerance;//Remember to replace the tolerance with DDTMTolerance variable.

dtmSubPoints[0].x := 913;
dtmSubPoints[0].y := 388;
dtmSubPoints[0].AreaSize := 1;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := RoadColor;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 918;
dtmSubPoints[1].y := 379;
dtmSubPoints[1].AreaSize := 1;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := RoadColor;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 925;
dtmSubPoints[2].y := 378;
dtmSubPoints[2].AreaSize := 1;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := RoadColor;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 908;
dtmSubPoints[3].y := 392;
dtmSubPoints[3].AreaSize := 1;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := RoadColor;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 906;
dtmSubPoints[4].y := 399;
dtmSubPoints[4].AreaSize := 1;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := RoadColor;
dtmSubPoints[4].Tolerance := DDTMTolerance;
end;
end;
TempTDTM.MainPoint := dtmMainPoint;//Notice how these three lines are outside the case.
TempTDTM.SubPoints := dtmSubPoints;//This is because they are exactly the same in both DDTMs.
Result := AddDTM(TempTDTM);
end;

function WalkToBarbVillage(WalkNumber: Integer): Boolean;//We use the WalkNumber parameter again so we can call the procedure to walk to whichever DDTM we wish without having to write the same code over and over again.
var
TheDDTM, x, y : Integer;
begin
if not LoggedIn then Exit;
SetRun(True);
DDTMTolerance := 5;
TheDDTM := SetDDTM(WalkNumber);//Notice how to function is dependant on what you assign WalkNumber to.
repeat
if not DTMRotated(TheDDTM, x, y, MMX1, MMCY, MMCX, MMY2) then//Notice how I have MMCY and MMCX - I will explain that below.
begin
Writeln('Didn''t find DDTM number ' + IntToStr(WalkNumber) + ', increasing tolerance...');//Notice how I added a small part that tells us which DDTM it found. This way, if there is an error, we can tell which DDTM is having the problems.
IncEx(DDTMTolerance, 5);
FreeDTM(TheDDTM);
TheDDTM := SetDDTM(WalkNumber);
end else
begin
Writeln('Found DDTM number ' + IntToStr(WalkNumber) + '!');
Mouse(x, y, 4, 4, True);
Result := True;
FFlag(3);//This is new. This will wait until your player is within 3 tiles on the MM. There is a whole list of Flag functions in Flag.scar.
Break;
end;
until((DDTMTolerance >= 50) or not LoggedIn);
DDTMTolerance := 5;
FreeDTM(TheDDTM);
end;

begin
ClearDebug;
SetupSRL;
ActivateClient;
if WalkToBarbVillage(0) then//Noticed how we called upon the first DDTM.
begin
Writeln('Walking out of the bank, first DDTM.');
if WalkToBarbVillage(1) then//Notice how it will only try to find the second DDTM, IF it finds the first. This is an excellent way of looking less "Bot-like".
Writeln('Walking to second DDTM.')
else
Writeln('Couldn''t walk to second DDTM');
end else
Writeln('Couldn''t walk out of the bank.');
end.
At this time I would normally say, "Make sure you understand everything in that script before hitting run", but this time, I have to explain what MMCX/MMCY are, and why I used them. So, breaking them down:
  • MMCX stands for MiniMap Center. The "X" refers to whether it is the x/y corrdinate.
  • MMCY stands for MiniMap Center Y. "Y" is just like "X", it refers to the y coordinate.
Now, that's all good and great, but why did I use them? Well, I used them to make the area to look for the DDTM smaller, which will make it more accurate and faster.

But, why did I have it in the order I did (MMX1, MMCY, MMCX, MMY2)? Well, think of it like a box - MMX1 = X1, MMCY = Y1, MMCX = X2, and MMY2 = Y2. I have made this diagram to help you understand:

[BANANA][/BANANA]


The first diagram represents the box that SCAR will look in for the DDTM if you use the parameters (MMX1, MMY1, MMX2, MMY2). I also marked the center, so you understand what I mean by MMCX/MMCY.

The second diagram represents the box SCAR will look for the DDTM for the parameters I used to the last example, understand? I hope so, that may have been a little jumbled. :p

Not only does using those parameters make you script faster, but it also makes it a lot less likely that SCAR will find the DDTM on another part of the map, that isn't where you want to walk. For example, with the second DDTM in the last example, Juliette's house a little north-west of our DDTM The color of the house floor is very close to that of the Varrock road color. So, to avoid clicking inside the house by accident, all you have to do is narrow down the box that SCAR looks in.

If you have successfully made, and understand the above example, your character should have turned run on, and then walked to an area just south of Juliette's house. Before hitting run make sure you drag the cosshairs over the RS screen. If you did it correctly, your debug box should read something like this:

SRL Compiled in 16 msec
Found DDTM number 0!
Walking out of the bank, first DDTM.
Found DDTM number 1!
Walking to second DDTM.
Successfully executed

Congratulations, after much explanation, you know everything you need to know about DDTMs! If you don't understand a part of the tutorial, try rereading that part, or you can take a look at this nice DDTM tutorial -> Correctly Creating/Using a DDTM

Radial Walking:

Radial Walking should always be used as a failsafe for DDTMs. It is slightly less accurate than a DDTM, and they take up only one line as appose to 50, so it can be used very easily as a failsafe. Basically how radial walking works, it SCAR will search for a color based on what you use for your parameters. Here is the radial walking function:

function RadialWalk(TheColor: Integer; StartRadial, EndRadial: Integer; Radius: Integer; Xmod, Ymod: Integer): Boolean;
Now you probably have no idea what what most of those parameters are, so I'll explain them to the best of my ability.
  • TheColor - Pretty straight forward - the color you are looking for on the MM.
  • StartRadial/EndRadial - This is basically the start and end angles to search for the color. In RS, the angles are as follows (credit 100% to Zeph for the diagram):
  • [BANANA][/BANANA]
  • Radius - This is how far out from the center of the MiniMap, in pixels, you want SCAR to search. Here's a quote from Zeph, with a nice little analogy:
  • From: ZephyrsFury
    Imagine a piece of pizza, the tip of the piece is the MiniMap center and the crust is the radius.
  • XMod/YMod - These parameters are used if SCAR clicks the MM, and the flag doesn't appear. For example, maybe it clicks somewhere that you can't walk, and the flag doesn't appear on the MiniMap. If this happens, the values you use for XMod/YMod represent the amount of pixels away from the first point SCAR will try to click next.
  • The values for XMod/YMod can be both positive and negative. A positive XMod will click to the right, negative to the left. A positive YMod will click down, a negative up. Yes, you read that right, because how RS is set up, for the Y values, positive is down and negative is up. If you don't understand, I'm sure you will after you see an example.

For this example, we will be walking from the Draynor bank, to the Willow trees. Exciting, no? Now, to obtain the best StartRadial, EndRadial, and Radius values, we will use a nifty little tool called Radial Walking Aid (RRA), developed by Yakman.

This tool can be found in your "Scripting Tools" folder in SRL. Just open the script, and press run. You will be greeted with a window called "Radial Walking Aid - Yakman" When you've managed to do this, follow these steps:
  1. Log your character into RS, and make sure they are standing in Draynor Bank.
  2. Open RRA and click Find RS, followed by Capture From Client. You should now see your RS MiniMap in the RRA window.
  3. Now, fill in the Start Radial, End Radial, and Radius according to where you want to search. I used 190, 230, and 60.
  4. Once you have chosen your values, hit Show Path. You should see the RRA draw some red lines. This will be your searching area. It should look something like this:
  5. [BANANA][/BANANA]
    Adjust the parameters until you have found the the searching area you like the best. I should also mention what we will be doing about the parameter "TheColor". Well, like we used in DDTMs, we will be using AutoColoring functions. Because the RS water color is easily visible from any point in the Draynor bank. Therefore, we will be using FindWaterColor.
  6. Now, at this point, you can hit Print Procedure if you would like. However, neither of the two functions that get printed are ones we will be using. :p Otherwise, just fill in the parameters that you've chosen.
  7. As for XMod/YMod, it is best to use 2 and 1 because you don't want it to click too far away from your point. Also, we use positive numbers because we don't want to click the water, am I right?
  8. So, with all the parameters filled out, you should have a function that looks something like this:

RadialWalk(FindWaterColor, 190, 230, 60, 2, 1)
Well, now that we have the function, it's not doing anything. We have to make a function that will walk from the bank to the Willows. A function such as this should do the job:

program RadialWalkExample;
{.include SRL/SRL.scar}

function WalkToWillows: Boolean;
begin
if not LoggedIn then Exit;//Get into the habbit of writing this in all your procedures early.
SetRun(True);
Result := RadialWalk(FindWaterColor, 190, 230, 60, 2, 1);//Notice how the Result is true if it walks to the Willows.
if Result then
begin
Writeln('We are walking to the Willow trees, Radial walk method.');
Wait(80 + Random(100));
FFlag(3);
end else
Writeln('Radial walking method failed.');
end;
//You may notice that there is no point in the function that clicks the mouse. This is because it is already incorperated into RadialWalk. So, there is no need to click twice.

begin
ClearDebug;
SetupSRL;
ActivateClient;
if not WalkToWillows then//Decided to do something differet this time.
TerminateScript;//This means that if it doesn't walk to the Willows, the script will execute.
end.
Once again, make sure you understand everything before you test it out. Before testing, make sure you have done the following:
  • Have your character logged in, sitting in the Draynor bank.
  • Dragged the crosshairs over the RS window.
If you wrote this script correctly, it should turn the run on if it isn't already, and walk to the Willow trees, and you debug box should say something like this:

SRL Compiled in 0 msec
We are walking to the Willow trees, Radial walk method.
Successfully executed

Congratulations, you now know two different methods of walking in RuneScape using SCAR. Remember, if there is some part of this guide that you don't understand, be sure to look back at that specific part and reread for a better understanding.

Symbol Finding:

Symbol finding is probably the easiest way of walking in RuneScape, but it's also the most unreliable of the three walking methods I'm showing you. This is because there are several things that can happen that will make SCAR not find the symbol:
  • The symbol is not in view of the MiniMap.
  • The symbol is only in partial view of the MiniMap.
  • There is a person (white dot) or NPC (yellow dot) on top of the symbol.
  • The symbol moves ALOT, so it may not be where you need it to be.
As you can see, there are many reasons why you shouldn't use Symbol Finding as your first walking procedure. It is best to use as a fail safe for Radial Walking.

However, some of these problems can sometimes be avoided with a small little command called SymbolAccuracy. For example:

SymbolAccuracy := 0.5;
This will make FindSymbol return true even if only 50% of the symbol is found (1.0 = 100%, 0.4 = 40%, etc.). If you don't understand, you will in the next example.

What you should do is use a DDTM for your first walking procedure, then Radial Walking for a failsafe, and then Symbol Finding as a third failsafe. If you use this method for all your walking procedures, chances are that it will never fail, and your script has the chance of running for hours without failing.

Symbol Finding procedures are extremely easy to use, especially after you know how to do DDTMs and Radial Walking. Here is the function, straight out of Symbol.scar:

function FindSymbol(var rx, ry: Integer; Name: string): Boolean;
There are also several other Symbol Finding function in Symbol.scar for you to choose from, including some with customizable area to look in (remember the DDTM example).

You should already know what the x, y do. They store the coordinates of the symbol when it's found. The Name is the symbol name, and can be any of the following (also from Symbol.scar):

{*******************************************************************************
Valid Arguments are:
- agility - furnace - rare trees, tree
- altar - gem stall - rest, resting spot
- anvil - guide - sandpit
- apothecary - hair dresser - saw mill
- archery shop - herbalist - scimitar shop
- arrow - house - shield
- axe shop - hunter store - shop, store
- bar - hunter training - short cut
- bank - jewelery - silk stall
- candle shop - kebab shop - silver stall
- churn - mace shop - slayer master
- clothes shop - magic shop - spice stall
- cookery shop - makeover mage - spinning wheel, spin
- cookery, cook - mill - staff shop
- crafing shop - minigame - summoning store
- dungeon - mining shop - sword shop
- farming shop - pet shop - tanner
- farming spot - platebody shop - training dummy
- fishing shop, fish store - plateskirt shop - underground
- fishing spot, fish - portal (to player owned houses) - water source, water
- food shop - pottery, pot - weave
- fur trader - quest - windmill

*******************************************************************************}
For my symbol finding example, we are going to find the fishing symbol south of the Draynor bank, and click it. The following example should be pretty easy for you to understand, as it is very simple:

program FindSymbolExample;
{.include SRL/SRL.scar}

function WalkToWillows: Boolean;
var
x, y : Integer;
begin
if not LoggedIn then Exit;
SetRun(True);
SymbolAccuracy := 0.5;//Notice how I set the accuracy to 50%, so it will still work if it only finds half of the symbol.
Result := FindSymbol(x, y, 'fish');
if Result then
begin
Writeln('Found fishing symbol!');
Mouse(x, y, 4, 4, True);//Click the fishing symbol.
end else
begin
Writeln('Couldn''t find the fishing symbol');
Logout;//Logout and execute script if it can't find the symbol.
TerminateScript;
end;
SymbolAccuracy := 0.8;//Make sure you set the SymbolAccuracy back to the defaut accuracy, 0.8 or 80%.
end;

begin
ClearDebug;
SetupSRL;
ActivateClient;
if WalkToWillows then
Writeln('Walking to Willows!')
else
Writeln('Not walking to Willows.');
end.
Now, I'm sure you wont have any trouble understanding that example, but before you hit run, make sure the fishing symbol is in view in the MiniMap and don't forget to drag your crosshairs over the RS window. If you made a successful script, your debug box should read something like this:

SRL Compiled in 16 msec
Found fishing symbol!
Walking to Willows!
Successfully executed

There, you now know how to use the three best methods of walking. For a more in depth walking tutorial you can visit this thread -> Map Walking - The Basics to the Advanced

Using All Three Methods:

This section is going to be very small as I am just going to show you an example of a walking function that includes all three methods of walking, each as a failsafe of the other. Note that the following script will NOT work if you press run as the DDTM isn't loaded in the script.

I am showing you this because I want you to have an idea of what the function looks like with all three methods incorporated into it. This example is from my Draynor Chop N' Bank script:

procedure W_WalkToWillows;
var
x, y : Integer;
begin
if not LoggedIn then Exit;
SetRun(True);
MakeCompass('n');//This just makes the RS compass point to which ever direction you wish ('n', 'e', 's', 'w').

if DTMRotated(W_WalkDDTMs(1), x, y, MMX1, MMY1, MMX2, MMY2) then
begin
S_FindRandoms;
Wait(80 + Random(100));
Writeln('Walking to Willows, DDTM method.');
Mouse(x + 35, y + 5, 4, 4, True);
FFlag(0);
end else//Notice the end else, so it will do RadialWalk if it doesn't find the DDTM.

if RadialWalk(FindWaterColor, 190, 230, 60, 2, 1) then
begin
S_FindRandoms;
Writeln('DDTM method failed, using radial walking.');
Wait(80 + Random(100));
Writeln('Arrived at Willows.');
FFlag(0);
end else//Again, notice that it will do FindSymbol if RadialWalk fails.

if FindSymbol(x, y, 'fish') then
begin
S_FindRandoms;
Writeln('Radial walking failed, using sumbol finding.');
Wait(80 + Random(100));
Writeln('Arrived at Willows.');
Mouse(x, y + 10 + Random(15), 4, 4, True);
FFlag(0);
end else

begin
Writeln('Couldn''t walk to Willows, logging out.');
S_EndScript;//This is just a procedure I have elseware in my script
end;
FreeDTM(W_WalkDDTMs(1));
end;
Now, after seeing that procedure, do you understand what I mean by using Radial Walking and Symbol Finding as a failsafe? Good.

Multiplayer:

Multiplayer is a very useful aspect that should be incorporated into every script. Multiplayer allows you to switch between RS characters when the previous one is finished, or is taking a break. In this section of the tutorial, you are going to learn how to add multiplayer to your script.

The first thing you should know about adding multiplayer is the very useful command, NextPlayer. This command is used to switch between players, and can be used in two different ways:
  • NextPlayer(True) - This will switch players, but leave the current player true, so it can come back to it later.
  • NextPlayer(False) - This will switch players and set the current player to not active. You would want to do this if the current player cut enough logs for example, or got lost.
You should always only have to use the NextPlayer command in your main loop. Look at this main loop for example:

begin
repeat
repeat
ChopLogs;
BankLogs;
until((NumOfLogs >= 1000) or not LoggedIn);
NextPlayer(True);
until(AllPlayersInactive);//This will end the script when all the players are inactive.
end.
That example will chop and bank logs using the current player until it has cut more than 1000 logs, or if it is not logged in.

However, sometimes the script will mess up during a procedure such as walking, or banking the logs, and you don't want the script to continue thinking that player is active when it got lost somewhere. So, what you have to do is change all your procedures, and use something like this:

function BankLogs: Boolean;
begin
if BankLogs then
//Do this...
else//Notice how if it can't bank the logs, it will set the player to inactive, and logout.
begin
Players[CurrentPlayer].Active := False;//Set the current player to inactive because it got lost in the script.
Logout;//Logout the player!
Exit;//Be sure to exit the procedure! Otherwise it will continue and not do anything, wasting time.
end;
end;
Do you understand what is needed for multiplayer when a procedure messes up? Good. Now, if something such as this should occur, the script will try to move on with other procedures. This is where adding "if not LoggedIn then Exit" to the beginning to every procedure/function becomes really useful.

Since the character logged out because it messed up somehwere, it will just exit out of every other procedure/function in the main loop until it gets to the spot where it switches players.

Now, when it switches players, it will switch just fine, but it will keep the current player active because you used NextPlayer(True). To avoid this small bug, you should change that line to:

NexPlayer(Players[CurrentPlayer].Active);
Using that small change, it will switch to the next player in DeclarePlayers that is set to active. When it is all said and done, you should have the ending of each procedure/function looking something like this:

function DoSomething: Boolean;
begin
if Condition then
//Do this...
else
begin
Players[CurrentPlayer].Active := False;
Logout;
Exit;
end;
end;
And, your main loop should look something like this:

begin
repeat
repeat
ChopLogs;
BankLogs;
until((NumOfLogs >= 1000) or not LoggedIn);
NextPlayer(Players[CurrentPlayer].Active);
until(AllPlayersInactive);
end.
Hopefully that wasn't too difficult to understand. For are more in depth tutorial on multiplayer, check out this nice guide -> Adding Multiplayer

Congratulations! :D You can now call yourself an intermediate scripter! Well done! Again, look over a section of the tutorial that you don't understand before you move on to the advanced section. Before moving on, you should know that some of the content in the Advanced section is much more complicated than what you have done so far, but I know you're up for the challenge.

Coh3n

2009-08-21 04:21:13

5. For the Advanced:

During this section of the tutorial, you will be learning many different advanced SCAR scripting strategies that will make your scripts both shorter, and better. You will be learning things such as CTS, TPAs and Types. I will also teach you how to make your very own AutoColoring functions.

ColorToleranceSpeed:

The first thing I'm going to teach you in this part of the guide is all about ColorToleranceSpeed. ColorToleranceSpeed is how fast or how accurate you want to find the color you're searching for. There are four different color tolerance speeds:
  • 0 - The fastest of the four, but the least accurate.
  • 1 - Slightly slower than CTS(0), but more accurate. This is the CTS that SCAR uses as default.
  • 2 - More accurate than 1, but a little slower. This is the CTS that is most commonly used in RS scripts.
  • 3 - The slowest, but the most accurate.

For the example in this section, I'll be using CTS(2), simply because it is the most commonly used, and most likely the one you will be using in your scripts. Setting the CTS requires this procedure:

ColorToleranceSpeed(2);//This sets the CTS to 2, and can be changed to any number from 0-3.
Now, for CTS(2) and CTS(3), there are what we call modifiers, and they need to be set after calling ColorToleranceSpeed(2), or ColorToleranceSpeed(3). These are straight from the SCAR Manual.:

procedure SetColorSpeed2Modifiers(huemodifier, saturationmodifier: Extended);
These work when ColorToleranceSpeed(2) has been set. Normally Tolerance parameter in this mode applies to Luminance directly. For an example, SimilarColors(c1, c2, 10) would work if both colors differ by 10 max luminance. After calling SetColorspeed2Modifiers(0.2, 2) it would mean that SimilarColors(c1, c2, 10) would check for Hue in range of 2 and Saturation in range of 20. Default huemodifier and saturationmodifier is 0.2.

procedure SetColorSpeed3Modifiers(Sensitivity: Integer);
This works when ColorToleranceSpeed(3) has been set. This sets the Sensitivity of the 3th color comparison mode. The default Sensitivity is 4. (Note that this is carefully chosen and will be sufficient in most cases.)

Now, if you are anything like me, and suck with vocabulary, you probably do not know what Luminance or Saturation are. So, I have prepared for a situation just like this. I have come up with the following definitions:
  • Luminance refers to a quality of reflecting light, or in other words, the brightness of the object. And example would be "The blinding luminance of the sun."
  • Saturation refers the the "purity" of a color. For example, the color red is pure red, but the color maroon (dark red) isn't. It is partly red, partly black.
Hopefully knowing those definitions helps you understand the CTS modifier procedures. Now, you are probably wondering, "How the heck am I doing to get the correct HueMod and HueSat values?" Well, thanks to Nielsie95 and Sumilion, we have access to an amazing application called Auto Coloring Aid v2 (ACA). This can be found in your Scripting Tools folder.

Using this awesome tool, we can get the HueMod and HueSat values very easily. We can also make our very own AutoColoring functions that we can use in various functions such as Radial Walking, DDTMs, and FindColorTolerance.

Once you have opened ACA I want you to do the following steps.
  1. Log your character in, and stand beside a normal tree.
  2. Open ACA and go to Client > Client Window > Find RS. A picture of your RS screen should come up in the ACA window.
  3. By simply using your mouse, select 4-5 different colors of the tree. You will notice that the colors you pick will come up in the top right corner of the window.
  4. In the bottom right corner, you will see a small box titled "CTS", and you will see areas to select 0-2. Because we are going to be using CTS(2), you should select "2".
  5. Once this is done, just to the right, you will see a button called "Mark Best Color". Hit this button. You should notice some "Red" areas on the screen over the tree. This represents the colors SCAR would find when you use the current settings. Your window should look something like this (I have also marked the area which holds all the "settings" I mentioned in the last sentence):
[BANANA][/BANANA]


Now, you may notice that in that picture, there are some red spots in the MiniMap, this is because SCAR finds these colors. You can change your colors around so SCAR doesn't find the colors on the MM. However, when we attempt to find the color, it will be in the main screen, so SCAR wont find the color anyway.

The use of CTS modifiers is usually used with TPointArrays (TPAs), however, you haven't learned those yet, so we'll just use CTS modifiers without them for now.

The following example will find and click the normal tree. Now, this example will look a lot like the example I used for FindColor object finding the in intermediate section. The difference is, that this one is much more accurate because we will be using CTS(2) instead of CTS(1).

program CTSExample;
{.include SRL/SRL.scar}

function ClickTree: Boolean;
var
x, y : Integer;
begin
if not LoggedIn then Exit;
x := MSCX;//Remember we use this so it'll start searching at your character.
y := MSCY;
ColorToleranceSpeed(2);//Sets the CTS to 2.
SetColorSpeed2Modifiers(0.04, 0.85);//Set the modifiers. Notice they are the values found in the "Settings" found in ACA.
if FindColorSpiralTolerance(x, y, 3239522, MSX1, MSY1, MSX2, MSY2, 10) then//Notice both the color and the tolerance are from the ACA settings.
begin
MMouse(x, y, 4, 4);
if WaitUpText('ree', 2500) then//Notice the new function, WaitUpText. This means it will move the mouse and wait 2500ms to see if the uptext will appear.
begin
Writeln('Found tree!');
Mouse(x, y, 0, 0, True);
Result := True;
end else
Writeln('Couldn''t find the uptext.');
end else
Writeln('Couldn''t find the tree color.');
SetColorSpeed2Modifiers(0.2, 0.2);//Be sure to set the modifiers back to default, (0.2, 0.2).
ColorToleranceSpeed(1);//Be sure to set the CTS back to the default, 1.
end;

begin
ClearDebug;
SetupSRL;
ActivateClient;
if ClickTree then
Writeln('Clicked tree!')
else
Writeln('Didn''t click tree.');
end.
If you wrote that script successfully, you understand it fully, your debug box should say something like this:

SRL Compiled in 0 msec
Found tree!
Clicked tree!
Successfully executed

There, you should now have a good feel of what ColorToleranceSpeed is all about, if you don't, try rereading this section of the tutorial, or you can check out this useful guide -> ColorToleranceSpeed and XYZ

Advanced Arrays:

During this section of the tutorial, you will be learning three different, more advanced types of arrays. These include:
  • TIntegerArray (TIA) and TExtendedArrays (TEA).
  • TStringArray (TSA).
  • TPointArray (TPA) and T2DPointAray (ATPA).
You will learn how to use each one of them, and where they would be useful. During my time here at SRL, I have had the chance to use each one of them successfully, so I hope I can explain them well enough for you.

TIntegerArray and TExtendedArray:

The example used in this section is going to done using a TExtendedArray, but the explanation on what it is and how to declare it, I'm going to use a TIntegerArray. I decided to do this because both types of arrays are used exactly the same. The only difference is that TExtendedArray uses decimal numbers and TIntegerArrays use whole numbers.

TIntegerArray is another way of saying Array of Integer, except when the array is declared like this, you can write it differently, without having to set the array length at all. For example, using Array of Integer:

var
Logs : Array[0..5] of Integer;
begin
Logs[0] := 10;
Logs[1] := 20;
Logs[2] := 30;
Logs[3] := 40;
Logs[4] := 50;
Logs[5] := 60;
end;
As you can see, it takes up many lines, and you have to set the length. Now, declaring it as TIntegerArray:

var
Logs : TIntegerArray;
begin
Logs := [10, 20, 30, 40, 50, 60];
end;
See how that is much shorter? It also looks much, much better and cleaner. Do you notice now you don't have to set the length? That is because the "[]" lets the length automatically, and if you need to add a part to the array such as "70", you just have to add it in after 60, and the length will adjust automatically.

Now that you know how to declare the array, lets move on to an example. In this example, I am going to be using a procedure from my Anywhere Powerchopper that checks the amount of experience a player has gained.

procedure ExpGained;
var
XpGain : TExtendedArray;
i : Integer;
begin
XpGain := [25, 37.5, 67.5, 175];//Set the array, notice the extended values.
case Lowercase(Players[CurrentPlayer].Strings[0])of//.Strings[0] is in the DeclarePlayers, and is used to determine which tree the player is going to chop.
'tree' : i := 0;//The variable 'i' is used later in the script, so that no matter which tree the player is going to cut, the exp gained will be calculated correctly.
'oak' : i := 1;
'willow' : i := 2;
'yew' : i := 3;
end;
end;
There, after that small example, you should understand how to declare and use TInteger and TExtended Arrays. If you are really good, you will be able to see that the latter example can be shortened, but that would require knowledge of TStringArrays. :p

TStringArray:

Like the previous arrays, TStringArray is another way of saying Array of String, and can be written differently, without setting the array length. All the TArrays are declared the same, and you don't have to set the length for any of them. If you don't understand, look at how this TStringArray is declared:

var
Words : TStringArray;
begin
Words := ['left', 'right', 'center', 'up', 'down'];
end;
Simple as that, and just like declaring TInteger and TExtended arrays. In the following example, I am going to shorten my ExpGained procedure into something that looks better, and is more efficient:

function ExpGained: Integer;
var
XpGain : TStringArray;
begin
XpGain := ['tree', IntToStr(25), 'oak', FloatToStr(37.5),//Notice the IntToStr and FloatToStr, that makes the exp into a string.
'willow', FloatToStr(67.5), 'yew', IntToStr(175)];

if InStrArrEx(Lowercase(Players[CurrentPlayer].Strings[0], XpGain, i) then//Explained below.
Result := StrToInt(XpGain[i + 1] * NumOfLogs)//Explained below.
else
Writeln('String not in DeclarePlayers.');//This will come up if the person didn't fill out DeclarePlayers properly.
end;
Now, there is probably a lot in that example you don't understand. So, I'm going to explain it to you the best I can. I'll break it up step by step.
  1. So this part:

  2. XpGain := ['tree', IntToStr(25), 'oak', FloatToStr(37.5),
    'willow', FloatToStr(67.5), 'yew', IntToStr(175)];
    Is the TStringArray. Notice how each part of the array is a string because I used the functions IntToStr and FloatToStr. Now, you may wonder why I have it like this. Well, you'll see as I explain the rest of the function.
  3. This little part:

  4. if InStrArrEx(Lowercase(Players[CurrentPlayer].Strings[0], XpGain, i) then
    Is a new function, and here's the explanation, straight from Text.scar:

    {*******************************************************************************
    Function InStrArrEx(S: String; StrArr: TStringArray; Var Where: Integer): Boolean;
    By: n3ss3s
    Description: Returns true if the string S was found in the StrArr, and if so
    stores the index into Where.
    *******************************************************************************}
    That should be pretty understandable for you. Basically it will return true if any of the correct trees stated in the XpGain array are found in the DeclarePlayers procedure, and stores the index of the array in the variable 'i'.
  5. This part here:

  6. Result := StrToInt(XpGain[i + 1] * NumOfLogs);
    Since the result in an Integer, and the array is a string, we have to use the function StrToInt, which just converts a string to an integer. The is so it uses the right amount of exp depending on the type of tree specified in DeclarePlayers. For example, if in DeclarePlayers:

    Players[0].Strings[0] := 'tree';
    Then i would be equal "0" because that is the first string in the array, and 'tree' is the first string in the array. Then, adding 1 to 0 would convert the string that occurs after 'tree', which in this case, is the amount of exp for cutting down one tree, into an integer.
  7. I hope that wasn't too hard to follow, I made it as clear as I could. Now, the NumOfLogs part is a separate part in my script that calculates how many logs each player has cut. So, the "* NumOfLogs" is needed to multiply the log the player is cutting, but the amount of logs they have cut in order to get the total exp gained, understand? I hope.
There, you now know how to use the easiest of the four TArrays, now if you think you're up for the challenge, you can move on and learn TPointArrays (they're really not as hard as everyone thinks). :p

TPointArray and T2DPointArray:

This part of the tutorial is going to me much longer than the previous two, simply because TPAs are much harder, and you will be using them much more in your scripts.

TPAs are most commonly used in FindColor procedures because it makes them much more accurate and most of the time, faster. Remember how you learned all the different FindColor functions way back in the intermediate section of the tutorial? Well, those functions were used to find single colors.

The following functions are used to find multiple colors (straight from the SCAR Manual):

function FindColors(var Points: TPointArray; Color, xs, ys, xe, ye: Integer): Boolean;
Finds all colors in the area specified by xs, ys, xe, ye and returns their coordinates in Points. Will return True if any colors are found.

function FindColorsTolerance(var Points: TPointArray; Color, xs, ys, xe, ye, Tol: Integer): Boolean;
Finds all colors with tolerance in the area specified by xs, ys, xe, ye and returns their coordinates in Points. Will return True if any colors are found.

procedure FindColorsSpiralTolerance(x, y: Integer; var Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer);
Finds all colors in area specified by xs, ys, xe, ye and returns their coordinates into Points.

Those explanations are pretty straight forward, and I'm sure you can guess which one we'll be using for out example? FindColorsSpiralTolerance. Since it's been working well so far, we may as well stick with it. For this example, we will find and click a normal tree.

Before we move on to the example, I need to tell you a little bit about what a T2DPointArray or ATPA is. ATPA stands for Array of TPointArray, which may seem confusing, but maybe this will help you understand better:

function ATPAExample;
var
TPA : TPointArray;
ATPA : T2DPointArray;//This is how you declare a ATPA - the 2D stands for 2 Dimentional TPA.
begin
ATPA[0]: TPA := [Point(1, 2), Point(3, 4), Point(5, 6)];//See how the ATPA is an array, and inside that array is a TPointArray?
ATPA[1]: TPA := [Point(a, b), Point(c, d), Point(e, f)];
end;
I hope that helps you understand a little better, how TPA is an array, inside an array. Now, in the following example, you will be introduced to many new functions and strategies that will make your script much faster, and more efficient. The functions I marked with "WizzyPlugin" will be explained after the example.

Now, there are going to be a lot of things in this example that you won't understand right away, so don't just say "this is too hard" and give up. That is the wrong attitude to have! Go through it slow, and you'll understand it much better.

program TPAExample;
{.include SRL/SRL.scar}

function ClickTree: Boolean;
var
x, y, i, h : Integer;
TPA : TPointArray;//Don't forget to set the TPA to a variable.
ATPA : T2DPointArray;//Notice how a ATPA is declared.
begin
if not LoggedIn then Exit;
ColorToleranceSpeed(2);//Remember to do these two lines to make the color finding more accurate.
SetColorSpeed2Modifiers(0.04, 0.85);
repeat//Notice the repeat. This will repeatedly click the trees until you tell it to stop.
FindColorsSpiralTolerance(x, y, TPA, 3239522, MSX1, MSY1, MSX2, MSY2, 10);//Notice that we don't use an if..then statement this time. This is because FindColorsSpiralTolerance is a procedure, not a function, and doesn't return a boolean.
ATPA := SplitTPAEx(TPA, 5, 5);//WizzyPlugin.

if (Length(ATPA) = 0) then
begin
Writeln('Couldn''t find the tree color.');
Exit;//This will exit the procedure if it can't find the color. Remember, the amount of colors SCAR finds is stored in the array TPA.
end;

SortATPAFromFirstPoint(ATPA, Point(MSCX, MSCY));//WizzyPlugin.
h := High(ATPA);
for i := 0 to h do//For every color that SCAR finds, do this.
begin
Writeln('Length: ' + IntToStr(Length(ATPA[i])));//This will write, in the debug box, how many colors were found.
MiddleTPAEx(ATPA[i], x, y);//WizzyPlugin.
MMouse(x, y, 4, 4);
if WaitUpText('ree', 300) then
begin
Writeln('Found tree!');
Mouse(x, y, 0, 0, True);
Result := True;
Wait(8000 + Random(2000));//This will wait a Random 10 seconds before clicking next tree. This is probably the worste way of doing this. See below on what you should do. ;) However, without this line, the script will "spam" click the trees.

{ This is where you would have the script detect if the player is chopping
a tree. It would also be a good idea to perform your Antiban procedure
here. However, I'm not going to show you how to check if the player is
cutting the tree, that is for me to know and you to figure out. ;) }

end else
Writeln('Couldn''t find the right uptext.');
end;
until(InvFull or not LoggedIn);//Will repeat until the inventory is full, or not logged in.

SetColorSpeed2Modifiers(0.2, 0.2);//Don't forget to reset back to default.
ColorToleranceSpeed(1);
end;

begin
ClearDebug;
SetupSRL;
ActivateClient;
if ClickTree then
Writeln('Clicked tree!')
else
Writeln('Couldn''t click tree.');
end.
Now, I guarantee you are saying something like, "Whaa", with a very confused look on your face. Don't worry, I'm going to explain each part that I said "WizzyPlugin" beside. Because I'm sure that's the part you are confused about.

Introduction to the WizzyPlugin:

The WizzyPlugin is is comprised of a TON of different TPA/ATPA functions made by Wizzup?. Each one serves it's own purpose, and each one makes working with TPAs much more accurate. A list of these functions and their descriptions can be found in WizzyPlugin.scar (SCAR 3.21/Includes/SRL/SRL/misc/WizzyPlugin.scar).
  1. The first function I used from the WizzyPlugin is called SplitTPAEx:

  2. {*******************************************************************************
    function SplitTPAEx(arr: TPointArray; w, h: Integer): T2DPointArray;
    Description: Splits the points with max X and Y distances W and H to their
    own TPointArrays.
    *******************************************************************************}
    So, what it does it split the TPAs into separate boxes of size determined by the parameters w and h, and is put into an array. Or, in other words an Array of TPointArray (ATPA). The reason I used that nifty little function was so that the colors found by SCAR could be broken down into more manageable pieces. Think of it like a 5 gallon tub of water. Would it be easier to carry all 5 gallons at once? Or 1 gallon at a time.
  3. The second function I used is called SortATPAFromFirstPoint:

  4. {*******************************************************************************
    procedure SortATPAFromFirstPoint(var a: T2DPointArray; const From: TPoint);
    Description: Sorts the T2DPointArray a from the point From.
    *******************************************************************************}
    This one is a little simpler. Since we split the TPAs of the colors into separate boxes (each part of the ATPA), we use SortATPAFromFirstPoint to put the ATPA in the order we wish. In this case, we organized them, starting from Point(MSCX, MSCY), which is the center of the main screen, and where our player is. Basically, this way, SCAR should click the tree closest to our character.
  5. The third and final function I used is called MiddleTPAEx:

  6. {*******************************************************************************
    function MiddleTPAEx(TPA: TPointArray; var x, y: Integer): Boolean;
    Description: Stores the coordinates of the middle of the TPointArray a to X & Y.
    *******************************************************************************}
    Again, this one is a little simpler. This one finds the middle value of the ATPA, and stores its coordinates in the parameters x and y. Without this step, we wouldn't be able to move our mouse to the colors on the main screen because this function defines x and y, so we have a point to move the mouse to.

With those explanations, you should be able to understand the last ClickTree function pretty well. Like I've said before, this section was a lot to handle, so take it slow, and triple read things if you have to. No one is going to understand things like this the first time it is showed to them.

If you fully understand that example, and your wrote it right, you debug box should be filled with text that looks something like this:

SRL Compiled in 0 msec
Length: 1
Couldn't find the right uptext.
Length: 2263
Couldn't find the right uptext.
Length: 908
Found tree!
Length: 1086
Couldn't find the right uptext.
Length: 907
Couldn't find the right uptext.
Length: 405
Found tree!
Successfully executed

In instances where it says "Couldn't find the right uptext" most likely occur when it accidentally finds the color of another tree. After all, all the tree colors are extremely close together. Also, where it says "Length: 405" (or whatever number). That is simply just the amount of colors SCAR finds in the specified search area.

Congratulations, you have finally learned all about the much talked about TPAs! For a much more in depth tutorial on the WizzyPlugin and TPAs, visit this guide -> A low down on WizzyPlugin and TPAs

Custom Autocoloring:

Since the last section of the tutorial may have been a little overwhelming for you, I have decided to reward you with a nice, small, easy section on making your own Autocoloring functions.

Now you may be thinking, "Easy? How is making an Autocoloring function EASY?". Well because we have access to ACA (remember from the CTS section?). Last time I showed you how to get the HueMod and SatMod values using ACA. This time, with one extra step, you will be able to make your very own Autocolor function.

For the example, we will be autocoloring the Draynor bank floor, and using a DDTM to walk from the Willow trees, to the bank, with RadialWalking and Symbol Finding as failsafes.

So what you need to do is follow these steps:
  1. Log your character in, and have him stand outside the Draynor bank somewhere.
  2. Open up ACA and go Client > Client Window > Find RS, and you should see your RS screen in the ACA window.
  3. Just like you did before, click the bank floor color on the MiniMap because that's where we will be looking for the color. Select CTS(2), and hit "Mark Best Color". Your screen should now look something like this:
  4. [BANANA][/BANANA]
    Notice how the bank floor color on the MiniMap is completely red. This is exactly what you want. :D
  5. Next I want you to click on "AutoColor Function" at the top of the window, just below the pull-down menus. Something should come up that looks just like the SCAR welcoming page.
  6. Now, at the bottom of the window you should see a few different settings. You want it looking like this:
  7. [BANANA][/BANANA]
    Once you have done this, click on "Create Function" in the bottom left corner, and you will see a whole mess of code pop up. This is going to be your AutoColoring function.
So, copy and paste this into your script, make your DDTM, write a walking procedure, WITH FAILSAFES.

What I would suggest when making your DDTM for a busy place like a bank, is to make a DDTM of something near the bank. Somewhere where no one every walks. This increases the change of finding the DDTM. Now, because the DDTM won't be exactly in the bank, you will have to click a certain amount of pixels in the x and y directions of the DDTM. If you don't know what I mean, I have marked in the example.

When you have made a good walking script, it should look something like this:

program AutoColorExample;
{.include SRL/SRL.scar}

var
DDTMTolerance : Integer;

function FindBankFloorColor: Integer;
var
arP: TPointArray;
arC: TIntegerArray;
tmpCTS, i, arL: Integer;
X, Y, Z: Extended;
begin
tmpCTS := GetColorToleranceSpeed;
ColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.00, 0.00);

FindColorsSpiralTolerance(MMCX, MMCY, arP, 2565930, MMX1, MMY1, MMX2, MMY2, 0);
if (Length(arP) = 0) then
begin
Writeln('Failed to find the bank floor color, no result.');
ColorToleranceSpeed(tmpCTS);
SetColorSpeed2Modifiers(0.2, 0.2);
Exit;
end;

arC := GetColors(arP);
ClearSameIntegers(arC);
arL := High(arC);

for i := 0 to arL do
begin
ColorToXYZ(arC[i], X, Y, Z);

if (X >= 2.03) and (X <= 2.07) and (Y >= 2.07) and (Y <= 2.11) and (Z >= 2.19) and (Z <= 2.23) then
begin
Result := arC[i];
Writeln('Bank floor color = ' + IntToStr(arC[i]));
Break;
end;
end;

ColorToleranceSpeed(tmpCTS);
SetColorSpeed2Modifiers(0.2, 0.2);

if (i = arL + 1) then
Writeln('AutoColor failed in finding the bank floor color.');
end;

function SetDDTM: Integer;
var
dtmMainPoint: TDTMPointDef;
dtmSubPoints: Array [0..4] of TDTMPointDef;
TempTDTM: TDTM;
BankColor : Integer;
begin
BankColor := FindBankFloorColor;
dtmMainPoint.x := 970;
dtmMainPoint.y := 413;
dtmMainPoint.AreaSize := 1;
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := BankColor;
dtmMainPoint.Tolerance := DDTMTolerance;

dtmSubPoints[0].x := 970;
dtmSubPoints[0].y := 413;
dtmSubPoints[0].AreaSize := 1;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := BankColor;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 964;
dtmSubPoints[1].y := 420;
dtmSubPoints[1].AreaSize := 1;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := BankColor;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 956;
dtmSubPoints[2].y := 413;
dtmSubPoints[2].AreaSize := 1;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := BankColor;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 980;
dtmSubPoints[3].y := 410;
dtmSubPoints[3].AreaSize := 1;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := BankColor;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 978;
dtmSubPoints[4].y := 422;
dtmSubPoints[4].AreaSize := 1;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := BankColor;
dtmSubPoints[4].Tolerance := DDTMTolerance;

TempTDTM.MainPoint := dtmMainPoint;
TempTDTM.SubPoints := dtmSubPoints;
Result := AddDTM(TempTDTM);
end;

function WalkToBank: Boolean;
var
x, y, TheDDTM : Integer;
begin
if not LoggedIn then Exit;
DDTMTolerance := 15;
TheDDTM := SetDDTM;
BankColor := FindBankFloorColor;
SetRun(True);

repeat
if not DTMRotated(TheDDTM, x, y, MMCX, MMY1, MMX2, MMCY) then
begin
Writeln('Didn''t find DDTM, increasing tolerance...');
IncEx(DDTMTolerance, 5);
FreeDTM(TheDDTM);
end else
begin
Writeln('Found DDTM!');
Mouse(x, y - 10 - Random(5), 4, 4, True);//Notice how it doesn't click the DDTM exactly, 10-15 pixels up.
Result := True;
FFlag(3);
Break;
end;
until((DDTMTolerance >= 50) or not LoggedIn);

if (DDTMTolerance >= 50) then
begin
if RadialWalk(BankColor, 5, 45, 52, -2, 1) then
begin
Writeln('Walking to bank, RR method.');
Result := True;
FFlag(5);
end else
if FindSymbol(x, y, 'bank') then
begin
Writeln('Radial walking failed, using sumbol finding.');
Mouse(x, y, 4, 4, True);
FFlag(5);
end else
begin
Writeln('Couldn''t walk to bank.');
Logout;
TerminateScript;
end;
end;
DDTMTolerance := 15;
FreeDTM(TheDDTM);
end;

begin
ClearDebug;
SetupSRL;
ActivateClient;
if WalkToBank then
Writeln('Walking to bank!')
else
Writeln('Couldn''t walk to bank.');
end.
Using that example, my debug box looked like this:

SRL Compiled in 16 msec
Failed to find the bank floor color, no result.
Failed to find the bank floor color, no result.
Found DDTM!
Successfully executed

Yours will obviously look different depending on how you wrote you script. When it says "Failed to find the bank floor color, no result." That just means that the AutoColoring function failed the first two times, but was successful the third time. :)

There, you now know how to make and use AutoColoring functions for whichever purposes you wish. Remember Autocoloring functions can be used for more than just walking, they can also be used in item and object finding.

Types:

Hang in there, the tutorial is almost done… ish. :p Types are very easy to understand, and I am going to be teaching you how to make your own so they can be incorporated into your script.

You are probably wondering what a Type is. Well… these are all different kinds of types:

Integer, String, Extended, Boolean, Variant, etc.

Not too difficult, I'd say. Now, in order to make your own type, you have to know what a record is:
  • Record - also known as Record Data Structure, is used to combine the different built-in SCAR types.
So, declaring your type is pretty basic and is usually done at the start of your script, after you declare all your variables and constants, like so:

type
end;//Notice the 'end;'. You always need an 'end;' after declaring a type.
Now, what you would do is choose your record. I am going to use Tree for my example. You would then go and declare it like this:

type
Tree = record;
end;
I have come up with this little analogy to help you better understand. If you think of "Tree" as a a file folder, and inside that file folder, you have a bunch of different sheets of paper in it. These would be known as the "records" of anything that has something to do with "Tree".

You could also think about it as your Criminal Record - a bunch of files that keeps track of any criminal acts you've partaken in during your life.

That little explanation will help you understand what I'm about to do. I'm about to add the "sheets of paper" or records if you will into the "Tree" folder:

type
Tree = record
UpText : TStringArray;
Colors : TIntegerArray;
Tolerance : Integer;
end;
That is how types are declared. Now, types can be used as many times as needed throughout your script. Since you know what types are and how to declare them, I am going to show you how to use them.

With..Do Statements:

In this section of the tutorial I am going to teach you what a with..do statement is, and how to use them. I chose to wait until the advanced section to teach them to you, simply because they are most commonly used when working with types.

Now that you have your type declared properly, we are going to use FindObjCustom to find a… you guessed it… a tree! I know you already know how to use that function and everything, but it will be a clear example on how to use types.

Now, in order to use your type, it has to be declared as a variable, just like any built-in SCAR type would be. You can do this by simply writing it like this at the beginning of your procedure/function:

var
NormalTree : Tree//Notice the type "Tree";
Not too difficult, is it? Well that is all good and everything, but we haven't set any of the records to anything yet. They are all still declared as other types already built into SCAR. So, at the start of our procedure/function we would set values to them. Something like this:

function ClickTree: Boolean;
var
x, y : Integer;
NormalTree : Tree;
begin
NormalTree.UpText := ['ree', 'hop'];//The uptext of a normal tree.
NormalTree.Colors := [3762768, 1852733];//These can just be picked using the SCAR color picker.
NormalTree.Tolerance := 10;//The tolerance of the .Colors.

//Object finding goes here.
end;
See how each part of the record is declared? Good. Now, you are probably asking, "That's great, Coh3n, but what does any of this have to do with the with..do statements you mentioned?". Well, I'm about to show you.

Declaring a record with only three parts isn't that bad, but when you get into 9 and 10 parts, there is a lot of needless repeated code that we can get rid of simply by using a with..do statement. In the following example, I have used a with..do statement, and I have added in the rest of the script that will find and click a normal tree:

program TypeExample;
{.include SRL/SRL.scar}

type
Tree = record
UpText : TStringArray;
Colors : TIntegerArray;
Tolerance : Integer;
end;

function ClickTree: Boolean;
var
x, y : Integer;
NormalTree : Tree;
begin
with NormalTree do
begin
UpText := ['ree', 'hop'];
Colors := [3762768, 1852733];
Tolerance := 10;
end;//Notice the begin..end nest after the with..do statement.

if FindObjCustom(x, y, NormalTree.UpText, NormalTree.Colors, NormalTree.Tolerance) then//Notice how all the different elements of the Tree record is used.
begin
Writeln('Found tree!');
Mouse(x, y, 4, 4, True);
Result := True;
end else
Writeln('Didn''t find tree.');
end;

begin
ClearDebug;
SetupSRL;
ActivateClient;
if ClickTree then
Writeln('Clicked tree!')
else
Writeln('Didn''t click tree.');
end.
Before you press run, remember to make sure you fully understand how to use types. When the script has been run, your debug box should look something like this:

SRL Compiled in 15 msec
Found tree!
Clicked tree!
Successfully executed

Remember to look back at any part of the tutorial that you don't understand fully, there is nothing wrong with rereading parts you don't understand. Believe me, I've had to do it plenty of times since I started scripting. For a more in-depth tutorial on types visit this guide -> A list of common Types in SCAR - Plus making your own!!

CONGRATULATIONS! You can now call yourself an advanced scripter, and you are well on your way to making a very successful RuneScape script, and even getting into SRL Members!

Coh3n

2009-08-21 04:22:17

Back To Top

6. Recommended Reads:

Any of the tutorials on this list have really helped me write my tutorial, and made it easier for me to understand different parts of scripting. Thanks to anyone who wrote these tutorials.

7. Credits:

The credits go to anyone's tutorial that I used a direct quote or example from. Or a guide that just, in general, helped me understand parts better so I could explain them better. Thanks to everyone who made these tutorials. You made writing mine much easier.
  1. Bam Bam -> SCAR Script Official Standards.
  2. Macro_FTW -> Not-so-well known SCAR shortcuts.
  3. Nava2 -> Guide on the Many Statements in SCAR!
  4. Bumblebee -> Correctly Creating/Using a DDTM
  5. ZephyrsFury -> Map Walking - The Basics to the Advanced
  6. Nielsie95 -> Adding Multiplayer
  7. NaumanAkhlaQ -> A list of common Types in SCAR - Plus making your own!!

8. Conclusion:

Well, there you have it, the longest tutorial I will every write. I think it is safe to say and as of right now, this is the longest tutorial on the forums. Either this, or Masterkill's form tutorial. :p

I have spent WAY too much time writing this guide, and I'm extremely glad I can finally released it. I really, really hope that it helps a lot of people that are interested in scripting, and even those people who didn't understand something specific.

Writing this tutorial gave me a much better understanding of almost every element of scripting. I can honestly say that I learned more from writing this tutorial than I would have from reading a million others.

Thank you all for reading (or giving up half way through :p), and I hope it was an enjoyable read. Please feel free to post any mistakes I may have made, and please post any comments or questions you may have.

Cheers! :D

Harry

2009-08-21 04:24:49

You trying to get a tut cup? :p

Nice work!

Wizzup?

2009-08-21 04:27:18

Quite big. ;)
Nice.

TRiLeZ

2009-08-21 04:30:28

Dont make such a damn big tutorial!! LOL
Rep +

Blumblebee

2009-08-21 04:41:05

amazing, nice job man really well done.

Coh3n

2009-08-21 04:42:29

From: TRiLeZ
Dont make such a damn big tutorial!! LOL
Rep +


Lol, it had to be big to include everything! :p

From: Blumblebee
amazing, nice job man really well done.


Thanks a lot! :D

noidea

2009-08-21 04:43:04

I didn't know there was an updated RWAid :p
Nice.. I think you're trying to compete with Naum. He loves competition :p

Coh3n

2009-08-21 04:44:03

From: noidea
I didn't know there was an updated RWAid :p
Nice.. I think you're trying to compete with Naum. He loves competition :p


Haha well I'll give up easy, I don't want to write another tutorial for a while. This one is long enough, I've done enough writing for now. :p

Awkwardsaw

2009-08-21 04:54:54

:o z0mg nice tut. lol. nice refresher :D

Coh3n

2009-08-21 04:56:01

From: Awkwardsaw
:o z0mg nice tut. lol. nice refresher :D


Yeah lol, I feel like there isn't much I don't know now. :p

Boreas

2009-08-21 08:15:29

Obvious tut cup is obvious :p

Coh3n

2009-08-21 08:17:08

From: Boreas
Obvious tut cup is obvious :p


Haha well thank you very much! :D

Nava2

2009-08-21 08:43:27

Kid, I need to get you drunk.

Since you are getting laid more than I, something else must change.

Nub, you forgot forms.

Laimonas171

2009-08-21 11:44:43

REP++ all in one tut and well explained. :)

Naum

2009-08-21 12:17:46

Amazingly done man, keep up the great work :) rep+

Coh3n

2009-08-21 19:42:50

From: Nava2
Kid, I need to get you drunk.

Since you are getting laid more than I, something else must change.

Nub, you forgot forms.


Haha forms… I think it's long enough without adding a section for forms. :p

Thanks Laimon and Naum! :D

HyperSecret

2009-08-21 19:57:56

Took me like half a mousepad of a click and drag to get to the quick reply box. I don't need to read it all but geez this thing is HUGE.

I don't give rep out often but this deserves it!

Great job!

Coh3n

2009-08-21 20:09:12

From: HyperSecret
Took me like half a mousepad of a click and drag to get to the quick reply box. I don't need to read it all but geez this thing is HUGE.

I don't give rep out often but this deserves it!

Great job!


Thanks Hyper! Your rep got me to 2 rep squares. :p

MylesMadness

2009-08-21 20:20:46

From: Coh3n
Thanks Hyper! Your rep got me to 2 rep squares. :p
Whos the funny guy who put you down… Reped to try to raise you

Coh3n

2009-08-21 20:22:29

From: MylesMadness
Whos the funny guy who put you down… Reped to try to raise you


Awe mannnn. :(

But thanks. :D

EDIT: LOL they wrote under comments "NO BALLS FOR YOU!".

How unfortunate…

Naum

2009-08-22 00:00:07

From: Coh3n
Awe mannnn. :(

But thanks. :D

EDIT: LOL they wrote under comments "NO BALLS FOR YOU!".

How unfortunate…


I'll Sort that.

Coh3n

2009-08-22 00:12:41

From: NaumanAkhlaQ
I'll Sort that.


Yay thanks Naum. :D

10 REP POINTS! :eek:

You are God.

Death-Magnetic

2009-08-22 02:02:28

Very nice turorial, good job!

Rep ++

:)

~D-M

Coh3n

2009-08-22 02:03:26

From: Death-Magnetic
Very nice turorial, good job!

Rep ++

:)

~D-M


Thanks Death. ;)

Death-Magnetic

2009-08-22 02:04:38

Seriously, how long time did it take to write it all? :O

Coh3n

2009-08-22 02:05:24

From: Death-Magnetic
Seriously, how long time did it take to write it all? :O


You don't want to know. But if I have to guess, I'd say around 24 hours spread out over a couple weeks.

Death-Magnetic

2009-08-22 02:06:37

From: Coh3n
You don't want to know. But if I have to guess, I'd say around 24 hours spread out over a couple weeks.


Nice :D

Coh3n

2009-08-22 02:07:13

From: Death-Magnetic
Nice :D


Lol, thanks. I'm glad I could release it, and I hope it helps a lot of people.

Death-Magnetic

2009-08-22 02:08:12

From: Coh3n
I hope it helps a lot of people.


I'm sure it will.

Rick

2009-08-22 04:15:09

Rep ++. You can see how much effort you put into this, and it's absolutely incredible.

Coh3n

2009-08-23 06:15:31

Thanks to both of you. :D

CorbLimey

2009-09-02 15:58:22

Hi Coh3n,

I'm working my way through this now - great tutorial. Looking forward to posting my first script soon.

Coh3n

2009-09-02 18:25:37

From: CorbLimey
Hi Coh3n,

I'm working my way through this now - great tutorial. Looking forward to posting my first script soon.


Thanks, I can't wait to see it, do me a favor and PM me when you post it. That way I can see what you made using my guide, and give you a few pointers if I need to. :p

Cheers, Coh3n

Bionicle

2009-09-09 01:12:27

amazing tut, if i could, id give this 7 stars out of 5 :D

Coh3n

2009-09-09 01:13:22

From: bionicle1800
amazing tut, if i could, id give this 7 stars out of 5 :P


Haha thanks, I'm glad you found it helpful. :) Everything was easy enough to understand?

Hoplite

2009-09-09 17:47:33

Nice.. very helpful.. :)

Coh3n

2009-09-18 06:45:52

From: Hoplite
Nice.. very helpful.. :)


That's good to hear, I like to see new people learning to script. :)

Main

2009-09-21 03:21:10

Even srl members are learning from this :norris:

Coh3n

2009-09-21 14:11:01

From: Main_Ftw
Even srl members are learning from this :norris:


:p Well it was aimed at everyone!

Bionicle

2009-09-21 22:56:53

1000 view pwnd xD
lol gj again :p

Coh3n

2009-09-21 23:09:04

From: bionicle1800
1000 view pwnd xD
lol gj again :p


Haha thanks! :D

voot

2009-09-21 23:14:33

many thanks for all the hard work on this tutorial and the scripts i have seen posted by you. i am reading everything i can and going through all the scripts i have seem posted to try to learn enough to dive into the process myself.

had thought about using reflection but then after reading posts it seems to be a bit of a pain for the devs to update with all the RS updates. so deciding to skip that and try to learn using just SCAR and SLR so things more likely to work.

Coh3n

2009-09-21 23:16:57

From: voot
many thanks for all the hard work on this tutorial and the scripts i have seen posted by you. i am reading everything i can and going through all the scripts i have seem posted to try to learn enough to dive into the process myself.

had thought about using reflection but then after reading posts it seems to be a bit of a pain for the devs to update with all the RS updates. so deciding to skip that and try to learn using just SCAR and SLR so things more likely to work.


It's great to see that you're learning! If there is something that's unclear about my tutorial, you can always add me on MSN and ask. To be quite honest, I would recommend learning color scripting, before reflection.

Once you have mastered color, reflection is a breeze to learn, but it does challenge you to make longer and more complicated scripts. At least that's how I feel. :)

Good luck!

voot

2009-09-21 23:23:44

thanks for the advice. what i had noticed from all the tutorials i have been reading is that the progression you mention is about the only way to learn it properly. been having fun trying out some really basic scripts but am trying to build up a mental image of everything that SCAR and SLR already do so i don't end up coding a bone-head custom version of something that is already out there.

Coh3n

2009-09-21 23:42:58

From: voot
thanks for the advice. what i had noticed from all the tutorials i have been reading is that the progression you mention is about the only way to learn it properly. been having fun trying out some really basic scripts but am trying to build up a mental image of everything that SCAR and SLR already do so i don't end up coding a bone-head custom version of something that is already out there.


Yeah, I think it's the best way to learn. That's why I wrote this guide. When I learn new things myself, I always find it much easier to learn really easy things, and then gradually get more difficult. It makes everything easier, and that was my main objective when writing this tutorial.

Bionicle

2009-09-21 23:56:30

From: voot
thanks for the advice. what i had noticed from all the tutorials i have been reading is that the progression you mention is about the only way to learn it properly. been having fun trying out some really basic scripts but am trying to build up a mental image of everything that SCAR and SLR already do so i don't end up coding a bone-head custom version of something that is already out there.


you picked a great member to learn from, almost everything i learned about scar, i learned from him :)

Coh3n

2009-09-21 23:57:42

From: bionicle1800
you picked a great member to learn from, almost everything i learned about scar, i learned from him :)


<3 you!

SCAR 3.21

2009-09-26 20:46:29

WOW really helpful, took me 2 hours just to read the beginner part.
Guna save the other 2 parts for later while i try to make a beginner script :D

Coh3n

2009-09-26 21:04:16

From: SCAR 3.21
WOW really helpful, took me 2 hours just to read the beginner part.
Guna save the other 2 parts for later while i try to make a beginner script :D

That's great! I'm glad you're learning, and yeah, it's a looong guide! But, I had to include everything. :p

appolo13

2009-09-27 03:39:56

when i have time il try some ^^

Rich

2009-09-27 14:29:42

From: appolo13
when i have time il try some ^^


If you don't stop spamming, I swear I will personally beat you to a pulp.

Dynamite

2009-09-27 14:33:28

From: R1ch
If you don't stop spamming, I swear I will personally beat you to a pulp.


Lol, rep+

T~M

Coh3n

2009-09-27 21:55:08

From: R1ch
If you don't stop spamming, I swear I will personally beat you to a pulp.

Lol, couldn't have said it better myself.

Nava2

2009-09-27 22:11:35

From: The Man
Lol, rep+

T~M


This was spam itself. I would just like to point that out.

Also, to everyone else, its not really advisable to spam vs. spam. Looks silly.

Coh3n

2009-09-29 05:04:18

From: Nava2
Also, to everyone else, its not really advisable to spam vs. spam. Looks silly.

But it's so fun!

ItsBrucey

2009-10-19 23:45:30

Thanks for the tutorial not quite done reading it yet but you may want to fix where it says while do and repeat untill loops are exactly the same. You may want to add in the R/U loops go through the sequence at least once no matter what and W/D loops may or may not.

Coh3n

2009-10-20 17:49:53

From: ItsBrucey
Thanks for the tutorial not quite done reading it yet but you may want to fix where it says while do and repeat untill loops are exactly the same. You may want to add in the R/U loops go through the sequence at least once no matter what and W/D loops may or may not.


Did I say they were EXACTLY the same? If so, I didn't mean to. Thanks for that correction.

ItsBrucey

2009-10-21 17:44:13

From: Coh3n
Did I say they were EXACTLY the same? If so, I didn't mean to. Thanks for that correction.


Wasn't trying to antagonize you or anything :D

++rep for great tut :D

Coh3n

2009-10-21 19:42:51

From: ItsBrucey
Wasn't trying to antagonize you or anything :D

++rep for great tut :D

No not at all. I'm going to change that right now actually. Thanks!

zionz

2009-10-24 09:54:23

Does this guide teach how to use S.M.A.R.T before i give it a thorough look over.

Coh3n

2009-10-24 14:06:10

From: zionz
Does this guide teach how to use S.M.A.R.T before i give it a thorough look over.

No, I have a separate guide for that.

zionz

2009-10-25 05:08:55

From: Coh3n
No, I have a separate guide for that.

Ok cheers.

Illidus

2009-10-29 21:55:08

Just spent like 6 hours reading to from top to bottom. Thanks a lot dude i learned a tonne! Would rep you but already have for your powerchopper script. There were a few grammatical errors which made a few things a little confusing but understandable considering how freaking long it is!

Coh3n

2009-10-30 07:15:25

From: Illidus
Just spent like 6 hours reading to from top to bottom. Thanks a lot dude i learned a tonne! Would rep you but already have for your powerchopper script. There were a few grammatical errors which made a few things a little confusing but understandable considering how freaking long it is!

Thanks for reading. Do you remember where I made the grammatical mistakes by any chance? I'd like to fix them. :)

WhiskySK

2009-11-17 12:24:17

I have just finnished reading it. Truly the tutorial, which can learn something (no offence to others though). I like very very very long tutorials, i have better feeling when i am done reading it.

I read it very long, maybe 4-5 days, practicing everything. It is really a great masterpiece, it should be rewarded more, because you made a amazing incredible effort. Simply i do not know words to say… It should be like on the first page of forums like "Coh3n`s great tutorial to all your questions" lol.

Now, i ask myself, if i am capable of making scripts, it seems, i will have it on my first tab another 4-5 days so i can gather help from it. lol

Just a word from me, i like to speech.:p

THANK YOU COH3N !!!

WhiskySK

Coh3n

2009-11-17 12:45:58

From: WhiskySK
I have just finnished reading it. Truly the tutorial, which can learn something (no offence to others though). I like very very very long tutorials, i have better feeling when i am done reading it.

I read it very long, maybe 4-5 days, practicing everything. It is really a great masterpiece, it should be rewarded more, because you made a amazing incredible effort. Simply i do not know words to say… It should be like on the first page of forums like "Coh3n`s great tutorial to all your questions" lol.

Now, i ask myself, if i am capable of making scripts, it seems, i will have it on my first tab another 4-5 days so i can gather help from it. lol

Just a word from me, i like to speech.:p

THANK YOU COH3N !!!

WhiskySK


Haha thanks very much! I'm really glad to hear you appreciated it so much. Good luck with your scripting. :)

I tried to Rep+ you, but apparently I need to spread it around more. :tongue:

WhiskySK

2009-11-17 12:48:07

Hmm, as you are saying that, i forgot to rep+ you. lol

Coh3n

2009-11-17 13:31:16

From: WhiskySK
Hmm, as you are saying that, i forgot to rep+ you. lol

Haha, well I'm not going to argue. ;)

scriptkitty

2009-12-04 11:53:30

excellent tut, it was a good refresher for me.

i am having one problem getting one piece of code to work.

this code
function LoadBitmaps: Integer;
begin
LogBMP: Result := BitmapFromString(5, 5, 'beNpzkIzwVyAShfjIQUggCvCQ' +//Notice how I used the variable "Result".
'9XGRtjUXc7KWACJ3B0l3AM9zEjg=');
end;
Very simple. I would suggest using a function like that to load bitmaps, only of you have more than one bitmap, otherwise you can use the bitmap locally (like the the example to come).

i cant get that code to work with more then one Bitmap, how could it be written to load 3 bitmaps?
i am working on a script… its a bit messy right now but i keep getting failed when compiling when i us the
: Result
after my bitmap name like in the code
Failed when compiling
Line 19: [Error] (20649:9): Assignment expected in script

and when i leave
: Result
out i get
Successfully compiled (18797 ms)
Line 16: [Hint] (20646:10): Variable 'Result' never used in script

i would like to have a clean debug box when i finish compiling… maybe im just using the the code wrong

scriptkitty

2009-12-04 12:10:53

just ran what i have finished with out
: Result
and it works great. just really wanting to know what im doing wrong to get that in my debug box

Quickmarch

2009-12-04 12:24:48

From: scriptkitty
just ran what i have finished with out and it works great. just really wanting to know what im doing wrong to get that in my debug box


Could you post the whole script? And don't double post next time. ;)

Coh3n

2009-12-04 12:34:39

If you would like to load with more than one Bitmap, you would have to add a parameter and use a case, so you can choose which Bitmap to load. Something like this:

function LoadBitmaps(Which: Integer): Integer;
begin
case Which of
0: Result := { Bitmap stuff here. };
1: Result := {};
2: Result := {};
else
Writeln('Invalid Bitmap Selection.');
end;
end;

// Then when you use it, you would do something like this:
var
Bitmap: Integer;
begin
Bitmap := LoadBitmaps(1);

if FindBitmap(Bitmap, { Rest of parameters here. }) then
begin
// Blah Blah.
end;
end.
When you get an 'Assingment Expected' error, that means you forgot to put an equals ('=') sign after a colon when assigning the bitmap to the result. (0: Result :=).

I hope this answers your question.

Coh3n

scriptkitty

2009-12-04 16:01:33

i see what i did now i tried to just use one instance with several results :duh:
function LoadBitmaps: Integer;
begin
bmp0: Result := BitmapFromString(.....);
bmp1: Result := BitmapFormString(.....);
bmp2: Result := BitmapFormString(.....);
end;
end;
But it works when i did this

 function LoadBitmaps: Integer;
begin
bmp0 := BitmapFromString(.....);
bmp1 := BitmapFromString(.....);
bmp2 := BitmapFromString(.....);
end;[/code'

Thank you for you help

Coh3n

2009-12-04 16:13:21

From: scriptkitty
i see what i did now i tried to just use one instance with several results :duh:
function LoadBitmaps: Integer;
begin
bmp0: Result := BitmapFromString(.....);
bmp1: Result := BitmapFormString(.....);
bmp2: Result := BitmapFormString(.....);
end;
end;
But it works when i did this

 function LoadBitmaps: Integer;
begin
bmp0 := BitmapFromString(.....);
bmp1 := BitmapFromString(.....);
bmp2 := BitmapFromString(.....);
end;[/code'

Thank you for you help


You second one would work, yes, but it would be slower because it's loading all the bitmaps each time the function is called. When you use a case, it only loads the one you want. :smile:

CptTerrell

2009-12-10 11:26:46

WOW this will probably be the most helpful tutorial on the forums to me. I am going to try and make my first script using this tutorial :). I still have yet to read it all. But once again thanks and i look forward to crediting you in my script

Coh3n

2009-12-10 12:11:49

From: CptTerrell
WOW this will probably be the most helpful tutorial on the forums to me. I am going to try and make my first script using this tutorial :). I still have yet to read it all. But once again thanks and i look forward to crediting you in my script

Glad to see I helped you become interesting in scripting. :)

Cigue

2010-01-07 00:33:31

procedure Event;
var i : integer;
begin
if (i = 6) then
writeln('local var works')
else begin
i := 6;
writeln('localvarscheck');
end;
end;

begin
Event;
Event;
end.

Returns :
localvarscheck
localvarscheck

So this means that local variables reset when the procedure they're called in is over?

Coh3n

2010-01-07 09:51:12

From: Cigue
procedure Event;
var i : integer;
begin
if (i = 6) then
writeln('local var works')
else begin
i := 6;
writeln('localvarscheck');
end;
end;

begin
Event;
Event;
end.

Returns :
localvarscheck
localvarscheck

So this means that local variables reset when the procedure they're called in is over?

Yes, because it's local. :)

JackF

2010-01-13 06:48:47

Geat tut, thanks alot.

game over

2010-01-30 06:11:47

Wow very nice guide. thanks for posting this :)

WT-Fakawi

2010-05-05 18:53:10

Wow Coh3n! This is the best tutorial I have ever seen. Seriously: have you considered publishing this in a portable format, PDF for example? You have written a complete reference guide that ought to be included in SCAR, I'd say. (At least in SIMBA such a reference guide should be in the distro!!!)

Its awesome, truly amazing. I never could have dreamed someone actually write a book about SCAR… But you did!

You should send this to Kaitnieks :)



Superior work.

Coh3n

2010-05-05 18:59:21

From: WT-Fakawi
Wow Coh3n! This is the best tutorial I have ever seen. Seriously: have you considered publishing this in a portable format, PDF for example? You have written a complete reference guide that ought to be included in SCAR, I'd say. (At least in SIMBA such a reference guide should be in the distro!!!)

Its awesome, truly amazing. I never could have dreamed someone actually write a book about SCAR… But you did!

You should send this to Kaitnieks :)



Superior work.

Thanks very much! I'd really like to update it a lot and redo all the example for Simba and such. I plan on doing that eventually. And yes, I've thought about exporting as PDF, I just haven't gotten around to it yet. And unless there's a way to use the forums formatting in a word document, I'd have to go through the whole thing and get rid of all the tags and then go through again and format everything.

I'm willing to do it, it's just something that's hard to find the initiative for. :p

Oh, and were you serious when you said I should send to kaitnieks? Lol

WT-Fakawi

2010-05-05 19:24:23

From: Coh3n
I'd have to go through the whole thing and get rid of all the tags and then go through again and format everything.l

Maybe someone else can do that for you :)

From: Coh3n
Oh, and were you serious when you said I should send to kaitnieks? Lol
Dead serious.

Coh3n

2010-05-05 22:46:55

From: WT-Fakawi
Maybe someone else can do that for you :)

Dead serious.

Maybe. I may just start working at it slowly, and that way I can update the content as I go. Oh and I have no idea how I'd go about contacting kaitneiks… Does he have an email he uses frequently or anything?

E: Wow, if I just copy/paste directly from the forums (not the edit screen), the formatting and everything copies write to open office! :D I can upload a .PDF in a few minutes.

i luffs yeww

2010-05-05 23:06:42

[email]scar@kaitnieks.com[/email]
Or you could look for his work email.

Coh3n

2010-05-05 23:38:55

From: i luffs yeww
[email]scar@kaitnieks.com[/email]
Or you could look for his work email.

Alright, thanks. :)

Oh, and you can download a .PDF of the guide here. I just glanced through it, so some of the formatting may be messed up.

Drakan

2010-05-06 06:59:30

GREAT job coh3n! This is the most impressive, extensive, tutorial i have ever seen! Thanks bro :)

WT-Fakawi

2010-05-06 08:51:33

From: Coh3n
Alright, thanks. :)

Oh, and you can download a .PDF of the guide here. I just glanced through it, so some of the formatting may be messed up.


Its great. Now get someone to format it properly, and the six pages stamped with info will propagate to 20 pages Manual.

P.S. Open Office definately rules! But Google Docs does a equally well job at this.

Coh3n

2010-05-06 10:00:20

From: drags111
GREAT job coh3n! This is the most impressive, extensive, tutorial i have ever seen! Thanks bro :)

Thanks. :)

From: WT-Fakawi
Its great. Now get someone to format it properly, and the six pages stamped with info will propagate to 20 pages Manual.

P.S. Open Office definately rules! But Google Docs does a equally well job at this.

I've never actually used Google Docs, but my brother recently did a project with them and said they were pretty neat, so I'll have to take a look. :)

WT-Fakawi

2010-05-06 11:03:08

From: Coh3n
I've never actually used Google Docs, but my brother recently did a project with them and said they were pretty neat, so I'll have to take a look. :)


You could even work together by sharing docs on Google Docs.

Nava2

2010-05-06 11:36:41

From: Coh3n
Alright, thanks. :)

Oh, and you can download a .PDF of the guide here. I just glanced through it, so some of the formatting may be messed up.


https://docs.google.com/viewer?url=http://coh3n.webege.com/AIO%2520SCAR%2520Scripting%2520Guide.pdf&pli=1

Err, not legible. Just sayin.

E: When I downloaded it, it worked fine.. weird.

E2:
So I started going through a bit, with the Hello Worlds, could probably be slightly simpler, as well perhaps notes about the ToStr() function in Simba? :)

Coh3n

2010-05-06 12:18:57

From: Nava2
https://docs.google.com/viewer?url=http://coh3n.webege.com/AIO%2520SCAR%2520Scripting%2520Guide.pdf&pli=1

Err, not legible. Just sayin.

E: When I downloaded it, it worked fine.. weird.

E2:
So I started going through a bit, with the Hello Worlds, could probably be slightly simpler, as well perhaps notes about the ToStr() function in Simba? :)

Yeahh, there's A LOT that I don't know about Simba. I'll have to do a lot before I update it for Simba.

I'm going to slowly start updating it for Simba. I'll start with OO because I'm familiar with it, and apparently something went wrong when transferring to Google Docs. :s

i luffs yeww

2010-05-08 01:38:37

:) Maybe add try..except..finally? And I didn't check to see if you take about shl and shr, but it might be useful.

Coh3n

2010-05-09 18:34:27

From: i luffs yeww
:) Maybe add try..except..finally? And I didn't check to see if you take about shl and shr, but it might be useful.

try..except is already on my list of things to do for Simba. I'll add shr/shl (or just a link to a better tutorial on bitwise operations).

mrpickle

2010-05-10 10:26:42

Ur Tut > My Tech teacher

Coh3n

2010-05-10 10:44:21

From: mrpickle
Ur Tut > My Tech teacher

Haha thanks. :p

mrpickle

2010-05-11 19:41:22

I tried messing around with some of the example scripts you made. Keep getting an exception at the "DTM Not Found, Increasing Tolerance" when I try running on RS.


program TestWalker;
{.include srl/srl.scar}
{.include srl/srl/skill/mining.scar}

var
DDTMTolerance: Integer;

function DDTMToMine1: Integer;
var
dtmMainPoint: TDTMPointDef;
dtmSubPoints: Array [0..4] of TDTMPointDef;
TempTDTM: TDTM;
begin
// VRoadColor := FindVarrockRoadColor; // Not working
dtmMainPoint.x := 1035;
dtmMainPoint.y := 332;
dtmMainPoint.AreaSize := 0;
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := 5921877;
dtmMainPoint.Tolerance := DDTMTolerance;

dtmSubPoints[0].x := 1035;
dtmSubPoints[0].y := 332;
dtmSubPoints[0].AreaSize := 0;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := 5921877;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 1036;
dtmSubPoints[1].y := 329;
dtmSubPoints[1].AreaSize := 0;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := 4539711;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 1035;
dtmSubPoints[2].y := 334;
dtmSubPoints[2].AreaSize := 0;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := 4539711;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 1037;
dtmSubPoints[3].y := 337;
dtmSubPoints[3].AreaSize := 0;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := 4539711;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 1033;
dtmSubPoints[4].y := 333;
dtmSubPoints[4].AreaSize := 0;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := 4539711;
dtmSubPoints[4].Tolerance := DDTMTolerance;

TempTDTM.MainPoint := dtmMainPoint;
TempTDTM.SubPoints := dtmSubPoints;
Result := AddDTM(TempTDTM);
end;

function DDTMToMine2: Integer;
var
dtmMainPoint: TDTMPointDef;
dtmSubPoints: Array [0..4] of TDTMPointDef;
TempTDTM: TDTM;
begin
dtmMainPoint.x := 1001;
dtmMainPoint.y := 390;
dtmMainPoint.AreaSize := 0;
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := 16509686;
dtmMainPoint.Tolerance := DDTMTolerance;

dtmSubPoints[0].x := 1001;
dtmSubPoints[0].y := 390;
dtmSubPoints[0].AreaSize := 0;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := 16509686;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 998;
dtmSubPoints[1].y := 406;
dtmSubPoints[1].AreaSize := 0;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := 1268001;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 1008;
dtmSubPoints[2].y := 405;
dtmSubPoints[2].AreaSize := 0;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := 1268001;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 1012;
dtmSubPoints[3].y := 398;
dtmSubPoints[3].AreaSize := 0;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := 1268001;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 1006;
dtmSubPoints[4].y := 397;
dtmSubPoints[4].AreaSize := 0;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := 1268001;
dtmSubPoints[4].Tolerance := DDTMTolerance;

TempTDTM.MainPoint := dtmMainPoint;
TempTDTM.SubPoints := dtmSubPoints;
Result := AddDTM(TempTDTM);
end;

function Walk(DDTM: Integer):Boolean;
var
DDTMVarrokWalk, x, y: Integer;
begin
if not LoggedIn then Exit;
SetRun(True);
DDTMTolerance := (0);
//DDTMVarrokWalk := DDTM;
repeat
if not (DTMRotated(DDTM,x,y,MMX1,MMY1,MMX2,MMY2)) then
begin // When Not Find DDTM, Increase Tolerance
Writeln('DDTM not found, increasing Tolerance');
DDTMTolerance := DDTMTolerance + 5;
FreeDTM(DDTM);
//DDTMVarrokWalk := DDTM;
end else
begin // DDTM is Found
Writeln('Moving along the Varrok Road...');
Mouse(x,y+10+random(4),2+random(3),2+random(3),true);
Result := True;
Break;
end;
Until ((DDTMTOLERANCE >= 26) or not LoggedIn)
DDTMTolerance := (0);
FreeDTM(DDTM);
end;




begin
SetupSRL;
ActivateClient;
if (MakeCompass('n')) then
begin
if (Walk(DDTMToMine1)) then
begin
Writeln('Walked to Varrok East Gates --- PASS');
end else
begin
Writeln('Walked to Varrok East Gates --- FAIL');
end;
if (Walk(DDTMToMine2)) then
begin
Writeln('Walked to Building SE of Gates --- PASS');
end else
begin
Writeln('Walked to Building SE of Gates --- FAIL');
end;
end;
end.

Coh3n

2010-05-11 19:53:36

Try updating the colors. Those examples were written a long time ago (before the minimap graphics were updated).

mrpickle

2010-05-11 19:56:54

Oh i've done all the colours myself :), the script started failing when I added (DDTM:Integer) and allowed more variables in the function so I can use same set of code for different DDTMS by just changing one variable.

function Walk(DDTM: Integer):Boolean;

If I run your example with updated colours, its fine :)

Coh3n

2010-05-11 20:17:43

From: mrpickle
Oh i've done all the colours myself :), the script started failing when I added (DDTM:Integer) and allowed more variables in the function so I can use same set of code for different DDTMS by just changing one variable.

function Walk(DDTM: Integer):Boolean;

If I run your example with updated colours, its fine :)

Hmm you should be able to add vars/params, what's your code look like and what errors are you getting?

mrpickle

2010-05-11 20:22:11

SRL Compiled in 15 msec
DDTM not found, increasing Tolerance
[Runtime Error] : Exception: Access violation at address 007876D4 in module 'scar.exe'. Read of address 00000000 in line 77 in script …\scarprerelease\includes\SRL\SRL\Core\Color.scar

if you scroll down on the code I posted above… its everything :)

Coh3n

2010-05-11 20:35:01

From: mrpickle
SRL Compiled in 15 msec
DDTM not found, increasing Tolerance
[Runtime Error] : Exception: Access violation at address 007876D4 in module 'scar.exe'. Read of address 00000000 in line 77 in script …\scarprerelease\includes\SRL\SRL\Core\Color.scar

if you scroll down on the code I posted above… its everything :)

Does that happen every time? I think that's just SCAR failing. Have you tried just restarting SCAR?

mrpickle

2010-05-11 20:38:07

Scar fails after restarting it. 3.23 and 3.22. Same exception error.

Coh3n

2010-05-11 20:40:13

From: mrpickle
Scar fails after restarting it. 3.23 and 3.22. Same exception error.

Ohh, you're freeing the DDTM twice so the second time it's trying to free a dtm that isn't loaded.

mrpickle

2010-05-11 20:46:19

OMG! LOL ur right! Yeah, double Freed. Now it works, Thanks !

Coh3n

2010-05-11 20:47:43

From: mrpickle
OMG! LOL ur right! Yeah, double Freed. Now it works, Thanks !

No problem, glad it works now. :)

mrpickle

2010-05-11 20:53:47

Second Problem now. xD

Doing this, the script will find the DTM, and click

function Walk:Boolean;
var
DDTMVarrokWalk, x, y: Integer;
begin
if not LoggedIn then Exit;
SetRun(True);
DDTMTolerance := (3);
DDTMVarrokWalk := DDTMToMine1;
repeat
if not DTMRotated(DDTMVarrokWalk,x,y,MMX1,MMY1,MMX2,MMY2) then
begin // When Not Find DDTM, Increase Tolerance
Writeln('DDTM not found, increasing Tolerance');
DDTMTolerance := DDTMTolerance + 5;
// FreeDTM(DDTM);
DDTMVarrokWalk := DDTMToMine1;
end else
begin // DDTM is Found
Writeln('Moving along the Varrok Road...');
Mouse(x,y+10+random(4),2+random(3),2+random(3),true);
Result := True;
FreeDTM(DDTMVarrokWalk);
Break;
end;
Until ((DDTMTOLERANCE >= 26) or not LoggedIn)
DDTMTolerance := (0);
FreeDTM(DDTMToMine1);
end;

begin
SetupSRL;
ActivateClient;
if (MakeCompass('n')) then
begin
if Walk then
begin
Writeln('Walked to Varrok East Gates --- PASS');
end else
begin
Writeln('Walked to Varrok East Gates --- FAIL');
end;
end;
end.

Doing this the Program just keeps increasing tolerance, and don't find a match.

function Walk(DDTM: Integer):Boolean;
var
DDTMVarrokWalk, x, y: Integer;
begin
if not LoggedIn then Exit;
SetRun(True);
DDTMTolerance := (3);
DDTMVarrokWalk := DDTM;
repeat
if not DTMRotated(DDTMVarrokWalk,x,y,MMX1,MMY1,MMX2,MMY2) then
begin // When Not Find DDTM, Increase Tolerance
Writeln('DDTM not found, increasing Tolerance');
DDTMTolerance := DDTMTolerance + 5;
// FreeDTM(DDTM);
DDTMVarrokWalk := DDTM;
end else
begin // DDTM is Found
Writeln('Moving along the Varrok Road...');
Mouse(x,y+10+random(4),2+random(3),2+random(3),true);
Result := True;
FreeDTM(DDTM);
Break;
end;
Until ((DDTMTOLERANCE >= 26) or not LoggedIn)
DDTMTolerance := (0);
FreeDTM(DDTM);
end;




begin
SetupSRL;
ActivateClient;
if (MakeCompass('n')) then
begin
if (Walk(DDTMToMine1)) then
begin
Writeln('Walked to Varrok East Gates --- PASS');
end else
begin
Writeln('Walked to Varrok East Gates --- FAIL');
end;
if (Walk(DDTMToMine2)) then
begin
Writeln('Walked to Building SE of Gates --- PASS');
end else
begin
Writeln('Walked to Building SE of Gates --- FAIL');
end;
end;
end.

Coh3n

2010-05-11 22:36:47

You don't need to reassign the DDTMVarrockWalk variable if the DDTM isn't found. You also are still freeing the DTM twice.

Blumblebee

2010-05-12 00:25:43

From: Coh3n
You don't need to reassign the DDTMVarrockWalk variable if the DDTM isn't found. You also are still freeing the DTM twice.


if he is increasing the DTM tolerance he needs to reload the DDTM does he not?

Edit: like coh3n said your freeing your DTM twice, if you don't wish to change the code you could simply wrap the bottom FreeDTM() with a try..except allowing an exception to occur (freeing an already freed DDTM) and get away with it :)

mrpickle

2010-05-12 07:11:25

Sorry, I was geting excited yesterday, didn't explain problem properly xD.

When I run the "Walk" function (return boolean) with an additional parameter to incorporate varaible DDTMS (seen 3 posts up, second bundle of code), it fails with an "exception: access violation" error that leads me to line 77 in Color.scar.

But without changing the contents, and just removing the DDTM parameter of the Function, and replacing the entire fuction with constant DDTMs, it would work, click and everything (even with the double FreeDTM).

So, why did the Additional Variable integer parameter of DDTM on the function fail, and when it is removed, script works?

Coh3n

2010-05-12 09:51:28

From: Blumblebee
if he is increasing the DTM tolerance he needs to reload the DDTM does he not?

Yeah you're right, my bad.

From: mrpickle
Sorry, I was geting excited yesterday, didn't explain problem properly xD.

When I run the "Walk" function (return boolean) with an additional parameter to incorporate varaible DDTMS (seen 3 posts up, second bundle of code), it fails with an "exception: access violation" error that leads me to line 77 in Color.scar.

But without changing the contents, and just removing the DDTM parameter of the Function, and replacing the entire fuction with constant DDTMs, it would work, click and everything (even with the double FreeDTM).

So, why did the Additional Variable integer parameter of DDTM on the function fail, and when it is removed, script works?

It could be that the interpreter is acting weird. Try something like this:


function LoadDDTM(which): Integer;
//all the dtm vars here
begin
case which of
0: //the first ddtm here
1: //the second ddtm here
end;
end;

function Walk(where: Integer): Boolean;
var
pt: Integer;
begin
pt := LoadDDTM(where);

if DTMRotated...
end;

mrpickle

2010-05-12 20:18:02

No go man, Still fails, same error in Color.scar

Coh3n

2010-05-12 22:11:57

Can you post what you tried above?

mrpickle

2010-05-12 22:19:23


{.include srl/srl.scar}
{.include srl/srl/skill/mining.scar}


var
DDTMTolerance: Integer;

function DDTMToMine1: Integer;
var
dtmMainPoint: TDTMPointDef;
dtmSubPoints: Array [0..4] of TDTMPointDef;
TempTDTM: TDTM;
begin
// VRoadColor := FindVarrockRoadColor; // Not working
dtmMainPoint.x := 1035;
dtmMainPoint.y := 332;
dtmMainPoint.AreaSize := 1;
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := 5921877;
dtmMainPoint.Tolerance := DDTMTolerance;

dtmSubPoints[0].x := 1035;
dtmSubPoints[0].y := 332;
dtmSubPoints[0].AreaSize := 1;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := 5921877;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 1036;
dtmSubPoints[1].y := 329;
dtmSubPoints[1].AreaSize := 1;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := 4539711;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 1035;
dtmSubPoints[2].y := 334;
dtmSubPoints[2].AreaSize := 1;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := 4539711;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 1037;
dtmSubPoints[3].y := 337;
dtmSubPoints[3].AreaSize := 1;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := 4539711;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 1033;
dtmSubPoints[4].y := 333;
dtmSubPoints[4].AreaSize := 1;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := 4539711;
dtmSubPoints[4].Tolerance := DDTMTolerance;

TempTDTM.MainPoint := dtmMainPoint;
TempTDTM.SubPoints := dtmSubPoints;
Result := AddDTM(TempTDTM);
end;

function DDTMToMine2: Integer;
var
dtmMainPoint: TDTMPointDef;
dtmSubPoints: Array [0..4] of TDTMPointDef;
TempTDTM: TDTM;
begin
dtmMainPoint.x := 1001;
dtmMainPoint.y := 390;
dtmMainPoint.AreaSize := 1;
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := 16509686;
dtmMainPoint.Tolerance := DDTMTolerance;

dtmSubPoints[0].x := 1001;
dtmSubPoints[0].y := 390;
dtmSubPoints[0].AreaSize := 1;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := 16509686;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 998;
dtmSubPoints[1].y := 406;
dtmSubPoints[1].AreaSize := 1;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := 1268001;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 1008;
dtmSubPoints[2].y := 405;
dtmSubPoints[2].AreaSize := 1;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := 1268001;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 1012;
dtmSubPoints[3].y := 398;
dtmSubPoints[3].AreaSize := 1;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := 1268001;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 1006;
dtmSubPoints[4].y := 397;
dtmSubPoints[4].AreaSize := 1;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := 1268001;
dtmSubPoints[4].Tolerance := DDTMTolerance;

TempTDTM.MainPoint := dtmMainPoint;
TempTDTM.SubPoints := dtmSubPoints;
Result := AddDTM(TempTDTM);
end;

function DDTMToMine3: Integer;
var
dtmMainPoint: TDTMPointDef;
dtmSubPoints: Array [0..4] of TDTMPointDef;
TempTDTM: TDTM;
begin
dtmMainPoint.x := 1026;
dtmMainPoint.y := 389;
dtmMainPoint.AreaSize := 1;
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := 666678;
dtmMainPoint.Tolerance := 0;

dtmSubPoints[0].x := 1026;
dtmSubPoints[0].y := 389;
dtmSubPoints[0].AreaSize := 1;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := 666678;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 1023;
dtmSubPoints[1].y := 392;
dtmSubPoints[1].AreaSize := 1;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := 8489353;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 1009;
dtmSubPoints[2].y := 380;
dtmSubPoints[2].AreaSize := 1;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := 8489353;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 1007;
dtmSubPoints[3].y := 377;
dtmSubPoints[3].AreaSize := 1;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := 8489353;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 1017;
dtmSubPoints[4].y := 386;
dtmSubPoints[4].AreaSize := 1;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := 8489353;
dtmSubPoints[4].Tolerance := DDTMTolerance;

TempTDTM.MainPoint := dtmMainPoint;
TempTDTM.SubPoints := dtmSubPoints;
Result := AddDTM(TempTDTM);
end;

function LoadDDTM(WhichDDTM:integer):integer;
begin
case WhichDDTM of
0: Result := DDTMToMine1;
1: Result := DDTMToMine2;
2: Result := DDTMToMine3;
end;
end;

function ToMine(LoadWhichDDTM: Integer):Boolean;
var
x, y, DDTMVarrokToMine: Integer;
begin
if not LoggedIn then Exit;
SetRun(True);
DDTMTolerance := (3);
DDTMVarrokToMine := LoadDDTM(LoadWhichDDTM);
repeat
if not DTMRotated(DDTMVarrokToMine,x,y,550,8,703,161) then //Covers the Bitmap Area in "just fitting" Box
begin // When Not Find DDTM, Increase Tolerance
Writeln('DDTM not found, increasing Tolerance');
DDTMTolerance := DDTMTolerance + 4;
try
FreeDTM(DDTMVarrokToMine);
except
WriteLn('DDTM Freeing Failed');
end;
// DDTMVarrokToMine := DDTMToMine1;
end else

begin // DDTM is Found
Writeln('Moving along the Varrok Road...');
Mouse(x,y+10+random(4),2+random(3),2+random(3),true);
Result := True;
FreeDTM(DDTMVarrokToMine);
Break;
end;
Until ((DDTMTOLERANCE >= 25) or not LoggedIn)
DDTMTolerance := (0);
end;

begin
SetupSRL;
ActivateClient;
if (MakeCompass('n')) then
begin
if (ToMine(0)) then
begin
writeln ('ToMineed to Varrok East Gates --- PASS');
end else
writeln ('ToMineed to Varrok East Gates --- FAIL');
if (ToMine(1)) then
begin
writeln ('ToMineed Past Building SE of Gates --- PASS');
end else
writeln ('ToMineed Past Building SE of Gates --- FAIL');
if (ToMine(2)) then
begin
writeln ('ToMineed to Third Checkpoint --- PASS');
end else
writeln ('ToMineed to Third Checkpoint --- FAIL');
end;
end.

Coh3n

2010-05-12 22:27:04

Try

{.include srl/srl.scar}
{.include srl/srl/skill/mining.scar}


var
DDTMTolerance: Integer;

function LoadDDTM(WhichDDTM:integer):integer;
var
dtmMainPoint: TDTMPointDef;
dtmSubPoints: Array [0..4] of TDTMPointDef;
TempTDTM: TDTM;
begin
case WhichDDTM of
0: begin
dtmMainPoint.x := 1035;
dtmMainPoint.y := 332;
dtmMainPoint.AreaSize := 1;
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := 5921877;
dtmMainPoint.Tolerance := DDTMTolerance;

dtmSubPoints[0].x := 1035;
dtmSubPoints[0].y := 332;
dtmSubPoints[0].AreaSize := 1;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := 5921877;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 1036;
dtmSubPoints[1].y := 329;
dtmSubPoints[1].AreaSize := 1;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := 4539711;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 1035;
dtmSubPoints[2].y := 334;
dtmSubPoints[2].AreaSize := 1;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := 4539711;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 1037;
dtmSubPoints[3].y := 337;
dtmSubPoints[3].AreaSize := 1;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := 4539711;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 1033;
dtmSubPoints[4].y := 333;
dtmSubPoints[4].AreaSize := 1;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := 4539711;
dtmSubPoints[4].Tolerance := DDTMTolerance;
end;
1: begin
dtmMainPoint.x := 1001;
dtmMainPoint.y := 390;
dtmMainPoint.AreaSize := 1;
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := 16509686;
dtmMainPoint.Tolerance := DDTMTolerance;

dtmSubPoints[0].x := 1001;
dtmSubPoints[0].y := 390;
dtmSubPoints[0].AreaSize := 1;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := 16509686;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 998;
dtmSubPoints[1].y := 406;
dtmSubPoints[1].AreaSize := 1;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := 1268001;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 1008;
dtmSubPoints[2].y := 405;
dtmSubPoints[2].AreaSize := 1;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := 1268001;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 1012;
dtmSubPoints[3].y := 398;
dtmSubPoints[3].AreaSize := 1;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := 1268001;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 1006;
dtmSubPoints[4].y := 397;
dtmSubPoints[4].AreaSize := 1;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := 1268001;
dtmSubPoints[4].Tolerance := DDTMTolerance;
end;
2: begin
dtmMainPoint.x := 1026;
dtmMainPoint.y := 389;
dtmMainPoint.AreaSize := 1;
dtmMainPoint.AreaShape := 0;
dtmMainPoint.Color := 666678;
dtmMainPoint.Tolerance := 0;

dtmSubPoints[0].x := 1026;
dtmSubPoints[0].y := 389;
dtmSubPoints[0].AreaSize := 1;
dtmSubPoints[0].AreaShape := 0;
dtmSubPoints[0].Color := 666678;
dtmSubPoints[0].Tolerance := DDTMTolerance;

dtmSubPoints[1].x := 1023;
dtmSubPoints[1].y := 392;
dtmSubPoints[1].AreaSize := 1;
dtmSubPoints[1].AreaShape := 0;
dtmSubPoints[1].Color := 8489353;
dtmSubPoints[1].Tolerance := DDTMTolerance;

dtmSubPoints[2].x := 1009;
dtmSubPoints[2].y := 380;
dtmSubPoints[2].AreaSize := 1;
dtmSubPoints[2].AreaShape := 0;
dtmSubPoints[2].Color := 8489353;
dtmSubPoints[2].Tolerance := DDTMTolerance;

dtmSubPoints[3].x := 1007;
dtmSubPoints[3].y := 377;
dtmSubPoints[3].AreaSize := 1;
dtmSubPoints[3].AreaShape := 0;
dtmSubPoints[3].Color := 8489353;
dtmSubPoints[3].Tolerance := DDTMTolerance;

dtmSubPoints[4].x := 1017;
dtmSubPoints[4].y := 386;
dtmSubPoints[4].AreaSize := 1;
dtmSubPoints[4].AreaShape := 0;
dtmSubPoints[4].Color := 8489353;
dtmSubPoints[4].Tolerance := DDTMTolerance;
end;
end;

TempTDTM.MainPoint := dtmMainPoint;
TempTDTM.SubPoints := dtmSubPoints;
Result := AddDTM(TempTDTM);
end;

function ToMine(LoadWhichDDTM: Integer):Boolean;
var
x, y, DDTMVarrokToMine: Integer;
begin
if not LoggedIn then Exit;
SetRun(True);
DDTMTolerance := (3);
DDTMVarrokToMine := LoadDDTM(LoadWhichDDTM);
repeat
if not DTMRotated(DDTMVarrokToMine,x,y,550,8,703,161) then //Covers the Bitmap Area in "just fitting" Box
begin // When Not Find DDTM, Increase Tolerance
Writeln('DDTM not found, increasing Tolerance');
DDTMTolerance := DDTMTolerance + 4;
DDTMVarrokToMine := DDTMToMine1;
end else

begin // DDTM is Found
Writeln('Moving along the Varrok Road...');
Mouse(x,y+10+random(4),2+random(3),2+random(3),true);
Result := True;
Break;
end;
Until ((DDTMTOLERANCE >= 25) or not LoggedIn)
DDTMTolerance := (0);
FreeDTM(DDTMVarrokToMine);
end;

begin
SetupSRL;
ActivateClient;
if (MakeCompass('n')) then
begin
if (ToMine(0)) then
begin
writeln ('ToMineed to Varrok East Gates --- PASS');
end else
writeln ('ToMineed to Varrok East Gates --- FAIL');
if (ToMine(1)) then
begin
writeln ('ToMineed Past Building SE of Gates --- PASS');
end else
writeln ('ToMineed Past Building SE of Gates --- FAIL');
if (ToMine(2)) then
begin
writeln ('ToMineed to Third Checkpoint --- PASS');
end else
writeln ('ToMineed to Third Checkpoint --- FAIL');
end;
end.

mrpickle

2010-05-12 22:34:50

That works after line 164 var change.

However, now script is unable to detect any colours… worked the inefficient way.

Also, at end of the last DDTMdetection, I get "[Runtime Error] : Exception: Access violation at address 00406B20 in module 'scar.exe'. Read of address FFFFFFFF in line 175 in "

>.<Now I would prefer to do Radial walking instead xD.

EDIT: Away for ~8 hours.

Coh3n

2010-05-12 22:37:18

From: mrpickle
That works after line 164 var change.

However, now script is unable to detect any colours… worked the inefficient way.

Also, at end of the last DDTMdetection, I get "[Runtime Error] : Exception: Access violation at address 00406B20 in module 'scar.exe'. Read of address FFFFFFFF in line 175 in "

>.<Now I would prefer to do Radial walking instead xD.

EDIT: Away for ~8 hours.

Yeah sorry I never checked to see if it compiled. The way you have it (before what I posted above) will work, you just put the try..except block on the wrong FreeDTM statement.

mrpickle

2010-05-13 15:36:32

I'm kinda convinced that the problem doesn't lie with the code. Still doesn't work. Same error, no matter which FreeDTM I place in the Try / Except


Looking at ur Radial walking now :)

Coh3n

2010-05-13 16:05:13

From: mrpickle
I'm kinda convinced that the problem doesn't lie with the code. Still doesn't work. Same error, no matter which FreeDTM I place in the Try / Except


Looking at ur Radial walking now :)

Then where would the problem lie?

mrpickle

2010-05-13 16:16:32

If it worked the more inefficient way by stating all the different DDTMs in different functions, i'm pretty sure that its not the code that is making it screw up…

But… perhaps if you run it on runescape VEB? Maybe my computer got screwed up? Otherwise, it could just be scar.

Coh3n

2010-05-13 16:25:50

From: mrpickle
If it worked the more inefficient way by stating all the different DDTMs in different functions, i'm pretty sure that its not the code that is making it screw up…

But… perhaps if you run it on runescape VEB? Maybe my computer got screwed up? Otherwise, it could just be scar.

Well you coded it one way and it worked, then you coded a different way that didn't work. Logically, it makes sense that there is something wrong with the code that doesn't work.

mrpickle

2010-05-23 21:24:32

Sry for continually bugging you xD… but.

I'm messing around with Types. Wondering, how do I use a type as an integer?

say:

Type
SRecord = record
MoveCoordinateX : array [1..4]of Integer;
MoveCoordinateY : array [1..4]of Integer;
end;

Movement:Array of SRecord;

Procedure Example (x,y:integer)
begin
DoSomething(x,y,blah,blah,blah);
end;

begin
With Movement[0] do
begin
MoveCoordinateX[0] := 1 ;
MoveCoordinateY[0] := 3 ;
end;
///
Example(SRecord.MoveCoordinateX[0],SRecord.MoveCoordinateX[0]); // How to make this part work?
/// I get class type error.
end.

Edit: Changed that line to Movement.MoveCoordinateX[0]… That worked. Thanks MylesMadness =D.

Coh3n

2010-05-24 09:43:18

From: mrpickle
Edit: Changed that line to Movement.MoveCoordinateX[0]… That worked. Thanks MylesMadness =D.

Yes. ;)

Glad you got it sorted out.

mrpickle

2010-05-24 09:59:49

After everything compiles, my first run ended with an exception error on a line where it's a simple If Findbitmap. I kinda get the feeling I missed something obvious and am trying too hard >.<.


I used it like this.

var BattleButton:integer;

procedure Loadbitmaps:
...

Function ClickBitmap(Bitmap,Xchange,xRandom,Ychange,yRandom:integer):boolean;
var x,y:integer;
begin
if(not(FindBitmap(Bitmap,x,y)))then /// I get exception @ this line
begin
writeln('Could not Locate the Bitmap To click');
writeln('Please make sure that the entire screen is visible');
Result := false;
end else
begin
Mouse(x+Xchange+random(xRandom),y+Ychange+random(yRandom),2+random(3),2+random(3),true);
freebitmap(Bitmap);
Result := true;
end;
end;

Function WaitForBitmap( Bitmap,DelayRate, MaxAmountOfDelay:integer):Boolean;
var timer,x,y:integer;
begin
repeat
wait(DelayRate);
Timer := Timer + 1
If Timer > MaxAmountOfDelay then
Writeln ('Bitmap '+ InttoStr(Bitmap) + ' Took too long to load');
Result := false;
Break;
until (FindBitmap(Bitmap,x,y))
FreeBitmap(Bitmap);
Result := true;
end;

begin
If(WaitforBitmap(BattleButton,500,50))then
begin
If(ClickBitmap(BattleButton,0,100,-5,15)) then
end else
begin
break;
end;
end.

Coh3n

2010-05-24 10:02:45

Can you post the whole error?

mrpickle

2010-05-24 10:06:55

[Runtime Error] : Exception: Access violation at address 006BDFF1 in module 'scar.exe'. Read of address 00000040 in line 183 in script

Coh3n

2010-05-24 10:23:39

You never called LoadBitmaps in your mainloop, so it's trying to find a bitmap that hasn't been loaded, and therefore doesn't exist.

mrpickle

2010-05-24 10:34:11

I did =S

begin
setupSRL;
LoadBitmaps;
BattleCount := 0;
Repeat

If(WaitforBitmap(BattleButton,500,50))then
begin
If(ClickBitmap(BattleButton,0,100,-5,15)) then
begin
writeln('Clicked the Battle Button on main page');
end;
end else
begin
break;
end;
...

mrpickle

2010-05-24 10:37:48

in my program there, the first bitmap that is used is during the "Waitforbitmap" function. That same bitmap is used again in "Clickbitmap" right after.

soo error should be in wait for bitmap if I didn't load properly. therefore, I loaded properly. :)




Edit: it worked after I removed all the freebitmaps.

Frement

2010-05-24 10:45:57

From: mrpickle
in my program there, the first bitmap that is used is during the "Waitforbitmap" function. That same bitmap is used again in "Clickbitmap" right after.

soo error should be in wait for bitmap if I didn't load properly. therefore, I loaded properly. :)




Edit: it worked after I removed all the freebitmaps.


Well you free it in the first function :)

Coh3n

2010-05-24 10:47:01

In the first script you posted you didn't call it in the mainloop. You never load the bitmap again after freeing it in WaitForBitmap. If you load the bitmaps at the beginning of the script, you don't have to free them until you're completely finished using them. You could also just load/free the bitmaps in each procedure you use them it (which is what I do).

E: Lol ninga'd.

mrpickle

2010-05-24 11:02:33

I've changed script to load each bitmap repeatedly, and freeing repeatedly. Easier to manage too :).


moar problems ^^'.

I've messed around with this function that I made last year. I never really tested it before.
It does not do its job when I run it. It only runs once through the loop even if bitmap is still nonexistant. The code looked fine to me.


Function WaitForBitmap(Bitmap,DelayRate, MaxAmountOfDelay:integer):Boolean;
var timer,x,y:integer;
begin
Repeat
wait(DelayRate);
Timer := Timer + 1
writeln('test');
If Timer > MaxAmountOfDelay then
Writeln ('Bitmap '+ InttoStr(Bitmap) + ' Took too long to load');
break;
Until(FindBitmap(Bitmap,x,y);
//FreeBitmap(Bitmap);
if(FindBitmap(Bitmap,x,y))then
begin
Result := true;
end else
Result := false;
end;

Coh3n

2010-05-24 11:04:51

It's because you have it break out of the loop after one try no matter what. You need a being..end nest.

If Timer > MaxAmountOfDelay then
begin
Writeln ('Bitmap '+ InttoStr(Bitmap) + ' Took too long to load');
break;
end;

mrpickle

2010-05-24 11:08:00

0_o… my last year's mistake haunts me today… and I didn't see it =[…

Thanks again Cohen.

Coh3n

2010-05-24 11:09:34

From: mrpickle
0_o… my last year's mistake haunts me today… and I didn't see it =[…

Thanks again Cohen.

Anytime. :)

anonymity

2010-06-18 20:12:25

I am impressed by the comprehensiveness and all around encompassed information you provide(d). I would have rep`d you for it, but it won't let me ;). Your tut is a great and proud piece of the island.

Coh3n

2010-06-18 20:17:21

From: anonymity
I am impressed by the comprehensiveness and all around encompassed information you provide(d). I would have rep`d you for it, but it won't let me ;). Your tut is a great and proud piece of the island.

Why thank you kind sir. :)

anc13nt noob

2010-06-19 19:23:12

Nice tutorial although there are a few things I have noticed

  • Some poor grammar in places, but nothing which you can't make sense of which is good.
  • Some of the script examples are outdated for example "FindVarockRoadColor" don't seem to be working so I am assuming they have been deprecated. I have looked through the SRL core myself and tried using "LoadAutoColor" but couldn't seem to get the right parameters to get it working =/
  • P.s have never been good with params so this is a fault on my part.
Apart from that great tutorial so far, i plan to read the rest of it tomorrow and maybe start working on a script!

Sabzi

2010-06-19 20:47:15

@anc13nt noob: If you are interested in the new AutoColor "system" and want to use it then look here: http://villavu.com/forum/showthread.php?t=57021

@Coh3n: You should take a look at that link too I guess. You must have missed some SRL update, my friend. That you made :pinch:

EDIT: Oh lol, smiley is not white :duh:. (but it's a must there)

anc13nt noob

2010-06-19 21:14:01

From: Sabzi
@anc13nt noob: If you are interested in the new AutoColor "system" and want to use it then look here: http://villavu.com/forum/showthread.php?t=57021

@Coh3n: You should take a look at that link too I guess. You must have missed some SRL update, my friend. That you made :pinch:

EDIT: Oh lol, smiley is not white :duh:. (but it's a must there)


Thanks very much Sabzi, this has cleared my problem up, now just to make it work with the script snippet so i can understand how to use it then i can continue reading more of your tutorial Coh3n.

Thanks both of you :)

Edit

———————————————————–

Okay a slight problem now, i have got the script to find the color of the water but for some reason the radial walk function is not working, even when i choose my own co ordinates for it to walk?

This is the progress report i get

SRL Compiled in 16 msec
Preparing to get the water color...
** Warning in LoadAutoColor: Function Successful: Found Color = 9470852 **
Obtained the water color
Radial walking method failed.
Successfully executed

And below is the example script which i slightly modified to get it working + some debug code in case i messed up.


program RadialWalkExample;
{.include SRL/SRL.scar}

var
DraynorWaterColor: Integer;

function FindWaterColor: Integer;
begin
if not LoggedIn then Exit;
Writeln('Preparing to get the water color...');
DraynorWaterColor := AutoColor(srl_waterColor);
Writeln('Obtained the water color');
end;


function WalkToWillows: Boolean;
begin
if not LoggedIn then Exit;//Get into the habbit of writing this in all your procedures early.
SetRun(True);
Result := RadialWalk(DraynorWaterColor, 190, 225, 50, 2, 1);//Notice how the Result is true if it walks to the Willows.
if Result then
begin
Writeln('We are walking to the Willow trees, Radial walk method.');
Wait(80 + Random(100));
FFlag(3);
end else
Writeln('Radial walking method failed.');
end;
//You may notice that there is no point in the function that clicks the mouse. This is because it is already incorperated into RadialWalk. So, there is no need to click twice.

begin
ClearDebug;
SetupSRL;
ActivateClient;
FindWaterColor;
if not WalkToWillows then//Decided to do something differet this time.
TerminateScript;//This means that if it doesn't walk to the Willows, the script will execute.
end.

Coh3n

2010-06-20 20:09:29

From: anc13nt noob
Nice tutorial although there are a few things I have noticed

  • Some poor grammar in places, but nothing which you can't make sense of which is good.
  • Some of the script examples are outdated for example "FindVarockRoadColor" don't seem to be working so I am assuming they have been deprecated. I have looked through the SRL core myself and tried using "LoadAutoColor" but couldn't seem to get the right parameters to get it working =/
  • P.s have never been good with params so this is a fault on my part.
Apart from that great tutorial so far, i plan to read the rest of it tomorrow and maybe start working on a script!


From: Sabzi
@anc13nt noob: If you are interested in the new AutoColor "system" and want to use it then look here: http://villavu.com/forum/showthread.php?t=57021

@Coh3n: You should take a look at that link too I guess. You must have missed some SRL update, my friend. That you made :pinch:

EDIT: Oh lol, smiley is not white :duh:. (but it's a must there)

Yeah, there are parts of this that aren't up to date as a lots changed since I wrote it. I do plan on updating it all for Simba and SRL 5 once they've both been released. But for the most part, the examples should still work.

From: anc13nt noob
Thanks very much Sabzi, this has cleared my problem up, now just to make it work with the script snippet so i can understand how to use it then i can continue reading more of your tutorial Coh3n.

Thanks both of you :)

Edit

———————————————————–

Okay a slight problem now, i have got the script to find the color of the water but for some reason the radial walk function is not working, even when i choose my own co ordinates for it to walk?

This is the progress report i get

SRL Compiled in 16 msec
Preparing to get the water color...
** Warning in LoadAutoColor: Function Successful: Found Color = 9470852 **
Obtained the water color
Radial walking method failed.
Successfully executed

And below is the example script which i slightly modified to get it working + some debug code in case i messed up.


program RadialWalkExample;
{.include SRL/SRL.scar}

var
DraynorWaterColor: Integer;

function FindWaterColor: Integer;
begin
if not LoggedIn then Exit;
Writeln('Preparing to get the water color...');
DraynorWaterColor := AutoColor(srl_waterColor);
Writeln('Obtained the water color');
end;


function WalkToWillows: Boolean;
begin
if not LoggedIn then Exit;//Get into the habbit of writing this in all your procedures early.
SetRun(True);
Result := RadialWalk(DraynorWaterColor, 190, 225, 50, 2, 1);//Notice how the Result is true if it walks to the Willows.
if Result then
begin
Writeln('We are walking to the Willow trees, Radial walk method.');
Wait(80 + Random(100));
FFlag(3);
end else
Writeln('Radial walking method failed.');
end;
//You may notice that there is no point in the function that clicks the mouse. This is because it is already incorperated into RadialWalk. So, there is no need to click twice.

begin
ClearDebug;
SetupSRL;
ActivateClient;
FindWaterColor;
if not WalkToWillows then//Decided to do something differet this time.
TerminateScript;//This means that if it doesn't walk to the Willows, the script will execute.
end.

So it's finding the colour, just not where you have the radials setup. RadialWalkTolerance was also added to SRL after I wrote this guide, so I would recommend using that, or even better, RadialWalkAutoColor. Using either of those should solve you problem. :)

mrpickle

2010-06-28 11:21:49

Hey Cohn, is it possible to return a Type?

Sabzi

2010-06-28 12:10:01

From: mrpickle
Hey Cohn, is it possible to return a Type?


A function can return your own type, yes. If that's what you mean.

Coh3n

2010-06-28 18:31:39

From: mrpickle
Hey Cohn, is it possible to return a Type?

Yes. Generally, they're used something like this:

program ReturnTypeExample;

type
TRock = record
name: string;
uptext: string;
color: integer;
end;

function GetRock: TRock;
begin
with result do
begin
name := 'Iron';
uptext := 'ine';
color := 0123456;
end;
end;

begin
writeln(GetRock.name);
end.
Run that and it should output the rocks name.

mrpickle

2010-06-28 21:56:05

Ah, alright :). Thanks.

Edit2:
I've successfully created a function that returns type. However, on the last line i'm getting a Class Type Expected error.

Edit3:
Maybe something like. Type to int? I can't find one in manual.


Program AirCrafter;
{.include srl/srl.scar}

type
Grids = record
Gridx :Integer;
Gridy :Integer;
end;

var WestBankTree1,WestBankTree2:Integer;
var x,y:Integer;

const
PixelInGrid = 4;

Procedure LoadBitmaps;
begin
WestBankTree1 := BitmapFromString(1, 2, 'beNoz4FCMFIgCAANXAR0=');
WestBankTree2 := BitmapFromString(1, 2, 'beNrT4VAMFYgCAAMzARU=');
end;

Function StartGridFromBank:Grids;
var ToStartGridx,ToStartGridy:Integer;
begin
MakeCompass('N');
If(FindBitmapin(WestBankTree1,x,y,550,92,601,125) or FindBitmapin(WestBankTree2,x,y,550,92,601,125))Then
begin
ToStartGridx := x + 45;
ToStartGridy := y + 4;

Mouse(ToStartGridx,ToStartGridy,0,2,true);

With Result do
begin
Gridx := 57;
Gridy := 0;
end;
end else
writeln('fail');
end;

Function MoveGrids(StartGridx,StartGridy,MoveXGrid,MoveYGrid:Integer):Grids;
begin
Mouse(MoveXGrid*PixelInGrid,MoveYGrid*PixelInGrid,0,0,true);
With result do
begin
Gridx := StartGridx + MoveXGrid;
Gridy := StartGridy + MoveYGrid;
end;
end;








begin
setupSRL;
LoadBitmaps;
//repeat
StartGridFromBank;

MoveGrids(Grids.Gridx,Grids.Gridy,5,5); //////// Class Type Expected. isn't Grids.Gridx and integer?
// until (False)
end.

i luffs yeww

2010-06-28 22:59:03

:) I see you're working on the air crafter for the competition. ;) Good luck to you.

I'm not quite sure what you're asking though?

mrpickle

2010-06-29 09:09:28

I can see where it gets kinda confusing. i'll reword my post.

and gl to you too :)… i only got a few days left cuz i'mma be away for 3 weeks xD.

Sabzi

2010-06-29 09:53:55

You are using a function there which returns your type that you don't pass to anything. Any function with any type it returns would cause the same.(if used like this)

Make a var like MyGrids: Grids;
then do
MyGrids := MoveGrids blabla;

Oh and you must declare a variable after the type declaration(if it's the type you want to use).

EDIT: Oh, I see now :p. You can't use a type as a variable. A type is like an integer, string, boolean. They doesn't hold values. You have to make variables with the types you created to make it work :).

But let's the code speak!
Program AirCrafter;
{.include srl/srl.scar}

type
Grids = record
x :Integer; //making it more readable imo, should change the rest of the code accordingly, though
y :Integer;
end;

var WestBankTree1,WestBankTree2:Integer;
var x,y:Integer;

const
PixelInGrid = 4;

Procedure LoadBitmaps;
begin
WestBankTree1 := BitmapFromString(1, 2, 'beNoz4FCMFIgCAANXAR0=');
WestBankTree2 := BitmapFromString(1, 2, 'beNrT4VAMFYgCAAMzARU=');
end;

Function StartGridFromBank:Grids;
var ToStartGridx,ToStartGridy:Integer;
begin
MakeCompass('N');
If(FindBitmapin(WestBankTree1,x,y,550,92,601,125) or FindBitmapin(WestBankTree2,x,y,550,92,601,125))Then
begin
ToStartGridx := x + 45;
ToStartGridy := y + 4;

Mouse(ToStartGridx,ToStartGridy,0,2,true);

With Result do
begin
Gridx := 57;
Gridy := 0;
end;
end else
writeln('fail');
end;

Function MoveGrids(StartGridx,StartGridy,MoveXGrid,MoveYGrid:Integer):Grids;
begin
Mouse(MoveXGrid*PixelInGrid,MoveYGrid*PixelInGrid,0,0,true);
With result do
begin
Gridx := StartGridx + MoveXGrid;
Gridy := StartGridy + MoveYGrid;
end;
end;

var //I am declaring the variable here.
MyGrids: Grids;

begin
setupSRL;
LoadBitmaps;
//repeat
MyGrids := StartGridFromBank;

MyGrids := MoveGrids(MyGrids.x, MyGrids.y, 5, 5); //You can make as many variable as Grids as you want, but I
//just reuse it.
// until (False)
end.

mrpickle

2010-06-29 10:13:17

Oh, gotta declare another one. and more readable variables :D

blother

2011-07-21 18:58:49

Checking this out because it is soo good and it is easy to find good information even if it is for scar and not simba.

I was just wondering if there is a difference between bitmaps and DTMs. Learning what i should use for the first script i am finally going to make and didn't know if one was easier or if one was better to use.

Also, will definately check this out more once i get a little bit experience and try making different scripts.

Dgby714

2011-07-21 19:02:54

From: blother
Checking this out because it is soo good and it is easy to find good information even if it is for scar and not simba.

I was just wondering if there is a difference between bitmaps and DTMs. Learning what i should use for the first script i am finally going to make and didn't know if one was easier or if one was better to use.

Also, will definately check this out more once i get a little bit experience and try making different scripts.


DTMs are only a few dots of specific color (Outline of an Item?) or tol (Middle of item)
Bitmaps are the whole image and can be specific or have tol

blother

2011-07-22 11:01:39

From: Dgby714
DTMs are only a few dots of specific color (Outline of an Item?) or tol (Middle of item)
Bitmaps are the whole image and can be specific or have tol


So, are bitmaps better or more reliable?

Dgby714

2011-07-22 11:07:09

From: blother
So, are bitmaps better or more reliable?


It all depends on what you're doing.

Coh3n

2011-07-22 11:26:18

From: blother
So, are bitmaps better or more reliable?
I would say DTMs are more reliable, but we've had a lot of issues with DTMs in MSI. In most cases you should be fine, but with bitmaps you can have an image of the entire item if you wish.

blother

2011-07-22 11:56:45

From: Coh3n
I would say DTMs are more reliable, but we've had a lot of issues with DTMs in MSI. In most cases you should be fine, but with bitmaps you can have an image of the entire item if you wish.


Well, in your example of DTMs you can use the entire item, which i am assuming is because the black outline surronds it all. So with something like iron ore you would have to pick one of the pieces because each little piece has an outline around it. I would think a bitmap would be better for an item like this.

In a different tutorial on bitmaps it was saying you shouldn't use the whole image and you should use just part of it. Would this limit where it will click on the item though?

Coh3n

2011-07-22 13:08:54

From: blother
Well, in your example of DTMs you can use the entire item, which i am assuming is because the black outline surronds it all. So with something like iron ore you would have to pick one of the pieces because each little piece has an outline around it. I would think a bitmap would be better for an item like this.
You don't pick every black outline pixel, just 3 or 4 of them.

From: blother

In a different tutorial on bitmaps it was saying you shouldn't use the whole image and you should use just part of it. Would this limit where it will click on the item though?
Yes, it would only click where the bitmap appears (i.e. only click an area as big as the image).

blother

2011-07-23 22:21:57

From: Coh3n
You don't pick every black outline pixel, just 3 or 4 of them.

Yes, it would only click where the bitmap appears (i.e. only click an area as big as the image).


I know you only use a few of them, but you can't pick ones on other parts of the item. If you look at the ores each individual rock piece in the picture has a black outline around it. You can only use the ones around one of the pieces, so i was think i bitmap would be smarter so it looks like you click on more parts of the item. Sorry if that is hard to follow my thinking is foggy right now.

KingKong

2011-07-23 23:16:36

From: blother
So, are bitmaps better or more reliable?


Yes, they are more reliable, because the dtms for different objects can be the same(eg: ores, necklaces, bars, rings and so on) and if searching for items in inventory, it will be easier for it stuff up, whereas IMO bitmaps are better since it won't confuse one item for another.

blother

2011-07-24 12:04:38

From: KingKong
Yes, they are more reliable, because the dtms for different objects can be the same(eg: ores, necklaces, bars, rings and so on) and if searching for items in inventory, it will be easier for it stuff up, whereas IMO bitmaps are better since it won't confuse one item for another.


Ok thanks. Do most people use bitmaps?

BraK

2011-07-24 12:16:51

From: blother
Ok thanks. Do most people use bitmaps?


It depends on what your trying to do as to whether or not you use Bitmaps. If you can be done with TPAs your better off with those. Bitmaps are best when kept very small.

~BraK

Coh3n

2011-07-24 16:18:19

From: blother
I know you only use a few of them, but you can't pick ones on other parts of the item. If you look at the ores each individual rock piece in the picture has a black outline around it. You can only use the ones around one of the pieces, so i was think i bitmap would be smarter so it looks like you click on more parts of the item. Sorry if that is hard to follow my thinking is foggy right now.
No, you can pick the main point color on any of the "ore pieces" then pick a black outline point on any of the other pieces. They don't all have to be on the same "piece", they just have to be somewhere on the ore.

blother

2011-07-24 20:54:49

From: Coh3n
No, you can pick the main point color on any of the "ore pieces" then pick a black outline point on any of the other pieces. They don't all have to be on the same "piece", they just have to be somewhere on the ore.


OK thanks for clearing that up.

I haven't learned too much about TPAs yet. I'm going to try DTMs and bitmaps first to learn about them.

MuffinMan

2011-12-03 12:29:43

Very nice work! Might try it later… Seems a bit complicated but, meh im new

Swatarianess

2011-12-19 08:15:10

Best tut i've read aswell as the other one on the fourm ^^ thanks i gotta read it more times

LordJashin

2012-02-11 21:10:28

This guide is gold, the scroll bar alone is a testimony to its worth. I don't understand why a guide like this isn't linked to, compared to all of SCAR's wiki's, manuals, they don't even touch this. This is like scar'smanual+wiki+functionlists * 100.

I'll be using this so much lol, seeing this makes me wanna ddos or somehow hack and change all those old dead guides over at scar sites, and replace them with this guide and a better function list.

Seriously gz you explain everything and its a books length long. Godlies are forever

This is godlike <3

likelike697

2012-02-15 20:38:48

i downloaded all this and printed it out im still working on gettn allllllllllllllll that info in my brain alot 2 get in 1 day =-[]

Godli

2012-02-15 21:35:54

Vary Vary big but thanks for all the effort put in to this post will bookmark and try a basic mining bot to start of with.

kunzy

2012-02-18 18:54:28

thanks for the guide, will read and try to learn =D

zyxw121

2012-02-25 06:47:22

Great tutorial, it helped me a alot.

Mr Stoj

2012-03-06 17:32:49

thank you, this has helped me understand simba future

Taikei no Yuurei

2012-03-10 09:53:58

Did simba change its bitmap loader since the tutorial was written? First off it seems to be called bitmap conversion in the tools menu now, and second off I can't do anything with it. I can't scroll the window, I can't zoom, I can't select a specific area I want it to convert. It wouldn't even let me paste into it, I had to paste into paint and save it, then load it.

Any help on how to do a bitmap now?

Taikei no Yuurei

2012-03-10 11:13:01

Alright, I went over to the bitmap tutorial and am going to use that. Seems things have changed.

Coh3n

2012-03-10 15:10:38

From: Taikei no Yuurei
Did simba change its bitmap loader since the tutorial was written? First off it seems to be called bitmap conversion in the tools menu now, and second off I can't do anything with it. I can't scroll the window, I can't zoom, I can't select a specific area I want it to convert. It wouldn't even let me paste into it, I had to paste into paint and save it, then load it.

Any help on how to do a bitmap now?
Because this tutorial is for SCAR. Almost all of the programming part of it is the same, but some things like the bitmap editor and DTM editor are different.

kunzy

2012-04-04 20:30:49

Woo, thanks for this coh3n.. huge effort in that ++rep ill check it out and read it when i have time 0_O

tvain

2013-01-02 11:46:10

From: Coh3n
Because this tutorial is for SCAR. Almost all of the programming part of it is the same, but some things like the bitmap editor and DTM editor are different.


Since the coding is pretty much the same I just need to figure out how to get the BITMAPS and DTMS and I'll be able to follow you no problem with SIMBA for the INTERMEDIATE section of your tut?

StickToTheScript

2013-03-23 21:48:24

This hurt my brain soo much, but its good! Thanks!

Ian

2013-03-23 22:10:16

From: StickToTheScript
This hurt my brain soo much, but its good! Thanks!


You should check out Coh3n's tutorial, it's like this one but updated. Also I find Coh3n explains things in a way that's easy for a new scripter to understand :).

StickToTheScript

2013-03-23 22:11:40

From: BMWxi
You should check out Coh3n's tutorial, it's like this one but updated. Also I find Coh3n explains things in a way that's easy for a new scripter to understand :).


Give me a link?

Ian

2013-03-23 22:17:23

From: StickToTheScript
Give me a link?


Here you go :) http://villavu.com/forum/showthread.php?t=58935

StickToTheScript

2013-03-23 23:49:16

From: BMWxi
Here you go :) http://villavu.com/forum/showthread.php?t=58935


Thanks! Ill read into it!

Edit: Yeah, i read that one already.. But thanks for the help anyways, BMWxi!