PDA

View Full Version : [Utility] [Color] Tutorial Island Runner



Citrus
02-19-2018, 04:06 AM
All color :cool:
You should be able to start it from almost any point in the tutorial.
Just target the fixed window, check the settings, and press play.
One potential issue: make sure you log in manually at least once on the client before starting the script.

It's pretty hacky right now, but improvements should be easy to implement (e: for me). I might get around to some of them eventually, but in the meantime this should work.


program Citrus_Tutorial_Island;
{$LoadLib SimpleOCR}

const
{settings begin}

LOGIN = '';
PASSWORD = '';
RANDOMCHARACTER = True;
WORLDS = [301, 308, 316, 326, 335, 382, 383, 384, 393, 394];

{settings end}

type
TCTS2Settings = Record
Color, Tol: Int32; HueMod, SatMod: Extended;
end;

TInventoryItem = Record
Length, Width, Height, ShadowLength, AverageColor: Int32; Text: TStringArray;
end;

TTab = (CombatOptions, Stats, QuestList, Inventory, WornEquipment, Prayer, Magic, ClanChat, FriendsList, IgnoreList, Logout, Options, Emotes, MusicPlayer);

TOption = Record
Text: String;
Bounds: TBox;
end;

TOptionArray = Array of TOption;

const
MOUSE_MOVE = 3;

FIXED_WIDTH = 765;
FIXED_HEIGHT = 503;

OCR_RULES_UPTEXT: TCompareRules = [-1, 85, True, 55];
UPTEXT_BOX: TBox = [7, 7, 465, 25];

MSX1 = 4;
MSY1 = 4;
MSX2 = 515;
MSY2 = 337;
MSCX = 259;
MSCY = 170;
MSCP: TPoint = [MSCX, MSCY];
MSBOX: TBox = [MSX1, MSY1, MSX2, MSY2];
CHATBOX: TBox = [6, 344, 513, 474];
INVBOX: TBox = [547, 204, 736, 465];

MMX1 = 570;
MMY1 = 9;
MMX2 = 714;
MMY2 = 159;
MMCX = 642;
MMCY = 84;
MMCP: TPoint = [MMCX, MMCY];
MMBOX: TBox = [MMX1, MMY1, MMX2, MMY2];
MM_COMPASS_BOX: TBox = [546, 6, 574, 34];
MM_XP_DROP_BOX: TBox = [516, 21, 542, 47];

BANK_CLOSE_BOX: TBox = [475, 12, 500, 34];

TEXT_ORANGE = 2070783;
TEXT_GREEN = 49152;
TEXT_BLACK = 0;
TEXT_WHITE = $FFFFFF;
TEXT_BLUE = 16711680;
TEXT_DARK_BLUE = 8388608;
TEXT_RED = 128;

YELLOW_ARROW_CTS2: TCTS2Settings = [7011068, 15, 0.02, 0.09];
GUIDE_RED_CTS2: TCTS2Settings = [792697, 9, 0.05, 0.42];
FIRE_FLAME_CTS2: TCTS2Settings = [2598615, 13, 0.19, 1.61];
CHICKEN_CTS2: TCTS2Settings = [6919082, 15, 0.03, 0.58];
INV_BG_CTS2: TCTS2Settings = [3424072, 5, 0.66, 1.26];

TUTORIAL_STAGES: TStringArray = [
'Getting started',
'your player controls',
'r should acc',
'Interacting with scenery',
'Moving around',
'Viewing the items',
'Cut down a tree',
'Making a fire',
'ear the inventory button',
'Your skill stats',
'Catch some Shrimp',
'Cooking your shrimp',
'Burning your shrimp',
'your first RuneScape meal',
'used for navigation',
'out your music p',
'Making dough',
'Cooking dough',
'move on. Click on the fla',
'The music player',
'Emotes',
'Running',
'Run to the next guide',
'Talk with the Quest Guide',
'Open the Quest Journal',
'Your Quest Journal',
'the next area',
'Mining and Smithing',
'Prospecting',
'It''s tin',
'It''s copper',
'Mining.',
'Smelting',
'You''ve made a bronze bar!',
'Smithing a dagger',
'You''ve finished in this area',
'Combat.',
'Wielding weapons.',
'This is your worn inventory.',
'Worn interface',
'You''re now holding your dagger.',
'Unequipping items.',
'Combat interface.',
'This is your combat interface.',
'Attacking',
'Well done, you''ve made your first kill!',
'Rat ranging.',
'Moving on.',
'Banking.',
'This is your bank box.',
'This is a poll booth.',
'Financial advice.',
'Continue through the next door.',
'Prayer.',
'open the Prayer menu.',
'tell you about prayers',
'open your friends list',
'This is your friends list.',
'This is your ignore list.',
'find the path leading to your final',
'Your final instructor!',
'Open up your final menu.',
'Cast Wind Strike at a chicken.',
'You have almost completed the tutorial!'
];



var
UpFont: TFontSet;
OCR: TSimpleOCR;
Tinderbox : TInventoryItem = [80, 30, 28, 51, 7789174, ['Tinderbox', 'inder']];
Logs : TInventoryItem = [85, 31, 25, 44, 3698039, ['Logs', 'ogs']];
RawShrimp : TInventoryItem = [137, 31, 23, 65, 7030867, ['Raw shrimps', 'shrimp']];
PotOfFlour : TInventoryItem = [79, 26, 28, 35, 6100572, ['Pot of flour', 'of flour']];
BucketOfWater : TInventoryItem = [75, 20, 29, 37, 4950905, ['Bucket of water']];
BreadDough : TInventoryItem = [75, 29, 23, 36, 7106950, ['Bread dough', 'read', 'dough']];
Bread : TInventoryItem = [65, 27, 25, 43, 947766, ['Bread']];
TinOre : TInventoryItem = [171, 32, 28, 75, 5164116, ['Tin ore']];
BronzeBar : TInventoryItem = [62, 28, 22, 39, 2032043, ['Bronze bar', 'ronze ba']];
BronzeDagger : TInventoryItem = [73, 21, 31, 49, 1365088, ['Bronze dagger', 'ronze da']];
BronzeSword : TInventoryItem = [67, 20, 31, 48, 1433026, ['Bronze sword', 'ronze sw']];
WoodenShield : TInventoryItem = [71, 27, 26, 39, 935175, ['Wooden shield', 'ooden sh']];
BronzeArrows50: TInventoryItem = [243, 31, 30, 71, 1446391, ['Bronze arrow', 'ronze ar']];
Shortbow : TInventoryItem = [102, 30, 24, 66, 1121035, ['Shortbow', 'hortbo']];


procedure Wait(w1, w2: Int32); Overload;
begin
Wait(Random(w1, w2));
end;

function FindColorsCTS2(var TPA: TPointArray; const B: TBox; const Settings: TCTS2Settings): Boolean;
begin
SetColorToleranceSpeed(2);
SetToleranceSpeed2Modifiers(Settings.HueMod, Settings.SatMod);
Result := FindColorsTolerance(TPA, Settings.Color, B.X1, B.Y1, B.X2, B.Y2, Settings.Tol);
SetColorToleranceSpeed(1);
end;

function FindColorsTolerance(var TPA: TPointArray; Color: Int32; b: TBox; Tol: Int32): Boolean; Overload;
begin
Result := FindColorsTolerance(TPA, Color, b.x1, b.y1, b.x2, b.y2, Tol);
end;

function FindColors(var TPA: TPointArray; Color: Int32; b: TBox): Boolean; Overload;
begin
Result := FindColors(TPA, Color, b.x1, b.y1, b.x2, b.y2);
end;

function CountColorTolerance(const Color: Int32; b: TBox; Tol: Int32): Int32; Overload;
begin
Result := CountColorTolerance(Color, b.x1, b.y1, b.x2, b.y2, Tol);
end;

