Results 1 to 1 of 1

Thread: Find objects with SRL & RSWalker

  1. #1
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default Find objects with SRL & RSWalker

    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.
    Last edited by slacky; 04-27-2018 at 12:37 AM.
    !No priv. messages please

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •