Jump to content

liverare

Scripter II
  • Posts

    1296
  • Joined

  • Last visited

  • Days Won

    3
  • Feedback

    0%

Everything posted by liverare

  1. Sorry that's my fault, I missed out a method in the RSBuddyExchangePrice.java that would translate that squiggly bit of weird text to something that can actually be understood. I've uploaded a fixed version of RSBuddyExchangePrice.java and attached it to the thread: https://osbot.org/forum/topic/150093-rsbuddy-exchange-oracle
  2. This oracle processes the the summary.json from the RSBuddy Exchange website. public static void main(String[] args) throws IOException { // Load prices for now RSBuddyExchangeOracle.retrievePriceGuide(); // Load prices from yesterday RSBuddyExchangeOracle.retrievePriceGuide(System.currentTimeMillis() - (24 * 60 * 60 * 1000)); // ... } All the prices will be processed and cached, then accessed like: RSBuddyExchangePrice price; List<RSBuddyExchangePrice> prices; // Get item by name price = RSBuddyExchangeOracle.getItemByName("Dragon chainbody"); System.out.println(price); // Get item by ID price = RSBuddyExchangeOracle.getItemByID(4151); // Abyssal whip System.out.println(price); // Get item(s) by name containing price = RSBuddyExchangeOracle.getItemByNameContaining("Bronze dagg"); // Bronze dagger System.out.println(price); prices = RSBuddyExchangeOracle.getItemsByNameContaining("Bronze dagg"); // [ Bronze dagger, Bronze dagger(p++), Bronze dagger(p+), Bronze dagger(p) ] System.out.println(prices); // Get item(s) by name matching price = RSBuddyExchangeOracle.getItemByNameMatching("Rune kiteshield \\(.?\\)"); // Rune kiteshield (g) System.out.println(price); prices = RSBuddyExchangeOracle.getItemsByNameMatching("Rune kiteshield \\(.?\\)"); // [ Rune kiteshield (g), Rune kiteshield (t) ] System.out.println(prices); Running these returns the following: Have fun! RSBuddyExchangeOracle.java RSBuddyExchangePrice.java Test.java
  3. Very nice. One small change I would request is for the 'all' button to be used when you have exactly two coal on you. This is more of an anti-ban (or rather anti-bot behaviour) thing. Similarly if you have 5 coal, you might just use the '+' button to put in two.
  4. Try break your code down into separate routines and use a data structure for your attack styles: if (defenceLevel < 20) { // need to train defence if (!isAttackStyleSelected(AttackStyle.DEFENCE)) { // need to change attack style if (setAttackStyle(AttackStyle.DEFENCE)) { // we are now training defence (yay) } else { // something f'd up? throw new InterruptedException("Something wen't wrong!"); } } } via static enum AttackStyle { ATTACK(0, "Slash"), STRENGTH(1, "Chop"), DEFENCE(3, "Block"); private final int configValue; private final String action; private AttackStyle(int configValue, String action) { this.configValue = configValue; this.action = action; } public int getConfigValue() { return configValue; } public String getAction() { return action; } public static AttackStyle valueOf(int configValue) { AttackStyle value = null; for (AttackStyle next : values()) { if (next.configValue == configValue) { value = next; break; } } return value; } } private int getAttackStyleConfigValue() { return configs.get(43); } private boolean isAttackStyleSelected(AttackStyle attackStyle) { int configValue = getAttackStyleConfigValue(); return attackStyle == AttackStyle.valueOf(configValue); } private boolean setAttackStyle(AttackStyle attackStyle) { boolean success = false; List<RS2Widget> styleButtons; ConditionalSleep conditionalSleep; if (tabs.open(Tab.ATTACK)) { styleButtons = widgets.containingActions(593, attackStyle.action); if (styleButtons != null && !styleButtons.isEmpty()) { if (styleButtons.get(0).interact(attackStyle.action)) { conditionalSleep = new ConditionalSleep(2500) { // 2.5 seconds @Override public boolean condition() throws InterruptedException { return getAttackStyleConfigValue() == attackStyle.configValue; } }; success = conditionalSleep.sleep(); } } } return success; }
  5. It looks like a server error, however their website still works. Perhaps RSBuddy closed off their exchange API because too many clients were making way too many requests, or perhaps they're dealing with a server problem.
  6. Looking good - now let's take it up a gear! Take what you've done here and make it modular. I'll give you some examples: CustomPaint This'll let us hide/show different paints and gives us a basis for our paint modules. Here's an example: SkillTrackerPaint And... MousePaint And best of all, here's how to add it to the script: public class Test extends Script { CustomPaint skillTrackerPaint; CustomPaint mousePaint; @Override public void onStart() throws InterruptedException { skillTrackerPaint = new SkillTrackerPaint(); skillTrackerPaint.exchangeContext(bot); // must give botty to painte first! skillTrackerPaint.initializeModule(); mousePaint = new MousePaint(); mousePaint.exchangeContext(bot); mousePaint.initializeModule(); } @Override public int onLoop() throws InterruptedException { if (ehh for whatever reason we want) { skillTrackerPaint.setVisible(false); } return 0; } } Doing this means you can split up your paint code, add fine-tuned functionality (such as draggable paints, or even your own paint GUI windows!) This'll help keep the script code and paint code clean.
  7. public static boolean isInArea(Entity e, Area... areas) { return Stream.of(areas).anyMatch(area -> area.contains(e)); }
  8. You could check to see if you've already completed the quest onStart and terminate the script if it is. If the quest is incomplete and in progress, then you could go through the quest journal and figure out what's still outstanding, store them as variables and referencing them as opposed to re-open the widget to check manually for each step.
  9. *ahem* getSkills()::getStatic
  10. There's already a method that'll find widgets containing text. Try it: public boolean isContinueWidgetVisible() { List<RS2Widget> l = widgets.containingText("Click here to continue", "Click to continue"); return l != null && !l.isEmpty(); } Then you could do something like: ConditionalSleep sleepyTime; if (isContinueWidgetVisible()) { // can we continue? if (keyboard.typeString(" ", false)) { // k let's try press space bar (false = no pressy enter!) sleepyTime = new ConditionalSleep(5000) { // k now lets create new conditional sleep @Override public boolean condition() throws InterruptedException { return !isContinueWidgetVisible(); } }; // k now let's see if sleepy wakes up if (sleepyTime.sleep()) { // yay interface went away! } } }
  11. NullPointerException occurs when you're trying to do stuff to something that doesn't exist. You need to check to make sure your 'thing' exists first before doing any further checks against it: RS2Widget sodaAsh = getWidgets().get(300, 16, 23); if (sodaAsh != null) { // this tells us sodaAsh variables has a value if(sodaAsh.getItemAmount() < 0) { // now we can check what's inside of it // ... } }
  12. I have played legit using OSBot a lot on my main account that has over 2K total levels, and I've only ever been banned once for having run a poorly written runecrafting script of mine. I use OSBot as a client because it's clear, clean from widgets n stuff, and because I can write plug-ins that assist similar to RuneLite and RSBuddy, but are tailored to exactly what I want them to do.
  13. Login to an account. Put player in a CC. Run the script. Turn off fast keyboard (it's broken and non-standard feature) Log into a second account. From the second account, type in commands in the CC. Bot plays the game. That's it in a nutshell. This bot is designed to play the games of chance. You need two accounts for this operation: Account #1 'game bot' runs the script and plays the games when told to. Account #2 'host' handles the money and CC.
  14. If you're using MS Word, you can go to References tab, change the style to Harvard, manage your sources, then insert the bibliography.
  15. int something; @Override public int onLoop() throws InterruptedException { try { something = Integer.parseInt("12345"); } catch (NumberFormatException e) { logger.error(e); } return 200; } @Override public void onPaint(Graphics2D g) { g.drawString(25, 25, "Something: " + something); }
  16. I just noticed you're parsing a lot of strings to integers, so I suspect that's throwing an NumberFormatException error which is preventing the paint from being rendered. I would avoid parsing anything on the paint method, as the rendering is called a stupid amount of times per second and so you're re-parsing again and again. It's both inefficient and likely causing problems. You should perhaps paint the raw string values and see whether they display as numbers, null, or empty. You can actually test this by going back to my earlier comment and making it "if (false)" instead, that way you're not parsing anything and are instead going straight to the drawing code.
  17. Don't worry about that warning. @Alek has said in the past it's used for internal use, so it's not likely to be removed and it's perfectly fine to use.
  18. if (guiOptionChose == "Headless arrows") { Change to if (true) { If it's still not rendering, then it's a different issue.
  19. Fair enough. I'd still use long values just because it can be reused elsewhere without having to worry about this issue.
  20. Long time no see! I used to script for Excobot and I remember being in direct contact with you (or another dev). I don't quite remember who, but I knew that you guys were very active in the community. It's great to see you on-board! Also, your Dungeoneering script was legendary and I have used it extensively.
  21. Caching prices is definitely good. However, that's a layer of logic that should be handled outside of the raw routine that grabs those values. If you start to merge your caching code with your price retrieval code, it'll get unwieldy. Also, the user case might be that the prices are so volatile and necessary that caching isn't an option. Wrong. Players have had multiple max cash stacks and there are items that are worth billions. Now, it's unlikely the script would ever work with those sorts of figures. However, your code should be ready to handle situations where it could. For instance, what if somebody using the script needs to calculate a huge total buy/sell? If the script uses integers, it could overflow. You can (and so should) account for this sooner rather than later.
  22. Firstly: name = name().substring(0,1).toUpperCase() + name().substring(1).toLowerCase() + name().replace("_", " "); System.out.println(Potion.MARRENTILL.name); // MarrentillMARRENTILL You're not generating the correct name. You should just hard code these values, because you're working with an enumerator. Enumerators are ideal for storing constants: MARRENTILL("Marrentill", "Marrentill potion (unf)") // ... ; private final String herbName; private final String unfinishedPotionName; Potion(String herbName, String unfinishedPotionName) { this.herbName = herbName; this.unfinishedPotionName = unfinishedPotionName; // ... Then, you're going to need to look at what it is ItemLookup#get is actually returning, because looking at your variables: public final Optional<String> herbPriceMax; public final Optional<String> herbPriceMin; public final Optional<String> unfinishedPriceMax; public final Optional<String> unfinishedPriceMin; It's returning an Optional<String> which is wrapping the value. You need to retrieve the value like so: herbPriceMax = ItemLookup.get(name, Property.BUY_AVERAGE).orElse(null); This will attempt to get the value stored in the optional, or else it will return null. However, from looking at the <String>, the value will be a string that needs to be parsed to a Long: String herbPriceMaxStr = ItemLookup.get(name, Property.BUY_AVERAGE).orElse(null); long herbPriceMax = (herbPriceMaxStr != null ? Long.parseLong(herbPriceMaxStr) : 0); Once you've done that, you may wish to consider not generating these values on the constructor. Why? Because margins change and you'd want to know about that in real time. You're going to want to build getter methods that'll retrieve the latest prices: /** * greater than 1 = priced * 0 = not priced * -1 = failed to retrieve/cast price */ public long getMaxHerbPrice() { long price = 0L; try { price = ItemLookup.get(name, Property.BUY_AVERAGE).map(Long::parseLong).get(); } catch (Exception e) { price = -1L; } return price; } (this was rushed so you can do a better job than I've done). This should enable you to do: long marrentillMaxHerbPrice = Potion.MARRENTILL.getMaxHerbPrice(); However, you're going to want to setup some sort of caching mechanism to avoid grabbing new prices each time. unless it's absolutely critical. :EDIT: Whenever you're working with prices and quantities, do so in LONG, not INTEGER. Why? Because an integers are 32-bit and their min/max values are only -2,147,483,648 and 2,147,483,647. https://stackoverflow.com/questions/15004944/max-value-of-integer
  23. You could record yourself doing some mundane activity, draft up a workflow, then try to implement it. If you're looking to implement an anti-ban, then it's a waste of time as there's no guarantee they even work. However, there are certain behaviours that might be worth exhibiting, for example, right clicking a fishing pool to figure out whether it's the pool you're after. I'd has at a guess that all the fishing scripts currently out there don't do this and get a 100% accuracy rate fishing at the right spot, which is very suspect at places like Catherby.
  24. I have ran into similar problems in the past that I believe were caused by caching issues between script executions. However, it would be worth seeing your code and for me to test whether I encounter the same problem.
×
×
  • Create New...