SRL Archive - OSR Beginner Scripting Tutorials

[SRL-OSR] Build a simple chopper & banker


Flight

2021-12-28 11:27:02

Building a simple Port Sarim chopper & banker

Resources used

Simba 1400+
SRL-F
ACA (Built into Simba)



Step 1: Defining the script

Going into this tutorial I'll assume you have some basic knowledge about writing scripts using Simba. I'll keep things as simple in this script as possible with plenty of documentation, however should any part not make sense please feel free to post any questions you may have. With that being said, off we go. Start by opening Simba and pasting the following chunk of code:

program PortSarimChopper;
{$DEFINE SRL_USE_REMOTEINPUT} // Allows us to use the OEM client without taking over mouse & keyboard
{$I SRL-F/OSR.simba} // We'll need the SRL-F include

Type TTreeType = (Willow);

Const
(* Script settings *)
TREETYPE = Willow; // Type of tree to chop (only Willow supported currently)
PERCSHIFT = 16; // Percent pixelshift to be considered 'chopping'
MAXRUNTIME = 75; // Max run time in minutes

(* Player settings *)
PNAME = ''; // Player name
PPASS = ''; // Player password
PPIN = ''; // Player pin (not needed here as we use the deositbox)


(*
Here we add a new type of variable called a 'TTree'
Inside the TTree we'll store useful information
that we can apply to multiple types of trees
*)
Type
TTree = record
XP : Int32;
WalkTile: TPoint;
Color : TCTS2Color;
Log : TRSItem;
Tiles : TPointArray;
end;

(*
Our base record for the script, containing
global variables to be used throughout.
*)
TScript = record
LogCount : Int32;
Tree : TTree;
PrevTile,
BankTile : TPoint;
BankPath,
TreePath : TPointArray;
TreeZones : T2DPointArray;
MiscItems : TRSItemArray;
RSW : TRSWalker;
ShutdownTime: Int64;
end;

(*
Create a single instance of a 'TScript', call it 'Bot'.
*)
Var
Bot: TScript;


As you can see I've denotations for every block of code in the example, and I'll continue to do so throughout the tutorial. In a nutshell what's going on here is importing SRL-F, which is just my personal version of Olly's SRL-OSR, as well as defining that the script will utilize the very powerful and handy feature called RemoteInput. This allows us to bot using the official OSRS client and does not take over your mouse and keyboard. It's just about as safe as you can possibly bot without Simba taking control of you PC (unless using a VM, ect…). Aside from that we define the script settings as well as global variables to be used throughout.

Step 2: Adding useful/critical components

Here we'll add some useful functions such as customized mouse movements, progress reporting and anti-ban setup.

(*
Just a neater version of writing debug messages.
*)
procedure TScript.WriteMsg(Message: String);
begin
WriteLn('[Bot]: ', Message);
end;

(*
Always declare your players.
*)
procedure TScript.DeclarePlayers();
begin
Login.AddPlayer(PNAME, PPASS, PPIN, []);
end;

(*
Print out a report of your in-game progress.
Makes use of SRL-F's built-in 'ProgressReport' procedure.
*)
procedure TScript.Report();
var
XpGained:Int32;
begin
XpGained := Max(1,(Self.LogCount*Self.Tree.XP));

(* Let's clean up Simba's output section before printing another progress report *)
ClearDebug();

(* See progreports.simba (Includes/SRL-F/utils/progreports.simba) for reference *)
ProgressReport(RESULT_REPORTBOX, 'Port Sarim Chopper', 'Flight', '1.00',
['Runtime', 'Logs chopped', 'XP gained', 'Until shutdown'],
[SRL.MsToTime(GetTimeRunning, Time_Short),
ToStr(Self.LogCount, '(', Round(Self.LogCount / (GetTimeRunning()/1000/60/60)),' / hr)'),
ToStr(Round(XpGained,2),'(', Round(XpGained / (GetTimeRunning()/1000/60/60)),' / hr)'),
SRL.MsToTime(Self.ShutdownTime-GetTimeRunning, Time_Short)]);
end;

(* Some homegrown anti-ban *)
procedure TMouse.RandomMovement();
var
S: Int32;
begin
S := Self.Speed;
Self.Speed := 4;
Self.Move(Box(Mouse.Position, 75, 75), True, );
Self.Speed := S;
end;

procedure TScript.DoLoseFocus();
begin
Antiban.LoseFocus(SRL.NormalRange(3700,500));
end;

(* Setup our antiban *)
procedure TScript.SetupAntiban();
begin
Antiban.Skills += ERSSKILL.WOODCUTTING;
// Interval Antiban method
Antiban.AddTask(ONE_SECOND*10, @Mouse.RandomMovement);
Antiban.AddTask(ONE_MINUTE*2, @Self.DoLoseFocus);
Antiban.AddTask(ONE_MINUTE*4, @Antiban.HoverMSPlayers);
Antiban.AddTask(ONE_MINUTE*7, @Antiban.RandomRotate);
Antiban.AddTask(ONE_MINUTE*9, @Antiban.HoverSkills);
Antiban.AddBreak(ONE_MINUTE*18, ONE_SECOND*40, 0.2, 0.0);
end;

