About a year and a half ago, I was getting back into Old School Runescape. You sit down to grind a bunch of skills, like woodcutting or whatever, and then you just have to Right Click -> Drop for every item in your inventory. It's frustrating.
To address this complaint of mine with Runescape, I created the Runescape "DropBot" the May before last. This was a program that analyzed an image of the game window and extracted the positions of the inventory items, then used the real mouse cursor to go through and drop every one. It's not nearly the most efficient option, but it's sure as hell difficult to detect on their end, and it worked.
I said in the original post that I wasn't releasing it until I fixed all the bugs and removed some of the default assumptions (resizing the screen, or playing as a free member, would make the tool break). What I didn't realize when writing that post is that I would stop playing Runescape shortly after finishing the bot. The code's sat untouched since then.
I decided to dig it out and give it a proper open-sourcing, just in case anyone wants to take a look
How It Works
Here's how the bot breaks down the steps:
- Takes a screenshot of the game window.
- Extracts the inventory section of the screenshot using a hardcoded position and size.
- Divides up the inventory image into seperate images for each inventory item.
- Discards empty items.
- Remove the background of every image, using hardcoded background color values (since the background is all shades of brown).
- Hash each image using aHash.
- Merge together similar looking items, since they're probably the same item.
- Present the list of items to the user.
Then, when the user selects an item to drop:
- Takes the list of items computed previously.
- Lerps to the position of the first item.
- Right clicks on it.
- Lerps to the position of the "Drop" button.
- Clicks on it.
- Repeats 2-5 for each item of the selected type.
You might notice that this process is actually pretty simple, algorithm wise, save for the image hashing. Originally, the plan was to remove the background and compare the images pixel by pixel, because they all should be the same sprite. However, this proved to be rather difficult - it required each image be aligned in the same way, and all the background pixels to be removed perfectly. This ended up being too much effort, and I implemented image hashing instead.