Aaron1520
2012-07-08 21:24:57
So I've watched my bot log in about 30 times now (let's say I've had to do some debugging and leave it at that) and I've felt it looks pretty regular and bot-like. So I had the following ideas to make it look more like a player:
First, make the typing seem more variable and have it make errors / fix them.
Luckily I managed to find a function integrated into SRL that already made mistakes, AddMistakes. So I modified TypeSend and made EnTypeSend (En for Enhanced…) that adds mistakes and tries to correct them while typing. It works like a charm.
Second make the login script occasionally use tab to get to the password box from the login box— or use enter. It just seemed really, really strange to have it click on password after entering your username. I've never seen an actual person do that. So I butchered LoginPlayerToLob and made it do my bidding:
I've thrown both together into a script that accurately demos the functions logging in and out several times. Apologies ahead of time if I'm using a different coding style. I tried to force myself to change but it's painstaking. Hope you guys can get some use out of this.
First, make the typing seem more variable and have it make errors / fix them.
Luckily I managed to find a function integrated into SRL that already made mistakes, AddMistakes. So I modified TypeSend and made EnTypeSend (En for Enhanced…) that adds mistakes and tries to correct them while typing. It works like a charm.
procedure EnTypeSend(Text: string; PressEnter: Boolean);
var
I, prob: Integer;
bText, newText : string;
begin
prob := 30;
bText := AddMistakes(Text, prob);
for i := 1 to Length(bText) do
begin
{$IFDEF SIMBAMAJOR980}
SendKeys(bText[i], 40 + Random(40));
{$ELSE}
SendKeys(bText[i], 30 + Random(30), 30 + Random(30));
{$ENDIF}
Wait(40 + Random(40));
//decent chance to catch our mistake
if((random(10) <> 0 ) and (bText[i] <> Text[i])) then
begin
if((bText[i] <> '')) then
TypeByte( VK_BACK );
Wait(80 + Random(80));
newText := AddMistakes(Text, prob-10);
{$IFDEF SIMBAMAJOR980}
SendKeys(newText[i], 40 + Random(40));
{$ELSE}
SendKeys(newText[i], 30 + Random(30), 30 + Random(30));
{$ENDIF}
end
end;
if (PressEnter) then
TypeByte(VK_RETURN);
end; Second make the login script occasionally use tab to get to the password box from the login box— or use enter. It just seemed really, really strange to have it click on password after entering your username. I've never seen an actual person do that. So I butchered LoginPlayerToLob and made it do my bidding:
function LoginPlayerToLob: Boolean;
var
Members, RetryLogin: Boolean;
typtmp, t, w: integer;
Actions: TVariantArray;
Attempts: LongInt;
p: TPoint;
//ATPA: T2dPointArray;
TPA: TPointArray;
Boxes : TIntegerArray;
//B: TBox;
label
ProcStart;
begin
ActivateClient;
Wait(100);
TypeByte(vk_Escape);
Wait(500);
{Check for lobby screen already open/ already logged in}
Result := ((LobbyScreen) or (LoggedIn));
if (Result) then
Exit;
{Check for active player.}
if (not (Players[CurrentPlayer].Active)) then
begin
WriteLn('Player is not Active...');
if (AllPlayersInActive) then
begin
WriteLn('All players not active!');
Exit;
end;
NextPlayer(False);
Exit;
end;
{Wait for the client to finish loading.}
T := GetSystemTime;
repeat
if (RSReady) then
Break;
if ((GetSystemTime - T) > 180000) then
begin
WriteLn('It has been 3 minutes and Runescape is not yet ready... Terminating.');
TerminateScript;
end;
Wait(RandomRange(1000, 2000));
until (False);
WriteLn('Welcome to Runescape.');
{New graphics have changed box}
Case CountColor(LOGIN_TEXTCOLOUR, 198, 192, 567, 259) of
1079: MouseBox(347, 295, 414, 303, mouse_left);
1745: MouseBox(347, 305, 414, 312, mouse_left); { "Available graphics options have been changed..." }
1801: MouseBox(347, 305, 414, 312, mouse_left); { "There was a problem with your current graphics settings..." }
end;
{Click less info if needed.}
{
if (not (SimilarColors(GetColor(382, 11), 14285562, 20))) then //Runescae sword green bead
begin
MouseBox(212, 479, 550, 495, 1); //Less info button
Wait(RandomRange(1000, 2000));
end;
}
{Click Members/free.}
Members := Players[CurrentPlayer].Member;
if (Length(Players[CurrentPlayer].WorldInfo) > 0) then
Members := Players[CurrentPlayer].WorldInfo[0];
ProcStart:
{if (Members) then
I := 1;
if (GetColor(248, 359) <> 1381653) then //Black outline on forgotten pwd button.
begin
FindColors(TPA, 9291999, 10, 370, 675, 475);
ATPA := SplitTPA(TPA, 4);
if (Length(ATPA) > 2) then
begin
if (I = 1) then
I := 0
else
I := 1;
B := GetTPABounds(ATPA[1 + I]); //If demo mode is still up
end
else
if (Length(ATPA) = 2) then
B := GetTPABounds(ATPA[0 + I]) //When there's no demo mode
else
B := IntToBox(210, 424, 367, 446);
with B do
MouseBox(X1 + 20, Y1 + 10, X2 - 20, Y2 + 8, 1);
T := GetSystemTime; //Black outline on forgotten pwd button.
while ((GetSystemTime - T < 3000) and (GetColor(248, 359) <> 1381653)) do
Wait(RandomRange(100, 200));
end; }
{Type in username and pass}
if (loggedIn) then
exit;
for W:= 0 to 1 do
begin
if W = 0 then
Boxes:= [UBX1, UBY1, UBX2, UBY2]
else
Boxes:= [PBX1, PBY1, PBX2, PBY2];
t := (getSystemTime + (60000 * 2));
FindColors(TPA, LOGIN_TEXTCOLOUR, Boxes[0], Boxes[1], Boxes[2], Boxes[3]);
if ( W <> 1 ) or ( random( 5 ) = 0 ) then
begin
repeat
begin
if (Length(TPA) > 0) then
begin
SortTPAFrom(TPA, Point(Boxes[2], Boxes[1] + (Boxes[3] - Boxes[2]) div 2));
p := point(TPA[0].X + 20, TPA[0].Y);
if (not pointInBox(p, intToBox(Boxes[0], Boxes[1], Boxes[2], Boxes[3]))) then
p := point(UBX2 - (10 + random(10)), p.y);
Mouse(p.x, p.y, 5, 5, mouse_left);
end else
MouseBox(Boxes[0], Boxes[1], Boxes[2], Boxes[3], mouse_left);
typtmp := 0;
while (CountColor(LOGIN_TEXTCOLOUR, Boxes[0], Boxes[1], Boxes[2], Boxes[3]) > 0) do
begin
Inc(typtmp);
TypeByte(VK_BACK);
Wait(50+Random(50));
if (typtmp >= RandomRange(20, 24)) then
Break;
end
end
until(not FindColors(TPA, LOGIN_TEXTCOLOUR, Boxes[0], Boxes[1], Boxes[2], Boxes[3]) or (getSystemTime > t));
end
else
begin
if ( random( 5 ) = 4 ) then
begin
TypeByte( VK_RETURN );
wait( 50 + random( 50 ) );
end
else
begin
TypeByte( VK_TAB );
wait( 50 + random( 50 ) );
end
end;
Wait(100 + Random(200));
if W = 0 then
begin
WriteLn(Capitalize(Players[CurrentPlayer].Name));
EnTypeSend(Players[CurrentPlayer].Name, false);
end else
begin
if( W = 1 ) then
begin
typtmp := 0;
Boxes:= [PBX1, PBY1, PBX2, PBY2];
while (CountColor(LOGIN_TEXTCOLOUR, Boxes[0], Boxes[1], Boxes[2], Boxes[3]) > 0) do
begin
Inc(typtmp);
TypeByte(VK_BACK);
Wait(50+Random(50));
if (typtmp >= RandomRange(20, 24)) then
Break;
end
end;
EnTypeSend(Players[CurrentPlayer].Pass, true);
Wait(100 + Random(50));
end
end;
{Check responses}
T := GetSystemTime;
repeat
// so the lobby appears (gets rid of black screen)
if (countColorTolerance(clBlack, 0, 0, 500, 500, 20) > 245000) then
begin
wait(2000 + random(1500));
mouseBox(0, 0, 750, 490, mouse_Move);
end;
result := validEmail; // To handle "Validate Email" screen
if result then
break;
SetLength(Actions, 0);
if ((GetSystemTime - T) > 60000) then
Actions := ['One minute has passed... Debug: ' + ToStr(CountColor(LOGIN_TEXTCOLOUR, 260, 140, 510, 400)), 0, 5, 'PlayerFalse', 'Login Failed']
else
case (CountColor(LOGIN_TEXTCOLOUR, 260, 140, 510, 400)) of //text colour points
// WriteLn Error Wait for Retrys Action Player[CurrentPlayer].Loc
763, 2348, 2299:
Actions := ['Invalid Username / Password', 0, 2, 'PlayerFalse', 'Wrong User/Pass'];
1088: Actions := ['Your account has been disabled', 0, 0, 'PlayerFalse', 'Acc Disabled'];
951: Actions := ['Your account is already logged in', 5000, 5, 'PlayerTrue', 'Already logged in'];
1239: Actions := ['Not a Members Account', 0, 1, 'PlayerTrue', ''];
364: Actions := ['Error Connecting.', 20000, 9, 'Terminate', 'Error Connecting'];
1057: Actions := ['Too many incorrect logins.', 5 * 60000, 2, 'PlayerFalse', 'Too many logins'];
732: Actions := ['Runescape has been updated.', 0, 0, 'RSUpdate', 'RS Updated'];
591: Actions := ['Client token changed.', 0, 0, 'RSUpdate', 'Client Token Changed'];
1606: Actions := ['Game session expired.', 0, 0, 'RSUpdate', 'Session Expired'];
777: Actions := ['Login limit exceeded.', 20000, 10, '', 'Waiting for login.'];
end;
{Respond}
if (Length(Actions) > 0) then
begin
WriteLn(Actions[0]);
if (Actions[0] <> 'Not a Members Account') then
begin
Wait(1000 + Random(500));
TypeByte(vk_Escape);
end;
Wait(Actions[1] + Random(100));
if (Actions[2] <> 0) then
if (Attempts < Actions[2]) or (Actions[2] = -1) then
begin
if (Actions[0] = 'Not a Members Account') then
begin
Players[CurrentPlayer].Member := False;
if (Length(Players[CurrentPlayer].WorldInfo) > 0) then
Players[CurrentPlayer].WorldInfo[0] := False;
MouseBox(267, 321, 496, 350, mouse_left); //Play free game instead button
Wait(3000 + Random(2000));
Result := True;
Exit;
end;
RetryLogin := True;
Wait(2000 + Random(1000));
Break;
end;
if (Actions[4] <> '') then
Players[CurrentPlayer].Loc := Actions[4];
case Actions[3] of
'PlayerFalse': NextPlayer(False);
'PlayerTrue':
begin
LeaveLobby();
NextPlayer(True);
end;
'Terminate': TerminateScript;
'RSUpdate':
begin
if (SRL_Procs[srl_OnRSUpdate] <> nil) then
begin
SRL_Procs[srl_OnRSUpdate]();
Exit;
end;
Writeln('Runescape has been updated! Please restart Simba.');
TerminateScript;
end;
end;
Exit;
end;
Wait(100);
Result := (LobbyScreen) or (LoggedIn);
until (Result);
TakeIPScreen();
{Back to main screen if needed}
if (RetryLogin) then
begin
RetryLogin := False;
Inc(Attempts);
goto ProcStart;
end;
end; I've thrown both together into a script that accurately demos the functions logging in and out several times. Apologies ahead of time if I'm using a different coding style. I tried to force myself to change but it's painstaking. Hope you guys can get some use out of this.