Jump to content

Free AIO shopper


Wacky Jacky

Recommended Posts

Welcome to my free yet premium shopper!

YzBKVJH.png

It is uploaded :) feel free to decompile it and watch the spaghetti galore ^^ but hé, it works, I blame the rum. And yes if you request nicely I will even fix some bugs 🐛 
(download here) v1.02
virus scan

Features:

  1. : shop anywhere with manual shop selector, click the npc
  2. : multi item support, add multiple names, and separate them with a (,) comma.
  3. : or enter shop name manually, with interaction and locations, yep all shop are supported…
  4. : shop and unpack at location
  5. : shop and bank items/packs
  6. : invoke support 
  7. : invoke open packs after amount reached (a whole inventory within 1.5 seconds)
  8. : hop support, ascending order, descending order or random
  9. : stop when x money left 
  10. : stop after x items bought
  11. : setting fix like all my scripts 

Note!
All item names, shop names and all other stuff are CaSe SeNsiTiVe. 
 

Updates:

Spoiler

v1.02:
— Added multi item support in v1.02 and above, to use just type in the item name and separate them with a ',' (comma).
i.g. Empty jug pack, Empty bucket pack, knife
— Added feature that automatically sorts the world list if it isn't sorted yet.

Note:
names are still case-sensitive



v1.01: 
— Removed the remains of !example script within the package, it won't show up anymore :)
— Added a handler, if the game isn't in fixed mode, it will set it to fixed mode
— Cleaned up the GUI, took care of some spacings


 

So this is the release, expect bugs and other weird things, if you post logs and good bug information I will be fixing them, slowly but surely,
want to keep track your bug? 

Bug Tracker | Board (notion.site)

Here you can see requested features to come or rejected for good.
Feature creep | Board (notion.site)

OGdJen9.jpeg
b0ukbUH.png
wM1SzEO.png
Py2Y3Rx.jpeg

https://i.imgur.com/UYdEkDz.mp4
https://i.imgur.com/cEafqCU.mp4

Edited by Wacky Jacky
1.02
  • Like 1
Link to comment
Share on other sites

  • Wacky Jacky changed the title to Free AIO shopper (uploaded)
Posted (edited)

Released the jar file ^^
For bugs, let me know, but I must have a log, and you need to paint me a nice picture of the scenario and provide the used profile it will always be the one called: last_config.txt

where to find the profile:
C:\Users\%user%\OSBot\Data\WackyJackysFolder\WackyJackyShopper\


where to find the log:
C:\Users\%user%\OSBot\Data\logs\

Because it is free and an unofficial release, I will maintain it but slow and irregular. 

Edited by Wacky Jacky
Link to comment
Share on other sites

I don't suppose it will have support for wilderness cape shops?

EDIT: also why does this appear in my script lists now?

Captura de pantalla 2024-03-03 091714.png

EDIT: how do I buy more than 1 item in the shop? putting a comma between the items didn't work,

EDIT: seems to do 2 checks when about to hop world so opens and closes the world hopper interface uneccesarily EDIT EDIT: i'm thinking maybe it's because i'm on resizeable modern and widget ID's are different or not static

