imancity Posted May 12, 2016 Share Posted May 12, 2016 (edited) Hello! So I had an idea to make a adamant arrow looting script. It would be good for low levels to run in the Edgeville wild in f2p worlds. So far the script runs to the wild, and it does loot, but it seems to take its time. It doesn't immediately jump at an arrow pile when it sees one. Also, how can i make it move around in 'search' of more arrows? Along with that, it'd be cool to add a loot counter and price calculator, would that be difficult? Only my second time coding scripts, any help is appreciated. Here is my current code, hopefully doesn't get my idea stolen :P import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import org.osbot.rs07.api.model.Entity; import org.osbot.rs07.api.model.GroundItem; import org.osbot.rs07.script.Script; import org.osbot.rs07.api.map.Area; import org.osbot.rs07.script.ScriptManifest; @ScriptManifest(name="Edgeville Arrow Looter", author="iManCity", version=1.0, info="", logo="") public class EdgevilleArrowLooter extends Script { GroundItem arrows; private final Area edgevilleBank = new Area(3092, 3494, 3098, 3498); private final Area edgevilleWild = new Area(3070, 3527, 3100, 3548); int sleep; long startTime; boolean hasMoved = false; Thread tasks = new Thread(); public void onStart() { this.startTime = System.currentTimeMillis(); } public void onExit() { } public int onLoop() throws InterruptedException { this.sleep = EdgevilleArrowLooter.random((int)200, (int)400); this.arrows = (GroundItem)this.groundItems.closest(new String[]{"Adamant arrow"}); if (!edgevilleWild.contains(myPosition())){ getWalking().webWalk(edgevilleWild); } if (this.arrows.getAmount() <25 && this.arrows != null && this.groundItems.closest(new String[]{"Adamant arrow"}) != null) { if (this.map.canReach((Entity) this.arrows) && !this.arrows.isOnScreen() && !this.isPlayerAnimating()) { this.walking.walk((Entity)this.arrows); } if (!this.isPlayerAnimating()) { this.arrows.interact(new String[]{"Take"}); } } if (this.arrows.getAmount() >= 100) getWalking().webWalk(edgevilleBank); if (!getBank().isOpen()) { getBank().open(); } else { getBank().depositAll(); getBank().close(); } return EdgevilleArrowLooter.random((int)300, (int)600); } public boolean isPlayerAnimating() throws InterruptedException { int i = 0; while (i < 25) { if (this.myPlayer().isAnimating() || this.myPlayer().isMoving()) { return true; } EdgevilleArrowLooter.sleep((long)100); ++i; } return false; } public String format(long time) { StringBuilder string = new StringBuilder(); long totalSeconds = time / 1000; long totalMinutes = totalSeconds / 60; long totalHours = totalMinutes / 60; int seconds = (int)totalSeconds % 60; int minutes = (int)totalMinutes % 60; int hours = (int)totalHours % 24; if (hours > 0) { string.append(String.valueOf(hours) + "h "); } if (minutes > 0) { string.append(String.valueOf(minutes) + "m "); } string.append(String.valueOf(seconds) + "s"); return string.toString(); } public void onPaint(Graphics2D g) { Font font1 = new Font("Arial", 0, 12); Color color1 = new Color(255, 255, 255, 255); g.setFont(font1); g.setColor(color1); g.drawString("Runtime: " + this.format(System.currentTimeMillis() - this.startTime), 8, 335); } } Edited May 12, 2016 by imancity Quote Link to comment Share on other sites More sharing options...
Qubit Posted May 12, 2016 Share Posted May 12, 2016 (edited) if (this.map.canReach((Entity) this.arrows) && !this.arrows.isOnScreen() && !this.isPlayerAnimating()) { this.walking.walk((Entity)this.arrows); //Why not just interact with?. Removing this would also cut off time to collect arrows } if (!this.isPlayerAnimating()) { this.arrows.interact(new String[]{"Take"}); } counter get number of arrows at pos attempt to pickup, get number of arrows at same pos and get difference and add to counter, price checker there's many snippets of that code in the tutorials section for the forum Edited May 12, 2016 by Qubit Quote Link to comment Share on other sites More sharing options...
The Hero of Time Posted May 12, 2016 Share Posted May 12, 2016 tip: make it loot a lot more than addy arrows, food, pots, etc Quote Link to comment Share on other sites More sharing options...
Explv Posted May 12, 2016 Share Posted May 12, 2016 (edited) Hello! So I had an idea to make a adamant arrow looting script. It would be good for low levels to run in the Edgeville wild in f2p worlds. So far the script runs to the wild, and it does loot, but it seems to take its time. It doesn't immediately jump at an arrow pile when it sees one. Also, how can i make it move around in 'search' of more arrows? Along with that, it'd be cool to add a loot counter and price calculator, would that be difficult? Only my second time coding scripts, any help is appreciated. Here is my current code, hopefully doesn't get my idea stolen :P import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import org.osbot.rs07.api.model.Entity; import org.osbot.rs07.api.model.GroundItem; import org.osbot.rs07.script.Script; import org.osbot.rs07.api.map.Area; import org.osbot.rs07.script.ScriptManifest; @ScriptManifest(name="Edgeville Arrow Looter", author="iManCity", version=1.0, info="", logo="") public class EdgevilleArrowLooter extends Script { GroundItem arrows; private final Area edgevilleBank = new Area(3092, 3494, 3098, 3498); private final Area edgevilleWild = new Area(3070, 3527, 3100, 3548); int sleep; long startTime; boolean hasMoved = false; Thread tasks = new Thread(); public void onStart() { this.startTime = System.currentTimeMillis(); } public void onExit() { } public int onLoop() throws InterruptedException { this.sleep = EdgevilleArrowLooter.random((int)200, (int)400); this.arrows = (GroundItem)this.groundItems.closest(new String[]{"Adamant arrow"}); if (!edgevilleWild.contains(myPosition())){ getWalking().webWalk(edgevilleWild); } if (this.arrows.getAmount() <25 && this.arrows != null && this.groundItems.closest(new String[]{"Adamant arrow"}) != null) { if (this.map.canReach((Entity) this.arrows) && !this.arrows.isOnScreen() && !this.isPlayerAnimating()) { this.walking.walk((Entity)this.arrows); } if (!this.isPlayerAnimating()) { this.arrows.interact(new String[]{"Take"}); } } if (this.arrows.getAmount() >= 100) getWalking().webWalk(edgevilleBank); if (!getBank().isOpen()) { getBank().open(); } else { getBank().depositAll(); getBank().close(); } return EdgevilleArrowLooter.random((int)300, (int)600); } public boolean isPlayerAnimating() throws InterruptedException { int i = 0; while (i < 25) { if (this.myPlayer().isAnimating() || this.myPlayer().isMoving()) { return true; } EdgevilleArrowLooter.sleep((long)100); ++i; } return false; } public String format(long time) { StringBuilder string = new StringBuilder(); long totalSeconds = time / 1000; long totalMinutes = totalSeconds / 60; long totalHours = totalMinutes / 60; int seconds = (int)totalSeconds % 60; int minutes = (int)totalMinutes % 60; int hours = (int)totalHours % 24; if (hours > 0) { string.append(String.valueOf(hours) + "h "); } if (minutes > 0) { string.append(String.valueOf(minutes) + "m "); } string.append(String.valueOf(seconds) + "s"); return string.toString(); } public void onPaint(Graphics2D g) { Font font1 = new Font("Arial", 0, 12); Color color1 = new Color(255, 255, 255, 255); g.setFont(font1); g.setColor(color1); g.drawString("Runtime: " + this.format(System.currentTimeMillis() - this.startTime), 8, 335); } } Firstly I am not sure that your script even works? You have created a variable GroundItem arrows; And you set its value to the closest arrows ground item: this.arrows = (GroundItem)this.groundItems.closest(new String[]{"Adamant arrow"}); You only need to use this. to refer to a variable in the current class, if there is another variable in the method with the same name. I am not sure why you are casting to GroundItem here because the method already returns a GroundItem. I am also not sure why you are using a String[] with one value, rather than just using a String. Perhaps you decompiled this from someone else's script? You then only pick up these arrows if there are < 25 of them: if(this.arrows.getAmount() <25 && this.arrows != null ...) Which will also throw a NullPointerException by the way, as you are calling getAmount() before checking if it is null. Finally, you walk to the bank when the amount of arrows on the ground is >= 100: if (this.arrows.getAmount() >= 100) getWalking().webWalk(edgevilleBank); I also don't understand why you are always web walking to the bank. You only need to do that if you are not already in the bank. The web walking may also fail, which will lead to your calls to getBank().open() etc. throwing errors. You are also not sleeping after calling getBank().open or after taking the arrows, which will result in a lot of spam clicking. None of this code makes any sense, and I would be surprised if it has been working at all for you. What you really want to be doing, is checking how many arrows you have in your Inventory. If you have more than 100 arrows in your inventory, the you want to bank. If there are any amount of arrows on the ground, then you want to pick them up. With regards to walking to find arrows, you can just web walk to random positions within the area you created, and stop walking if there are arrows on the ground. I have written an untested example and have added comments to it, to try and show you how this could be done: import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.map.Position; import org.osbot.rs07.api.map.constants.Banks; import org.osbot.rs07.api.model.GroundItem; import org.osbot.rs07.api.webwalk.INodeRouteFinder; import org.osbot.rs07.event.WebWalkEvent; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; import org.osbot.rs07.utility.Condition; import org.osbot.rs07.utility.ConditionalSleep; import java.awt.*; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.Optional; @ScriptManifest(author = "Explv", name = "Adamant Arrow Wildy Looter", info = "Loots adamant arrows in the Wilderness", version = 0.1, logo = "") public class WildyLooter extends Script { // This is an enum of all the possible states of the script private enum State { FIND_LOOT, LOOTING, BANKING, WALKING_TO_WILDERNESS, WALKING_TO_BANK } private final Area wilderness = new Area(3070, 3527, 3100, 3548); private final int adamantArrowID = 890; private int adamantArrowPrice = -1; private long prevArrowCount; // Stores the amount of arrows in the inventory private long arrowCounter; // Stores the amount of arrows collected private long startTime; /* The INoderouteFinder is what web walking uses to find routes, you need to create one of these to use custom web walking events. Only create this ONCE, it is very expensive to create. */ private INodeRouteFinder routeFinder; @Override public void onStart() { // When the script starts, an instance of INodeRouteFinder is created, for the custom web walk event routeFinder = INodeRouteFinder.createAdvanced(); // When the script starts, set the prevArrowCount to the amount of arrows in the inventory prevArrowCount = getInventory().getAmount("Adamant arrow"); startTime = System.currentTimeMillis(); adamantArrowPrice = getPrice(adamantArrowID); // get the price of adamant arrows } @Override public int onLoop() throws InterruptedException { // This line makes sure that the route finder is created, before we continue with the script if (routeFinder == null) return 100; /* A switch statement, is just like having multiple if else statements, where we are only checking the value on one variable */ switch (getState()) { // get the result of the getState() method case FIND_LOOT: findLoot(); // when the value is FIND_LOOT, call the findLoot() method (random walk) break; case LOOTING: loot(); // when the value is LOOTING, call the loot method (pick up arrows) break; case BANKING: bank(); // when the value is BANKING, perform the banking break; case WALKING_TO_WILDERNESS: // TODO: I'm not sure that web walking to the wilderness will even work, you may need to make a custom method for this getWalking().webWalk(wilderness); break; case WALKING_TO_BANK: getWalking().webWalk(Banks.EDGEVILLE); break; } return random(200, 300); } // This method returns what State the script is in at the current point in time. private State getState() { // If there are at least 100 Adamant arrows in the inventory if (getInventory().getAmount("Adamant arrow") >= 100) { // If we are in the bank, then perform banking, otherwise, walk to the bank return Banks.EDGEVILLE.contains(myPosition()) ? State.BANKING : State.WALKING_TO_BANK; } // We do not have 100 Adamant arrows in the inventory so: // If the player is not in the wilderness, walk there if (!wilderness.contains(myPosition())) return State.WALKING_TO_WILDERNESS; // If there are Adamant arrows on the ground, pick them up if (getGroundItems().closest("Adamant arrow") != null) return State.LOOTING; // There are no Adamant arrows on the ground, so randomly walk until we find some return State.FIND_LOOT; } // This method randomly walks around the wilderness, looking for arrows private void findLoot() { // Here we try and get a Position which is inside the wilderness area, and at least 20 tiles from the player final Optional<Position> randomDestination = wilderness.getPositions().stream().filter(position -> getMap().distance(position) >= 20).findAny(); // If we found a position that is at least 20 tiles away if (randomDestination.isPresent()) { // Create a custom WebWalkEvent, using the routefinder we created, and with the position as its destination final WebWalkEvent webWalkEvent = new WebWalkEvent(routeFinder, randomDestination.get()); // Set the break condition of the event to stop walking when there are Adamant arrows on the ground webWalkEvent.setBreakCondition(new Condition() { @Override public boolean evaluate() { return getGroundItems().closest("Adamant arrow") != null; } }); // Start web walking execute(webWalkEvent); } } // This method picks up Adamant arrows from the ground private void loot() { // Find the closest Adamant arrows final GroundItem adamantArrows = getGroundItems().closest("Adamant arrow"); // If we found some, and we successfully perform the interaction "Take" if (adamantArrows != null && adamantArrows.interact("Take")) { // Sleep for 5 seconds or until the arrows no longer exist (Either we picked them up, or someone else did) new ConditionalSleep(5000) { @Override public boolean condition() throws InterruptedException { return !adamantArrows.exists(); } }.sleep(); updateArrowCount(); // Update the arrow counter } } // This method updates the arrow counter; private void updateArrowCount() { long arrowInvcount = getInventory().getAmount("Adamant arrow"); arrowCounter += (arrowInvcount - prevArrowCount); prevArrowCount = arrowInvcount; } // This method performs the banking private void bank() throws InterruptedException { if (!getBank().isOpen()) openBank(); // If the bank isn't open, open it else if(!getInventory().isEmpty() && getBank().depositAll()){ // Otherwise, the bank is open, so deposit everything prevArrowCount = 0; // Reset inventory arrow amount to 0 (we just deposited them) } } // Custom method for opening the bank (with a sleep to avoid spam clicking) private void openBank() throws InterruptedException { // If we successfully performed the open bank interaction if (getBank().open()){ // Sleep for 5 seconds, or until the bank is open new ConditionalSleep(5000) { @Override public boolean condition() throws InterruptedException { return getBank().isOpen(); } }.sleep(); } } @Override public void onPaint(final Graphics2D g) { Font font1 = new Font("Arial", 0, 12); Color color1 = new Color(255, 255, 255, 255); g.setFont(font1); g.setColor(color1); g.drawString("Runtime: " + formatTime(System.currentTimeMillis() - startTime), 8, 335); g.drawString("Arrows collected: " + arrowCounter, 8, 350); if (adamantArrowPrice > -1) { g.drawString("Arrow price: " + adamantArrowPrice, 8, 370); g.drawString("Profit: " + formatValue(adamantArrowPrice * arrowCounter), 8, 390); } } // Converts ms to a timestamp private String formatTime(long ms){ long s = ms / 1000, m = s / 60, h = m / 60, d = h / 24; s %= 60; m %= 60; h %= 24; return d > 0 ? String.format("%02d:%02d:%02d:%02d", d, h, m, s) : h > 0 ? String.format("%02d:%02d:%02d", h, m, s) : String.format("%02d:%02d", m, s); } // Converts a value to m or k private String formatValue(long v){ return (v > 1_000_000) ? String.format("%.2fm", (double) (v / 1_000_000)) : (v > 1000) ? String.format("%.1fk", (double) (v / 1000)) : v + ""; } // Gets the price of an item from the rsbuddy api private int getPrice(int id){ try { URL url = new URL("http://api.rsbuddy.com/grandExchange?a=guidePrice&i=" + id); URLConnection con = url.openConnection(); con.setUseCaches(true); BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream())); String[] data = br.readLine().replace("{", "").replace("}", "").split(","); return Integer.parseInt(data[0].split(":")[1]); } catch(Exception e){ log(e); } return -1; } @Override public void onExit(){ routeFinder = null; } } An explanation of this: If there are at least 100 Adamant arrows in the inventory: If the player is in the bank: If the bank is not open: Attempt to open it Sleep until it is open Else: Deposit everything Else: Walk to the bank Else if the player is not in the wilderness: Walk there Else if there are any Adamant arrows on the ground: Attempt to take them Sleep until the arrows no longer exist Else: Randomly walk until there are some Adamant arrows on the ground Edited May 12, 2016 by Explv 4 Quote Link to comment Share on other sites More sharing options...
imancity Posted May 12, 2016 Author Share Posted May 12, 2016 Firstly I am not sure that your script even works? You have created a variable GroundItem arrows; And you set its value to the closest arrows ground item: this.arrows = (GroundItem)this.groundItems.closest(new String[]{"Adamant arrow"}); You only need to use this. to refer to a variable in the current class, if there is another variable in the method with the same name. I am not sure why you are casting to GroundItem here because the method already returns a GroundItem. I am also not sure why you are using a String[] with one value, rather than just using a String. Perhaps you decompiled this from someone else's script? You then only pick up these arrows if there are < 25 of them: if(this.arrows.getAmount() <25 && this.arrows != null ...) Which will also throw a NullPointerException by the way, as you are calling getAmount() before checking if it is null. Finally, you walk to the bank when the amount of arrows on the ground is >= 100: if (this.arrows.getAmount() >= 100) getWalking().webWalk(edgevilleBank); I also don't understand why you are always web walking to the bank. You only need to do that if you are not already in the bank. The web walking may also fail, which will lead to your calls to getBank().open() etc. throwing errors. You are also not sleeping after calling getBank().open or after taking the arrows, which will result in a lot of spam clicking. None of this code makes any sense, and I would be surprised if it has been working at all for you. What you really want to be doing, is checking how many arrows you have in your Inventory. If you have more than 100 arrows in your inventory, the you want to bank. If there are any amount of arrows on the ground, then you want to pick them up. With regards to walking to find arrows, you can just web walk to random positions within the area you created, and stop walking if there are arrows on the ground. I have written an untested example and have added comments to it, to try and show you how this could be done: import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.map.Position; import org.osbot.rs07.api.map.constants.Banks; import org.osbot.rs07.api.model.GroundItem; import org.osbot.rs07.api.webwalk.INodeRouteFinder; import org.osbot.rs07.event.WebWalkEvent; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; import org.osbot.rs07.utility.Condition; import org.osbot.rs07.utility.ConditionalSleep; import java.awt.*; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.Optional; @ScriptManifest(author = "Explv", name = "Adamant Arrow Wildy Looter", info = "Loots adamant arrows in the Wilderness", version = 0.1, logo = "") public class WildyLooter extends Script { // This is an enum of all the possible states of the script private enum State { FIND_LOOT, LOOTING, BANKING, WALKING_TO_WILDERNESS, WALKING_TO_BANK } private final Area wilderness = new Area(3070, 3527, 3100, 3548); private final int adamantArrowID = 890; private int adamantArrowPrice = -1; private long prevArrowCount; // Stores the amount of arrows in the inventory private long arrowCounter; // Stores the amount of arrows collected private long startTime; /* The INoderouteFinder is what web walking uses to find routes, you need to create one of these to use custom web walking events. Only create this ONCE, it is very expensive to create. */ private INodeRouteFinder routeFinder; @Override public void onStart() { // When the script starts, an instance of INodeRouteFinder is created, for the custom web walk event routeFinder = INodeRouteFinder.createAdvanced(); // When the script starts, set the prevArrowCount to the amount of arrows in the inventory prevArrowCount = getInventory().getAmount("Adamant arrow"); startTime = System.currentTimeMillis(); adamantArrowPrice = getPrice(adamantArrowID); // get the price of adamant arrows } @Override public int onLoop() throws InterruptedException { // This line makes sure that the route finder is created, before we continue with the script if (routeFinder == null) return 100; /* A switch statement, is just like having multiple if else statements, where we are only checking the value on one variable */ switch (getState()) { // get the result of the getState() method case FIND_LOOT: findLoot(); // when the value is FIND_LOOT, call the findLoot() method (random walk) break; case LOOTING: loot(); // when the value is LOOTING, call the loot method (pick up arrows) break; case BANKING: bank(); // when the value is BANKING, perform the banking break; case WALKING_TO_WILDERNESS: // TODO: I'm not sure that web walking to the wilderness will even work, you may need to make a custom method for this getWalking().webWalk(wilderness); break; case WALKING_TO_BANK: getWalking().webWalk(Banks.EDGEVILLE); break; } return random(200, 300); } // This method returns what State the script is in at the current point in time. private State getState() { // If there are at least 100 Adamant arrows in the inventory if (getInventory().getAmount("Adamant arrow") >= 100) { // If we are in the bank, then perform banking, otherwise, walk to the bank return Banks.EDGEVILLE.contains(myPosition()) ? State.BANKING : State.WALKING_TO_BANK; } // We do not have 100 Adamant arrows in the inventory so: // If the player is not in the wilderness, walk there if (!wilderness.contains(myPosition())) return State.WALKING_TO_WILDERNESS; // If there are Adamant arrows on the ground, pick them up if (getGroundItems().closest("Adamant arrow") != null) return State.LOOTING; // There are no Adamant arrows on the ground, so randomly walk until we find some return State.FIND_LOOT; } // This method randomly walks around the wilderness, looking for arrows private void findLoot() { // Here we try and get a Position which is inside the wilderness area, and at least 20 tiles from the player final Optional<Position> randomDestination = wilderness.getPositions().stream().filter(position -> getMap().distance(position) >= 20).findAny(); // If we found a position that is at least 20 tiles away if (randomDestination.isPresent()) { // Create a custom WebWalkEvent, using the routefinder we created, and with the position as its destination final WebWalkEvent webWalkEvent = new WebWalkEvent(routeFinder, randomDestination.get()); // Set the break condition of the event to stop walking when there are Adamant arrows on the ground webWalkEvent.setBreakCondition(new Condition() { @Override public boolean evaluate() { return getGroundItems().closest("Adamant arrow") != null; } }); // Start web walking execute(webWalkEvent); } } // This method picks up Adamant arrows from the ground private void loot() { // Find the closest Adamant arrows final GroundItem adamantArrows = getGroundItems().closest("Adamant arrow"); // If we found some, and we successfully perform the interaction "Take" if (adamantArrows != null && adamantArrows.interact("Take")) { // Sleep for 5 seconds or until the arrows no longer exist (Either we picked them up, or someone else did) new ConditionalSleep(5000) { @Override public boolean condition() throws InterruptedException { return !adamantArrows.exists(); } }.sleep(); updateArrowCount(); // Update the arrow counter } } // This method updates the arrow counter; private void updateArrowCount() { long arrowInvcount = getInventory().getAmount("Adamant arrow"); arrowCounter += (arrowInvcount - prevArrowCount); prevArrowCount = arrowInvcount; } // This method performs the banking private void bank() throws InterruptedException { if (!getBank().isOpen()) openBank(); // If the bank isn't open, open it else if(!getInventory().isEmpty() && getBank().depositAll()){ // Otherwise, the bank is open, so deposit everything prevArrowCount = 0; // Reset inventory arrow amount to 0 (we just deposited them) } } // Custom method for opening the bank (with a sleep to avoid spam clicking) private void openBank() throws InterruptedException { // If we successfully performed the open bank interaction if (getBank().open()){ // Sleep for 5 seconds, or until the bank is open new ConditionalSleep(5000) { @Override public boolean condition() throws InterruptedException { return getBank().isOpen(); } }.sleep(); } } @Override public void onPaint(final Graphics2D g) { Font font1 = new Font("Arial", 0, 12); Color color1 = new Color(255, 255, 255, 255); g.setFont(font1); g.setColor(color1); g.drawString("Runtime: " + formatTime(System.currentTimeMillis() - startTime), 8, 335); g.drawString("Arrows collected: " + arrowCounter, 8, 350); if (adamantArrowPrice > -1) { g.drawString("Arrow price: " + adamantArrowPrice, 8, 370); g.drawString("Profit: " + formatValue(adamantArrowPrice * arrowCounter), 8, 390); } } // Converts ms to a timestamp private String formatTime(long ms){ long s = ms / 1000, m = s / 60, h = m / 60, d = h / 24; s %= 60; m %= 60; h %= 24; return d > 0 ? String.format("%02d:%02d:%02d:%02d", d, h, m, s) : h > 0 ? String.format("%02d:%02d:%02d", h, m, s) : String.format("%02d:%02d", m, s); } // Converts a value to m or k private String formatValue(long v){ return (v > 1_000_000) ? String.format("%.2fm", (double) (v / 1_000_000)) : (v > 1000) ? String.format("%.1fk", (double) (v / 1000)) : v + ""; } // Gets the price of an item from the rsbuddy api private int getPrice(int id){ try { URL url = new URL("http://api.rsbuddy.com/grandExchange?a=guidePrice&i=" + id); URLConnection con = url.openConnection(); con.setUseCaches(true); BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream())); String[] data = br.readLine().replace("{", "").replace("}", "").split(","); return Integer.parseInt(data[0].split(":")[1]); } catch(Exception e){ log(e); } return -1; } @Override public void onExit(){ routeFinder = null; } } An explanation of this: If there are at least 100 Adamant arrows in the inventory: If the player is in the bank: If the bank is not open: Attempt to open it Sleep until it is open Else: Deposit everything Else: Walk to the bank Else if the player is not in the wilderness: Walk there Else if there are any Adamant arrows on the ground: Attempt to take them Sleep until the arrows no longer exist Else: Randomly walk until there are some Adamant arrows on the ground I used bits and pieces from other open scripts to try to get an idea for how to write mine, and I hadn't finished up cleaning it completely. I know there is some useless stuff and definitely some stuff I did wrong, but it seemed to at least run which was good for a start for me lol. Thanks a ton for the help, I'm gonna sift through this and study and edit it to make this correctly, I appreciate it! Quote Link to comment Share on other sites More sharing options...