Rawrstin Posted May 17, 2016 Share Posted May 17, 2016 (edited) Hi everyone, I'm in need of some help here. This is my first attempt at making a script for OSBot, so be patient with me, please! I have attempted to develop a simple cow killing script, but have run into some slight troubles.. I don't have any errors when compiling the script, and it will boot up the client just fine and load it actually.. but when I attempt to simply "Run" the script, it will simply immediately stop and not allow me to run another script, unless I restart the client.. of course. If you could be so kind as to take a peak at my bittersweet looking code, and help a desperate guy out?! http://pastebin.com/aa1enxJW For those unwilling to view the link : import org.osbot.rs07.api.filter.Filter; import org.osbot.rs07.api.model.NPC; import org.osbot.rs07.api.ui.Skill; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; import java.awt.*; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; @ScriptManifest(name = "Rawr.Killer", info = "I take pride in what I do greatly; kill things.", version = 1.0, author = "Rawrstin", logo = "") public class main extends Script { //Declaring variables for paint / debugging. private String status = " "; private long startTime; private long runTime = System.currentTimeMillis() - startTime; @Override public void onStart() { status = "Loading..."; startTime = System.currentTimeMillis(); for (Skill skill : new Skill[]{ Skill.ATTACK, Skill.STRENGTH, Skill.DEFENCE, Skill.HITPOINTS, Skill.RANGED, Skill.MAGIC }) { getExperienceTracker().start(skill); } } // Will implement in the future. @SuppressWarnings("unused") 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; } private String targetName = "Cow"; private NPC target = npcs.closest(new Filter<NPC>() { public boolean match(NPC n) { return n.getName().equalsIgnoreCase(targetName) && n.getCurrentHealth() != 0 && n.isAttackable() != false && map.canReach(n) != false; } }); private enum State { SEARCH, ATTACK, WAIT }; private State getState() { if (target != null) { if (!target.isOnScreen()) { status = "Searching for target."; return State.SEARCH; } else { if (myPlayer().getInteracting() != null) { status = "Attacking the target."; return State.ATTACK; } else { status = "Killing the target."; return State.WAIT; } } } else { status = new String("Waiting for Spawn."); return State.WAIT; } } @Override public int onLoop() throws InterruptedException { switch (getState()) { case SEARCH : camera.toEntity(target); break; case ATTACK : target.interact("Attack"); sleep(random(99, 999)); break; case WAIT : sleep(random(99, 999)); break; default: return random(99, 999); } return random(99, 999); } public 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); } public double percentToNextLevel(Skill skill){ int curLvl = getSkills().getStatic(skill), curXP = getSkills().getExperience(skill), xpCurLvl = getSkills().getExperienceForLevel(curLvl), xpNextLvl = getSkills().getExperienceForLevel(curLvl + 1); return (((curXP - xpCurLvl) * 100) / (xpNextLvl - xpCurLvl)); } @Override public void onPaint(Graphics2D g) { //Mouse cross-hair g.setColor(Color.ORANGE); Point mP = getMouse().getPosition(); g.drawLine(mP.x, 0, mP.x, 500); g.drawLine(0, mP.y, 800, mP.y); //Debugging information g.setColor(Color.WHITE); g.drawString("Currently : " + status, 350, 330); g.drawString("Time Elapsed : " + formatTime(runTime), 10, 330); int attack, strength, defence, ranged, magic; attack = getExperienceTracker().getGainedXP(Skill.ATTACK); strength = getExperienceTracker().getGainedXP(Skill.STRENGTH); defence = getExperienceTracker().getGainedXP(Skill.DEFENCE); ranged = getExperienceTracker().getGainedXP(Skill.RANGED); magic = getExperienceTracker().getGainedXP(Skill.MAGIC); if (attack > strength && attack > defence && attack > ranged && attack > magic) { g.drawString("Attack Level : " + getSkills().getStatic(Skill.ATTACK) + " ( +" + getExperienceTracker().getGainedLevels(Skill.ATTACK) + " )", 10, 310); g.drawString("Exp Gained : " + getExperienceTracker().getGainedXP(Skill.ATTACK) + " ( " + getExperienceTracker().getGainedXPPerHour(Skill.ATTACK) + " \\ hr )", 10, 290); int nextLevel = getSkills().getStatic(Skill.ATTACK) + 1; g.drawString(getSkills().experienceToLevel(Skill.ATTACK) + " Exp ( " + percentToNextLevel(Skill.ATTACK) + "% ) until " + nextLevel, 10, 270); } else if (strength > attack && strength > defence && strength > ranged && strength > magic) { g.drawString("Strength Level : " + getSkills().getStatic(Skill.STRENGTH) + " ( +" + getExperienceTracker().getGainedLevels(Skill.STRENGTH) + " )", 10, 310); g.drawString("Exp Gained : " + getExperienceTracker().getGainedXP(Skill.STRENGTH) + " ( " + getExperienceTracker().getGainedXPPerHour(Skill.STRENGTH) + " \\ hr )", 10, 290); int nextLevel = getSkills().getStatic(Skill.STRENGTH) + 1; g.drawString(getSkills().experienceToLevel(Skill.STRENGTH) + " Exp ( " + percentToNextLevel(Skill.STRENGTH) + "% ) until " + nextLevel, 10, 270); } else if (defence > strength && defence > attack && defence > ranged && defence > magic) { g.drawString("Defence Level : " + getSkills().getStatic(Skill.DEFENCE) + " ( +" + getExperienceTracker().getGainedLevels(Skill.DEFENCE) + " )", 10, 310); g.drawString("Exp Gained : " + getExperienceTracker().getGainedXP(Skill.DEFENCE) + " ( " + getExperienceTracker().getGainedXPPerHour(Skill.DEFENCE) + " \\ hr )", 10, 290); int nextLevel = getSkills().getStatic(Skill.DEFENCE) + 1; g.drawString(getSkills().experienceToLevel(Skill.DEFENCE) + " Exp ( " + percentToNextLevel(Skill.DEFENCE) + "% ) until " + nextLevel, 10, 270); } else if (ranged > strength && ranged > defence && ranged > attack && ranged > magic) { g.drawString("Ranged Level : " + getSkills().getStatic(Skill.RANGED) + " ( +" + getExperienceTracker().getGainedLevels(Skill.RANGED) + " )", 10, 310); g.drawString("Exp Gained : " + getExperienceTracker().getGainedXP(Skill.RANGED) + " ( " + getExperienceTracker().getGainedXPPerHour(Skill.RANGED) + " \\ hr )", 10, 290); int nextLevel = getSkills().getStatic(Skill.RANGED) + 1; g.drawString(getSkills().experienceToLevel(Skill.RANGED) + " Exp ( " + percentToNextLevel(Skill.RANGED) + "% ) until " + nextLevel, 10, 270); } else if (magic > strength && magic > defence && magic > ranged && magic > attack) { g.drawString("Magic Level : " + getSkills().getStatic(Skill.MAGIC) + " ( +" + getExperienceTracker().getGainedLevels(Skill.MAGIC) + " )", 10, 310); g.drawString("Exp Gained : " + getExperienceTracker().getGainedXP(Skill.ATTACK) + " ( " + getExperienceTracker().getGainedXPPerHour(Skill.MAGIC) + " \\ hr )", 10, 290); int nextLevel = getSkills().getStatic(Skill.MAGIC) + 1; g.drawString(getSkills().experienceToLevel(Skill.MAGIC) + " Exp ( " + percentToNextLevel(Skill.MAGIC) + "% ) until " + nextLevel, 10, 270); } } @Override public void onExit() { log("Time ran : " + formatTime(runTime)); } } Thanks in advance. UPDATE:Logger info upon request : [DEBUG][05/16 02:52:31 PM]: OSBot is now ready! [INFO][05/16 02:52:32 PM]: Loaded 2 RS accounts! [INFO][05/16 02:52:33 PM]: Welcome to OSBot 2.4.59! [INFO][05/16 02:53:17 PM]: Updated injection hooks for client revision : 114! [DEBUG][Bot #1][05/16 02:53:17 PM]: Initializing stealth injection bot... [INFO][Bot #1][05/16 02:53:18 PM]: Downloading latest RS2 old-school client parameters... [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected bot reference into client! [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected world accessors! [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected 31 class and 308 field accessors! [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected canvas! [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected 4 model update calls! [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected 12 definition calls! [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected 14 definition transformation calls! [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected random.dat patch for bot #1 [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected 3 tooltip callbacks! [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected 5 config callbacks! [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected 5 head message callbacks! [DEBUG][Bot #1][05/16 02:53:19 PM]: Injected 5 chatbox message callbacks! [DEBUG][Bot #1][05/16 02:53:20 PM]: Injected 29 draw skip points! [DEBUG][Bot #1][05/16 02:53:21 PM]: Injected 2 hit splat callbacks! [DEBUG][Bot #1][05/16 02:53:21 PM]: Injected 2 equipment callbacks! [DEBUG][Bot #1][05/16 02:53:21 PM]: Injected 1 login return code callbacks! [DEBUG][Bot #1][05/16 02:53:21 PM]: Injected 14 analysis callbacks! [DEBUG][Bot #1][05/16 02:53:21 PM]: Loading RS world : 367 [INFO][Bot #1][05/16 02:53:22 PM]: Initializing 37 API modules... [INFO][05/16 02:53:22 PM]: Started bot #1 [DEBUG][05/16 02:55:23 PM]: Loading script id : 784 [DEBUG][05/16 02:55:23 PM]: Loaded script! [DEBUG][05/16 02:55:23 PM]: Launching script... [INFO][Bot #1][05/16 02:55:24 PM]: Loaded 4 built-in random solvers! [INFO][Bot #1][05/16 02:55:24 PM]: Gold Simple Fighter Started [INFO][05/16 02:55:33 PM]: Started script : Gold Simple Fighter [INFO][Bot #1][05/16 04:55:42 PM]: Terminating script Gold Simple Fighter... [INFO][Bot #1][05/16 04:55:43 PM]: Thanks for running Gold Simple Fighter, feel free to post Proggies! [INFO][Bot #1][05/16 04:55:43 PM]: Script Gold Simple Fighter has exited! [DEBUG][05/16 05:59:57 PM]: Loading script id : 784 [DEBUG][05/16 05:59:58 PM]: Loaded script! [DEBUG][05/16 05:59:58 PM]: Launching script... [INFO][Bot #1][05/16 05:59:58 PM]: Loaded 4 built-in random solvers! [INFO][Bot #1][05/16 05:59:59 PM]: Gold Simple Fighter Started [INFO][05/16 06:00:10 PM]: Started script : Gold Simple Fighter [INFO][Bot #1][05/16 06:26:13 PM]: Terminating script Gold Simple Fighter... [INFO][Bot #1][05/16 06:26:13 PM]: Thanks for running Gold Simple Fighter, feel free to post Proggies! [INFO][Bot #1][05/16 06:26:13 PM]: Script Gold Simple Fighter has exited! Edited May 17, 2016 by Rawrstin Quote Link to comment Share on other sites More sharing options...
Chris Posted May 17, 2016 Share Posted May 17, 2016 It would be best to post the client logger info. Quote Link to comment Share on other sites More sharing options...
Rawrstin Posted May 17, 2016 Author Share Posted May 17, 2016 I have modified the original post with the updated information you requested. As you can see hopefully, the client loads properly... I test another script out for a while, then attempt to run mine after the previous had ended.. but nothing appears in the log. Quote Link to comment Share on other sites More sharing options...
Explv Posted May 17, 2016 Share Posted May 17, 2016 (edited) private String targetName = "Cow"; private NPC target = npcs.closest(new Filter<NPC>() { public boolean match(NPC n) { return n.getName().equalsIgnoreCase(targetName) && n.getCurrentHealth() != 0 && n.isAttackable() != false && map.canReach(n) != false; } }); It's probably because of this ^^^^^^^^^^^^^. Firstly, this is incorrect because you are only ever looking for a Cow once. If no Cow is found, you never try to find another one, so your script will do nothing. Secondly this will break your script, because you are calling npcs.closest() before the script has been setup. To fix both of the above, you should be doing this in onLoop. Every time you go to attack a new Cow, you will need to call that code to find one. By doing this in onLoop you can also be sure that the script is setup: @Override public int onLoop() throws InterruptedException { if (!getCombat().isFighting()) attackEnemy(); return random(200, 300); } private void attackEnemy() { NPC enemy = getEnemy(); if(enemy != null && enemy.interact("Attack")) { new ConditionalSleep(5000) { @Override public boolean condition() throws InterruptedException { return getCombat().isFighting(); } }.sleep(); } } private NPC getEnemy() { return npcs.closest(n-> n.getName().equals("Cow") && n.getCurrentHealth() > 0 && n.isAttackable() && map.canReach(n) ); } I will explain in more detail why this causes your script to crash (Note the code is obfuscated so may be hard to read, I have added comments to make it more clear): There is a class called ScriptExecutor which handles the starting / stopping etc of scripts. In this class there is a method named start, which handles the starting of a new script. It's definition looks like: public void start(Script iiiIIIiIii1) throws InterruptedException { SwingUtilities.invokeLater(new Runnable() { public void run() { BotApplication.iiiIIIiIii().iiiIIIiIii().iiIiIiIIiI.setEnabled(false); BotApplication.iiiIIIiIii().iiiIIIiIii().iIIiIIiiii.setEnabled(true); BotApplication.iiiIIIiIii().iiiIIIiIii().IiIIiIiIii.setEnabled(true); } }); iiiIIIiIii.prepare(iiiIIIiIii1); // Prepare the script before starting if(!iiiIIIiIii.iiiIIIiIii(iiiIIIiIii1)) { // Start the script iiiIIIiIii.stop(); // If starting the script failed, stop the script } iiiIIIiIii.restart(); } Now notice how before starting the script, it makes a call to prepare. The prepare method looks like: public void prepare(Script iiiIIIiIii1) throws InterruptedException { iiiIIIiIii.iIIIIiiiIi.setHumanInputEnabled(false); if(iiiIIIiIii.IiiiIiIIIi) { iiiIIIiIii.stop(false); } iiiIIIiIii.IiiIiIiiII = iiiIIIiIii1; iiiIIIiIii.iiIiiIiIiI = new ScriptExecutor.InternalExecutor(null); iiiIIIiIii.IiiiIiIIIi = true; iiiIIIiIii.IIiIIiiiII = iiiIIIiIii.iIIiIIiiii = false; for(ScriptExecutor var10000 = iiiIIIiIii; !var10000.iIIIIiiiIi.isLoaded(); var10000 = iiiIIIiIii) { Thread.sleep(100L); } iiiIIIiIii1.exchangeContext(iiiIIIiIii.iIIIIiiiIi); // This is what sets up all the methods like getNpcs() etc. iiiIIIiIii.iIIIIiiiIi.getRandomExecutor().IIiIiIiIiI(); iiiIIIiIii.iIIIIiiiIi.addPainter(iiiIIIiIii1); if(!BotApplication.iiiIIIiIii().iiiIIIiIii().iiiIIIiIii()) { Lb var2 = new Lb(iiiIIIiIii.iIIIIiiiIi); iiiIIIiIii.iIIIIiiiIi.addPainter(var2); iiiIIIiIii.iIIIIiiiIi.addMouseListener(var2); } iiiIIIiIii.iIIIIiiiIi.addConfigListener(iiiIIIiIii1); iiiIIIiIii.iIIIIiiiIi.addAudioListener(iiiIIIiIii1); iiiIIIiIii.iIIIIiiiIi.messageEventQueue.clear(); iiiIIIiIii.iIIIIiiiIi.addMessageListener(iiiIIIiIii1); iiiIIIiIii.iIIIIiiiIi.addLoginListener(iiiIIIiIii1); } This prepare method includes a call to exchangeContext. The exchangeContext method is what sets up all the objects like npcs, inventory etc. This is necessary to allow scripters to access the API. The exchangeContext method looks like: public MethodProvider exchangeContext(Bot iiiIIIiIii1) { iiiIIIiIii.bot = iiiIIIiIii1; iiiIIIiIii.client = iiiIIIiIii1.getClient(); iiiIIIiIii.logger = iiiIIIiIii1.getLogger(); iiiIIIiIii.npcs = iiiIIIiIii1.getMethods().npcs; iiiIIIiIii.players = iiiIIIiIii1.getMethods().players; iiiIIIiIii.groundItems = iiiIIIiIii1.getMethods().groundItems; iiiIIIiIii.objects = iiiIIIiIii1.getMethods().objects; iiiIIIiIii.widgets = iiiIIIiIii1.getMethods().widgets; iiiIIIiIii.tabs = iiiIIIiIii1.getMethods().tabs; iiiIIIiIii.inventory = iiiIIIiIii1.getMethods().inventory; iiiIIIiIii.bank = iiiIIIiIii1.getMethods().bank; iiiIIIiIii.depositBox = iiiIIIiIii1.getMethods().depositBox; iiiIIIiIii.store = iiiIIIiIii1.getMethods().store; iiiIIIiIii.equipment = iiiIIIiIii1.getMethods().equipment; iiiIIIiIii.map = iiiIIIiIii1.getMethods().map; iiiIIIiIii.combat = iiiIIIiIii1.getMethods().combat; iiiIIIiIii.magic = iiiIIIiIii1.getMethods().magic; iiiIIIiIii.prayer = iiiIIIiIii1.getMethods().prayer; iiiIIIiIii.configs = iiiIIIiIii1.getMethods().configs; iiiIIIiIii.skills = iiiIIIiIii1.getMethods().skills; iiiIIIiIii.mouse = iiiIIIiIii1.getMethods().mouse; iiiIIIiIii.keyboard = iiiIIIiIii1.getMethods().keyboard; iiiIIIiIii.camera = iiiIIIiIii1.getMethods().camera; iiiIIIiIii.menu = iiiIIIiIii1.getMethods().menu; iiiIIIiIii.antiBan = iiiIIIiIii1.getMethods().antiBan; iiiIIIiIii.dialogues = iiiIIIiIii1.getMethods().dialogues; iiiIIIiIii.settings = iiiIIIiIii1.getMethods().settings; iiiIIIiIii.colorPicker = iiiIIIiIii1.getMethods().colorPicker; iiiIIIiIii.logoutTab = iiiIIIiIii1.getMethods().logoutTab; iiiIIIiIii.doorHandler = iiiIIIiIii1.getMethods().doorHandler; iiiIIIiIii.experienceTracker = iiiIIIiIii1.getMethods().experienceTracker; iiiIIIiIii.localWalker = iiiIIIiIii1.getMethods().localWalker; iiiIIIiIii.walking = iiiIIIiIii1.getMethods().walking; iiiIIIiIii.trade = iiiIIIiIii1.getMethods().trade; iiiIIIiIii.chatbox = iiiIIIiIii1.getMethods().chatbox; iiiIIIiIii.quests = iiiIIIiIii1.getMethods().quests; iiiIIIiIii.hintArrow = iiiIIIiIii1.getMethods().hintArrow; iiiIIIiIii.grandExchange = iiiIIIiIii1.getMethods().grandExchange; iiiIIIiIii.worlds = iiiIIIiIii1.getMethods().worlds; iiiIIIiIii.projectiles = iiiIIIiIii1.getMethods().projectiles; return iiiIIIiIii; } Only after these are setup does it call the onStart method in your script. So why does your code break? Well, where you put the npcs.closest() call in your script, means that it is called when an instance of your script is created. This means that you are calling npcs.closest() before any of the above has happened. This means that exchangeContext has not been called, so npcs is null. The result of this is that your code will throw a NullPointerException, causing your script to not start. Edited May 17, 2016 by Explv 2 Quote Link to comment Share on other sites More sharing options...
Rawrstin Posted May 17, 2016 Author Share Posted May 17, 2016 I truly appreciate the help, Explv! That makes sense entirely, and I totally overlooked that. I started from scratch, implementing your suggestions and guess what.. it's working now! I can't thank you enough. It's probably because of this ^^^^^^^^^^^^^. Firstly, this is incorrect because you are only ever looking for a Cow once. If no Cow is found, you never try to find another one, so your script will do nothing. Secondly this will break your script, because you are calling npcs.closest() before the script has been setup. To fix both of the above, you should be doing this in onLoop. Every time you go to attack a new Cow, you will need to call that code to find one. By doing this in onLoop you can also be sure that the script is setup: @Override public int onLoop() throws InterruptedException { if (!getCombat().isFighting()) attackEnemy(); return random(200, 300); } private void attackEnemy() { NPC enemy = getEnemy(); if(enemy != null && enemy.interact("Attack")) { new ConditionalSleep(5000) { @Override public boolean condition() throws InterruptedException { return getCombat().isFighting(); } }.sleep(); } } private NPC getEnemy() { return npcs.closest(n-> n.getName().equals("Cow") && n.getCurrentHealth() > 0 && n.isAttackable() && map.canReach(n) ); } I will explain in more detail why this causes your script to crash (Note the code is obfuscated so may be hard to read, I have added comments to make it more clear): There is a class called ScriptExecutor which handles the starting / stopping etc of scripts. In this class there is a method named start, which handles the starting of a new script. It's definition looks like: public void start(Script iiiIIIiIii1) throws InterruptedException { SwingUtilities.invokeLater(new Runnable() { public void run() { BotApplication.iiiIIIiIii().iiiIIIiIii().iiIiIiIIiI.setEnabled(false); BotApplication.iiiIIIiIii().iiiIIIiIii().iIIiIIiiii.setEnabled(true); BotApplication.iiiIIIiIii().iiiIIIiIii().IiIIiIiIii.setEnabled(true); } }); iiiIIIiIii.prepare(iiiIIIiIii1); // Prepare the script before starting if(!iiiIIIiIii.iiiIIIiIii(iiiIIIiIii1)) { // Start the script iiiIIIiIii.stop(); // If starting the script failed, stop the script } iiiIIIiIii.restart(); } Now notice how before starting the script, it makes a call to prepare. The prepare method looks like: public void prepare(Script iiiIIIiIii1) throws InterruptedException { iiiIIIiIii.iIIIIiiiIi.setHumanInputEnabled(false); if(iiiIIIiIii.IiiiIiIIIi) { iiiIIIiIii.stop(false); } iiiIIIiIii.IiiIiIiiII = iiiIIIiIii1; iiiIIIiIii.iiIiiIiIiI = new ScriptExecutor.InternalExecutor(null); iiiIIIiIii.IiiiIiIIIi = true; iiiIIIiIii.IIiIIiiiII = iiiIIIiIii.iIIiIIiiii = false; for(ScriptExecutor var10000 = iiiIIIiIii; !var10000.iIIIIiiiIi.isLoaded(); var10000 = iiiIIIiIii) { Thread.sleep(100L); } iiiIIIiIii1.exchangeContext(iiiIIIiIii.iIIIIiiiIi); // This is what sets up all the methods like getNpcs() etc. iiiIIIiIii.iIIIIiiiIi.getRandomExecutor().IIiIiIiIiI(); iiiIIIiIii.iIIIIiiiIi.addPainter(iiiIIIiIii1); if(!BotApplication.iiiIIIiIii().iiiIIIiIii().iiiIIIiIii()) { Lb var2 = new Lb(iiiIIIiIii.iIIIIiiiIi); iiiIIIiIii.iIIIIiiiIi.addPainter(var2); iiiIIIiIii.iIIIIiiiIi.addMouseListener(var2); } iiiIIIiIii.iIIIIiiiIi.addConfigListener(iiiIIIiIii1); iiiIIIiIii.iIIIIiiiIi.addAudioListener(iiiIIIiIii1); iiiIIIiIii.iIIIIiiiIi.messageEventQueue.clear(); iiiIIIiIii.iIIIIiiiIi.addMessageListener(iiiIIIiIii1); iiiIIIiIii.iIIIIiiiIi.addLoginListener(iiiIIIiIii1); } This prepare method includes a call to exchangeContext. The exchangeContext method is what sets up all the objects like npcs, inventory etc. This is necessary to allow scripters to access the API. The exchangeContext method looks like: public MethodProvider exchangeContext(Bot iiiIIIiIii1) { iiiIIIiIii.bot = iiiIIIiIii1; iiiIIIiIii.client = iiiIIIiIii1.getClient(); iiiIIIiIii.logger = iiiIIIiIii1.getLogger(); iiiIIIiIii.npcs = iiiIIIiIii1.getMethods().npcs; iiiIIIiIii.players = iiiIIIiIii1.getMethods().players; iiiIIIiIii.groundItems = iiiIIIiIii1.getMethods().groundItems; iiiIIIiIii.objects = iiiIIIiIii1.getMethods().objects; iiiIIIiIii.widgets = iiiIIIiIii1.getMethods().widgets; iiiIIIiIii.tabs = iiiIIIiIii1.getMethods().tabs; iiiIIIiIii.inventory = iiiIIIiIii1.getMethods().inventory; iiiIIIiIii.bank = iiiIIIiIii1.getMethods().bank; iiiIIIiIii.depositBox = iiiIIIiIii1.getMethods().depositBox; iiiIIIiIii.store = iiiIIIiIii1.getMethods().store; iiiIIIiIii.equipment = iiiIIIiIii1.getMethods().equipment; iiiIIIiIii.map = iiiIIIiIii1.getMethods().map; iiiIIIiIii.combat = iiiIIIiIii1.getMethods().combat; iiiIIIiIii.magic = iiiIIIiIii1.getMethods().magic; iiiIIIiIii.prayer = iiiIIIiIii1.getMethods().prayer; iiiIIIiIii.configs = iiiIIIiIii1.getMethods().configs; iiiIIIiIii.skills = iiiIIIiIii1.getMethods().skills; iiiIIIiIii.mouse = iiiIIIiIii1.getMethods().mouse; iiiIIIiIii.keyboard = iiiIIIiIii1.getMethods().keyboard; iiiIIIiIii.camera = iiiIIIiIii1.getMethods().camera; iiiIIIiIii.menu = iiiIIIiIii1.getMethods().menu; iiiIIIiIii.antiBan = iiiIIIiIii1.getMethods().antiBan; iiiIIIiIii.dialogues = iiiIIIiIii1.getMethods().dialogues; iiiIIIiIii.settings = iiiIIIiIii1.getMethods().settings; iiiIIIiIii.colorPicker = iiiIIIiIii1.getMethods().colorPicker; iiiIIIiIii.logoutTab = iiiIIIiIii1.getMethods().logoutTab; iiiIIIiIii.doorHandler = iiiIIIiIii1.getMethods().doorHandler; iiiIIIiIii.experienceTracker = iiiIIIiIii1.getMethods().experienceTracker; iiiIIIiIii.localWalker = iiiIIIiIii1.getMethods().localWalker; iiiIIIiIii.walking = iiiIIIiIii1.getMethods().walking; iiiIIIiIii.trade = iiiIIIiIii1.getMethods().trade; iiiIIIiIii.chatbox = iiiIIIiIii1.getMethods().chatbox; iiiIIIiIii.quests = iiiIIIiIii1.getMethods().quests; iiiIIIiIii.hintArrow = iiiIIIiIii1.getMethods().hintArrow; iiiIIIiIii.grandExchange = iiiIIIiIii1.getMethods().grandExchange; iiiIIIiIii.worlds = iiiIIIiIii1.getMethods().worlds; iiiIIIiIii.projectiles = iiiIIIiIii1.getMethods().projectiles; return iiiIIIiIii; } Only after these are setup does it call the onStart method in your script. So why does your code break? Well, where you put the npcs.closest() call in your script, means that it is called when an instance of your script is created. This means that you are calling npcs.closest() before any of the above has happened. This means that exchangeContext has not been called, so npcs is null. The result of this is that your code will throw a NullPointerException, causing your script to not start. 1 Quote Link to comment Share on other sites More sharing options...