procedure TScript.DoAB();
begin
Antiban.DismissRandom();
if Antiban.DoAntiban() then
if (not RSClient.IsLoggedIn) then
Login.LoginPlayer();
end;

(* Combination of miss mouse + slowing near the target destination *)
procedure TMouse.HumanMove(Point: TPoint);
var
mPt: TPoint;
S: Int32;
Miss: Double;
Range: Int64;
begin
S := Self.Speed;
Range := Trunc(Power(Self.Position().DistanceTo(Point), 0.80)); // how much possible range to miss
Miss := SRL.SkewedRand(0.9, 0.1, 1.5); // Where miss will happen. 1 = destination (P).

mPt.X := Trunc((1-Miss)*Self.Position().X + Miss*Point.X);
mPt.Y := Trunc((1-Miss)*Self.Position().Y + Miss*Point.Y);

mPt.X += SRL.NormalRange(-Range, Range);
mPt.Y += SRL.NormalRange(-Range, Range);

Self.Move(mPt);
Self.Speed := round(S*0.85);
Self.Move(Point);
Self.Speed := S;
end;
If it's hard to read the denotation within that code block just copy & paste it into Simba to make it a bit easier to read.

Step 3: Finding & interacting with objects

Here we have the actual finding of mainscreen objects, in this case willow trees and the depositbox at Port Sarim. You'll notice both accomplish the same task but are done differently. It's simply to demonstrate different ways to go about accomplishing tasks.

(* Function to gather all available trees of our tree type *)
function TScript.AllAvailableTrees(): TPointArray;
var
TPA: TPointArray;
ATPA: T2DPointArray;
Finder: TRSObjectFinder;
begin
// Uses SRL-OSR's built-in color-finding
// See examples in Includes/SRL-F/docs/images

Finder.Colors += Self.Tree.Color; // Load our tree type's color into the finder
Finder.Grow := 4;
Finder.ClusterDistance := 4;

ATPA := MainScreen.FindObject(Finder); // Finder will spit out a T2DPointArray of any found trees as 'ATPA'
if ATPA.Len < 1 then Exit; // No colors found
for TPA in ATPA do
Result += TPA.Mean(); // For each TPA within the ATPA we'll extract the mean and add it to the result

Result.Sort([Mainscreen.GetPlayerBox.Middle.X, Mainscreen.GetPlayerBox.Y2]); // Now sort the result from our player
end;

(*
Finding the depositbox. By this point you should already
understand how this works.
*)
function TScript.FindDepositBox(): Boolean;
var
TPA: TPointArray;
ATPA: T2DPointArray;
Finder: TRSObjectFinder;
begin
Finder.Colors += CTS2(6189178, 7, 0.06, 0.56);

Finder.Grow := 1;
Finder.ClusterDistance := 3;

ATPA := MainScreen.FindObject(Finder);

if (ATPA.Len > 0) then
begin
ATPA.SortByMiddle(Mainscreen.Center);
for TPA in ATPA do
begin
Mouse.HumanMove(TPA.Mean()); // Right away move the mouse to each TPA mean and check for uptext
if MainScreen.IsUpText(['eposit']) then // Found it, exit and return 'True'
Exit(True);
end;
end;
end;
You can see here that TScript.AllAvailableTrees() will (hopefully) spit out a TPA of all located willow trees whereas TScript.FindDepositBox() right away moves the mouse until the correct uptext is found.

Step 4: Chopping a tree

Alright, we have a function to find those willow trees on the mainscreen, now let's build a procedure that calls that finder and actually chops the tree. While we're at it, let's create a loop that waits while we're still chopping. Here's one way to accomplish this:

procedure TScript.ChopTree();
var
i,XP: Int32;
T: TCountdown;
Trees: TPointArray;
begin
// Failsafe...
if DepositBox.IsOpen then
begin
DepositBox.Close();
Exit;
end;

// We're > 25 distance from the tree's 'WalkTile', so let's webwalk back
if RSW.GetMyPos().DistanceTo(Self.Tree.WalkTile) >= 25 then
begin
Self.WriteMsg('Returning to initial spot');
Minimap.EnableRun();
RSW.WebWalk(Self.Tree.WalkTile);
Exit;
end;

// Get all trees of our treetype, stored as a TPA
Trees := Self.AllAvailableTrees();

// So we don't spam move the mouse, let's limit the attempts to a max of 3 movements
for i:=0 to min(3, high(Trees)) do
begin
Mouse.HumanMove(Trees[i]);
if MainScreen.IsUpText('Chop down', 75) then // Found the desired uptext, let's break the loop now
break;
end;

// Never found the uptext, perhars we're too far away
// Webwalk back to the tree's WalkTile
if (not MainScreen.IsUpText('Chop down')) then
begin
Self.WriteMsg('No trees found, returning to initial spot');
RSW.WebWalk(Self.Tree.WalkTile);
Exit;
end;

Mouse.Click(MOUSE_LEFT);
if (not MainScreen.DidRedClick) then Exit;

// Record the value in the XP bar before we begin chopping
XP := XPBar.Read();

// Wait while the player is walking towards the tree
if Minimap.HasFlag(500) then
if WaitUntil(Minimap.IsPlayerMoving(300), 75, 1000) then
Minimap.WaitPlayerMoving(300, 6000);

// Start a countdown timer between 1.6 and 1.8 seconds, begin chopping loop
T.Init(SRL.NormalRange(1600,1800));
// Repeating loop while 'T' is still counting down
while (not T.IsFinished) do
begin
if (not RSClient.IsLoggedIn) then Exit;
if Inventory.IsFull() then break;

if Chat.ClickContinue(False) then
T.Restart;

// The XP bar reads higher than the previous record
// So restart T timer and re-record the our XP bar as XP
if XPBar.Read() > XP then
begin
XP := XPBar.Read();
T.Restart();
end;

// If there's a percent pixelshift (PERCSHIFT) within our player's box
// restart the T timer
if (SRL.PercentShift(MainScreen.GetPlayerBox(), 500) >= PERCSHIFT) then
T.Restart();

Self.DoAB(); // Let's do some anti-ban while chopping
Wait(60,120); // Slow down the loop 60-120ms so we're not chewing up CPU usage
end;

Wait(130, 850);
if SRL.Dice(15) then // 15% chance of rotating the camera
case SRL.Dice(50) of // 50/50 chance to rotate left or rght by 20-70 degrees
True: Minimap.SetCompassAngle(Minimap.GetCompassAngle() - random(20, 70));
False: Minimap.SetCompassAngle(Minimap.GetCompassAngle() + random(20, 70));
end;
end;
Script logic is key to an efficient and reliable script, and you can take my word for it when I say I've run into nearly every possible scenario that can go wrong. Learn from my mistakes and make use of failsafes when at all possible. For this section the logic is:
  1. Make sure the depositbox screen is not open, if so close it and exit
  2. Check our position, if we're too far from the trees web-walk back
  3. Gather all visible trees, mouse each one (max 4 attempts) until our uptext is found
  4. Click the tree
  5. Wait until we've stopped walking
  6. Wait while chop

Step 5: Deposit the logs

By this point we find the trees and chop 'em until we've a full inventory. So we need a build a method to walk to the depositbox, find & open it, deposit our logs (as well as misc. items such as bird nests). I also find that after handling banking in any script is an appropriate time to do a progress report, so we'll do that here as well.

(* Deposit the logs *)
procedure TScript.DepositLogs();
var
i: Int32;
begin
if (not RSClient.IsLoggedIn) then Exit;
if (not DepositBox.IsOpen()) then // Is the depositbox already open?
if RSW.GetMyPos().DistanceTo(Self.BankTile) >= 15 then
begin
Self.WriteMsg('Walking to the deposit box');
Minimap.DisableRun();
RSW.WebWalk(Self.BankTile);
Exit;
end;

if (not Self.FindDepositBox()) then Exit;

if MainScreen.IsUpText(['eposit']) then
begin
Inc(Self.LogCount, Inventory.CountItem(Self.Tree.Log)); // Count the logs and save it to our 'LogCount' variable

Mouse.Click(MOUSE_LEFT);
if (not MainScreen.DidRedClick) then Exit;
Minimap.WaitPlayerMoving(200, 3000);

// Wait until the depositbox is open within 4.1 seconds, at an interval of 75ms
if (not WaitUntil(DepositBox.IsOpen(), 75, 4100)) then Exit;
end;

Wait(35, 450);
DepositBox.DepositItem([Self.Tree.Log, DEPOSITBOX_DEPOSIT_ALL], True); // Deposit all of 'Log' TItem, using quantity buttons
Wait(35, 750);

for i:=0 to high(Self.MiscItems) do // Deposit any other misc item (can be defined in TScript.Init()), such as birdnests
if DepositBox.FindItem(Self.MiscItems[i]) then
begin
DepositBox.DepositItem([Self.MiscItems[i], DEPOSITBOX_DEPOSIT_ALL], True);
Wait(35, 250);
end;

DepositBox.Close();
if (not WaitUntil((not DepositBox.IsOpen()), 75, 4100)) then DepositBox.Close(); // Try again?
Wait(175,350);

