#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SendMode Input ; Recommended for new scripts due to its superior speed and reliability. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. ; XOff and YOff need to be global variables ; All coordinates in any function need to have XOff and YOff ; removed from them in order to be universally compatible ; These are only relevant for Orion, otherwise use LaunchRS() OrionOffset() { WinActivate, Orion WinWaitActive, Orion WinGetActiveStats, T, W, H, X, Y XOff := X + 5 YOff := Y + 52 } ; Only run this if you want something random to happen ; Area = X1 | Y1 | W | H, RClick should be true if random right clicks are acceptable ; LClick should be true if random left clicks are acceptable, hRandom will try to undo any fuckups (Banking/Use-item/ect...) ; STab should be true if hRandom is allowed to randomly switch tabs to view things hRandom(Area, RClick, LClick, STab) { } ; Moves your mouse over your chat box when the box to create an item is open. MakeItem(Pos := 1, Amount := 1) { If (tTemp := RSeed(0, 1)) { Loop { Image := Gdip_BitmapFromScreen(505 + XOff "|" 360 + YOff "|1|1") If !(ColorMatch(Gdip_GetPixel(Image, 0, 0), Black, SubStr(Delimiters, 2, 1))) Break Gdip_DisposeImage(Image) } Gdip_DisposeImage(Image) } If (Amount = 1) hMovement(78 + XOff SubStr(Delimiters, 1, 1) 379 + YOff SubStr(Delimiters, 1, 1) 362 SubStr(Delimiters, 1, 1) 78) Else If (Amount = 3) { If (Pos = 1) hMovement(21 + XOff SubStr(Delimiters, 1, 1) 377 + YOff SubStr(Delimiters, 1, 1) 159 SubStr(Delimiters, 1, 1) 78) Else If (Pos = 2) hMovement(191 + XOff SubStr(Delimiters, 1, 1) 372 + YOff SubStr(Delimiters, 1, 1) 137 SubStr(Delimiters, 1, 1) 84) Else If (Pos = 3) hMovement(335 + XOff SubStr(Delimiters, 1, 1) 375 + YOff SubStr(Delimiters, 1, 1) 159 SubStr(Delimiters, 1, 1) 81) } Else If (Amount = 4) { If (Pos = 1) hMovement(22 + XOff SubStr(Delimiters, 1, 1) 378 + YOff SubStr(Delimiters, 1, 1) 112 SubStr(Delimiters, 1, 1) 79) Else If (Pos = 2) hMovement(136 + XOff SubStr(Delimiters, 1, 1) 377 + YOff SubStr(Delimiters, 1, 1) 118 SubStr(Delimiters, 1, 1) 80) Else If (Pos = 3) hMovement(255 + XOff SubStr(Delimiters, 1, 1) 377 + YOff SubStr(Delimiters, 1, 1) 120 SubStr(Delimiters, 1, 1) 80) Else If (Pos = 4) hMovement(376 + XOff SubStr(Delimiters, 1, 1) 377 + YOff SubStr(Delimiters, 1, 1) 119 SubStr(Delimiters, 1, 1) 80) } If !(tTemp) { Loop { Image := Gdip_BitmapFromScreen(505 + XOff "|" 360 + YOff "|1|1") If !(ColorMatch(Gdip_GetPixel(Image, 0, 0), Black, SubStr(Delimiters, 2, 1))) Break Gdip_DisposeImage(Image) } Gdip_DisposeImage(Image) } } ; Previous contains area data in the form: "X-Y|X-Y..." ; Text should contain the text data the examine area should contain for the loop to end ; Color refers to the color of the text the script will read using QuickText SearchGrid(Previous, Text, Color) { Tooltip, Search beginning, XOff - 5, YOff - 52 If InStr(Examine(Color), Text) AND (Previous = "") { MouseGetPos, MX, MY Return Previous := MX - XOff SubStr(Delimiters, 2, 1) MY - YOff } Loop { Coord := ReturnPos(Previous, RSeed(1, CountVarBy(Previous, SubStr(Delimiters, 1, 1))), SubStr(Delimiters, 1, 1)) hMovement(ReturnPos(Coord, 1, SubStr(Delimiters, 2, 1)) + Round(RandomSkew(Alpha, 5)) + XOff SubStr(Delimiters, 1, 1) ReturnPos(Coord, 2, SubStr(Delimiters, 2, 1)) + Round(RandomSkew(Alpha, 5)) + YOff SubStr(Delimiters, 1, 1) 1 SubStr(Delimiters, 1, 1) 1) Sleep % Round(Abs(RandomSkew(Alpha, 75))) + 50 MouseGetPos, MX, MY If InStr(Examine(Color), Text) { If !InString(Previous, MX - XOff SubStr(Delimiters, 2, 1) MY - YOff, SubStr(Delimiters, 1, 1)) Previous .= SubStr(Delimiters, 1, 1) MX - XOff SubStr(Delimiters, 2, 1) MY - YOff Break } Else RPLInstance(Previous, Coord, SubStr(Delimiters, 1, 1)) } Tooltip, Search Ending, XOff - 5, YOff - 52 Return Previous } ; Banklist should contain inputs for QuickBankInteract ; Use should contain the horizontal inventory position of an item to click-use ; UseOn should contain the horizontal inventory position of an item to use the prior item on ; Make should contain the chatbox item you want to interact with using MakeIem() ; MakeLen should contain the total number of items in the chatbox interaction ; Interchangeable is true if you can use either set of items on the other BankStanding(Record, BankList, Use := 1, UseOn := 28, Make := 1, MakeLen := 1, Type := 0) { If !InStr(Examine(White), "Bank") SearchGrid(Record, "Bank", White) Send("LButton", 0, Round(Abs(RandomSkew(Alpha, 50))) + 30, Round(Abs(RandomSkew(Alpha, 50))) + 30) Thresh := QuickBankInteract(BankList) hrMovement(Inventory(Use, 1)) Loop { If InStr(QuickText(XOff + 8 "|" YOff + 9 "|" 50 "|" 11, White, Section, 4, 50), "Use") Break Sleep % Round(Abs(RandomSkew(Alpha, 50))) + 30 } Send("LButton", Round(Abs(RandomSkew(Alpha, 50))) + 30, Round(Abs(RandomSkew(Alpha, 50))) + 30, Round(Abs(RandomSkew(Alpha, 50))) + 30) If (UseOn <> "") { Loop { If (Floor(A_Index / 4) = Ceil(A_Index / 4)) Send("LButton", Round(Abs(RandomSkew(Alpha, 50))) + 30, Round(Abs(RandomSkew(Alpha, 50))) + 30, Round(Abs(RandomSkew(Alpha, 50))) + 30) If InStr(QuickText(XOff + 8 "|" YOff + 9 "|" 500 "|" 11, White, Section, 4, 150), "->") Break Sleep % Round(Abs(RandomSkew(Alpha, 50))) + 30 } hrMovement(Inventory(UseOn, 1)) WaitContains(Inventory(UseOn, 1), Grey, RSeed(200, 500), 0, 1) Send("LButton", Round(Abs(RandomSkew(Alpha, 50))) + 30, Round(Abs(RandomSkew(Alpha, 50))) + 30, Round(Abs(RandomSkew(Alpha, 50))) + 30) MakeItem(Make, MakeLen) If (RSeed(1, 20) = 20) RCMenu("MakeX", White), Type := 1 Else QuickRCMenu(4, 5, 100) Start := A_TickCount If (Type) { Sleep % RSeed(600, 1000) Loop { If (sTemp := QuickText(XOff + 205 "|" YOff + 396 "|" 105 "|" 11, Black, Section, 4, 345) = "EnterAmount:") OR (A_TickCount - Start > 4000) { Sleep % RSeed(50, 600) Type(RSeed(3, 9) RSeed(0, 9) "{Enter}", RSeed(150, 300)) Break } Sleep % RSeed(200, 400) } } } If (Thresh) Return 0 Else Return Record } ; Returns the specifically colored text currently in your chat box. Pos 1 is the most recent line of text. ChatBox(Colors, Pos := 1) { Pos := ((Pos > 8) ? 8 : Pos) Return QuickText(XOff + 9 "|" YOff + 445 - ((Pos - 1) * 14) "|" 487 "|" 11, Colors, tSection, 3, 70) } ; Returns the specifically colored text currently in your examine area. Examine(Colors) { Return QuickText(XOff + 8 "|" YOff + 9 "|" 500 "|" 11, Colors, Section, 4, 70) } HPOrb() { Return QuickText(XOff + 522 "|" YOff + 58 "|" 16 "|" 9, Green SubStr(Delimiters, 1, 1) Red SubStr(Delimiters, 1, 1) Orange SubStr(Delimiters, 1, 1) Yellow, SubSection, 4, 16) } ; Same as hMovement except it will expand the area and click if that click performs no action, ; Or it will right click and then move to close the menu hrMovement(Area, Total := "", Iterations := "", FalseActs := 1) { hMovement(ReturnPos(Area, 1, SubStr(Delimiters, 1, 1)) - Round(ReturnPos(Area, 3, SubStr(Delimiters, 1, 1)) * .1) SubStr(Delimiters, 1, 1) ReturnPos(Area, 2, SubStr(Delimiters, 1, 1)) - Round(ReturnPos(Area, 4, SubStr(Delimiters, 1, 1)) * .1) SubStr(Delimiters, 1, 1) ReturnPos(Area, 3, SubStr(Delimiters, 1, 1)) + Round(ReturnPos(Area, 3, SubStr(Delimiters, 1, 1)) * .1) SubStr(Delimiters, 1, 1) ReturnPos(Area, 4, SubStr(Delimiters, 1, 1)) + Round(ReturnPos(Area, 4, SubStr(Delimiters, 1, 1)) * .1), Total, Iterations, FalseActs) MouseGetPos, MX, MY If (MX < ReturnPos(Area, 1, SubStr(Delimiters, 1, 1))) OR (MY < ReturnPos(Area, 2, SubStr(Delimiters, 1, 1))) OR (MX > ReturnPos(Area, 1, SubStr(Delimiters, 1, 1)) + ReturnPos(Area, 3, SubStr(Delimiters, 1, 1))) OR (MY > ReturnPos(Area, 2, SubStr(Delimiters, 1, 1)) + ReturnPos(Area, 4, SubStr(Delimiters, 1, 1))) { Sleep % Round(Abs(RandomSkew(Alpha, 50))) + 50 If (Examine(White) = "") AND (RSeed(0, 1)) Send("LButton", 0, Round(Abs(RandomSkew(Alpha, 50))) + 30, Round(Abs(RandomSkew(Alpha, 50))) + 30) hMovement(Area,,, FalseActs) } If (RSeed(1, 20) = 20) { Send("RButton", 0, Round(Abs(RandomSkew(Alpha, 50))) + 30, Round(Abs(RandomSkew(Alpha, 50))) + 30) hMovement(MX - 30 SubStr(Delimiters, 1, 1) MY - 80 SubStr(Delimiters, 1, 1) 60 SubStr(Delimiters, 1, 1) 40) hMovement(Area,,, FalseActs) } } ; Area := X1|Y1|W|H, Event := Colors|All|False|X1|Y1|X2|Y2 ; Total and Iterations are used to determine the average time a movement should take ; If FalseActs is true then there may be stops between the start and end points ; Returns a new total time, Iterations should be incremented outside this function as well hMovement(Area, Total := "", Iterations := "", FalseActs := 1) { BlockInput, MouseMove MouseGetPos, MX, MY Start := A_TickCount PrevX := MX, PrevY := MY Loop, Parse, Area, % SubStr(Delimiters, 1, 1) Area%A_Index% := ((A_Index <= 2) ? A_LoopField : ReturnPos(Area, A_Index - 2, SubStr(Delimiters, 1, 1)) + A_LoopField) If (MX >= Area1) AND (MX <= Area3) AND (MY >= Area2) AND (MY <= Area4) AND (RSeed(1, 2) = 1) Return ODX := DX := RSeed(Area1, Area3), ODY := DY := RSeed(Area2, Area4, 1) If (Total = "") OR (Iterations = "") Total := (RSeed(6, 10) / 10) * Distance(MX, MY, DX, DY), Iterations := 1 mList .= DX SubStr(Delimiters, 2, 1) DY Loop { oRemainder := Remainder := Total / Iterations, oIndex := A_Index Loop, Parse, mList, % SubStr(Delimiters, 1, 1) { nX := ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2, 1)), nY := ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2, 1)) If (A_Index - CountVarBy(mList, SubStr(Delimiters, 1, 1)) = 0) AND (FalseActs) { DX := RandomSkew(Alpha, oIndex * 25) + ODX, DY := RandomSkew(Alpha, oIndex * 25 + ODY) Remainder := Remainder - lTime := Round(RSeed(250, 700) / 1000 * Distance(PrevX, PrevY, DX, DY)) Remainder := Remainder - tTime := RSeed(250, 700) / 1000 * Distance(DX, DY, nX, nY) If (Remainder >= 50) mList .= SubStr(Delimiters, 1, 1) Round(DX) SubStr(Delimiters, 2, 1) Round(DY), tList .= Round(tTime) SubStr(Delimiters, 1, 1) Break } Else Remainder := Remainder - ReturnPos(tList, A_Index, SubStr(Delimiters, 1, 1)) } If (RSeed(1, 7 - A_Index) = 1) OR (Remainder < 50) OR !(FalseActs) Break } Loop, % CountVarBy(mList, SubStr(Delimiters, 1, 1)) { LoopField := ReturnPos(mList, CountVarBy(mList, SubStr(Delimiters, 1, 1)) - A_Index + 1, SubStr(Delimiters, 1, 1)) MouseGetPos, MXN, MYN If (Remainder > 0) { Sleep, % tSleep := ((RSeed(1, 2) = 1) ? 0 : RSeed(15, Remainder)) Remainder := Remainder - tSleep } gtX := ReturnPos(LoopField, 1, SubStr(Delimiters, 2, 1)), gtY := ReturnPos(LoopField, 2, SubStr(Delimiters, 2, 1)) gtX := ((gtX < 0 OR gtX > A_ScreenWidth) ? ((gtX < 0) ? 0 : A_ScreenWidth) : gtX), gtY := ((gtY < 0 OR gtY > A_ScreenHeight) ? ((gtY < 0) ? 0 : A_ScreenHeight) : gtY) If (MXN = ReturnPos(LoopField, 1, SubStr(Delimiters, 2, 1))) OR (MYN = ReturnPos(LoopField, 1, SubStr(Delimiters, 2, 1))) RandomBezier(0, 0, gtX, gtY, "OT0 OB0 OL0 OR0 RO P2-5 T" tMove := ((A_Index = 1) ? lTime : ReturnPos(tList, CountVarBy(mList, SubStr(Delimiters, 1, 1)) - A_Index + 1, SubStr(Delimiters, 1, 1)))) Else MouseMove("x" gtX " y" gtY " t" tMove := ((A_Index = 1) ? lTime : ReturnPos(tList, CountVarBy(mList, SubStr(Delimiters, 1, 1)) - A_Index + 1, SubStr(Delimiters, 1, 1)))) } Sleep, % ((Abs(Remainder) < 15) ? RSeed(15, 50) : RSeed(15, Round(Abs(Remainder)))) BlockInput, MouseMoveOff Return A_TickCount - Start + Total } ; ItemName-Amount-Noted (Boolean, 1 or 0)| ; Redefines global Inventory variable accordingly DepositBoxInteract(DList) { NewInv := Inventory StringReplace, DList, DList, % A_Space,, All Loop { If (QuickText(XOff + 145 "|" YOff + 36 "|" 250 "|" 11, Orange, Section, 4, 20) = "TheBankofRuneScape-DepositBox") Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 50) } Loop, Parse, DList, % SubStr(Delimiters, 1, 1) { LoopField := A_LoopField Loop, Parse, NewInv, % SubStr(Delimiters, 1, 1) If (A_LoopField = ReturnPos(LoopField, 1, SubStr(Delimiters, 2))) OR RegExMatch(A_LoopField, "i)([0-9]+)([+]" ReturnPos(LoopField, 1, SubStr(Delimiters, 2)) ")([" SubStr(Delimiters, 1, 1) "]|$)") AND ReturnPos(LoopField, 3, SubStr(Delimiters, 2)) { InvPos := A_Index Amount := DepositBoxGUI(A_Index, 1) Break } If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = 1) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Else If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = 5) QuickRCMenu(2, 7) Else If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = 10) QuickRCMenu(3, 7) Else If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "All") QuickRCMenu(4, 7) Else If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) > 1) { QuickRCMenu(5, 7) Loop { If (QuickText(XOff + 205 "|" YOff + 396 "|" 105 "|" 11, Black, Section, 4, 345) = "EnterAmount:") Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 50) } Type(ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) "{Enter}") WaitContains(DepositBoxGUI(InvPos), "55-85-50-75-40-70", RSeed(200, 300), 0) } If ReturnPos(A_LoopField, 3, SubStr(Delimiters, 2)) StringReplace, NewInv, NewInv, % ReturnPos(NewInv, InvPos, SubStr(Delimiters, 1, 1)), % ((Amount - ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) > 0) ? Amount - ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) "+" ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) : "") Else NewInv := RPLInstance(NewInv, ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)), SubStr(Delimiters, 1, 1),, ((ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "All") ? 28 : ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)))) } hMovement(XOff + 421 SubStr(Delimiters, 1, 1) YOff + 30 SubStr(Delimiters, 1, 1) 25 SubStr(Delimiters, 1, 1) 30) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Loop { If (QuickText(XOff + 145 "|" YOff + 36 "|" 250 "|" 11, Orange, Section, 4, 20) <> "TheBankofRuneScape-DepositBox") Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 50) } Return Inventory := NewInv } ; Bank must be open prior to start, closes bank and waits for close after execution. ; List should contain any number of: ; D - Inventory Position Horizontal - Right Click Menu Position ; W - Bank GUI Position Horizontal & at top row - Right Click Menu Position - Threshold (Optional, if the item drops below this the function returns a 1) ; DB - Deposit Box GUI Position - Right Click Menu Position ; Each interaction should be separated by |, can occur in any order. ; EX: QuickBankInteract("D-9-5|W-6-5-2000|D-3-8|W-20-6|DB-8-5") QuickBankInteract(List) { If (rTemp := RSeed(0, 3)) { Loop { Text := ((ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) = "DB") ? QuickText(XOff + 145 "|" YOff + 36 "|" 250 "|" 11, "155-255-110-170-30-130", Section, 4, 20) : QuickText(XOff + 183 "|" YOff + 36 "|" 155 "|" 11, "155-255-110-170-30-130", Section, 4, 156)) If (Text = "TheBankofRuneScape") Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 50) } } Loop, Parse, List, % SubStr(Delimiters, 1, 1) { If (ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) = "D") hMovement(Inventory(ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)), 1)) Else If (ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) = "W") hMovement(BankGUI(ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)))) Else If (ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) = "DB") hMovement(DepositBoxGUI(ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)))) If (rTemp = 0) { Loop { Text := ((ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) = "DB") ? QuickText(XOff + 145 "|" YOff + 36 "|" 250 "|" 11, "155-255-110-170-30-130", Section, 4, 20) : QuickText(XOff + 183 "|" YOff + 36 "|" 155 "|" 11, "155-255-110-170-30-130", Section, 4, 156)) If (Text = "TheBankofRuneScape") Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 50) } } Sleep % Round(Abs(RandomSkew(Alpha, 50)) + 20) + rTemp := 1 If (ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) = "W") { Threshold := BankGUI(ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)), 1) ThreshReturn .= ((ReturnPos(Threshold, 5, SubStr(Delimiters, 1, 1)) <= ReturnPos(A_LoopField, 4, SubStr(Delimiters, 2, 1))) ? 1 : 0) } QuickRCMenu(ReturnPos(A_LoopField, 3, SubStr(Delimiters, 2)), 8) } hMovement(XOff + ((ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) = "DB") ? 421 : 475) SubStr(Delimiters, 1, 1) YOff + 30 SubStr(Delimiters, 1, 1) 22 SubStr(Delimiters, 1, 1) 22) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Loop { NewText := ((ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) = "DB") ? QuickText(XOff + 145 "|" YOff + 36 "|" 250 "|" 11, Orange, Section, 4, 20) : QuickText(XOff + 183 "|" YOff + 36 "|" 155 "|" 11, Orange, Section, 4, 156)) If (Text <> NewText) Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 100) } Return ThreshReturn } ; BankInteract("OCR Examine", "OCR Subtext", "Shrimps-All|Cod-All-1|Green Partyhat-1|Arrow Shaft-5-1|Herring-10-1", "Shrimps-10-0-1|Green Partyhat-1|Cod-10-0-1|Coins-AB1-69-1") ; DList := "ItemName-Amount-Noted|ItemName-Amount-Noted|..." ; WList := "ItemName-Amount-Threshold-Noted|ItemName-Amount-Threshold-Noted|..." ; Returns a binary string where 1s indicate triggered thresholds and 0s are above threshold level, in WList's order. BankInteract(DList := 0, WList := "") { Note := Search := 0 Loop { If (QuickText(XOff + 183 "|" YOff + 36 "|" 155 "|" 11, Orange, Section, 4, 156) = "TheBankofRuneScape") Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 50) } If (DList <> "") { StringReplace, DList, DList, % A_Space,, All If (DList = "All") OR (DList = 1) { hMovement(XOff + 426 SubStr(Delimiters, 1, 1) YOff + 287 SubStr(Delimiters, 1, 1) 35 SubStr(Delimiters, 1, 1) 35) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 150)) + 200)) Inventory := MultiplyString(SubStr(Delimiters, 1, 1), 27) } Else { NewInv := Inventory Loop, Parse, Inventory, % SubStr(Delimiters, 1, 1) { Found := NestedSearchPos(DList, SubStr(A_LoopField, ((InStr(A_LoopField, "+")) ? InStr(A_LoopField, "+") + 1 : 1)), ((InStr(A_LoopField, "+")) ? 1 : 0), 3) If Found { Obj := ReturnPos(DList, Found, SubStr(Delimiters, 1, 1)) If ReturnPos(Obj, 3, SubStr(Delimiters, 2)) AND InStr(A_LoopField, "+") OR !ReturnPos(Obj, 3, SubStr(Delimiters, 2)) AND !InStr(A_LoopField, "+") { Inventory(A_Index, 1) Sleep % Round(Abs(RandomSkew(Alpha, 100)) + 50) If (ReturnPos(Obj, 2, SubStr(Delimiters, 2)) = "All") OR (ReturnPos(Obj, 2, SubStr(Delimiters, 2)) >= 28) AND !InStr(A_LoopField, "+") QuickRCMenu(6, 8) Else If (ReturnPos(Obj, 2, SubStr(Delimiters, 2)) = 1) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Else If (ReturnPos(Obj, 2, SubStr(Delimiters, 2)) = 5) QuickRCMenu(2, 8) Else If (ReturnPos(Obj, 2, SubStr(Delimiters, 2)) = 10) QuickRCMenu(3, 8) Else { QuickRCMenu(5, 8) Loop { If (QuickText(XOff + 205 "|" YOff + 396 "|" 105 "|" 11, Black, Section, 4, 345) = "EnterAmount:") Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 50) } Type(ReturnPos(Obj, 2, SubStr(Delimiters, 2)) "{Enter}") WaitContains(Inventory(A_Index, 1), "55-85-50-75-40-70", RSeed(200, 300), 0) } } If ReturnPos(Obj, 3, SubStr(Delimiters, 2)) StringReplace, NewInv, NewInv, % A_LoopField, % ((SubStr(A_LoopField, 1, InStr(A_LoopField, "+") - 1) - ReturnPos(Obj, 2, SubStr(Delimiters, 2)) > 0) ? SubStr(A_LoopField, 1, InStr(A_LoopField, "+") - 1) - ReturnPos(Obj, 2, SubStr(Delimiters, 2)) "+" SubStr(A_LoopField, InStr(A_LoopField, "+") + 1) : "") Else NewInv := RPLInstance(NewInv, ReturnPos(Obj, 1, SubStr(Delimiters, 2)), SubStr(Delimiters, 1, 1),, ((ReturnPos(Obj, 2, SubStr(Delimiters, 2)) = "All") ? 28 : ReturnPos(Obj, 2, SubStr(Delimiters, 2)))) StringReplace, DList, DList, % Obj } } Inventory := NewInv } } If (WList <> "") { Loop, Parse, WList, % SubStr(Delimiters, 1, 1) { If !Search { hMovement(XOff + 380 SubStr(Delimiters, 1, 1) YOff + 287 SubStr(Delimiters, 1, 1) 35 SubStr(Delimiters, 1, 1) 35) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Loop { If (QuickText(XOff + 88 "|" YOff + 396 "|" 345 "|" 11, Black, Section, 4, 345) = "Showitemswhosenamescontainthefollowingtext:") Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 50) } Search := 1 } If (Note <> ReturnPos(A_LoopField, 4, SubStr(Delimiters, 2))) { hMovement(XOff + ((Note = 1) ? 201 : 286) SubStr(Delimiters, 1, 1) YOff + 302 SubStr(Delimiters, 1, 1) 84 SubStr(Delimiters, 1, 1) 21) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Note := !Note } Type(TempName := ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2))) StringReplace, TempName, TempName, % A_Space,, All Loop { If (QuickText(XOff + 124 "|" YOff + 36 "|" 265 "|" 11, Orange SubStr(Delimiters, 1, 1) Red, Section, 4) = "Showingitems:" TempName) Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 50) } Loop, 48 { Amount := ReturnPos(BankGUI(A_Index, 1), 5, SubStr(Delimiters, 1, 1)) If (QuickText(XOff + 9 "|" YOff + 9 "|" 500 "|" 11, Orange, Section, 4, 100) = TempName) Break Index := A_Index } If (A_Index = 48) Continue If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "All") OR (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "AB1") QuickRCMenu(((ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "All") ? 6 : 7), 9) Else If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = 1) Send("LButton", 0, RSeed(20, 80), RSeed(150, 200)) Else If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = 5) QuickRCMenu(2, 9) Else If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = 10) QuickRCMenu(3, 9) Else If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) > 1) { QuickRCMenu(5, 9) Loop { If (QuickText(XOff + 205 "|" YOff + 396 "|" 105 "|" 11, Black, Section, 4, 345) = "EnterAmount:") Break Sleep % Round(Abs(RandomSkew(Alpha, 125)) + 50) } Type(ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) "{Enter}") Search := 0 } If (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = 1) OR (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = 5) OR (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = 10) OR (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "All") OR (ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "AB1") Loop % StrLen(ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2))) Send("Backspace", 0, Round(Abs(RandomSkew(Alpha, 50)) + 20)) If !ReturnPos(A_LoopField, 4, SubStr(Delimiters, 2)) Inventory := RPLInstance(Inventory, "", SubStr(Delimiters, 1, 1), ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)), ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2))) Else If !RegExMatch(Inventory, "i)([0-9]+)([+]" ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) ")([" SubStr(Delimiters, 1, 1) "]|$)", SubPat) Inventory := RPLInstance(Inventory, "", SubStr(Delimiters, 1, 1), ((ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "All" OR ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "AB1") ? Amount : ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2))) "+" ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2))) Else Inventory := RegExReplace(Inventory, "i)([0-9]+[+]" ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) ")([" SubStr(Delimiters, 1, 1) "]|$)", SubPat1 + ((ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "All" OR ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) = "AB1") ? Amount : ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2))) "+" ReturnPos(A_LoopField, 1, SubStr(Delimiters, 2)) "${2}") WReturn .= ((Amount - ReturnPos(A_LoopField, 2, SubStr(Delimiters, 2)) <= ReturnPos(A_LoopField, 3, SubStr(Delimiters, 2)) AND ReturnPos(A_LoopField, 3, SubStr(Delimiters, 2)) > 0) ? 1 : 0) } } hMovement(XOff + 475 SubStr(Delimiters, 1, 1) YOff + 30 SubStr(Delimiters, 1, 1) 22 SubStr(Delimiters, 1, 1) 22) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Loop { If (QuickText(XOff + 183 "|" YOff + 36 "|" 155 "|" 11, Orange, Section, 4, 156) <> "TheBankofRuneScape") Break Sleep % RSeed(200, 300) } Return WReturn } ; Player should contain the player's name whom you want to interact with, with appropriate spaces ; If they are not in your global Friendslist variable then they will be added to your FL ingame and to the variable ; Message should contain the message you want to send them, or left blank if you do not wish to send them anything ; Delete should be true if you wish to delete them (after sending the message) FLInteract(Player, Message := "", Delete := 0) { If (Tab <> 9) InventoryTabs(9) If !InStr(FriendsList, SubStr(Delimiters, 1, 1) Player SubStr(Delimiters, 1, 1)) { hMovement(XOff + 562 SubStr(Delimiters, 1, 1) YOff + 429 SubStr(Delimiters, 1, 1) 71 SubStr(Delimiters, 1, 1) 35) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Loop { Sleep % ((A_Index > 1) ? RSeed(20, 30) * 10 : 0) If (QuickText(146 + XOff "|" 396 + YOff "|" 250 "|" 11, Black, Section, 4, 15, 1) = "Enternameoffriendtoaddtolist") Break } Type(Player "{Enter}", StrLen(Player) * 60) FriendsList .= Player SubStr(FriendsList, StrLen(FriendsList)) } If (Message <> "") { MouseGetPos, MX, MY If (MX - XOff < 555) OR (MX - XOff > 732) OR (MY - YOff < 230) OR (MY - YOff > 423) hMovement(XOff + 555 SubStr(Delimiters, 1, 1) YOff + 230 SubStr(Delimiters, 1, 1) 177 SubStr(Delimiters, 1, 1) 193) Loop { tImage := Gdip_BitmapFromScreen(XOff + 725 "|" YOff + 246 "|" 10 "|" 10) If ColorMatch(Gdip_GetPixel(tImage, 0, 0), "0-15-0-15-0-15", "-") Break Else { Send {WheelUp} Sleep % Round(Abs(RandomSkew(Alpha, 100)) + 30) } Gdip_DisposeImage(tImage) } StringReplace, TempName, Player, % A_Space,, All Base := 232 Loop, 13 { Answer := FLMatch(Base + ((A_Index - 1) * 15), TempName, A_Index) If (Answer > 0) OR (Answer = "E") Break Else If (A_Index = 13) { Loop { Send {WheelDown} Sleep % Round(Abs(RandomSkew(Alpha, 100)) + 30) tImage := Gdip_BitmapFromScreen(XOff + 725 "|" YOff + 407 "|" 10 "|" 10) If ColorMatch(Gdip_GetPixel(tImage, 0, 0), Black, "-") ; At the bottom of Friends List Base := 226 Gdip_DisposeImage(tImage) Loop, 3 { Answer := FLMatch(Base + ((A_Index + 9) * 15), TempName, A_Index + 10) If (Answer > 0) OR (Answer = "E") OR (A_Index = 3) AND (Base <> 232) Break 3 } } } } If (Answer <> "E") AND (Answer > 0) { hMovement(XOff + 557 SubStr(Delimiters, 1, 1) YOff + Base + ((Answer - 1) * 15) SubStr(Delimiters, 1, 1) 95 SubStr(Delimiters, 1, 1) 14) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 100)) + 50)) Loop, 10 { Sleep % ((A_Index > 1) ? RSeed(20, 30) * 10 : 0) If (QuickText(100 + XOff "|" 396 + YOff "|" 320 "|" 11, Black, Section, 4, 15, 1) = "Entermessagetosendto" TempName) Break Index := A_Index } If (Index < 10) OR (Index = "") Type(Message, StrLen(Message) * 50) Else Send("Enter", Round(Abs(RandomSkew(Alpha, 50)) + 50), Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 100)) + 50)) } } If Delete { hMovement(XOff + 642 SubStr(Delimiters, 1, 1) YOff + 429 SubStr(Delimiters, 1, 1) 71 SubStr(Delimiters, 1, 1) 35) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 50), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Loop { Sleep % ((A_Index > 1) ? RSeed(20, 30) * 10 : 0) If (QuickText(146 + XOff "|" 396 + YOff "|" 250 "|" 11, Black, Section, 4, 15, 1) = "Enternameoffriendtodeletefromlist") Break } Type(Player "{Enter}", StrLen(Player) * 50) StringReplace, FriendsList, FriendsList, % SubStr(Delimiters, 1, 1) Player SubStr(Delimiters, 1, 1) } Return Answer } ; Opt must be set to the text of the menu item you wish to click or the text the item contains if Contains is true ; Colors should contain the colors of the text as passed to the QuickText function ; Stop is distance w/o text to stop after, Length is width for QuickText, Contains is to choose an option that contains the phrase ; Optimize efficiency by reading the least amount of text. Want to find "Fire" to cook? Fire is cyan RCMenu(Opt, Colors := "", Stop := 50, Length := "", Contains := 0, RClick := 1) { If (RClick) Send("RButton", 0, Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 50)) MouseGetPos, MX, MY MX := MX - XOff, MY := MY - YOff Image := Gdip_BitmapFromScreen(XOff "|" YOff "|" 765 "|" 503) Gdip_SaveBitmapToFile(Image, "File.png") Loop, % MY ; Search Up MY + YOff - UpIndex { UpIndex := A_Index - 1 If ColorMatch(Gdip_GetPixel(Image, MX, MY - UpIndex), "80-105-75-95-60-85", SubStr(Delimiters, 2)) AND ColorMatch(Gdip_GetPixel(Image, MX, MY - UpIndex + 1), "0-15-0-15-0-15", SubStr(Delimiters, 2)) AND ColorMatch(Gdip_GetPixel(Image, MX, MY - UpIndex + 2), "0-15-0-15-0-15", SubStr(Delimiters, 2)) { MatchCount := SType := 1 Loop, 6 { SIndex := ((SType) ? A_Index : SCount := SCount - 1) If ColorMatch(Gdip_GetPixel(Image, MX + SIndex, MY - UpIndex), "80-105-75-95-60-85", SubStr(Delimiters, 2)) AND ColorMatch(Gdip_GetPixel(Image, MX + SIndex, MY - UpIndex + 1), "0-15-0-15-0-15", SubStr(Delimiters, 2)) AND ColorMatch(Gdip_GetPixel(Image, MX + SIndex, MY - UpIndex + 2), "0-15-0-15-0-15", SubStr(Delimiters, 2)) MatchCount++ Else SType := SCount := 0 If (MatchCount = 6) Break 2 } } } Loop, % 503 - MY ; Search Down MY + Yoff + DIndex { DIndex := A_Index - 1 If ColorMatch(Gdip_GetPixel(Image, MX, MY + DIndex), "0-15-0-15-0-15", SubStr(Delimiters, 2)) AND ColorMatch(Gdip_GetPixel(Image, MX, MY + DIndex - 1), "80-105-75-95-60-85", SubStr(Delimiters, 2)) AND ColorMatch(Gdip_GetPixel(Image, MX, MY + DIndex - 2), "80-105-75-95-60-85", SubStr(Delimiters, 2)) { MatchCount := SType := 1 Loop, 3 { SIndex := ((SType) ? A_Index : SCount := SCount - 1) If ColorMatch(Gdip_GetPixel(Image, MX + SIndex, MY + DIndex), "0-15-0-15-0-15", SubStr(Delimiters, 2)) AND ColorMatch(Gdip_GetPixel(Image, MX + SIndex, MY + DIndex - 1), "80-105-75-95-60-85", SubStr(Delimiters, 2)) AND ColorMatch(Gdip_GetPixel(Image, MX + SIndex, MY + DIndex - 2), "80-105-75-95-60-85", SubStr(Delimiters, 2)) MatchCount++ Else SType := SCount := 0 If (MatchCount = 3) Break 2 } } } Loop, % MX { LIndex := A_Index - 1 If ColorMatch(Gdip_GetPixel(Image, MX - LIndex, MY - UpIndex + 1), "80-105-75-95-60-85", SubStr(Delimiters, 2)) AND ColorMatch(Gdip_GetPixel(Image, MX - LIndex + 1, MY - UpIndex + 1), "0-15-0-15-0-15", SubStr(Delimiters, 2)) Break } Loop, % 765 - MX { RIndex := A_Index - 1 If ColorMatch(Gdip_GetPixel(Image, MX + RIndex, MY - UpIndex + 1), "80-105-75-95-60-85", SubStr(Delimiters, 2)) AND ColorMatch(Gdip_GetPixel(Image, MX + RIndex - 1, MY - UpIndex + 1), "0-15-0-15-0-15", SubStr(Delimiters, 2)) Break } Gdip_DisposeImage(Image) If (Colors <> "") AND RegExMatch(Opt, "i)[a-z]") { Loop, % (UpIndex + DIndex - 20) / 15 { If (Opt = Temp := QuickText(XOff + MX - LIndex + 3 "|" YOff + MY - UpIndex + (A_Index - 1) * 15 + 21 "|" ((Length = "") ? LIndex + RIndex : Length) "|" 11, Colors, Section, 4, Stop)) OR (Contains) AND InStr(Temp, Opt) { Opt := A_Index Break } } } Else If (Opt <= 0) Opt := Floor((UpIndex + DIndex - 20) / 15 + Opt) If Opt is digit { hMovement(XOff + MX - LIndex + 1 SubStr(Delimiters, 1, 1) YOff + MY - UpIndex + (Opt - 1) * 15 + 19 SubStr(Delimiters, 1, 1) LIndex + RIndex - 1 SubStr(Delimiters, 1, 1) 14, "", "", 0) Return Floor((UpIndex + DIndex - 20) / 15) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) } Return 0 } ; Launches RS in your default browser if it is not already open and defines XOff and YOff ; YO should be the previous OY return in order to minimize search time, W = Login world ; Orion must be launched manually and define X/YOff with the OrionOffset() function LaunchRS(YO := 0, W := 69) { IfWinNotExist, Old School RuneScape Game { Run % "http://oldschool" W ".runescape.com/j1" WinGetActiveStats, T, W, H, X, Y Sleep 5000 } WinActivate, Old School RuneScape Game WinWaitActive, Old School RuneScape Game WinGetActiveStats, T, W, H, X, Y If (W < 800) OR (H < 660) WinMove, Old School RuneScape Game, % X := 0, % Y := 0, % W := 800, % H := 860 pImage := Gdip_BitmapFromScreen(((X < 0) ? X := 0 : X) "|" ((Y < 0) ? Y := 0 : Y) "|" ((W > A_ScreenWidth) ? W := A_ScreenWidth : W) "|" ((H > A_ScreenHeight) ? H := A_ScreenHeight : H)) Loop, % Gdip_GetImageWidth(pImage) { XOff := ((A_Index = 1) ? Round(X + (W / 2) - 381) : A_Index - 2) Loop, % Gdip_GetImageHeight(pImage) { YCoord := ((A_Index = 1 AND YO > 0) ? YO - 27 : A_Index - 1) If ColorMatch(Gdip_GetPixel(pImage, XOff, YCoord), "0-15-0-15-0-15", "-") AND ColorMatch(Gdip_GetPixel(pImage, XOff, YCoord + 26), "0-15-0-15-0-15", "-") AND ColorMatch(Gdip_GetPixel(pImage, XOff - 1, YCoord + 27), "0-15-0-15-0-15", "-") AND ColorMatch(Gdip_GetPixel(pImage, XOff - 1, YCoord + 25), "1-255-1-255-1-255", "-") AND ColorMatch(Gdip_GetPixel(pImage, XOff - 2, YCoord + 25), "0-15-0-15-0-15", "-") Return YOff := YCoord + 27 } } } ; Waits until the first login button exists then... ; Types user name {Enter} Pass {Enter} and clicks the Click Here to Play button ; Ends when the "Click Here To Play" button disappears Login(User, Pass) { Loop { If (QuickText(418 + XOff "|" 285 + YOff "|" 100 "|" 11, White, Section, 4, 15, 1) = "ExistingUser") Break Sleep, % Round(Abs(RandomSkew(Alpha, 125)) + 50) } hMovement(XOff + 388 SubStr(Delimiters, 1, 1) YOff + 271 SubStr(Delimiters, 1, 1) 149 SubStr(Delimiters, 1, 1) 40) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Type(User "¤" Pass "¤", StrLen(User "¤" Pass "¤") * 50) Loop { If (QuickText(361 + XOff "|" 331 + YOff "|" 150 "|" 11, White, Section, 4, 15, 1) = "CLICKHERETOPLAY") Break Sleep, % Round(Abs(RandomSkew(Alpha, 125)) + 50) } hMovement(XOff + 271 SubStr(Delimiters, 1, 1) YOff + 293 SubStr(Delimiters, 1, 1) 228 SubStr(Delimiters, 1, 1) 88) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 50)) + 20)) Loop { If (QuickText(361 + XOff "|" 331 + YOff "|" 150 "|" 11, White, Section, 4, 15, 1) <> "CLICKHERETOPLAY") Break Sleep, % Round(Abs(RandomSkew(Alpha, 125)) + 50) } } ; Logs you out by clicking the 'Logout' button in the 'Logout' tab ; Ceases attempts once the white text of the "Existing Users" button appears Logout() { Image := Gdip_BitmapFromScreen("0|0|" A_ScreenWidth "|" A_ScreenHeight) Gdip_SaveBitmapToFile(Image, "Logout.png") If (Tab <> 11) InventoryTabs(11) Loop { hMovement( XOff + 572 SubStr(Delimiters, 1, 1) YOff + 359 SubStr(Delimiters, 1, 1) 140 SubStr(Delimiters, 1, 1) 35) Send("LButton", Round(Abs(RandomSkew(Alpha, 50)) + 20), Round(Abs(RandomSkew(Alpha, 75)) + 20), Round(Abs(RandomSkew(Alpha, 125)) + 50)) If (QuickText(416 + XOff "|" 285 + YOff "|" 100 "|" 11, White, Section, 4, 15, 1) = "ExistingUser") Break } } ; Returns the text within an image. ; Image requires "X|Y|W|H", Delimiters: "|-", Data: OCR Section dumped into a var, Space: Maximum space between words to keep text color constant ; Stop: Streak of no-text pixels to cease searching after QuickText(Image, Colors, iSection, Space := 1, Stop := "", StartColor := 0) { Colors := ((nColors <> "") ? nColors : Colors) IniRead, Data, % Ini, % iSection FoundPos := StartColor If InStr(Image, "|") Image := Gdip_BitmapFromScreen(Image) Gdip_SaveBitmapToFile(Image, "File.png") ;Image := Gdip_CreateBitmapFromFile("File.png") Height := Gdip_GetImageHeight(Image) Stop := ((Stop = "") ? Gdip_GetImageWidth(Image) : Stop) Loop, % Gdip_GetImageWidth(Image) { XCoord := A_Index - 1 Loop, % Height { Container := InitialMatching(Gdip_GetPixel(Image, XCoord, A_Index - 1), Colors, FoundPos) FoundPos := SubStr(Container, 2) Addendum .= SubStr(Container, 1, 1) ; Addendum is either 1 or 0, so the position of the match in the 'colors' string is the data stored after it } ; This is necessary to prevent a yellow pixel from registering as text in the middle of a white word If (Addendum = 0) ; Only when a space (Space) is registered are the word colors allowed to change { ; If a stop is encountered then the image ceases being read (Stop must be > Space) Pixels .= "¤" Count := Count + 1 } Else { Pixels .= Addendum "¦" Count := 0 } If (Count > Stop) Break FoundPos := ((Count > Space) ? 0 : FoundPos) Addendum := } Gdip_DisposeImage(Image) Loop, Parse, Data, `n MaxIndex := A_Index Loop, Parse, Pixels, ¤ { Success := 0 If (%A_LoopField% <> "") Phrase .= %A_LoopField% Else If (%A_LoopField% = "") AND (A_LoopField <> "") { If InStr("`n" Data, "`n" A_LoopField "=") Phrase .= %A_LoopField% := SubStr("`n" Data, InStr("`n" Data, "`n" A_LoopField "=") + StrLen("`n" A_LoopField "="), 1) Else { Field := A_LoopField Loop, Parse, Data, `n { If (StrLen(Field) = StrLen(SubStr(A_LoopField, 1, InStr(A_LoopField, "=") - 1))) ; RegExMatch consuming whole key + search, break 2 releases from search methodology { ; Only needs to run once, first (bc it consumes whole search) StringReplace, Temp, Field, 1, \d, All If RegExMatch(A_LoopField, Temp) { Phrase .= SubStr(A_LoopField, InStr(A_LoopField, "=") + 1, 1) Success := 1 Break } } } If !Success ; The entire search string was not consumed, secondary efforts are necessary { ; First attempt: Look for exact matches of keys inside search, then remove/add/repeat using nested loops SearchField := Field ; If an entire data parse is completed without success (breaking) then break 2 runs and stops the nested loops Substitute := MultiplyString("¤", Height + 1) Loop { Loop, Parse, Data, `n { If (StrLen(SearchField) > StrLen(SubStr(A_LoopField, 1, InStr(A_LoopField, "=") - 1))) AND InStr(SearchField, SubStr(A_LoopField, 1, InStr(A_LoopField, "=") - 1)) AND (StrLen(A_LoopField) > (Height + 1) * 2 + 2) { StringReplace, Field, Field, % SubStr(A_LoopField, 1, InStr(A_LoopField, "=") - 1), % "¤" SubStr(A_LoopField, InStr(A_LoopField, "=") + 1, 1) "¤" StringReplace, SearchField, SearchField, % SubStr(A_LoopField, 1, InStr(A_LoopField, "=") - 1), % Substitute Break } If (A_Index = MaxIndex) Break 2 } } If (StrLen(Field) > Height + 1) ; If there are enough characters left (no character is only one pixel wide, hence this line) { ; Then we start this tertiary search method using the same basic algorithm Loop ; EXCEPT looking for floating matches, then removing from field/adding to phrase/breaking { Loop, Parse, Data, `n { If (StrLen(Field) > StrLen(SubStr(A_LoopField, 1, InStr(A_LoopField, "=") - 1))) { Found := FloatingBinMatch(SearchField, SubStr(A_LoopField, 1, InStr(A_LoopField, "=") - 1), Height + 1) If Found { StringReplace, Field, Field, % SubStr(SearchField, Found, StrLen(SubStr(A_LoopField, 1, InStr(A_LoopField, "=") - 1))), % "¤" SubStr(A_LoopField, InStr(A_LoopField, "=") + 1, 1) "¤" SearchField := LTrim(SubStr(SearchField, 1, Found - 1) Substitute SubStr(SearchField, Found + InStr(A_LoopField, "=") - 1), "¤") Break } } If (A_Index = MaxIndex) Break 2 } } } Loop, Parse, Field, ¤ If !Ceil(SubStr(A_Index / 2, InStr(A_Index / 2, "."))) Phrase .= A_LoopField } } } } Return Phrase } ; Types your phrase, add {Enter} or ¤ to send Enter keystrokes ; MS is the time to type within, it is a rough estimate ; MS should be based off of the number of characters within Phrase to constitute "human-like typing" Type(Phrase, MS := "") { Elapsed := 0 StringReplace, Phrase, Phrase, {Enter}, ¤, All MS := ((MS = "") ? StrLen(Phrase) * 50: MS) Loop, Parse, Phrase { Avg := (MS - Elapsed) / ((StrLen(Phrase) - A_Index + 1) * 2) LoopField := ((A_LoopField = " ") ? "Space" : ((A_LoopField = "¤") ? "Enter" : A_LoopField)) T1 := Ceil(RSeed(0, Round(Avg * 1.1))) T2 := Ceil(RSeed(0, Round(Avg * 1.1), 1)) Sleep % T1 := ((T1 < 16) ? 15 : T1) Send % "{" LoopField " Down}" Sleep % T2 := ((T2 < 16) ? 15 : T2) Send % "{" LoopField " Up}" Elapsed := Elapsed + T1 + T2 } } ; Sends the character Char, waits B before pushing down, waits D before releasing, and waits A before exiting Send(Char, B := 0, D := 0, A := 0) { Sleep % B Send % "{" Char " Down}" Sleep % D Send % "{" Char " Up}" Sleep % A } ; Waits tSleep amount of time for the area you input to the Image parameter to have Color(s) ; The color requirement is applied to the first pixel by default, all pixels if All is true and looks for colors outside your range if vNot is true. WaitContains(Image, Colors, tSleep := 0, All := 0, vNot := 0) { Loop { If AreaContains(Image, Colors, All, vNot) Return Sleep % tSleep } } ; Puts your entire Friends List into the Friendslist global variable and writes it to your .ini RecordFL() { FriendsList := If (Tab <> 9) InventoryTabs(9) MouseGetPos, MX, MY If (MX - XOff < 555) OR (MX - XOff > 710) OR (MY - YOff < 230) OR (MY - YOff > 423) hMovement(XOff + 555 SubStr(Delimiters, 1, 1) YOff + 230 SubStr(Delimiters, 1, 1) 155 SubStr(Delimiters, 1, 1) 193) Loop { tImage := Gdip_BitmapFromScreen(XOff + 725 "|" YOff + 246 "|" 10 "|" 10) If ColorMatch(Gdip_GetPixel(tImage, 0, 0), Black, SubStr(Delimiters, 2, 1)) Break Else { Send {WheelUp} Sleep % RSeed(100, 200) } Gdip_DisposeImage(tImage) } Base := 232 Loop, 13 { FriendsList .= SubStr(Delimiters, 1, 1) QuickText(XOff + 556 "|" YOff + Base + ((A_Index - 1) * 15) "|" 96 "|" 11, White, fSection, 4, 156) If (A_Index = 13) { Loop { Send {WheelDown} Sleep % RSeed(100, 200) tImage := Gdip_BitmapFromScreen(XOff + 725 "|" YOff + 407 "|" 10 "|" 10) If ColorMatch(Gdip_GetPixel(tImage, 0, 0), Black, SubStr(Delimiters, 2, 1)) Base := 226 Gdip_DisposeImage(tImage) Loop, 3 { If (Base = 232) FriendsList .= SubStr(Delimiters, 1, 1) QuickText(XOff + 556 "|" YOff + Base + ((A_Index + 9) * 15) "|" 96 "|" 11, White, fSection, 4, 156) Else If (Base <> 232) { Temp := QuickText(XOff + 556 "|" YOff + Base + ((A_Index + 9) * 15) "|" 96 "|" 11, White, fSection, 4, 156) If !InStr(FriendsList SubStr(Delimiters, 1, 1), SubStr(Delimiters, 1, 1) Temp SubStr(Delimiters, 1, 1)) FriendsList .= SubStr(Delimiters, 1, 1) Temp } If (A_Index = 3) AND (Base <> 232) Break 3 } } } } FriendsList .= SubStr(Delimiters, 1, 1) IniWrite, % FriendsList, % Ini, Seed, FriendsList } ; Records your inventory by mousing over your items and reading the Examine area's text. ; Records amounts by reading the little text in the upper left corner of the item ; Returns a list of items in the form "AbyssalWhip|10+Salmon|100000+Coins" w/o spaces where #+ indicates a stackable or noted item RecordInv() { Loop, 28 { Index := A_Index If !AreaContains(Inventory(Index, 1), Grey, 0, 1) { Inv .= SubStr(Delimiters, 1, 1) Continue } hMovement(SubStr(Temp := Inventory(Index, 1, 1), 0, InStr(Temp, SubStr(Delimiters, 1, 1),,, 4) - 1)) Noted := ReturnPos(Temp, 5, SubStr(Delimiters, 1, 1)) Loop { Text := QuickText(XOff + 9 "|" YOff + 9 "|" 500 "|" 11, Orange, Section, 4, 50) If (Text <> "") Break Sleep % RSeed(200, 300) } Inv .= SubStr(Delimiters, 1, 1) ((Noted <> 0) ? Noted "+": "") Text } StringReplace, Inv, Inv, % SubStr(Delimiters, 1, 1) Return Inv }