SRL Archive - Jr. Member General Help and Discussion

[Dev Log] Burthrope Agility


Brotein

2014-01-17 18:54:12

Hey guys, creating a thread to document everything I do to update this script from pre RS3 to current. Worked on this I guess a year ago now, everything went pretty smoothly on it. Wasn't happy with the DTM for the rope, maybe I can change it this time around. Anyways here's my old code…

program BroteinBurthrope;
{$DEFINE SMART}
{$DEFINE SRL5}
{$i SRL/srl.simba}
{$IFDEF SMART}
{$I SRL/SRL/Misc/SmartGraphics.Simba}
{$ENDIF}

////////////////////////////////////////////////////////////////////////////////
// Read Me!!! //
// http://www.youtube.com/watch?v=Tu8qY__oAM8 //
////////////////////////////////////////////////////////////////////////////////
// - Start this script at the beginning of the course in Burthrope. No food //
// is needed for this course. Average xp/hr is ~8,000. //
////////////////////////////////////////////////////////////////////////////////

var
x, y, obstacle, Monkey, t, XpCount, LapTotal, XpHour, StartTime, Sec: integer;
aFound: extended;
PBox: TBox;

const
ScriptVersion = '1.30';
UseAutoChecker = true;

////////////////////////////////////////////////////////////////////////////////
// Set up your Character info here!!! //
////////////////////////////////////////////////////////////////////////////////
procedure DeclarePlayers;
begin
HowManyPlayers := 1;
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0;
Players[0].Name := 'Ignore'; //Set your player name here
Players[0].Pass := 'Ignore'; //Set your player password here
Players[0].Pin := ''; //Set your player PIN here
Players[0].Active := True;
end;

procedure SetupLogin;
begin
ClearDebug;
{$IFDEF SIMBAMAJOR980}
SMART_SERVER := 10;
SMART_MEMBERS := TRUE;
SMART_SIGNED := TRUE;
SMART_SUPERDETAIL := FALSE;
{$ELSE}
SRL_SIXHOURFIX := TRUE;
SMART_FIXSPEED := TRUE;
{$ENDIF}
SetupSRL;
DeclarePlayers;
LoginPlayer;
end;
////////////////////////////////////////////////////////////////////////////////
// Script starts here //
////////////////////////////////////////////////////////////////////////////////

// * Procedure AutoUpdateMe by Harry and Shuttleu
// * Auto-Downloads the newest version of the script when run.
procedure AutoUpdateMe;
var Neifile:integer;
OnlineVersion, NewScript, NeiFeilNennen:string;
begin
if UseAutoChecker then
begin
Writeln('Checking for latest version...');
OnlineVersion := GetPage('Ignore');
Writeln(OnlineVersion);
Writeln(ScriptVersion)
if (trim(OnlineVersion) > ScriptVersion) then
begin
Writeln('Newer Version Found!');
Writeln('Autoupdating to newer version...');
NewScript := GetPage('Ignore');
NeiFeilNennen := ScriptPath+ 'BroAgile_Burthrope_v'+OnlineVersion+'.simba';
Neifile := Rewritefile(NeiFeilNennen, true);
try
WriteFileString(Neifile, NewScript);
except
begin
Writeln('Fatal error writing to '+NeiFeilNennen+'!!');
Terminatescript;
end;
end;
CloseFile(Neifile);
Writeln('New script downloaded to '+NeiFeilNennen+'!! Please use this one!!');
TerminateScript;
end else
Writeln('You have the latest version of the script!');
end else
Writeln('!!!!! Not checking for latest version, you may be outdated!');
end;

// * Procedure SetDTMs
// * Declares DTMs to be used for the course.
// # These have been tested a lot, but please report errors if they exist.
procedure SetDTMs;
begin
Monkey := DTMFromString('mWAAAAHicY2FgYHgExK+BmIGRgeEnkOoE4i4orgHiYHcLBnkpUYbkCB+G2ztqGFKAYvxImBENgwAAJooJsA==');
end;

// * Procedure FreeTheDTMs
// * Frees the DTMs from memory.
procedure FreeTheDTMs;
begin
FreeDTM(Monkey);
end;

// * Procedure AntiBan
// * Will frequent the agility skill icon in the skills tab. Will also do
// random mouse movements and screen rotation.
// # These should be non-disruptive, but if they are please report them.
procedure AntiBan;
begin
if not(LoggedIn)then
Exit;
case Random(180)of
0: PickUpMouse;
1: RandomRClick;
2: HoverSkill('Agility', false);
3: RandomMovement;
end;
end;

// * Procedure LogColor
// * Creates TPA for Log Balance obstacle.
// * Sets camera to high North(0), searches for TPA "LogTPA", and clicks on
// random area of the log.
// * Increments course completion to (1/6).
// # Color:3487805, Hue:0.7, Sat:0.68, CTS:2, Tol:5
procedure LogColor;
var
LogTPA:TPointArray;
LogATPA:T2DPointArray;
LogBox:TBox;
begin
SetColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.7, 0.68);
if findcolorstolerance(LogTPA, 3487805, MSX1, MSY1, MSX2, MSY2, 5) then
begin
LogATPA := SplitTPAEx(LogTPA, 30, 30);
SortATPASize(LogATPA, True);
LogBox := GetTPABounds(LogATPA[0]);
SMART_ClearCanvas;
SMART_DrawDotsEx(True, LogTPA, clYellow);
SMART_DrawBoxes(False, False ,[GetTPABounds(LogTPA)], clAqua);
SMART_DebugATPA(False,LogATPA);
Mousebox(GetTPABounds(LogATPA[0]).X1, GetTPABounds(LogATPA[0]).Y1, GetTPABounds(LogATPA[0]).X2, GetTPABounds(LogATPA[0]).Y2, 2);
SetColorToleranceSpeed(1);
SetColorSpeed2Modifiers(0.2, 0.2);
Wait(50 + random(25));
if(isUpText('og be'))then
begin
Wait(150 + random(50));
ClickMouse2(True);
WriteLn('Found Log!');
Wait(6200 + random(100));
if FindChatBoxText('lost', 8, clBlack) then
begin
Writeln('YOU FELL! Lets try again...');
wait(3000);
LogColor;
end;
obstacle := 1;
end;
end;
end;

// * Procedure WallColor
// * Creates TPA for Wall obstacle.
// * Searches for TPA "WallTPA", and clicks on the arrow/wall.
// * Sets camera to high South during obstacle, for preperation of balance.
// * Increments course completion to (2/6).
// # Color:13356504, Hue:0.53, Sat:1.69, CTS:2, Tol:5
procedure WallColor;
var
WallTPA:TPointArray;
WallATPA:T2DPointArray;
WallBox:TBox;
begin
SetColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.53, 1.69);
if findcolorstolerance(WallTPA, 13356504, 229, 28, 293, 114, 5) then
begin
WallATPA := SplitTPAEx(WallTPA, 10, 10);
SortATPASize(WallATPA, True);
WallBox := GetTPABounds(WallATPA[0]);
SMART_ClearCanvas;
SMART_DrawDotsEx(True, WallTPA, clYellow);
SMART_DrawBoxes(False, False ,[GetTPABounds(WallTPA)], clAqua);
SMART_DebugATPA(False,WallATPA);
Mousebox(GetTPABounds(WallATPA[0]).X1, GetTPABounds(WallATPA[0]).Y1, GetTPABounds(WallATPA[0]).X2, GetTPABounds(WallATPA[0]).Y2, 2);
SetColorToleranceSpeed(1);
SetColorSpeed2Modifiers(0.2, 0.2);
Wait(50 + random(25));
if(isUpText('limb'))then
begin
Wait(150 + random(50));
ClickMouse2(True);
WriteLn('Found ladder!');
SetAngle(SRL_ANGLE_HIGH);
MakeCompass(180);
Wait(3800 + random(100));
obstacle := 2;
end;
end;
end;

// * Procedure BalanceColor
// * Creates and Searches TPA for Balance Beam obstacle and clicks on random
// area of ATPA[0] after boundries have been modified to click the cloest
// part of the plank.This is done because the 2nd partition has no action,
// and the third is "out of reach".
// * Sets camera high East during balance, for preperation of shields.
// * Increments course completion to (3/6).
// # Color:5072243, Hue:0.1, Sat:0.2, CTS:2, Tol:5
procedure BalanceColor;
var
BalanceTPA:TPointArray;
BalanceATPA:T2DPointArray;
BalanceBox:TBox;
begin
SetColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.1, 0.2);
if findcolorstolerance(BalanceTPA, 5072243, MSX1, MSY1, MSX2, MSY2, 5) then
begin
BalanceATPA := SplitTPAEx(BalanceTPA, 30, 30);
SortATPASize(BalanceATPA, True);
BalanceBox := GetTPABounds(BalanceATPA[0]);
SMART_ClearCanvas;
SMART_DrawDotsEx(True, BalanceTPA, clYellow);
SMART_DrawBoxes(False, False ,[GetTPABounds(BalanceTPA)], clAqua);
SMART_DebugATPA(False,BalanceATPA);
SMART_DrawBoxes(False,false, [IntToBox(GetTPABounds(BalanceATPA[0]).X1, GetTPABounds(BalanceATPA[0]).Y1, GetTPABounds(BalanceATPA[0]).X1 + 25, GetTPABounds(BalanceATPA[0]).Y2 + 2)], clPurple);
Mousebox(GetTPABounds(BalanceATPA[0]).X1, GetTPABounds(BalanceATPA[0]).Y1, GetTPABounds(BalanceATPA[0]).X1 + 25, GetTPABounds(BalanceATPA[0]).Y2 + 2, 2);
SetColorToleranceSpeed(1);
SetColorSpeed2Modifiers(0.2, 0.2);
Wait(150 + random(25));
if(isUpText('alanc'))then
begin
Wait(150 + random(50));
ClickMouse2(True);
WriteLn('Found Balance!');
Wait(150 + random(50));
SetAngle(SRL_ANGLE_HIGH);
MakeCompass('E');
Wait(2700 + random(100));
obstacle := 3;
end;
end;
end;

// * Procedure ShieldColor
// * Creates TPA for Shield obstacle.
// * Searches for TPA "ShieldTPA", and clicks on lower shield.
// * Sets camera to high South during obstacle, in preperation of rope.
// * Increments course completion to (4/6).
// # Color:9801358, Hue:0.0, Sat:0.12, CTS:2, Tol:12
procedure ShieldColor;
var
ShieldTPA:TPointArray;
ShieldATPA:T2DPointArray;
ShieldBox:TBox;
begin
SetColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.0, 0.12);
if findcolorstolerance(ShieldTPA, 9801358, MSX1, MSY1, MSX2, MSY2, 12) then
begin
ShieldATPA := SplitTPAEx(ShieldTPA, 10, 10);
SortATPASize(ShieldATPA, True);
ShieldBox := GetTPABounds(ShieldATPA[0]);
SMART_ClearCanvas;
SMART_DrawDotsEx(True, ShieldTPA, clYellow);
SMART_DrawBoxes(False, False ,[GetTPABounds(ShieldTPA)], clAqua);
SMART_DebugATPA(False,ShieldATPA);
Mousebox(GetTPABounds(ShieldATPA[0]).X1, GetTPABounds(ShieldATPA[0]).Y1, GetTPABounds(ShieldATPA[0]).X2, GetTPABounds(ShieldATPA[0]).Y2, 2);
SetColorToleranceSpeed(1);
SetColorSpeed2Modifiers(0.2, 0.2);
Wait(50 + random(25));
if(isUpText('limb'))then
begin
Wait(150 + random(50));
ClickMouse2(True);
WriteLn('Found Shields!');
Wait(150 + random(50));
SetAngle(SRL_ANGLE_HIGH);
MakeCompass(180);
Wait(3500 + random(100));
if FindChatBoxText('footing', 8, clBlack) then
begin
Writeln('YOU FELL! Lets try again');
wait(3000);
ShieldColor;
end;
obstacle := 4;
end;
end;
end;

