slacky
02-16-2018, 11:42 PM
We don't have enough flyfishing bots that work at barbarian village! This release is partially for educational purposes to showcase SRL in action, in a simple bot.
This one does no debugging, and doesn't currently keep track over caught fish etc, it doesn't use SMART either. So in all it's very minimalistic. Feel free to try to expand on it and if you add cool features, you are free to publish your variant of it.
However, it's fairly accurate, somewhat efficient, and features decent antiban as well as breaking.
Features:
The bot has three options: Fish->Drop | Fish->Cook->Drop | Fish->Cook->Bank
You can start the bot just about anywhere "normal" (not a dungeon), it will find, or try to find it's path to barbarian village.
Can bank, but it may cause limited run-time, since the bank in edgeville is pretty bad.
Antiban, break-handling and fatigue to go with it.
Step by step setup:
Follow SRL setup procedures if you haven't yet. (https://villavu.com/forum/showthread.php?t=118211)
Requires SRL from Github (https://github.com/SRL/SRL/) version 1.0 or later compatible version.
Requires RSWalker from Github (https://github.com/slackydev/RSWalker/releases), version 1.1 or later compatible version.
Extract the last two in the correct folders: That is inside Simba/Include/ folder.
The script:
program BarbFlyFisher_V004;
{$I SRL/OSR.simba}
{$I RSWalker/Walker.simba}
{.$I SRL/utils/rsclient.simba}
{.$I SRL/utils/rsclient_overrides.simba}
{.$I WindowOverlay/WindowOverlay.simba}
{$H-}
{================================================= =============================]
| Barbarian FlyFisher ™
|
| Steps to use:
| 1. For longer runs you need to declare user details bellow
| 2. Start the script wherever, just have fishing rod and feathers in your inv
|
| Any issues starting it: Re-target RS, and try again, may help if you log
| in manually before doing that.
|
| Banking might not work very well.
[================================================== ============================}
type
TFisherStyle = (FishCookBank, FishCookDrop, FishDrop);
const
LOGIN_NAME = 'yourname';
LOGIN_PASS = 'yourpass';
RS_WORLD = -1; // preferred world, -1 = random world
IS_MEMBER = FALSE; // TRUE or FALSE
STYLE = FishCookBank; // FishCookBank or FishCookDrop, FishDrop
type
TFisher = record
StatsDebugTick: Int64;
Antiban: TAntiban;
end;
var
Bot: TFisher;
RSW: TRSWalker;
{$ifdecl TWindowOverlay}
Overlay: TWindowOverlay;
Debug: TMufasaBitmap;
{$endif}
var
SalmonDTM := DTMFromString('mrAAAAHic42BgYJjKxMDQD8RdQLwQiBcA8S wg7gDi6UD8DKjmAxC/BOLbQPwIiF8A8XsgvgvEp10lgCQjTizHgB/g1gnBMAAAzZcNRg==');
TroutDTM := DTMFromString('mrAAAAHic42BgYJjGxMDQAcQTmCDshUC8BI inA3E/EHMxMjAIAzEHEDMA8R8gxQykBYBYBIibstMgEjiwHAN+gFsnBM MAABHQB5c=');
BurntDTM := DTMFromString('mlwAAAHicY2dgYJjKxMAwDYg7ofRcIF4CxA uBOICRgcEDiGOAOAqIA4HYG4hdgNjSxASomxEHxg1w6UDSBQBl 4wcl');
RawTrout := DTMFromString('mggAAAHicY2NgYJjKxMAwDYgXAvESKLsDiM sZGRhygDgDiPOBuA6I64F457q1QF2MWDB2gE0lQjUAQtcIfQ== ');
RawSalmon := DTMFromString('mlwAAAHicY2dgYJjGBMELgXgJlN0BxL1ArM fIwKACxApArA7EZkBszggRX5efBNTNiAPjBrh0IOkCAEQMBvk= ');
Feathers := DTMFromString('mlwAAAHicY2dgYHBmYmBwAGJvIHYBYlsgtg NiKyB+ApS/B8QPgfgNEH8G4hdA/BGIt69ZAyQZsWI5BtwAuw4IhgIAZtgKcg==');
FishingRod:= DTMFromString('m1gAAAHic42JgYMhiYmCIB+JsIC4E4gogLg PiAiDOAeJ0IE4F4qdAtW+A+A4Q3wDiq0B8H4ifAfE7IP4MxE+A ONqZE0gyEsRyDMQBwiZBMAIAAO7FDhY=');
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// OVERRIDES AND METHODS FOR FATIGUE
procedure WaitFatigue(t: Double; Exp: Double=0.2);
begin
System.Wait(Trunc(2*t * (1-Power(System.Max(0.0001, Bot.Antiban.EnergyLevel()/100),Exp))));
end;
procedure Wait(min, max:Double; weight:EWaitDir=wdMean); override;
var t: Double;
begin
t := PerformanceTimer();
inherited(min, max, weight);
WaitFatigue(PerformanceTimer()-t);
end;
procedure WaitEx(mean, dev:Double); override;
var t: Double;
begin
t := PerformanceTimer();
inherited(mean, dev);
WaitFatigue(PerformanceTimer()-t);
end;
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// FISHER
procedure TFisher.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;
procedure TFisher.DoAntiban();
begin
srl.DismissRandom();
if Self.Antiban.DoAntiban() then
Players.GetCurrent()^.Login(); // if we got logged out, and not logged back in
end;
procedure TFisher.PostAction(AntiBan:Boolean=True);
begin
WaitEx(450,70);
if AntiBan then Self.DoAntiban;
end;
procedure TFisher.ProcessWhileWaiting();
begin
if GetTickCount() - StatsDebugTick > 2000 then
begin
ClearDebug();
ClearDebug();
WriteLn('+---| STATS |----------------------------------------');
WriteLn('|- Script Runtime : ', SRL.MsToTime(GetTimeRunning, Time_Short));
WriteLn('|- Time Since Break : ', SRL.MsToTime(Antiban.TimeSinceBreak(), Time_Short));
//WriteLn('|- Recent Break Len : ', SRL.MsToTime(Antiban.ResidualBreakValue(), Time_Short));
WriteLn('|- Energy Level : ', Round(Antiban.EnergyLevel,2));
WriteLn('+----------------------------------------------------');
Self.StatsDebugTick := GetTickCount();
end;
Self.DoAntiban;
end;
// Find fishingspots by finding the edges of the water, over and over again
// Then do some fancy stuff to remove land->water borders.
// what's left is an accurate TPA of the fishingspot
function TFisher.FindFishingSpot(scanTime: Int32=450): T2DPointArray;
var
i: Int32;
SUM,TPA: TPointArray;
R: TRectangle;
t: TCountDown;
begin
t.Init(scanTime);
while not t.IsFinished do
begin
srl.FindColors(TPA, CTS2(8875103,16,0.2,0.7), Mainscreen.GetBounds);
SUM += TPA.Edges();
end;
SUM.ClearDuplicates();
SUM := ClearTPAFromTPA(Sum, Sum.Edges());
Result := SUM.Cluster(5);
Result.FilterSize(12, __GT__);
{$ifdecl TWindowOverlay}
Debug.Clear();
for i:=0 to High(Result) do
Debug.DrawTPA(Result[i], Random($FFFFFF));
{$endif}
end;
// Basically we find the fishingrod by checking the two tiles infront of
// our character. It can fail if your character covers most of the rod
function TFisher.IsFishing(): Boolean;
var
rect1,rect2: TRectangle;
TPA1,TPA2: TPointArray;
begin
Rect1 := Minimap.StaticToMsRect([646,84],1);
Rect2 := Minimap.StaticToMsRect([649,84],1);
{$ifdecl TWindowOverlay}
Debug.DrawRect(Rect1, $FFFFFF);
Debug.DrawRect(Rect2, $FFFFFF);
{$endif}
if srl.FindColors(TPA1, CTS2(6694,10), Rect1.Bounds) > 12 then
Result := srl.FindColors(TPA2, CTS2(6694,10), Rect2.Bounds) > 5;
end;
// Finds fishing spots, click one, and waits while we are fishing
//
function TFisher.Fish(): Boolean;
var
ATPA: T2DPointArray;
TPA: TPointArray;
begin
if (not Inventory.Contains(FishingRod)) or
(not Inventory.Contains(Feathers)) then
TerminateScript('No feathers or fly fishing rod');
ATPA := Self.FindFishingSpot();
ATPA.SortByMiddle(mainscreen.GetMiddle);
for TPA in ATPA do
begin
mouse.Move(TPA.Bounds);
if not MainScreen.IsUpText(['Fishing spot']) then
Continue;
if mouse.Click(ctRed) then
begin
Wait(700,1000);
Minimap.WaitPlayerMoving();
Wait(1400,1700);
Self.FindFishingSpot(); //update drawing.
while Self.IsFishing() do
begin
Self.ProcessWhileWaiting();
Chatbox.HandleLevelUp();
WaitEx(70,10);
end;
Exit(True);
end else
begin
Wait(700,1200);
Minimap.WaitPlayerMoving();
Wait(700,1200);
Exit(False);
end;
end;
end;
// Waits while we are cooking.
// Cooking is determined by checking if the number of raw fish in our inventory
// is reducing. It must reduce by at least 1 within 5.5 seconds.
function TFisher.WaitCooking(): Boolean;
var
c, currCount: Int32;
t: TCountDown;
begin
c := Inventory.Count(RawTrout) + Inventory.Count(RawSalmon);
t.Init(5500);
repeat
if Chatbox.GotLevelUp then
Break;
currCount := Inventory.Count(RawTrout) + Inventory.Count(RawSalmon);
if currCount <> c then
begin
c := currCount;
t.Restart(50);
end;
Self.ProcessWhileWaiting();
Wait(70);
until t.IsFinished() or (c = 0);
Result := True;
end;
// Do the cooking!
// 1. Walks to a point near the eternal fire.
// 2. Searches for the fire and uses a fish on the fire
// If it fails to find the fire it rotates the screen and tries again.
// 3. Cooks it, and waits til we dont cook any more, or till we level up.
// Repeats #2->#3 until there are no more fish in our inventory.
function TFisher.Cook(): Boolean;
var
idx: Int32;
arr: TIntArray;
rect: TRectangle;
Objs: T2DPointArray;
Fire: TPointArray;
FoundFire: Boolean;
begin
Inventory.Open();
if (not Inventory.Contains(RawTrout)) and (not Inventory.Contains(RawSalmon)) then
Exit;
if Distance(Point(4230,2718), RSW.GetMyPos) > 8 then
RSW.WebWalk(Point(4230,2718), 2);
repeat
arr := Inventory.FindItem(RawTrout) + Inventory.FindItem(RawSalmon);
if(arr = []) then Break;
FoundFire := False;
srl.FindColors(Fire, CTS2(12348,15), MainScreen.GetBounds);
Objs := Fire.Cluster(5);
Objs.FilterSize(16, __GT__);
Objs.SortByMiddle(Mainscreen.GetMiddle);
Inventory.Use(arr[0]);
for Fire in Objs do
begin
rect := Fire.MinAreaRect();
mouse.Move(rect);
Wait(60,100); //wait for game to refresh
if MainScreen.IsUpText('Fire') then
mouse.Click(mouse_Left)
else if MainScreen.IsUpText('options') then
begin
if not ChooseOption.Select('Fire') then
begin
Wait(60,200);
Continue;
end
end else
continue;
FoundFire := True;
Chatbox.ClickButtonId('How many', 1, 'Cook', 3000);
if Self.WaitCooking() then
Break;
end;
if(not FoundFire) then
Minimap.SetCompassAngle([0,90,180,270][Random(4)]+Random(-15,15));
until False;
end;
// Clear the inventory by dropping, or banking fish.
//
procedure TFisher.DoInventory();
var
dtms, slots: TIntArray;
dtm: Int32;
t: TCountDown;
// Deposits all the fish in our inventory, cooked, raw and burnt.
procedure Deposit();
begin
RSW.WebWalk(locEdgevilleBank, 3);
for 0 to 2 do
if BankScreen.Open(blEdgeville) then
Break
else
Wait(800,100);
if not BankScreen.IsOpen() then
TerminateScript('No bank');
dtms := [SalmonDTM, TroutDTM, BurntDTM, RawTrout, RawSalmon];
for dtm in dtms do
begin
slots := Inventory.FindItem(dtm);
if Length(slots) > 0 then
begin
BankScreen.DepositItem(slots[0], True);
t.Init(2000);
while (not t.IsFinished) and Inventory.IsSlotUsed(slots[0],False) do
Wait(70,160);
end;
end;
end;
// drop all the fish in our inventory, cooked, raw and burnt.
procedure Drop();
var
Ptrn: TIntArray;
i: Int32;
begin
dtms := [SalmonDTM, TroutDTM, BurntDTM, RawTrout, RawSalmon];
for dtm in dtms do
slots += Inventory.FindItem(dtm);
for i:=0 to 27 do
if slots.Find(i) <> -1 then
Ptrn += i;
// same as Inventory.DropItems(ptrn) except we add some errors to the order
Inventory.DropItems(Inventory.ErrorPattern(ptrn));
end;
begin
if STYLE in [FishCookDrop, FishDrop] then
Drop()
else
Deposit();
end;
// Runs the bot
//
procedure TFisher.Run();
begin
MainScreen.SetAngle(True);
while srl.IsLoggedIn() do
begin
if Inventory.IsFull() then
begin
if STYLE <> FishDrop then
begin
self.Cook();
self.PostAction();
end;
self.DoInventory();
self.PostAction();
end;
if not self.Fish() then
begin
if RSW.GetMyPos.DistanceTo([4245, 2716]) > 20 then
RSW.WebWalk(Point(4245, 2716),3)
else
RSW.WebWalk(Point(4223, 2748),3);
Wait(700,1200);
end;
{$ifdecl TWindowOverlay}
Debug.Clear();
{$endif}
Self.ProcessWhileWaiting();
end;
end;
procedure TFisher.SetupAntiban();
begin
Antiban.Init(SKILL_FISHING, 4);
Antiban.AddTask([@Antiban.LoseFocus, ONE_MINUTE*5]);
Antiban.AddTask([@Antiban.HoverPlayers, ONE_MINUTE*8]);
Antiban.AddTask([@Antiban.CheckSkill, ONE_MINUTE*9]);
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([45 * ONE_MINUTE, 05 * ONE_MINUTE, 0.05]);
Antiban.AddBreak([02 * ONE_HOUR, 10 * ONE_MINUTE, 0.15]);
Antiban.AddBreak([04 * ONE_HOUR, 45 * ONE_MINUTE, 0.85]);
Antiban.AddBreak([17 * ONE_HOUR, 07 * ONE_HOUR, 0.99]);
end;
procedure TFisher.Init();
begin
RSW.Init('world.png');
{$ifdecl TWindowOverlay}
Overlay := TWindowOverlay.Create();
Overlay.PaintInterval(100);
Debug := Overlay.ToMufasaBitmap();
{$endif}
self.DeclarePlayers();
self.SetupAntiban();
Inventory.ShiftDrop := True;
Players.LoginCurrent();
end;
procedure TFisher.Free();
begin
RSW.Free();
{$ifdecl TWindowOverlay}
Overlay.Free();
Debug.Free();
{$endif}
FreeDTMs([SalmonDTM, TroutDTM, BurntDTM, RawTrout, RawSalmon, Feathers, FishingRod]);
end;
begin
{$ifdecl RSClient}
srl.SetupForClient([soDebugAntiban]);
RSClient.SetFocus();
{$else}
srl.Setup([]);
{$endif}
bot.Init();
AddOnTerminate(@bot.Free);
bot.Run();
end.
Before you ask:
No, it doesn't 3 tick fish or whatever you call it. It's a bot, it's pointless to have the bot be maximum efficient (it's free XP).. And higher XP/H can have side-effects resulting in higher ban-rate, that is since it very easily will be too perfect in comparison to a human that feels fatigue, can be sloppy at times, etc. So it's a lot of extra work, for very little gain.
WARNING: Use at your own risk.
This one does no debugging, and doesn't currently keep track over caught fish etc, it doesn't use SMART either. So in all it's very minimalistic. Feel free to try to expand on it and if you add cool features, you are free to publish your variant of it.
However, it's fairly accurate, somewhat efficient, and features decent antiban as well as breaking.
Features:
The bot has three options: Fish->Drop | Fish->Cook->Drop | Fish->Cook->Bank
You can start the bot just about anywhere "normal" (not a dungeon), it will find, or try to find it's path to barbarian village.
Can bank, but it may cause limited run-time, since the bank in edgeville is pretty bad.
Antiban, break-handling and fatigue to go with it.
Step by step setup:
Follow SRL setup procedures if you haven't yet. (https://villavu.com/forum/showthread.php?t=118211)
Requires SRL from Github (https://github.com/SRL/SRL/) version 1.0 or later compatible version.
Requires RSWalker from Github (https://github.com/slackydev/RSWalker/releases), version 1.1 or later compatible version.
Extract the last two in the correct folders: That is inside Simba/Include/ folder.
The script:
program BarbFlyFisher_V004;
{$I SRL/OSR.simba}
{$I RSWalker/Walker.simba}
{.$I SRL/utils/rsclient.simba}
{.$I SRL/utils/rsclient_overrides.simba}
{.$I WindowOverlay/WindowOverlay.simba}
{$H-}
{================================================= =============================]
| Barbarian FlyFisher ™
|
| Steps to use:
| 1. For longer runs you need to declare user details bellow
| 2. Start the script wherever, just have fishing rod and feathers in your inv
|
| Any issues starting it: Re-target RS, and try again, may help if you log
| in manually before doing that.
|
| Banking might not work very well.
[================================================== ============================}
type
TFisherStyle = (FishCookBank, FishCookDrop, FishDrop);
const
LOGIN_NAME = 'yourname';
LOGIN_PASS = 'yourpass';
RS_WORLD = -1; // preferred world, -1 = random world
IS_MEMBER = FALSE; // TRUE or FALSE
STYLE = FishCookBank; // FishCookBank or FishCookDrop, FishDrop
type
TFisher = record
StatsDebugTick: Int64;
Antiban: TAntiban;
end;
var
Bot: TFisher;
RSW: TRSWalker;
{$ifdecl TWindowOverlay}
Overlay: TWindowOverlay;
Debug: TMufasaBitmap;
{$endif}
var
SalmonDTM := DTMFromString('mrAAAAHic42BgYJjKxMDQD8RdQLwQiBcA8S wg7gDi6UD8DKjmAxC/BOLbQPwIiF8A8XsgvgvEp10lgCQjTizHgB/g1gnBMAAAzZcNRg==');
TroutDTM := DTMFromString('mrAAAAHic42BgYJjGxMDQAcQTmCDshUC8BI inA3E/EHMxMjAIAzEHEDMA8R8gxQykBYBYBIibstMgEjiwHAN+gFsnBM MAABHQB5c=');
BurntDTM := DTMFromString('mlwAAAHicY2dgYJjKxMAwDYg7ofRcIF4CxA uBOICRgcEDiGOAOAqIA4HYG4hdgNjSxASomxEHxg1w6UDSBQBl 4wcl');
RawTrout := DTMFromString('mggAAAHicY2NgYJjKxMAwDYgXAvESKLsDiM sZGRhygDgDiPOBuA6I64F457q1QF2MWDB2gE0lQjUAQtcIfQ== ');
RawSalmon := DTMFromString('mlwAAAHicY2dgYJjGBMELgXgJlN0BxL1ArM fIwKACxApArA7EZkBszggRX5efBNTNiAPjBrh0IOkCAEQMBvk= ');
Feathers := DTMFromString('mlwAAAHicY2dgYHBmYmBwAGJvIHYBYlsgtg NiKyB+ApS/B8QPgfgNEH8G4hdA/BGIt69ZAyQZsWI5BtwAuw4IhgIAZtgKcg==');
FishingRod:= DTMFromString('m1gAAAHic42JgYMhiYmCIB+JsIC4E4gogLg PiAiDOAeJ0IE4F4qdAtW+A+A4Q3wDiq0B8H4ifAfE7IP4MxE+A ONqZE0gyEsRyDMQBwiZBMAIAAO7FDhY=');
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// OVERRIDES AND METHODS FOR FATIGUE
procedure WaitFatigue(t: Double; Exp: Double=0.2);
begin
System.Wait(Trunc(2*t * (1-Power(System.Max(0.0001, Bot.Antiban.EnergyLevel()/100),Exp))));
end;
procedure Wait(min, max:Double; weight:EWaitDir=wdMean); override;
var t: Double;
begin
t := PerformanceTimer();
inherited(min, max, weight);
WaitFatigue(PerformanceTimer()-t);
end;
procedure WaitEx(mean, dev:Double); override;
var t: Double;
begin
t := PerformanceTimer();
inherited(mean, dev);
WaitFatigue(PerformanceTimer()-t);
end;
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// FISHER
procedure TFisher.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;
procedure TFisher.DoAntiban();
begin
srl.DismissRandom();
if Self.Antiban.DoAntiban() then
Players.GetCurrent()^.Login(); // if we got logged out, and not logged back in
end;
procedure TFisher.PostAction(AntiBan:Boolean=True);
begin
WaitEx(450,70);
if AntiBan then Self.DoAntiban;
end;
procedure TFisher.ProcessWhileWaiting();
begin
if GetTickCount() - StatsDebugTick > 2000 then
begin
ClearDebug();
ClearDebug();
WriteLn('+---| STATS |----------------------------------------');
WriteLn('|- Script Runtime : ', SRL.MsToTime(GetTimeRunning, Time_Short));
WriteLn('|- Time Since Break : ', SRL.MsToTime(Antiban.TimeSinceBreak(), Time_Short));
//WriteLn('|- Recent Break Len : ', SRL.MsToTime(Antiban.ResidualBreakValue(), Time_Short));
WriteLn('|- Energy Level : ', Round(Antiban.EnergyLevel,2));
WriteLn('+----------------------------------------------------');
Self.StatsDebugTick := GetTickCount();
end;
Self.DoAntiban;
end;
// Find fishingspots by finding the edges of the water, over and over again
// Then do some fancy stuff to remove land->water borders.
// what's left is an accurate TPA of the fishingspot
function TFisher.FindFishingSpot(scanTime: Int32=450): T2DPointArray;
var
i: Int32;
SUM,TPA: TPointArray;
R: TRectangle;
t: TCountDown;
begin
t.Init(scanTime);
while not t.IsFinished do
begin
srl.FindColors(TPA, CTS2(8875103,16,0.2,0.7), Mainscreen.GetBounds);
SUM += TPA.Edges();
end;
SUM.ClearDuplicates();
SUM := ClearTPAFromTPA(Sum, Sum.Edges());
Result := SUM.Cluster(5);
Result.FilterSize(12, __GT__);
{$ifdecl TWindowOverlay}
Debug.Clear();
for i:=0 to High(Result) do
Debug.DrawTPA(Result[i], Random($FFFFFF));
{$endif}
end;
// Basically we find the fishingrod by checking the two tiles infront of
// our character. It can fail if your character covers most of the rod
function TFisher.IsFishing(): Boolean;
var
rect1,rect2: TRectangle;
TPA1,TPA2: TPointArray;
begin
Rect1 := Minimap.StaticToMsRect([646,84],1);
Rect2 := Minimap.StaticToMsRect([649,84],1);
{$ifdecl TWindowOverlay}
Debug.DrawRect(Rect1, $FFFFFF);
Debug.DrawRect(Rect2, $FFFFFF);
{$endif}
if srl.FindColors(TPA1, CTS2(6694,10), Rect1.Bounds) > 12 then
Result := srl.FindColors(TPA2, CTS2(6694,10), Rect2.Bounds) > 5;
end;
// Finds fishing spots, click one, and waits while we are fishing
//
function TFisher.Fish(): Boolean;
var
ATPA: T2DPointArray;
TPA: TPointArray;
begin
if (not Inventory.Contains(FishingRod)) or
(not Inventory.Contains(Feathers)) then
TerminateScript('No feathers or fly fishing rod');
ATPA := Self.FindFishingSpot();
ATPA.SortByMiddle(mainscreen.GetMiddle);
for TPA in ATPA do
begin
mouse.Move(TPA.Bounds);
if not MainScreen.IsUpText(['Fishing spot']) then
Continue;
if mouse.Click(ctRed) then
begin
Wait(700,1000);
Minimap.WaitPlayerMoving();
Wait(1400,1700);
Self.FindFishingSpot(); //update drawing.
while Self.IsFishing() do
begin
Self.ProcessWhileWaiting();
Chatbox.HandleLevelUp();
WaitEx(70,10);
end;
Exit(True);
end else
begin
Wait(700,1200);
Minimap.WaitPlayerMoving();
Wait(700,1200);
Exit(False);
end;
end;
end;
// Waits while we are cooking.
// Cooking is determined by checking if the number of raw fish in our inventory
// is reducing. It must reduce by at least 1 within 5.5 seconds.
function TFisher.WaitCooking(): Boolean;
var
c, currCount: Int32;
t: TCountDown;
begin
c := Inventory.Count(RawTrout) + Inventory.Count(RawSalmon);
t.Init(5500);
repeat
if Chatbox.GotLevelUp then
Break;
currCount := Inventory.Count(RawTrout) + Inventory.Count(RawSalmon);
if currCount <> c then
begin
c := currCount;
t.Restart(50);
end;
Self.ProcessWhileWaiting();
Wait(70);
until t.IsFinished() or (c = 0);
Result := True;
end;
// Do the cooking!
// 1. Walks to a point near the eternal fire.
// 2. Searches for the fire and uses a fish on the fire
// If it fails to find the fire it rotates the screen and tries again.
// 3. Cooks it, and waits til we dont cook any more, or till we level up.
// Repeats #2->#3 until there are no more fish in our inventory.
function TFisher.Cook(): Boolean;
var
idx: Int32;
arr: TIntArray;
rect: TRectangle;
Objs: T2DPointArray;
Fire: TPointArray;
FoundFire: Boolean;
begin
Inventory.Open();
if (not Inventory.Contains(RawTrout)) and (not Inventory.Contains(RawSalmon)) then
Exit;
if Distance(Point(4230,2718), RSW.GetMyPos) > 8 then
RSW.WebWalk(Point(4230,2718), 2);
repeat
arr := Inventory.FindItem(RawTrout) + Inventory.FindItem(RawSalmon);
if(arr = []) then Break;
FoundFire := False;
srl.FindColors(Fire, CTS2(12348,15), MainScreen.GetBounds);
Objs := Fire.Cluster(5);
Objs.FilterSize(16, __GT__);
Objs.SortByMiddle(Mainscreen.GetMiddle);
Inventory.Use(arr[0]);
for Fire in Objs do
begin
rect := Fire.MinAreaRect();
mouse.Move(rect);
Wait(60,100); //wait for game to refresh
if MainScreen.IsUpText('Fire') then
mouse.Click(mouse_Left)
else if MainScreen.IsUpText('options') then
begin
if not ChooseOption.Select('Fire') then
begin
Wait(60,200);
Continue;
end
end else
continue;
FoundFire := True;
Chatbox.ClickButtonId('How many', 1, 'Cook', 3000);
if Self.WaitCooking() then
Break;
end;
if(not FoundFire) then
Minimap.SetCompassAngle([0,90,180,270][Random(4)]+Random(-15,15));
until False;
end;
// Clear the inventory by dropping, or banking fish.
//
procedure TFisher.DoInventory();
var
dtms, slots: TIntArray;
dtm: Int32;
t: TCountDown;
// Deposits all the fish in our inventory, cooked, raw and burnt.
procedure Deposit();
begin
RSW.WebWalk(locEdgevilleBank, 3);
for 0 to 2 do
if BankScreen.Open(blEdgeville) then
Break
else
Wait(800,100);
if not BankScreen.IsOpen() then
TerminateScript('No bank');
dtms := [SalmonDTM, TroutDTM, BurntDTM, RawTrout, RawSalmon];
for dtm in dtms do
begin
slots := Inventory.FindItem(dtm);
if Length(slots) > 0 then
begin
BankScreen.DepositItem(slots[0], True);
t.Init(2000);
while (not t.IsFinished) and Inventory.IsSlotUsed(slots[0],False) do
Wait(70,160);
end;
end;
end;
// drop all the fish in our inventory, cooked, raw and burnt.
procedure Drop();
var
Ptrn: TIntArray;
i: Int32;
begin
dtms := [SalmonDTM, TroutDTM, BurntDTM, RawTrout, RawSalmon];
for dtm in dtms do
slots += Inventory.FindItem(dtm);
for i:=0 to 27 do
if slots.Find(i) <> -1 then
Ptrn += i;
// same as Inventory.DropItems(ptrn) except we add some errors to the order
Inventory.DropItems(Inventory.ErrorPattern(ptrn));
end;
begin
if STYLE in [FishCookDrop, FishDrop] then
Drop()
else
Deposit();
end;
// Runs the bot
//
procedure TFisher.Run();
begin
MainScreen.SetAngle(True);
while srl.IsLoggedIn() do
begin
if Inventory.IsFull() then
begin
if STYLE <> FishDrop then
begin
self.Cook();
self.PostAction();
end;
self.DoInventory();
self.PostAction();
end;
if not self.Fish() then
begin
if RSW.GetMyPos.DistanceTo([4245, 2716]) > 20 then
RSW.WebWalk(Point(4245, 2716),3)
else
RSW.WebWalk(Point(4223, 2748),3);
Wait(700,1200);
end;
{$ifdecl TWindowOverlay}
Debug.Clear();
{$endif}
Self.ProcessWhileWaiting();
end;
end;
procedure TFisher.SetupAntiban();
begin
Antiban.Init(SKILL_FISHING, 4);
Antiban.AddTask([@Antiban.LoseFocus, ONE_MINUTE*5]);
Antiban.AddTask([@Antiban.HoverPlayers, ONE_MINUTE*8]);
Antiban.AddTask([@Antiban.CheckSkill, ONE_MINUTE*9]);
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([45 * ONE_MINUTE, 05 * ONE_MINUTE, 0.05]);
Antiban.AddBreak([02 * ONE_HOUR, 10 * ONE_MINUTE, 0.15]);
Antiban.AddBreak([04 * ONE_HOUR, 45 * ONE_MINUTE, 0.85]);
Antiban.AddBreak([17 * ONE_HOUR, 07 * ONE_HOUR, 0.99]);
end;
procedure TFisher.Init();
begin
RSW.Init('world.png');
{$ifdecl TWindowOverlay}
Overlay := TWindowOverlay.Create();
Overlay.PaintInterval(100);
Debug := Overlay.ToMufasaBitmap();
{$endif}
self.DeclarePlayers();
self.SetupAntiban();
Inventory.ShiftDrop := True;
Players.LoginCurrent();
end;
procedure TFisher.Free();
begin
RSW.Free();
{$ifdecl TWindowOverlay}
Overlay.Free();
Debug.Free();
{$endif}
FreeDTMs([SalmonDTM, TroutDTM, BurntDTM, RawTrout, RawSalmon, Feathers, FishingRod]);
end;
begin
{$ifdecl RSClient}
srl.SetupForClient([soDebugAntiban]);
RSClient.SetFocus();
{$else}
srl.Setup([]);
{$endif}
bot.Init();
AddOnTerminate(@bot.Free);
bot.Run();
end.
Before you ask:
No, it doesn't 3 tick fish or whatever you call it. It's a bot, it's pointless to have the bot be maximum efficient (it's free XP).. And higher XP/H can have side-effects resulting in higher ban-rate, that is since it very easily will be too perfect in comparison to a human that feels fatigue, can be sloppy at times, etc. So it's a lot of extra work, for very little gain.
WARNING: Use at your own risk.