Self.Report(); // This is a good time to print out a progress report
if (getTimeRunning() > Self.ShutdownTime) then // Check if the script has been running for more than 'MAXRUNTIME'
begin
Logout.ClickLogout(); // If so, logout and terminate the script
TerminateScript('Time to shutdown');
Exit;
end;
end;
No need to include a bit to walk our player back to the trees, if you remember from our TScript.ChopTree() procedure above this is already handled.

Step 6: Initiate and run the script

We're almost there! At this point we just need to define all the variables of the script, do our set-ups and create a main repeating loop the script will run off of.

(* Our script's main repeating loop *)
procedure TScript.Run();
begin
while RSClient.IsLoggedIn do // While we're logged in do...
begin
if Inventory.IsFull() then // Full inventory, so go deposit logs
Self.DepositLogs()
else
Self.ChopTree(); // Not a full inventory, so chop some trees

Self.DoAB(); // Check if it's a good time to initiate some anti-ban
if (getTimeRunning() > Self.ShutdownTime) then // Time to shutdown?
begin
Logout.ClickLogout();
TerminateScript('Time to shutdown');
Exit;
end;
end;

Self.WriteMsg('Not logged in'); // No info given, so stay logged out
end;

(* Setup our script & variables *)
procedure TScript.Init();
begin
with Self do
begin
DeclarePlayers(); // Don't forget to do this!
SetupAntiban();
RSW.Setup('world'); // Must setup RSWalker as well
RSW.ScreenWalk := False; // True for walking via the mainscreen
RSW.EnableRunAtEnergy := 85; // At 85+ run energy, auto-enable running
MM2MS.ZoomLevel := Options.GetZoomLevel(); // Done just once per session to get zoom level. Needed for MMtoMS conversion
Mouse.Speed := 20; // Mouse speed, 20 seems nice
BankTile := [3995,3508]; // MM tile to walk to for the depositbox
end;

case lowercase(ToStr(TREETYPE)) of // Load tree variables based on the 'TREETYPE'
'willow': // Self-explanatory...
with Self.Tree do
begin
XP := 67;
WalkTile := [4043, 3436];
Color := CTS2(4161909, 1, 0.10, 0.71);
Log := 'Willow logs';
end;
end;

// Setup shutdown time, which is MAXRUNTIME X 60000 (1 minute), with a random +/- 10%
Self.ShutdownTime := (MAXRUNTIME * 60000) + Random(- (MAXRUNTIME * 6000), (MAXRUNTIME * 6000));
end;
You can easily decipher the logic of the script's main loop here:
  1. While we're logged in…
  2. If the inventory is full, deposit logs
  3. If the inventory is not fll, chop trees
  4. If it's time to shut down, logout and terminate the script
  5. Perform anti-ban
Aside from that we also do our setup, including defining our script's variables.

Step 7: Putting it all together

We have everything we need for this simple chopping script, now all that's left to do is tell Simba to load the TScript (defined as "Bot") and run it.

begin
RSClient.Image.Clear(Mainscreen.Bounds); // Always a good idea to clear the RSClient's image, just in case
Bot.Init(); // Setup Bot (our TScript)
Bot.Run(); // Lights, camera, action!
end.
And everything put together:

program PortSarimChopper;
{$DEFINE SRL_USE_REMOTEINPUT} // Allows us to use the OEM client without taking over mouse & keyboard
{$I SRL-F/OSR.simba} // We'll need the SRL-F include

Type TTreeType = (Willow);

Const
(* Script settings *)
TREETYPE = Willow; // Type of tree to chop (only Willow supported currently)
PERCSHIFT = 16; // Percent pixelshift to be considered 'chopping'
MAXRUNTIME = 75; // Max run time in minutes

(* Player settings *)
PNAME = ''; // Player name
PPASS = ''; // Player password
PPIN = ''; // Player pin (not needed here as we use the deositbox)


(*
Here we add a new type of variable called a 'TTree'
Inside the TTree we'll store useful information
that we can apply to multiple types of trees
*)
Type
TTree = record
XP : Int32;
WalkTile: TPoint;
Color : TCTS2Color;
Log : TRSItem;
Tiles : TPointArray;
end;

(*
Our base record for the script, containing
global variables to be used throughout.
*)
TScript = record
LogCount : Int32;
Tree : TTree;
PrevTile,
BankTile : TPoint;
BankPath,
TreePath : TPointArray;
TreeZones : T2DPointArray;
MiscItems : TRSItemArray;
RSW : TRSWalker;
ShutdownTime: Int64;
end;

(*
Create a single instance of a 'TScript', call it 'Bot'.
*)
Var
Bot: TScript;


(*
Just a neater version of writing debug messages.
*)
procedure TScript.WriteMsg(Message: String);
begin
WriteLn('[Bot]: ', Message);
end;

(*
Always declare your players.
*)
procedure TScript.DeclarePlayers();
begin
Login.AddPlayer(PNAME, PPASS, PPIN, []);
end;

(*
Print out a report of your in-game progress.
Makes use of SRL-F's built-in 'ProgressReport' procedure.
*)
procedure TScript.Report();
var
XpGained:Int32;
begin
XpGained := Max(1,(Self.LogCount*Self.Tree.XP));

(* Let's clean up Simba's output section before printing another progress report *)
ClearDebug();

(* See progreports.simba (Includes/SRL-F/utils/progreports.simba) for reference *)
ProgressReport(RESULT_REPORTBOX, 'Port Sarim Chopper', 'Flight', '1.00',
['Runtime', 'Logs chopped', 'XP gained', 'Until shutdown'],
[SRL.MsToTime(GetTimeRunning, Time_Short),
ToStr(Self.LogCount, '(', Round(Self.LogCount / (GetTimeRunning()/1000/60/60)),' / hr)'),
ToStr(Round(XpGained,2),'(', Round(XpGained / (GetTimeRunning()/1000/60/60)),' / hr)'),
SRL.MsToTime(Self.ShutdownTime-GetTimeRunning, Time_Short)]);
end;

(* Some homegrown anti-ban *)
procedure TMouse.RandomMovement();
var
S: Int32;
begin
S := Self.Speed;
Self.Speed := 4;
Self.Move(Box(Mouse.Position, 75, 75), True, );
Self.Speed := S;
end;

procedure TScript.DoLoseFocus();
begin
Antiban.LoseFocus(SRL.NormalRange(3700,500));
end;

(* Setup our antiban *)
procedure TScript.SetupAntiban();
begin
Antiban.Skills += ERSSKILL.WOODCUTTING;
// Interval Antiban method
Antiban.AddTask(ONE_SECOND*10, @Mouse.RandomMovement);
Antiban.AddTask(ONE_MINUTE*2, @Self.DoLoseFocus);
Antiban.AddTask(ONE_MINUTE*4, @Antiban.HoverMSPlayers);
Antiban.AddTask(ONE_MINUTE*7, @Antiban.RandomRotate);
Antiban.AddTask(ONE_MINUTE*9, @Antiban.HoverSkills);
Antiban.AddBreak(ONE_MINUTE*18, ONE_SECOND*40, 0.2, 0.0);
end;

procedure TScript.DoAB();
begin
Antiban.DismissRandom();
if Antiban.DoAntiban() then
if (not RSClient.IsLoggedIn) then
Login.LoginPlayer();
end;

(* Combination of miss mouse + slowing near the target destination *)
procedure TMouse.HumanMove(Point: TPoint);
var
mPt: TPoint;
S: Int32;
Miss: Double;
Range: Int64;
begin
S := Self.Speed;
Range := Trunc(Power(Self.Position().DistanceTo(Point), 0.80)); // how much possible range to miss
Miss := SRL.SkewedRand(0.9, 0.1, 1.5); // Where miss will happen. 1 = destination (P).

mPt.X := Trunc((1-Miss)*Self.Position().X + Miss*Point.X);
mPt.Y := Trunc((1-Miss)*Self.Position().Y + Miss*Point.Y);

mPt.X += SRL.NormalRange(-Range, Range);
mPt.Y += SRL.NormalRange(-Range, Range);

Self.Move(mPt);
Self.Speed := round(S*0.85);
Self.Move(Point);
Self.Speed := S;
end;

(* Function to gather all available trees of our tree type *)
function TScript.AllAvailableTrees(): TPointArray;
var
TPA: TPointArray;
ATPA: T2DPointArray;
Finder: TRSObjectFinder;
begin
// Uses SRL-OSR's built-in color-finding
// See examples in Includes/SRL-F/docs/images

Finder.Colors += Self.Tree.Color; // Load our tree type's color into the finder
Finder.Grow := 4;
Finder.ClusterDistance := 4;

ATPA := MainScreen.FindObject(Finder); // Finder will spit out a T2DPointArray of any found trees as 'ATPA'
if ATPA.Len < 1 then Exit; // No colors found
for TPA in ATPA do
Result += TPA.Mean(); // For each TPA within the ATPA we'll extract the mean and add it to the result

Result.Sort([Mainscreen.GetPlayerBox.Middle.X, Mainscreen.GetPlayerBox.Y2]); // Now sort the result from our player
end;

(*
Finding the depositbox. By this point you should already
understand how this works.
*)
function TScript.FindDepositBox(): Boolean;
var
TPA: TPointArray;
ATPA: T2DPointArray;
Finder: TRSObjectFinder;
begin
Finder.Colors += CTS2(6189178, 7, 0.06, 0.56);

Finder.Grow := 1;
Finder.ClusterDistance := 3;

ATPA := MainScreen.FindObject(Finder);

if (ATPA.Len > 0) then
begin
ATPA.SortByMiddle(Mainscreen.Center);
for TPA in ATPA do
begin
Mouse.HumanMove(TPA.Mean()); // Right away move the mouse to each TPA mean and check for uptext
if MainScreen.IsUpText(['eposit']) then // Found it, exit and return 'True'
Exit(True);
end;
end;
end;

procedure TScript.ChopTree();
var
i,XP: Int32;
T: TCountdown;
Trees: TPointArray;
begin
// Failsafe...
if DepositBox.IsOpen then
begin
DepositBox.Close();
Exit;
end;

// We're > 25 distance from the tree's 'WalkTile', so let's webwalk back
if RSW.GetMyPos().DistanceTo(Self.Tree.WalkTile) >= 25 then
begin
Self.WriteMsg('Returning to initial spot');
Minimap.EnableRun();
RSW.WebWalk(Self.Tree.WalkTile);
Exit;
end;

// Get all trees of our treetype, stored as a TPA
Trees := Self.AllAvailableTrees();

// So we don't spam move the mouse, let's limit the attempts to a max of 4 movements
for i:=0 to min(3, high(Trees)) do
begin
Mouse.HumanMove(Trees[i]);
if MainScreen.IsUpText('Chop down', 75) then // Found the desired uptext, let's break the loop now
break;
end;

// Never found the uptext, perhars we're too far away
// Webwalk back to the tree's WalkTile
if (not MainScreen.IsUpText('Chop down')) then
begin
Self.WriteMsg('No trees found, returning to initial spot');
RSW.WebWalk(Self.Tree.WalkTile);
Exit;
end;

Mouse.Click(MOUSE_LEFT);
if (not MainScreen.DidRedClick) then Exit;

// Record the value in the XP bar before we begin chopping
XP := XPBar.Read();

// Wait while the player is walking towards the tree
if Minimap.HasFlag(500) then
if WaitUntil(Minimap.IsPlayerMoving(300), 75, 1000) then
Minimap.WaitPlayerMoving(300, 6000);

// Start a countdown timer between 1.6 and 1.8 seconds, begin chopping loop
T.Init(SRL.NormalRange(1600,1800));
// Repeating loop while 'T' is still counting down
while (not T.IsFinished) do
begin
if (not RSClient.IsLoggedIn) then Exit;
if Inventory.IsFull() then break;

if Chat.ClickContinue(False) then
T.Restart;

// The XP bar reads higher than the previous record
// So restart T timer and re-record the our XP bar as XP
if XPBar.Read() > XP then
begin
XP := XPBar.Read();
T.Restart();
end;

// If there's a percent pixelshift (PERCSHIFT) within our player's box
// restart the T timer
if (SRL.PercentShift(MainScreen.GetPlayerBox(), 500) >= PERCSHIFT) then
T.Restart();

Self.DoAB(); // Let's do some anti-ban while chopping
Wait(60,120); // Slow down the loop 60-120ms so we're not chewing up CPU usage
end;

Wait(130, 850);
if SRL.Dice(15) then // 15% chance of rotating the camera
case SRL.Dice(50) of // 50/50 chance to rotate left or rght by 20-70 degrees
True: Minimap.SetCompassAngle(Minimap.GetCompassAngle() - random(20, 70));
False: Minimap.SetCompassAngle(Minimap.GetCompassAngle() + random(20, 70));
end;
end;

(* Deposit the logs *)
procedure TScript.DepositLogs();
var
i: Int32;
begin
if (not RSClient.IsLoggedIn) then Exit;
if (not DepositBox.IsOpen()) then // Is the depositbox already open?
if RSW.GetMyPos().DistanceTo(Self.BankTile) >= 15 then
begin
Self.WriteMsg('Walking to the deposit box');
Minimap.DisableRun();
RSW.WebWalk(Self.BankTile);
Exit;
end;

if (not Self.FindDepositBox()) then Exit;

if MainScreen.IsUpText(['eposit']) then
begin
Inc(Self.LogCount, Inventory.CountItem(Self.Tree.Log)); // Count the logs and save it to our 'LogCount' variable

Mouse.Click(MOUSE_LEFT);
if (not MainScreen.DidRedClick) then Exit;
Minimap.WaitPlayerMoving(200, 3000);

// Wait until the depositbox is open within 4.1 seconds, at an interval of 75ms
if (not WaitUntil(DepositBox.IsOpen(), 75, 4100)) then Exit;
end;

Wait(35, 450);
DepositBox.DepositItem([Self.Tree.Log, DEPOSITBOX_DEPOSIT_ALL], True); // Deposit all of 'Log' TItem, using quantity buttons
Wait(35, 750);

for i:=0 to high(Self.MiscItems) do // Deposit any other misc item (can be defined in TScript.Init()), such as birdnests
if DepositBox.FindItem(Self.MiscItems[i]) then
begin
DepositBox.DepositItem([Self.MiscItems[i], DEPOSITBOX_DEPOSIT_ALL], True);
Wait(35, 250);
end;

DepositBox.Close();
if (not WaitUntil((not DepositBox.IsOpen()), 75, 4100)) then DepositBox.Close(); // Try again?
Wait(175,350);

Self.Report(); // This is a good time to print out a progress report
if (getTimeRunning() > Self.ShutdownTime) then // Check if the script has been running for more than 'MAXRUNTIME'
begin
Logout.ClickLogout(); // If so, logout and terminate the script
TerminateScript('Time to shutdown');
Exit;
end;
end;

(* Our script's main repeating loop *)
procedure TScript.Run();
begin
while RSClient.IsLoggedIn do // While we're logged in do...
begin
if Inventory.IsFull() then // Full inventory, so go deposit logs
Self.DepositLogs()
else
Self.ChopTree(); // Not a full inventory, so chop some trees

Self.DoAB(); // Check if it's a good time to initiate some anti-ban
if (getTimeRunning() > Self.ShutdownTime) then // Time to shutdown?
begin
Logout.ClickLogout();
TerminateScript('Time to shutdown');
Exit;
end;
end;

Self.WriteMsg('Not logged in'); // No info given, so stay logged out
end;

(* Setup our script & variables *)
procedure TScript.Init();
begin
with Self do
begin
DeclarePlayers(); // Don't forget to do this!
SetupAntiban();
RSW.Setup('world'); // Must setup RSWalker as well
RSW.ScreenWalk := False; // True for walking via the mainscreen
RSW.EnableRunAtEnergy := 85; // At 85+ run energy, auto-enable running
MM2MS.ZoomLevel := Options.GetZoomLevel(); // Done just once per session to get zoom level. Needed for MMtoMS conversion
Mouse.Speed := 20; // Mouse speed, 20 seems nice
BankTile := [3995,3508]; // MM tile to walk to for the depositbox
end;

case lowercase(ToStr(TREETYPE)) of // Load tree variables based on the 'TREETYPE'
'willow': // Self-explanatory...
with Self.Tree do
begin
XP := 67;
WalkTile := [4043, 3436];
Color := CTS2(4161909, 1, 0.10, 0.71);
Log := 'Willow logs';
end;
end;

// Setup shutdown time, which is MAXRUNTIME X 60000 (1 minute), with a random +/- 10%
Self.ShutdownTime := (MAXRUNTIME * 60000) + Random(- (MAXRUNTIME * 6000), (MAXRUNTIME * 6000));
end;

begin
RSClient.Image.Clear(Mainscreen.Bounds); // Always a good idea to clear the RSClient's image, just in case
Bot.Init(); // Setup Bot (our TScript)
Bot.Run(); // Lights, camera, action!
end.

This tutorial was just intended to cover some of the basics, and keep in mind this just one of near limitless ways to structure a script. It's not the way to do it, just my way. If you'd like some more examples of SRL-OSR scripts I invite you to SRL-OSR's test scripts (includes/SRL-F/tests). Please do feel free to posts questions or comments and I'll try to help to the best of my ablity.

Roko

2022-01-06 11:21:00

Thank you very much for this. It actually helped me understand the basics again while being in a script itself. I have even tweaked it a bit to chop and fletch maple trees (not working perfectly but I understand it still). The comments helped me to figure out where to put extra tasks. Great work and nice of you to take the time to create this.

Flight

2022-01-09 12:04:22

From: Roko
Thank you very much for this. It actually helped me understand the basics again while being in a script itself. I have even tweaked it a bit to chop and fletch maple trees (not working perfectly but I understand it still). The comments helped me to figure out where to put extra tasks. Great work and nice of you to take the time to create this.


Very pleased to hear it aided you!

Tringy

2022-01-17 23:01:14

Hi Flight,

What is the best way to go about getting coordinates for walking? I've looked through the tutorials section and it doesn't seem like there's any straight answer that has been updated in the last 5 years.

Cheers

Flight

2022-01-18 07:03:35

From: Tringy
Hi Flight,

What is the best way to go about getting coordinates for walking? I've looked through the tutorials section and it doesn't seem like there's any straight answer that has been updated in the last 5 years.

Cheers


Definitely SPSToolbox, which can be found here. Obviously the Code Snippet doesn't apply directly to RSWalker, but the Copy To Clipboard functions correctly and spits out a TPA of the path you build.

For real time debugging of your position you could make a simple repeating loop that calls RSWalker.DebugPosition();, like so:

repeat
RSW.DebugPosition; // RSW = your instance of RSWalker
wait(250); // 250ms seems fast enough, and doesn't slaughter your CPU
until(False);

Tringy

2022-01-19 00:50:21

From: Flight
Definitely SPSToolbox, which can be found here. Obviously the Code Snippet doesn't apply directly to RSWalker, but the Copy To Clipboard functions correctly and spits out a TPA of the path you build.

For real time debugging of your position you could make a simple repeating loop that calls RSWalker.DebugPosition();, like so:

repeat
RSW.DebugPosition; // RSW = your instance of RSWalker
wait(250); // 250ms seems fast enough, and doesn't slaughter your CPU
until(False);


Thanks for this - SPSToolbox worked a treat. I'm still very bad at building scripts but based on what you've posted in this thread and the scripts in the SRL-OSR test I'm learning to put together a mining script which I'm super stoked about.

P.S. I don't have enough posts to reply to your PM but I'd be happy to test that other script for you :-)

Tringy

2022-01-21 07:10:24

I've used this script as a base now to make my mining script, but the problem I keep running in to is that when I drop the iron ore while power-mining, the script will always mouse over the dropped ore when attempting to find the iron rock. Could somebody point me in the right direction of how I would go about fixing this?

Flight

2022-01-21 10:36:12

From: Tringy
I've used this script as a base now to make my mining script, but the problem I keep running in to is that when I drop the iron ore while power-mining, the script will always mouse over the dropped ore when attempting to find the iron rock. Could somebody point me in the right direction of how I would go about fixing this?


The colors you used for your iron rocks are too similar with iron ores on the ground. You could remedy this by dropping an iron ore then use your ACA to choose a CTS2 color unique to the iron rocks and not the iron ore on the ground. You could also adjust the finder's grow, erode, MinShortSide/LongSide, and MaxShortSide/LongSide. For more info on this check out mainscreen.simba (Includes/SRL-F/osr/mainscreen.simba). Not sure if this'll work for you but here's the color I use for iron rocks in my private guild-miner:

CTS2(2306123, 11, 0.10, 0.56);

Gruntzer

2022-01-21 14:06:34

Hello Flight

first of all, thank you for the amazing effort you are doing <3

I have successfully edited the script to chop teaks, but for the life of me I can not figure out to drop the logs

I used to make simple scripts for rsbot

it was easy since already I can see the API and use the functions
if inventory is full
drop inventory

also, the antiban is has changed and no longer works, I just copied the new antiban from your fishing script :spongebob:

tehYosh

2022-01-21 15:31:49

Depending on what you want to drop (Full inventory or specific slots) you will need to use something along the lines of:
if Inventory.IsFull then //Check if the inventory is full.
Inventory.ShiftDrop(DROP_PATTERN_REGULAR); //Drop items from slot 1 through to 28.


var
slots: TIntegerArray;

if Inventory.IsFull then //Check if the inventory is full.
if Inventory.FindItem('Teak logs', slots) then //Find all slots that hold the item we're looking for and make an array of the results.
Inventory.ShiftDrop(slots); //Drop items in all valid slots that found the item.

It's worth noting that the above methods will only work if you have Shift Drop enabled in your game settings.

From: Gruntzer

I used to make simple scripts for rsbot

it was easy since already I can see the API and use the functions
if inventory is full
drop inventory

In Simba, if you look at the 'Function List' section you will see a bit called 'Includes', if you expand that and then click on one of the files that appear (For example 'Inventory') you'll get some documentation and a list of the functions within which are all available for you to use. You can also type the name of one of these in your script, followed by a '.' and you'll then get options to choose from, like so:


Flight - Yet again you continue to do God's work, thank you for all your hard work!

Flight

2022-01-21 16:27:02

From: Gruntzer
Hello Flight

first of all, thank you for the amazing effort you are doing <3

I have successfully edited the script to chop teaks, but for the life of me I can not figure out to drop the logs

I used to make simple scripts for rsbot

it was easy since already I can see the API and use the functions
if inventory is full
drop inventory

also, the antiban is has changed and no longer works, I just copied the new antiban from your fishing script :spongebob:


Good catch, I'll go ahead and adjust the OP to reflect the changes to SRL-F's antiban. And tehYosh, thank you kindly for providing those tips!

Tringy

2022-01-22 00:55:14

From: Flight
The colors you used for your iron rocks are too similar with iron ores on the ground. You could remedy this by dropping an iron ore then use your ACA to choose a CTS2 color unique to the iron rocks and not the iron ore on the ground. You could also adjust the finder's grow, erode, MinShortSide/LongSide, and MaxShortSide/LongSide. For more info on this check out mainscreen.simba (Includes/SRL-F/osr/mainscreen.simba). Not sure if this'll work for you but here's the color I use for iron rocks in my private guild-miner:

CTS2(2306123, 11, 0.10, 0.56);


Thanks Flights (again),

I managed to get a color with the ACA and used erode to a level that it was only picking up the rocks.

Cheers!!!

Pntbllfrk

2022-03-23 21:25:06

This is amazing, thank you.