Simba Code:
(*
Grand Exchange
==============
The grandexchange file holds functions and procedures that are used to interact with the runescape Grand Exchange.
The source for this file can be found `here <https://github.com/SRL/SRL-6/blob/master/lib/interfaces/grandexchange.simba>`_.
*)
{$f-}
(*
Consts, Types, Vars
~~~~~~~~~~~~~~~~~~~
The following constants, types and variables are used throughout the collectBox methods.
**const Grand Exchange Tabs**
Constants that represent the two grandExchange tabs
* GE_TAB_EXCHANGE
* GE_TAB_HISTORY
*)
const
GE_TAB_EXCHANGE = 0;
GE_TAB_HISTORY = 1;
(*
**type TRSGrandExchange**
.. code-block:: pascal
type
TRSGrandExchange = type TRSInterface;
A type that stores the Grand Exchange interface properties.
*)
type
TRSGrandExchange = record(TRSInterface)
tabBoxes: TBoxArray;
end;
(*
**var grandExchange**
.. code-block:: pascal
var
grandExchange: TRSGrandExchange;
A variable through which scripters can access the TRSGrandExchange type methods.
*)
var
grandExchange: TRSGrandExchange;
(*
TRSGrandExchange methods
~~~~~~~~~~~~~~~~~~~~~~~~~
The following methods should be called through the **grandExchange** variable.
Example:
.. code-block:: pascal
if grandExchange.isOpen() then
writeln('It''s open');
*)
{*
__init
------
.. code-block:: pascal
procedure TRSGrandExchange.__init();
Initializes the TRSGrandExchange.
.. note::
- by The Mayor
- Last Updated: 9th October 2014 by Clarity
Example:
.. code-block:: pascal
grandExchange.__init();
*}
{$IFNDEF CODEINSIGHT}
procedure TRSGrandExchange.__init();
begin
with self do
begin
name := 'Grand Exchange';
ID := ID_INTERFACE_GRANDEXCHANGE;
parentID := -1;
static := false;
end;
end;
{$ENDIF}
{*
__find
------
.. code-block:: pascal
function TRSGrandExchange.__find(): boolean;
Returns true if the grandExchange interface is detected and its bounds are set.
Scripters should use grandExchange.isOpen() below.
.. note::
- by The Mayor
- Last Updated: 6 July 2015 by The Mayor
Example:
.. code-block:: pascal
if grandExchange.__find() then
writeln('The grandExchange is open, and the bounds are set!');
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__find(): boolean;
const
PINK_COLOR = [14581920, 0]; // [Col, Tol] pink item in the balance scale.
var
i: Integer;
TPA: TPointArray;
ATPA: T2DPointArray;
b: TBox;
begin
findColorsTolerance(TPA, PINK_COLOR[0], getClientBounds(), PINK_COLOR[1]);
if length(TPA) < 10 then
begin
print('TRSGrandExchange.__find(): Didn''t find enough PINK_COLOR', TDebug.WARNING);
exit(false);
end;
ATPA := TPA.cluster(5);
ATPA.sortBySize(true);
for i := 0 to high(ATPA) do
begin
b := ATPA[i].getBounds();
if inRange(b.getWidth(), 10, 20) and (b.getHeight() < 20) then
begin
b.edit(21, -10, 114, 12);
if (pos('GRAND', upperCase(tesseract_GetText(b, TESS_FILTER_SMALL_CHARS))) > 0) then
begin
self.setBounds([b.x1 - 88, b.y1 - 8, b.x2 + 570, b.y2 + 515]);
self.tabBoxes := grid(2, 1, 60, 22, 125, 0, point(x1 + 92, y1 + 113));
exit(true);
end;
end;
end;
end;
{$ENDIF}
(*
isOpen
------
.. code-block:: pascal
function TRSGrandExchange.isOpen(waitTime: integer = 0): boolean;
Returns true if the grandExchange is open. The optional **waitTime** parameter
*(default = 0)* is the maximum time (in milliseconds) it will keep looking.
.. note::
- by The Mayor
- Last Updated: 14 January 2015 by The Mayor
Example:
.. code-block:: pascal
if grandExchange.isOpen() then
writeln('The grandExchange is open!');
*)
function TRSGrandExchange.isOpen(waitTime: integer = 0): boolean;
var
t: UInt64;
begin
t := (getTickCount64() + waitTime);
repeat
if self.__find() then
begin
result := true;
break();
end;
until (getSystemTime() >= t);
print('TRSGrandExchange.isOpen(): Result = ' + boolToStr(result));
end;
(*
close
-----
.. code-block:: pascal
function TRSGrandExchange.close(escape: boolean = true): boolean;
Returns true if the grandExchange is successfully closed. It uses the ESC key
by default, but the **escape** parameter can be set to false to close via the mouse.
.. note::
- by The Mayor
- Last Updated: 6 July 2015 by The Mayor
Example:
.. code-block:: pascal
if grandExchange.close() then
writeln('Closed the grandExchange');
*)
function TRSGrandExchange.close(escape: boolean = true): boolean;
const
__CLOSE_OFFSET: TPoint = [756, 22]; // From self(x1, y1) to middle of 'X'
var
timeOut: UInt64;
begin
if (not self.isOpen()) then
exit(true);
if escape then // Try the escape button first if possible
begin
timeOut := (getTickCount64() + randomRange(600, 900));
repeat
typeByte(VK_ESCAPE);
wait(300 + random(50));
until (not self.isOpen()) or (getTickCount64() > timeOut);
if (not self.isOpen()) then
exit(true);
end;
if self.isOpen(100 + random(50)) then // Wait a bit in case it closes
begin
mouse(point(self.x1 + __CLOSE_OFFSET.x, self.y1 + __CLOSE_OFFSET.y).rand(3), MOUSE_LEFT);
timeOut := (getTickCount64() + randomRange(5000, 6000));
while (timeOut > getTickCount64()) do
begin
if (not self.isOpen()) then
begin
result := true;
break();
end;
wait(50 + random(50));
end;
end else
result := true;
print('TRSGrandExchange.close(): result = ' + boolToStr(result), TDebug.SUB);
end;
{*
__getActiveTab
--------------
.. code-block:: pascal
function TRSGrandExchange.__getActiveTab(): Integer;
Returns the current tab number (0 - Grand Exchange | 1 - Sale History).
.. note::
- by The Mayor
- Last Updated: 9 July 2015 by The Mayor
Example:
.. code-block:: pascal
writeLn(grandExchange.__getActiveTab());
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__getActiveTab(): Integer;
var
i: Integer;
begin
for i := 0 to high(self.tabBoxes) do
if (not (getColor(self.tabBoxes[i].X2, self.tabBoxes[i].Y2) = 9078134)) then
exit(i);
end;
{$ENDIF}
(*
openTab
-------
.. code-block:: pascal
function TRSGrandExchange.openTab(tab: Integer): Boolean;
Opens the grandExchange tab **tab** . The **tab** parameter should be one of the
two tab constants at the top of this page.
.. note::
- by The Mayor
- Last Updated: 9 July 2015 by The Mayor
Example:
.. code-block:: pascal
grandExchange.openTab(GE_TAB_HISTORY);
*)
function TRSGrandExchange.openTab(tab: Integer): Boolean;
begin
if (not self.isOpen()) then
exit(false);
if (self.__getActiveTab() = tab) then
exit(true);
for 0 to 2 do
begin
multiClick(self.tabBoxes[tab].getGaussPoint(), 30, 3);
wait(random(800, 1200));
if (self.__getActiveTab() = tab) then exit(true);
end;
end;
(*
getPackSlotBox
--------------
.. code-block:: pascal
function TRSGrandExchange.getPackSlotBox(slot: integer): TBox;
Returns a TBox of the pack slot **slot** in the grandExchange interface.
.. note::
- by The Mayor
- Last Updated: 6 July 2015 by The Mayor
Example:
.. code-block:: pascal
var
b: TBox;
begin
b := grandExchange.getPackSlotBox(1);
mouseBox(b, MOUSE_MOVE);
end;
*)
function TRSGrandExchange.getPackSlotBox(slot: integer): TBox;
const
__PACK_OFFSET: TPoint = [582, 183]; // From self(x1, y1) to middle of first pack slot
begin
result := gridBox(slot - 1, 4, 7, 36, 32, 46, 36, point(self.x1 + __PACK_OFFSET.x, self.y1 + __PACK_OFFSET.y));
end;
{*
__getSlotBoxes
--------------
.. code-block:: pascal
function TRSGrandExchange.__getSlotBoxes(): TBoxArray;
Returns a TBoxArray of the 8 Grand Exchange slots.
.. note::
- by The Mayor
- Last Updated: 19 November 2015 by SlipperyPickle
Example:
.. code-block:: pascal
tba := grandExchange.__getSlotBoxes();
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__getSlotBoxes(): TBoxArray;
const
__GE_SLOT_OFFSET: TPoint = [104, 203]; // From self(x1, y1) to middle of first GE slot
var
tba: TBoxArray;
begin
tba := grid(3, 3, 169, 121, 177, 128, point(self.x1 + __GE_SLOT_OFFSET.x, self.y1 + __GE_SLOT_OFFSET.y));
tba.deleteIndex(8);
result := tba;
end;
{$ENDIF}
{*
__getBuyBoxes
-------------
.. code-block:: pascal
function TRSGrandExchange.__getBuyBoxes(): TBoxArray;
Returns a TBoxArray of the Grand Exchange buy boxes.
.. note::
- by The Mayor
- Last Updated: 27 July 2015 by Clarity
Example:
.. code-block:: pascal
tba := grandExchange.__getBuyBoxes();
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__getBuyBoxes(): TBoxArray;
const
__BUY_OFFSET: TPoint = [74, 223]; // From self(x1, y1) to middle of first buy button
var
tba: TBoxArray;
begin
tba := grid(3, 3, 44, 44, 177, 128, point(self.x1 + __BUY_OFFSET.x, self.y1 + __BUY_OFFSET.y));
tba.deleteIndex(8);
result := tba;
end;
{$ENDIF}
{*
__getSellBoxes
--------------
.. code-block:: pascal
function TRSGrandExchange.__getSellBoxes(): TBoxArray;
Returns a TBoxArray of the Grand Exchange sell boxes.
.. note::
- by The Mayor
- Last Updated: 27 July 2015 by Clarity
Example:
.. code-block:: pascal
tba := grandExchange.__getSellBoxes();
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__getSellBoxes(): TBoxArray;
const
__SELL_OFFSET: TPoint = [134, 223]; // From self(x1, y1) to middle of first sell button
var
tba: TBoxArray;
begin
tba := grid(3, 3, 44, 44, 177, 128, point(self.x1 + __SELL_OFFSET.x, self.y1 + __SELL_OFFSET.y));
tba.deleteIndex(8);
result := tba;
end;
{$ENDIF}
{*
__getInputBoxes
---------------
.. code-block:: pascal
function TRSGrandExchange.__getInputBoxes(): TBoxArray;
Returns a TBoxArray of the Grand Exchange input boxes, where you can type.
.. note::
- by Clarity
- Last Updated: 27 July 2015 by Clarity
Example:
.. code-block:: pascal
tba := grandExchange.__getInputBoxes();
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__getInputBoxes(): TBoxArray;
var
TPA: TPointArray;
ATPA: T2DPointArray;
i: integer;
begin
if findColors(TPA, 1388125, self.getBounds()) then
begin
ATPA := TPA.cluster(1);
ATPA.sortFromMidPoint(point(290, 238));
result := ATPA.getEachBounds();
end;
writeLn(result);
end;
{$ENDIF}
{*
__isOfferOpen
-------------
.. code-block:: pascal
function TRSGrandExchange.__isOfferOpen(waitTime: integer = 500): boolean;
Returns true if the buy or sell offer screen is open.
.. note::
- by The Mayor
- Last Updated: 27 July 2015 by Clarity
Example:
.. code-block:: pascal
writeLn(grandExchange.__isOfferOpen());
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__isOfferOpen(waitTime: integer = 500): boolean;
var
timeOut: UInt64;
TPA: TPointArray;
begin
timeOut := getTickCount64() + waitTime;
while (getTickCount64() < timeOut) do
if findColors(TPA, 6247745, self.getBounds()) then
begin
print('colors: ' + toStr(length(TPA)));
if (InRange(length(TPA), 2600, 3500)) then //DIT EVEN CHEKCEN
exit(true);
end;
end;
{$ENDIF}
{*
__isProgressOpen
----------------
.. code-block:: pascal
function TRSGrandExchange._isProgressOpen(waitTime: integer = 500): boolean;
Returns true if the offer in progress screen is open.
.. note::
- by The Mayor
- Last Updated: 27 July 2015 by Clarity
Example:
.. code-block:: pascal
writeLn(grandExchange.__isProgressOpen());
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__isProgressOpen(waitTime: integer = 500): boolean;
var
timeOut: integer;
TPA: TPointArray;
begin
timeOut := getTickCount64() + waitTime;
while (getTickCount64() < timeOut) do
if findColors(TPA, 6247745, self.getBounds()) then
begin
if (length(TPA) = 3501) then
exit(true);
end;
end;
{$ENDIF}
{*
__isSlotActive
--------------
.. code-block:: pascal
function TRSGrandExchange.__isSlotActive(geSlot: integer): boolean;
Returns true if the slot **geSlot** is active. This is necessary
because slots 3 to 8 are inactive when you are not a member.
.. note::
- by The Mayor
- Last Updated: 10 July 2015 by The Mayor
Example:
.. code-block:: pascal
writeLn(grandExchange.__isSlotActive(1));
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__isSlotActive(geSlot: integer): boolean;
var
TPA: TPointArray;
TBA : TBoxArray := self.__getSlotBoxes();
begin
findColors(TPA, 5063989, TBA[geSlot - 1]);
result := length(TPA) < 5000;
end;
{$ENDIF}
{*
__isSlotEmpty
-------------
.. code-block:: pascal
function TRSGrandExchange._isSlotEmpty(geSlot: integer): boolean;
Returns true if the offer slot **geSlot** is empty and avaliable to use.
.. note::
- by The Mayor
- Last Updated: 10 July 2015 by The Mayor
Example:
.. code-block:: pascal
writeLn(grandExchange.__isSlotEmpty(2));
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__isSlotEmpty(geSlot: integer): boolean;
var
TPA: TPointArray;
TBA : TBoxArray := self.__getSlotBoxes();
begin
if self.__isSlotActive(geSlot) then
begin
findColors(TPA, 2694922, TBA[geSlot - 1]);
result := length(TPA) > 10000;
end;
print('TRSGrandExchange._isSlotEmpty(): Slot ' + toStr(geSlot) + ' = ' + boolToStr(result), TDebug.SUB);
end;
{$ENDIF}
{*
__isSlotComplete
----------------
.. code-block:: pascal
function TRSGrandExchange.__isSlotComplete(geSlot: integer): boolean;
Returns true if the offer is slot **geSlot** is complete.
.. note::
- by The Mayor
- Last Updated: 15 January 2015 by The Mayor
Example:
.. code-block:: pascal
writeLn(grandExchange.__isSlotComplete(2));
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__isSlotComplete(geSlot: integer): boolean;
var
TBA: TBoxArray := self.__getSlotBoxes();
begin
result := (countColorTolerance(1799224, TBA[geSlot - 1], 17) > 1700);
print('TRSGrandExchange.isSlotComplete(): Slot ' + toStr(geSlot) + ' = ' + boolToStr(result), TDebug.SUB);
end;
{$ENDIF}
{*
__isSlotAborted
---------------
.. code-block:: pascal
function TRSGrandExchange.__isSlotAborted(geSlot: integer): boolean;
Returns true if the offer is slot **geSlot** is aborted.
.. note::
- by The Mayor
- Last Updated: 15 January 2015 by The Mayor
Example:
.. code-block:: pascal
writeLn(grandExchange.__isSlotAborted(2));
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__isSlotAborted(geSlot: integer): boolean;
var
TBA: TBoxArray := self.__getSlotBoxes();
begin
result := (countColorTolerance(983163, TBA[geSlot - 1], 16) > 1700);
print('TRSGrandExchange.isSlotAborted(): Slot ' + toStr(geSlot) + ' = ' + boolToStr(result), TDebug.SUB);
end;
{$ENDIF}
{*
__isSlotBuying
--------------
.. code-block:: pascal
function TRSGrandExchange.__isSlotBuying(geSlot: integer): boolean;
Returns true if the offer is slot **geSlot** is currently buying.
.. note::
- by The Mayor
- Last Updated: 31 July 2015 by The Mayor
Example:
.. code-block:: pascal
writeLn(grandExchange.__isSlotBuying(2));
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__isSlotBuying(geSlot: integer): boolean;
var
TBA: TBoxArray := self.__getSlotBoxes();
TPA, TPA2: TPointArray;
begin
if self.__isSlotAborted(geSlot) or self.__isSlotComplete(geSlot)
then exit(false);
findColors(TPA, 2433824, TBA[geSlot - 1]);
findColors(TPA2, 3815734, TBA[geSlot - 1]); // If hovering the box
TPA.combine(TPA2);
result := (length(TPA) > 10000);
print('TRSGrandExchange.isSlotBuying(): Slot ' + toStr(geSlot) + ' = ' + boolToStr(result), TDebug.SUB);
end;
{$ENDIF}
{*
__isSlotSelling
---------------
.. code-block:: pascal
function TRSGrandExchange.__isSlotSelling(geSlot: integer): boolean;
Returns true if the offer is slot **geSlot** is currently selling.
.. note::
- by The Mayor
- Last Updated: 31 July 2015 by The Mayor
Example:
.. code-block:: pascal
writeLn(grandExchange._isSlotSelling(2));
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__isSlotSelling(geSlot: integer): boolean;
var
TBA: TBoxArray := self.__getSlotBoxes();
TPA, TPA2: TPointArray;
begin
if self.__isSlotAborted(geSlot) or self.__isSlotComplete(geSlot)
then exit(false);
findColors(TPA, 3287837, TBA[geSlot - 1]);
findColors(TPA2, 4603955, TBA[geSlot - 1]); // If hovering the box
TPA.combine(TPA2);
result := (length(TPA) > 10000);
print('TRSGrandExchange.isSlotSelling(): Slot ' + toStr(geSlot) + ' = ' + boolToStr(result), TDebug.SUB);
end;
{$ENDIF}
{*
__findInsertionCursor
---------------------
.. code-block:: pascal
TRSGrandExchange.__findInsertionCursor(searchBox: TBox; waitTime: integer = 4000): boolean;
Returns true is the insertion cursor is found inside **searchBox** within the **waitTime**
*(default = 4000)* .
.. note::
- by Clarity
- Last Updated: 27 July 2015 by Clarity
Example:
.. code-block:: pascal
writeLn(grandExchange.__findInsertionCursor(b));
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__findInsertionCursor(searchBox: TBox; waitTime: integer = 4000): boolean;
var
timeOut: UInt64;
TPA: TPointArray;
begin
timeOut := getTickCount64() + waitTime;
while getTickCount64() < timeOut do
begin
findColors(TPA, 14606050, searchBox);
if length(TPA) > 0 then
exit(true);
end;
end;
{$ENDIF}
{*
__enterQuantity
---------------
.. code-block:: pascal
procedure TRSGrandExchange.__enterQuantity(quantity: string);
Returns true if it successfully enters the desired item quantity **quantity**
into the input box.
.. note::
- by The Mayor
- Last Updated: 19 November 2015 by The Mayor
Example:
.. code-block:: pascal
grandExchange.__enterQuantity('1500'); // To buy/sell 1500 of an item
grandExchange.__enterQuantity('all'); // To SELL all of the item
*}
{$IFNDEF CODEINSIGHT}
procedure TRSGrandExchange.__enterQuantity(quantity: string);
var
i: integer;
strArr : TStringArray;
inputBox: TBoxArray;
amountBox: TBoxArray := grid(4, 1, 34, 24, 44, 0, point(self.x1 + 84, self.y1 + 298));
begin
strArr := ['1', '10', '100', 'all'];
i := strArr.returnInArray(lowercase(quantity));
if inRange(i, 0, 3) then
mouseBox(amountBox[i], MOUSE_LEFT)
else
begin
inputBox := self.__getInputBoxes();
mouseBox(inputBox[0], MOUSE_LEFT);
if self.__findInsertionCursor(inputBox[0]) then
begin
typeSend(toStr(quantity), true);
wait(randomRange(1000, 1500));
end;
end;
end;
{$ENDIF}
{*
__enterPrice
------------
.. code-block:: pascal
procedure TRSGrandExchange.__enterPrice(price: string);
Returns true if it successfully enters the desired item price **price**
into the input box.
.. note::
- by The Mayor
- Last Updated: 19 November 2015 by The Mayor
Example:
.. code-block:: pascal
grandExchange.__enterPrice('+5'); // Will click the +5% button
grandExchange.__enterPrice('mid'); // Will leave at mid price
grandExchange.__enterPrice('32500'); // Will type in 32500
*}
{$IFNDEF CODEINSIGHT}
procedure TRSGrandExchange.__enterPrice(price: string);
var
i: integer;
b: TBox;
strArr : TStringArray;
priceBox, inputBox: TBoxArray;
begin
priceBox := grid(3, 1, 34, 24, 45, 0, point(self.x1 + 367, self.y1 + 298));
strArr := ['-5', 'mid', '+5'];
i := strArr.returnInArray(lowercase(price));
if (i = 0) or (i = 2) then
mouseBox(priceBox[i], MOUSE_LEFT)
else if (i <> 1) then // Don't click mid button as it's set by default
begin
inputBox := self.__getInputBoxes();
mouseBox(inputBox[2], MOUSE_LEFT);
if self.__findInsertionCursor(inputBox[2]) then
begin
typeSend(toStr(price), true);
wait(randomRange(1000, 1500));
end;
end;
end;
{$ENDIF}
{*
__enterName
-----------
.. code-block:: pascal
procedure TRSGrandExchange.__enterName(itemName: string)
Returns true if it successfully types the item name **itemName** into the search
box and clicks it.
.. note::
- by The Mayor
- Last Updated: 24 Decenber 2015 by The Mayor
Example:
.. code-block:: pascal
grandExchange.__enterName('Swamp toad');
*}
{$IFNDEF CODEINSIGHT}
function TRSGrandExchange.__enterName(itemName: string): boolean;
const
TESS_FILTER_GE_CHARS: TTesseractFilter = [4, 4, [False, 20, TM_Mean]];
var
i: integer;
timeOut: UInt64;
resultsBox: TBoxArray := grid(3, 2, 166, 49, 172, 55, point(self.x1 + 104, self.y1 + 405));
resultsTextBox: TBoxArray := grid(3, 2, 122, 16, 172, 55, point(self.x1 + 121, self.y1 + 396));
inputBox: TBoxArray;
begin
timeOut := getTickCount64() + randomRange(3000, 4000);
inputBox := self.__getInputBoxes();
if not self.__findInsertionCursor(inputBox[1]) then
mouseBox(inputBox[1], MOUSE_LEFT);
if self.__findInsertionCursor(inputBox[1]) then
typeSend(itemName, false);
if waitColorCountRange(9214319, 10, resultsTextBox[0], 5000, 10) then
for i := 0 to 5 do
if stringMatch(trim(tesseractGetText(resultsTextBox[i], TESS_FILTER_GE_CHARS)), itemName) >= 0.7 then
begin
mouseBox(resultsBox[i], MOUSE_LEFT);
waitColorCountRange(16777215, 3, inputBox[2], 5000, 507, 509);
exit(true);
end;
print('TRSGrandExchange.__enterName(): Found no matches for item: ' + itemName, TDebug.SUB);
end;
{$ENDIF}
{*
__returnToSummary
-----------------
.. code-block:: pascal
procedure TRSGrandExchange._returnToSummary();
If the GE offer screen or GE progress screen is currently open, it will click
the back arrow to return to the summary screen.
.. note::
- by The Mayor
- Last Updated: 27 July 2015 by Clarity
Example:
.. code-block:: pascal
grandExchange.__returnToSummary();
*}
{$IFNDEF CODEINSIGHT}
procedure TRSGrandExchange.__returnToSummary();
var
backButton: TPoint := [self.x1 + 33, self.y1 + 515];
timeOut: UInt64;
begin
if self.__isOfferOpen() or self.__isProgressOpen() then
begin
print('TRSGrandExchange._returnToSummary(): returning to summary screen', TDebug.SUB);
multiClick(backButton.rand(5), 30, 3);
timeOut := getTickCount64() + randomRange(2500, 3500);
while getTickCount64() < timeOut do
begin
if ((not self.__isOfferOpen()) and (not self.__isProgressOpen())) then
break();
end;
end;
end;
{$ENDIF}
(*
collectSlot
-----------
.. code-block:: pascal
function TRSGrandExchange.collectSlot(geSlot: integer): boolean;
Returns true if it collects coins and/or items from the completed or aborted slot
**geSlot** .
.. note::
- by The Mayor
- Last Updated: 27 July 2015 by Clarity
Example:
.. code-block:: pascal
grandExchange.collectSlot(2);
*)
function TRSGrandExchange.collectSlot(geSlot: integer): boolean;
var
TBA: TBoxArray := self.__getSlotBoxes();
collectBox: TBoxArray := grid(2, 1, 37, 32, 49, 0, point(self.x1 + 463, self.y1 + 385));
timeOut: UInt64;
i: integer;
begin
if not self.__isProgressOpen() then
begin
self.__returnToSummary();
if (not self.__isSlotActive(geSlot)) or self.__isSlotEmpty(geSlot) then
begin
print('TRSGrandExchange.collectSlot(): Cannot collect as offer slot ' + toStr(geSlot) + ' is empty', TDebug.ERROR);
exit(false);
end;
timeOut := getTickCount64() + randomRange(3000, 4000);
repeat
mouseBox(TBA[geSlot - 1], MOUSE_LEFT);
if self.__isProgressOpen(2000 + random(500)) then
break();
until (getTickCount64() < timeOut);
end;
for i := high(collectBox) downto 0 do
for 0 to 2 do // Attempt up to 3 times in case of lag
if isItemIn(collectBox[i]) then
begin
mouseBox(collectBox[i], MOUSE_LEFT);
wait(randomRange(1750, 2500));
if not self.__isProgressOpen() then
begin
result := true;
break(1);
end;
end;
self.__returnToSummary();
print('TRSGrandExchange.collectSlot(): Slot ' + toStr(geSlot) + ' = ' + boolToStr(result));
end;
(*
waitCollectSlot
---------------
.. code-block:: pascal
function TRSGrandExchange.waitCollectSlot(geSlot, maxTime: integer): boolean;
Returns true if it collects coins and/or items from the completed or aborted slot
**geSlot** . Waits up to **maxTime** for **geSlot** to finish selling.
.. note::
- by The Mayor
- Last Updated: 12 March 2015 by The Mayor
Example:
.. code-block:: pascal
grandExchange.waitCollectSlot(2, 60000); // Wait up to 1 minute to collect slot 2
*)
function TRSGrandExchange.waitCollectSlot(geSlot, maxTime: Integer): boolean;
var
TBA: TBoxArray := self.__getSlotBoxes();
timeOut: UInt64;
begin
self.__returnToSummary();
if (not self.__isSlotActive(geSlot)) or self.__isSlotEmpty(geSlot) then
begin
print('TRSGrandExchange.waitCollectSlot(): Cannot collect as offer slot ' + toStr(geSlot) + ' is empty', TDebug.ERROR);
exit(false);
end;
timeOut := getTickCount64() + maxTime;
while (getTickCount64() < timeOut) do
if self.__isSlotComplete(geSlot) then
begin
if self.collectSlot(geSlot) then
begin
result := true;
break();
end;
end else
wait(500);
print('TRSGrandExchange.waitCollectSlot(): Slot ' + toStr(geSlot) + ' = ' + boolToStr(result), TDebug.SUB);
end;
(*
collectAllSlots
---------------
.. code-block:: pascal
procedure TRSGrandExchange.collectAllSlots(toInventory: boolean = true): boolean;
Collects all coins and items to either the inventory or the bank depending on the
**toInventory** paramter *(default = true)* via the collect buttons.
.. note::
- by The Mayor
- Last Updated: 27 July 2015 by Clarity
Example:
.. code-block:: pascal
grandExchange.collectAllSlots(false); // Collect all to bank
*)
procedure TRSGrandExchange.collectAllSlots(toInventory: boolean = true);
const
_OFFSET: TPoint = [653, 481];
var
TBA: TBoxArray;
begin
TBA := grid(1, 2, 180, 20, 0, 36, point(self.x1 + _OFFSET.x, self.y1 + _OFFSET.y));
case ToInventory of
true: multiClick(TBA[0].getMiddle().rand(5), 25, 3);
false: multiClick(TBA[1].getMiddle().rand(5), 25, 3);
end;
end;
(*
abortSlot
---------
.. code-block:: pascal
function TRSGrandExchange.abortSlot(geSlot: integer; collect: boolean = true): boolean;
Returns true if it aborts the slot **geSlot**. If the **collect** parameter is
set to true it will also collect the items and gold from the aborted offer.
.. note::
- by The Mayor
- Last Updated: 27 July 2015 by Clarity
Example:
.. code-block:: pascal
grandExchange.abortSlot(2);
grandExchange.abortSlot(2, false); // To leave items in the aborted offer slot
*)
function TRSGrandExchange.abortSlot(geSlot: integer; collect: boolean = true): boolean;
var
TBA: TBoxArray := self.__getSlotBoxes();
abortButton: TPoint := [self.x1 + 402, self.y1 + 383];
redBox: TBox := [self.x1 + 29, self.y1 + 404, self.x1 + 423, self.y1 + 410];
begin
if not self.isOpen() then
begin
print('TRSGrandExchange.abortSlot(): Cannot abort as the GE is not open', TDebug.ERROR);
exit(false);
end;
self.__returnToSummary();
if self.__isSlotEmpty(geSlot) or (not self.__isSlotActive(geSlot)) then
begin
print('TRSGrandExchange.abortSlot(): Cannot abort as offer slot ' + toStr(geSlot) + ' is empty', TDebug.ERROR);
exit(false);
end;
if self.__isSlotAborted(geSlot) then
begin
print('TRSGrandExchange.abortSlot(): Offer slot ' + toStr(geSlot) + ' is already aborted');
exit(true);
end;
if self.__isSlotComplete(geSlot) then
begin
print('TRSGrandExchange.abortSlot(): Cannot abort as offer slot ' + toStr(geSlot) + ' is already completed', TDebug.ERROR);
exit(false);
end;
mouseBox(TBA[geSlot - 1], MOUSE_LEFT);
if self.__isProgressOpen(3000) then
begin
multiClick(abortButton.rand(5), 30, 3);
waitColorCountRange(1048714, 5, redBox, 4000, 2000);
if collect then
result := self.collectSlot(geSlot)
else
begin
result := self.__isSlotAborted(geSlot);
self.__returnToSummary();
end;
end;
print('TRSGrandExchange.abortSlot(): Slot ' + toStr(geSlot) + ' = ' + boolToStr(result));
end;
(*
abortAllSlots
-------------
.. code-block:: pascal
procedure TRSGrandExchange.abortAllSlots(collect: boolean);
Aborts all slots that are not currently empty. If the **collect** parameter is
set to true, it will also collect all items and gold.
.. note::
- by The Mayor
- Last Updated: 12 March 2015 by The Mayor
Example:
.. code-block:: pascal
grandExchange.abortAllSlots();
*)
procedure TRSGrandExchange.abortAllSlots(collect: boolean = true);
var
i: integer;
TBA: TBoxArray := self.__getSlotBoxes();
begin
for i := 1 to length(TBA) do
if (not self.__isSlotEmpty(i)) and self.__isSlotActive(i) then
self.abortSlot(i, collect);
end;
(*
getPercentDone
--------------
.. code-block:: pascal
function TRSGrandExchange.getPercentDone(geSlot: integer): integer;
Returns the percentage toward completion for the offer in **geSlot** .
.. note::
- by turpinator
- Last Updated: 19 November 2015 by SlipperyPickle
Example:
.. code-block:: pascal
var
per: Integer;
begin
per := grandExchange.getPercentDone(2);
writeLn('Slot 2 is ' + toStr(per) + ' percent complete!');
end;
*)
function TRSGrandExchange.getPercentDone(geSlot: integer): integer;
const
BG_COLORS = [2565929, 2039584, 2237482, 1776673];
var
i, x, y: integer;
TBA: TBoxArray := self.__getSlotBoxes();
begin
if self.__isSlotEmpty(geSlot) or (not self.__isSlotActive(geSlot)) then exit(-1);
x := TBA[geSlot -1].x1 + 8;
y := TBA[geSlot -1].y1 + 100;
for result := 153 downto 1 do
if (getColor(x + result, y) <> BG_COLORS[0]) and (getColor(x + result, y) <> BG_COLORS[1]) then
exit(round(0.6897 * result));
end
(*
sellItem
--------
.. code-block:: pascal
function TRSGrandExchange.sellItem(packSlot: integer; price, quantity: string; waitCollect: boolean = false; waitTime: integer = 10000): boolean;
Returns true if it sells the item in backpack slot **packSlot** . If **waitCollect**
is set to true, it will wait the specified waitTime for the offer to complete
before collecting the resulting gold.
The **price** parameter is a string - valid options are:
* 'mid' : GE mid price button
* '-5' : 5% below mid price button
* '+5' : 5% above mid price button
* Any other number : It will enter the price
The **quantity** parameter is a string - valid options are:
* '1' : '1' button
* '10' : '10' button
* '100' : '100' button
* 'all' : 'All' button (Selling ONLY)
* Any other number : It will enter the quantity
.. note::
- by The Mayor
- Last Updated: 13 November 2015 by SlipperyPickle
Example:
.. code-block:: pascal
// Sell all of item in backPack slot 1 for mid price
grandExchange.sellItem(1, 'mid', 'all');
// To sell 100 of the item in backPack slot 1, for 1500gp each
grandExchange.sellItem(1, '1500', '100');
// As above, but waits up to 20 seconds for completion before collecting the coins
grandExchange.sellItem(1, '1500', '100', true, 20000);
*)
function TRSGrandExchange.sellItem(packSlot: integer; price, quantity: string; waitCollect: boolean = false; waitTime: integer = 10000): boolean;
var
i, nextSlot: integer;
confirm: TBox := [self.x1 + 225, self.y1 + 518, self.x1 + 373, self.y1 + 542];
begin
if not self.isOpen() then
begin
print('TRSGrandExchange.sellItem(): Cannot abort as the GE is not open', TDebug.ERROR);
exit(false);
end;
self.__returnToSummary();
for i := 1 to 8 do
if self.__isSlotEmpty(i) and self.__isSlotActive(i) then
begin
nextSlot := i;
break();
end;
if nextSlot < 1 then
begin
print('TRSGrandExchange.sellItem(): Cannot sell item as there are no empty offer slots', TDebug.ERROR);
exit(false);
end;
if isItemIn(self.getPackSlotBox(packSlot)) then
mouseBox(self.getPackSlotBox(packSlot), MOUSE_LEFT)
else
begin
print('TRSGrandExchange.sellItem(): No item in pack slot: ' + intToStr(packSlot), TDebug.ERROR);
exit(false);
end;
if self.__isOfferOpen(3000) then
begin
self.__enterQuantity(quantity);
self.__enterPrice(price);
mouseBox(confirm, MOUSE_LEFT);
wait(randomRange(1000, 1500));
end;
result:= self.__isSlotSelling(nextSlot);
print('TRSGrandExchange.sellItem(): ' + boolToStr(result), TDebug.SUB);
if waitCollect then
self.waitCollectSlot(nextSlot, waitTime);
end;
(*
buyItem
-------
.. code-block:: pascal
function TRSGrandExchange.buyItem(itemName, price, quantity: string; waitCollect: boolean = false; waitTime: integer = 10000): boolean;
Returns true if it buys the item **itemName** . If **waitCollect** is set to true,
it will wait the specified waitTime for the offer to complete before collecting
the resulting gold and items.
The **price** parameter is a string - valid options are:
* 'mid' : GE mid price button
* '-5' : 5% below mid price button
* '+5' : 5% above mid price button
* Any other number : It will enter the price
The **quantity** parameter is a string - valid options are:
* '1' : '1' button
* '10' : '10' button
* '100' : '100' button
* Any other number : It will enter the quantity
.. note::
- by The Mayor
- Last Updated: 13 November 2015 by SlipperyPickle
Example:
.. code-block:: pascal
// To buy 10000 oak logs at 5% over the mid price
grandExchange.buyItem('Oak log', '+5', '10000');
// To buy 10000 oak logs for 150gp each
grandExchange.buyItem('Oak log', '150', '10000');
// As above, but waits up to 20 seconds for completion before collecting items
grandExchange.buyItem('Oak log', '150', '10000', true, 20000);
*)
function TRSGrandExchange.buyItem(itemName, price, quantity: string; waitCollect: boolean = false; waitTime: integer = 10000): boolean;
var
i, nextSlot, x, y: integer;
b: TBox;
TBA : TBoxArray := self.__getBuyBoxes();
confirm: TBox := [self.x1 + 225, self.y1 + 518, self.x1 + 373, self.y1 + 542];
begin
if not self.isOpen() then
begin
print('TRSGrandExchange.sellItem(): Cannot abort as the GE is not open', TDebug.ERROR);
exit(false);
end;
self.__returnToSummary();
for i := 1 to 8 do
if self.__isSlotEmpty(i) and self.__isSlotActive(i) then
begin
nextSlot := i;
break();
end;
if nextSlot < 1 then
begin
print('TRSGrandExchange.sellItem(): Cannot sell item as there are no empty offer slots', TDebug.ERROR);
exit(false);
end;
mouseBox(TBA[nextSlot - 1], MOUSE_LEFT);
if self.__isOfferOpen(3000) then
if self.__enterName(itemName) then
begin
self.__enterQuantity(quantity);
self.__enterPrice(price);
mouseBox(confirm, MOUSE_LEFT);
wait(randomRange(1000, 1500));
end else
self.__returnToSummary();
result := self.__isSlotBuying(nextSlot);
print('TRSGrandExchange.buyItem(): ' + boolToStr(result), TDebug.SUB);
if waitCollect then
self.waitCollectSlot(nextSlot, waitTime);
end;
(*
getPrice
--------
.. code-block:: pascal
TRSGrandExchange.getPrice(item: integer): integer;
Returns the current market price of any item in the Grand Exchange. The **item**
parameter must be the item's ID number.
IDs can be found on the Grand Exchange website at the end of the URL. For example,
the ID in the below URL is 2150 (Swamp toad)
http://services.runescape.com/m=itemdb_rs/viewitem.ws?obj=2150
.. note::
- by The Mayor
- Last Updated: 16 July 2015 by The Mayor
Example:
.. code-block:: pascal
var
toadPrice: Integer;
begin
toadPrice := grandExchange.getPrice(2150); // The ID for Swamp toads
profit := (toadPrice * toadsCollected);
end;
*)
function TRSGrandExchange.getPrice(ID: integer): integer;
var
webPage: string;
TSA: TStringArray;
begin
webPage := getPage('http://services.runescape.com/m=itemdb_rs/viewitem.ws?obj=' + toStr(ID));
TSA := multiBetween(webPage, 'average30.push([new Date(',']);');
if length(TSA) < 1 then
begin
print('TRSGrandExchange.getPrice(): Unable to retrieve price for ID: ' + toStr(ID), TDebug.ERROR);
exit(-1);
end;
result := strToInt(Between('), ', ',', TSA[High(TSA)]));
print('TRSGrandExchange.getPrice(' + toStr(ID) + '): ' + toStr(result));
end;
begin
grandExchange.__init();
end;
{$f+}