Page 1 of 2 12 LastLast
Results 1 to 25 of 43

Thread: Surfaces! - Accurate way of locating objects in RuneScape.

  1. #1
    Join Date
    May 2007
    Posts
    526
    Mentioned
    12 Post(s)
    Quoted
    109 Post(s)

    Default Surfaces! - Accurate way of locating objects in RuneScape.

    Good day folks,

    I wanted to explain and show my surfaces-system, which should be quite useful for finding objects accurately in RuneScape.
    You might have seen it in action in my script Irony. So, to cut the chase, the basic part of a surface consists of the following
    structure:

    Simba Code:
    type
        TSurfacePart = record
            // The filter function which ultimately decides which surface to pick up.
            filter: TSurfacePartFilterFunc;
           
            // Hue modifier.
            hm: extened;

            // Saturation modifier.
            sm: extended;

            // Color.
            c: integer;

            // Tolerance.
            t: integer;

            // Minimum width of the surface.
            minw: integer;

            // Maximum width of the surface.
            maxw: integer;

            // Minimum height of the surface.
            minh: integer;

            // Maximum height of the surface.
            maxh: integer;

            // Offset Y-axis, from the median.
            off_y: integer;

            // Offset X-axis, from the median.
            off_x: integer;

            // A simple TBox containing the bounds of the surface.
            bounds: TBox;

            // Pixel density / distance.
            step: integer;

            // Ignore, for internal use.
            index: integer;

            // The point where the surface was found.
            p: TPoint;

            // Ignore, for internal use.
            base_atpa: T2DPointArray;

            // Maximum distance allowed, where the surface can be found.
            max_distance: integer;
        end;

    One of the useful things about the system is that you can define a surface object which
    constructs out of multiple surfaces. This ensures great accuracy.

    Maybe it's the best to demonstrate this through an example. Lets take an iron rock and try to detect it, closest to us
    and as accurately as possible! First off, you need to define your surface variable for the rock itself. Not iron rock, but an
    empty one instead! Lets call it..

    Simba Code:
    var
        surface_rock: TSurfacePart;

    Fantastic, now lets put there some values:

    Simba Code:
    // c, hm, sm and t can be neatly found with the wonderful ACA.

    with surface_rock do begin
        c    := 3367539;
        hm   := 0.02;
        sm   := 0.07;
        t    := 16;
        minw := 4;  // At least 4 pixels wide.
        maxw := 80; // No more than 80 pixels wide.
        minh := 4;  // At least 4 pixels tall.
        maxh := 80; // No more than 80 pixel tall.
        step := 9;
        max_distance := 200;
    end;

    We can use now surface_rock as a base for all type of rocks, like iron, mithril and adamantite, since all of those has the same
    looking rock when its empty or mined.

    Now, lets define our iron rock surface object:

    Simba Code:
    var
        obj_iron_rock: TSurfaceObject;

    As explained above, we use the base surface for all type of rocks:

    Simba Code:
    // We need two different surfaces for iron rock. The rock and the brown part in middle of it.
    // Remember, the consecutive parts has to be found inside the previous one.
    CreateSurfaceParts(obj_iron_rock, 2);

    with obj_iron_rock do begin
        // So, the first part we copy:
        parts[0] := CopySurfacePart(surface_rock);

        // And then the second one, which is the brown part in iron rock when it's not mined yet.
        // For mithril, you can use ACA for the blue-part, etc.
        parts[1].c            := 2831959;
        parts[1].hm           := 0.05;
        parts[1].sm           := 0.64;
        parts[1].t            := 10;
        parts[1].filter       := @SurfaceFilterClosest; // We want to have the closest iron rock next to us.
        parts[1].minw         := 1;
        parts[1].maxw         := parts[0].maxw;
        parts[1].minh         := 1;
        parts[1].maxh         := parts[0].maxh;
        parts[1].step         := 16;
        parts[1].max_distance := parts[0].max_distance;

        name := 'Iron ore';
        uptext := 'Iron';
        filter := @SurfaceFilterClosest;
    end;

    That's pretty much the basics. Now if you want to find an iron rock, you can simply call

    Simba Code:
    if FindSurfaceObject(obj_iron_rock, MSX1, MSY1, MSX2, MSY2) then begin
        WriteLn('Found the iron rock!');

        // Now you can click the iron rock, if you wish..

        with obj_iron_rock do
            Mouse(p.x, p.y, 2, 2, mouse_left);
    end;

    and you should get this:



    If you want the system to automatically click it, you can call

    Simba Code:
    if ClickSurfaceObject(obj_iron_rock, true) then // False for left click through menu instead.
        WriteLn('Clicked iron ore!');

    You can download su_surfaces.simba, which contains all the necessary functions etc. To summarize, here's the actual script
    which find you the iron ore:

    Simba Code:
    program surfaces;

    {$DEFINE SMART}

    {$i srl\srl.simba}
    {$i srl\srl\misc\SmartGraphics.simba}

    {$i su_surfaces.simba}

    var
        surface_rock: TSurfacePart;
        obj_iron_rock: TSurfaceObject;

    procedure Init();
    begin
        SetupSRL();
        SMART_ClearMS();

        with surface_rock do begin
            c    := 3367539;
            hm   := 0.02;
            sm   := 0.07;
            t    := 16;
            minw := 4;  // At least 4 pixels wide.
            maxw := 80; // No more than 80 pixels wide.
            minh := 4;  // At least 4 pixels tall.
            maxh := 80; // No more than 80 pixel tall.
            step := 9;
            max_distance := 200;
        end;

        CreateSurfaceParts(obj_iron_rock, 2);

        with obj_iron_rock do begin
            // So, the first part we copy:
            parts[0] := CopySurfacePart(surface_rock);

            // And then the second one, which is the brown part in iron rock when it's not mined yet.
            parts[1].c            := 2831959;
            parts[1].hm           := 0.05;
            parts[1].sm           := 0.64;
            parts[1].t            := 10;
            parts[1].filter       := @SurfaceFilterClosest; // We want to have the closest iron rock next to us.
            parts[1].minw         := 1;
            parts[1].maxw         := parts[0].maxw;
            parts[1].minh         := 1;
            parts[1].maxh         := parts[0].maxh;
            parts[1].step         := 16;
            parts[1].max_distance := parts[0].max_distance;

            name := 'Iron ore';
            uptext := 'Iron';
            filter := @SurfaceFilterClosest;
        end;
    end;

    begin
        Init();

        if FindSurfaceObject(obj_iron_rock, MSX1, MSY1, MSX2, MSY2) then begin
            WriteLn('Found the iron rock at ' + IntToStr(obj_iron_rock.p.x) + ', ' + IntToStr(obj_iron_rock.p.y));
        end;
    end.

    There's still more to the surfaces, but this'll get you started. Please shoot if you have any guestions.

    Edit:

    Just a curious thought, but it would be possible to create huge database of various objects (surfaces) of RuneScape. Now
    wouldn't that be nice, eh?

    All the best,
    superuser
    Attached Images Attached Images
    Attached Files Attached Files

  2. #2
    Join Date
    Feb 2013
    Posts
    465
    Mentioned
    6 Post(s)
    Quoted
    221 Post(s)

    Default

    First, this looks really nice. The example you provide is exactly how my Lumbridge miner works, it first finds all the empty rocks then finds the ore veins inside them.

  3. #3
    Join Date
    Oct 2012
    Posts
    758
    Mentioned
    6 Post(s)
    Quoted
    282 Post(s)

    Default

    wow this really nice
    I will use in all my script if I make a script k bye

  4. #4
    Join Date
    Jun 2012
    Location
    Howell, Michigan
    Posts
    1,585
    Mentioned
    34 Post(s)
    Quoted
    553 Post(s)

    Default

    This is awesome! im going to try this out in some scripts I am making I'll post the results!(:

  5. #5
    Join Date
    Aug 2007
    Location
    Colorado
    Posts
    7,421
    Mentioned
    268 Post(s)
    Quoted
    1442 Post(s)

    Default

    Really nice job with this superuser!

    Current projects:
    [ AeroGuardians (GotR minigame), Motherlode Miner, Blast furnace ]

    "I won't fall in your gravity. Open your eyes,
    you're the Earth and I'm the sky..."


  6. #6
    Join Date
    Oct 2012
    Posts
    758
    Mentioned
    6 Post(s)
    Quoted
    282 Post(s)

    Default

    have you use for anything else than mining?
    like treeS?

  7. #7
    Join Date
    May 2007
    Posts
    526
    Mentioned
    12 Post(s)
    Quoted
    109 Post(s)

    Default

    Quote Originally Posted by Runehack123 View Post
    have you use for anything else than mining?
    like treeS?
    Yeah, take a look at Superuser's Arctic Pines

  8. #8
    Join Date
    Oct 2012
    Posts
    758
    Mentioned
    6 Post(s)
    Quoted
    282 Post(s)

    Default

    Quote Originally Posted by superuser View Post
    Yeah, take a look at Superuser's Arctic Pines
    will do thanks
    this is so nice

  9. #9
    Join Date
    May 2007
    Posts
    526
    Mentioned
    12 Post(s)
    Quoted
    109 Post(s)

    Default

    Quote Originally Posted by Flight View Post
    Really nice job with this superuser!
    Quote Originally Posted by SRLKing View Post
    This is awesome! ...
    Quote Originally Posted by Runehack123 View Post
    wow this really nice ...
    Thanks ya'll. I know I didn't give the most explaining tutorial, but please, try it out and as I said, ask if you got something on your mind!

  10. #10
    Join Date
    Oct 2012
    Posts
    758
    Mentioned
    6 Post(s)
    Quoted
    282 Post(s)

    Default

    Quote Originally Posted by superuser View Post
    Thanks ya'll. I know I didn't give the most explaining tutorial, but please, try it out and as I said, ask if you got something on your mind!
    maybe brief summary at top for tl;dr user would help some people
    or summary at bottom

  11. #11
    Join Date
    Dec 2011
    Location
    Hyrule
    Posts
    8,662
    Mentioned
    179 Post(s)
    Quoted
    1870 Post(s)

  12. #12
    Join Date
    Mar 2012
    Location
    Over there
    Posts
    840
    Mentioned
    4 Post(s)
    Quoted
    42 Post(s)

    Default

    Looks very accurate, thanks for sharing!

  13. #13
    Join Date
    Apr 2012
    Posts
    157
    Mentioned
    10 Post(s)
    Quoted
    57 Post(s)

    Default

    superuser, how does this compare to say...getting the colors in a TPA, and then sorting the TPA/ATPA and scanning it by size?

  14. #14
    Join Date
    Jun 2012
    Location
    Howell, Michigan
    Posts
    1,585
    Mentioned
    34 Post(s)
    Quoted
    553 Post(s)

    Default

    Quote Originally Posted by serajin View Post
    superuser, how does this compare to say...getting the colors in a TPA, and then sorting the TPA/ATPA and scanning it by size?
    Ive used it in a mining script and seems to be more reliable for me, and has a much wider range of uses. TPA/ATPA's only go so far, this works very well for things like banking(;

  15. #15
    Join Date
    Apr 2012
    Posts
    157
    Mentioned
    10 Post(s)
    Quoted
    57 Post(s)

    Default

    Cool stuff. I'll have to give it a go in my next script then.

  16. #16
    Join Date
    May 2007
    Posts
    526
    Mentioned
    12 Post(s)
    Quoted
    109 Post(s)

    Default

    Quote Originally Posted by serajin View Post
    superuser, how does this compare to say...getting the colors in a TPA, and then sorting the TPA/ATPA and scanning it by size?
    It's pretty much what you say, but the include gives you much more flexibility and convenience.

  17. #17
    Join Date
    Jul 2011
    Location
    /home/litoris
    Posts
    2,226
    Mentioned
    0 Post(s)
    Quoted
    159 Post(s)

    Default

    Very nice! I never knew about surfaces, and this looks os professional I do a watered down version of this in my miner, using two colors for the iron rock, but this is insane!
    You should make this support other CTS's (cts 1 is much faster tough less accurate, cts 3 is kinda slow but more accurate, and its easier to pick colors for cts 1)
    Miner & Urn Crafter & 07 Chicken Killer
    SPS BlindWalk Tutorial

    Working on: Nothing

    teacher in every art, brought the fire that hath proved to mortals a means to mighty ends

  18. #18
    Join Date
    May 2007
    Posts
    526
    Mentioned
    12 Post(s)
    Quoted
    109 Post(s)

    Default

    Quote Originally Posted by litoris View Post
    Very nice! I never knew about surfaces, and this looks os professional I do a watered down version of this in my miner, using two colors for the iron rock, but this is insane!
    You should make this support other CTS's (cts 1 is much faster tough less accurate, cts 3 is kinda slow but more accurate, and its easier to pick colors for cts 1)
    Trust me, this is fast enough (CTS2) Beats constantly Java-bots at the same area

  19. #19
    Join Date
    Apr 2012
    Posts
    157
    Mentioned
    10 Post(s)
    Quoted
    57 Post(s)

    Default

    Quote Originally Posted by superuser View Post
    It's pretty much what you say, but the include gives you much more flexibility and convenience.
    Cool stuff! I'll give it a go =D

  20. #20
    Join Date
    Jan 2013
    Posts
    294
    Mentioned
    1 Post(s)
    Quoted
    121 Post(s)

    Default

    does this work with objects without >2 color? since iron ore has a base empty ore color state, and an iron ore color. does it work with, lets say mithril ore when it was wholely colored blueish.

  21. #21
    Join Date
    May 2007
    Posts
    526
    Mentioned
    12 Post(s)
    Quoted
    109 Post(s)

    Default

    Quote Originally Posted by dzpliu View Post
    does this work with objects without >2 color? since iron ore has a base empty ore color state, and an iron ore color. does it work with, lets say mithril ore when it was wholely colored blueish.
    Yes, it works with one part as well. You can define as many parts as you wish. And yes, it works with mithril ore as well.

  22. #22
    Join Date
    Mar 2007
    Posts
    393
    Mentioned
    1 Post(s)
    Quoted
    98 Post(s)

    Default

    very nice guide!

  23. #23
    Join Date
    Jan 2013
    Posts
    294
    Mentioned
    1 Post(s)
    Quoted
    121 Post(s)

    Default

    how do i use this to search multi-objects? lets say there are 2 type of this butterfly of different color in this specified area, i wan to use it to find both of them and catch either one if it detects them.

  24. #24
    Join Date
    Feb 2012
    Location
    Wonderland
    Posts
    1,988
    Mentioned
    41 Post(s)
    Quoted
    272 Post(s)

    Default

    Quote Originally Posted by dzpliu View Post
    how do i use this to search multi-objects? lets say there are 2 type of this butterfly of different color in this specified area, i wan to use it to find both of them and catch either one if it detects them.
    I'd assume (didn't test nor study superuser's [awesome] code), that you could simply create two variables of the type TSurfaceObject and search for both. This would probably be an unoptimized approach, but also the more simple to use if you're not fully aware of every/most things happening in the code (the butterfly's could potentially differ to the extent where they don't share very many parts either).

  25. #25
    Join Date
    Sep 2010
    Posts
    5,762
    Mentioned
    136 Post(s)
    Quoted
    2739 Post(s)

    Default

    I'm confused, how do you make 2 parts?

    @superuser
    Simba Code:
    procedure InitRocks();
    begin
        SMART_ClearMS();

        with surface_rock do begin
            c    := 1070711;
            hm   := 0.02;
            sm   := 0.19;
            t    := 6;
            minw := 4;  // At least 4 pixels wide.
            maxw := 80; // No more than 80 pixels wide.
            minh := 4;  // At least 4 pixels tall.
            maxh := 80; // No more than 80 pixel tall.
            step := 9;
            max_distance := 200;
        end;

        CreateSurfaceParts(obj_coal_rock, 2);

        with obj_coal_rock do begin
            // So, the first part we copy:
            parts[0] := CopySurfacePart(surface_rock);

            // And then the second one, which is the brown part in iron rock when it's not mined yet.
            parts[1].c            := 1251873;
            parts[1].hm           := 1.39;
            parts[1].sm           := 4.49;
            parts[1].t            := 6;
            parts[1].filter       := @SurfaceFilterClosest; // We want to have the closest iron rock next to us.
            parts[1].minw         := 5;
            parts[1].maxw         := parts[0].maxw;
            parts[1].minh         := 5;
            parts[1].maxh         := parts[0].maxh;
            parts[1].step         := 16;
            parts[1].max_distance := parts[0].max_distance;

            name := 'Coal ore';
            uptext := 'Coal';
            filter := @SurfaceFilterClosest;
        end;


         with surface_bank do begin
            c    := 6713206;
            hm   := 0.29;
            sm   := 0.08;
            t    := 5;
            minw := 4;  // At least 4 pixels wide.
            maxw := 40; // No more than 80 pixels wide.
            minh := 4;  // At least 4 pixels tall.
            maxh := 100; // No more than 80 pixel tall.
            step := 9;
            max_distance := 250;
        end;

        CreateSurfaceParts(obj_Deposite, 2);

        with obj_deposite do begin
            // So, the first part we copy:
            parts[1] := CopySurfacePart(surface_bank);

            // And then the second one, which is the brown part in iron rock when it's not mined yet.
            parts[1].c            := 6653336;
            parts[1].hm           := 0.11;
            parts[1].sm           := 0.39;
            parts[1].t            := 3;
            parts[1].filter       := @SurfaceFilterClosest; // We want to have the closest iron rock next to us.
            parts[1].minw         := 5;
            parts[1].maxw         := parts[1].maxw;
            parts[1].minh         := 5;
            parts[1].maxh         := parts[1].maxh;
            parts[1].step         := 16;
            parts[1].max_distance := parts[1].max_distance;

            name := 'Deposite booth';
            uptext := 'deposite';
            filter := @SurfaceFilterClosest;
        end;
    end;

    Does not seem to work?

Page 1 of 2 12 LastLast

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
  •