function BitmapFromClient(const B: TBox): Int32; Overload;
begin
Result := BitmapFromClient(B.X1, B.Y1, B.X2, B.Y2);
end;

function BitmapFromTPA(const TPA: TPointArray; Color: Int32 = $FFFFFF): Int32;
var
b: TBox;
temp: TPointArray;
begin
b := GetTPABounds(tpa);
Result := CreateBitmap(b.x2 - b.x1 + 1, b.y2 - b.y1 + 1);
temp := CopyTPA(TPA);
OffsetTPA(temp, [-b.x1, -b.y1]);
DrawTPABitmap(Result, temp, Color);
end;

//https://github.com/SRL/SRL-6/blob/d5817b11a391940d12180740a914a4cf5d72b204/lib/utilities/math.simba#L59
function GridBox(Slot, Columns, Rows, w, h, DiffX, DiffY: Int32; StartPoint: TPoint): TBox;
begin
Result.x1 := (StartPoint.x + ((Slot mod Columns) * DiffX) - (w div 2));
Result.y1 := (StartPoint.y + ((Slot div Columns) * DiffY) - (h div 2));
Result.x2 := (Result.x1 + w);
Result.y2 := (Result.y1 + h);
end;

function GetSlotBox(const Slot: Int32): TBox;
begin
if (not InRange(Slot, 1, 28)) then Exit;
Result := GridBox(Slot - 1, 4, 7, 31, 31, 42, 36, [578, 228]);
end;

function BoxWidth(const B: TBox): Int32;
begin
Result := B.X2 - B.X1 + 1;
end;

function BoxHeight(const B: TBox): Int32;
begin
Result := B.Y2 - B.Y1 + 1;
end;

procedure Mouse(p: TPoint; Button: Int32);
var
x, y: Int32;
begin
MoveMouse(p.x, p.y);
if (Button = MOUSE_MOVE) then Exit();
Wait(15, 22);
HoldMouse(p.x, p.y, Button);
Wait(69, 120);
GetMousePos(x, y);
ReleaseMouse(x, y, Button);
end;

procedure FastClick(Button: Int32);
var
x, y: Int32;
begin
GetMousePos(x, y);
HoldMouse(x, y, Button);
Wait(69, 120);
ReleaseMouse(x, y, Button);
end;

procedure MouseBox(B: TBox; Button: Int32);
begin
Mouse(MiddleBox(B), Button);
end;

procedure TypeSend(Text: String; Enter: Boolean);
var
Shift: Boolean;
i: Int32;
begin
for i := 1 to Length(Text) do
begin
Shift := (Pos(Text[i], 'ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+<>?:"{}~|') > 0);
if Shift then
begin
KeyDown(VK_SHIFT);
Wait(44, 69);
end;
KeyDown(GetKeyCode(Text[i]));
Wait(44, 69);
KeyUp(GetKeyCode(Text[i]));
Wait(44, 69);
if Shift then
begin
KeyUp(VK_SHIFT);
Wait(44, 69);
end;
end;
if Enter then
begin
KeyDown(VK_RETURN);
Wait(44, 69);
KeyUp(VK_RETURN);
end;
end;

function ClientColors(x1, y1, w, h: Int32): T2DIntegerArray;
var
bmp: Int32;
begin
bmp := BitmapFromClient(x1, y1, x1 + w, y1 + h);
try
GetBitmapSize(bmp, w, h);
Result := GetBitmapAreaColors(bmp, 0, 0, w - 1, h - 1);
finally
FreeBitmap(bmp);
end;
end;

function IsUpText(Text: String; WaitTime: Int32 = -1): Boolean;
var
t: UInt32;
begin
t := GetTickCount + WaitTime;
repeat
Result := (Pos(Text, OCR.Recognize(UPTEXT_BOX, OCR_RULES_UPTEXT)) > 0);
if Result then Exit;
Wait(4);
until (GetTickCount > t);
end;

function IsUpTextMulti(Text: TStringArray; WaitTime: Int32 = -1): Boolean;
var
t: UInt32;
begin
t := GetTickCount + WaitTime;
repeat
Result := IsArrInStr(Text, OCR.Recognize(UPTEXT_BOX, OCR_RULES_UPTEXT));
if Result then Exit;
Wait(4);
until (GetTickCount > t);
end;

function IsXPOpen(): Boolean;
begin
Result := (CountColor(2306104, 389, 0, 515, 40) > 244);
end;

function GetXP(): Int32;
var
tpa: TPointArray;
atpa: T2DPointArray;
begin
if IsXPOpen() then
begin
if FindColors(tpa, $FFFFFF, 389, 0, 515, 40) then
begin
atpa := ClusterTPA(tpa, 1);
Result := StrToIntDef(ExtractFromStr(GetTextATPA(atpa, 9, 'StatChars07'), NUMBERS), -1);
end;
end;
end;

//https://github.com/SRL/SRL/blob/master/shared/text.simba#L18
function FindTextIn(var Matches: TPointArray; const Text, Font: String; const Color: Int32; const b: TBox): Boolean;
var
w, h: Int32;
TPA, TextTPA: TPointArray;
begin
if FindColors(TPA, Color, b) then
begin
SetLength(Matches, 0);
TextTPA := TPAFromText(Text, Font, w, h);
Result := FindTextTPAinTPA(h-1, TextTPA, TPA, Matches);
end;
end;

function FindText(var Matches: TPointArray; Text, Font: String; const Color: Int32): Boolean;
var
w, h: Int32;
begin
GetClientDimensions(w, h);
Result := FindTextIn(Matches, Text, Font, Color, [0, 0, w-1, h-1]);
end;

function WaitFunc(Func: function: Boolean; WaitTime, WaitInterval: Int32; Condition: Boolean = True): Boolean;
var
t: UInt32;
begin
t := GetTickCount() + WaitTime;
repeat
Result := Func();
if (Result = Condition) then Exit(True);
Wait(WaitInterval);
until (GetTickCount() > t);
Result := False;
end;

function IsWalking(): boolean;
var
bmp1, bmp2, w, h: Int32;
begin
try
bmp1 := BitmapFromClient(MSX1, MSY1, MSX2, MSY2);
Wait(69);
bmp2 := BitmapFromClient(MSX1, MSY1, MSX2, MSY2);
GetBitmapSize(bmp1, w, h);
Result := (CalculatePixelShift(bmp1, bmp2, [0, 0, w-1, h-1]) > 69696);
finally
if BitmapExists(bmp1) then FreeBitmap(bmp1);
if BitmapExists(bmp2) then FreeBitmap(bmp2);
end;
end;

function WaitForInventoryShift(const WaitTime, WaitInterval: Int32): Boolean;
var
BMP1, BMP2, w, h: Int32;
t: UInt32;
begin
Result := False;
t := GetTickCount() + WaitTime;
BMP1 := BitmapFromClient(INVBOX);
GetBitmapSize(BMP1, w, h);
try
repeat
Wait(WaitInterval);
BMP2 := BitmapFromClient(INVBOX);
Result := (CalculatePixelShift(BMP1, BMP2, [0, 0, w-1, h-1]) > 0);
if Result then Exit;
FreeBitmap(BMP2);
until (GetTickCount() > t);
finally
FreeBitmap(BMP1);
if BitmapExists(BMP2) then FreeBitmap(BMP2);
end;
end;

function IsOptionOpen(var b: TBox): Boolean;
var
tpa: TPointArray;
atpa: T2DPointArray;
begin
if FindColors(tpa, 4674653, 0, 0, FIXED_WIDTH-1, FIXED_HEIGHT-1) then
begin
atpa := ClusterTPA(tpa, 5);
if (Length(atpa) > 0) then
begin
SortATPASize(atpa, True);
b := GetTPABounds(atpa[0]);
Exit(True);
end;
end;
end;

function OptionOpen(): Boolean;
var
b: TBox;
begin
Result := IsOptionOpen(b);
end;

function GetOptions(): TOptionArray;
var
n, bmp, w, h, OldT: Int32;
tpa, bg, black: TPointArray;
atpa: T2DPointArray;
b, b2, b3: TBox;
begin
if IsOptionOpen(b) then
begin
OldT := GetImageTarget;
b2 := [b.x1 + 4, b.y1 + 21, b.x2 - 2, b.y1 + 21 + 13];
SetLength(Result, 99);
while (b2.y2 < b.y2) do
begin
tpa := TPAFromBox(b2);
if FindColors(bg, 4674653, b2) then
begin
if FindColors(black, 0, b2) then
begin
tpa := ClearTPAFromTPA(tpa, bg);
tpa := ClearTPAFromTPA(tpa, black);
b3 := GetTPABounds(tpa);
bmp := BitmapFromTPA(tpa);
SetTargetBitmap(bmp);
GetBitmapSize(bmp, w, h);
Result[n] := [GetTextAtEx(0, 0, w-1, h-1, 0, 3, 9, $FFFFFF, 0, 'UpChars07'), b2];
Inc(n);
SetImageTarget(OldT);
FreeBitmap(bmp);
end;
end;
b2.y1 += 15;
b2.y2 += 15;
end;
SetLength(Result, n);
end;
end;

function ChooseOption(Text: TStringArray; Button: Int32 = MOUSE_LEFT): Boolean;
var
i, j, x, y: Int32;
Options: TOptionArray;
begin
Options := GetOptions();
if (Length(Options) > 0) then
begin
for i := 0 to High(Text) do
begin
for j := 0 to High(Options) do
begin
if (Pos(Text[i], Options[j].Text) > 0) then
begin
Mouse(MiddleBox(Options[j].Bounds), Button);
Exit(True);
end;
end;
end;
end;
end;

function IsBankOpen(): Boolean;
var
Matches: TPointArray;
begin
Result := (FindTextIn(Matches, 'Rearrange', 'SmallChars07', 2070783, MSBOX) or
FindTextIn(Matches, 'The Bank of RuneScape', 'UpChars07', 2070783, MSBOX));
end;

function IsBankClosed(): Boolean;
begin
Result := (not IsBankOpen);
end;

function IsLoggedIn(): Boolean;
begin
Result := (GetColor(FIXED_WIDTH - 1, 0) = 3494488);
end;

function IsLoginScreen(): Boolean;
var
Matches: TPointArray;
begin
Result := FindTextIn(Matches, 'World', 'UpChars07', $FFFFFF, [0, 420, 111, FIXED_HEIGHT-1]);
end;

procedure ClickToSwitch;
begin
Mouse([55, 480], MOUSE_LEFT);
end;

function IsWorldScreen(): Boolean;
var
Matches: TPointArray;
begin
Result := FindText(Matches, 'Type', 'UpChars07', $FFFFFF);
end;

function FindWorld(World: Int32): Boolean;
var
Matches: TPointArray;
begin
Result := FindTextIn(Matches, IntToStr(World), 'UpChars07', $FFFFFF, [0, 420, 111, FIXED_HEIGHT-1]);
end;

function ClickWorld(World: Int32): Boolean;
var
WorldBMP, ClientBMP, OldT, NewT, x, y: Int32;
begin
Result := False;
WorldBMP := BitmapFromText(IntToStr(World), 'UpChars07');
ClientBMP := BitmapFromClient(152, 49, 611, 475);
try
FastReplaceColor(ClientBMP, 0, $FFFFFF);
OldT := GetImageTarget;
NewT := SetTargetBitmap(ClientBMP);
Result := FindBitmap(WorldBMP, x, y);
SetImageTarget(OldT);
if Result then Mouse([x + 152, y + 49], MOUSE_LEFT);
finally
FreeTarget(NewT);
FreeBitmap(ClientBMP);
FreeBitmap(WorldBMP);
end;
end;

function SelectWorld(WorldNumber: Int32): Boolean;
var
WorldNumberBMP, x, y: Int32;
begin
Result := False;
if FindWorld(WorldNumber) then Exit(True);
WorldNumberBMP := BitmapFromText(IntToStr(WorldNumber), 'UpChars07');
try
if IsLoginScreen then
begin
ClickToSwitch;
if (not WaitFunc(@IsWorldScreen, 4567, 234, True)) then Exit;
end;
if IsWorldScreen() then
begin
if ClickWorld(WorldNumber) then
begin
Result := WaitFunc(@IsLoginScreen, 4567, 234, True);
end;
end;
finally
FreeBitmap(WorldNumberBMP);
end;
end;

function IsWelcomeBox(): Boolean;
var
TPA: TPointArray;
begin
Result := FindText(TPA, 'Welcome to', 'UpChars07', $00FFFF);
end;

function IsEnterBox(): Boolean;
var
TPA: TPointArray;
begin
Result := FindText(TPA, 'Enter your', 'UpChars07', $00FFFF);
end;

function ClickExistingUser(): Boolean;
var
TPA: TPointArray;
begin
if IsWelcomeBox() then
begin
if FindText(TPA, 'Existing', 'UpChars07', $FFFFFF) then
begin
Mouse(TPA[0], MOUSE_LEFT);
Result := WaitFunc(@IsEnterBox, 2345, 234, True);
end;
end;
end;

function DoLogin(UN, PW: String; World: Int32): Boolean;
var
TPA: TPointArray;
begin
if SelectWorld(World) then
begin
if ClickExistingUser() then
begin
if (not FindText(TPA, UN, 'UpChars07', $FFFFFF)) then
begin
TypeSend(UN, True);
Wait(121, 212);
end;
TypeSend(PW, True);
Result := WaitFunc(@IsLoginScreen, 9876, 678, False);
end;
end;
end;

function ItemAverageColor(Slot: Int32): Int32;
var
i: Int32;
B: TBox;
Colors: TIntegerArray;
BGTPA, ShadowTPA, BorderTPA, TPA: TPointArray;
begin
B := GetSlotBox(Slot);
if FindColors(BorderTPA, 65536, B) then
begin
if (FindColors(ShadowTPA, 2105392, B) or FindColors(ShadowTPA, 3355443, B)) then
begin
if FindColorsCTS2(BGTPA, B, INV_BG_CTS2) then
begin
TPA := TPAFromBox(B);
TPA := ClearTPAFromTPA(TPA, CombineTPA(CombineTPA(BorderTPA, BGTPA), ShadowTPA));
Colors := GetColors(TPA);
ClearSameIntegers(Colors);
Result := AverageTIA(Colors);
end;
end;
end;
end;

function TInventoryItem.GetSlot(): Int32;
var
i: Int32;
B: TBox;
TPA, ShadowTPA: TPointArray;
begin
for i := 1 to 28 do
begin
if (FindColors(TPA, 65536, GetSlotBox(i)) and (FindColors(ShadowTPA, 2105392, GetSlotBox(i)) or FindColors(ShadowTPA, 3355443, GetSlotBox(i)))) then
begin
B := GetTPABounds(TPA);
if ((Self.Length = (High(TPA) + 1)) and
(Self.Width = BoxWidth(B)) and
(Self.Height = BoxHeight(B)) and
(Self.ShadowLength = (High(ShadowTPA) + 1)) and
(Self.AverageColor = ItemAverageColor(i))) then
Exit(i);
end;
end;
Result := -1;
end;

function TInventoryItem.Count(): Int32;
var
i: Int32;
B: TBox;
TPA: TPointArray;
begin
for i := 1 to 28 do
begin
if FindColors(TPA, 65536, GetSlotBox(i)) then
begin
B := GetTPABounds(TPA);
if ((Self.Length = (High(TPA) + 1)) and
(Self.Width = BoxWidth(B)) and
(Self.Height = BoxHeight(B))) then
Inc(Result);
end;
end;
end;

function TInventoryItem.Click(Button: Byte = MOUSE_LEFT): Boolean;
var
Slot: Int32;
begin
Slot := Self.GetSlot();
if (Slot > 1) then
begin
MouseBox(GetSlotBox(Slot), MOUSE_MOVE);
if IsUpTextMulti(Self.Text, 444) then
begin
FastClick(Button);
Result := True;
end;
end;
end;

function TInventoryItem.Find(): Boolean;
begin
Result := (Self.GetSlot() > 1);
end;

function IsDesignScreen(): Boolean;
var
TPA: TPointArray;
begin
Result := FindText(TPA, 'design your player', 'UpChars07', TEXT_ORANGE);
end;

function DoDesignScreen(RandomChar: Boolean): Boolean;
const
DESIGN_BOX: TBox = [80, 70, 140, 320];
COLOUR_BOX: TBox = [380, 70, 440, 250];
DESIGNS: TStringArray = ['Head', 'Jaw', 'Torso', 'Arms', 'Hands', 'Legs', 'Feet'];
COLOURS: TStringArray = ['Hair', 'Torso', 'Legs', 'Feet', 'Skin'];
var
i: Int32;
TPA: TPointArray;
begin
if RandomChar then
begin
for i := 0 to High(DESIGNS) do
begin
if FindTextIn(TPA, DESIGNS[i], 'SmallChars07', TEXT_ORANGE, DESIGN_BOX) then
begin
OffsetTPA(TPA, [70, 0]);
for 0 to Random(9) do
begin
Mouse(TPA[0], MOUSE_LEFT);
Wait(222, 321);
end;
end;
end;
for i := 0 to High(COLOURS) do
begin
if FindTextIn(TPA, COLOURS[i], 'SmallChars07', TEXT_ORANGE, COLOUR_BOX) then
begin
OffsetTPA(TPA, [70, 0]);
for 0 to Random(9) do
begin
Mouse(TPA[0], MOUSE_LEFT);
Wait(222, 321);
end;
end;
end;
end;
if FindText(TPA, 'Accept', 'SmallChars07', TEXT_GREEN) then
begin
Mouse(TPA[0], MOUSE_LEFT);
Result := WaitFunc(@IsDesignScreen, 4567, 456, False);
end;
end;

procedure ResetCamera();
begin
MouseBox((MM_COMPASS_BOX), MOUSE_LEFT);
Wait(222);
KeyDown(VK_UP);
Wait(969, 1234);
KeyUp(VK_UP);
end;

function FindYellowArrow(var P: TPoint): Boolean;
var
c: Int32;
TPA: TPointArray;
begin
while (not FindColorsCTS2(TPA, MSBOX, YELLOW_ARROW_CTS2)) do
begin
Wait(22);
if (Inc(c) > 22) then Exit;
end;
if InRange(Length(TPA), 200, 220) then
begin
P := MedianTPA(TPA);
Result := True;
end;
end;

function ClickHereToContinue(): Boolean;
var
TPA: TPointArray;
begin
if (FindTextIn(TPA, 'Click here to continue', 'CharsNPC07', TEXT_BLUE, CHATBOX) or
FindTextIn(TPA, 'Click here to continue', 'CharsNPC07', TEXT_WHITE, CHATBOX)) then
begin
OffsetTPA(TPA, [69, 4]);
Mouse(TPA[0], MOUSE_LEFT);
Result := True;
end;
end;

function PleaseWait(): Boolean;
var
TPA: TPointArray;
begin
Result := (FindTextIn(TPA, 'wait', 'CharsNPC07', TEXT_BLUE, CHATBOX) or
FindTextIn(TPA, 'wait', 'CharsNPC07', TEXT_WHITE, CHATBOX));
end;

function IsConversation(): Boolean;
var
TPA: TPointArray;
begin
Result := FindTextIn(TPA, 'Click here to continue', 'CharsNPC07', TEXT_BLUE, CHATBOX);
end;

function DoConversation(TextOptions: TStringArray = []): Boolean;
var
i: Int32;
TPA: TPointArray;
begin
repeat
if PleaseWait() then
begin
Wait(234, 432);
Continue;
end;
if ClickHereToContinue() then
begin
Wait(121, 212);
Continue;
end;
if (Length(TextOptions) > 0) then
begin
for i := 0 to High(TextOptions) do
begin
if FindTextIn(TPA, TextOptions[i], 'CharsNPC07', TEXT_BLACK, CHATBOX) then
begin
OffsetTPA(TPA, [4, 4]);
Mouse(TPA[0], MOUSE_LEFT);
Wait(121, 212);
Break;
end;
end;
if (i <= High(TextOptions)) then Continue;
end;
Break;
until False;
Result := True;
end;

function IsTalkingTo(NPCName: String; WaitTime: Int32 = -1): Boolean;
var
t: UInt32;
TPA: TPointArray;
begin
t := GetTickCount + WaitTime;
repeat
Result := FindTextIn(TPA, NPCName, 'CharsNPC07', TEXT_RED, CHATBOX);
if Result then Exit;
Wait(44);
until (GetTickCount > t);
end;

function TalkToNPC(Name: String; Text: TStringArray; WaitTime: Int32): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(Text, 444) then
begin
FastClick(MOUSE_LEFT);
Result := IsTalkingTo(Name, WaitTime) or IsConversation();
end;
end;
end;

