Page 1 of 8 123 ... LastLast
Results 1 to 25 of 184

Thread: All-In-One SCAR Scripting Tutorial!

  1. #1
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default All-In-One SCAR Scripting Tutorial!

    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!

    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.


    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!
    Last edited by Coh3n; 09-13-2010 at 04:21 AM.

  2. #2
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    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." 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:
    SCAR Code:
    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.

    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:
    SCAR Code:
    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.


    SCAR Code:
    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:

    SCAR Code:
    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:
    SCAR Code:
    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:

    SCAR Code:
    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.

    SCAR Code:
    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?

    SCAR Code:
    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:

    Code:
    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!

    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:
      SCAR Code:
      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.

    4. Try not to combine two or more statements on one line. Each statement gets it's own line.

    5. 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).

    6. 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:
      SCAR Code:
      I := (5 * 4 + 3);
      HowManyLogs(1, 5, 10);
    7. You should never have a white space on the inside of parenthesis. Example:
      SCAR Code:
      if (I = 100) or (K = 50) then
        DoThis(DoThis);
    8. SCAR bolds keywords such as "begin, end, procedure, function, etc." These words should be entirely lowercase as it looks much better.

    9. The names of procedures and functions should always begin with a capital letter and be camel-capped for easier readability. Example:
      SCAR Code:
      procedure WalkToBank;
    10. 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).

    11. Where possible, parameters/variables of the same type should be combined into one statement. For example:
      SCAR Code:
      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.
    12. Boolean variable names must be descriptive enough so that their meanings of True and False values will be clear.

    13. When you declare a variable, they are put on the next line after the var statement, and are indented. Example:
      SCAR Code:
      var
        Logs : Integer;
    14. 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. 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:
    SCAR Code:
    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?

    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:

    SCAR Code:
    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:
    SCAR Code:
    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.
    SCAR Code:
    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...
    Quote Originally Posted by 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:
    SCAR Code:
    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:

    Quote Originally Posted by Nava2 View Post
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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.
    SCAR Code:
    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. 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:
    SCAR Code:
    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.
    SCAR Code:
    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:
    SCAR Code:
    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:
    Code:
    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.
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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. It is actually very, very simple. The first thing you should do is add this little piece of code to you DeclarePlayers procedure:
    SCAR Code:
    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:
    SCAR Code:
    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?
    Last edited by Coh3n; 09-13-2010 at 04:24 AM.

  3. #3
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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. Here is a simple breakdown of an array:
    SCAR Code:
    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:
    SCAR Code:
    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. 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!

    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?

    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.

    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:
    SCAR Code:
    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:


    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):
    SCAR Code:
    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:
    SCAR 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).

    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:
    SCAR Code:
    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
    I can't stress this enough, make sure you ALWAYS free your bitmaps! Otherwise, it will slow your script/computer down tremendously!

    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:
    SCAR Code:
    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:



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


    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:

    SCAR Code:
    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:
    SCAR Code:
    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.

    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
    I can't stress this enough, make sure you ALWAYS free your DTMs! Otherwise, it will slow your script/computer down tremendously!

    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:
      SCAR Code:
      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:


      • Now, using the SCAR color picking icon:
        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:
        SCAR Code:
        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:
    SCAR Code:
    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:
    SCAR Code:
    {*******************************************************************************
    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:
    SCAR Code:
    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.
    SCAR Code:
    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. 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.

    7. 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.

    8. 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:
      SCAR Code:
      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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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.

      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:
      SCAR Code:
      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.
    2. Next what you want to do is replace the color of the MainPoint, and all the SubPoints with RoadColor, like this:
      SCAR Code:
      dtmMainPoint.Color := RoadColor;
      There, you now have made your DDTM dynamic!

    3. 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.

      In order to do this, we need to make a global variable called DDTMTolerance, like so:
      SCAR Code:
      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.

    4. 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:
      SCAR Code:
      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:
      SCAR Code:
      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;
    5. 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:
      SCAR Code:
      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.
    6. If you ran the script successfully, your debug box should read something like this:
      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:


    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:
    SCAR Code:
    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:


    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.

    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:
    SCAR Code:
    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):


    • 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:
      Quote Originally Posted by ZephyrsFury View Post
      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:


      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.

    5. 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. Otherwise, just fill in the parameters that you've chosen.

    6. 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?

      So, with all the parameters filled out, you should have a function that looks something like this:

    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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):
    SCAR Code:
    {*******************************************************************************
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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! 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.
    Last edited by Coh3n; 12-27-2009 at 06:00 AM.

  4. #4
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    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:
    SCAR Code:
    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):


    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).
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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.
    SCAR Code:
    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.

    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
      SCAR Code:
      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.

    2. This little part:
      SCAR Code:
      if InStrArrEx(Lowercase(Players[CurrentPlayer].Strings[0], XpGain, i) then
      Is a new function, and here's the explanation, straight from Text.scar:
      SCAR Code:
      {*******************************************************************************
      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'.

    3. This part here:
      SCAR Code:
      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 [i + 1] is so it uses the right amount of exp depending on the type of tree specified in DeclarePlayers. For example, if in DeclarePlayers:
      SCAR Code:
      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.

    4. 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).

    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:
    SCAR Code:
    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.
    SCAR Code:
    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:
      SCAR Code:
      {*******************************************************************************
      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.

    2. The second function I used is called SortATPAFromFirstPoint:
      SCAR Code:
      {*******************************************************************************
      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.

    3. The third and final function I used is called MiddleTPAEx:
      SCAR Code:
      {*******************************************************************************
      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:


      Notice how the bank floor color on the MiniMap is completely red. This is exactly what you want.

    4. 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.

    5. Now, at the bottom of the window you should see a few different settings. You want it looking like this:


      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:
    SCAR Code:
    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. 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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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:
    SCAR Code:
    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!
    Last edited by Coh3n; 09-09-2009 at 09:13 AM.

  5. #5
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    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.

    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 ), 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!
    Last edited by Coh3n; 12-27-2009 at 06:01 AM.

  6. #6
    Join Date
    Dec 2006
    Location
    Sweden
    Posts
    10,812
    Mentioned
    3 Post(s)
    Quoted
    16 Post(s)

    Default

    You trying to get a tut cup?

    Nice work!
    Last edited by Harry; 08-21-2009 at 08:26 AM.


    Send SMS messages using Simba
    Please do not send me a PM asking for help; I will not be able to help you! Post in a relevant thread or make your own! And always remember to search first!

  7. #7
    Join Date
    Feb 2006
    Location
    Amsterdam
    Posts
    13,691
    Mentioned
    146 Post(s)
    Quoted
    130 Post(s)

    Default

    Quite big.
    Nice.



    The best way to contact me is by email, which you can find on my website: http://wizzup.org
    I also get email notifications of private messages, though.

    Simba (on Twitter | Group on Villavu | Website | Stable/Unstable releases
    Documentation | Source | Simba Bug Tracker on Github and Villavu )


    My (Blog | Website)

  8. #8
    Join Date
    Feb 2009
    Posts
    1,447
    Mentioned
    0 Post(s)
    Quoted
    1 Post(s)

  9. #9
    Join Date
    Feb 2007
    Location
    Alberta,Canada
    Posts
    2,358
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    amazing, nice job man really well done.

  10. #10
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by TRiLeZ View Post
    Dont make such a damn big tutorial!! LOL
    Rep +
    Lol, it had to be big to include everything!

    Quote Originally Posted by Blumblebee View Post
    amazing, nice job man really well done.
    Thanks a lot!

  11. #11
    Join Date
    Jan 2008
    Location
    NC, USA.
    Posts
    4,429
    Mentioned
    0 Post(s)
    Quoted
    4 Post(s)

    Default

    I didn't know there was an updated RWAid
    Nice.. I think you're trying to compete with Naum. He loves competition
    Quote Originally Posted by irc
    [00:55:29] < Guest3097> I lol at how BenLand100 has become noidea
    [01:07:40] <@BenLand100> i'm not noidea i'm
    [01:07:44] -!- BenLand100 is now known as BenLand42-
    [01:07:46] <@BenLand42-> shit
    [01:07:49] -!- BenLand42- is now known as BenLand420
    [01:07:50] <@BenLand420> YEA

  12. #12
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by noidea View Post
    I didn't know there was an updated RWAid
    Nice.. I think you're trying to compete with Naum. He loves competition
    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.

  13. #13
    Join Date
    May 2007
    Location
    knoxville
    Posts
    2,873
    Mentioned
    7 Post(s)
    Quoted
    70 Post(s)

    Default

    z0mg nice tut. lol. nice refresher
    <TViYH> i had a dream about you again awkwardsaw
    Malachi 2:3

  14. #14
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Awkwardsaw View Post
    z0mg nice tut. lol. nice refresher
    Yeah lol, I feel like there isn't much I don't know now.

  15. #15
    Join Date
    Sep 2006
    Posts
    5,219
    Mentioned
    4 Post(s)
    Quoted
    1 Post(s)

    Default

    Obvious tut cup is obvious

  16. #16
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Boreas View Post
    Obvious tut cup is obvious
    Haha well thank you very much!

  17. #17
    Join Date
    Jan 2008
    Location
    Ontario, Canada
    Posts
    7,805
    Mentioned
    5 Post(s)
    Quoted
    3 Post(s)

    Default

    Kid, I need to get you drunk.

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

    Nub, you forgot forms.
    Last edited by Nava2; 08-21-2009 at 12:46 PM.
    Writing an SRL Member Application | [Updated] Pascal Scripting Statements
    My GitHub

    Progress Report:
    13:46 <@BenLand100> <SourceCode> @BenLand100: what you have just said shows you 
                        have serious physchological problems
    13:46 <@BenLand100> HE GETS IT!
    13:46 <@BenLand100> HE FINALLY GETS IT!!!!1

  18. #18
    Join Date
    Nov 2008
    Location
    Norway, Alesund
    Posts
    924
    Mentioned
    0 Post(s)
    Quoted
    37 Post(s)

    Default

    REP++ all in one tut and well explained.

  19. #19
    Join Date
    Mar 2007
    Posts
    4,810
    Mentioned
    3 Post(s)
    Quoted
    3 Post(s)

    Default

    Amazingly done man, keep up the great work rep+

  20. #20
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by Nava2 View Post
    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.

    Thanks Laimon and Naum!

  21. #21
    Join Date
    Jun 2007
    Location
    La Mirada, CA
    Posts
    2,484
    Mentioned
    1 Post(s)
    Quoted
    3 Post(s)

    Default

    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!

    "Failure is the opportunity to begin again more intelligently" (Henry Ford)


  22. #22
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by HyperSecret View Post
    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.

  23. #23
    Join Date
    Mar 2007
    Posts
    3,116
    Mentioned
    0 Post(s)
    Quoted
    2 Post(s)

    Default

    Quote Originally Posted by Coh3n View Post
    Thanks Hyper! Your rep got me to 2 rep squares.
    Whos the funny guy who put you down... Reped to try to raise you

  24. #24
    Join Date
    Apr 2008
    Location
    Marquette, MI
    Posts
    15,252
    Mentioned
    138 Post(s)
    Quoted
    680 Post(s)

    Default

    Quote Originally Posted by MylesMadness View Post
    Whos the funny guy who put you down... Reped to try to raise you
    Awe mannnn.

    But thanks.

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

    How unfortunate...

  25. #25
    Join Date
    Mar 2007
    Posts
    4,810
    Mentioned
    3 Post(s)
    Quoted
    3 Post(s)

    Default

    Quote Originally Posted by Coh3n View Post
    Awe mannnn.

    But thanks.

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

    How unfortunate...
    I'll Sort that.

Page 1 of 8 123 ... LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •