What's needed for this totorial:
> Simba 1.2 RC6 - fixes (drop the .exe in Simba folder, and use it instead of Simba.exe)
> SRL for OSRS
> RSWalker (download)
> SPSToolbox
A fancy simple way to find objects using RSWalker and SRL:
It builds around RSWalker's GetTileMSEx, which will take a worldmap coordinate and convert it to a local tile on the mainscreen.
So first we can do with a simple datatype that stores the object, and the many locations it can be at:
Simba Code:
type
TMSObject = record
WorldLoc: TPointArray; // loctions on the world map
Color: TCTS2Color; // must have color
MinCount: Int32; // size of TPA
SplitDist: Int32;
end;
That should be sufficient for most cases..
Then we need a function to utilize the above stuff, perhaps something like this:
Simba Code:
function TMSObject.Find(DoSort: Boolean=True; Expand:Int32=0): TRectArray;
var
loc, me: TPoint;
rect: TRectangle;
locations, TPA: TPointArray;
ATPA: T2DPointArray;
begin
me := RSW.GetMyPos();
locations := Copy(Self.WorldLoc);
if DoSort then Locations.Sorted(me);
for loc in Locations do
begin
rect := RSW.GetTileMsEx(me, loc, 1).Expand(Expand);
if MainScreen.GetBounds.Contains(rect.Bounds) then
begin
if (srl.FindColors(TPA, Color, rect.Bounds) < Self.MinCount) then
Continue;
if (Self.SplitDist > 0) then
begin
TPA := rect.Filter(TPA);
ATPA := TPA.Cluster(Self.SplitDist);
SortATPAFromSize(ATPA, 0, False);
Result += ATPA[0].MinAreaRect;
end else
Result += rect;
end;
end;
end;
A bit complex I guess, but at least that reduces the chance of it failing. You might have spotted that it has two result scenarios depending on if you specify a split distance or not.. if you don't then the color count is all that is taken into account, and it returns the tile as returned by `GetTileMSEx`, that's fine for a lot of simple cases.
The latter one will split and return the rectangle covering the largest TPA within the rectangle returned by `GetTileMSEx`.
Since neither RSWalker nor MM2MS is perfectly accurate the result may vary depending on your location, compass angle, and other factors that affect the minimap, and MM2MS is imperfect as a result of the camera not being perfectly focused on your character, and height differences between you and the object tile.
As a result of those, I've added a "Expand"-parameter, which will expand the area of the tile returned by `GetTileMSEx`. You might wanna play with the function I created, adjust it for your use if it's not suitable out of the box.
So, how do you get the world location of the objects? Well that's like making a path to walk with RSWalker, grab https://github.com/TheTS/SPSToolbox/releases and then just click the object locations.. might need to manually adjust the coordinate +/-2 px afterwards for optimal experience.
Putting it all together in a test script:
Simba Code:
program new;
{$H-}
{$define SMART}
{$I SRL/OSR.simba}
{$I RSWalker/Walker.simba}
type
TMSObject = record
WorldLoc: TPointArray; //loctions on the world map
Color: TCTS2Color; //must have color
MinCount: Int32; //size of TPA
SplitDist: Int32;
end;
var
RSW: TRSWalker;
function TMSObject.Find(DoSort: Boolean=True; Expand:Int32=0): TRectArray;
var
loc, me: TPoint;
rect: TRectangle;
locations, TPA: TPointArray;
ATPA: T2DPointArray;
begin
me := RSW.GetMyPos();
locations := Copy(Self.WorldLoc);
if DoSort then Locations.Sorted(me);
for loc in Locations do
begin
rect := RSW.GetTileMSEx(me, loc, 1).Expand(Expand);
if MainScreen.GetBounds.Contains(rect.Bounds) then
begin
if (srl.FindColors(TPA, Color, rect.Bounds) < Self.MinCount) then
Continue;
if (Self.SplitDist > 0) then
begin
TPA := rect.Filter(TPA);
ATPA := TPA.Cluster(Self.SplitDist);
ATPA.SortByMiddle(rect.Mean);
Result += ATPA[0].MinAreaRect;
end else
Result += rect.Expand(-Expand);
end;
end;
end;
procedure Test();
var
i: Int32;
obj: TMSObject;
rectangles: array of TRectangle;
begin
while True do
begin
// two booth locations, color of booth, min points, splitDist
obj := [[[143, 176], [147, 176]], CTS2(2380900,30), 200, 8];
rectangles := obj.Find(True, 3);
smart.Image.Clear();
for i:=0 to High(rectangles) do
smart.Image.DrawTPA(rectangles[i].ToTPA.Connect, $00FFFF);
end;
end;
begin
smart.EnableDrawing := True;
srl.Setup([]);
RSW.Init('images/varrock.png', -1);
test();
RSW.Free();
end.
This is my Varrock image used in the above test: https://i.imgur.com/xxQDMyo.png
PS: This concept is at the core of my Universal Miner, and is the sole reason I bothered making it.