Jump to content

Pandemic's Scripting Series: Part II - Path Walking and Simple Banking [UPDATED FOR OSBOT 2]


Pandemic
 Share

Recommended Posts

Updated for OSBot 2's API!

 

Hello again everyone! I hope you enjoyed my first tutorial, and I hope you'll enjoy this on as well.

All feedback is appreciated, so feel free to post your thoughts!

This tutorial will use some of my methods for simple banking and path walking!

We’ll expand upon our script we were working on last time, so you'll need the source.

 

Step I: Converting to a Banking Script

Now as we all know, this script isn’t only boring, it will keep trying to click the rocks after we mine them, even if that vein isn’t ready!

To remedy this, we’ll be searching for the rocks using object IDs instead of names.

Since we’ll be using specific IDs, we have to choose what and where we’ll be mining!

For this second tutorial, we’ll make a script that mines tin in the mines south-east of Varrock:

02bSm2H.png

Finding Object IDs

Finding object IDs in OSBot is very simple, stand near the object you want the ID of, press Settings:

uwp87qw.png

Then press Advanced Settings:

zhX3FFR.png

Then finally press Object Info:

pMbAytc.png

This will lag your client a lot, but don’t worry, you can shut it off as soon as you get the IDs.

To get the ID, just look for the number near/on the object you’re looking for:

SJRT6zu.png

Note: Some objects and NPCs in Runescape have deviations of themselves (like tin), so the same object/NPC may have different IDs (make sure to get all the IDs of whatever you’re using).

Now that we have tin’s ID, we’ll make a constant in our script:

private static final int[] TIN_ID = { 7140, 7141, 7142 };

We’ll put this line right after this:
 

