SRL Archive - OSR Help

Help with combat script


Tringy

2022-02-15 21:00:15

Hey team,

I'm relatively new to scripting (and unfortunately have been using more of other people's scripts than my own) but nevertheless I am trying to put something together outside of Flight's tutorial on making your own first script :p

I'm currently attempting to make a script that will AFK Ammonite Crabs for me and I think I have a lot of the bones of the script done (hopefully), but the error I am running into right now is that the walker does not want to work for me.

Runtime error: "MatchTemplateMask: Cache is empty" at line 283, column 30 in file "C:\Simba 1.4\Includes\SRL-F\osr\walker\walker.simba"

Which highlights the code " Matrix := MatchTemplateMask(Cache, Sample.ToMatrix, TM_CCOEFF_NORMED);"

What am I doing wrong here? I've put my script below in case there's something wrong with the script, or anyone spots anything else obvious I have done wrong (because I can't get the script to run)

program CrabKiller;  
{$DEFINE SRL_USE_REMOTEINPUT}
{$I SRL-F/osr.simba}

var
RSW: TRSWalker;
AGGRO: TPoint := [1457, 316];
RESET: TPoint := [1351, 397];

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

Type
TScript = record
RSW : TRSWalker;
ShutdownTime: Int64;
end;
Var
Bot: TScript;

procedure TScript.WriteMsg(Message: String);
begin
WriteLn('[Bot]: ', Message);
end;

procedure TScript.DeclarePlayers();
begin
Login.AddPlayer(PNAME, PPASS, PPIN, []);
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.STRENGTH;
// 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;

function TRSMainScreen.InCombat: Boolean;
begin
Result := (Self.FindHitsplats <> []);
end;

function AtTile(Tile: TPoint; Distance: Int32 = 15): Boolean;
begin
Result := RSW.GetMyPos.DistanceTo(Tile) <= Distance;
end;

function TScript.WaitCombat: Boolean;
begin
if MainScreen.InCombat then
WaitUntil(not MainScreen.InCombat, 10000, -1);
end;

procedure TScript.GetAggro();
begin
while RSClient.IsLoggedIn do
begin
if not AtTile(AGGRO) and not MainScreen.InCombat() then
Self.WriteMsg('Returning to Crabs');
Minimap.EnableRun();
RSW.WebWalk(AGGRO, 0, 0.2);
end;
end;

procedure TScript.ResetAggro();
begin
while RSClient.IsLoggedIn do
begin
if not MainScreen.InCombat() then
Wait(Random(100, 5000));
RSW.WebWalk(RESET, 10, 0.2);
end;
end;

procedure TScript.Init();
begin
DeclarePlayers();
SetupAntiban();
RSW.Setup('world');
RSW.ScreenWalk := False; // True for walking via the mainscreen
RSW.EnableRunAtEnergy := 85;
MM2MS.ZoomLevel := Options.GetZoomLevel();
Mouse.Speed := 20;
end;

procedure TScript.Run();
begin
while RSClient.IsLoggedIn do
begin
if AtTile(AGGRO) and not MainScreen.InCombat() then
Self.ResetAggro();
Self.GetAggro();
end;
Self.WaitCombat();
Self.DoAB();
if (getTimeRunning() > Self.ShutdownTime) then
begin
Logout.ClickLogout();
TerminateScript('Time to shutdown');
Exit;
end;
end;
begin
RSClient.Image.Clear(Mainscreen.Bounds);
Bot.Init();
Bot.Run();
end.

Thanks in advance!

masterBB

2022-02-16 14:03:56

Hi Tringy

In your script you have defined a TRSWalker twice. One of them is in the TScript type, and one of them as a global.

The global walker is on line 6 and the TScript scoped walker is on line 19. The problem is that the second walker will be setup with your Init function. But the global RSW is never setup. Because your function "AtTile" is not part of TScript, it will use the global RSW walker. And thus giving you the error.

I advice you to use a single instance of the walker, so please delete on of the aforementioned lines (6 or 19).

Tringy

2022-02-16 18:34:34

Thank you! I knew it would be something I had overlooked, I'll read my code a bit better next time :-)

Tringy

2022-02-17 08:56:57

I have encountered another problem, and I would really appreciate some guidance on where to look if anyone could help –

The script currently works to AFK Ammonite Crabs but doesn't perform the antiban properly, and sometimes doesn't recognize that it is still in combat and will use the function
Self.ResetAggro()

I assume that the antiban might have something to do with my use of
while MainScreen.InCombat() do
begin
while Self.WaitCombat() do
Self.DoAB();[CODE]

but I'm not exactly sure how to fix it?

For the ResetAggro function, I've tried increasing
WaitUntil(not MainScreen.InCombat, 35000, 3 * ONE_DAY);
in
function TScript.WaitCombat: Boolean;
begin
if MainScreen.InCombat then
WaitUntil(not MainScreen.InCombat, 35000, 3 * ONE_DAY);
end;
but still get the same result?

Full script code is below:

program CrabKiller;
{$DEFINE SRL_USE_REMOTEINPUT}
{$I SRL-F/osr.simba}

var
RSW: TRSWalker;
AGGROEAST: TPoint := [1520, 319];
RESETEAST: TPoint := [1365, 372];
AGGROWEST: TPoint := [1457, 316];
RESETWEST: TPoint := [1351, 397];
AGGRO := AGGROEAST;
RESET := RESETEAST;

const
PNAME = '';
PPASS = '';
PPIN = '';
MAXRUNTIME = 100;

type
TScript = record
ABTimeMod: Int32;
ShutdownTime: Int64;
end;

var
Bot: TScript;

procedure TScript.WriteMsg(Message: String);
begin
WriteLn('[Bot]: ', Message);
end;

procedure TScript.DeclarePlayers();
begin
Login.AddPlayer(PNAME, PPASS, PPIN, []);
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.STRENGTH;
Antiban.Skills += ERSSKILL.AGILITY;
Antiban.AddTask((ONE_MINUTE * 1) * Self.ABTimeMod, @ Antiban.SmallRandomMouse);
Antiban.AddTask((ONE_MINUTE * 4) * Self.ABTimeMod, @ Self.DoLoseFocus);
Antiban.AddTask((ONE_MINUTE * 5) * Self.ABTimeMod, @ Antiban.HoverMSPlayers);
Antiban.AddTask((ONE_MINUTE * 6) * Self.ABTimeMod, @ Antiban.HoverMSItems);
Antiban.AddTask((ONE_MINUTE * 6) * Self.ABTimeMod, @ Antiban.HoverMSNPCs);
Antiban.AddTask((ONE_MINUTE * 7) * Self.ABTimeMod, @ Antiban.RandomRotate);
Antiban.AddTask((ONE_MINUTE * 15) * Self.ABTimeMod, @ Antiban.HoverSkills);
Antiban.AddBreak(ONE_MINUTE * 18, ONE_SECOND * 40, 0.2, 0.0);
end;

procedure TScript.DoAB();
begin
Antiban.DoAntiban();
Antiban.DismissRandom();
end;

function TRSMainScreen.InCombat: Boolean;
begin
Result := (Self.FindHitsplats <> []);
end;

function AtTile(Tile: TPoint; Distance: Int32 = 15): Boolean;
begin
Result := RSW.GetMyPos.DistanceTo(Tile) <= Distance;
end;

function TScript.WaitCombat: Boolean;
begin
if MainScreen.InCombat then
WaitUntil(not MainScreen.InCombat, 35000, 3 * ONE_DAY);
end;

procedure TScript.GetAggro();
begin
Self.WriteMsg('Returning to Crabs');
Minimap.EnableRun();
RSW.WebWalk(AGGRO, 0, 0.2);
end;

procedure TScript.ResetAggro();
begin
Self.WriteMsg('Resetting Aggro');
RSW.WebWalk(RESET, 10, 0.2);
end;

procedure TScript.Init();
begin
RSW.EnableRunAtEnergy := 85;
MM2MS.ZoomLevel := Options.GetZoomLevel();
Mouse.Speed := Random(19, 24);
Self.ABTimeMod := 1;
Self.ShutdownTime := (MAXRUNTIME * 60000) + Random(- (MAXRUNTIME * 6000), (MAXRUNTIME * 6000));
DeclarePlayers();
Self.SetupAntiban();
RSW.Setup('world');
end;

procedure TScript.Run();
begin
if RSClient.IsLoggedIn then
repeat
while MainScreen.InCombat() do
begin
while Self.WaitCombat() do
Self.DoAB();
end;
if not MainScreen.InCombat() then
begin
Self.ResetAggro();
Self.GetAggro();
end;
until (getTimeRunning() > Self.ShutdownTime);
Logout.ClickLogout();
TerminateScript('Time to shutdown');
end;

begin
RSClient.Image.Clear(Mainscreen.Bounds);
ClearDebug;
Bot.Init();
Bot.Run();
end.

Any guidance would be very much appreciated. I'm hoping to get this in a state where it's good enough to share it in the public scripts as there's not too many combat scripts there at the moment :-)

Cheers

tehYosh

2022-02-17 13:41:50

Fun fact, you can use the
 tags in place of [CODE] and it will format the segments in the script just to help with visibility :)

Looking at your script, I see this following section:
[SIMBA]
function TRSMainScreen.InCombat: Boolean;
begin
Result := (Self.FindHitsplats <> []);
end;
I'm not familiar with using these crabs for combat training, but my concern is that whilst you're in combat there will be sections of time where hit splats won't display, could that potentially be causing an issue?

With my own combat script (more of a colour clicker, but I digress!) I use the Mainscreen.FindHPBars function in conjunction with hit splats to detect if I'm in combat or not, though this has it's limitations with other players who might also be using the area.

Perhaps you could try something like:

function TRSMainScreen.InCombat: Boolean;
begin
if Self.FindHitsplats <> [] then exit(True); // If we find any hitsplats then we're in combat (Exit function as True)
if Mainscreen.FindHPBars <> [] then exit(True); // If we find any HP bars then we're in combat (Exit function as True)
// If neither of the above are true, the function will return False without any extra lines.
end;
I'm sure someone with more knowledge than me might be able to help use the Mainscreen.FindHPBars in conjuction with Mainscreen.GetPlayerBox, but sadly I'm not that guy.

Hope this helps and I haven't gone down a completely different rabbit hole!

masterBB

2022-02-17 18:14:47

I think your main problem is the reliability of the FindHitsplats function. Personally I would suggest that one negative does not mean you are out of combat. I suggest something like this:


