ikk Posted January 4, 2016 Share Posted January 4, 2016 Hey, I'm extremely new to scripting currently trying to work out all the bugs in my first script. I'm trying to use the door handler to open my doors but at the moment I'm getting errors in my script. Here's the code: if ( doorHandler.getNextObstacle(Constants.AK_WEST_FIGHT.getRandomPosition()) != null) { doorHandler.handleNextObstacle(Constants.AK_WEST_FIGHT); //^^ This is the line causing the error Script.sleep(300 + Script.random(1000)); this.sA.log("Opened door"); } else { this.walk.walkPath(Constants.WEST_START2); this.sA.log("Entering west room"); } Any help with this would be greatly appreciated Quote Link to comment Share on other sites More sharing options...
Explv Posted January 4, 2016 Share Posted January 4, 2016 Hey, I'm extremely new to scripting currently trying to work out all the bugs in my first script. I'm trying to use the door handler to open my doors but at the moment I'm getting errors in my script. Here's the code: if ( doorHandler.getNextObstacle(Constants.AK_WEST_FIGHT.getRandomPosition()) != null) { doorHandler.handleNextObstacle(Constants.AK_WEST_FIGHT); //^^ This is the line causing the error Script.sleep(300 + Script.random(1000)); this.sA.log("Opened door"); } else { this.walk.walkPath(Constants.WEST_START2); this.sA.log("Entering west room"); } Any help with this would be greatly appreciated Are you sure that line is the one causing the error? There isn't anything obviously wrong with it. Quote Link to comment Share on other sites More sharing options...
ikk Posted January 4, 2016 Author Share Posted January 4, 2016 (edited) Are you sure that line is the one causing the error? There isn't anything obviously wrong with it. I'm fairly certain, this is the debug I'm getting in the logger: [INFO][Bot #1][01/04 01:09:07 PM]: Terminating script ikkWarriors... [ERROR][Bot #1][01/04 01:09:07 PM]: Error in script executor! java.lang.NullPointerException at org.osbot.rs07.api.DoorHandler.getObstacles(vk:52) at org.osbot.rs07.api.DoorHandler.getNextObstacle(vk:22) at Nodes.PickRoom.execute(PickRoom.java:81) at Core.ikkWarriors.onLoop(ikkWarriors.java:83) at org.osbot.rs07.event.ScriptExecutor$InternalExecutor.run(we:22) at java.lang.Thread.run(Unknown Source) [INFO][Bot #1][01/04 01:09:07 PM]: Script ikkWarriors has exited! And line 83 is the line that I pointed out in the post above. It's really weirding me out because this code worked fine yesterday, I can't figure out what I changed to make everything mess up. Here is the whole Node that I'm working from if that is of any more use: package Nodes; import org.osbot.rs07.api.DoorHandler; import org.osbot.rs07.script.Script; import Core.Node; import Data.Constants; import Utils.Walking; public class PickRoom extends Node { Walking walk = new Walking(this.sA); Constants c = new Constants(); public PickRoom(Script sA) { super(sA); } public String status() { return "Choosing Fight Room"; } public boolean shouldBank() { return ( (this.sA.inventory.isFull() && this.sA.inventory.getAmount(Constants.FOOD) < 6) || ( !this.sA.inventory.contains(Constants.FOOD) ) ); } public boolean validate() throws InterruptedException { return ( Constants.AK_CHOOSE_AREA.contains(this.sA.myPlayer()) && !shouldBank()); } public boolean execute() throws InterruptedException { if (!Constants.AK_EAST_FIGHT.contains(this.sA.myPlayer()) || !Constants.AK_WEST_FIGHT.contains(this.sA.myPlayer())) { DoorHandler doorHandler = new DoorHandler(); if (Constants.EAST_HALL.contains(this.sA.myPlayer())) { if ( doorHandler.getNextObstacle(Constants.AK_WEST_FIGHT.getRandomPosition()) != null) { doorHandler.handleNextObstacle(Constants.AK_WEST_FIGHT); Script.sleep(300 + Script.random(1000)); this.sA.log("Opened door"); } else { this.walk.walkPath(Constants.WEST_START2); this.sA.log("Entering west room"); } } else if (Constants.WEST_HALL.contains(this.sA.myPlayer())) { if ( doorHandler.getNextObstacle(Constants.AK_WEST_FIGHT.getRandomPosition()) != null) { doorHandler.handleNextObstacle(Constants.AK_WEST_FIGHT); Script.sleep(300 + Script.random(1000)); this.sA.log("Opened door"); } else { this.walk.walkPath(Constants.WEST_START2); this.sA.log("Entering west room"); } } } Script.sleep(250 + Script.random(750)); return true; } Edited January 4, 2016 by ikk Quote Link to comment Share on other sites More sharing options...
FrostBug Posted January 4, 2016 Share Posted January 4, 2016 Don't create a new doorhandler instance; use the one in your Script class. If you want to create a new doorhandler instance, you have to exchange contexts with it before using it. Quote Link to comment Share on other sites More sharing options...
ikk Posted January 5, 2016 Author Share Posted January 5, 2016 Don't create a new doorhandler instance; use the one in your Script class. If you want to create a new doorhandler instance, you have to exchange contexts with it before using it. Oh, my mistake. Thank you so much, I was able to get it to work because of that! I also realized I needed some null checks for the areas I was trying to walk to. It's workin right now, but I don't think the code is very optimal because it's quite slow / somewhat glitchy. Any critiques would be greatly appreciated package Nodes; import org.osbot.rs07.api.DoorHandler; import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.map.Position; import org.osbot.rs07.script.Script; import org.osbot.rs07.api.webwalk.dir.WalkToTile; import org.osbot.rs07.input.mouse.MiniMapTileDestination; import Core.Node; import Data.Constants; import Utils.Walking; public class PickRoom extends Node { Walking walk = new Walking(this.sA); Constants c = new Constants(); public PickRoom(Script sA) { super(sA); } public String status() { return "Choosing Fight Room"; } public boolean shouldBank() { return ( (this.sA.inventory.isFull() && this.sA.inventory.getAmount(Constants.FOOD) < 6) || ( !this.sA.inventory.contains(Constants.FOOD) ) ); } public boolean validate() throws InterruptedException { return ( Constants.AK_CHOOSE_AREA.contains(this.sA.myPlayer()) && !shouldBank()); } public void walkSleep() throws InterruptedException { while (this.sA.myPlayer().isMoving()) { Script.sleep(100 + Script.random(125)); } } public Area getHall() { if (Constants.EAST_HALL.contains(this.sA.myPlayer())) { return Constants.EAST_HALL; } else if (Constants.WEST_HALL.contains(this.sA.myPlayer())) { return Constants.WEST_HALL; } else return null; } public Area getFightArea() { if (getHall() == Constants.EAST_HALL) { return Constants.AK_EAST_FIGHT; } else if (getHall() == Constants.WEST_HALL) { return Constants.AK_WEST_FIGHT; } else return null; } public Position[] getFightPos() { if (getHall() == Constants.EAST_HALL) { return Constants.EAST_START2; } else if (getHall() == Constants.WEST_HALL) { return Constants.WEST_START2; } else return null; } public boolean execute() throws InterruptedException { /* * Check which half * check door of half * if open walk through */ //If Player isn't in fight zone if (!Constants.AK_EAST_FIGHT.contains(this.sA.myPlayer()) || !Constants.AK_WEST_FIGHT.contains(this.sA.myPlayer())) { //Null checks if (getHall() != null && getFightArea() != null && getFightPos() != null) { //If obstacle is found if ( this.sA.doorHandler.getNextObstacle(getFightArea().getRandomPosition()) != null ) { //Wait while moving, then open door if (this.sA.doorHandler.handleNextObstacle(getFightArea())) { this.sA.log("Opened door"); Script.sleep(400 + Script.random(400)); walkSleep(); } } //If no obstacle, walk inside else { //this.sA.localWalker.walk(getFightPos()); //this.walk.walkPath(getFightPos()); //^^For some reason these wouldn't walk into the room because // the tile I was trying to walk to was too close to my character this.sA.mouse.click(new MiniMapTileDestination(this.sA.bot, getFightPos()[0]), false); walkSleep(); this.sA.log("Walking into room"); } } } Script.sleep(250 + Script.random(750)); return true; } } Quote Link to comment Share on other sites More sharing options...
Explv Posted January 5, 2016 Share Posted January 5, 2016 (edited) Oh, my mistake. Thank you so much, I was able to get it to work because of that! I also realized I needed some null checks for the areas I was trying to walk to. It's workin right now, but I don't think the code is very optimal because it's quite slow / somewhat glitchy. Any critiques would be greatly appreciated I think you should try and clean up your code a bit. Generally if your code is cleaner, it is easier to spot bugs / optimisations. Here is how you could clean up this class for example. You have two different halls each with the same properties, but different values. So you should probably create an enum to store this information: import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.map.Position; public enum Hall { // TODO: Define these EAST (null, null, null), WEST (null, null, null); final Area HALL_AREA, FIGHT_AREA; final Position[] FIGHT_POS; Hall(final Area HALL_AREA, final Area FIGHT_AREA, final Position[] FIGHT_POS){ this.HALL_AREA = HALL_AREA; this.FIGHT_AREA = FIGHT_AREA; this.FIGHT_POS = FIGHT_POS; } public static Hall getHall(Position playerPosition){ return Hall.EAST.HALL_AREA.contains(playerPosition) ? Hall.EAST : Hall.WEST.HALL_AREA.contains(playerPosition) ? Hall.WEST : null; } public static boolean inFightArea(Position playerPosition){ return EAST.FIGHT_AREA.contains(playerPosition) || WEST.FIGHT_AREA.contains(playerPosition); } public static Area getFightArea(Position playerPosition){ Hall hall = getHall(playerPosition); return hall != null ? hall.FIGHT_AREA : null; } } Seeing as you are sleeping at the end of the execute method, why not just change the return type of execute to an int, and perform the sleep in onLoop. Also I am guessing you have that state() method in every class, so you might as well just put this method into the base Node class: import org.osbot.rs07.script.Script; public abstract class Node { protected final Script S; private final String STATUS; public Node(final Script S, final String STATUS){ this.S = S; this.STATUS = STATUS; } public String status(){ return STATUS; } public abstract boolean validate() throws InterruptedException; public abstract int execute() throws InterruptedException; } Once I cleaned stuff up the code looks like: import org.osbot.rs07.api.map.Area; import org.osbot.rs07.script.Script; import org.osbot.rs07.input.mouse.MiniMapTileDestination; import org.osbot.rs07.utility.ConditionalSleep; public class PickRoom extends Node { public PickRoom(final Script S) { super(S, "Choosing Fight Room"); } public boolean validate() throws InterruptedException { return !Hall.inFightArea(S.myPosition()) && hasFood(); } private boolean hasFood() { return S.getInventory().contains(Constants.FOOD); } public int execute() throws InterruptedException { final Area FIGHT_AREA = Hall.getFightArea(S.myPosition()); if (!canReachFightArea(FIGHT_AREA)) openFightAreaDoor(FIGHT_AREA); else walkInsideFightArea(); return (250 + Script.random(750)); } private boolean canReachFightArea(final Area FIGHT_AREA){ return S.getMap().canReach(FIGHT_AREA.getRandomPosition()); } private void openFightAreaDoor(final Area FIGHT_AREA){ if(S.getDoorHandler().handleNextObstacle(FIGHT_AREA)){ new ConditionalSleep(5_000) { @Override public boolean condition() throws InterruptedException { return S.getMap().canReach(FIGHT_AREA.getRandomPosition()); } }.sleep(); } } /** * * S.getLocalWalker().walk(getFightPos()); * S.walk.walkPath(getFightPos()); * For some reason these wouldn't walk into the room because * the tile I was trying to walk to was too close to my character */ private void walkInsideFightArea(){ Hall hall = Hall.getHall(S.myPosition()); if(hall != null) { S.getMouse().click(new MiniMapTileDestination(S.getBot(), hall.FIGHT_POS[0]), false); new ConditionalSleep(5000) { @Override public boolean condition() throws InterruptedException { return Hall.inFightArea(S.myPosition()); } }.sleep(); } } } Edited January 5, 2016 by Explv Quote Link to comment Share on other sites More sharing options...
ikk Posted January 5, 2016 Author Share Posted January 5, 2016 I think you should try and clean up your code a bit. Generally if your code is cleaner, it is easier to spot bugs / optimisations. Here is how you could clean up this class for example. You have two different halls each with the same properties, but different values. So you should probably create an enum to store this information: import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.map.Position; public enum Hall { // TODO: Define these EAST (null, null, null), WEST (null, null, null); final Area HALL_AREA, FIGHT_AREA; final Position[] FIGHT_POS; Hall(final Area HALL_AREA, final Area FIGHT_AREA, final Position[] FIGHT_POS){ this.HALL_AREA = HALL_AREA; this.FIGHT_AREA = FIGHT_AREA; this.FIGHT_POS = FIGHT_POS; } public static Hall getHall(Position playerPosition){ return Hall.EAST.HALL_AREA.contains(playerPosition) ? Hall.EAST : Hall.WEST.HALL_AREA.contains(playerPosition) ? Hall.WEST : null; } public static boolean inFightArea(Position playerPosition){ return EAST.FIGHT_AREA.contains(playerPosition) || WEST.FIGHT_AREA.contains(playerPosition); } public static Area getFightArea(Position playerPosition){ Hall hall = getHall(playerPosition); return hall != null ? hall.FIGHT_AREA : null; } } Seeing as you are sleeping at the end of the execute method, why not just change the return type of execute to an int, and perform the sleep in onLoop. Also I am guessing you have that state() method in every class, so you might as well just put this method into the base Node class: import org.osbot.rs07.script.Script; public abstract class Node { protected final Script S; private final String STATUS; public Node(final Script S, final String STATUS){ this.S = S; this.STATUS = STATUS; } public String status(){ return STATUS; } public abstract boolean validate() throws InterruptedException; public abstract int execute() throws InterruptedException; } Once I cleaned stuff up the code looks like: import org.osbot.rs07.api.map.Area; import org.osbot.rs07.script.Script; import org.osbot.rs07.input.mouse.MiniMapTileDestination; import org.osbot.rs07.utility.ConditionalSleep; public class PickRoom extends Node { public PickRoom(final Script S) { super(S, "Choosing Fight Room"); } public boolean validate() throws InterruptedException { return !Hall.inFightArea(S.myPosition()) && hasFood(); } private boolean hasFood() { return S.getInventory().contains(Constants.FOOD); } public int execute() throws InterruptedException { final Area FIGHT_AREA = Hall.getFightArea(S.myPosition()); if (!canReachFightArea(FIGHT_AREA)) openFightAreaDoor(FIGHT_AREA); else walkInsideFightArea(); return (250 + Script.random(750)); } private boolean canReachFightArea(final Area FIGHT_AREA){ return S.getMap().canReach(FIGHT_AREA.getRandomPosition()); } private void openFightAreaDoor(final Area FIGHT_AREA){ if(S.getDoorHandler().handleNextObstacle(FIGHT_AREA)){ new ConditionalSleep(5_000) { @Override public boolean condition() throws InterruptedException { return S.getMap().canReach(FIGHT_AREA.getRandomPosition()); } }.sleep(); } } /** * * S.getLocalWalker().walk(getFightPos()); * S.walk.walkPath(getFightPos()); * For some reason these wouldn't walk into the room because * the tile I was trying to walk to was too close to my character */ private void walkInsideFightArea(){ Hall hall = Hall.getHall(S.myPosition()); if(hall != null) { S.getMouse().click(new MiniMapTileDestination(S.getBot(), hall.FIGHT_POS[0]), false); new ConditionalSleep(5000) { @Override public boolean condition() throws InterruptedException { return Hall.inFightArea(S.myPosition()); } }.sleep(); } } } Oh man, thank you so much for the critique. This was all so helpful, I've been trying to look at snippets and decompile .jars to see what good code is supposed to look like to speed up my learning process. The simplicity of the code you just wrote makes so much more sense than the way I had been doing it! I just spent the past hour or so rewriting the script to fit the style you demonstrated. Because of your help, my script is running soo much smoother and I'm getting more combat xp/h too! I really appreciate the help, can't wait to release my first script once all the last remaining bugs are fixed. I'll give you credits for helping me out Quote Link to comment Share on other sites More sharing options...
Explv Posted January 5, 2016 Share Posted January 5, 2016 Oh man, thank you so much for the critique. This was all so helpful, I've been trying to look at snippets and decompile .jars to see what good code is supposed to look like to speed up my learning process. The simplicity of the code you just wrote makes so much more sense than the way I had been doing it! I just spent the past hour or so rewriting the script to fit the style you demonstrated. Because of your help, my script is running soo much smoother and I'm getting more combat xp/h too! I really appreciate the help, can't wait to release my first script once all the last remaining bugs are fixed. I'll give you credits for helping me out No problem Quote Link to comment Share on other sites More sharing options...