public class BasicMiner extends Script {

Now that we have the object ID found and defined, let’s change our original code to use the ID instead of a name, simply by changing this line:
 

RS2Object vein = objects.closest("Rocks”);

to this:
 

RS2Object vein = objects.closest(TIN_ID);

Step II: Area Based State

For this script, we’ll see which state we should be in with the help of OSBot’s Area class, which is defined as Area(int x1, int y1, int x2, int y2).

Simply stand on two opposite corners and fill in the x and y.

For the areas, put this after our path variable:

private static final Area MINE_AREA = new Area(3277, 3358, 3293, 3371);
private static final Area BANK_AREA = new Area(3250, 3419, 3257, 3423);

Step II: Path Making

The first step to path walking, would be path making!

We’ll be making a path by enabling the “Player Position” setting (same place we enabled Object Info):

4pbD76a.png

Now, I like to open notepad, or some other text editor while finding my path, so do that now.

Alright, finding a path to the bank is pretty simple, but can be slightly confusing at first.

Start at the tin veins, and add the position you’re current at (this will be used when we reverse the path to walk from the bank back):

Arp8hnA.png

Then act like you’re walking to the bank, but only press ONCE on the minimap.

Let your player walk to that position and stop, then write down your first position to that path.

mHVTrnC.png

Then keep doing that until you’re in the bank, here’s what I got:

3283, 3363
3290, 3374
3292, 3386
3290, 3374
3291, 3401
3287, 3413
3282, 3427
3270, 3429
3256, 3429
3254, 3421

To turn this path into something we can use in our script, we’ll be using an array (collection of a type of variable).

We’ll put this line of code right after where we defined TIN_ID:
 

private Position[] path = {
     new Position(3283, 3363, 0),
     new Position(3290, 3374, 0),
     new Position(3292, 3386, 0),
     new Position(3290, 3374, 0),
     new Position(3291, 3401, 0),
     new Position(3287, 3413, 0),
     new Position(3282, 3427, 0),
     new Position(3270, 3429, 0),
     new Position(3256, 3429, 0),
     new Position(3254, 3421, 0)
};

Yay! We now have a full path from the mines to the bank, which we’ll reverse to go from the bank to the mines (saving us a step)!

Step IV: Path Walking

Now that we have a path, let’s put it to use!

First of all, let’s change our enum by removing the DROP constant, and adding WALK_TO_BANK, BANK, WALK_TO_MINES:
 


private enum State {
    MINE, WALK_TO_BANK, BANK, WALK_TO_MINE
};

Now it’s time to change our getState() function to return what exact state we should be in:
 


private State getState() {
    if (inventory.isFull() && MINE_AREA.contains(myPlayer()))
        return State.WALK_TO_BANK;
    if (!inventory.isFull() && BANK_AREA.contains(myPlayer()))
        return State.WALK_TO_MINE;
    if (inventory.isFull() && BANK_AREA.contains(myPlayer()))
        return State.BANK;
    return State.MINE;
}

Now that the script knows what state we should be in, let’s handle the actual path walking, with a pretty simple method to traverse the whole path:

private void traversePath(Position[] path, boolean reversed) throws InterruptedException {
	if (!reversed) {
		for (int i = 1; i < path.length; i++)
			if (!walkTile(path[i]))
				i--;
	} else {
		for (int i = path.length-2; i > 0; i--)
			if (!walkTile(path[i]))
				i++;
	}
} 

You can put this method after getState() if you’d like, and the walkTile(path) will be underlined red, because we’re about to make that method too!

I’ll explain this method, as it may look confusing:

If the path isn’t reversed, we’ll iterate through the path starting at position 1 (note that arrays start at 0, but remember, our 0 is in the mine) until we end in the bank.

If the path is reversed, we’ll simply do the opposite! We’ll start at the 2nd to last position (path.length - 2) and continue to decrease through the path until we end up back in the mine!

The reason we aren’t using OSBot’s walk() method is because, well, it doesn’t work nicely at all. It tends to continue clicking the position til you’re there, and many other problems can happen.

So here’s the walkTile(Position p) method, put this after the traversePath() method:

private boolean walkTile(Position p) throws InterruptedException {
	client.moveMouse(new MinimapTileDestination(bot, p), false);
	sleep(random(150, 250));
	client.pressMouse();
	int failsafe = 0;
	while (failsafe < 10 && myPlayer().getPosition().distance(p) > 2) {
		sleep(200);
		failsafe++;
		if (myPlayer().isMoving())
			failsafe = 0;
	}
	if (failsafe == 10)
		return false;
	return true;
}

Simply put, we move the mouse to where the tile is on the minimap, then press the mouse button.

After that, we’ll sit around and wait until we’re pretty close to the tile we’re walking to.

I also implemented a simple failsafe here, just incase we misclicked or something, that will reclick the same position until we're actually near that position.

Step V: Preparing for Banking

Now let’s actually make the walking states actually walk, by changing our onLoop() to this:
 


@Override
public int onLoop() throws InterruptedException {
    switch (getState()) {
        case MINE:
            if (!myPlayer().isAnimating()) {
                RS2Object vein = objects.closest(TIN_ID);
                if (vein != null) {
                    if (vein.interact("Mine"))
                        sleep(random(1000, 1500));
                }
            }
            break;
        case WALK_TO_BANK:
            traversePath(path, false);
            sleep(random(1500, 2500));
            break;
        case WALK_TO_MINE:
            traversePath(path, true);
            sleep(random(1500, 2500));
            break;
    }
    return random(200, 300);
}

Step VI: Banking

Now that we’ve managed to walk to and from the bank, let’s actually do some banking!

If we’re in the bank state, that means we’re already in the bank!

Now, let’s add this case to our onLoop() function (as seen above), by simply adding this after the last “break;” and before the ‘}’:


case BANK:
    RS2Object bankBooth = objects.closest("Bank booth");
    if (bankBooth != null) {
        if (bankBooth.interact("Bank")) {
            while (!bank.isOpen())
                sleep(250);
            bank.depositAll();
        }
    }
    break;

This looks for the bank booth, if it isn’t null and if we actually managed to click on it, we’ll wait til it’s open, then deposit everything except our pickaxe, which is hardcoded so you’ll have to change this to whatever pickaxe you’re using. We’ll automatically detect which pickaxe we’re using in the next tutorial.

Conclusion

If you managed to get through this whole tutorial without error, congratulations!

If not, you can find the full source here.

I hope you've learned something from this, and if you didn’t, don’t worry! Programming takes time to learn, look this over a few times, I promise you’ll get it!

Thanks for viewing my second tutorial, stay tuned for future tutorials!

Edited by Pandemic
  • Like 19
Link to comment
Share on other sites

I use walkMinimap() from the API, it works pretty well. It won't validate that you're actually at the position, just near it (or so it seems). Great tutorial though, lots of effort. Hope it inspires the next generation of scripters!

Thanks, after my first experience with walk() I just gave up on the API for the most part (for walking and interacting) , haha.

The methods in this tutorial are very fleshed out versions of what my little library contains, they work extremely well, I'll probably release those some time.

Link to comment
Share on other sites

Great tutorial I am still trying to get what everything means I understand some of it pretty wel but could you please explain me what this exactly means that would help me out -      RS2Object bank = closestObject(BANK_BOOTH_ID);  it creates an object right? thats called bank? and look in the RS2Object class? but I don't get the closestObject method it is not in RS2Object I know I am doing something wrong thats why I am asking this because I would like to learn and create a script some day help is appreciated :)

Link to comment
Share on other sites

It's better to use names for entities because entity IDs change frequently (no RS update required).

 

Also:

RS2Object bank = closestObject(BANK_BOOTH_ID);
if (bank != null) {
    if (bank.interact("Bank")) {
        while (!client.getBank().isOpen())
               sleep(250);
        client.getBank().depositAllExcept("Bronze pickaxe");
    }
}

to:

RS2Object bank = closestObjectForName("Bank booth");
if (bank != null) {
    if (!client.getBank().isOpen()) {
        bank.interact("Bank");
        sleep(250);
    } else {
        client.getBank().depositAllExcept("Bronze pickaxe");
    }
}

There's no need to create a while loop.

 

Nice guide nonetheless.

 

Edited by Celestial
  • Like 1
Link to comment
Share on other sites

It's better to use names for entities because entity IDs change frequently (no RS update required).

Also:

RS2Object bank = closestObject(BANK_BOOTH_ID);if (bank != null) {    if (bank.interact("Bank")) {        while (!client.getBank().isOpen())               sleep(250);        client.getBank().depositAllExcept("Bronze pickaxe");    }}
to:
RS2Object bank = closestObjectForName("Bank booth");if (bank != null) {    if (!client.getBank().isOpen()) {        bank.interact("Bank");        sleep(250);    } else {        client.getBank().depositAllExcept("Bronze pickaxe");    }}
There's no need to create a while loop.

Nice guide nonetheless.

I already taught how to use names, this tutorial was on using IDs.

Also, if they replaced the banking with what you put, it would click the bank every half a second or so until it's open. My way clicks it only once and waits to open.

Link to comment
Share on other sites

Great tutorial I am still trying to get what everything means I understand some of it pretty wel but could you please explain me what this exactly means that would help me out - RS2Object bank = closestObject(BANK_BOOTH_ID); it creates an object right? thats called bank? and look in the RS2Object class? but I don't get the closestObject method it is not in RS2Object I know I am doing something wrong thats why I am asking this because I would like to learn and create a script some day help is appreciated :)

closestObject is a method in the MethodProvider class, check that out.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...