// * Procedure RopeColor
// * Creates TPA for Rope Swing obstacle.
// * Searches for TPA "RopeTPA", and clicks on rope.
// * Increments course completion to (5/6).
// # Color:402731, Hue:0.11, Sat:0.41, CTS:2, Tol:10
procedure RopeColor;
var
RopeTPA:TPointArray;
RopeATPA:T2DPointArray;
RopeBox:TBox;
begin
SetColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.11, 0.41);
if findcolorstolerance(RopeTPA, 402731, MSX1, MSY1, MSX2, MSY2, 10) then
begin
RopeATPA := SplitTPAEx(RopeTPA, 5, 5);
SortATPASize(RopeATPA, True);
RopeBox := GetTPABounds(RopeATPA[0]);
SMART_ClearCanvas;
SMART_DrawDotsEx(True, RopeTPA, clYellow);
SMART_DrawBoxes(False, False ,[GetTPABounds(RopeTPA)], clAqua);
SMART_DebugATPA(False,RopeATPA);
Mousebox(GetTPABounds(RopeATPA[0]).X1, GetTPABounds(RopeATPA[0]).Y1, GetTPABounds(RopeATPA[0]).X2, GetTPABounds(RopeATPA[0]).Y2, 2);
SetColorToleranceSpeed(1);
SetColorSpeed2Modifiers(0.2, 0.2);
Wait(150 + random(25));
if(isUpText('wing'))then
begin
Wait(150 + random(50));
ClickMouse2(True);
WriteLn('Found Rope!');
Wait(3500 + random(100));
obstacle := 5;
end;
end;
end;

// * Procedure DoMonkey
// * Searches for DTM "Monkey", and clicks on monkey bars.
// * Sets camera to high North during obstacle, in preperation for checker jump.
// * Increments course completion to (6/6).
procedure DoMonkey;
begin
if FindDTMRotated(Monkey, x, y, 197, 53, 295,193, -Pi, Pi, Pi/30, aFound)then
begin
PBox := IntToBox(197, 53, 295,193);
SMART_DrawBoxEx(true, false, PBox, clRed);
MMouse(x, y, 0, 0);
Wait(300 + random(50));
if(IsUpTextMultiCustom(['ing', 'across', 'Swi', 'Swing', 'wing-', 'across', 'Swing-across']))then
begin
ClickMouse2(True);
SMART_DrawBoxEx(true, false, PBox, clGreen);
WriteLn('Found Monkey!');
Wait(450 + random(50));
SMART_ClearMS
ClickNorth(SRL_ANGLE_HIGH);
Wait(4400 + random(100));
obstacle := 6;
end;
end;
end;

// * Procedure CheckerColor
// * Creates TPA for Checker obstacle and clicks on random area of ATPA[0].
// * Updates progress report information.
// * Resets course completion to (0/6).
// # Color:5992831, Hue:0.03, Sat:0.05, CTS:2, Tol:40
procedure CheckerColor;
var
CheckerTPA:TPointArray;
CheckerATPA:T2DPointArray;
CheckerBox:TBox;
begin
SetColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.03, 0.05);
if findcolorstolerance(CheckerTPA, 5992831, MSX1, MSY1, MSX2, MSY2, 40) then
begin
CheckerATPA := SplitTPAEx(CheckerTPA, 5, 5);
SortATPASize(CheckerATPA, True);
CheckerBox := GetTPABounds(CheckerATPA[0]);
SMART_ClearCanvas;
SMART_DrawDotsEx(True, CheckerTPA, clYellow);
SMART_DrawBoxes(False, False ,[GetTPABounds(CheckerTPA)], clAqua);
SMART_DebugATPA(False,CheckerATPA);
Mousebox(GetTPABounds(CheckerATPA[0]).X1, GetTPABounds(CheckerATPA[0]).Y1, GetTPABounds(CheckerATPA[0]).X2, GetTPABounds(CheckerATPA[0]).Y2, 2);
SetColorToleranceSpeed(1);
SetColorSpeed2Modifiers(0.2, 0.2);
Wait(300 + random(50));
if(isUpText('ump'))then
begin
Wait(200 + random(50));
ClickMouse2(True);
WriteLn('Found Checkers!');
Wait(150 + random(50));
ClickNorth(SRL_ANGLE_LOW);
Wait(750 + random(100));
obstacle := 0;
end;
end;
end;

// * Procedure DoCourse
// * Base case is off integer "obstacle" for course completion porgress.
// * If base case is met, will search for DTM/TPA of case, and execute the
// procedure of the selected case.
// * Will print status of "Looking..." or "Found" when executed.
// # This is prevent searching for DTMs that are all present on the screen, and
// will only search for the one based off progress.
// # (Case/Procedure) - (0/Log), (1/Ladder), (2/Balance), (3/Shields),
// (4/Rope), (5,Monkey), (6/Checker).
procedure DoTheCourse;
var
x, y: integer;
begin
if obstacle = 0 then
begin
WriteLn('Looking For Log...');
MarkTime(t);
repeat
LogColor;
wait(100);
if TimeFromMark(t) > 30000 then
begin
Writeln('Timed out finding log, stopping script!');
Logout;
TerminateScript;
end;
until(obstacle = 1);
end;

if obstacle = 1 then
begin
WriteLn('Looking For Ladder...');
MarkTime(t);
repeat
WallColor;
wait(100);
if TimeFromMark(t) > 30000 then
begin
Writeln('Timed out finding Wall, stopping script!');
Logout;
TerminateScript;
end;
until(obstacle = 2);
end;

if obstacle = 2 then
begin
WriteLn('Looking For Balance...');
PBox := IntToBox(186, 145, 508, 309);
SMART_DrawBoxEx(true, false, PBox, clRed);
MarkTime(t);
repeat
BalanceColor;
wait(100);
if TimeFromMark(t) > 30000 then
begin
Writeln('Timed out finding Balance, stopping script!');
Logout;
TerminateScript;
end;
until(obstacle = 3);
end;

if obstacle = 3 then
begin
WriteLn('Looking For Shields...');
MarkTime(t);
repeat
ShieldColor;
wait(100);
if TimeFromMark(t) > 30000 then
begin
Writeln('Timed out finding Shields, stopping script!');
Logout;
TerminateScript;
end;
until(obstacle = 4);
end;

if obstacle = 4 then
begin
WriteLn('Looking For Rope...');
MarkTime(t);
repeat
RopeColor;
wait(100);
if TimeFromMark(t) > 30000 then
begin
Writeln('Timed out finding Rope, stopping script!');
Logout;
TerminateScript;
end;
until(obstacle = 5);
end;

if obstacle = 5 then
begin
WriteLn('Looking For Monkey...');
MarkTime(t);
repeat
DoMonkey;
wait(100);
if TimeFromMark(t) > 30000 then
begin
Writeln('Timed out finding Monkey, stopping script!');
Logout;
TerminateScript;
end;
until(obstacle = 6);
end;

if obstacle = 6 then
begin
WriteLn('Looking For Checker...');
MarkTime(t);
repeat
CheckerColor;
wait(100);
if TimeFromMark(t) > 30000 then
begin
Writeln('Timed out finding Checker, stopping script!');
Logout;
TerminateScript;
end;
until(obstacle = 0);
IncEx(LapTotal, 1);
XpCount := LapTotal * 79;
end;
end;

procedure ProgressReport;
begin
Sec := (GetTimeRunning/1000);
XpHour := (3600*XpCount) / (Sec);
Writeln('*************Progress Report***************');
Writeln(TimeRunning);
Writeln('Laps Completed: ' + IntToStr(LapTotal));
Writeln('Xp Gained: ' + IntToStr(XpCount));
Writeln('Xp per Hour: ' + IntToStr(XpHour));
Writeln('*******************************************');
end;

// * Procedure Main
// * Sets up client and players.
// * Sets camera to high North, and sets our DTMs, and will free them when the
// script is finished.
// * Sets course completion to (0/6).
begin
AutoUpdateMe
SetupLogin;
SetupSRL;
DeclarePlayers;
ActivateClient;
LoginPlayer;
ClickNorth(SRL_ANGLE_LOW);
obstacle := 0;
SetDTMs;
repeat
DoTheCourse;
FindNormalRandoms;
AntiBan;
ProgressReport;
until(AllPlayersInactive);
FreeTheDTMs;
end.

Here's the youtube video showing how it works(and breaks :) )
http://youtu.be/Tu8qY__oAM8

So I guess I will go and update all the code, but post updates as I redo each procedure and explain whatever changes I made or just the code in general. Stay tuned, hopefully I can get back to grips with SRL after this.

IROC-Z

2014-01-17 21:19:11

This seems like it could be very helpful for others and hopefully I can learn a little too. Good idea!

Brotein

2014-01-19 19:43:28

Ran through the course again, camera movement is almost instantaneous which is great and should allow this script to run faster and not have lag issues on clicking the last obstacle. Been reading through some of the tutorials, doesn't look too difficult to update this. Also trying to find the best camera position now, probably going to do zoomed all the way out.

But since I'm lazy I did the easy part first. Here's the progress report :)



