Simba Code:
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('mrAAAAHic42BgYJjKxMDQD8RdQLwQiBcA8Swg7gDi6UD8DKjmAxC/BOLbQPwIiF8A8XsgvgvEp10lgCQjTizHgB/g1gnBMAAAzZcNRg==');
TroutDTM := DTMFromString('mrAAAAHic42BgYJjGxMDQAcQTmCDshUC8BIinA3E/EHMxMjAIAzEHEDMA8R8gxQykBYBYBIibstMgEjiwHAN+gFsnBMMAABHQB5c=');
BurntDTM := DTMFromString('mlwAAAHicY2dgYJjKxMAwDYg7ofRcIF4CxAuBOICRgcEDiGOAOAqIA4HYG4hdgNjSxASomxEHxg1w6UDSBQBl4wcl');
RawTrout := DTMFromString('mggAAAHicY2NgYJjKxMAwDYgXAvESKLsDiMsZGRhygDgDiPOBuA6I64F457q1QF2MWDB2gE0lQjUAQtcIfQ==');
RawSalmon := DTMFromString('mlwAAAHicY2dgYJjGBMELgXgJlN0BxL1ArMfIwKACxApArA7EZkBszggRX5efBNTNiAPjBrh0IOkCAEQMBvk=');
Feathers := DTMFromString('mlwAAAHicY2dgYHBmYmBwAGJvIHYBYlsgtgNiKyB+ApS/B8QPgfgNEH8G4hdA/BGIt69ZAyQZsWI5BtwAuw4IhgIAZtgKcg==');
FishingRod:= DTMFromString('m1gAAAHic42JgYMhiYmCIB+JsIC4E4gogLgPiAiDOAeJ0IE4F4qdAtW+A+A4Q3wDiq0B8H4ifAfE7IP4MxE+AONqZE0gyEsRyDMQBwiZBMAIAAO7FDhY=');
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// 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.
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.