function TalkToRuneScapeGuide2(): Boolean;
var
TPA: TPointArray;
begin
if FindColorsCTS2(TPA, MSBOX, GUIDE_RED_CTS2) then
begin
Mouse(MedianTPA(TPA), MOUSE_MOVE);
if IsUpTextMulti(['RuneScape Guide', 'uide', 'cape'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := IsTalkingTo('RuneScape Guide', 4567);
end;
end;
end;

function ClickTab(Tab: TTab): Boolean;
begin
MouseBox(GridBox(Int32(Tab), 7, 2, 32, 35, 33, 298, [543, 185]), MOUSE_LEFT);
Result := True;
end;

function IsOptionsTab(): Boolean;
var
TPA: TPointArray;
begin
Result := FindTextIn(TPA, 'Advanced options', 'SmallChars07', TEXT_ORANGE, INVBOX);
end;

function AdjustBrightness(): Boolean;
begin
if IsOptionsTab() then
begin
Mouse([715, 309], MOUSE_MOVE);
if IsUpTextMulti(['djust', 'creen', 'ightn'], 1234) then
begin
FastClick(MOUSE_LEFT);
Result := True;
end;
end;
end;

function OpenDoor(): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['pen Do', 'Open Door', 'oor', 'Open', 'Door'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := True;
end;
end;
end;

function WalkToYellowArrow(): Boolean;
var
c: Int32;
TPA: TPointArray;
begin
while (not FindColorsCTS2(TPA, MMBOX, YELLOW_ARROW_CTS2)) do
begin
Wait(22);
if (Inc(c) > 22) then Exit;
end;
if InRange(Length(TPA), 30, 40) then
begin
OffsetTPA(TPA, [0, 4]);
Mouse(MedianTPA(TPA), MOUSE_LEFT);
if WaitFunc(@IsWalking, 1696, 345, True) then
while IsWalking() do
Wait(222);
Result := True;
end;
end;

function WalkToRedArrow(): Boolean;
var
c: Int32;
TPA: TPointArray;
begin
while (not FindColors(TPA, 255, MMBOX)) do
begin
Wait(22);
if (Inc(c) > 22) then Exit;
end;
if InRange(Length(TPA), 80, 90) then
begin
OffsetTPA(TPA, [-9, 0]);
Mouse(MedianTPA(TPA), MOUSE_LEFT);
if WaitFunc(@IsWalking, 1696, 345, True) then
while IsWalking() do
Wait(222);
Result := True;
end;
end;

function ChopTree(): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Chop', 'down', 'Tree', 'hop do'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := WaitForInventoryShift(12345, 969);
end;
end;
end;

function WaitXPChange(WaitTime: Int32): Boolean;
var
XP: Int32;
t: UInt32;
begin
t := GetTickCount() + WaitTime;
XP := GetXP();
repeat
Result := (GetXP() > XP);
if Result then Exit();
Wait(WaitTime div 9);
until (GetTickCount() > t);
end;

function UseItemOnItem(ItemA, ItemB: TInventoryItem): Boolean;
var
SlotA, SlotB: Int32;
begin
SlotA := ItemA.GetSlot();
SlotB := ItemB.GetSlot();
if ((SlotA + SlotB) > 1) then
begin
MouseBox(GetSlotBox(SlotA), MOUSE_MOVE);
if IsUpTextMulti(ItemA.Text, 696) then
begin
FastClick(MOUSE_LEFT);
Wait(222);
MouseBox(GetSlotBox(SlotB), MOUSE_MOVE);
if IsUpTextMulti(ItemB.Text, 696) then
begin
FastClick(MOUSE_LEFT);
Result := True;
end;
end;
end;
end;

function LightFire(): Boolean;
begin
if UseItemOnItem(Tinderbox, Logs) then
begin
Wait(444);
if WaitForInventoryShift(2345, 234) then
begin
Result := WaitXPChange(12345);
end else
begin
Mouse([300, 170], MOUSE_RIGHT);
ChooseOption(['Walk', 'here', 'lk he', 'alk h', 'k her']);
end;
end;
end;

function CatchShrimp(): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Net', 'Fishing', 'spot', 'ish'], 696) then
begin
FastClick(MOUSE_RIGHT);
if ChooseOption(['Walk', 'here']) then
begin
Wait(444);
while IsWalking() do Wait(444);
if FindYellowArrow(P) then
begin
P.Y += 30;
repeat
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Net', 'Fishing', 'spot', 'ish'], 696) then
begin
FastClick(MOUSE_LEFT);
WaitForInventoryShift(9876, 456);
end;
until (RawShrimp.Count() > 1);
Result := True;
end;
end;
end;
end;
end;

function CookShrimp(): Boolean;
var
ShrimpSlot, i: Int32;
TPA: TPointArray;
ATPA: T2DPointArray;
begin
ShrimpSlot := RawShrimp.GetSlot();
if (ShrimpSlot > 0) then
begin
if FindColorsCTS2(TPA, MSBOX, FIRE_FLAME_CTS2) then
begin
ATPA := ClusterTPA(TPA, 2);
FilterTPAsBetween(ATPA, 0, 22);
if (Length(ATPA) < 1) then Exit;
SortATPAFromMidPoint(ATPA, MSCP);
MouseBox(GetSlotBox(ShrimpSlot), MOUSE_MOVE);
if IsUpTextMulti(RawShrimp.Text, 1234) then
begin
FastClick(MOUSE_LEFT);
for i := 0 to High(ATPA) do
begin
Mouse(MedianTPA(ATPA[i]), MOUSE_MOVE);
if IsUpTextMulti(['Fire'], 696) then
begin
FastClick(MOUSE_RIGHT);
if ChooseOption(['Fire']) then
begin
Result := WaitForInventoryShift(12345, 696);
Exit;
end;
end;
end;
end
end;
end;
end;

function OpenGate(Offset: TPoint): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.X += Offset.X;
P.Y += Offset.Y;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Open', 'Gate', 'pen', 'ate'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := True;
end;
end;
end;

function CookDough(): Boolean;
var
P: TPoint;
begin
if Bread.Find() then Exit(True);
if BreadDough.Click(MOUSE_LEFT) then
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Range', 'ange', 'nge'], 696) then
begin
FastClick(MOUSE_LEFT);
Wait(444);
Result := WaitForInventoryShift(4567, 456);
end;
end;
end;
end;

function ClickYesEmote(): Boolean;
begin
MouseBox([549, 211, 590, 258], MOUSE_MOVE);
if IsUpText('Yes', 444) then
begin
FastClick(MOUSE_LEFT);
Result := True;
end;
end;

function ClickRun(): Boolean;
begin
MouseBox([599, 425, 638, 464], MOUSE_MOVE);
if IsUpText('Toggle Run', 444) then
begin
FastClick(MOUSE_LEFT);
Result := True;
end;
end;

function DescendLadder(): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Climb', 'down', 'Ladder', 'dder', 'limb'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := True;
end;
end;
end;

function WalkToMiningGuide(): Boolean;
begin
Mouse([615, 130], MOUSE_LEFT);
if WaitFunc(@IsWalking, 1444, 234, True) then
while IsWalking() do
Wait(222);
end;

function Prospect(): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Mine', 'Rocks', 'ine', 'ocks'], 696) then
begin
FastClick(MOUSE_RIGHT);
if ChooseOption(['Prospect']) then
begin
Result := WaitFunc(@IsConversation, 5678, 567, True);
end;
end;
end;
end;

function Mining(): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Mine', 'Rocks', 'ine', 'ocks'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := WaitForInventoryShift(9876, 456);
end;
end;
end;

function Smelt(): Boolean;
var
P: TPoint;
begin
if BronzeBar.Find() then Exit(True);
if TinOre.Click(MOUSE_LEFT) then
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Furnace', 'urna', 'nace'], 696) then
begin
FastClick(MOUSE_LEFT);
Wait(444);
Result := WaitForInventoryShift(4567, 456);
end;
end;
end;
end;

function IsConversation2(): Boolean;
var
TPA: TPointArray;
begin
Result := FindTextIn(TPA, 'Click to continue', 'UpChars07', TEXT_DARK_BLUE, CHATBOX);
end;

function DoConversation2(): Boolean;
var
TPA: TPointArray;
begin
if FindTextIn(TPA, 'Click to continue', 'UpChars07', TEXT_DARK_BLUE, CHATBOX) then
begin
OffsetTPA(TPA, [4, 4]);
Mouse(TPA[0], MOUSE_LEFT);
Result := WaitFunc(@IsConversation2, 2345, 234, False);
end;
end;

function IsSmithScreen(): Boolean;
var
TPA: TPointArray;
begin
Result := FindTextIn(TPA, 'would you like to make', 'UpChars07', TEXT_ORANGE, MSBOX);
end;

function SmithDagger(): Boolean;
var
TPA: TPointArray;
begin
if FindTextIn(TPA, 'Dagger', 'StatChars07', TEXT_WHITE, MSBOX) then
begin
OffsetTPA(TPA, [4, 0]);
Mouse(TPA[0], MOUSE_MOVE);
if IsUpTextMulti(['Smith', 'Bronze', 'dagger'], 1234) then
begin
FastClick(MOUSE_LEFT);
Result := WaitForInventoryShift(3456, 345);
end;
end;
end;

function Smith(): Boolean;
var
P: TPoint;
begin
if BronzeDagger.Find() then Exit(True);
if BronzeBar.Click(MOUSE_LEFT) then
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Anvil', 'nvil'], 696) then
begin
FastClick(MOUSE_LEFT);
Wait(444);
if WaitFunc(@IsSmithScreen, 2345, 234, True) then
begin
if SmithDagger() then
begin
Result := True;
end;
end;
end;
end;
end;
end;

function IsEquipScreen(): Boolean;
var
TPA: TPointArray;
begin
Result := FindTextIn(TPA, 'bonus', 'UpChars07', TEXT_ORANGE, MSBOX);
end;

function ViewEquipmentStats(): Boolean;
begin
MouseBox([554, 413, 593, 452], MOUSE_MOVE);
if IsUpTextMulti(['View', 'equipment', 'stats'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := WaitFunc(@IsEquipScreen, 2345, 234, True);
end;
end;

function CloseEquipScreen(): Boolean;
begin
if (not IsEquipScreen()) then Exit(True);
MouseBox([481, 15, 506, 37], MOUSE_MOVE);
if IsUpTextMulti(['Close', 'lose'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := WaitFunc(@IsEquipScreen, 2345, 234, False);
end;
end;

function EquipSwordAndShield(): Boolean;
begin
Result := (BronzeSword.Click() and WoodenShield.Click())
end;

function SitBackAndWatch(): Boolean;
var
TPA: TPointArray;
begin
Result := (FindTextIn(TPA, 'Sit back and watch', 'CharsNPC07', TEXT_BLUE, CHATBOX) or
FindTextIn(TPA, 'Rat ranging.', 'CharsNPC07', TEXT_BLUE, CHATBOX));
end;

function AttackRat(): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Attack', 'Giant', 'rat', 'ttac', 'iant'], 696) then
begin
FastClick(MOUSE_LEFT);
if WaitFunc(@SitBackAndWatch, 12345, 1234, True) then
begin
Result := WaitFunc(@SitBackAndWatch, 12345, 1234, False);
end;
end;
end;
end;

function ExitRatArea(): Boolean;
var
TPA: TPointArray;
ATPA: T2DPointArray;
begin
if FindColorsTolerance(TPA, 237, MMBOX, 9) then
begin
ATPA := ClusterTPA(TPA, 1);
FilterTPAsBetween(ATPA, 0, 4);
if (Length(ATPA) < 1) then Exit;
TPA := ATPA[0];
if (MedianTPA(TPA).X < MMCX) then Exit(True);
Mouse(MedianTPA(TPA), MOUSE_LEFT);
if WaitFunc(@IsWalking, 1456, 345, True) then
while IsWalking() do Wait(121);
Mouse([290, 160], MOUSE_MOVE);
if IsUpTextMulti(['Open', 'Gate', 'pen', 'ate'], 1234) then
begin
FastClick(MOUSE_LEFT);
Result := True;
end;
end;
end;

function EquipBowAndArrows(): Boolean;
begin
if ((not BronzeArrows50.Find()) and (not Shortbow.Find())) then
Exit(True);
Result := (BronzeArrows50.Click() and Shortbow.Click())
end;

function AscendLadder(): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Climb', 'up', 'Ladder', 'dder', 'limb'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := True;
end;
end;
end;

function ClickBank(): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Bank', 'ank'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := IsTalkingTo('Banker', 4567);
end;
end;
end;

function CloseBank(): Boolean;
begin
if IsBankClosed() then Exit(True);
MouseBox(BANK_CLOSE_BOX, MOUSE_MOVE);
if IsUpTextMulti(['Close', 'lose', 'Clo'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := WaitFunc(@IsBankClosed, 2345, 234, True);
end;
end;

function IsPollScreen(): Boolean;
var
TPA: TPointArray;
begin
Result := FindTextIn(TPA, 'History', 'StatChars07', TEXT_ORANGE, MSBOX);
end;

function ClickPollBooth(): Boolean;
var
P: TPoint;
begin
if FindYellowArrow(P) then
begin
P.Y += 30;
Mouse(P, MOUSE_MOVE);
if IsUpTextMulti(['Poll', 'booth', 'ooth', 'oll', 'll bo'], 696) then
begin
FastClick(MOUSE_LEFT);
if WaitFunc(@IsConversation, 3456, 345, True) then
begin
if DoConversation() then
begin
Result := WaitFunc(@IsPollScreen, 2345, 234, True);
end;
end;
end;
end;
end;

function WalkToChapel(): Boolean;
var
i: Int32;
TPA: TPointArray;
ATPA: T2DPointArray;
begin
if FindColorsTolerance(TPA, 237, MMBOX, 9) then
begin
ATPA := ClusterTPA(TPA, 1);
FilterTPAsBetween(ATPA, 0, 7);
if (Length(ATPA) <> 1) then Exit;
Mouse(MedianTPA(ATPA[0]), MOUSE_LEFT);
if WaitFunc(@IsWalking, 1696, 456, True) then
while IsWalking() do Wait(234);
Result := True;
end;
end;

function OpenChapelDoor(): Boolean;
begin
Mouse([240, 169], MOUSE_MOVE);
if IsUpText('Open', 696) then
begin
FastClick(MOUSE_LEFT);
Wait(969);
end;
Result := True;
end;

function StrikeChicken(): Boolean;
var
i: Int32;
TPA: TPointArray;
ATPA: T2DPointArray;
begin
MouseBox([583, 220, 606, 243], MOUSE_MOVE);
if IsUpTextMulti(['Wind', 'Strike', 'ind', 'trike'], 696) then
begin
FastClick(MOUSE_LEFT);
if FindColorsCTS2(TPA, MSBOX, CHICKEN_CTS2) then
begin
ATPA := ClusterTPA(TPA, 2);
FilterTPAsBetween(ATPA, 0, 22);
if (Length(ATPA) < 1) then Exit;
SortATPAFromMidPoint(ATPA, MSCP);
for i := 0 to High(ATPA) do
begin
Mouse(MedianTPA(ATPA[i]), MOUSE_MOVE);
if IsUpTextMulti(['Chicken', 'hick', 'cken'], 444) then
begin
FastClick(MOUSE_LEFT);
Result := WaitXPChange(4567);
end;
end;
end;
end;
end;

function IsRunOn(): Boolean;
const
COLOR = 6998507;
TOL = 55;
B: TBox = [570, 127, 590, 147];
begin
Result := (CountColorTolerance(COLOR, B, TOL) > 69);
end;

function MMClickRun(): Boolean;
const
B: TBox = [544, 126, 593, 151];
begin
MouseBox(B, MOUSE_MOVE);
if IsUpTextMulti(['Toggle', 'Run', 'oggle', 'ggle'], 696) then
begin
FastClick(MOUSE_LEFT);
Result := True;
end;
end;

function GetTutorialStage(): Int32;
var
i: Int32;
TPA: TPointArray;
begin
for i := 0 to High(TUTORIAL_STAGES) do
begin
if (FindTextIn(TPA, TUTORIAL_STAGES[i], 'CharsNPC07', TEXT_BLUE, CHATBOX) or
FindTextIn(TPA, TUTORIAL_STAGES[i], 'CharsNPC07', TEXT_BLACK, CHATBOX)) then
Exit(i);
end;
Result := -1;
end;

function Finished(): Boolean;
var
TPA: TPointArray;
begin
Result := FindTextIn(TPA, '*', 'SmallChars07', TEXT_BLUE, CHATBOX);
end;

procedure Setup();
var
w, h: Int32;
begin
GetClientDimensions(w, h);
if ((w <> FIXED_WIDTH) or (h <> FIXED_HEIGHT)) then
begin
WriteLn('client dimensions are wrong');
TerminateScript();
end;

UpFont.Load('UpChars07_s');
OCR.Init(UpFont);


if (not IsLoggedIn()) then DoLogin(LOGIN, PASSWORD, WORLDS[Random(High(WORLDS))]);
if (not WaitFunc(@IsLoggedIn, 9876, 678, True)) then TerminateScript();
ResetCamera(); Wait(444);
if (not IsXPOpen()) then MouseBox(MM_XP_DROP_BOX, MOUSE_LEFT);
if (not IsRunOn()) then MMClickRun();
end;

procedure Mainloop();
begin
case GetTutorialStage() of
-1:
begin
if Finished() then TerminateScript();
Wait(444);
DoConversation();
DoConversation2();
end;

0: //design character and talk to guide
begin
if IsDesignScreen() then
if DoDesignScreen(RANDOMCHARACTER) then
Wait(444);

if (not IsXPOpen()) then MouseBox(MM_XP_DROP_BOX, MOUSE_LEFT);

if TalkToNPC('RuneScape Guide', ['RuneScape', 'Guide', 'uneSc', 'uide'], 4567) then
if DoConversation(['I am an experienced player']) then Wait(444);
end;

1: //player controls
begin
if ClickTab(Options) then Wait(444);
if WaitFunc(@IsOptionsTab, 1234, 234, True) then
if AdjustBrightness() then
Wait(444);
end;

2: //talk to guide again, no arrow this time
begin
if TalkToRuneScapeGuide2() then
if DoConversation() then
Wait(444);
end;

3, 14, 19, 50, 52, 59: //open door
begin
if (not IsRunOn()) then
if MMClickRun() then
Wait(444);
if OpenDoor() then
begin
if WaitFunc(@IsWalking, 1234, 234, True) then
while IsWalking() do
Wait(222);
end else
if WalkToYellowArrow() then
Wait(444);
end;

4: //walk and talk to surivival
begin
if TalkToNPC('Survival Expert', ['Survival', 'Expert', 'urviv', 'pert'], 4567) then
begin
if DoConversation() then
Wait(444);
end else
if WalkToYellowArrow() then
Wait(444);
end;

5: //click inventory
begin
if ClickTab(Inventory) then
Wait(444);
end;

6: //cut down a tree
begin
if ChopTree() then
if DoConversation() then
Wait(444);
end;

7: //making a fire
begin
if LightFire() then
Wait(444);
end;

8: //click stats
begin
ClickTab(Stats);
end;

9: //speak to survival expert again
begin
if TalkToNPC('Survival Expert', ['Survival', 'Expert', 'urviv', 'pert'], 4567) then
begin
if DoConversation() then
Wait(444);
end else
if WalkToYellowArrow()
then Wait(444);
end;

10: //catch some shrimp
begin
if ClickTab(Inventory) then
Wait(444);
if WalkToYellowArrow() then
if CatchShrimp() then
Wait(444);
end;

11, 12: //cook shrimp
begin
if CookShrimp() then
Wait(444);
end;

13, 35: //walk to and open gate
begin
if WalkToYellowArrow() then
begin
if OpenGate([-4, 30]) then
begin
Wait(999);
while IsWalking() do
Wait(444);
end;
end;
end;

15: //talk to master chef
begin
if TalkToNPC('Master Chef', ['Master', 'Chef', 'aste', 'hef'], 4567) then
if DoConversation() then
Wait(444);
end;

16: //making dough
begin
ClickTab(Inventory);
if UseItemOnItem(PotOfFlour, BucketOfWater) then
Wait(696);
end;

17: //cooking dough
begin
if (not CookDough()) then
WalkToYellowArrow() else
Wait(696);
end;

18: //click music tab
begin
if ClickTab(MusicPlayer) then
Wait(444);
end;

20: //emotes
begin
if ClickTab(Emotes) then
begin
Wait(224);
if ClickYesEmote() then
Wait(969);
end;
end;

21: //running
begin
if ClickTab(Options) then
begin
Wait(444);
if ClickRun() then
Wait(969);
end;
end;

22: //run to next guide
begin
if WalkToYellowArrow() then
begin
if OpenDoor() then
begin
Wait(696);
while IsWalking() do
Wait(222);
end;
end else
if WalkToRedArrow() then
Wait(444);
end;

23, 25: //talk to quest guide
begin
if TalkToNPC('Quest Guide', ['Quest', 'Guide', 'uest', 'uide'], 4567) then
begin
if DoConversation() then
Wait(444);
end else
if WalkToYellowArrow() then
Wait(444);
end;

24: //open the quest journal
begin
if ClickTab(QuestList) then
Wait(444);
end;

26: //go down ladder
begin
if DescendLadder() then
Wait(2345) else
if WalkToYellowArrow() then
Wait(444);
end;

27, 30, 33: //talk to mining instructor
begin
if TalkToNPC('Mining Instructor', ['Mining', 'Instructor', 'ining', 'nstr'], 2345) then
begin
if DoConversation() then
Wait(444);
end else
if WalkToYellowArrow() then
Wait(444) else
if WalkToRedArrow() then
Wait(444) else
if WalkToMiningGuide() then
Wait(444);
end;

28, 29: //prospecting
begin
if Prospect() then
begin
if DoConversation() then
Wait(444);
end else
if WalkToYellowArrow() then
Wait(444);
end;

31: //mining
begin
if ClickTab(Inventory) then
if Mining() then
begin
if DoConversation() then
Wait(696);
end else
if WalkToYellowArrow() then
Wait(444);
end;

32: //smelting
begin
if WalkToYellowArrow() then
if Smelt() then
if DoConversation2() then
Wait(444);
end;

34: //smith a dagger
begin
if WalkToYellowArrow() then
if Smith() then
Wait(444);
end;

36: //talk to combat instructor
begin
if (not TalkToNPC('Combat Instructor', ['Combat', 'Instructor', 'omba', 'nstr'], 2345)) then
WalkToYellowArrow() else
if DoConversation() then
Wait(444);
end;

37: //click equip tab
begin
if ClickTab(WornEquipment) then
Wait(696);
end;

38: //view equip stats
begin
if ViewEquipmentStats() then
Wait(696);
end;

39: //equip dagger
begin
if IsEquipScreen() then
if BronzeDagger.Click() then
Wait(696);
end;

40: //talk to comabt instructor again
begin
if CloseEquipScreen() then
if TalkToNPC('Combat Instructor', ['Combat', 'Instructor', 'omba', 'nstr'], 2345) then
begin
if DoConversation() then
Wait(696);
end else
if WalkToYellowArrow() then
Wait(696);
end;

41: //equip sword and shield
begin
if ClickTab(Inventory) then
if EquipSwordAndShield() then
Wait(696);
end;

42: //combat interface
begin
if ClickTab(CombatOptions) then
Wait(696);
end;

43: //gate
begin
if WalkToYellowArrow() then
begin
Wait(444);
if OpenGate([1, 20]) then
begin
Wait(444, 696);
while IsWalking() do Wait(444);
end;
end;
end;

44: //attack rat
begin
if AttackRat() then
Wait(696) else
if WalkToYellowArrow() then
Wait(696);
end;

45: //exit rat area and comabt instructor again
begin
if ExitRatArea() then
begin
Wait(1234);
if WalkToYellowArrow() then
if TalkToNPC('Combat Instructor', ['Combat', 'Instructor', 'omba', 'nstr'], 2345) then
if DoConversation() then
Wait(444);
end;
end;

46: //rat ranging
begin
if ClickTab(Inventory) then Wait(444);
if EquipBowAndArrows() then
Wait(696) else
Exit;
if (not AttackRat()) then
if WalkToYellowArrow() then
Wait(444);
end;

47: //climb ladder
begin
if (not AscendLadder()) then
WalkToYellowArrow() else
Wait(2345);
end;

48: //banking
begin
if (not ClickBank()) then
WalkToYellowArrow() else
if DoConversation(['Yes']) then
if IsBankOpen() then
Wait(696);
end;

49: //close bank
begin
if CloseBank() then
if ClickPollBooth() then
Wait(696);
end;

51: //talk to financial advisor
begin
if TalkToNPC('Financial Advisor', ['Financial', 'Advisor', 'inanc', 'dviso'], 2345) then
if DoConversation() then
Wait(696);
end;

53: //prayer
begin
if WalkToChapel() then
if OpenChapelDoor() then
if TalkToNPC('Brother Brace', ['Brother', 'Brace', 'rothe', 'race'], 2345) then
begin
if DoConversation() then
Wait(696);
end else
if WalkToYellowArrow() then
Wait(444);
end;

54: //click prayer tab
begin
if ClickTab(Prayer) then
Wait(444);
end;

55, 58: //talk to brother again
begin
if TalkToNPC('Brother Brace', ['Brother', 'Brace', 'rothe', 'race'], 2345) then
DoConversation() else
if WalkToYellowArrow() then
Wait(696);
end;

56: //click friends tab
begin
if ClickTab(FriendsList) then
Wait(444);
end;

57: //click ignore tab
begin
if ClickTab(IgnoreList) then
Wait(444);
end;

60, 63: //walk and talk to magic instructor
begin
if TalkToNPC('Magic Instructor', ['Magic', 'Instructor', 'agic', 'nstru'], 2345) then
DoConversation(['Yes.', 'No, I''m not planning to do that.']) else
if (not WalkToYellowArrow()) then
if (not WalkToRedArrow()) then
begin
Mouse([662, 132], MOUSE_LEFT);
if WaitFunc(@IsWalking, 1696, 345, True) then
while IsWalking() do
Wait(222);
end;
end;

61: //click magic tab
begin
if ClickTab(Magic) then
if WaitFunc(@IsConversation, 2345, 456, True) then
if DoConversation() then
Wait(696);
end;

62: //cast wind strike
begin
if ClickTab(Magic) then
if StrikeChicken() then
Wait(1234);
end;

end;
Wait(444);
end;

begin
ClearDebug();
Setup();
while IsLoggedIn() do Mainloop();
end.

icyxen
02-19-2018, 06:21 AM
Awesome, will test tomorrow.

P1nky
02-19-2018, 02:39 PM
Thanks Citrus! I'll tweak the script if needed.

icyxen
02-19-2018, 08:12 PM
First of all, very well done.

Secondly, it did manage to get stuck during the banking and poll booth part.

At the banking part it walked to the right of teller, and would loop attempting to click the booth but it aimed too high.

After I manually clicked the booth, because of the location it was stuck and wouldn't click the poll booth.

Other than that no issues, thank for release again.

Citrus
02-20-2018, 12:56 AM
First of all, very well done.

Secondly, it did manage to get stuck during the banking and poll booth part.

At the banking part it walked to the right of teller, and would loop attempting to click the booth but it aimed too high.

After I manually clicked the booth, because of the location it was stuck and wouldn't click the poll booth.

Other than that no issues, thank for release again.

Thanks for the feedback. I never had that issue with the bank, but I'll look into it.

slacky
02-20-2018, 04:29 AM
> Standalone
> Uses a plugin that has only ever been shipped with aerolib
Pick 1

> Improvements should be easy to implement
> Uses no includes
Pick 1


Good effort tho, skeptical about the idea of not using any include when they are right there, available, and even needed since you use rstext.dll.

Citrus
02-20-2018, 05:02 AM
> Standalone
> Uses a plugin that has only ever been shipped with aerolib
Pick 1

> Improvements should be easy to implement
> Uses no includes
Pick 1


Good effort tho, skeptical about the idea of not using any include when they are right there, available, and even needed since you use rstext.dll.

Oh, I thought rstext was just a 'default' Simba plugin. :confused:

The whole no include thing is a half-truth. Really I just gutted my own include and only left in things that were actually used. I want to be able to run the script without having to worry about downloading the latest version of whatever.
I also meant that improvements would be easy for me to implement.
The improvements I had in mind were e.g. using standard color-finding methods to click objects and NPCs instead of the big yellow arrow. Some of this is already in the script and it would just be a matter of taking the time to write more.

Smalfinn
02-20-2018, 10:34 AM
I'm getting the error below:

Error: Access violation at line 325
Execution failed.

underforu
02-21-2018, 03:27 AM
looks sweet will try it soon

Citrus
02-21-2018, 09:02 AM
I'm getting the error below:

Error: Access violation at line 325
Execution failed.

I'm not sure why that's happening to you, but I made a couple changes to the script, so try the current version.

Smalfinn
02-21-2018, 09:58 AM
I'm not sure why that's happening to you, but I made a couple changes to the script, so try the current version.

Okay fresh install of Simba with your new version and now I get this error:

Error: Out of memory at line 183
Execution failed.

Citrus
02-21-2018, 10:30 AM
Okay fresh install of Simba with your new version and now I get this error:

Error: Out of memory at line 183
Execution failed.

Sorry, I still don't know what the problem is. Can you give any more information? Does error happen immediately, or after a few seconds?

Smalfinn
02-21-2018, 10:33 AM
Sorry, I still don't know what the problem is. Can you give any more information? Does error happen immediately, or after a few seconds?

I fill in the settings, the script loads and logs me in, raises the camera angle then throws that error.

Citrus
02-21-2018, 10:40 AM
I fill in the settings, the script loads and logs me in, raises the camera angle then throws that error.

Have you tried starting the script after you're already logged in?

One potential issue: make sure you log in manually at least once on the client before starting the script.

Smalfinn
02-21-2018, 11:06 AM
Have you tried starting the script after you're already logged in?

Okay so no more out of memory, I now have:

ERROR comes from a non-existing file (!addDelayedCore)
Error: Access violation at line 103
Execution failed.

Just tried again after a plugin update to a different error too:

Error: Access violation at line 325
Execution failed.
Exception TLPThread.Destroy: Access violation

Citrus
02-21-2018, 11:41 AM
Okay so no more out of memory, I now have:

ERROR comes from a non-existing file (!addDelayedCore)
Error: Access violation at line 103
Execution failed.

Just tried again after a plugin update to a different error too:

Error: Access violation at line 325
Execution failed.
Exception TLPThread.Destroy: Access violation

Alright another update. RsText is out, SimpleOCR is in. I did another run and tweaked a few other things too.

Smalfinn
02-21-2018, 07:06 PM
Alright another update. RsText is out, SimpleOCR is in. I did another run and tweaked a few other things too.

IT WORKS PERFECTLY! A few things; Any plans to move to SMART, holding down space bar would go through text a lot faster then clicking continue, but other then that really good little script.

Citrus
02-21-2018, 11:16 PM
IT WORKS PERFECTLY! A few things; Any plans to move to SMART, holding down space bar would go through text a lot faster then clicking continue, but other then that really good little script.

Glad it works! I would have used SimpleOCR from the start, but it never worked until I redownloaded it yesterday.

I'll consider adding an option for SMART, but tbh it's a low priority at this point. I'll do some testing with using spacebar when I have the time.

icyxen
02-22-2018, 03:25 AM
IMO it's good enough without spacebar takes no more than 10 minutes to complete tutorial island, way faster than anything else.

gay_retard
12-30-2018, 07:19 PM
Script is broken. Tried in official Client and RuneLite

It detects the Client, sets Compass to North, opens up the XP meter and then hangs over the Run Energy bubble until I manually continue the tutorial.

If I open up a text Window (talking, something that requires you to click 'next' or use spacebar to continue) it starts clicking the 'continue' button.

It requires you to be logged in, it does not Select a world, but it does open up the world Select menu.

1. Set display name and do tutorial until settings are configured according to this https://villavu.com/forum/showthread.php?t=118223&p=1391739#post1391739 post.
2. Talk to Gielinor Guide and then run the script
3. Wait until it bugs out, open the door, it takes over again and runs to the Survival Expert
4. After about a minute of the script trying to click the NPC, it finally clicks her, finishes the dialogue, then stops again
5. Have to manually Cook shrimp

at this point I don't think it's Worth continuing trying so I just bail on it.

Maybe it's because of some updates, but it's at least outdated, at worst broken. :(