Bmp := BitmapFromString(568, 146, 'meJzsvYd7FMe2L3rPOXt7J2xj' +
'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' +
'j535jbt7jpiJ5kPBE3ffGYqhyAoLEqTSXXVXfSIG5sGX9GI68ff4/' +
'cjhtquygl37rqFqUZzD5XuA1ffL96yyaMuL6Zsv6b0wsY84pETdNL' +
'G+prv/HTcfzYUbdxUVKU71Xy9q1bni14YP9eqpKlQjbSbniw36vAr' +
'Vu3BOzYfXun3K5/8P57XR2tc1UEWxJuy14FOtpb21ubn1oO1EqtkJ' +
'B1BC6mkgQdPet/6uT75HGhVSVdvnTJd0Wgkm5jHxJgeRUeHR6kMi/' +
'5uHz5ElSDauxzE6NAwMfqvfnGsfndUSnH/rzipYM/Vbaro2f8eENL' +
't92kyVCyCJ5KoeMp5ytUwiw9H38YMc8sLbEpgIMQAZF5KscoBoZCc' +
'f+y9EIqnsrQzvAU8aaVQYh4Ci1RQcqbYS5Rrs08Ojza0zfe2D6WW9' +
'Wy/rWZeU7mM0f3DaloX3/z/372tO7k/WUb1pIRgaeohAEUt+mTyV4' +
'Uj/HSv1KiFOxEOq7pPkxZjZ7DnjqSn3PIiOt6j1CVAxA0Vl3zxhWq' +
'jKA1DeLapvFntbNTQazjyvI2KsnVr5/GVkXWmF9brxt7DyPStCnDn' +
'EluR/Lz5FP6KnUvra0u/9Ifx6effBK+Zb3buBjs7/Uq/P5773q24J' +
'7JCarCk8VspF1RQe6carVnaqKjrXlOWW5MT2N77tszOae8nsd7J94' +
'l61iQlzWn7FB/PC5UyeIbN6bnWoGB/h63PvPpJx/PtRC3A0wk4Sd4' +
'jn0+K2Z6em41PHrk8P/xeOnrXltSWtfeOXJkd3O3zaDKVNHxlHOJi' +
'njVt8AsAp5KU7AIAlJxck2SYuervsAy5A0SzmgSIuCpFFl8mpKdqR' +
'MgngIxiyzOjaeAyIhlLLSbQi/A0W7Rzg3EU1lWw/DAYP/gZHPXRNX' +
'Orq3rlpMd0meJ7ruqrI15/f/yQ9q2xQ2RpmTiJ1c7knO9tnuUBiJ4' +
'0wakY8jwu5QlZ1V56ujWczAiIUwFN/IejVXXHLtClXGlOZsO8Zmt/' +
'Vr9CLkdXytvp1bhhFuU5o3VnfMDxValgVsp0+F2xIjkhWOavkrVS2' +
'urK+/549i6cZXnuHj3nbe9Ck9Njnu2IFykKlwuZiGNxILEOdWqtaU' +
'J0pyynD93DtsTaGJOeb0eGoUU68hnRc8pb0tTA7JSdNiGc+fOzq8C' +
'7a1N5D5DY2ffj48//sht7M+7hv293XO9o1KNfd/Hhds+irL6ztaBA' +
'7saOlJ08ixNYol1Zt4PLRhl6/jg2pSmJVc6ZniqODWp0EIEkQDqsc' +
'jiUxUscJQKrTL0ClVqcgL4Smi/OhGdzygGIjMnxVmdM4RwBX00xJq' +
'cYBBHQ3a7mgs8BSWAXwZUBTLZeiFen0L+lOsVKlGWRTvQ3TU2tre5' +
'Y7S+tXdDyFLsP+KNJaHziu77Wll7yJX/+exp9UcPN6nNZMQVxS1Uw' +
'sFtB9ziCW/M27lq6jOa8l87fBnruP7YVSqxleYcTx2pIhgHG7Mo1T' +
'lyhcaqUBnKelpyaBBXlrQ9o53BquR2XFvRQanC0AncB1CU5g2VnVT' +
'Ca7JrmB8/pMQ9889MNh8Q15RT9paViXzy86Rf4qXX1Vbe9sdx5osv' +
'0sxqt3EBF70K9/V2e7bgxPgoVeFk7eZUq+amhtbmhrkpcuYLbM/Ji' +
'bE55fV65OVkkHvpnPJC5VELTj1DTa5cuSwXsXCfaWnaPe+iyAf0HP' +
'LYHx7omXdRnj2H/o7q33jpISsWVzX1tfbvr9vdbtHIMlQJxSki5E/' +
'NgacMQiApFG2JeIXq5+GpApPIYVT3dXaMjO5p7hxr7h4P2/waefPJ' +
's0T3XV7UHHzxf/gnnf4rI46NEZcXtfit5Iv/Y6stD+sYcugSldhqc' +
'46njnga2W13zQZrHiXiwYs0VoVfKTMas2kQ15V3PKMdXtVnktsxpL' +
'SNUrj/HcbsKM2rSiiFwW4blAY66DedN+TaISoBaPpgf8dLr6ksu+G' +
'n4+LFiyJuLHlcwBWvkk0N9Z4tODYyRFUyWbvPT3/me5Uad++CNCct' +
'Tn/2GbYnTZV8P8DC5F4K5fuet7mxHloQrPqMdejp6sB9Bsp8xtLQA' +
'YrgsR+1fb1XmZMfvJ9q0aNeWldTTtUfDh7YN6c7KtXY931ckHlq9a' +
'plta1DLX2v1+5qNaul6cq4efEUEZKixKZAPJUii/t5eEps0yV3tbY' +
'MD0+2dI219EysX/1qkJ+i+y4raH717H/6Ky0f/QQjrihs9VexK6oH' +
'yTqG9L1DKWmv8NQRTzExZkcwXmYrp1Sk+y0aqy7bd4EqY0hGFR3iM' +
'1ubEc8jt+OKghYqyWXdbzFIMw/0wiHGbNBxVe0wDXTw2CevHrtFUz' +
'E8dU9uAnyFqq/S9NKKsuLr/jv279tLHhdUYk0NuzxbcGR4yKvw+fP' +
'nydq9cfyo7/UBoN27auekwqeffILtSVUldDTs3rVlfbBz80DM8WOU' +
'tQILk3vpsaNHfK8M1B9aEP5SCezbu0fIiUW1BbHz5895FcM2hNYpL' +
'y2iQXz/vRMZNjMaibnZGe+9d4JGWKuUonZsqN/pDfQcNyGS3EuTpX' +
'yqoqK2rfP9jko19n0fF2SeWrNqaV3HCPBUdV2LSSVJV8QWWYTz5im' +
'gIRTi72fiqVSNrKO5aWgIeGq8tXdq0/oQpp+i+zKL25Z+/h9+TEFR' +
'CQhxVWGrXwpkdL/tpmNI8wFK9IoBTx3JDnswKYLxqw2vU5WzovF1G' +
'qsu3XOesgJ5TTSIy/Obn9EaqxN55HZcU0Rp5BXDH+PxgrIsL6AUXm' +
'/JRTouHfpo3u1OfrzEYzD4GeKlV5cXX/HrkRgbhqtHJbOrrsazBQc' +
'H+rwKf/TRh2Ttjhw+7HtlAAj10tD1wWfOnPEqs33ja1T2HB4a8JoF' +
'iuLER5CtCrdZqjqUlxSSe+nRI3Oof7OTp9595x2vv7a3tbiNRL1SQ' +
'lWUIkmAhHMy7VQyYOqEyE3kkQjGeeedt6nkcTvumZr0/LWjvcXTql' +
'Tq52Q5fL+jUo1938fFrLhJG1c3tY01dUxW72w2KsRZWlZJijjX+dU' +
'nFN8PeApYAygDqAp9Usq55Q8ISJim4pikscA1QC4gUGZTAKeAPLhU' +
'dhUnUyfINUlyTBKbUwyoyqZi5wABOUP8AZ0ZJTFwHcguQydwfsaX5' +
'9BwIWU5N1Hg93zxq75wMd0sad5dOTayp7V1sqP39cgdW5h+iu67LL' +
'f5pU//3WsKGvzoiSfrnERdsyV0WfnAyx/8SJUFEqNyCJUPkjRiPiZ' +
'UmpuOyyoGqeRffvMbTx0Z3iIYr1i//qX3KRVhVA3RWDVo8jxVxiU5' +
'TVSIcLKkrP8ZDbIimkVuR7rmmzyPLICjNEPdqISZhqwZHdcyX3nzm' +
'3lUbHUCj+laO/ZXvPTS4vyLFMfU5LgbVug6Brgnp0+fpsoCx87aKi' +
'QsYEXTyHi2IPCUV+G333qTrN3kxDgNuicQVvnUyZNeZWjsOdDX4zV' +
'Lf1+Pp1VPnvzAq3BleTG5l4JVfa9/w64aAPJqcLgIzeE5Ettam7wW' +
'VVKUh3RMNeuo4KAzeI7E3Kx0KnmwA2rHz73VEIyPECtKC+H80KGDN' +
'JqWFhf6fkelGvu+j4tZ+/1WB7e2TzS2j1fXNhmSRVkaVnGKyCeeMg' +
'hTlWxPnsrRC35OnhI37CwZG5lqa5sCngrbuj7IT9F9V+e3vnjq37y' +
'm5XX73LKgtDQifvE7j6lyvdJzCiG+UtxHJeNjghK86riUp6TJtSy7' +
'2U3HUG8RjJfu3EtTCEDQWPWlI19RZQzObaZChL+vVQxRZVy8d5q+H' +
'VdkN68oG3BrRxojvzRylkGK5UJMV2Y1UQmvymvFWMsF6nk01oooFn' +
'4gxIhuPYemr3rtpYX52WcojqbGeq9Y8dHbPvroI6pcI8NDCJEVG04' +
'lU1dT6dmCPd2dXoX37dtD1q63p4uq2JqqCpqReOLEu15z0dizu6vD' +
'axa47mnVE+96L7+oIJfcS6nKhKO6qtyzBTevW+FVGOzs9W5js+i8y' +
'tfvrEY6mvRqqgps3bDK67igkn/dOc0L2lEJ+H5A2/l+R6Ua+76PCz' +
'JPhW1Z3969r6FtvLK6QS8XZKgT5sBTCoJrgIDS1dxfhqfsJuHOyvz' +
'x0T2dnfs6+/ZHhG1GhsI78Bmz3zULdoX7wM8ATNceFWQ6/O/Swr4X' +
'TvyL1/Ra6QAyexBpZhUhBnWepMr10sS1GYeluJ9Kxsf00oEvqXR88' +
'fgjqlzw00qBhqwj6hXIW5/pbxkNdLjHv6e36uIDX1LlZWQ1eUVE6d' +
'UiSmsvGzo7j3akMfLLA1846zCzOAt/X3HsphJemdNMRpxH2y2PTHR' +
'p/QTRs+d46kijXU1V+WcUR1VFKRXW4EA/VS54bEYyibERVDI1zhuy' +
'Wwt2drR5FZ6anCBr193Z7lXs8KGD9CPxrTff9JqRxp493R1es3R2t' +
'Hta9a23vJdfkJdF7qVUakL9vbYgLyHSqzzY0OvdJjEmzKt8dWUZKj' +
'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' +
'ncFv0VoYMCDQFhFmUM+2KzklBXl9I/t7x4/3jh7YyGTMGAq9xUxa4' +
'0NETzZjiCvyfPDsL9MFk9bvyG9JM1wuKi4QZwkgBhD9i7iwtQsgzg' +
'nRoFXS8NTC0PGpiGSegn/XrmFk5pXU7mqprao2KpPsOrFXniJ8K0U' +
'i2kpBbO2zSq3yOH7Mlpgd2+MiwtTcHanJ3ByTLD9FmWlWpBtkZgVP' +
'LYh65+0Pz1/7/vzV7y5Pf3/++venr3yt1Rh04oQcHVefxJHzYlWiB' +
'LNSBIxWmJIElAR8RMdTWna6iluQk9U7sr9v4vjA5LGQlUFkK4W6vh' +
'2JbYItw5jZ8ThjWGKriSsoIhLbsWEJkmE63zXDTxEMktuLTwKIAUS' +
'/Iy5s7QKIviPqNAoqntqxdd3C0PGpiG48tXHNioycktq65l01tRZN' +
'sk3r3Z+Ck9TkBLSVotAqy7XI1OIEESdxcHC0qbnDajIJONzEuDiJU' +
'CjhsfiJMcliPjs6rLq29drtv168/uj67Z/OXP3u1p//uay0QpoQlq' +
'vnGeTcZH5sEidKI2Vn6kX5zh0a6PUrKp7K1bJtCg7BU8P7e8aODk4' +
'd3xJKfNI32LX6howQ7Jw1xXtUmGg7ysym/Sev/8N5qOuLXWBSZB+3' +
'cpBJGaTdlUzXF1UCiAFEPyIubO0CiHNCpJn3A55aGDo+FdFtv9/Wt' +
'UH2jNzq2qb6nXVWndInnkqRZqWoOPGxFkvq3a9/mL7/+ML0N5+dv3' +
'Xg+Kn2/qny8qpkuYKVyF6zek1WXs114Klrj67ceHzzq389fOKMTKZ' +
'QcqPzjQJTMk8Qt12SGK5LYpll8cTLWWnJ4KkhSvLOUxpWWjIbeKpn' +
'6PXu0SNDe97Yvm0zHuZkrg+avfCHQs1jG2JrI5swseNJOglyzZ3O+' +
'LOuWL4zcAHEAKJfERe2dgHEOSHGRGyh4qltG4IXho5PRXTzp9atfE' +
'lnTKmsaWja3Zhm0qZphM7Q5SK7B0+lyOPtaiKgRCEQR6o6NjKstLT' +
'q5t0fzl57dP7OX8/e/PH87b9cvPu3m3cfXpn+8ovz0+NTh989dfHy' +
'zR/OX/tuaPLtlq4pY0pGbFRkuk6aqeUm8SLFnJgP3nnn6ME3lLyYb' +
'IOgOE1RlJqMvibsfd5Px0pTsLPSbT1De3vHjw7vfTMmKpxsEKZr2j' +
'OYtNEXG5Dp+n4KMi/+AjIugekKkIgKYcx+AIAr60NeDiXFYwwgBhD' +
'9hbiwtQsgBhDniujGU0Ev/qNCrS+rrG9pbnOkWawqQZ5JTITgU3NT' +
'ZPFknrLI4lMV7EyDqNAqz7Ym8Vjhu3bW37nz01vvXxvcd+L8zcdX7' +
'//18r2frt16fOn6t1duPJy+8/jqrcdnr/x5+t5fJg+ejI4XRYZtN6' +
'pkDoPEpuFwE7eUleR/+fVfPjr9QCsVp6vZRWmKQhJP4T3wiKeILRw' +
'Gtl3FtlmM3QOT/RPHRva9FRMVEeSaKWW6/FDgekT3QaRZUGxnJIOM' +
'A38JSReVY8ujF6WRuWa8Xee3VIiw86S52QBiANFfiAtbuwBiAHGui' +
'LN4yplFJJGWVtS1NrflOmypamEuBU+Zk+LQ56LyLUlZKUncxPC6nf' +
'Vfff1vVbW96zZszs4tfH3/4Q8//vyLC3dv3P3x8vS3l64/uDT98OL' +
'0wwvXic1+H3x8UcTnKyQCu1aUoedzEjZXlBV8/c1fL1z+KU2ntqtY' +
'T+cpPcumZNlTTF39E4inIiMjQ1wf6mLO3m2CuRuTPqb4YNfWfWwcs' +
'iTDNaeKLIkTfpwIIAYQ/Y64sLULIAYQ54rotj4FSSgUllbuam1uLc' +
'rJTNOIqHgKfevQGd5cmmmWJESHjo6MX7z0QCqBf8IlCRHcyC3ihMh' +
'4try1a+rUp9eu3nx48fp3Z68+uHLr8cXpR19/+88tjQ2xO7bYNYIs' +
'PV+TnBAbtb20rP7S1b9lmA02VeJTeSoPeErBAn+qs2+8f+Io8FRUV' +
'DRZX2Q9PJFCJn2Ga2c+CnJIfjDAZkQ8jk06I+O0Lf7KDBQSQAwg+h' +
'1xYWsXQAwgzhXRbd4PiuLxBaWV9a3N7WWFeTbMU5pZPJWqYAFPmZP' +
'i04moFFK9LFHAjf3i87MjY29s3RydJo8jZgsNIqssgcOT9w0eeOeD' +
'cxeu/vnC9W+v3PrhwvWH5699d+naNzdv3KosKRLG77BpxWoFb8M6p' +
'jzZdOb8dza9yq5KLH4aT+UaWGlKVppJ39U7PuD0p2LjYsleJDJIqG' +
'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' +
'Sffff/g8cveeFwp2YETdIBMyyzgn3dFjTbiEfoX6AxbqOuVBUxSq8' +
'DGZv9AhCAKYm6I5rZOEAUxS6Kh328zZYg7MpuXSdqxaV9FyeDw2JO' +
'X//7Vg5dTExPdbfZEl3060joatPd6W8Luuu7WqqCjqq+jjnRqoi+p' +
'U+AfwbcgVSFXbbS9CX6o0yl4ZdCpzsbldAoUKuiuD7hqeztb+gOui' +
'M919dLFp09fLN152Nbm3FOWdE5J8ensrWSjNtOv7qzyvyJf1cYN/+' +
'HZTk7/K4iCmAuiua0TREHMimjs91O4sNikrmkeXEnhlpLCrWUlOzu' +
'8nZ/fenzn7sPZM2cjPk+ftxlEJ9ap6hTIUNBZna5T3sGgE2QFdAe8' +
'rUBrznSqp63B76j22St72huGov7rn119+PDJN09+ig2M7Ksolj7ZJ' +
'LFokxqbBOcElzB+Axu34IQeVXvz8QTK3Awe8AJflX80gM4q7guiIP' +
'52ormtE0RBzJaYUadUvywvpY8Sk0jtq/cqSvJra2tmL167fefhlUs' +
'X4wFvv98BOtXjqQ86a+DF69RkrHMwpOmUC5ypnOlUtF0dwII0vpbD' +
'xwb8j+5++fzF64dPfgpEh+VdBdKOzeo5KUzafsC6VUkf2vt7Nv6OJ' +
'F7iel9t2uMAUrIxoD4jIHPhLoIoiLkimts6QRTEbIm8TsnauBhqIq' +
'VX0oM0cF+2fPTppwdHp059/fDZjS9uD0XDsQ57pL3R7zgccB3ubas' +
'd8DdPqBPMdkz2dQ6H3H3exrCrBnTK31oFQhZtbySdAm16Q50aDjn6' +
'g/Z4oKXP3xT0VDqbah3NjSOJ+FefLzx//uLu4xc98aFiuVAqAMM3g' +
'fky6+pHSxXmjb6hjXQ+ZcNqy5QgeTa0fARREHNFNLd1giiI2RJ1/p' +
'SFWw6YsgK/DNcZSXP0ij85YLMlJk/devqnm9e+HAkF/a76Ls8Rn+t' +
'QxF3d72sEcZmOe4/2ekdD7v7O5h7UKbs6ShVpa0j47WOaTqE8wQt3' +
'JqPJKdZVnXLXgMDhor3wUnWqpzXa3RjxN/jcnzY2tyZGjl26srh05' +
'/H1rx40ezqspbuU0gKlaCt4kXQqsM9T5kJTsrCR3TH4RgKdSWwqKM' +
'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' +
'NrH9hu3/AYupIPU=');

