Jump to content

Hawk

Lifetime Sponsor
  • Posts

    28
  • Joined

  • Last visited

  • Feedback

    0%

Everything posted by Hawk

  1. The proper way to compare strings is with .equals() if(!"LOADING".equals(state) && !"HOPPING".equals(state)) { You could also just compare directly to the enum Client.GameState state = getClient().getGameState(); if(!Client.GameState.LOADING.equals(state) && !Client.GameState.HOPPING.equals(state)) { There is a conditional sleep class: https://osbot.org/api/org/osbot/rs07/utility/ConditionalSleep2.html
  2. This is actually not human-like behavior. I was doing testing recently on this, and a human does occasionally move the mouse up to a few pixels if they're clicking on the same spot.
  3. I think the only way botting is ever going to be successful again is to leave no stone unturned. Mouse movement is a very easy way to detect a human from a bot, so it's better to assume they do consider it to some extent, rather than not. Even all parts of a mouse click event should be considered. What's the average ms it takes to enter the target area and press down the mouse? To release the mouse? What's the chance of dragging the mouse after a mouse press before the release? What's the mean pixel distance of a click-drag? Are human clicks actually normally distributed within rectangle bounds? These are parts of human nuance that are easy to detect for that I'd bet nobody implements. The mouse is just one part though. The biggest factor is bot behavior. Like you said though, there's just no incentive for anyone who puts in the time and money to solve these problems to give them to the public. The only way it would get into the public is if they need something from the public, such as their human data. One way to test scripts for detectability would be to run it through some of the bot detection methods from research papers, but that's obviously not going to be exactly like RS's detection methods. It would give you an idea though. Injection mode is 100% detectable. You can test this yourself making F2P accounts that only ever login through injection mode and not even botting. I don't think this is really news, but rarely ever anyone talks about it.
  4. It's not. You can test this yourself by making a new account during jagex hours and only ever logging in using stealth injection. Make the account, do tutorial island, go kill chickens for 15 min, and then log out. You'll be banned. Edit: everything is done legit by hand and not using a proxy
  5. It's possible chat interaction is a metric they use for bot classification, but definitely not not the only metric they're looking at. If it is one, I would probably say it's one of the least important metrics since plenty of legit players go hours or days without ever talking to anyone. It entirely depends on what activity you're doing to train magic too. Are you splashing which involves very few clicks? Alching? Killing a certain monster in an area repeatedly? Or some other method that requires a high APM? Also, just because it's a free script doesn't necessarily mean you will get banned faster. I'd imagine there are some free scripts out there that are decent and never used.
  6. How long does it take for the api site to reflect these changes or is it just infrequently updated? Also, it would be nice to have a dedicated thread for cli options. The one from 2017 is obviously outdated and the only way to figure out what's new is to go through every client release thread.
  7. If I understand your problem correctly you want to do something like blabla someStringVariable in one drawString call? I don't think it's possible to do it in one drawString call, but this works, taken from https://stackoverflow.com/questions/23591034/how-to-use-multiple-colors-when-using-drawstring-in-java-awt-graphics public class Test extends Script { private static final String s = "<html>all your <font color=\"#ffd700\">base</font> belong to us</html>"; private JLabel renderer = new JLabel(s); private CellRendererPane crp = new CellRendererPane(); private Dimension dim = renderer.getPreferredSize(); @Override public int onLoop() throws InterruptedException { return 10000; } @Override public void onPaint(Graphics2D g) { renderer.setForeground(Color.BLUE); crp.paintComponent(g, renderer, bot.getBotPanel(), 10, 10, dim.width, dim.height); } }
  8. I would recommend starting with a Java book to learn the basics of Java first. The method formatTime takes one argument of type long. The method getTimeToLevel() returns a long value. So to get the output that you're wanting, you need to pass the long value to the format method. formatTime(getExperienceTracker().getTimeToLevel(Skill.DEFENCE)) formatTime returns a String value which is a required argument of the drawString() method in the Graphics2D class.
  9. You need to pass getExperienceTracker().getTimeToLevel(Skill.DEFENCE) to the formatTime method.
  10. What is an example of your input? It prints 02:00:00 for an input of 7_200_000 which is what you want, right?
  11. The new UI looks nice, but can there please be a cli option added to start the client with the side bar toggled to collapsed, or even better, if the client just starts in the same state as a previously run client? The logger being at the bottom is also kind of annoying and just takes up screen real estate, although I can see its purpose of being there in regard to script users being able to easily identify it to save the logger info to send to the scripter. With respect to the scripter, it would be nice to be able to pop out the logger to be able to see more than 7 lines of text at runtime. Great work though.
  12. I don't really know the full context of your botting habits, so it's hard to say what a good solution is; I don't even fully understand yet what a "good" solution is. But I'm 99% sure sleeps like that are bad if you wanted to create something more than an assistance tool. From my own experience with assistance tools, I've been banned for simply clicking a widget with a delay interval upon it appearing. This was on multiple accounts though, not just one. If you're only going to be botting for a total of 10-20 hours total over the course of a few weeks, the botting is paused frequently to perform manual actions such as opening the pouches, and you also do other stuff manually in the game, then you're probably fine without any sleeps. However, if you were to add a sleep like that and you were to bot for 50+ hours in a row, you're 100% going to get banned. Especially if you wanted to bot thieving on multiple accounts. With a 26/300 chance for a 3 second sleep, you're only modifying the average clicks per minute from 240 to 228(?). There are a lot of nuances to human behavior. You aren't doing anything beyond that to create a unique behavior profile. Every time you go to thieve you're using the exact same profile. I guess a question that needs to be answered is how similar does a human behave between different sessions? Is it sufficient to create a model of multiple sessions from the same human and use a deviation of that mean for each account? I suppose that would work for a few accounts, but if you're botting 10+ accounts, they're still going to have the same behavior clusters based off of that one human's data. I think the actual challenge is in generating a unique human-like profile for each account, you ideally wouldn't want it based off of one. I think that may be what the OSB team is trying to do with their AI implementations coming sometime next year, but I'm not entirely sure what their approach entails.
  13. It's because the closed trapdoor is not the same object as the open trapdoor. After you open the trapdoor and try to call "Climb-down" it does nothing because the only action that trapdoor object has is "Open".
  14. When you were grading papers did you tap exactly every 100-400ms? Did you ever not tap for a few seconds from time to time, for example, when putting down one paper and picking up another? Have you ever been distracted and end up afking for 5 min and logging out? Clicking at a random interval of 100-400ms consistently over a long period of time with no deviation is not human-like behavior.
  15. This seems fake and just an advertisement for your other thread.
  16. Are you ensuring you're on the spell select screen before trying to select the spell? Also, you should add a null check for the returned value of getSpell() since it has the possibility of being null.
  17. Can you show your code? It works for me.
  18. The sprite value of fire strike is 71. That method checks widgets with a root of 201 and has a sprite value of 71. The returned widget should be 201, 1, 4.
  19. If your spell strings are in a different format than the enum values you're going to have to modify one of the strings for comparison. String selectedSpell = "firestrike"; public MagicSpell getSpell() { for (Spells.NormalSpells spell : Spells.NormalSpells.values()) { if (spell.name().replaceAll("_", "").equalsIgnoreCase(selectedSpell)) { return spell; } } return null; } If your spell strings are in the same format as the enum values, you can simply perform a valueOf() check. String selectedSpell = "FIRE_STRIKE"; public MagicSpell getSpell() { try { return Spells.NormalSpells.valueOf(selectedSpell); } catch (IllegalArgumentException e) { return null; } } If you initialize your spell to a MagicSpell like above, this code should work, however I haven't tested it. private void selectSpell() throws InterruptedException { RS2Widget spellWidget = getWidgets().getWidgetContainingSprite(201, spell.getSpriteIndex()); if (spellWidget != null && spellWidget.isVisible()) { spellWidget.interact(); Sleep.sleepUntil(() -> widgets.isVisible(593), 5000); } } Look at the fields a MagicSpell has: https://osbot.org/api/index.html?org/osbot/rs07/api/ui/MagicSpell.html Look at the methods the Widgets class has: https://osbot.org/api/org/osbot/rs07/api/Widgets.html The only methods of importance in this case are: RS2Widget getWidgetContainingSprite(int sprite) Checks all widgets (second and third level) for the specified sprite. RS2Widget getWidgetContainingSprite(int rootId, int sprite) Checks all widgets (second and third level) for the specified parent id (first level) for the specified sprite. The first one should work but it has a greater potential to produce a runtime logic error, so use the one specifying the rootId of where the sprite should exist instead.
  20. MagicSpell is an interface with several concrete implementations, one being Spells.NormalSpells: https://osbot.org/api/org/osbot/rs07/api/ui/Spells.NormalSpells.html Enum classes have a method values() which returns an array of possible values. So you can loop through the values and return the appropriate NormalSpell by comparing the selected spell in your gui to the name() of the enum value. This should all be done within your GUI class.
  21. Well, the first thing is you need to be null checking before calling any method on an object like a widget or npc. If that doesn't fix your issues, then start printing debug statements after every action to get a chain of events to pinpoint what's causing the problem. Also remove that recursive call in changeAttackStyle() and add a conditional sleep or something after changing tabs.
  22. You can significantly shorten some of the methods used while allowing for any other spells you wish to add in the future much more streamlined. For instance, private boolean canAttack() throws InterruptedException { if(spell.toString().toLowerCase().equals("firestrike")) { return canUseFireStrike(); } if(spell.toString().toLowerCase().equals("earthstrike")) { return canUseEarthStrike(); } if(spell.toString().toLowerCase().equals("waterstrike")) { return canUseWaterStrike(); } if(spell.toString().toLowerCase().equals("airstrike")) { return canUseAirStrike(); } return false; } Can be shortened if you initialize spell to a MagicSpell: private boolean canAttack() throws InterruptedException { return getMagic().canCast(spell, false); } This private void selectSpell() throws InterruptedException { if (spell.toString().toLowerCase().equals("firestrike")) { RS2Widget w = widgets.get(201, 1, 4); if (w != null && w.isVisible()) { w.interact("Fire Strike"); } Sleep.sleepUntil(() -> widgets.isVisible(593), 5000); } if (spell.toString().toLowerCase().equals("earthstrike")) { RS2Widget w = widgets.get(201, 1, 3); if (w != null && w.isVisible()) { w.interact("Earth Strike"); } Sleep.sleepUntil(() -> widgets.isVisible(593), 5000); } if (spell.toString().toLowerCase().equals("waterstrike")) { RS2Widget w = widgets.get(201, 1, 2); if (w != null && w.isVisible()) { w.interact("Water Strike"); } Sleep.sleepUntil(() -> widgets.isVisible(593), 5000); } if (spell.toString().toLowerCase().equals("airstrike")) { RS2Widget w = widgets.get(201, 1, 1); if (w != null && w.isVisible()) { w.interact("Wind Strike"); } Sleep.sleepUntil(() -> widgets.isVisible(593), 5000); } } Can be shortened to private void selectSpell() throws InterruptedException { RS2Widget spellWidget = getWidgets().getWidgetContainingSprite(201, spell.getSpriteIndex()); if (spellWidget != null && spellWidget.isVisible()) { spellWidget.interact(); } Sleep.sleepUntil(() -> widgets.isVisible(593), 5000); } I would move some of the logic implementation in the loop to its own method for readability, so something like this: @Override public int onLoop() throws InterruptedException { dismissDialogue(); if (!canAttack()) { this.stop(); log("[Error] Out of runes."); } if (shouldAttack()) { if (shouldRotateScreen()) { rotateCameraToLesserDemon(); } else { attack(); } } return (random(600, 900)); // time before loop starts over }
  23. The way I would design paint implementation is to keep specific paint operations in their related class. So a Woodcutting class may have its specific paint operations that displays xp gained, number of logs collected, etc. You may also have SomeOtherClass that displays its own specific information that is unrelated to the operations of the Woodcutting class. It is much easier to debug this way if some portion of the paint works unexpectedly, as well as keeping it organized. Doing it this way you can add or remove specific painters depending on what is needed. If at script start it should display both the Woodcutting painter and SomeOtherClass painter, you would add them to the bot's painter list like getBot().addPainter(Woodcutting.getPainter()); getBot().addPainter(SomeOtherClass.getPainter()); If at any point it's not necessary to display a specific painter, you would remove it with getBot().removePainter(SomeOtherClass.getPainter());
  24. This isn't something you necessarily need to fix or can fix. Bank::depositAllExcept is an overloaded method, and you're using the one with a varargs of Filter<Item>, meaning an array of item filters. Filter is a generic type, so you can create Filter<Item> to filter items or Filter<Player> to filter players and so on, but the issue arises because generics have a loss of information at compile time due to type erasure. At runtime, the only information available is there is an array of Filters, not specifically an array of Filter<Item>. In the method body of Bank::depositAllExcept(Filter<Item>...) I'd assume it checks the type of each Filter to ensure it is indeed an Item filter in order to behave as intended. Here is an example of passing an array of filters that compiles fine, but throws a ClassCastException at runtime because a Player filter can't be cast to an Item filter. Filter<Player> playerFilter = player -> player.isVisible(); Filter<Item> itemFilter = item -> item.getName().contains(" axe"); Filter[] filters = new Filter[] { playerFilter, itemFilter }; getBank().depositAllExcept(filters); So to answer the question, it's fine to suppress the warning as long as you ensure the filters being passed can be cast to the desired type in the method declaration. Further reading: http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ300 You typically only want one class to do one thing. Not sure if this is what you're referring to by a word: https://en.wikipedia.org/wiki/SOLID You can easily get coordinates of positions and areas using this: https://explv.github.io/
×
×
  • Create New...