Page 1 of 2 12 LastLast
Results 1 to 25 of 44

Thread: [SRL]How To Write Your First Script: Collecting and Banking Cabbages!

  1. #1
    Join Date
    Feb 2012
    Location
    Canada
    Posts
    1,164
    Mentioned
    26 Post(s)
    Quoted
    433 Post(s)

    Default [SRL]How To Write Your First Script: Collecting and Banking Cabbages!

    How To Write Your First Script: Collecting and Banking Cabbages
    Verified Working On: January 31, 2019

    Table of Contents:
    Part 1: Introduction
    Part 2: Script Basics
    Part 3: Colour Finding
    Part 4: The Wait Loop
    Part 5: Walking via RSWalker
    Part 6: Banking
    Part 7: The Antiban
    Part 8: Final Words




    Part 1: Introduction

    What We Will Learn


    In this tutorial, you will learn the basics of how the Old School SRL include works. We will create a fairly basic script that will allow us to collect the cabbages in the cabbage patch north-west of Draynor and bank them in the Draynor bank. If you haven't already properly installed Simba or the SRL Old School include, please go and read the Complete Guide to Setting Up Simba and SRL. If you are new to programming, some of these ideas can be a little difficult to wrap your head around. If this is the case, you are encouraged to go back and read over the steps and descriptions again. If you are still having problems after that, you are more than welcome to post your questions below and I will do my best to answer them for you.

    Now that you are ready, let's get started!



    Part 2: Script Basics

    Script Skeleton


    Every script has a basic set of necessities that need to be implemented in order for it to function. These necessities are the 'bare bones' of the script and normally the starting point to every script (this is why we call it the skeleton). To start us off, this is generally what a skeleton will look like:

    Simba Code:
    program scriptSkeleton;
    {$define SMART}
    {$I SRL/OSR.simba}
    {$I RSWalker/Walker.simba}

    //Declare our Constants
    const
      LOGIN_NAME = '';    //Username/Email
      LOGIN_PASS = '';    //Password
      RS_WORLD   = -1;    //Desired World (-1 = Random)
      IS_MEMBER  = false; //True if your player is a Member

    //Declare our variables
    var
      Walk: TRSWalker;            //Used for RSWalker (to walk paths)

    {*******************************************************************************
      Name: declarePlayers();
      Function: Sets the proper variables using the constants above to allow
        a successful login.
    *******************************************************************************}

    procedure declarePlayers();
    begin
      with Players.New()^ do
      begin
        LoginName  := LOGIN_NAME;
        Password   := LOGIN_PASS;
        IsActive   := True;
        IsMember   := IS_MEMBER;
        World      := RS_WORLD;
      end;
      Players.SetCurrent(0);
    end;

    {*******************************************************************************
      Name: setUp();
      Function: Sets up the script by initializing everything and logging player in.
    *******************************************************************************}

    function setUp(): boolean;
    begin
      SRL.Setup([]);                 //Setup SRL to allow us to access it's functions.
      Walk.Init('world.png', -1);    //Setup RSWalker by initializing the map we want to use
      declarePlayers();              //Declare the player we are using

      if (not SRL.isLoggedIn) then   //If not logged in then..
      begin
         Players.LoginCurrent();     //Log player in
         MainScreen.setAngle(True);  //Sets the camera angle to the highest point
      end;

      Result := True;
    end;    

    begin //Main
      if setUp then
        writeln('We are set up and ready to go!');
    end.

    This may look a little bit daunting but bear with me. I'll go through and explain each part. Let's start at the top and work our way down.

    First, you will notice that we have this little section of code:
    Simba Code:
    program scriptSkeleton;
    {$define SMART}
    {$I SRL/OSR.simba}
    {$I RSWalker/Walker.simba}
    Each program ever created needs to have a name. All that the first line is doing is simply giving our script a name.

    On line two, we simply define SMART. This means that when we run the script, we are telling the include that we would like to run an instance of SMART. Therefore, the include will create an instance of SMART that is running Old School Runescape and will only allow the script to interact with that instance of SMART.

    Then we have our two include statements. By writing these two lines, we are telling Simba that we want to compile our program with the contents of both SRL/OSR.simba and RSWalker/WAlker.simba, which are the main files for the SRL Old School Include and the RSWalker Include.

    Next, you will see two sections where we declare our global constants and variables.
    Simba Code:
    //Declare our Constants
    const
      LOGIN_NAME = '';    //Username/Email
      LOGIN_PASS = '';    //Password
      RS_WORLD   = -1;    //Desired World (-1 = Random)
      IS_MEMBER  = false; //True if your player is a Member

    //Declare our variables
    var
      Walk: TRSWalker;            //Used for RSWalker (to walk paths)
    Constants are values that will remain constant throughout the entirety of the script. Their value/contents should never change. A variable, on the other hand, is something that can be changed and normally needs to be initiallized to something while the script is running to be able to be used. In this case, our constants contain our login information, our desired world number, and if our account is a member or not. The variables are made up of a TRSWalker. By creating and using this variable later on allows us to be able to use RSWalker and all of the functions that come along wiht it. You will see more about this in the a second.

    We then have our declarePlayers procedure:
    Simba Code:
    {*******************************************************************************
      Name: declarePlayers();
      Function: Sets the proper variables using the constants above to allow
        a successful login.
    *******************************************************************************}

    procedure declarePlayers();
    begin
      with Players.New()^ do
      begin
        LoginName  := LOGIN_NAME;
        Password   := LOGIN_PASS;
        IsActive   := True;
        IsMember   := IS_MEMBER;
        World      := RS_WORLD;
      end;
      Players.SetCurrent(0);
    end;
    A procedure is a set of code that, when executed, will only execute the code inside its section. In this case, our declarePlayers procedure will tell the SRL include what the current account login information is, as well as if it a member and what world we want to use.

    You should note that the declarePlayers procedure does not return anything. This is because we use functions to return values. You can see that happening here:
    Simba Code:
    {*******************************************************************************
      Name: setUp();
      Function: Sets up the script by initializing everything and logging player in.
    *******************************************************************************}

    function setUp(): boolean;
    begin
      SRL.Setup([]);                 //Setup SRL to allow us to access it's functions.
      Walk.Init('world.png', -1);    //Setup RSWalker by initializing the map we want to use
      declarePlayers();              //Declare the player we are using

      if (not SRL.isLoggedIn) then   //If not logged in then..
      begin
         Players.LoginCurrent();     //Log player in
         MainScreen.setAngle(True);  //Sets the camera angle to the highest point
      end;

      Result := True;
    end;
    The setUp function is what we call to initialize our includes, any variables we have globally created, declare our player, and do the beginning work of the script (i.e. log the player in). If you notice the first line of code where we declare the name of the function, you will notice a little tag that shows:
    Code:
    : boolean;
    This means that we are want to return a boolean value (True or False) when this section of code is finished executing. By default, the return value will be false unless we tell it to return true. This can be done by setting the result to true like this:
    Simba Code:
    Result := True;
    Functions do not only need to return boolean values. They can return any type of variable that you want. For example:
    Simba Code:
    function example: Integer;     //Returns an Integer
    function example: String;      //Returns a String
    function example: TBox;        //Returns a TBox
    function example: TPointArray; //Returns a TPointArray
    ...

    Finally, we have our main area which looks like this:
    Simba Code:
    begin //Main
      if setUp then
        writeln('We are set up and ready to go!');
    end.
    This final begin...end statement is where the brains of the operation is. If this begin...end statement is left empty, then nothing will happen. You can see that I put an if...then... statement in there and used our setUp function as our variable. In pseudo-code, this statement is read as:
    Code:
    if setUp is True, then 
      write a line saying "We are set up and ready to go!"
    I hope this gives you a basic understanding of some of the general ideas and how they work, along with the script skeleton. It might be a little confusing since I mixed a bunch of concepts into one section, so feel free to go back and read over things again until you understand the ideas. If you don't like the way I tried describing them, there is an excellent tutorial on them over here that I would encourage you to take a look through.



    Part 3: Colour Finding

    Grabbing The Colours


    To grab the colours, we will be using the ACA Colour Finding Tool that you can download here. I still use the outdated version, but the ideas should still be the same.

    Let's log in and go to the cabbage patch and then open up our ACA tool. You will then want to select the colours of the cabbage to the point where your screen looks like something similar to this:


    Make sure you are using the CTS2 mode because we want to get the best colour, tolerance, hue, and saturation values! I have selected unique colours to the cabbages and was able to get most of the cabbage recognized. This is normally what you want to go for when you are doing any sort of colour finding. Now that we have those values, we'll plug them into our colour finding procedure.

    The Colour Finding Procedure


    Now that we have the basis of the script down and we can successfully get a SMART window loaded, lets start with a method of finding the cabbages to pick up. Before we start to get the colours of the cabbages, we will go through the main colour finding procedure.
    Simba Code:
    {*******************************************************************************
      Name: findCabbages();
      Function: Locates cabbage in the field. Will print on screen if using SMART.
    *******************************************************************************}

    procedure findCabbages();
    var
      TPA, Cabbage: TPointArray;
      ATPA: T2DPointArray;
    begin
      if not SRL.isLoggedIn() then  //If not logged in, then terminate script
        TerminateScript;

      if (SRL.FindColors(TPA, CTS2(3127688, 27, 0.04, 0.87), MainScreen.GetBounds) > 0) then //If we find colours at all then...
      begin
        ATPA := TPA.Cluster(2);                 //Group them within a max pixel distance of 2
        ATPA.FilterSize(100, 500);              //Remove and ATPA of size < 100, or > 500.
        ATPA.SortByIndex(MainScreen.GetMiddle); //Sort by closest to Middle of the screen

        {$IFDEF SMART}                          //If we are using SMART, then...
          Smart.Image.DrawATPA(ATPA);           //Draws the ATPA's on the screen.
                                                //smart.Image.DebugATPA(ATPA) works as well
        {$ENDIF}                                //End SMART IF

        for Cabbage in ATPA do                  //For every possible cabbage in our ATPA
        begin
          Mouse.Move(Cabbage[Random(Length(Cabbage))]); //Move the mouse to the cabbage

          if MainScreen.IsUpText('Cabbage') then        //If the uptext is 'Cabbage', try to click it
          begin
             if Mouse.Click(ctRed) then         //Clicks the mouse and looks to see if red 'x' appeard when cicked
             begin
              waitLoop();                       //Call to our waitLoop because we want to wait while picking.
              Break;                            //If found red 'x', then break because we clicked it
            end;
          end;
        end;
      end;
      {$IFDEF SMART}
        Smart.Image.Clear;                      //Clears the ATPA's from screen
      {$ENDIF}
    end;
    Don't panic. Yes, there is a lot there, but I have added a lot of comments in it to help explain what each line does. To grasp a complete understanding of everything that is happening in this procedure, I am going to recommend you read The core of colorfinding tutorial. That tutorial will explain TPA's, ATPA's, and how to manipulate them to get the object you are looking for. The majority of this code is taken from that tutorial to allow you to get an understanding of it when applied to a specific object.

    Basically, this procedure will do the finding of the colours of the cabbage and will group them, filter them, and then sort them to allow us to find our cabbages and our cabbages only! It will then procede to click on them.

    To explain a bit, we will look at this line:
    Simba Code:
    if (SRL.FindColors(TPA, CTS2(XXXX, XX, X.XX, X.XX), MainScreen.GetBounds) > 0) then //If we find colours at all then...
    This is an if...then... statement that we covered earlier. Inside of it, we have a FindColors function that returns an Integer value. We check to see if this return value is greater than zero. If it is then we continue with at the begin...end statement directly below this line since it means we have found at least one colour, otherwise we will skip the begin...end statement completely.

    Inside the if...then... statement, we have the following:
    Simba Code:
    ATPA := TPA.Cluster(2);                 //Group them within a max pixel distance of 2
        ATPA.FilterSize(100, 500);              //Remove and ATPA of size < 100, or > 500.
        ATPA.SortByIndex(MainScreen.GetMiddle); //Sort by closest to Middle of the screen

        {$IFDEF SMART}                          //If we are using SMART, then...
          Smart.Image.DrawATPA(ATPA);           //Draws the ATPA's on the screen.
                                                //smart.Image.DebugATPA(ATPA) works as well
        {$ENDIF}                                //End SMART IF
    This is where we have the grouping, filtering, and sorting happening that I mentioned earlier. You can read the comments next to each line as they describe how each call affects the entire ATPA. The only spot that may need explaining is the unique looking $IFDEF statement. This works in a similar manner to our if...then... but it applied to if we have defined SMART or not. By this, I mean:
    Code:
    If SMART has been defined then
      Draw our ATPA on ths screen
    End If
    This means that if SMART is not defined at the top of our script (maybe you commented it out), then there will be no drawing on the RSClient that you are using, but if you are using SMART, you will see random colours overtop of each object the our script thinks are cabbages based on the information we have given it.

    We then have this:
    Simba Code:
    for Cabbage in ATPA do                  //For every possible cabbage in our ATPA
    begin
      Mouse.Move(Cabbage[Random(Length(Cabbage))]); //Move the mouse to the cabbage

      if MainScreen.IsUpText('Cabbage') then        //If the uptext is 'Cabbage', try to click it
      begin
        if Mouse.Click(ctRed) then         //Clicks the mouse and looks to see if red 'x' appeard when cicked
        begin
          Break;                            //If found red 'x', then dont go through all the others because we already clicked one
        end;
      end;
    end;
    This section uses a for...do... loop. To explain what is going on, we must note that 'Cabbage' is a TPointArray variable that points to TPA[0] to TPA[MAX] in the ATPA. The pseudo-code for this is:
    Code:
    For every TPA that can be a cabbage in ATPA do...
    The rest of it should be pretty self explanitory from the comments since we are then using some built-in functions from the SRL include to move the mouse, check the uptext of the cabbage and then click it and see if our click was the red 'x' or not.

    Putting It Together


    To test this, we can run the following code:
    Simba Code:
    program new;
    {$define SMART}
    {$I SRL/OSR.simba}
    {$I RSWalker/Walker.simba}

    const //This is where we declare our constants
      LOGIN_NAME = '';    //Username/Email
      LOGIN_PASS = '';    //Password
      RS_WORLD   = -1;    //Desired World (-1 = Random)
      IS_MEMBER  = false; //True if your player is a Member

    var  //This is where we declare our variables
      Walk: TRSWalker;            //Used for RSWalker (to walk paths)

    {*******************************************************************************
      Name: declarePlayers();
      Function: Sets the proper variables using the constants above to allow
        a successful login.
    *******************************************************************************}

    procedure declarePlayers();
    begin
      with Players.New()^ do
      begin
        LoginName  := LOGIN_NAME;
        Password   := LOGIN_PASS;
        IsActive   := True;
        IsMember   := IS_MEMBER;
        World      := RS_WORLD;
      end;
      Players.SetCurrent(0);
    end;

    {*******************************************************************************
      Name: findCabbages();
      Function: Locates cabbage in the field. Will print on screen if using SMART.
    *******************************************************************************}

    procedure findCabbages();
    var
      TPA, Cabbage: TPointArray;
      ATPA: T2DPointArray;
    begin
      if not SRL.isLoggedIn() then  //If not logged in, then terminate script
        TerminateScript;

      if (SRL.FindColors(TPA, CTS2(3127688, 27, 0.04, 0.87), MainScreen.GetBounds) > 0) then //If we find colours at all then...
      begin
        ATPA := TPA.Cluster(2);                 //Group them within a max pixel distance of 2
        ATPA.FilterSize(100, 500);              //Remove and ATPA of size < 100, or > 500.
        ATPA.SortByIndex(MainScreen.GetMiddle); //Sort by closest to Middle of the screen

        {$IFDEF SMART}                          //If we are using SMART, then...
          Smart.Image.DrawATPA(ATPA);           //Draws the ATPA's on the screen.
                                                //smart.Image.DebugATPA(ATPA) works as well
        {$ENDIF}                                //End SMART IF

        for Cabbage in ATPA do                  //For every possible cabbage in our ATPA
        begin
          Mouse.Move(Cabbage[Random(Length(Cabbage))]); //Move the mouse to the cabbage

          if MainScreen.IsUpText('Cabbage') then        //If the uptext is 'Cabbage', try to click it
          begin
             if Mouse.Click(ctRed) then         //Clicks the mouse and looks to see if red 'x' appeard when cicked
             begin
              Break;                            //If found red 'x', then break because we clicked it
            end;
          end;
        end;
      end;
      {$IFDEF SMART}
        Smart.Image.Clear;                      //Clears the ATPA's from screen
      {$ENDIF}
    end;

    {*******************************************************************************
      Name: setUp();
      Function: Sets up the script by initializing everything and logging player in.
    *******************************************************************************}

    function setUp(): boolean;
    begin
      {$IFDEF SMART}                 //If we are using SMART, then...
        Smart.EnableDrawing := True; //let us draw on SMART
      {$ENDIF}                       //end SMART IF

      SRL.Setup([]);                 //Setup SRL to allow us to access it's functions.

      Walk.Init('world.png', -1);    //Setup RSWalker by initializing the map we want to use

      declarePlayers();              //Declare the player we are using

      if (not SRL.isLoggedIn) then   //If not logged in then..
      begin
         Players.LoginCurrent();     //Log player in
         MainScreen.setAngle(True);  //Sets the camera angle to the highest point
      end;
    end;

    begin //Main
      if setUp then        //Calls the setup of the script
        writeln('We are set up and ready to go!');
     
      findCabbages();   //Collect Cabbages until inv is full
    end.
    By running this, you will see the computer find a cabbage on the ground and then click it to pick it up. This means that we have successfully been able to locate an object and interact with it! This can now be applied to any other object that you wish to find while writting scripts!



    Part 4: The Wait Loop

    Forming Your Wait Loop


    Since our cabbage is able to be found on the ground, you can try running the program with a repeat...until... loop in the main area like such:
    Simba Code:
    repeat
        findCabbages();   //Collect Cabbages until inv is full
    until(false);
    Without a wait loop when finding your cabbages, you will notice that your mouse will be constantly attempting to find cabbages and you will never actually pick one up. We need to construct a procedure/function that will allow us to be able to wait until we have picked up the cabbage we clicked before attempting to find the next one. To do this, I have constructed this procedure:
    Simba Code:
    {*******************************************************************************
      Name: waitLoop();
      Function: Waits until we have collected our cabbage
    *******************************************************************************}

    procedure waitLoop();
    var
      InvCount: Integer;
      T: TTimeMarker;
    begin
      if not SRL.isLoggedIn() then
        Exit;

      InvCount := Inventory.Count(); //Gets the count in our inventory
      T.Start;                       //Start our timer
      repeat
        wait(randomRange(75, 250));  //Wait a random amount of time
      until((Inventory.Count() > InvCount) or (T.GetTime > 7000)); //Stop repeating once inv count changes or we time out
    end;
    There are a few new elements in here, so let's go over them.

    For starters, you will notice that we have initialized some local variables. This is done similarily to how we did it with the global variables, but we place the var label inside of the procedure. We did the same thing in the colour finding section too. The two variables we have created are an invCount integer to keep track of our inventory count before we jump into the repeat, as well as a T variable which is a timer.

    To start, we initialize the invCount variable before we get into the loop. We do this because we need a reference point to check how many slots in our inventory are filled before we actually make it to the cabbage to pick it up. We then start the timer. This timer is used because we don't want to accidentally get stuck in an infinite loop. After this, we jump into the repeat...until... statement where we repeat waiting until our inventory count has increased from when we set invCount, or when we have been in the loop for 7 seconds because it should only take a couple seconds to actually make it to the cabbage.

    Calling Your Wait Loop


    Calling your wait loop can happen in multiple different ways. For this tutorial, I will call it in our findCabbages procedure like such:
    Simba Code:
    {*******************************************************************************
      Name: findCabbages();
      Function: Locates cabbage in the field. Will print on screen if using SMART.
    *******************************************************************************}

    procedure findCabbages();
    var
      TPA, Cabbage: TPointArray;
      ATPA: T2DPointArray;
    begin
      if not SRL.isLoggedIn() then  //If not logged in, then terminate script
        TerminateScript;

      if (SRL.FindColors(TPA, CTS2(3127688, 27, 0.04, 0.87), MainScreen.GetBounds) > 0) then //If we find colours at all then...
      begin
        ATPA := TPA.Cluster(2);                 //Group them within a max pixel distance of 2
        ATPA.FilterSize(100, 500);              //Remove and ATPA of size < 100, or > 500.
        ATPA.SortByIndex(MainScreen.GetMiddle); //Sort by closest to Middle of the screen

        {$IFDEF SMART}                          //If we are using SMART, then...
          Smart.Image.DrawATPA(ATPA);           //Draws the ATPA's on the screen.
                                                //smart.Image.DebugATPA(ATPA) works as well
        {$ENDIF}                                //End SMART IF

        for Cabbage in ATPA do                  //For every possible cabbage in our ATPA
        begin
          Mouse.Move(Cabbage[Random(Length(Cabbage))]); //Move the mouse to the cabbage

          if MainScreen.IsUpText('Cabbage') then        //If the uptext is 'Cabbage', try to click it
          begin
             if Mouse.Click(ctRed) then         //Clicks the mouse and looks to see if red 'x' appeard when cicked
             begin
              waitLoop();                       //Call to our waitLoop because we want to wait while picking.
              Break;                            //If found red 'x', then break because we clicked it
            end;
          end;
        end;
      end;
      {$IFDEF SMART}
        Smart.Image.Clear;                      //Clears the ATPA's from screen
      {$ENDIF}
    end;
    Notice how waitLoop is called before the break? This is because if it is called after the break in this procedure, it will not actually get called.

    Putting It Together


    Now let's run this script:
    Simba Code:
    program new;
    {$define SMART}
    {$I SRL/OSR.simba}
    {$I RSWalker/Walker.simba}

    const //This is where we declare our constants
      LOGIN_NAME = '';    //Username/Email
      LOGIN_PASS = '';    //Password
      RS_WORLD   = -1;    //Desired World (-1 = Random)
      IS_MEMBER  = false; //True if your player is a Member

    var  //This is where we declare our variables
      Walk: TRSWalker;            //Used for RSWalker (to walk paths)

    {*******************************************************************************
      Name: declarePlayers();
      Function: Sets the proper variables using the constants above to allow
        a successful login.
    *******************************************************************************}

    procedure declarePlayers();
    begin
      with Players.New()^ do
      begin
        LoginName  := LOGIN_NAME;
        Password   := LOGIN_PASS;
        IsActive   := True;
        IsMember   := IS_MEMBER;
        World      := RS_WORLD;
      end;
      Players.SetCurrent(0);
    end;

    {*******************************************************************************
      Name: waitLoop();
      Function: Waits until we have collected our cabbage
    *******************************************************************************}

    procedure waitLoop();
    var
      InvCount: Integer;
      T: TTimeMarker;
    begin
      if not SRL.isLoggedIn() then
        Exit;

      InvCount := Inventory.Count(); //Gets the count in our inventory
      T.Start;                       //Start our timer
      repeat
        wait(randomRange(75, 250));  //Wait a random amount of time
      until((Inventory.Count() > InvCount) or (T.GetTime > 7000)); //Stop repeating once inv count changes or we time out
    end;

    {*******************************************************************************
      Name: findCabbages();
      Function: Locates cabbage in the field. Will print on screen if using SMART.
    *******************************************************************************}

    procedure findCabbages;
    var
      TPA, Cabbage: TPointArray;
      ATPA: T2DPointArray;
    begin
      if not SRL.isLoggedIn() then  //If not logged in, then terminate script
        TerminateScript;

      if (SRL.FindColors(TPA, CTS2(3127688, 27, 0.04, 0.87), MainScreen.GetBounds) > 0) then //If we find colours at all then...
      begin
        ATPA := TPA.Cluster(2);                 //Group them within a max pixel distance of 2
        ATPA.FilterSize(100, 500);              //Remove and ATPA of size < 100, or > 500.
        ATPA.SortByIndex(MainScreen.GetMiddle); //Sort by closest to Middle of the screen

        {$IFDEF SMART}                          //If we are using SMART, then...
          Smart.Image.DebugATPA(ATPA);
        {$ENDIF}                                //End SMART IF

        for Cabbage in ATPA do                  //For every possible cabbage in our ATPA
        begin
          Mouse.Move(Cabbage[Random(Length(Cabbage))]); //Move the mouse to the cabbage

          if MainScreen.IsUpText('Cabbage') then        //If the uptext is 'Cabbage', try to click it
          begin
             if Mouse.Click(ctRed) then         //Clicks the mouse and looks to see if red 'x' appeard when cicked
             begin
              waitLoop();                       //Call to our waitLoop because we want to wait while picking.
              Break;                            //If found red 'x', then break because we clicked it
            end;
          end;
        end;
      end;
      {$IFDEF SMART}
        Smart.Image.Clear;                      //Clears the ATPA's from screen
      {$ENDIF}
    end;

    {*******************************************************************************
      Name: setUp();
      Function: Sets up the script by initializing everything and logging player in.
    *******************************************************************************}

    function setUp(): boolean;
    begin
      {$IFDEF SMART}                 //If we are using SMART, then...
        Smart.EnableDrawing := True; //let us draw on SMART
      {$ENDIF}                       //end SMART IF

      SRL.Setup([]);                 //Setup SRL to allow us to access it's functions.

      Walk.Init('world.png', -1);    //Setup RSWalker by initializing the map we want to use

      declarePlayers();              //Declare the player we are using

      if (not SRL.isLoggedIn) then   //If not logged in then..
      begin
         Players.LoginCurrent();     //Log player in
         MainScreen.setAngle(True);  //Sets the camera angle to the highest point
      end;
    end;

    begin //Main
      if setUp then        //Calls the setup of the script
        writeln('We are set up and ready to go!');
      repeat
        findCabbages();   //Collect Cabbages until inv is full
      until(false);       //Repeats forever
    end.

    You will notice that it picks up cabbages forever. This is great! It means we're making progress! Let's continue working on making it walk to the bank and bank all of the cabbages so we can grab more!



    Part 5: Walking via RSWalker

    Getting Your Points


    Walking via RSWalker is fortunately fairly easy. We'll start off with our SPS Path Generator. Using this program and the 'world.png' found in "C:\Simba\Includes\RSWalker\maps", you'll be able to create your own paths! For this tutorial, the path I have created is the following:

    This means that our paths should look like this:
    Simba Code:
    //Both paths that we plan to walk (pBank = Patch -> Bank | pPatch = Bank -> Patch)
    pBank := [Point(4022, 3289), Point(4022, 3332), Point(4059, 3342), Point(4096, 3347), Point(4105, 3394), Point(4127, 3431), Point(4153, 3457), Point(4178, 3478)];
    pPatch :=  [Point(4178, 3478), Point(4153, 3457), Point(4127, 3431), Point(4105, 3394), Point(4096, 3347), Point(4059, 3342), Point(4022, 3332), Point(4022, 3289)];

    You can create your own path and replace mine if you so desire! Feel free to experiment.

    Walking The Path


    Now that we actually have the path, we need to walk it! We can do that by using the WalkPath function:
    Simba Code:
    Walk.WalkPath(path);
    I have written a procedure that we can use that will accept a path and call the WalkPath function:
    Simba Code:
    {*******************************************************************************
      Name: walkTo(path);
      Function: Walks the path given by the 'path' variable.
    *******************************************************************************}

    procedure walkTo(path: TPointArray);
    begin
      Walk.WalkPath(path); //Walk our path passed to the procedure
    end;
    This might seem a little unnecessary that there is only one line of code in this procedure. It will make sense once we get to Part 7 (it's a little bit of foreshadowing).

    Putting It Together


    This means that we can walk our current path by using the following code:
    Simba Code:
    program new;
    {$define SMART}
    {$I SRL/OSR.simba}
    {$I RSWalker/Walker.simba}

    const //This is where we declare our constants
      LOGIN_NAME = '';    //Username/Email
      LOGIN_PASS = '';    //Password
      RS_WORLD   = -1;    //Desired World (-1 = Random)
      IS_MEMBER  = false; //True if your player is a Member

    var  //This is where we declare our variables
      Walk: TRSWalker;            //Used for RSWalker (to walk paths)
      pBank, pPatch: TPointArray; //Paths from Patch to Bank, and Bank to Path

    {*******************************************************************************
      Name: declarePlayers();
      Function: Sets the proper variables using the constants above to allow
        a successful login.
    *******************************************************************************}

    procedure declarePlayers();
    begin
      with Players.New()^ do
      begin
        LoginName  := LOGIN_NAME;
        Password   := LOGIN_PASS;
        IsActive   := True;
        IsMember   := IS_MEMBER;
        World      := RS_WORLD;
      end;
      Players.SetCurrent(0);
    end;

    {*******************************************************************************
      Name: walkTo(path);
      Function: Walks the path given by the 'path' variable.
    *******************************************************************************}

    procedure walkTo(path: TPointArray);
    begin
      Walk.WalkPath(path); //Walk our path passed to the procedure
    end;

    {*******************************************************************************
      Name: waitLoop();
      Function: Waits until we have collected our cabbage
    *******************************************************************************}

    procedure waitLoop();
    var
      InvCount: Integer;
      T: TTimeMarker;
    begin
      if not SRL.isLoggedIn() then
        Exit;

      InvCount := Inventory.Count(); //Gets the count in our inventory
      T.Start;                       //Start our timer
      repeat
        wait(randomRange(75, 250));  //Wait a random amount of time
      until((Inventory.Count() > InvCount) or (T.GetTime > 7000)); //Stop repeating once inv count changes or we time out
    end;

    {*******************************************************************************
      Name: findCabbages();
      Function: Locates cabbage in the field. Will print on screen if using SMART.
    *******************************************************************************}

    procedure findCabbages();
    var
      TPA, Cabbage: TPointArray;
      ATPA: T2DPointArray;
    begin
      if not SRL.isLoggedIn() then  //If not logged in, then terminate script
        TerminateScript;

      if (SRL.FindColors(TPA, CTS2(3127688, 27, 0.04, 0.87), MainScreen.GetBounds) > 0) then //If we find colours at all then...
      begin
        ATPA := TPA.Cluster(2);                 //Group them within a max pixel distance of 2
        ATPA.FilterSize(100, 500);              //Remove and ATPA of size < 100, or > 500.
        ATPA.SortByIndex(MainScreen.GetMiddle); //Sort by closest to Middle of the screen

        {$IFDEF SMART}                          //If we are using SMART, then...
          Smart.Image.DrawATPA(ATPA);           //Draws the ATPA's on the screen.
                                                //smart.Image.DebugATPA(ATPA) works as well
        {$ENDIF}                                //End SMART IF

        for Cabbage in ATPA do                  //For every possible cabbage in our ATPA
        begin
          Mouse.Move(Cabbage[Random(Length(Cabbage))]); //Move the mouse to the cabbage

          if MainScreen.IsUpText('Cabbage') then        //If the uptext is 'Cabbage', try to click it
          begin
             if Mouse.Click(ctRed) then         //Clicks the mouse and looks to see if red 'x' appeard when cicked
             begin
              waitLoop();                       //Call to our waitLoop because we want to wait while picking.
              Break;                            //If found red 'x', then break because we clicked it
            end;
          end;
        end;
      end;
      {$IFDEF SMART}
        Smart.Image.Clear;                      //Clears the ATPA's from screen
      {$ENDIF}
    end;

    {*******************************************************************************
      Name: setUp();
      Function: Sets up the script by initializing everything and logging player in.
    *******************************************************************************}

    function setUp(): boolean;
    begin
      {$IFDEF SMART}                 //If we are using SMART, then...
        Smart.EnableDrawing := True; //let us draw on SMART
      {$ENDIF}                       //end SMART IF

      SRL.Setup([]);                 //Setup SRL to allow us to access it's functions.

      Walk.Init('world.png', -1);    //Setup RSWalker by initializing the map we want to use

      //Both paths that we plan to walk (pBank = Patch -> Bank | pPatch = Bank -> Patch)
      pBank := [Point(4022, 3289), Point(4022, 3332), Point(4059, 3342), Point(4096, 3347), Point(4105, 3394), Point(4127, 3431), Point(4153, 3457), Point(4178, 3478)];
      pPatch :=  [Point(4178, 3478), Point(4153, 3457), Point(4127, 3431), Point(4105, 3394), Point(4096, 3347), Point(4059, 3342), Point(4022, 3332), Point(4022, 3289)];

      declarePlayers();              //Declare the player we are using

      if (not SRL.isLoggedIn) then   //If not logged in then..
      begin
         Players.LoginCurrent();     //Log player in
         MainScreen.setAngle(True);  //Sets the camera angle to the highest point
      end;

      Result := True;
    end;

    begin //Main
      if setUp then        //Calls the setup of the script
        writeln('We are set up and ready to go!');
      repeat
        walkTo(pPatch);   //Walk to Patch
        while (not Inventory.IsFull) do
          findCabbages();   //Collect Cabbages until inv is full
        walkTo(pBank);    //Walk to Bank
      until(false);       //Repeats forever
    end.

    You should notice that I've added a couple of things here. Let's go through them, shall we?

    In our global variables, we have created two new TPointArray's with the names of our paths:
    Simba Code:
    pBank, pPatch: TPointArray; //Paths from Patch to Bank, and Bank to Path
    These are the two paths that we generated above. Along with that, you will see some changes to setup where we added the two paths that we generated.

    Finally, in our main area, we added a few things:
    Simba Code:
    walkTo(pPatch);   //Walk to Patch
    while (not Inventory.IsFull) do
      findCabbages();   //Collect Cabbages until inv is full
    walkTo(pBank);    //Walk to Bank
    Here, we initially want to walk our path to our patch in the case we are not there yet. Otherwise we will be looking for cabbages somewhere where we won't be able to find them. There is also a while...do... loop which allows us to fill our inventory full of cabbages before we actually begin to walk to the bank to bank them all. Then we finalize it with our walk to the bank once we have gathered a full inventory of cabbages!

    Running to the field:


    Running to the Bank:


    Now we need to learn how to bank!



    Part 6: Banking

    Basics of Banking


    When it comes to banking, there are multiple ways you can do it. You can create your own methods for finding the bankers/bank booths/chests/etc or you can use the SRL include's methods that do most of the work for you! Today, we will be covering how to use the include's built in functions.

    For starters, we need to be able to open the bank once we have walked to it. We can do this by calling:
    Simba Code:
    BankScreen.Open(blDrynor);
    This function automatically find the banker and right click on them to open the bank! Easy, eh?

    Now, the unfortunate part is that sometimes things can fail. When it comes to opening the bank, we will want to double check that the bank is open. To do this, we can use the following:
    Simba Code:
    BankScreen.isOpen(5000);
    This function will wait for 5 seconds to see if the bank's screen opens up. If it doesn't, it will return false, otherwise it will return true.

    Once the bank screen in open, we will also want to be able to deposit our objects into the bank. To do so, we can use the following:
    Simba Code:
    BankScreen.DepositAll();
    This will press the 'Deposit All' button on the banking interface to deposite all the objects in the inventory.

    Using these three functions, we can put them together and get a function that looks like this:
    Simba Code:
    {*******************************************************************************
      Name: doBank();
      Function:
    *******************************************************************************}

    function doBank(): boolean;
    begin
      myAntiban();                    //Do antiban
      BankScreen.Open(blDrynor);      //Open bank using SRL's built in banker function
      if BankScreen.IsOpen(5000) then //If bank screen is open sometime within the 5 sec wait
      begin
        wait(randomRange(150, 500));  //Have a realistic wait time before we actually do anything
        BankScreen.DepositAll();      //Deposit all cabbages
        Result := True;               //We want to return true when the function finishes, so we set Result to True
      end;
    end;

    Putting It Together


    This function will do everything that we need it to do for the bank. To test it, we can run the following:
    Simba Code:
    program new;
    {$define SMART}
    {$I SRL/OSR.simba}
    {$I RSWalker/Walker.simba}

    const //This is where we declare our constants
      LOGIN_NAME = '';    //Username/Email
      LOGIN_PASS = '';    //Password
      RS_WORLD   = -1;    //Desired World (-1 = Random)
      IS_MEMBER  = false; //True if your player is a Member

    var  //This is where we declare our variables
      Walk: TRSWalker;            //Used for RSWalker (to walk paths)
      pBank, pPatch: TPointArray; //Paths from Patch to Bank, and Bank to Path

    {*******************************************************************************
      Name: declarePlayers();
      Function: Sets the proper variables using the constants above to allow
        a successful login.
    *******************************************************************************}

    procedure declarePlayers();
    begin
      with Players.New()^ do
      begin
        LoginName  := LOGIN_NAME;
        Password   := LOGIN_PASS;
        IsActive   := True;
        IsMember   := IS_MEMBER;
        World      := RS_WORLD;
      end;
      Players.SetCurrent(0);
    end;

    {*******************************************************************************
      Name: doBank();
      Function:
    *******************************************************************************}

    function doBank(): boolean;
    begin
      BankScreen.Open(blDrynor);      //Open bank using SRL's built in banker function
      if BankScreen.IsOpen(5000) then //If bank screen is open sometime within the 5 sec wait
      begin
        wait(randomRange(150, 500));  //Have a realistic wait time before we actually do anything
        BankScreen.DepositAll();      //Deposit all cabbages
        Result := True;               //We want to return true when the function finishes, so we set Result to True
      end;
    end;

    {*******************************************************************************
      Name: walkTo(path);
      Function: Walks the path given by the 'path' variable.
    *******************************************************************************}

    procedure walkTo(path: TPointArray);
    begin
      Walk.WalkPath(path); //Walk our path passed to the procedure
    end;

    {*******************************************************************************
      Name: waitLoop();
      Function: Waits until we have collected our cabbage
    *******************************************************************************}

    procedure waitLoop();
    var
      InvCount: Integer;
      T: TTimeMarker;
    begin
      if not SRL.isLoggedIn() then
        Exit;

      InvCount := Inventory.Count(); //Gets the count in our inventory
      T.Start;                       //Start our timer
      repeat
        wait(randomRange(75, 250));  //Wait a random amount of time
      until((Inventory.Count() > InvCount) or (T.GetTime > 7000)); //Stop repeating once inv count changes or we time out
    end;

    {*******************************************************************************
      Name: findCabbages();
      Function: Locates cabbage in the field. Will print on screen if using SMART.
    *******************************************************************************}

    procedure findCabbages();
    var
      TPA, Cabbage: TPointArray;
      ATPA: T2DPointArray;
    begin
      if not SRL.isLoggedIn() then  //If not logged in, then terminate script
        TerminateScript;

      if (SRL.FindColors(TPA, CTS2(3127688, 27, 0.04, 0.87), MainScreen.GetBounds) > 0) then //If we find colours at all then...
      begin
        ATPA := TPA.Cluster(2);                 //Group them within a max pixel distance of 2
        ATPA.FilterSize(100, 500);              //Remove and ATPA of size < 100, or > 500.
        ATPA.SortByIndex(MainScreen.GetMiddle); //Sort by closest to Middle of the screen

        {$IFDEF SMART}                          //If we are using SMART, then...
          Smart.Image.DrawATPA(ATPA);           //Draws the ATPA's on the screen.
                                                //smart.Image.DebugATPA(ATPA) works as well
        {$ENDIF}                                //End SMART IF

        for Cabbage in ATPA do                  //For every possible cabbage in our ATPA
        begin
          Mouse.Move(Cabbage[Random(Length(Cabbage))]); //Move the mouse to the cabbage

          if MainScreen.IsUpText('Cabbage') then        //If the uptext is 'Cabbage', try to click it
          begin
             if Mouse.Click(ctRed) then         //Clicks the mouse and looks to see if red 'x' appeard when cicked
             begin
              waitLoop();                       //Call to our waitLoop because we want to wait while picking.
              Break;                            //If found red 'x', then break because we clicked it
            end;
          end;
        end;
      end;
      {$IFDEF SMART}
        Smart.Image.Clear;                      //Clears the ATPA's from screen
      {$ENDIF}
    end;

    {*******************************************************************************
      Name: setUp();
      Function: Sets up the script by initializing everything and logging player in.
    *******************************************************************************}

    function setUp(): boolean;
    begin
      {$IFDEF SMART}                 //If we are using SMART, then...
        Smart.EnableDrawing := True; //let us draw on SMART
      {$ENDIF}                       //end SMART IF

      SRL.Setup([]);                 //Setup SRL to allow us to access it's functions.

      Walk.Init('world.png', -1);    //Setup RSWalker by initializing the map we want to use

      //Both paths that we plan to walk (pBank = Patch -> Bank | pPatch = Bank -> Patch)
      pBank := [Point(4022, 3289), Point(4022, 3332), Point(4059, 3342), Point(4096, 3347), Point(4105, 3394), Point(4127, 3431), Point(4153, 3457), Point(4178, 3478)];
      pPatch :=  [Point(4178, 3478), Point(4153, 3457), Point(4127, 3431), Point(4105, 3394), Point(4096, 3347), Point(4059, 3342), Point(4022, 3332), Point(4022, 3289)];

      declarePlayers();              //Declare the player we are using

      if (not SRL.isLoggedIn) then   //If not logged in then..
      begin
         Players.LoginCurrent();     //Log player in
         MainScreen.setAngle(True);  //Sets the camera angle to the highest point
      end;

      Result := True;
    end;

    begin //Main
      if setUp then        //Calls the setup of the script
        writeln('We are set up and ready to go!');
      repeat
        walkTo(pPatch);     //Walk to Patch
        while (not Inventory.IsFull) do
          findCabbages();   //Collect Cabbages until inv is full
        walkTo(pBank);      //Walk to Bank
        while (not doBank) do  //Deposit all Cabbages
          wait(randomRange(75, 250));
      until(false);         //Repeats forever
    end.
    And there we go! We now have a functioning bot that can pick up cabbages and bank them.



    Part 7: The Antiban

    The Way of The Antiban


    Congradulations on making it this far! We're almost done! We just have to include an Antiban now! If you're not sure what an antiban is, it is a collection of different activities that are activated by the script that make the bot seem like it is a genuine human playing the game. It can do things like check stats, hover over random players, change the camera angle, and even take breaks. You always will want something like this built into your script, otherwise you can get your account banned fairly easily. So, how do we implement it?

    Setting Up The Antiban


    In order to use the antiban correctly, we need to declare a global variable of type TAntiban. This will allow us to initialize our antibans and add different types of tasks. We can do this by:
    Simba Code:
    var  //This is where we declare our variables
      Walk: TRSWalker;            //Used for RSWalker (to walk paths)
      pBank, pPatch: TPointArray; //Paths from Patch to Bank, and Bank to Path
      Antiban: TAntiban;          //Used for Antiban procedures

    We then need to have a procedure to where we tell the script what kinds of things we want to do during our antiban. We will call the procedure SetupAntiban and it looks like this:
    Simba Code:
    {*******************************************************************************
      Name: setupAntiban();
      Function: Sets up the built-in antiban included with the SRL include.
      NOTE: Please feel free to customize this and make it unique to you.
    *******************************************************************************}

    procedure setupAntiban();
    begin
      Antiban.Init(SKILL_TOTAL, 4);

      Antiban.AddTask([@Antiban.LoseFocus,     ONE_MINUTE*5]);
      Antiban.AddTask([@Antiban.HoverPlayers,  ONE_MINUTE*8]);
      Antiban.AddTask([@Antiban.CheckStats,    ONE_MINUTE*10]);
      Antiban.AddTask([@Antiban.OpenRandomTab, ONE_MINUTE*10]);
      Antiban.AddTask([@Antiban.VeryShortBreak,ONE_MINUTE*25]);
      Antiban.AddTask([@Antiban.DoMiscStuff,   ONE_MINUTE*25]);
      Antiban.AddTask([@Antiban.RandomCompass, ONE_MINUTE*45]);

      Antiban.AddBreak([35 * ONE_MINUTE, 05 * ONE_MINUTE, 0.05]);
      Antiban.AddBreak([02 * ONE_HOUR,   15 * ONE_MINUTE, 0.20]);
      Antiban.AddBreak([05 * ONE_HOUR,   45 * ONE_MINUTE, 0.85]);
      Antiban.AddBreak([16 * ONE_HOUR,   08 * ONE_HOUR,   0.99]);
    end;
    The way this works is that we start off by initializing the antiban to our skill of choice. Since picking up cabbages does not train any skill, I have put 'SKILL_TOTAL' in there but you can put any skill in there that you would like since we are not going to be checking a specific skill.

    Then we have the AddTask functions. This is where we add different types of tasks for the antiban to do and the times when we want to have them execute. As you can see, we have 7 different tasks added here. These can be adjusted or changed, as well as their duration. If you are curious about the different types of antiban procedures you have access to, feel free to check out "C:\Simba\Includes\SRL\osr\antiban.simba".

    We also have the ability to add breaks. This is done using the AddBreak function. The first variable is how long until you take your break, the second is how long you plan to break for, and the last one is the chance that you log out for your break. You can also read up about this in "C:\Simba\Includes\SRL\osr\antiban.simba".

    Calling The Antiban


    We will now create an Antiban procedure that we can call in every spot that we want to run an antiban. Do note that just because we call the procedure does not mean that an antiban will occur.

    Our antiban procedure can look like this:
    Simba Code:
    {*******************************************************************************
      Name: myAntiban();
      Function: Executes the antiban and checks for random events.
    *******************************************************************************}

    Procedure myAntiban;
    begin
      if not SRL.isLoggedIn() then
        Exit;

      SRL.DismissRandom();  //Dismiss random events if any are found
      Antiban.DoAntiban();  //Do the antiban
    end;
    You can see that we call two unique functions here. We call SRL.DismissRandom and Antiban.DoAntiban. SRL.DismissRandom will do exactly what it sounds like. It will dismiss a random event that shows up around you. Antiban.DoAntiban will call all of the antiban tasks that you created before and will run them based on if they are ready to be run.

    Putting It Together


    Now that we have our antiban built and ready to go, we can test out the completed script:
    Simba Code:
    program new;
    {$define SMART}
    {$I SRL/OSR.simba}
    {$I RSWalker/Walker.simba}

    const //This is where we declare our constants
      LOGIN_NAME = '';    //Username/Email
      LOGIN_PASS = '';    //Password
      RS_WORLD   = -1;    //Desired World (-1 = Random)
      IS_MEMBER  = false; //True if your player is a Member

    var  //This is where we declare our variables
      Walk: TRSWalker;            //Used for RSWalker (to walk paths)
      pBank, pPatch: TPointArray; //Paths from Patch to Bank, and Bank to Path
      Antiban: TAntiban;          //Used for Antiban procedures

    {*******************************************************************************
      Name: declarePlayers();
      Function: Sets the proper variables using the constants above to allow
        a successful login.
    *******************************************************************************}

    procedure declarePlayers();
    begin
      with Players.New()^ do
      begin
        LoginName  := LOGIN_NAME;
        Password   := LOGIN_PASS;
        IsActive   := True;
        IsMember   := IS_MEMBER;
        World      := RS_WORLD;
      end;
      Players.SetCurrent(0);
    end;

    {*******************************************************************************
      Name: setupAntiban();
      Function: Sets up the built-in antiban included with the SRL include.
      NOTE: Please feel free to customize this and make it unique to you.
    *******************************************************************************}

    procedure setupAntiban();
    begin
      Antiban.Init(SKILL_TOTAL, 4);

      Antiban.AddTask([@Antiban.LoseFocus,     ONE_MINUTE*5]);
      Antiban.AddTask([@Antiban.HoverPlayers,  ONE_MINUTE*8]);
      Antiban.AddTask([@Antiban.CheckStats,    ONE_MINUTE*10]);
      Antiban.AddTask([@Antiban.OpenRandomTab, ONE_MINUTE*10]);
      Antiban.AddTask([@Antiban.VeryShortBreak,ONE_MINUTE*25]);
      Antiban.AddTask([@Antiban.DoMiscStuff,   ONE_MINUTE*25]);
      Antiban.AddTask([@Antiban.RandomCompass, ONE_MINUTE*45]);

      Antiban.AddBreak([35 * ONE_MINUTE, 05 * ONE_MINUTE, 0.05]);
      Antiban.AddBreak([02 * ONE_HOUR,   15 * ONE_MINUTE, 0.20]);
      Antiban.AddBreak([05 * ONE_HOUR,   45 * ONE_MINUTE, 0.85]);
      Antiban.AddBreak([16 * ONE_HOUR,   08 * ONE_HOUR,   0.99]);
    end;

    {*******************************************************************************
      Name: myAntiban();
      Function: Executes the antiban and checks for random events.
    *******************************************************************************}

    Procedure myAntiban;
    begin
      if not SRL.isLoggedIn() then
        Exit;

      SRL.DismissRandom();  //Dismiss random events if any are found
      Antiban.DoAntiban();  //Do the antiban
    end;

    {*******************************************************************************
      Name: doBank();
      Function:
    *******************************************************************************}

    function doBank(): boolean;
    begin
      myAntiban();                    //Do antiban
      BankScreen.Open(blDrynor);      //Open bank using SRL's built in banker function
      if BankScreen.IsOpen(5000) then //If bank screen is open sometime within the 5 sec wait
      begin
        wait(randomRange(150, 500));  //Have a realistic wait time before we actually do anything
        BankScreen.DepositAll();      //Deposit all cabbages
        Result := True;               //We want to return true when the function finishes, so we set Result to True
      end;
    end;

    {*******************************************************************************
      Name: walkTo(path);
      Function: Walks the path given by the 'path' variable.
    *******************************************************************************}

    procedure walkTo(path: TPointArray);
    begin
      myAntiban(); //Do Antiban
      Walk.WalkPath(path); //Walk our path passed to the procedure
    end;

    {*******************************************************************************
      Name: waitLoop();
      Function: Waits until we have collected our cabbage
    *******************************************************************************}

    procedure waitLoop();
    var
      InvCount: Integer;
      T: TTimeMarker;
    begin
      if not SRL.isLoggedIn() then
        Exit;

      InvCount := Inventory.Count(); //Gets the count in our inventory
      T.Start;                       //Start our timer
      repeat
        myAntiban();                 //Do Antiban
        wait(randomRange(75, 250));  //Wait a random amount of time
      until((Inventory.Count() > InvCount) or (T.GetTime > 7000)); //Stop repeating once inv count changes or we time out
    end;

    {*******************************************************************************
      Name: findCabbages();
      Function: Locates cabbage in the field. Will print on screen if using SMART.
    *******************************************************************************}

    procedure findCabbages();
    var
      TPA, Cabbage: TPointArray;
      ATPA: T2DPointArray;
    begin
      if not SRL.isLoggedIn() then  //If not logged in, then terminate script
        TerminateScript;

      if (SRL.FindColors(TPA, CTS2(3127688, 27, 0.04, 0.87), MainScreen.GetBounds) > 0) then //If we find colours at all then...
      begin
        ATPA := TPA.Cluster(2);                 //Group them within a max pixel distance of 2
        ATPA.FilterSize(100, 500);              //Remove and ATPA of size < 100, or > 500.
        ATPA.SortByIndex(MainScreen.GetMiddle); //Sort by closest to Middle of the screen

        {$IFDEF SMART}                          //If we are using SMART, then...
          Smart.Image.DrawATPA(ATPA);           //Draws the ATPA's on the screen.
                                                //smart.Image.DebugATPA(ATPA) works as well
        {$ENDIF}                                //End SMART IF

        for Cabbage in ATPA do                  //For every possible cabbage in our ATPA
        begin
          Mouse.Move(Cabbage[Random(Length(Cabbage))]); //Move the mouse to the cabbage

          if MainScreen.IsUpText('Cabbage') then        //If the uptext is 'Cabbage', try to click it
          begin
             if Mouse.Click(ctRed) then         //Clicks the mouse and looks to see if red 'x' appeard when cicked
             begin
              waitLoop();                       //Call to our waitLoop because we want to wait while picking.
              Break;                            //If found red 'x', then break because we clicked it
            end;
          end;
        end;
      end;
      {$IFDEF SMART}
        Smart.Image.Clear;                      //Clears the ATPA's from screen
      {$ENDIF}
    end;

    {*******************************************************************************
      Name: setUp();
      Function: Sets up the script by initializing everything and logging player in.
    *******************************************************************************}

    function setUp(): boolean;
    begin
      {$IFDEF SMART}                 //If we are using SMART, then...
        Smart.EnableDrawing := True; //let us draw on SMART
      {$ENDIF}                       //end SMART IF

      SRL.Setup([]);                 //Setup SRL to allow us to access it's functions.

      Walk.Init('world.png', -1);    //Setup RSWalker by initializing the map we want to use

      //Both paths that we plan to walk (pBank = Patch -> Bank | pPatch = Bank -> Patch)
      pBank := [Point(4022, 3289), Point(4022, 3332), Point(4059, 3342), Point(4096, 3347), Point(4105, 3394), Point(4127, 3431), Point(4153, 3457), Point(4178, 3478)];
      pPatch :=  [Point(4178, 3478), Point(4153, 3457), Point(4127, 3431), Point(4105, 3394), Point(4096, 3347), Point(4059, 3342), Point(4022, 3332), Point(4022, 3289)];

      setupAntiban();                //Setup our antiban
      declarePlayers();              //Declare the player we are using

      if (not SRL.isLoggedIn) then   //If not logged in then..
      begin
         Players.LoginCurrent();     //Log player in
         MainScreen.setAngle(True);  //Sets the camera angle to the highest point
      end;

      Result := True;
    end;

    begin //Main
      if setUp then        //Calls the setup of the script
        writeln('We are set up and ready to go!');
      repeat
        walkTo(pPatch);     //Walk to Patch
        while (not Inventory.IsFull) do
          findCabbages();   //Collect Cabbages until inv is full
        walkTo(pBank);      //Walk to Bank
        while (not doBank) do  //Deposit all Cabbages
          wait(randomRange(75, 250));
      until(false);         //Repeats forever
    end.

    Before running this program, you may notice a couple of small changes. You may notice that I call myAntiban in different parts of the script. This is because we want to run the antiban in random places to seem a little less predictable. You may also see that we call the SetupAntiban procedure in the setUp function. We do this to allow us to be able to actually do the antibans.



    Part 8: Final words

    The Completion of Your First Script


    Congradulations! We have now reached the end! This means that you have successfully been able to write your own script to collect and bank cabbages! You are more than welcome to take this code and modify it to your own personal liking. Feel free to dig through the include and find a way of getting creative if your own ways with writting scripts that do other tasks.

    If you have any questions or if you need any help, you are more than welcome to post below and I will do my best to get back to you! Also, if you notice anything than needs to be corrected, feel free to let me know as well.
    Last edited by StickToTheScript; 01-31-2019 at 04:53 PM. Reason: Updated.

  2. #2
    Join Date
    Aug 2007
    Posts
    539
    Mentioned
    20 Post(s)
    Quoted
    266 Post(s)

    Default

    Great work! Goes in depth into everything to making a script with the tools (ACA and SPS pathing). The demo gifs are very nice aswell. The antiban portion is great and is a necessity for every script!
    Discord: Guy#1693

  3. #3
    Join Date
    Dec 2006
    Location
    Program TEXAS home of AUTOERS
    Posts
    7,934
    Mentioned
    26 Post(s)
    Quoted
    237 Post(s)

    Default

    Awesome tutorial! Great for noob scripters and also scripters who have been away for a while... Rated this thread 5 stars

    Keep it up!

  4. #4
    Join Date
    Jan 2012
    Location
    Sydney, Australia
    Posts
    877
    Mentioned
    12 Post(s)
    Quoted
    368 Post(s)

  5. #5
    Join Date
    May 2012
    Location
    Glorious Nippon
    Posts
    1,011
    Mentioned
    50 Post(s)
    Quoted
    505 Post(s)

    Default

    Wow you're on a tutorial-writing rampage! Keep it up!

    The deposit box at Port Sarim might be a bit closer, but it probably doesn't matter. If you wanted to go a step further and make the behavior a bit less bot-like, you could pick the cabbages in a pattern instead of randomly.

    I made a cabbage script a while ago, but all my accounts got banned pretty fast

  6. #6
    Join Date
    Sep 2014
    Posts
    447
    Mentioned
    10 Post(s)
    Quoted
    203 Post(s)

    Default

    Great tutorial! Just what we need. Normally I wouldn't comment on this, but would you consider editing it a bit to make the casing more consistent? I remember being an absolute newcomer to code and being thrown off by it. For example, sometimes it's SRL and other times its srl (mainScreen vs MainScreen as well).

    It also looks like there are some camel case versus pascal case inconsistencies. I normally am lazy about this in my scripts and changing the entire thing to be one way of the other would probably be more annoying than it's worth, but I think that maybe having a consistent choice when calling functions would also help ease access for newcomers.

  7. #7
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by Citrus View Post
    The deposit box at Port Sarim might be a bit closer, but it probably doesn't matter. If you wanted to go a step further and make the behavior a bit less bot-like, you could pick the cabbages in a pattern instead of randomly.
    There's no code in SRL that handles depositboxes for you, so one would have to handle that manually. Oh, and there's actually a pattern in OP, it will prefer the cabbages visually closer to us, you can see how it will go east->south, or west->south (depending on how it started off) to pick as long as there's a cabbage in that direction, as a result of the visual distance, and how it's sorted.
    Last edited by slacky; 04-25-2018 at 06:31 PM.
    !No priv. messages please

  8. #8
    Join Date
    Feb 2012
    Location
    Canada
    Posts
    1,164
    Mentioned
    26 Post(s)
    Quoted
    433 Post(s)

    Default

    Quote Originally Posted by yourule97 View Post
    Great tutorial! Just what we need. Normally I wouldn't comment on this, but would you consider editing it a bit to make the casing more consistent? I remember being an absolute newcomer to code and being thrown off by it. For example, sometimes it's SRL and other times its srl (mainScreen vs MainScreen as well).

    It also looks like there are some camel case versus pascal case inconsistencies. I normally am lazy about this in my scripts and changing the entire thing to be one way of the other would probably be more annoying than it's worth, but I think that maybe having a consistent choice when calling functions would also help ease access for newcomers.
    I definitely agree. I got a little bit lazy when dealing with the code. I'll do my best to clean it up.

  9. #9
    Join Date
    May 2012
    Location
    Glorious Nippon
    Posts
    1,011
    Mentioned
    50 Post(s)
    Quoted
    505 Post(s)

    Default

    Quote Originally Posted by slacky View Post
    There's no code in SRL that handles depositboxes for you, so one would have to handle that manually. Oh, and there's actually a pattern in OP, it will prefer the cabbages visually closer to us, you can see how it will go east->south to pick as long as there's a cabbage in that direction, as a result of the visual distance, and how it's sorted.
    That's fair, and creating new functions for the deposit box is justifiably beyond the scope of this tutorial.
    Yeah, my comment was poorly worded. An ideal script would follow a more logical, human pattern. e.g. Pick a whole row of cabbages before moving up to the next row. This way you don't even have to move the mouse more than a few times. But again, that's probably beyond the scope of a first script tutorial.

  10. #10
    Join Date
    Feb 2012
    Location
    Canada
    Posts
    1,164
    Mentioned
    26 Post(s)
    Quoted
    433 Post(s)

    Default

    Quote Originally Posted by Citrus View Post
    ... An ideal script would follow a more logical, human pattern. e.g. Pick a whole row of cabbages before moving up to the next row. This way you don't even have to move the mouse more than a few times. But again, that's probably beyond the scope of a first script tutorial.
    You can actually make the row happen in a pretty simple manner.

    In the case you activate an antiban that involved mouse movements, you could simply just store the point directly after you click the cabbage by:
    Simba Code:
    GetMousePos(x,y);
    and then you could check that position (+/- a few pixels for randomization) and simply check the uptext. This could work theoretically since most of those cabbages are all the same distance from each other. Therefore, your mouse could technically never move and you could pick up an entire row/column. The only problem is that it is not super reliable. So you could possibly end up going diagonal...

  11. #11
    Join Date
    May 2012
    Location
    Glorious Nippon
    Posts
    1,011
    Mentioned
    50 Post(s)
    Quoted
    505 Post(s)

    Default

    Quote Originally Posted by StickToTheScript View Post
    You can actually make the row happen in a pretty simple manner.

    In the case you activate an antiban that involved mouse movements, you could simply just store the point directly after you click the cabbage by:
    Simba Code:
    GetMousePos(x,y);
    and then you could check that position (+/- a few pixels for randomization) and simply check the uptext. This could work theoretically since most of those cabbages are all the same distance from each other. Therefore, your mouse could technically never move and you could pick up an entire row/column. The only problem is that it is not super reliable. So you could possibly end up going diagonal...
    You don't really need to store the mouse position, just check the uptext before you search colors. Although you could check if the mouse is far away from the player to avoid weird behavior like skipping cabbages. To avoid diagonals you can either limit your search region or just filter the whole thing by different regions.

  12. #12
    Join Date
    Feb 2012
    Location
    Canada
    Posts
    1,164
    Mentioned
    26 Post(s)
    Quoted
    433 Post(s)

    Default

    Quote Originally Posted by Citrus View Post
    You don't really need to store the mouse position, just check the uptext before you search colors. Although you could check if the mouse is far away from the player to avoid weird behavior like skipping cabbages. To avoid diagonals you can either limit your search region or just filter the whole thing by different regions.
    That will definately work too. My idea was that in the case an antiban was initiated where you check your stats or examine an item in your inventory, then your cursor will be over your inventory, so this way we can check the location we last clicked on the Main Screen.

  13. #13
    Join Date
    May 2018
    Posts
    2
    Mentioned
    0 Post(s)
    Quoted
    1 Post(s)

    Default

    i dotn know how

  14. #14
    Join Date
    Dec 2006
    Location
    Program TEXAS home of AUTOERS
    Posts
    7,934
    Mentioned
    26 Post(s)
    Quoted
    237 Post(s)

    Default

    Quote Originally Posted by teachme2script View Post
    i dotn know how
    What do you need help with?

  15. #15
    Join Date
    Jun 2007
    Location
    south park
    Posts
    1,160
    Mentioned
    0 Post(s)
    Quoted
    62 Post(s)

    Default

    BankScreen.Open(blDrynor); im playing around with this script in seers, do i just change it to BankScreen.Open(blSeers); ?
    http://www.youtube.com/user/YoHoJoSRL
    Good scripting guides on youtube
    Formerly known as (djcheater)

  16. #16
    Join Date
    Feb 2018
    Posts
    23
    Mentioned
    1 Post(s)
    Quoted
    3 Post(s)

    Default

    Quote Originally Posted by randy marsh View Post
    BankScreen.Open(blDrynor); im playing around with this script in seers, do i just change it to BankScreen.Open(blSeers); ?
    Don't think there is a seers location setup that you can call,

    blYanille
    blAlKharid
    blLumbridge
    blDrynor
    blEdgeville
    blVarrockWest
    blVarrockEast
    blFaladorEast
    blFaladorWest
    bcBlue
    bcGray

    Those are the only options for opening a bank using the function that i can find, But i have only just started myself so could be wrong.

  17. #17
    Join Date
    Jun 2007
    Location
    south park
    Posts
    1,160
    Mentioned
    0 Post(s)
    Quoted
    62 Post(s)

    Default

    Another issue im having is when i try open sps path genrator its asking how to open it, what java version do i use?

    Because i read the sps thread and it says to use jdk6 which i did , i then selected java.exe but the program just black screens and shuts straight away?

    java.PNG
    http://www.youtube.com/user/YoHoJoSRL
    Good scripting guides on youtube
    Formerly known as (djcheater)

  18. #18
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by randy marsh View Post
    Another issue im having is when i try open sps path genrator its asking how to open it, what java version do i use?

    Because i read the sps thread and it says to use jdk6 which i did , i then selected java.exe but the program just black screens and shuts straight away?

    java.PNG
    Install java 8 (32 bit) and use https://github.com/TheTS/SPSToolbox/releases
    Last edited by slacky; 07-21-2018 at 02:40 PM.
    !No priv. messages please

  19. #19
    Join Date
    Jun 2007
    Location
    south park
    Posts
    1,160
    Mentioned
    0 Post(s)
    Quoted
    62 Post(s)

    Default

    Ty bro
    http://www.youtube.com/user/YoHoJoSRL
    Good scripting guides on youtube
    Formerly known as (djcheater)

  20. #20
    Join Date
    Jun 2007
    Location
    south park
    Posts
    1,160
    Mentioned
    0 Post(s)
    Quoted
    62 Post(s)

    Default

    The jar or zip?

    SPSToolbox.jar
    Source code (zip)
    http://www.youtube.com/user/YoHoJoSRL
    Good scripting guides on youtube
    Formerly known as (djcheater)

  21. #21
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by randy marsh View Post
    BankScreen.Open(blDrynor); im playing around with this script in seers, do i just change it to BankScreen.Open(blSeers); ?
    There are three options avialable:

    1) Write a custom finder for the banker, use what you learnt in this tutorial and write a function to find the banker. And then pass the location (TPoint) to our function:
    > function TRSBankScreen.OpenAt(P: TPoint): Boolean;
    It's safe to pass invalid locations, it will return True if it was able to open the bank at that location.

    2) I advice against this, as this is actually an internal method (note how it's prefixed with an underscore), so it can change, be removed or whatever, and could very well be unreliable (not really meant for full mainscreen search), just a last option kinda deal, and assuming the banker is either standard gray, or standard blue:
    > function TRSBankScreen._OpenNPC(Typ: EBankerColor; Area: TBox): Int8;

    3) I advice against this (see above reasons), but to use the internal generalized bank finder like we did internally, see:
    https://github.com/SRL/SRL/blob/mast...imba#L332-L339
    Example:
    > Bankscreen._MagicalBankerFinder([color, tolerance, huemod, satmod], bcBlue, [xoffset, yoffset]);
    Where the last parameter is an offset based off north angle, assuming you use the booth to find the banker, or a object that's beside him for example, so the banker is ? points to the left or down etc.

    Quote Originally Posted by randy marsh View Post
    The jar or zip?

    SPSToolbox.jar
    Source code (zip)
    The jar.
    Last edited by slacky; 05-09-2018 at 09:29 PM.
    !No priv. messages please

  22. #22
    Join Date
    Jun 2007
    Location
    south park
    Posts
    1,160
    Mentioned
    0 Post(s)
    Quoted
    62 Post(s)

    Default

    Ok i downloaded the 32 bit java and installed it , what pathway do i do to open it? I have tried the various java.exe ect still getting black screen grrr
    http://www.youtube.com/user/YoHoJoSRL
    Good scripting guides on youtube
    Formerly known as (djcheater)

  23. #23
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by randy marsh View Post
    Ok i downloaded the 32 bit java and installed it , what pathway do i do to open it? I have tried the various java.exe ect still getting black screen grrr
    open terminal, navigate to where you have the SPSToolBox and enter
    C:\Progra~2\Java\<insert java version here>\bin\java.exe -jar SPSToolbox.jar

    Example:
    C:\Progra~2\Java\jre1.8.0_131\bin\java.exe -jar SPSToolbox.jar

    Should work, and fyi, "Progra~2" refers to "Program Files (x86)", just trickery.
    Last edited by slacky; 05-09-2018 at 09:14 PM.
    !No priv. messages please

  24. #24
    Join Date
    Feb 2012
    Location
    Canada
    Posts
    1,164
    Mentioned
    26 Post(s)
    Quoted
    433 Post(s)

    Default

    Quote Originally Posted by randy marsh View Post
    BankScreen.Open(blDrynor); im playing around with this script in seers, do i just change it to BankScreen.Open(blSeers); ?
    As of right now, there is no option for opening the bank in Seers Village. You should be able to use the following function:
    Simba Code:
    TRSBankScreen._OpenNPC(Typ: EBankerColor; Area: TBox): Int8;

    Which can be called like this:
    Simba Code:
    BankScreen._OpenNPC(bcGray, MainScreen.GetBounds);

    And this should open the bank for you.

    Edit: Oops.. I'm late to the party...
    Last edited by StickToTheScript; 05-09-2018 at 09:17 PM.

  25. #25
    Join Date
    Jun 2007
    Location
    south park
    Posts
    1,160
    Mentioned
    0 Post(s)
    Quoted
    62 Post(s)

    Default

    Hmm java console isnt turning on now grrrr

    Edit thanks by running this program it fixed jar issue :

    https://johann.loefflmann.net/en/sof...fix/index.html
    Last edited by randy marsh; 05-10-2018 at 09:36 AM.
    http://www.youtube.com/user/YoHoJoSRL
    Good scripting guides on youtube
    Formerly known as (djcheater)

Page 1 of 2 12 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
  •