The Mayor

2014-01-19 19:47:21

I like this idea ;) I'm currently writing a SRL6 tutorial which demonstrates how to write a script step-by-step from scratch.


E: Actually I have a half finished burthorpe agility script that might come in useful. PM me if you want it

Brotein

2014-01-20 02:11:54

Getting our colors back in order. Still looking for a nice way to get the monkey bars with TPA, but the colors are all too common to the scene at the default viewing angle and zoomed as far out(will use DTM).

These are CTS2 colors and modifiers…
Format is: Color, Hue Mod, Sat Mod, HSL Tol

Log Color
[php]3356739, .7, .68, 5[/php]


Arrow Color
[php]11909057, .53, 1.69, 5[/php]


Balance Color
[php]4809844, .1, .2, 5[/php]


Shield Color
[php]10721175, 0.0, 0.12, 50[/php]


Rope Color
[php]206638, .11, .41, 10[/php]


Checker Color
[php]10666456, .03, .05, 40[/php]


Next will be updating the code for SRL6…

Wu-Tang Clan

2014-01-20 11:10:54

It seems like a lot of work for a script with such low xp gain? I would have done the gnome agility course instead of this personally, but it does look like the colors are easier and the there's no need for sps.
Very clean ACA color finding man… that's impressive.
EDIT: Maybe look for a better balance ledge color, the hay bales are closer than the ledge and have quite a few matches. Also a couple of other points have matches. Although if you increase the search area and specify the TPA/ATPA length above what the hay bale points are you should be good.

Brotein

2014-01-20 11:38:18

Don't worry about the balance, it is close to the other hay and rocks, but when I sort my TPAs and resize them, it only clicks on the one part of the ledge. In the game it's split into 3 segments, one you can click on, one you can't, and one that's out of reach. This color allows me to grab the TPA of the balance beam since it contains by far the most points, take the original bounds and make a mousebox that will only click on the first part.

This is from my vid, you can see that the balance will always be the first TPA sorted by points. The little purple box is the mousebox built from the TPA bounds. That was done with this line of code originally:
Mousebox(GetTPABounds(BalanceATPA[0]).X1, GetTPABounds(BalanceATPA[0]).Y1, GetTPABounds(BalanceATPA[0]).X1 + 25, GetTPABounds(BalanceATPA[0]).Y2 + 2, 2);

Brotein

2014-01-27 19:50:24

Thanks to some help along the way I got my color procedures all updated(mainly The Mayor for that list of SRL6 functions). I need to go back and fix 2 of the procedures(monkey and checker), since they aren't too unique right now ;) I am just rerunning my script calling a different procedure each time in this vid(that's why you hear me typing). It didn't break at the monkey bar the first time, I just couldn't type the procedure name lol.

[video=youtube_share;Es8cePpOxAg]http://youtu.be/Es8cePpOxAg[/video]

So here was my original procedure for checking for the log color at the start of the course.

OLD
procedure LogColor;
var
LogTPA:TPointArray;
LogATPA:T2DPointArray;
LogBox:TBox;
begin
SetColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.7, 0.68);
if findcolorstolerance(LogTPA, 3487805, MSX1, MSY1, MSX2, MSY2, 5) then
begin
LogATPA := SplitTPAEx(LogTPA, 30, 30);
SortATPASize(LogATPA, True);
LogBox := GetTPABounds(LogATPA[0]);
SMART_ClearCanvas;
SMART_DrawDotsEx(True, LogTPA, clYellow);
SMART_DrawBoxes(False, False ,[GetTPABounds(LogTPA)], clAqua);
SMART_DebugATPA(False,LogATPA);
Mousebox(GetTPABounds(LogATPA[0]).X1, GetTPABounds(LogATPA[0]).Y1, GetTPABounds(LogATPA[0]).X2, GetTPABounds(LogATPA[0]).Y2, 2);
SetColorToleranceSpeed(1);
SetColorSpeed2Modifiers(0.2, 0.2);
Wait(50 + random(25));
if(isUpText('og be'))then
begin
Wait(150 + random(50));
ClickMouse2(True);
WriteLn('Found Log!');
Wait(6200 + random(100));
if FindChatBoxText('lost', 8, clBlack) then
begin
Writeln('YOU FELL! Lets try again...');
wait(3000);
LogColor;
end;
obstacle := 1;
end;
end;
end;

NEW SRL6
procedure logColor;
var
x,y:Integer;
LogTPA:TPointArray;
LogATPA:T2DPointArray;
begin
if findColorsSpiralTolerance(x, y, LogTPA, 3356739, mainScreen.getBounds(), 5, colorSetting(2, 0.7, 0.68)) then
begin
LogATPA := LogTPA.toATPA(100, 100);
LogATPA.filterBetween(0, 100);
LogATPA.sortBySize(true);
smartImage.clear;
smartImage.debugTPA(LogTPA, true);
smartImage.debugATPA(LogATPA);
mouse(middleTPA(LogATPA[0]), MOUSE_MOVE);
wait(50 + random(25));
if isMouseOverText(['og be']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Log!');
smartImage.clear;
wait(6200 + random(100));
if chatbox.findAnyText(['lost']) then
begin
writeln('YOU FELL! Lets try again...');
wait(3000);
logColor;
end;
obstacle := 1;
end;
end;
end;


-So SRL6 has some niftier functions so I no longer need to set CTS tolerances since I do that inside of findColorsSpiralTolerance().
-Same concept as original, removed the TBox since it was dead code last time forgot to remove it after testing the paint boxes for MMouse.
-Next fill the TPA, split it into 100(needed bigger since the camera angle is different from original).
-Then I filter out the stray stuff that appears in the background.
-Then I sort by size. There are some shades that appear in the second TPA[1] but it's size is nearly 10% of TPA[0] which is our log, which will always appear as TPA[0].
-There are the debug procedures in there which will draw dots for all TPoints and do the normal ATPA debug.
-Then the mouse moves to the middle of out TPA[0], looks for the text 'og be' as part of 'Log beam', clicks it if true, waits and checks for text 'fell' in chatbox incase you slip(occurs levels lower than 5 I think). Last updates the obstacle to 1 for my doTheCourse procedure.

Next I'm going to throw it back together and work on the wait times, and then add in some failsafes or just measures for seeing if we actually completed an obstacle rather than just assuming we did when we click(check for xp perhaps).

The Mayor

2014-01-27 22:31:45

I would have made the compass east for the rope, but looking good :)

Wu-Tang Clan

2014-01-28 13:07:09

From: Brotein
Thanks to some help along the way I got my color procedures all updated(mainly The Mayor for that list of SRL6 functions). I need to go back and fix 2 of the procedures(monkey and checker), since they aren't too unique right now ;) I am just rerunning my script calling a different procedure each time in this vid(that's why you hear me typing). It didn't break at the monkey bar the first time, I just couldn't type the procedure name lol.

[video=youtube_share;Es8cePpOxAg]http://youtu.be/Es8cePpOxAg[/video]

So here was my original procedure for checking for the log color at the start of the course.

OLD
procedure LogColor;
var
LogTPA:TPointArray;
LogATPA:T2DPointArray;
LogBox:TBox;
begin
SetColorToleranceSpeed(2);
SetColorSpeed2Modifiers(0.7, 0.68);
if findcolorstolerance(LogTPA, 3487805, MSX1, MSY1, MSX2, MSY2, 5) then
begin
LogATPA := SplitTPAEx(LogTPA, 30, 30);
SortATPASize(LogATPA, True);
LogBox := GetTPABounds(LogATPA[0]);
SMART_ClearCanvas;
SMART_DrawDotsEx(True, LogTPA, clYellow);
SMART_DrawBoxes(False, False ,[GetTPABounds(LogTPA)], clAqua);
SMART_DebugATPA(False,LogATPA);
Mousebox(GetTPABounds(LogATPA[0]).X1, GetTPABounds(LogATPA[0]).Y1, GetTPABounds(LogATPA[0]).X2, GetTPABounds(LogATPA[0]).Y2, 2);
SetColorToleranceSpeed(1);
SetColorSpeed2Modifiers(0.2, 0.2);
Wait(50 + random(25));
if(isUpText('og be'))then
begin
Wait(150 + random(50));
ClickMouse2(True);
WriteLn('Found Log!');
Wait(6200 + random(100));
if FindChatBoxText('lost', 8, clBlack) then
begin
Writeln('YOU FELL! Lets try again...');
wait(3000);
LogColor;
end;
obstacle := 1;
end;
end;
end;