[INFO][Bot #1][03/03 09:33:59 a. m.]: [We Need To Hop]
[INFO][Bot #1][03/03 09:33:59 a. m.]: Sleeping: [Waitng for the store to close.]
[INFO][Bot #1][03/03 09:34:07 a. m.]: [Current[399] >> Hop[417]]

Like this 8 second delay to hop is unnecessary, I notice the bot closes interface immedietly after buying and world hop interface is already open so really no need to sleep or to wait too long to begin hopping maybe 2-3 seconds tops. 

last_config.txt

Edited by hingleberry
Link to comment
Share on other sites

Posted (edited)
7 hours ago, hingleberry said:

I don't suppose it will have support for wilderness cape shops?

EDIT: also why does this appear in my script lists now?

Captura de pantalla 2024-03-03 091714.png

EDIT: how do I buy more than 1 item in the shop? putting a comma between the items didn't work,

EDIT: seems to do 2 checks when about to hop world so opens and closes the world hopper interface uneccesarily EDIT EDIT: i'm thinking maybe it's because i'm on resizeable modern and widget ID's are different or not static

[INFO][Bot #1][03/03 09:33:59 a. m.]: [We Need To Hop]
[INFO][Bot #1][03/03 09:33:59 a. m.]: Sleeping: [Waitng for the store to close.]
[INFO][Bot #1][03/03 09:34:07 a. m.]: [Current[399] >> Hop[417]]

Like this 8 second delay to hop is unnecessary, I notice the bot closes interface immedietly after buying and world hop interface is already open so really no need to sleep or to wait too long to begin hopping maybe 2-3 seconds tops. 

last_config.txt 280 B · 0 downloads

Sorry for the !example issue, I saw it got teleported from my method's folder which had that script in it, new version has it removed :)

Q: EDIT: how do I buy more than 1 item in the shop? putting a comma between the items didn't work.
A: I have no support for multiple items in this script, I can take a look at it if you want, but it will take me a while since I am focused on other paid scripts, but I shall add it.

 Q: EDIT: seems to do 2 checks when about to hop world so opens and closes the world hopper interface uneccesarily EDIT EDIT: i'm thinking maybe it's because i'm on resizeable modern and widget ID's are different or not static.
A: Please use fixed mode always when botting, widgets and IDs do indeed change, but not to worry I will add a handler which is already in the new version now. It will set the game to fixed mode, the intended client window mode.

Q: Like this 8 second delay to hop is unnecessary, I notice the bot closes interface immedietly after buying and world hop interface is already open so really no need to sleep or to wait too long to begin hopping maybe 2-3 seconds tops. 
A: I think this is a side effect of the resizable modern mode. Let me know how it goes with the new version. :)

v1.01 is up, the download link will now take you to the folder with all version <3

Added a board for requested features so people know what will be coming 
Feature creep | Board (notion.site)

Edited by Wacky Jacky
Link to comment
Share on other sites

  • Wacky Jacky changed the title to Free AIO shopper
41 minutes ago, Wacky Jacky said:

Sorry for the !example issue, I saw it got teleported from my method's folder which had that script in it, new version has it removed :)

Q: EDIT: how do I buy more than 1 item in the shop? putting a comma between the items didn't work.
A: I have no support for multiple items in this script, I can take a look at it if you want, but it will take me a while since I am focused on other paid scripts, but I shall add it.

 Q: EDIT: seems to do 2 checks when about to hop world so opens and closes the world hopper interface uneccesarily EDIT EDIT: i'm thinking maybe it's because i'm on resizeable modern and widget ID's are different or not static.
A: Please use fixed mode always when botting, widgets and IDs do indeed change, but not to worry I will add a handler which is already in the new version now. It will set the game to fixed mode, the intended client window mode.

Q: Like this 8 second delay to hop is unnecessary, I notice the bot closes interface immedietly after buying and world hop interface is already open so really no need to sleep or to wait too long to begin hopping maybe 2-3 seconds tops. 
A: I think this is a side effect of the resizable modern mode. Let me know how it goes with the new version. :)

v1.01 is up, the download link will now take you to the folder with all version <3

Added a board for requested features so people know what will be coming 
Feature creep | Board (notion.site)

I appreciate a lot the response, I have been doing a script for 3 days and i'm a bit sad to find out that all my widget ID's were from resizeable modern and not fixed classic. Maybe there is a FIND and REPLACE function in Eclipse IDE where I can replace them automatically with the corrected values.

Additionally it wouldn't be such a sad sea if you birthed a buoy to my vessel that would set the bot to fixed for my own script's convenience. 

Once you can make it buy multiple items that will rock my world and I will continue to test and feedback until then thank you for despawning !example. 

Edited by hingleberry
Link to comment
Share on other sites

Posted (edited)

@hingleberry
If you like to add such code your self here is a bit of help, also a lot of credits to @Explv most of this code if from him, I just made it work since it was out-dated. 

The main code:

Spoiler
public class EnableFixedModeEvent extends Event {

    private final CachedWidget clientLayoutWidgetText = new CachedWidget(new WidgetMessageFilter("Game client layout:"));
    private final CachedWidget displaySettingsWidget = new CachedWidget(new WidgetActionFilter("Display"));
    private final CachedWidget fixedLayout = new CachedWidget(new WidgetMessageFilter("Fixed - Classic layout"));
    private final CachedWidget optionMenu = new CachedWidget(new WidgetMessageFilter("Fixed - Classic layout", "Resizable - Classic layout", "Resizable - Modern layout"));

    public static boolean isFixedModeEnabled(final MethodProvider methods) {
        return methods.getWidgets().isVisible(378) ||
                methods.getWidgets().isVisible(548) ||
                !methods.myPlayer().isVisible();
    }

    @Override
    public int execute() throws InterruptedException {
        if (isFixedModeEnabled(this)) {
            log("~Fixed mode is already set~");
            setFinished();
        } else if (Tab.SETTINGS.isDisabled(getBot())) {
            log("~Setting tab is disabled~");
            setFailed();
        } else if (getTabs().getOpen() != Tab.SETTINGS) {
            log("~Opening Setting Tab~");
            getTabs().open(Tab.SETTINGS);
        } else if (!clientLayoutWidgetText.isVisible(getWidgets())) {
            log("~Can't see client window options, opening display settings~");
            displaySettingsWidget.interact(getWidgets());
        } else if (!fixedLayout.isVisible(getWidgets())) {
            log("~Fixed layout not selected, trying to open~");
            if (!optionMenu.interact(getWidgets())){
                log("~Failed to open~");
                return 200;
            }
            Sleep.sleepUntil(()-> fixedLayout.isVisible(getWidgets()), 5000);

            log("~Trying to select fixed layout mode now~");
            if (!fixedLayout.interact(getWidgets(), "Select")){
                log("~Failed to open~");
                return 200;
            }

            Sleep.sleepUntil(() -> isFixedModeEnabled(this), 3000);
        }
        return 200;
    }
}

 


Utilities needed for it to work.

CachedWidget:

Spoiler
import org.osbot.rs07.api.Widgets;
import org.osbot.rs07.api.filter.Filter;
import org.osbot.rs07.api.ui.RS2Widget;

import java.util.Optional;

/**
 * This class provides a clean and efficient way of accessing RS2Widgets.
 * Widgets can be found using IDs, the message, or any other Filter<RS2Widget>
 * Once the RS2Widget is found, it's IDs are stored, so any future lookup can be performed in O(1) time.
 * <p>
 * Note that the class is thread safe, and so instances of this class may be static.
 */
public class CachedWidget {

    private int rootID = -1, secondLevelID = -1, thirdLevelID = -1;
    private String[] widgetTexts;
    private Filter<RS2Widget> filter;

    /**
     * This *SHOULD NOT* be used for constant widgets. Widget IDs can change, which is the entire purpose
     * of this class!
     *
     * @param rootID        The root ID of the RS2Widget to cache
     * @param secondLevelID The second level ID of the RS2Widget to cache
     */
    public CachedWidget(final int rootID, final int secondLevelID) {
        this.rootID = rootID;
        this.secondLevelID = secondLevelID;
    }

    /**
     * This *SHOULD NOT* be used for constant widgets. Widget IDs can change, which is the entire purpose
     * of this class!
     *
     * @param rootID        The root ID of the RS2Widget to cache
     * @param secondLevelID The second level ID of the RS2Widget to cache
     * @param thirdLevelID  The third level ID of the RS2Widget to cache
     */
    public CachedWidget(final int rootID, final int secondLevelID, final int thirdLevelID) {
        this.rootID = rootID;
        this.secondLevelID = secondLevelID;
        this.thirdLevelID = thirdLevelID;
    }

    /**
     * @param rootID      The root ID of the RS2Widget to cache
     * @param widgetTexts An array of widget messages to match when searching for the RS2Widget to cache
     */
    public CachedWidget(final int rootID, final String... widgetTexts) {
        this.rootID = rootID;
        this.widgetTexts = widgetTexts;
    }

    /**
     * @param widgetTexts An array of widget messages to match when searching for the RS2Widget to cache
     */
    public CachedWidget(final String... widgetTexts) {
        this.widgetTexts = widgetTexts;
    }

    /**
     * @param rootID The root ID of the RS2Widget to cache
     * @param filter A Filter<RS2Widget> to match when searching for the RS2Widget to cache
     */
    public CachedWidget(final int rootID, final Filter<RS2Widget> filter) {
        this.rootID = rootID;
        this.filter = filter;
    }

    /**
     * @param filter A Filter<RS2Widget> to match when searching for the RS2Widget to cache
     */
    public CachedWidget(final Filter<RS2Widget> filter) {
        this.filter = filter;
    }

    /**
     * @param rs2Widget An RS2Widget to cache
     */
    public CachedWidget(final RS2Widget rs2Widget) {
        setWidgetIDs(rs2Widget);
    }

    /**
     * Returns whether the cached RS2Widget is not null, and is visible
     *
     * @param widgets OSBot Widgets API
     * @return True if the cached RS2Widget is not null and visible
     */
    public boolean isVisible(final Widgets widgets) {
        return get(widgets).map(RS2Widget::isVisible)
                .orElse(false);
    }

    /**
     * Interacts with the cached RS2Widget if it is visible
     *
     * @param widgets     OSBot Widgets API
     * @param interaction Array of interaction options
     * @return True if the cached RS2Widget is visible and the interaction was successful, else false
     */
    public boolean interact(final Widgets widgets, final String... interaction) {
        return get(widgets).filter(RS2Widget::isVisible)
                .map(w -> w.interact(interaction))
                .orElse(false);
    }

    /**
     * Returns the parent RS2Widget of the cached widget
     * If the CachedWidget is a second level RS2Widget, the same RS2Widget will be returned
     * as you cannot have an RS2Widget with just a root ID.
     *
     * @param widgets OSBot Widgets API
     * @return An Optional parent RS2Widget
     */
    public Optional<RS2Widget> getParent(final Widgets widgets) {
        return get(widgets).map(widget -> {
            if (widget.isSecondLevel()) {
                return widget;
            }
            return widgets.get(widget.getRootId(), widget.getSecondLevelId());
        });
    }

    /**
     * Returns an RS2Widget relative to the cached widget
     *
     * @param widgets             OSBot Widgets API
     * @param rootModifier        Relative root ID modifier
     * @param secondLevelModifier Relative second level ID modifier
     * @param thirdLevelModifier  Relative third level ID modifier
     * @return An Optional relative RS2Widget
     */
    public Optional<RS2Widget> getRelative(final Widgets widgets,
                                           final int rootModifier,
                                           final int secondLevelModifier,
                                           final int thirdLevelModifier) {
        return get(widgets).map(widget -> {
            if (widget.isThirdLevel()) {
                return widgets.get(
                        rootID + rootModifier,
                        secondLevelID + secondLevelModifier,
                        thirdLevelID + thirdLevelModifier
                );
            }
            return widgets.get(
                    rootID + rootModifier,
                    secondLevelID + secondLevelModifier
            );
        });
    }

    /**
     * Returns the cached RS2Widget.
     * <p>
     * If no RS2Widget has been cached, it tries to find the RS2Widget using the supplied
     * filter / message string / etc.
     * <p>
     * If the RS2Widget is found, it is cached and then returned
     * <p>
     * If no RS2Widget is found, an empty Optional is returned.
     *
     * @param widgets OSBot Widgets API
     * @return The Optional cached RS2Widget
     */
    public Optional<RS2Widget> get(final Widgets widgets) {
        if (rootID != -1 && secondLevelID != -1 && thirdLevelID != -1) {
            return Optional.ofNullable(widgets.get(rootID, secondLevelID, thirdLevelID));
        } else if (rootID != -1 && secondLevelID != -1) {
            return Optional.ofNullable(widgets.get(rootID, secondLevelID));
        } else if (widgetTexts != null) {
            return getWidgetWithText(widgets);
        } else {
            return getWidgetUsingFilter(widgets);
        }
    }

    /**
     * Finds and caches a widget using the specified message Strings
     * <p>
     * If no RS2Widget is found, an empty Optional is returned
     *
     * @param widgets OSBot Widgets API
     * @return The cached RS2Widget
     */
    private Optional<RS2Widget> getWidgetWithText(final Widgets widgets) {
        RS2Widget rs2Widget;
        if (rootID != -1) {
            rs2Widget = widgets.getWidgetContainingText(rootID, widgetTexts);
        } else {
            rs2Widget = widgets.getWidgetContainingText(widgetTexts);
        }
        setWidgetIDs(rs2Widget);
        return Optional.ofNullable(rs2Widget);
    }

    /**
     * Finds and caches a widget using the specified Filter<RS2Widget>
     * <p>
     * If no RS2Widget is found, an empty Optional is returned
     *
     * @param widgets OSBot Widgets API
     * @return The cached RS2Widget
     */
    private Optional<RS2Widget> getWidgetUsingFilter(final Widgets widgets) {
        RS2Widget rs2Widget;
        if (rootID != -1) {
            rs2Widget = widgets.singleFilter(rootID, filter);
        } else {
            rs2Widget = widgets.singleFilter(widgets.getAll(), filter);
        }
        setWidgetIDs(rs2Widget);
        return Optional.ofNullable(rs2Widget);
    }

    /**
     * Caches an RS2Widget's IDs
     *
     * @param rs2Widget The RS2Widget to cache
     */
    private synchronized void setWidgetIDs(final RS2Widget rs2Widget) {
        if (rs2Widget == null) {
            return;
        }
        rootID = rs2Widget.getRootId();
        secondLevelID = rs2Widget.getSecondLevelId();
        if (rs2Widget.isThirdLevel()) {
            thirdLevelID = rs2Widget.getThirdLevelId();
        }
    }

    @Override
    public String toString() {
        return rootID + ", " + secondLevelID + ", " + thirdLevelID;
    }
} 

 


WidgetMessageFilter

Spoiler
import org.osbot.rs07.api.filter.Filter;
import org.osbot.rs07.api.ui.RS2Widget;

import java.util.stream.Stream;

public class WidgetMessageFilter implements Filter<RS2Widget> {

    private final String[] messages;

    public WidgetMessageFilter(final String... messages) {
        this.messages = messages;
    }

    @Override
    public boolean match(final RS2Widget widget) {
        return Stream.of(messages)
                .anyMatch(message -> widget.getMessage().contains(message));
    }
}

 


WidgetActionFilter:

Spoiler
import org.osbot.rs07.api.filter.Filter;
import org.osbot.rs07.api.ui.RS2Widget;

public final class WidgetActionFilter implements Filter<RS2Widget> {

    private final String[] actions;

    public WidgetActionFilter(final String... actions) {
        this.actions = actions;
    }

    @Override
    public final boolean match(final RS2Widget rs2Widget) {
        if (rs2Widget == null || !rs2Widget.isVisible() || rs2Widget.getInteractActions() == null) {
            return false;
        }
        for (final String widgetAction : rs2Widget.getInteractActions()) {
            for (final String matchAction : actions) {
                if (matchAction.equals(widgetAction)) {
                    return true;
                }
            }
        }
        return false;
    }
}

 

Edited by Wacky Jacky
Link to comment
Share on other sites

Ok so The Main Code would go into the main class which has my main onloop. 

The other 3 codes for CachedWidget, WidgetMEssageFilter and WidgetActionFiltet would be classes I create in the package and then perhaps somehow call them in the main class, perhaps The Main Code already does that for me. 

I would also like to make changes such as, activate Shift drop, set particular bind keys, zoom out to a particular level, de-activate 3 second trade delay, deactivate world hopping warning among other changes and selectively as well, not just spamming them all every time.

The logic for CachedWidgets seems an interesting failsafe applicable to every script you make that interacts with widgets I don't quite understand it 100% but cool, I will revisit this. How is the update going for the shopping bot?

Link to comment
Share on other sites

23 hours ago, hingleberry said:

Ok so The Main Code would go into the main class which has my main onloop. 

The other 3 codes for CachedWidget, WidgetMEssageFilter and WidgetActionFiltet would be classes I create in the package and then perhaps somehow call them in the main class, perhaps The Main Code already does that for me. 

I would also like to make changes such as, activate Shift drop, set particular bind keys, zoom out to a particular level, de-activate 3 second trade delay, deactivate world hopping warning among other changes and selectively as well, not just spamming them all every time.

The logic for CachedWidgets seems an interesting failsafe applicable to every script you make that interacts with widgets I don't quite understand it 100% but cool, I will revisit this. How is the update going for the shopping bot?

Feature is done, I am testing it right now, unforeseen issues may occur since it was a quick add and tested it not so much.
Multiple items support is as following: Item Name1, Item Name2, Item Name3.

Small patch, it now also sets the sorting of the worlds so it is more optimal if you use Decent or Accent hopping.

So just separate the items with a ',' (comma), still case-sensitive :/ 
I will upload it soon, keep checking the link :)

Link to comment
Share on other sites

On 3/8/2024 at 2:34 PM, Wacky Jacky said:

Feature is done, I am testing it right now, unforeseen issues may occur since it was a quick add and tested it not so much.
Multiple items support is as following: Item Name1, Item Name2, Item Name3.

Small patch, it now also sets the sorting of the worlds so it is more optimal if you use Decent or Accent hopping.

So just separate the items with a ',' (comma), still case-sensitive :/ 
I will upload it soon, keep checking the link :)

A good one for world hoping is that if F2p worlds only is selected in your GUI that there is now a star you can click that lists all f2p worlds sequentially in OSRS, more human-like maybe to activate that when hopping. Anyway I haven't yet tested the shopper again because I haven't adapted my own scripts to fixed mode yet neither applied the knowledge of how to make it so when my scripts activate it automatically goes to resizeable and so I don't want the hastle dead scripts and manual switching.

Considering you got the auto-to-fixed mode activated maybe you would make a separate forum post guide, if one doesn't already exist, for how to implement that function like how you tried to show me, I am too noob atm to comprehend what you shared. But man would be useful to for example run a bot that sets up all the little settings that manually are a bore on each character either in it's own seperate script or before the main script.

Link to comment
Share on other sites

  • 2 weeks later...
Posted (edited)
On 3/22/2024 at 2:54 AM, taltoniser said:

Yeah, i do! it would be a dope addition

I will be looking in to it, added to the feature creep list.

 

2 hours ago, TheCongregation said:

Possible to have "items to sell"? I got longbows on a perm iron I wanna sell for 10 or 15 at a time with world hop and I cba for all that

For now, I don't have the intention of adding a sell option anytime soon. Sorry, I can't help u with that wish. You could check out the premium shopper from the OSBot store, I think it supports that, if u want to spend money on a shopper of course.  

Edited by Wacky Jacky
Link to comment
Share on other sites

19 hours ago, Wacky Jacky said:

For now, I don't have the intention of adding a sell option anytime soon. Sorry, I can't help u with that wish. You could check out the premium shopper from the OSBot store, I think it supports that, if u want to spend money on a shopper of course.  

I think I might macro killer some npc's for nature runes and then APA auto alcher instead, thank you for reply!

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.
Note: Your post will require moderator approval before it will be visible.

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.

  • Recently Browsing   0 members

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