feggit Posted September 15, 2018 Share Posted September 15, 2018 (edited) I've been writing scripts for my own for a short time. I have a fair amount of knowledge in (Java) programming because I major in Computer Science. In the beginning, I didn't know how to write scripts for the OSBot and it took me a long time to understand it. I'll put useful links to other topics and I'll add my own knowledge to this topic. I hope veteran scripters can tell me if I am saying anything incorrect, so I can learn from it. This guide is not to teach you how to program, but it is targeted to people who already know how to program but just don't know how to start. If you want to learn how to program in Java, there are other tutorials for it like this one and that one. [1, 2] I'll be updating this thread when I discover something new or when mistakes have been made as I am a beginner myself. !!! IMPORTANT !!! Everything you need to know about the OSBot API can be found in the Javadocs of the OSBot API. Choosing IDE, importing libraries and compiling Spoiler Popular IDE's are IntelliJ and Eclipse. When starting programming in Java, I used Eclipse, but then others recommended IntellJ so I now used IntelliJ. The libraries you have to import is the OSBot client file. You need to compile and build the .class file, which you need to put in your OSBot folder [3]. Skeleton code Spoiler The minimum code you need to given here [4]. Your bot script should be a subclass of Script, which is a subclass of MethodProvider. Method Provider class Spoiler The MethodProvider class provides you all the method you need. By calling certain methods, you'll get an instance of a class returned of which you can call the methods to do certain actions. A few examples that I have used are given below. /* Example */ getWalking().walk(new Position(0, 0, 0)); //Walks to (0, 0, 0) if (getSkills().getDynamic(Skill.HITPOINTS) < getSkills().getStatic(Skill.HITPOINTS)) { //Checks if HP is full. //Eat } getBank().depositAll() //Deposit all items in bank. List<String> message = getChatbox().getMessages(Chatbox.MessageType.PLAYER) //Returns all chat messages by players in the chatbox including names. int inventorySpace = getInventory().getEmptySlotCount(); //Get amount of empty spaces in your inventory; myPlayer().getPosition(); //Get position of your player myPosition() //Same //Speaks for itself myPlayer().isAnimating(); myPlayer().isMoving(); myPlayer().isUnderAttack(); Logs Spoiler You may want to log messages like System.out.println() by using the log() method to see the messages in the logger. /* Example */ log("Hello World"); Positions and Areas Spoiler Position and Area are classes to define positions and areas in the game. A Position is defined by the (x, y, z)-coordinates of the game. An Area is a set of Positions, which means you can define a area of a certain house by giving the (x,y) coordinates of two opposite corners, though there are other ways to define an area. NOTE: Areas of banks are already predefined here. /* Example */ Position grandExchangePosition = new Position(3165, 3487, 0); //Somewhere in Grand Exchange Area grandExchangeArea = new Area(3162, 3492, 3167, 3487); // The middle of Grand Exchange Area grandExchangeArea2 = Banks.GRAND_EXCHANGE; Walking Spoiler There are mainly three ways to walk. Walk, WalkPath and WebWalk. Walk is for short distances (10 tiles or so) and WebWalking is for long distances. WalkPath is to walk a path, by giving it a set of Position objects. If you do not provide a list of position, WalkPath will generate a path. However, WalkPath does not handle obstacles, WebWalking does. Yet, WebWalking consumes more resources [5, 6, 9]. On 9/14/2017 at 3:03 PM, Apaec said: walkPath does not handle obstacles walkPath does not generate a path so presumable less cpu/ram, although neither use a huge amount walkPath is more reliable as it is not required to generate a path Rule of thumb: Use walkPath where possible, use walk for very short distances (i'd say no more than 10 tiles to be safe), use webWalk if the place that you're walking from is unknown. Entities Spoiler The Entity class is the superclass of the Player, NPC, RS2Object classes. These three classes are the things you can interact with in the game. Another player can be represented by a Player object, Hans can be represented by an NPC object and a door can be represented by an NPC object. You can get all players, all npcs and all objects by methods of the MethodProvider class. You can then interact with those entites. By interacting, you can let the player do the option that can be chosen when you right-click something in the game. /* Example */ List<Player> players = getPlayers().getAll(); //Get the list of all players. players.get(0).interact("Attack"); //Attack the first player in the list. getNpcs().closest("Hans").interact("Age"); //From all the NPCs, get the closest NPC named "Hans" and use the "Age" option. getObjects().closest("Rock").interact("Mine"); //Mine the closest rock. Dialogues Spoiler Dialogues is for speaking to an NPC, useful for questing when you need to choose your answers/actions. /* Example */ NPC horacio = getNpcs().closest("Duke Horacio"); //NPC from Rune Mysteries horacio.interact("Talk-to"); getDialogues().completeDialogueU("Have you any quests for me?", "Sure, no problem.") //Completing the dialogue ExperienceTracker Spoiler When making a script to do a certain skill, you may want to keep track of how many xp the player has gained and how much time has elapsed since the start of the script. You can do this by using the ExperienceTracker. /* Example */ @Override public void onStart() { ExperienceTracker experienceTracker = getExperienceTracker(); experienceTracker.start(Skill.RANGED); //Start of tracking Ranged. } @Override public void onPaint(Graphics2D g) { g.setColor(Color.white); g.drawString("Xp: " + experienceTracker.getGainedXP(Skill.RANGED), 0); //XP gained since start. Date date = new Date(experienceTracker.getElapsed(Skill.RANGED) - 3600*1000); //Time elapsed since start. DateFormat formatter = new SimpleDateFormat("HH:mm:ss"); String dateFormatted = formatter.format(date); g.drawString("Time: " + dateFormatted, 0); } (Conditional) Sleep and Random Number Generator Spoiler Your script sometimes needs to have sleeps, for instance waiting until the ore has been replenished, or waiting a moment to mine the rock after the ore has been replenished. You can sleep two ways by using sleep() and ConditionSleep. sleep() is to sleep x miliseconds. ConditionalSleep is an object used for sleeping until a condition has been satisfied. /* Example */ sleep(1000) //Sleeps exactly 1000 ms i.e. 1 second. new ConditionalSleep(10000, 2000) { //Timeout for this sleep is 10.000 ms i.e. 10 seconds, and the condition check is every 2000 ms i.e. 2 seconds [9]. @Override public boolean condition() throws InterruptedException { return getSkills().getStatic(Skill.SLAYER) == 99; //Sleeps until Slayer is 99 } }.sleep(); Instead of using uniformly distributed numbers (meaning all numbers have equal chance to be returned by the Random number generator), one could use the function nextGaussian() for the random sleeping times, which gives a normal distributions on the numbers the method returns. You can use this website to see how your normal distribution looks like with a defined mean and standard deviation [7]. The mean should be the number that has the highest chance of being returned by the random number generator. The standard deviation is to define the deviation of the numbers returned by the random number generator. A lower the standard deviation means the random generator numbers are closer to the mean. /* Example */ Random random = new Random(); int stdev = 1; int mean = 2 sleep(random.nextGaussian() * stdev + mean); GUI and Locks Spoiler Lots of scripts has a GUI (pronounced as Gee-You-Eye or Gooey xD) window shown when starting a script, where you can set the settings. The GUI is done by Java AWT. When this GUI is shown, the script should be locked at the beginning, waiting for you to click the start button. How to make these can be found here [8]. MouseListeners and KeyListeners Spoiler If you want to detect moves from for example your mouse or keyboard (pressing F1 to show your GUI for settings), you can use BotMouseListeners and BotKeyListeners. KeyEvent and MouseEvent (subclass of InputEvent) both have a method consume() [9]. By invoking this method, the key won't be send to the game. For example F2 is the shortkey for opening the Stats tab. By consuming the event, the Stats tab won't open. Be sure to add your listeners, or it won't work. BotKeyListener botKeyListener = new BotKeyListener() { @Override public void checkKeyEvent(KeyEvent keyEvent) { if (keyEvent.getKeyCode() == KeyEvent.VK_F1) { log("F1 pressed: Open GUI."); } else if (keyEvent.getKeyCode() == KeyEvent.VK_F2) { log("F2 pressed"); keyEvent.consume() // Now only F2 is consumed, by pressing F2, the stats tab won't open, however all over F-keys will still work. } else { log("Some key \"" + keyEvent.getKeyCode() + "\" has been pressed."); } } }; BotMouseListener botMouseListener = new BotMouseListener() { @Override public void checkMouseEvent(MouseEvent mouseEvent) { if (mouseEvent.getButton() == 1) { log("Left click"); } else if (mouseEvent.getButton() == 2) { log("Right click"); } else { log("Something click"); } } }; getBot().addMouseListener(botMouseListener); //Adds the MouseListener getBot().addKeyListener(botKeyListener); //Adds the KeyListener NOTE: You can check where a key/mouse button is pressed or released by using the paramString() method for the MouseEvent and the paramString() method for the KeyEvent. Using resources Spoiler If you want to read certain files on your system e.g. txt files, you need to place it in the OSBot folder. Any other places will be denied by the OSBot client with the following message: Quote Blocked permission: ("java.io.FilePermission" "C:\Users\user\Desktop\osbot.txt" "read") Here is a nice tutorial for using resources in the correct way.. Sources Spoiler [1] A Beginners Guide to Writing OSBot Scripts (where to get started!) by Apaec by Apaec (Yes he already has "by Apaec" in the name of his topic)https://osbot.org/forum/topic/58775-a-beginners-guide-to-writing-osbot-scripts-where-to-get-started-by-apaec/ [2] Explv's Scripting 101 by Explvhttps://osbot.org/forum/topic/115124-explvs-scripting-101/ [3] Setup instructions to start scripting - Very Easy by Alekhttps://osbot.org/forum/topic/60538-setup-instructions-to-start-scripting-very-easy/ [4] OSBot Script Skeleton - The minimum code to make a script by Alekhttps://osbot.org/forum/topic/60535-osbot-script-skeleton-the-minimum-code-to-make-a-script/ [5] Differences between webwalk, walkPath and walk by Apaechttps://osbot.org/forum/topic/129515-differences-between-webwalk-walkpath-and-walk/?do=findComment&comment=1487249 [6] Basic Walking / Webwalking Tutorial - A Simple Concept by Team Capehttps://osbot.org/forum/topic/111003-basic-walking-webwalking-tutorial-a-simple-concept/ [7] Normal Distribution - OnlineStatBook.comhttp://onlinestatbook.com/2/calculators/normal_dist.html [8] [TUT] How to make a simple GUI by Sebastianhttps://osbot.org/forum/topic/128136-tut-how-to-make-a-simple-gui/ [9] Feedback by Alekhttps://osbot.org/forum/topic/146716-all-in-one-programming-guide-for-programmers/?tab=comments#comment-1735545 Edits Spoiler 15-09-2018: Updated based on Alek's feedback. Added resources paragraph. Edited September 15, 2018 by feggit update 15/09/2018 7 1 Quote Link to comment Share on other sites More sharing options...
Naked Posted September 15, 2018 Share Posted September 15, 2018 Looks good my dude! 1 Quote Link to comment Share on other sites More sharing options...
yfoo Posted September 15, 2018 Share Posted September 15, 2018 Holy shit I was literally you 9 months ago. 1 Quote Link to comment Share on other sites More sharing options...
Alek Posted September 15, 2018 Share Posted September 15, 2018 Just a few areas of improvement: You're not consuming the events in the listeners, so that mouse data is being sent to the game. You do have access to the console for System.out.println walkPath does generate a path if you do not provide it a list of positions, but it's a lot cheaper than generating a web walking path The random number generator is already contained within method provider ConditionalSleep information is misleading. The timeout is 10 seconds, the recheck is every 2 seconds. It doesn't sleep "up to 2 seconds", it sleeps exactly 2 seconds. Also don't waste your time putting random numbers into conditional sleep, you can't iterate a fraction of a cycle. For instance, 10000/2000 = 5. The ConditionalSleep will have 5 cycles, each cycle being 2 seconds on the recheck, for a maximum timeout of 10 seconds. Pretty simple math. "if (getSkills().getDynamic(Skill.HITPOINTS) != getSkills().getStatic(Skill.HITPOINTS)) { //Checks if HP is full.", If you sara brew at full hp, it will say your hp is not full (which it is), use a < sign. 2 Quote Link to comment Share on other sites More sharing options...
Lost Panda Posted September 15, 2018 Share Posted September 15, 2018 Nice job my friend. 1 Quote Link to comment Share on other sites More sharing options...
feggit Posted September 15, 2018 Author Share Posted September 15, 2018 3 hours ago, Alek said: Just a few areas of improvement: You're not consuming the events in the listeners, so that mouse data is being sent to the game. You do have access to the console for System.out.println walkPath does generate a path if you do not provide it a list of positions, but it's a lot cheaper than generating a web walking path The random number generator is already contained within method provider ConditionalSleep information is misleading. The timeout is 10 seconds, the recheck is every 2 seconds. It doesn't sleep "up to 2 seconds", it sleeps exactly 2 seconds. Also don't waste your time putting random numbers into conditional sleep, you can't iterate a fraction of a cycle. For instance, 10000/2000 = 5. The ConditionalSleep will have 5 cycles, each cycle being 2 seconds on the recheck, for a maximum timeout of 10 seconds. Pretty simple math. "if (getSkills().getDynamic(Skill.HITPOINTS) != getSkills().getStatic(Skill.HITPOINTS)) { //Checks if HP is full.", If you sara brew at full hp, it will say your hp is not full (which it is), use a < sign. Ok, thanks for the feedback. I will change my post according to these bullet points. Quote Link to comment Share on other sites More sharing options...
liverare Posted September 18, 2018 Share Posted September 18, 2018 Your GUI & lock point is debatable: If you spent too much time in the GUI, you'll be logged out. If you're unprepared in-game, you'd have to stop the script so you can ready yourself and then restart it. If the GUI is more of a helper, then locking up the game renders the GUI pointless. You don't have to block the onStart from ending; you can simply run checks onLoop to make sure your bot doesn't do anything until it has the information it needs from the GUI. Also, you should include mention about script parameters, as they're very useful for power-users who don't want an expensive GUI to have to fiddle with. I wrote a tutorial about it here. Quote Link to comment Share on other sites More sharing options...
Knuckolls Posted September 18, 2018 Share Posted September 18, 2018 added to my library of posts to read through once I learn basic java programming. looks promising though! Great post! Quote Link to comment Share on other sites More sharing options...
Glaciation96 Posted October 7, 2018 Share Posted October 7, 2018 With the dialogue, won't the bot just spam the options if there is no sleeping put in place? Quote Link to comment Share on other sites More sharing options...
nechir123 Posted July 17, 2019 Share Posted July 17, 2019 thank man for sharing Quote Link to comment Share on other sites More sharing options...