procedure TScript.WaitCombat(attempts: Int32);
var
fails: Int32;
begin
while (fails < attempts) do
begin
if(MainScreen.FindHitsplats <> []) then
begin
WriteLn('We found hitsplats, we must be in combat');
fails := 0;
end else
begin
WriteLn('We dit not found hitsplats. Fails: ' + ToStr(fails));
Inc(fails); //increases fails by one
end;
Wait(500);
end;
end;

I wrote this in my browser, so errors might be included. It still requires some antiban and a timer making sure this does not run for more than x amount of time. But the basic logic is that if we did not found hitsplats for x amount of time, we must not be in be in com

Tringy

2022-02-17 19:45:23

From: masterBB
I think your main problem is the reliability of the FindHitsplats function. Personally I would suggest that one negative does not mean you are out of combat. I suggest something like this:


procedure TScript.WaitCombat(attempts: Int32);
var
fails: Int32;
begin
while (fails < attempts) do
begin
if(MainScreen.FindHitsplats <> []) then
begin
WriteLn('We found hitsplats, we must be in combat');
fails := 0;
end else
begin
WriteLn('We dit not found hitsplats. Fails: ' + ToStr(fails));
Inc(fails); //increases fails by one
end;
Wait(500);
end;
end;

I wrote this in my browser, so errors might be included. It still requires some antiban and a timer making sure this does not run for more than x amount of time. But the basic logic is that if we did not found hitsplats for x amount of time, we must not be in be in com


Thanks a lot! I like this approach and it looks like it works well. I've added in the antiban to this and I think all my problems are solved (for now) :-)

Flight

2022-02-18 17:26:52

A different approach to this might be determining if your player is attacking a NPC or not rather than if your player is being attacked. Whereas it might not be as critical for a AFK-style combat script it would be quite useful for aggressive fighters. Here's a very abridged version of my slayer script's combat detection:

function TScript.PlayerAttacking(): Boolean;
var
T: TCountDown;
HS: TRSHitsplat;
HSA: TRSHitsplatArray;
begin
T.Init(1300+Random(200)); // ToDo: Variable based off player's weapon speed
While (not T.IsFinished) do
begin
if Result then Break;
HSA := MainScreen.FindHitsplats(Mainscreen.Bounds);
if length(HSA) > 0 then
for HS in HSA do
if (not HS.Position.InBox(Mainscreen.GetPlayerBox())) then // Ignore hitsplats on our player
Exit(True);

Wait(30, 75);
end;
end;
This uses a countdown timer as is my style in most scripts, but will come to a very similar conclusion as the example posted above by masterBB.