NEW SRL6
procedure logColor;
var
x,y:Integer;
LogTPA:TPointArray;
LogATPA:T2DPointArray;
begin
if findColorsSpiralTolerance(x, y, LogTPA, 3356739, mainScreen.getBounds(), 5, colorSetting(2, 0.7, 0.68)) then
begin
LogATPA := LogTPA.toATPA(100, 100);
LogATPA.filterBetween(0, 100);
LogATPA.sortBySize(true);
smartImage.clear;
smartImage.debugTPA(LogTPA, true);
smartImage.debugATPA(LogATPA);
mouse(middleTPA(LogATPA[0]), MOUSE_MOVE);
wait(50 + random(25));
if isMouseOverText(['og be']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Log!');
smartImage.clear;
wait(6200 + random(100));
if chatbox.findAnyText(['lost']) then
begin
writeln('YOU FELL! Lets try again...');
wait(3000);
logColor;
end;
obstacle := 1;
end;
end;
end;


-So SRL6 has some niftier functions so I no longer need to set CTS tolerances since I do that inside of findColorsSpiralTolerance().
-Same concept as original, removed the TBox since it was dead code last time forgot to remove it after testing the paint boxes for MMouse.
-Next fill the TPA, split it into 100(needed bigger since the camera angle is different from original).
-Then I filter out the stray stuff that appears in the background.
-Then I sort by size. There are some shades that appear in the second TPA[1] but it's size is nearly 10% of TPA[0] which is our log, which will always appear as TPA[0].
-There are the debug procedures in there which will draw dots for all TPoints and do the normal ATPA debug.
-Then the mouse moves to the middle of out TPA[0], looks for the text 'og be' as part of 'Log beam', clicks it if true, waits and checks for text 'fell' in chatbox incase you slip(occurs levels lower than 5 I think). Last updates the obstacle to 1 for my doTheCourse procedure.

Next I'm going to throw it back together and work on the wait times, and then add in some failsafes or just measures for seeing if we actually completed an obstacle rather than just assuming we did when we click(check for xp perhaps).


best part of the video is when it freezes and your like
"What the F***, Wu-Tang forever"

footballjds

2014-01-28 13:20:17

do you have a location function that returns your current location?

Brotein

2014-01-30 20:57:33

Well I had an interesting find. In an attempt to create a new account to check the failed obstacles at those low levels(lower than 4 I am still guessing), I saw that there is camera lag created if you don't verify your email address. The lag caused long transitions in camera panning and movement that, but once you register the email the camera movements become instantaneous. Just a heads up to anyone testing with new accounts, REGISTER YOUR EMAIL!

So here's the current working script… (still a WIP so ignore anything wrong like the comments for colors not matching)
program BroteinBurthrope;

{$DEFINE SMART}
{$I SRL-6/SRL.simba}
{$I SPS/lib/SPS-RS3.Simba}

////////////////////////////////////////////////////////////////////////////////
// Read Me!!! //
// http://www.youtube.com/watch?v=Tu8qY__oAM8 //
////////////////////////////////////////////////////////////////////////////////
// - Start this script at the beginning of the course in Burthrope. No food //
// is needed for this course. Average xp/hr is ~8,000. //
////////////////////////////////////////////////////////////////////////////////

var
x, y, obstacle, XpCount, LapTotal, XpHour, StartTime, SecondS: Integer;
const
ScriptVersion = '1.40';
UseAutoChecker = false;

////////////////////////////////////////////////////////////////////////////////
// Set up your Character info here!!! //
////////////////////////////////////////////////////////////////////////////////
procedure declarePlayers;
begin
setLength(players, 1);
with players[0] do
begin
loginName := '';
password := '';
isActive := true;
isMember := false;
end
currentPlayer := 0;
end;

////////////////////////////////////////////////////////////////////////////////
// Script starts here //
////////////////////////////////////////////////////////////////////////////////

// * Procedure autoUpdateMe by Harry and Shuttleu
// * Auto-Downloads the newest version of the script when run.
procedure autoUpdateMe;
var Neifile:integer;
OnlineVersion, NewScript, NeiFeilNennen:string;
begin
if UseAutoChecker then
begin
writeln('Checking for latest version...');
OnlineVersion := getPage('http://broscripts.googlecode.com/svn/trunk/Agility/BroAgile-Version.txt');
writeln(OnlineVersion);
writeln(ScriptVersion)
if (trim(OnlineVersion) > ScriptVersion) then
begin
writeln('Newer Version Found!');
writeln('Autoupdating to newer version...');
NewScript := getPage('http://broscripts.googlecode.com/svn/trunk/Agility/BroAgile-Current.simba');
NeiFeilNennen := ScriptPath + 'BroAgile_Burthrope_v' + OnlineVersion + '.simba';
Neifile := Rewritefile(NeiFeilNennen, true);
try
writeFileString(Neifile, NewScript);
except
begin
writeln('Fatal error writing to ' + NeiFeilNennen + '!!');
terminatescript;
end;
end;
closeFile(Neifile);
writeln('New script downloaded to ' + NeiFeilNennen + '!! Please use this one!!');
terminateScript;
end else
writeln('You have the latest version of the script!');
end else
writeln('!!!!! Not checking for latest version, you may be outdated!');
end;

// * Procedure antiBan
// * Will frequent the agility skill icon in the skills tab. Will also do
// random mouse movements and screen rotation.
// # These should be non-disruptive, but if they are please report them.
procedure antiBan;
begin
if not isLoggedIn then
Exit;
case Random(4)of
0: begin
pickUpMouse();
writeLn('Performed pickUpMouse() AntiBan');
end;
1: begin
randomRClickItem();
writeLn('Performed randomRClickItem() AntiBan');
end;
2: begin
hoverSkill(4);
writeLn('Performed pickUpMouse() AntiBan');
end;
3: begin
smallRandomMouse();
writeLn('Performed pickUpMouse() AntiBan');
end;
end;
end;

// * Procedure logColor
// * Creates TPA for Log Balance obstacle.
// * Sets camera to high North(0), searches for TPA "LogTPA", and clicks on
// random area of the log.
// * Increments course completion to (1/6).
// # Color: 3356739, Hue: 0.7, Sat: 0.68, CTS: 2, Tol: 5
procedure logColor;
var
x,y:Integer;
LogTPA:TPointArray;
LogATPA:T2DPointArray;
begin
if findColorsSpiralTolerance(x, y, LogTPA, 3356739, mainScreen.getBounds(), 5, colorSetting(2, 0.7, 0.68)) then
begin
LogATPA := LogTPA.toATPA(100, 100);
LogATPA.filterBetween(0, 100);
LogATPA.sortBySize(true);
smartImage.clear;
smartImage.debugTPA(LogTPA, true);
smartImage.debugATPA(LogATPA);
mouse(middleTPA(LogATPA[0]), MOUSE_MOVE);
wait(50 + random(25));
if isMouseOverText(['og be']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Log!');
smartImage.clear;
wait(6200 + random(100));
if chatbox.findTextOnLines(['lost'], [0]) then
begin
writeln('YOU FELL! Lets try again...');
wait(3000);
logColor;
end;
obstacle := 1;
end;
end;
end;

// * Procedure wallColor
// * Creates TPA for Wall obstacle.
// * Searches for TPA "WallTPA", and clicks on the arrow/wall.
// * Sets camera to high South during obstacle, for preperation of balance.
// * Increments course completion to (2/6).
// # Color: 11909057, Hue: 0.53, Sat: 1.69, CTS: 2, Tol: 5
procedure wallColor;
var
x,y:Integer;
WallTPA:TPointArray;
WallATPA:T2DPointArray;
begin
if findColorsSpiralTolerance(x, y, WallTPA, 11909057, mainScreen.getBounds(), 5, colorSetting(2, 0.53, 1.69)) then
begin
WallATPA := WallTPA.toATPA(30, 30);
WallATPA.filterBetween(0, 10);
WallATPA.sortBySize(true);
smartImage.clear;
smartImage.debugTPA(WallTPA, true);
smartImage.debugATPA(WallATPA);
mouse(middleTPA(WallATPA[0]), MOUSE_MOVE);
wait(50 + random(25));
if isMouseOverText(['limb']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found ladder!');
smartImage.clear;
minimap.setAngle(MM_DIRECTION_SOUTH);
wait(6000 + random(100));
obstacle := 2;
end;
end;
end;

// * Procedure balanceColor
// * Creates and Searches TPA for Balance Beam obstacle and clicks on random
// area of ATPA[0] after boundries have been modified to click the cloest
// part of the plank.This is done because the 2nd partition has no action,
// and the third is "out of reach".
// * Sets camera high East during balance, for preperation of shields.
// * Increments course completion to (3/6).
// # Color: 5270653, Hue: 0.1, Sat: 0.05, CTS: 2, Tol: 5
procedure balanceColor;
var
x,y:Integer;
BalanceTPA:TPointArray;
BalanceATPA:T2DPointArray;
begin
if findColorsSpiralTolerance(x, y, BalanceTPA, 5139324, mainScreen.getBounds(), 2, colorSetting(2, 0.37, 0.42)) then
begin
BalanceATPA := BalanceTPA.toATPA(30, 15);
BalanceATPA.filterBetween(0,25);
BalanceATPA.sortFromMidPoint(mainscreen.playerPoint);
smartImage.clear;
smartImage.debugTPA(BalanceTPA, true);
smartImage.debugATPA(BalanceATPA);
mouse(middleTPA(BalanceATPA[0]), MOUSE_MOVE);
wait(150 + random(25));
if isMouseOverText(['alanc']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Balance!');
smartImage.clear;
wait(150 + random(50));
minimap.setAngle(MM_DIRECTION_WEST);
Wait(5000 + random(100));
obstacle := 3;
end;
end;
end;

// * Procedure shieldColor
// * Creates TPA for Shield obstacle.
// * Searches for TPA "ShieldTPA", and clicks on lower shield.
// * Sets camera to high South during obstacle, in preperation of rope.
// * Increments course completion to (4/6).
// # Color: 10721175, Hue: 0.0, Sat: 0.12, CTS: 2, Tol: 50
procedure shieldColor;
var
x,y:Integer;
ShieldTPA:TPointArray;
ShieldATPA:T2DPointArray;
begin
if findColorsSpiralTolerance(x, y, ShieldTPA, 10721175, mainScreen.getBounds(), 50, colorSetting(2, 0.0, 0.12)) then
begin
ShieldATPA := ShieldTPA.toATPA(80, 25);
ShieldATPA.filterBetween(0, 100);
ShieldATPA.sortBySize(true);
smartImage.clear;
smartImage.debugTPA(ShieldTPA, true);
smartImage.debugATPA(ShieldATPA);
mouse(middleTPA(ShieldATPA[0]), MOUSE_MOVE);
wait(50 + random(25));
if isMouseOverText(['limb']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Shields!');
smartImage.clear;
wait(150 + random(50));
minimap.setAngle(MM_DIRECTION_SOUTH);
Wait(5250 + random(100));
if chatbox.findTextOnLines(['footing'], [0]) then
begin
writeln('YOU FELL! Lets try again');
wait(3000);
minimap.setAngle(MM_DIRECTION_WEST);
shieldColor;
end;
obstacle := 4;
end;
end;
end;

// * Procedure ropeColor
// * Creates TPA for Rope Swing obstacle.
// * Searches for TPA "RopeTPA", and clicks on rope.
// * Increments course completion to (5/6).
// # Color: 206638, Hue: 0.11, Sat: 0.41, CTS: 2, Tol: 10
procedure ropeColor;
var
x,y:Integer;
RopeTPA:TPointArray;
RopeATPA:T2DPointArray;
begin
if findColorsSpiralTolerance(x, y, RopeTPA, 206638, mainScreen.getBounds(), 10, colorSetting(2, 0.11, 0.41)) then
begin
RopeATPA := RopeTPA.toATPA(75, 75);
RopeATPA.filterBetween(0, 10);
RopeATPA.sortBySize(true);
smartImage.clear;
smartImage.debugTPA(RopeTPA, true);
smartImage.debugATPA(RopeATPA);
mouse(middleTPA(RopeATPA[0]), MOUSE_MOVE);
wait(150 + random(25));
if isMouseOverText(['wing']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Rope!');
smartImage.clear;
minimap.clickCompass();
wait(3250 + random(100));
obstacle := 5;
end;
end;
end;

// * Procedure monkeyColor
// * Creates TPA for Monkey Bars obstacle.
// * Searches for TPA "MonkeyTPA", and clicks on rope.
// * Increments course completion to (6/6).
// # Color: 11061726, Hue: 0.1, Sat: 5.13, CTS: 2, Tol: 15
procedure monkeyColor;
var
x,y:Integer;
MonkeyTPA:TPointArray;
MonkeyATPA:T2DPointArray;
begin
if findColorsSpiralTolerance(x, y, MonkeyTPA, 11061726, mainScreen.getBounds(), 15, colorSetting(2, 0.1, 5.13)) then
begin
MonkeyATPA := MonkeyTPA.toATPA(10,10);
MonkeyATPA.filterBetween(0,30);
MonkeyATPA.sortFromMidPoint(mainscreen.playerPoint);
smartImage.clear;
smartImage.debugTPA(MonkeyTPA, true);
smartImage.debugATPA(MonkeyATPA);
mouse(middleTPA(MonkeyATPA[0]), MOUSE_MOVE);
wait(300 + random(50));
if isMouseOverText(['ing']) then
begin
wait(450 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Monkey Bars!');
smartImage.clear;
Wait(8000 + random(250));
obstacle := 6;
end;
end;
end;

// * Procedure checkerColor
// * Creates TPA for Checker obstacle and clicks on random area of ATPA[0].
// * Updates progress report information.
// * Resets course completion to (0/6).
// # Color: 4883624, Hue: 0.03, Sat: 0.19, CTS: 2, Tol: 45
procedure checkerColor;
var
x,y:Integer;
CheckerTPA:TPointArray;
CheckerATPA:T2DPointArray;
begin
if findColorsSpiralTolerance(x, y, CheckerTPA, 10996447, mainScreen.getBounds(), 5, colorSetting(2, 0.20, 2.47)) then
begin
CheckerATPA := CheckerTPA.toATPA(80,20);
CheckerATPA.filterBetween(0,40);
CheckerATPA.sortFromMidPoint(mainscreen.playerPoint);
smartImage.clear;
smartImage.debugTPA(CheckerTPA, true);
smartImage.debugATPA(CheckerATPA);
mouse(middleTPA(CheckerATPA[0]), MOUSE_MOVE);
wait(300 + random(50));
if isMouseOverText(['ump']) then
begin
wait(200 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Checkers!');
smartImage.clear;
Wait(2000 + random(150));
obstacle := 0;
end;
end;
end;

// * Procedure doTheCourse
// * Base case is off integer "obstacle" for course completion porgress.
// * If base case is met, will search for DTM/TPA of case, and execute the
// procedure of the selected case.
// * Will print status of "Looking..." or "Found" when executed.
// # This is prevent searching for DTMs that are all present on the screen, and
// will only search for the one based off progress.
// # (Case/Procedure) - (0/Log), (1/Ladder), (2/Balance), (3/Shields),
// (4/Rope), (5/Monkey), (6/Checker).
procedure doTheCourse;
var
x, y: integer;
obstacleTimer: TTimeMarker;
begin
if obstacle = 0 then
begin
writeLn('Looking For Log...');
obstacleTimer.start;
repeat
logColor;
wait(100);
if obstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding log, stopping script!');
players[currentPlayer].logout();
terminateScript;
end;
until(obstacle = 1);
end;

if obstacle = 1 then
begin
writeLn('Looking For Ladder...');
obstacleTimer.start;
repeat
wallColor;
wait(100);
if obstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Wall, stopping script!');
players[currentPlayer].logout();
terminateScript;
end;
until(obstacle = 2);
end;

if obstacle = 2 then
begin
writeLn('Looking For Balance...');
obstacleTimer.start;
repeat
balanceColor;
wait(100);
if obstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Balance, stopping script!');
players[currentPlayer].logout();
terminateScript;
end;
until(obstacle = 3);
end;

if obstacle = 3 then
begin
writeLn('Looking For Shields...');
obstacleTimer.start;
repeat
shieldColor;
wait(100);
if obstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Shields, stopping script!');
players[currentPlayer].logout();
terminateScript;
end;
until(obstacle = 4);
end;

if obstacle = 4 then
begin
writeLn('Looking For Rope...');
obstacleTimer.start;
repeat
ropeColor;
wait(100);
if obstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Rope, stopping script!');
players[currentPlayer].logout();
terminateScript;
end;
until(obstacle = 5);
end;

if obstacle = 5 then
begin
writeLn('Looking For Monkey...');
obstacleTimer.start;
repeat
monkeyColor;
wait(100);
if obstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Monkey, stopping script!');
players[currentPlayer].logout();
terminateScript;
end;
until(obstacle = 6);
end;

if obstacle = 6 then
begin
writeLn('Looking For Checker...');
obstacleTimer.start;
repeat
checkerColor;
wait(100);
if obstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Checker, stopping script!');
players[currentPlayer].logout();
terminateScript;
end;
until(obstacle = 0);
incEx(LapTotal, 1);
XpCount := LapTotal * 79;
end;
end;

procedure ProgressReport;
begin
SecondS := round((getTimeRunning/1000));
XpHour := round((3600*XpCount) / (SecondS));
writeln('*************Progress Report***************');
writeln(timeRunning);
writeln('Laps Completed: ' + intToStr(LapTotal));
writeln('Xp Gained: ' + intToStr(XpCount));
writeln('Xp per Hour: ' + intToStr(XpHour));
writeln('*******************************************');
end;

// * Procedure Main
// * Sets up client and players.
// * Sets camera to high North, and sets our DTMs, and will free them when the
// script is finished.
// * Sets course completion to (0/6).
begin
autoUpdateMe;
clearDebug();
smartEnableDrawing := true;
setupSRL;
declarePlayers;
obstacle := 0;
repeat
if not isLoggedIn then
begin
players[currentPlayer].login();
exitSquealOfFortune();
minimap.clickCompass();
end;
doTheCourse;
antiBan;
progressReport;
until(false);
end.

And a print out of one lap's worth of logs…

Looking For Log...
-- isMouseOverText()
---- Current mouse-over text: "Walk Log beam"
---- Found "og be" in mouse-over string: "Walk Log beam"
-- isMouseOverText(): True
Found Log!
Looking For Ladder...
-- isMouseOverText()
---- Current mouse-over text: "Climb-up Wall"
---- Found "limb" in mouse-over string: "Climb-up Wall"
-- isMouseOverText(): True
Found ladder!
---- minimap.setAngle(): Set the angle @ 175.601294645004 degrees
Looking For Balance...
-- isMouseOverText()
---- Current mouse-over text: "Walk-across Balancing ledge"
---- Found "alanc" in mouse-over string: "Walk-across Balancing ledge"
-- isMouseOverText(): True
Found Balance!
---- minimap.setAngle(): Set the angle @ 270 degrees
Looking For Shields...
-- isMouseOverText()
---- Current mouse-over text: "Climb-over Obstacle low wall"
---- Found "limb" in mouse-over string: "Climb-over Obstacle low wall"
-- isMouseOverText(): True
Found Shields!
---- minimap.setAngle(): Set the angle @ 184.398705354996 degrees
Looking For Rope...
-- isMouseOverText()
---- Current mouse-over text: "Swing-on Rope swing"
---- Found "wing" in mouse-over string: "Swing-on Rope swing"
-- isMouseOverText(): True
Found Rope!
-- chooseOption._select():
---- chooseOption.isOpen(): result = true
---- Options found: [Face NoMh, Cancel]
---- Found option "Face" in "Face NoMh"
-- chooseOption.select() result = true
---- TRSMinimap.clickCompass(): Clicked compass
Looking For Monkey...
-- isMouseOverText()
---- Current mouse-over text: "Swing-across Monkey bars"
---- Found "ing" in mouse-over string: "Swing-across Monkey bars"
-- isMouseOverText(): True
Found Monkey Bars!
Looking For Checker...
-- isMouseOverText()
---- Current mouse-over text: "Jump-down Ledge"
---- Found "ump" in mouse-over string: "Jump-down Ledge"
-- isMouseOverText(): True
Found Checkers!
Performed pickUpMouse() AntiBan
*************Progress Report***************
10 Minutes and 35 Seconds
Laps Completed: 13
Xp Gained: 1027
Xp per Hour: 5822
*******************************************

So it's running nice and stable, no misclicks, no bad lag issues. Next step I think is to eliminate the wait times for obstacles by checking for XP gains instead to determine if we passed our current obstacle. Then I will implement some more failsafes including teleporting back if the script ever gets stuck(Mayor for the tip on that one). And whatever else I can do to speed up the script and make it more stable. Then I can adapt it to other courses :) Stay tuned!

Brotein

2014-01-31 02:23:20

Here's a video showing the core script working. I added in some procedures for getting to the course using SPS that aren't in my previous post.
[video=youtube_share;9vxEohKpDSQ]http://youtu.be/9vxEohKpDSQ[/video]

So now I think I'm going to remove all the wait times, and replace it with a proper check for completing an obstacle. Since no text appears when you complete anything, the only ways to check if we completed anything are the following(well what I could think of).
1: Assume we didn't misclick and just wait :)
2: Check our position(might not be accurate)
3: Check for xp gain in agility

I think option 3 would be the best. I plan to check like this

get xp from chatbox at script start, store in OldXp
check for xp in chatbox after TPA and mouseOverText, store in NewXp
if NewXp > OldXp
advance obstacle state
else
retry current procedure

As an extra failsafe I will have a quit procedure to prevent too many retrys.

when a procedure fails to return any color, teleport back to start of course
increment FailCount
if FailCount > 3
logout

I think that would cover most issues that the script could run into. Some wait times will remain just to cover lag after an obstacle(camera). Will post back once I get that working.

Brotein

2014-02-01 18:27:55

Updated!

Implemented Ashaman88's getXP function to check if an obstacle has actually been completed. This removed my infinite loop if you ever failed an obstacle(log or shield) and added a fool proof fail safe to all the procedures, so that the state will not update unless there is a change in xp.

Other failsafes now include retrying an obstacle for 30 seconds, and increment a failcount when that time is exceeded. When it does so, it teleports and runs back to the start to begin again and will cut off when there are too many fails(set by user).

Added some other fixes here and there, along with some options to disable all the clutter in the debug. Going to add in the on screen progress report and probably call this one done.


program BroteinBurthrope;

{$DEFINE SMART}
{$I SRL-6/SRL.simba}
{$I SPS/lib/SPS-RS3.Simba}
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////--Burthrope Agility--//////////////////////////
///////////////////////////////////--By: Brotein--//////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Read Me!!! //
// http://www.youtube.com/watch?v=Tu8qY__oAM8 //
////////////////////////////////////////////////////////////////////////////////
// - Start this script at the beginning of the course in Burthrope. No food //
// is needed for this course. Average xp/hr is ~6,000. //
// //
// - Fill in the constants below this along with your chracter info //
// //
// - Have SRL bot settings already done, CHANGE CAMERA TO CLASSIC, which can //
// be found in the controls menu and move your XP counter into your chat //
// box(top right) with atleast 100 xp already on the counter. //
////////////////////////////////////////////////////////////////////////////////

var
x, y, TimesFailed, StartXp, NewXp, Obstacle, XpCount, LapTotal, XpHour, StartTime, SecondS: Integer;

////////////////////////////////////////////////////////////////////////////////
// Change Constants Here //
////////////////////////////////////////////////////////////////////////////////
const
USEANTIBAN = true; //Enable of disable Anti-Ban (true/false)
TIMESTOFAIL = 5; //Maximum times the script can fail before logging out
DEBUGSCRIPT = false; //Enable if you are having issues running script

////////////////////////////////////////////////////////////////////////////////
// Don't Touch These!!! //
////////////////////////////////////////////////////////////////////////////////
USEAUTOCHECKER = false;
SCRIPTVERSION = '1.40';

////////////////////////////////////////////////////////////////////////////////
// Set up your Character info here!!! //
////////////////////////////////////////////////////////////////////////////////
procedure declarePlayers;
begin
setLength(players, 1);
with players[0] do
begin
loginName := '';
//loginName := '';
//loginName := '';
password := '';
isActive := true;
isMember := false;
end
currentPlayer := 0;
end;

////////////////////////////////////////////////////////////////////////////////
// Script starts herem, enjoy! //
////////////////////////////////////////////////////////////////////////////////

// * Procedure autoUpdateMe by Harry and Shuttleu
// * Auto-Downloads the newest version of the script when run.
procedure autoUpdateMe;
var Neifile:integer;
OnlineVersion, NewScript, NeiFeilNennen:string;
begin
if USEAUTOCHECKER then
begin
writeln('Checking for latest version...');
OnlineVersion := getPage('http://broscripts.googlecode.com/svn/trunk/Agility/BroAgile-Version.txt');
writeln(OnlineVersion);
writeln(SCRIPTVERSION)
if (trim(OnlineVersion) > SCRIPTVERSION) then
begin
writeln('Newer Version Found!');
writeln('Autoupdating to newer version...');
NewScript := getPage('http://broscripts.googlecode.com/svn/trunk/Agility/BroAgile-Current.simba');
NeiFeilNennen := ScriptPath + 'BroAgile_Burthrope_v' + OnlineVersion + '.simba';
Neifile := Rewritefile(NeiFeilNennen, true);
try
writeFileString(Neifile, NewScript);
except
begin
writeln('Fatal error writing to ' + NeiFeilNennen + '!!');
terminatescript;
end;
end;
closeFile(Neifile);
writeln('New script downloaded to ' + NeiFeilNennen + '!! Please use this one!!');
terminateScript;
end else
writeln('You have the latest version of the script!');
end else
writeln('!!!!! Not checking for latest version, you may be outdated!');
end;

// * Procedure antiBan
// * Will frequent the agility skill icon in the skills tab. Will also do
// random mouse movements and screen rotation.
// # These should be non-disruptive, but if they are please report them.
procedure antiBan;
begin
if not isLoggedIn then
Exit;
case Random(2000)of
0..40: begin
pickUpMouse();
writeLn('Performed pickUpMouse() AntiBan');
end;
41..50: begin
randomRClickItem();
writeLn('Performed randomRClickItem() AntiBan');
end;
51..60: begin
hoverSkill(4);
writeLn('Performed hoverSkill() AntiBan');
end;
61..99: begin
smallRandomMouse();
writeLn('Performed smallRandomMouse() AntiBan');
end;
100..199: begin
wait(random(1000));
writeLn('Perfomed wait AntiBan');
end;
end;
end;

// * Procedure getXP by Ashaman88
// * Gets XP in current xp counter on chat box.
function TRSChatBox.getXP: Integer;
var
b : TBox;
s : String;
tpa : TPointArray;
atpa : T2DPointArray;
i,cts,p : Integer;
begin
b := self.getBounds();
b.edit( +(b.x2 - b.x1) - 140, +10, -5, -94);

findColorsTolerance(tpa, 14013909, b, 4, colorSetting(2, 0.00, 0.00));

if length(tpa) < 2 then
begin
print('chatBox.getXP(): No XP found', TDebug.SUB);
Exit;
end;

atpa := tpa.cluster(10);
atpa.sortFromFirstPoint(point(b.x2, b.y2));

b := atpa[low(atpa)].getbounds;
b.edit(-2, -2, +2, +3);

s := Replace(tesseractgettext(b.x1, b.y1, b.x2, b.y2, FILTER_SMALL_CHARS), ' ', '', [rfReplaceAll]);

P := Pos('x', S);
if P > 0 then
Result := StrToIntDef(ExtractFromStr(Copy(s, P, Length(S)), Numbers), 0)
else
Result := StrToIntDef(ExtractFromStr(S, Numbers), 0);

print('chatBox.getXP(): XP found: ' + tostr(result), TDebug.SUB);
end;

// * Procedure takeScreen by Olly
// * Saves a screenshot and blurs out info, safe for upload
procedure takeScreen(reason: string);

procedure blur(bmp, xs, ys, xe, ye: integer);
var
bmpCopy, tmp: integer;
begin
bmpCopy := copyBitmap(bmp);
cropBitmap(bmpCopy, xs, ys, xe, ye);

tmp := convoluteBitmap(bmpCopy, gaussMatrix(6, 3.00));
fastDrawTransparent(xs, ys, tmp, bmp);
freeBitmaps([bmpCopy, tmp]);
end;

var
bmpClient, w, h, i: integer;
areas: TBoxArray;
begin
getClientDimensions(w, h);
bmpClient := bitmapFromClient(0, 0, w-1, h-1);

areas := [[actionBar.x1, actionbar.y1, chatBox.x2, chatBox.y2], mainScreen.playerBox,
[tabBackpack.x1-4, tabBackpack.y2 - 40, tabBackpack.x2, tabBackpack.y2],
[mainScreen.x2 - 130, mainScreen.y1, mainScreen.x2, mainScreen.y1 + 75]];

for i := 0 to high(areas) do
blur(bmpClient, areas[i].x1, areas[i].y1, areas[i].x2, areas[i].y2);

getMufasaBitmap(bmpClient).drawClippedText('Reason: ' + reason, point(chatBox.x1 + 5, chatBox.y2 - 16), StatChars, true, clLime);

debugBitmap(bmpClient);
freeBitmap(bmpClient);
end;

// * Procedure logColor
// * Creates TPA for Log Balance Obstacle.
// * Sets camera to high North(0), searches for TPA "LogTPA", and clicks on
// random area of the log.
// * Increments course completion to (1/6).
// # Color: 3356739, Hue: 0.7, Sat: 0.68, CTS: 2, Tol: 5
procedure logColor;
var
x, y : Integer;
LogTPA : TPointArray;
LogATPA : T2DPointArray;
begin
StartXp := chatbox.getxp;
if findColorsSpiralTolerance(x, y, LogTPA, 3356739, mainScreen.getBounds(), 5, colorSetting(2, 0.7, 0.68)) then
begin
LogATPA := LogTPA.toATPA(100, 100);
LogATPA.filterBetween(0, 100);
LogATPA.sortBySize(true);
if DEBUGSCRIPT then
begin
smartImage.clear;
smartImage.debugTPA(LogTPA, true);
smartImage.debugATPA(LogATPA);
end;
mouse(middleTPA(LogATPA[0]), MOUSE_MOVE, MOUSE_HUMAN);
wait(50 + random(25));
if isMouseOverText(['og be']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Log!');
if DEBUGSCRIPT then
smartImage.clear;
if USEANTIBAN then
antiBan;
wait(6200 + random(100));
NewXp := chatbox.getxp;
if NewXp > StartXp then
Obstacle := 1;
if not NewXp > StartXp then
begin
if chatbox.findTextOnLines(['lost'], [0]) then
begin
writeln('YOU FELL! Lets try again...');
wait(5000);
logColor;
end;
end;
end;
end;
end;

// * Procedure wallColor
// * Creates TPA for Wall Obstacle.
// * Searches for TPA "WallTPA", and clicks on the arrow/wall.
// * Sets camera to high South during Obstacle, for preperation of balance.
// * Increments course completion to (2/6).
// # Color: 11843521, Hue: 2.53, Sat: 2.69, CTS: 2, Tol: 5
procedure wallColor;
var
x, y : Integer;
WallTPA : TPointArray;
WallATPA : T2DPointArray;
begin
StartXp := chatbox.getxp;
if findColorsSpiralTolerance(x, y, WallTPA, 11843521, mainScreen.getBounds(), 5, colorSetting(2, 2.53, 2.69)) then
begin
WallATPA := WallTPA.toATPA(30, 30);
WallATPA.filterBetween(0, 10);
WallATPA.sortBySize(true);
if DEBUGSCRIPT then
begin
smartImage.clear;
smartImage.debugTPA(WallTPA, true);
smartImage.debugATPA(WallATPA);
end;
mouse(middleTPA(WallATPA[0]), MOUSE_MOVE, MOUSE_HUMAN);
wait(50 + random(25));
if isMouseOverText(['limb']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found ladder!');
if DEBUGSCRIPT then
smartImage.clear;
minimap.setAngle(MM_DIRECTION_SOUTH);
if USEANTIBAN then
antiBan;
wait(6500 + random(100));
NewXp := chatbox.getxp;
if NewXp > StartXp then
Obstacle := 2;
end;
end;
end;

// * Procedure balanceColor
// * Creates and Searches TPA for Balance Beam Obstacle and clicks on random
// area of ATPA[0] after boundries have been modified to click the cloest
// part of the plank.This is done because the 2nd partition has no action,
// and the third is "out of reach".
// * Sets camera high East during balance, for preperation of shields.
// * Increments course completion to (3/6).
// # Color: 5139324, Hue: 0.37, Sat: 1.85, CTS: 2, Tol: 2
procedure balanceColor;
var
x, y : Integer;
BalanceTPA : TPointArray;
BalanceATPA : T2DPointArray;
begin
StartXp := chatbox.getxp;
if findColorsSpiralTolerance(x, y, BalanceTPA, 5139324, mainScreen.getBounds(), 2, colorSetting(2, 0.37, 1.85)) then
begin
BalanceATPA := BalanceTPA.toATPA(30, 15);
BalanceATPA.filterBetween(0,50);
BalanceATPA.sortFromMidPoint(mainscreen.playerPoint);
if DEBUGSCRIPT then
begin
smartImage.clear;
smartImage.debugTPA(BalanceTPA, true);
smartImage.debugATPA(BalanceATPA);
end;
mouse(middleTPA(BalanceATPA[0]), MOUSE_MOVE, MOUSE_HUMAN);
wait(150 + random(25));
if isMouseOverText(['alanc']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Balance!');
if DEBUGSCRIPT then
smartImage.clear;
wait(150 + random(50));
minimap.setAngle(MM_DIRECTION_WEST);
if USEANTIBAN then
antiBan;
Wait(5000 + random(100));
NewXp := chatbox.getxp;
if NewXp > StartXp then
Obstacle := 3;
end;
end;
end;

// * Procedure shieldColor
// * Creates TPA for Shield Obstacle.
// * Searches for TPA "ShieldTPA", and clicks on lower shield.
// * Sets camera to high South during Obstacle, in preperation of rope.
// * Increments course completion to (4/6).
// # Color: 10721175, Hue: 0.0, Sat: 0.12, CTS: 2, Tol: 50
procedure shieldColor;
var
x, y : Integer;
ShieldTPA : TPointArray;
ShieldATPA : T2DPointArray;
begin
StartXp := chatbox.getxp;
if findColorsSpiralTolerance(x, y, ShieldTPA, 10721175, mainScreen.getBounds(), 50, colorSetting(2, 0.0, 0.12)) then
begin
ShieldATPA := ShieldTPA.toATPA(80, 25);
ShieldATPA.filterBetween(0, 100);
ShieldATPA.sortBySize(true);
if DEBUGSCRIPT then
begin
smartImage.clear;
smartImage.debugTPA(ShieldTPA, true);
smartImage.debugATPA(ShieldATPA);
end;
mouse(middleTPA(ShieldATPA[0]), MOUSE_MOVE, MOUSE_HUMAN);
wait(50 + random(25));
if isMouseOverText(['limb']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Shields!');
if DEBUGSCRIPT then
smartImage.clear;
wait(150 + random(50));
minimap.setAngle(MM_DIRECTION_SOUTH);
if USEANTIBAN then
antiBan;
Wait(4500 + random(100));
NewXp := chatbox.getxp;
if NewXp > StartXp then
Obstacle := 4;
if not NewXp > StartXp then
begin
if chatbox.findTextOnLines(['footing'], [0]) then
begin
writeln('YOU FELL! Lets try again');
wait(3000);
minimap.setAngle(MM_DIRECTION_WEST);
shieldColor;
end;
end;
end;
end;
end;

// * Procedure ropeColor
// * Creates TPA for Rope Swing Obstacle.
// * Searches for TPA "RopeTPA", and clicks on rope.
// * Increments course completion to (5/6).
// # Color: 206638, Hue: 0.11, Sat: 0.41, CTS: 2, Tol: 10
procedure ropeColor;
var
x, y : Integer;
RopeTPA : TPointArray;
RopeATPA : T2DPointArray;
begin
StartXp := chatbox.getxp;
if findColorsSpiralTolerance(x, y, RopeTPA, 206638, mainScreen.getBounds(), 10, colorSetting(2, 0.11, 0.41)) then
begin
RopeATPA := RopeTPA.toATPA(75, 75);
RopeATPA.filterBetween(0, 10);
RopeATPA.sortBySize(true);
if DEBUGSCRIPT then
begin
smartImage.clear;
smartImage.debugTPA(RopeTPA, true);
smartImage.debugATPA(RopeATPA);
end;
mouse(middleTPA(RopeATPA[0]), MOUSE_MOVE, MOUSE_HUMAN);
wait(150 + random(25));
if isMouseOverText(['wing']) then
begin
wait(150 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Rope!');
if DEBUGSCRIPT then
smartImage.clear;
minimap.clickCompass();
if USEANTIBAN then
antiBan;
wait(3500 + random(100));
NewXp := chatbox.getxp;
if NewXp > StartXp then
Obstacle := 5;
end;
end;
end;

// * Procedure monkeyColor
// * Creates TPA for Monkey Bars Obstacle.
// * Searches for TPA "MonkeyTPA", and clicks on rope.
// * Increments course completion to (6/6).
// # Color: 11061726, Hue: 0.1, Sat: 5.13, CTS: 2, Tol: 15
procedure monkeyColor;
var
x, y : Integer;
MonkeyTPA : TPointArray;
MonkeyATPA : T2DPointArray;
begin
StartXp := chatbox.getxp;
if findColorsSpiralTolerance(x, y, MonkeyTPA, 11061726, mainScreen.getBounds(), 15, colorSetting(2, 0.1, 5.13)) then
begin
MonkeyATPA := MonkeyTPA.toATPA(10,10);
MonkeyATPA.filterBetween(0,30);
MonkeyATPA.sortFromMidPoint(mainscreen.playerPoint);
if DEBUGSCRIPT then
begin
smartImage.clear;
smartImage.debugTPA(MonkeyTPA, true);
smartImage.debugATPA(MonkeyATPA);
end;
mouse(middleTPA(MonkeyATPA[0]), MOUSE_MOVE, MOUSE_HUMAN);
wait(300 + random(50));
if isMouseOverText(['ing']) then
begin
wait(450 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Monkey Bars!');
if DEBUGSCRIPT then
smartImage.clear;
if USEANTIBAN then
antiBan;
Wait(8000 + random(250));
NewXp := chatbox.getxp;
if NewXp > StartXp then
Obstacle := 6;
end;
end;
end;

// * Procedure checkerColor
// * Creates TPA for Checker Obstacle and clicks on random area of ATPA[0].
// * Updates progress report information.
// * Resets course completion to (0/6).
// # Color: 10996447, Hue: 0.20, Sat: 2.47, CTS: 2, Tol: 5
procedure checkerColor;
var
x, y : Integer;
CheckerTPA : TPointArray;
CheckerATPA : T2DPointArray;
begin
StartXp := chatbox.getxp;
if findColorsSpiralTolerance(x, y, CheckerTPA, 10996447, mainScreen.getBounds(), 5, colorSetting(2, 0.20, 2.47)) then
begin
CheckerATPA := CheckerTPA.toATPA(80,20);
CheckerATPA.filterBetween(0,40);
CheckerATPA.sortFromMidPoint(mainscreen.playerPoint);
if DEBUGSCRIPT then
begin
smartImage.clear;
smartImage.debugTPA(CheckerTPA, true);
smartImage.debugATPA(CheckerATPA);
end;
mouse(middleTPA(CheckerATPA[0]), MOUSE_MOVE, MOUSE_HUMAN);
wait(300 + random(50));
if isMouseOverText(['ump']) then
begin
wait(200 + random(50));
fastClick(MOUSE_LEFT);
writeLn('Found Checkers!');
if DEBUGSCRIPT then
smartImage.clear;
if USEANTIBAN then
antiBan;
Wait(3000 + random(150));
NewXp := chatbox.getxp;
if NewXp > StartXp then
Obstacle := 0;
end;
end;
end;

// * Procedure getToCourse
// * Uses our SPS map to return back to starting point of agility course
procedure getToCourse;
var
ReturnToCourse : TPointArray;
begin
lodestoneScreen.teleportTo(8);
wait(randomRange(16000, 17500));
returnToCourse := [Point(205, 217), Point(254, 206), Point(273, 192)];
if SPS.walkPath(ReturnToCourse) then
minimap.waitPlayerMoving()
end;

// * Procedure doTheCourse
// * Base case is off integer "Obstacle" for course completion porgress.
// * If base case is met, will search for DTM/TPA of case, and execute the
// procedure of the selected case.
// * Will print status of "Looking..." or "Found" when executed.
// # This is prevent searching for DTMs that are all present on the screen, and
// will only search for the one based off progress.
// # (Case/Procedure) - (0/Log), (1/Ladder), (2/Balance), (3/Shields),
// (4/Rope), (5/Monkey), (6/Checker).
procedure doTheCourse;
var
ObstacleTimer : TTimeMarker;
begin
if TimesFailed > TIMESTOFAIL then
begin
writeln('Failed too many times, stopping script for good measure!');
takeScreen('Failed, saving screenshot for future reference');
players[currentPlayer].logout();
terminateScript;
end;
if Obstacle = 0 then
begin
writeLn('Looking For Log...');
ObstacleTimer.start;
repeat
logColor;
wait(100);
if ObstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Log, teleporting home!');
incEx(TimesFailed, 1);
writeLn('Total Failed :' + intToStr(TimesFailed));
getToCourse;
minimap.clickCompass();
Exit;
end;
until(Obstacle = 1);
end;

if Obstacle = 1 then
begin
writeLn('Looking For Ladder...');
ObstacleTimer.start;
repeat
wallColor;
wait(100);
if ObstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Wall, teleporting home!');
incEx(TimesFailed, 1);
writeLn('Total Failed :' + intToStr(TimesFailed));
getToCourse;
minimap.clickCompass();
Exit;
end;
until(Obstacle = 2);
end;

if Obstacle = 2 then
begin
writeLn('Looking For Balance...');
ObstacleTimer.start;
repeat
balanceColor;
wait(100);
if ObstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Balance, teleporting home!');
incEx(TimesFailed, 1);
writeLn('Total Failed :' + intToStr(TimesFailed));
getToCourse;
minimap.clickCompass();
Exit;
end;
until(Obstacle = 3);
end;

if Obstacle = 3 then
begin
writeLn('Looking For Shields...');
ObstacleTimer.start;
repeat
shieldColor;
wait(100);
if ObstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Shields, teleporting home!');
incEx(TimesFailed, 1);
writeLn('Total Failed :' + intToStr(TimesFailed));
getToCourse;
minimap.clickCompass();
Exit;
end;
until(Obstacle = 4);
end;

if Obstacle = 4 then
begin
writeLn('Looking For Rope...');
ObstacleTimer.start;
repeat
ropeColor;
wait(100);
if ObstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Rope, teleporting home!');
incEx(TimesFailed, 1);
writeLn('Total Failed :' + intToStr(TimesFailed));
getToCourse;
minimap.clickCompass();
Exit;
end;
until(Obstacle = 5);
end;

if Obstacle = 5 then
begin
writeLn('Looking For Monkey...');
ObstacleTimer.start;
repeat
monkeyColor;
wait(100);
if ObstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Monkey, teleporting home!');
incEx(TimesFailed, 1);
writeLn('Total Failed :' + intToStr(TimesFailed));
getToCourse;
minimap.clickCompass();
Exit;
end;
until(Obstacle = 6);
end;

if Obstacle = 6 then
begin
writeLn('Looking For Checker...');
ObstacleTimer.start;
repeat
checkerColor;
wait(100);
if ObstacleTimer.getTime > 30000 then
begin
writeln('Timed out finding Checker, teleporting home!');
incEx(TimesFailed, 1);
writeLn('Total Failed :' + intToStr(TimesFailed));
getToCourse;
minimap.clickCompass();
Exit;
end;
until(Obstacle = 0);
incEx(LapTotal, 1);
XpCount := LapTotal * 79;
end;
end;

// * Procedure progressReport
// * Prints at lap completion to display Laps Completed, Xp Gained, Xp/Hr, and
// the amount of Times Failed.
procedure progressReport;
begin
SecondS := round((getTimeRunning/1000));
XpHour := round((3600*XpCount) / (SecondS));
writeLn('*************Progress Report***************');
writeLn(timeRunning);
writeLn('Laps Completed: ' + intToStr(LapTotal));
writeLn('Xp Gained: ' + intToStr(XpCount));
writeLn('Xp per Hour: ' + intToStr(XpHour));
writeLn('Times Failed: ' + intToStr(TimesFailed));
writeLn('*******************************************');
end;

// * Procedure Main
// * Sets up client and players.
// * Logs in player and sets camera to high North
// * Sets course completion to (0/6).
begin
autoUpdateMe;
clearDebug();
if not DEBUGSCRIPT then
disableSRLDebug := true;
smartEnableDrawing := true;
setupSRL;
declarePlayers;
SPS.setup('BURHTROPE_AGILITY_SPS', RUNESCAPE_OTHER);
Obstacle := 0;
repeat
if not isLoggedIn then
begin
players[currentPlayer].login();
exitSquealOfFortune();
getToCourse;
minimap.clickCompass();
end;
doTheCourse;
progressReport;
until(false);
end.

The Mayor

2014-02-08 05:06:22

I actually need to get from 1-40ish agility on my noob, so just gave this a test on a f2p account. Seems to work ok, although I couldn't test the walking failsafe as you haven't posted the SPS map :)

Brotein

2014-02-08 17:49:30

Oops, here's the image as the attachment.

The Mayor

2014-02-09 16:26:21

From: Brotein
Oops, here's the image as the attachment.


Thanks, I'll give this a run and post any feedback if I have any ;)


*************Progress Report***************
49 Minutes and 14 Seconds
Laps Completed: 58
Xp Gained: 4582
Xp per Hour: 5582
Times Failed: 0
*******************************************


Edit 1:

I have found a major bug:

When it times out on any obstacle and lodestone teles, you don't reset the obstacle number to 0. In this example, it times out finding the ladder (obstacle 1), teles and runs back to the course fine, but then it looks for the ladder, not the log.


Timed out finding Wall, teleporting home!
Total Failed :1
---- TRSLodestoneScreen.teleportTo(): result = true
-- sps.getPlayerPos(): Angle is at 184.398705354996, Setting angle to 0 degrees
---- TRSMinimap.clickCompass(): Clicked compass
-- sps.getPlayerPos(): result = {X = 202, Y = 222}, took 2703 ms
---- Waiting while the player is moving...
-- sps.walkPath(): result = True
---- Waiting while the player is moving...
-- chooseOption._select():
---- chooseOption.isOpen(): result = true
---- Options found: [Face NoMh, Cancel]
---- Found option "Face" in "Face NoMh"
-- chooseOption.select() result = true
---- TRSMinimap.clickCompass(): Clicked compass
*************Progress Report***************
50 Minutes and 24 Seconds
Laps Completed: 58
Xp Gained: 4582
Xp per Hour: 5455
Times Failed: 1
*******************************************
Looking For Ladder...


Then it gets in an infinite loop of tele -> fail to climb ladder -> tele -> fail to climb ladder. In your doTheCourse proc just but


if ObstacleTimer.getTime > 30000 then
begin
Obstacle := 0; // reset to 0
writeln('Timed out finding Log, teleporting home!');
incEx(TimesFailed, 1);
writeLn('Total Failed :' + intToStr(TimesFailed));
getToCourse;
minimap.clickCompass();
Exit;
end;

Also if you wanted to make it real pro, you could make the camera rotate within a range of degrees each obstacle so it's not exactly the same each time, something like:

minimap.setAngle(randomRange(10, 50));


Edit 2: @Brotein

It's got me 1 - 38 agility so far ;)


*************Progress Report***************
1 Hours, 59 Minutes and 19 Seconds
Laps Completed: 131
Xp Gained: 10349
Xp per Hour: 5203
Times Failed: 6
*******************************************
Failed too many times, stopping script for good measure!

It seems it on the odd occasion it checks the XP just before it finished the obstacle, so it tried to repeat the obstacle and eventually times out. It might be an idea to wait until startXP <> currentXP. You could put this into a waitFunc() so you can change the timeout for each obstacle.


function xpChange(): boolean;
begin
result := startXP <> currentXP;
end;

procedure Obstacle;
begin
//blah
waitFunc(@xpChange, 50, 10000);
//blah
end;


Brotein

2014-02-10 09:13:53

Good tips and nice to see it working. I think I had fixed the obstacle reset on the teleport on my last revision but I will add in that wait on xp change.