justanotherkid Posted May 16, 2016 Share Posted May 16, 2016 (edited) Because this script was my first script and it is not flexible I will release it for opensource because I believe the readability will be very valuable to beginning scripters. i'm much much better now and this script is cancer, I only spent like 5minutes adding comments and i hope some people can learn whatever from this gl import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.util.Arrays; import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.map.Position; import org.osbot.rs07.api.model.Entity; import org.osbot.rs07.api.model.GroundItem; import org.osbot.rs07.api.model.NPC; import org.osbot.rs07.api.model.RS2Object; import org.osbot.rs07.api.ui.EquipmentSlot; import org.osbot.rs07.api.ui.Skill; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; import org.osbot.rs07.utility.ConditionalSleep; @ScriptManifest(author = "justanotherkid", info = "", name = "Unicows", version = 1.0, logo = "") public class main extends Script { Area area = new Area( new Position(3010,4412,0), new Position(3042,4373,0)); Area bankarea = new Area( new Position(2443,3082,0), new Position(2438,3096,0)); Area kandarinarea = new Area( new Position(2611,3219,0), new Position(2601,3228,0)); Position[] toarea1 = new Position[] { new Position(2606,3222,0), new Position(2616,3222,0), new Position(2628,3222,0), new Position(2636,3223,0), new Position(2649,3225,0),}; String state; Area position = new Area( new Position(3017,4409,0), new Position(3021,4408,0)); Position ladder = new Position (2648,3213,0); GroundItem horn; NPC unicow; long startTime; long count1; long totalcount; Entity door; RS2Object towerdoor; Entity bank; Entity trapdoor; @Override public void onStart() { startTime = System.currentTimeMillis(); // start a timer in ms for(Skill skill : new Skill[]{Skill.HITPOINTS, Skill.ATTACK, Skill.STRENGTH, Skill.DEFENCE}) { getExperienceTracker().start(skill); } // start exp trackers, you can add more skill trackers by just adding onto the list } private enum State { SUMMON,IDLE,LOOT,FIGHT,TRAVEL2BANK,BANK,TRAVEL2AREA,DROP,WORLDHOP // enum of states } private State getState() // below are conditions to required to execute each state, i believe the conditions are straight forward so i will not explain them { if(area.contains(myPlayer()) && getPlayers().getAll().size() > 1 && !myPlayer().isUnderAttack()) { return State.WORLDHOP; } if(horn != null && area.contains(myPlayer()) && !myPlayer().isUnderAttack() && getInventory().getAmount("Unicorn horn") < 28) { unicow = npcs.closest("Unicow"); return State.LOOT; } if(area.contains(myPlayer()) && getInventory().contains("Cowhide") && getInventory().contains("Unicorn horn") && unicow == null) { unicow = npcs.closest("Unicow"); return State.SUMMON; } if(getInventory().contains("Green satchel") || getInventory().contains("Tea flask") || getInventory().contains("Bones")) { return State.DROP; } if(!getInventory().contains("Cowhide") && bankarea.contains(myPlayer())) { return State.BANK; } if(!getInventory().contains("Cowhide") && !bankarea.contains(myPlayer())) { unicow = npcs.closest("Unicow"); return State.TRAVEL2BANK; } if(unicow != null && area.contains(myPlayer()) || myPlayer().isUnderAttack()) { unicow = npcs.closest("Unicow"); return State.FIGHT; } if(getInventory().contains("Unicorn horn") && getInventory().contains("Unicorn horn") && !area.contains(myPlayer())) { return State.TRAVEL2AREA; } return State.IDLE; } @Override public int onLoop() throws InterruptedException // the 2 lines below here are always on loop regardless of what state is executed { unicow = npcs.closest("Unicow"); // constantly refreshing unicow to mean the closest unicow; if no unicow exists then it will return null horn = getGroundItems().closest("Unicorn horn"); // same as the unicow line switch(getState()) // under here is the part where we define what each state does { case WORLDHOP: state = "WORLDHOPPING"; // this changes the string state to display a different word, this is helpful to debug where exactly a script error is occuring getWorlds().hopToP2PWorld(); //hop to a random p2p world break; // always add a break; after each case case DROP: state = "DROPPING"; getInventory().dropAllExcept("Cowhide","Unicorn horn"); // drop all except these items break; case TRAVEL2AREA: state = "TRAVELING"; getEquipment().interact(EquipmentSlot.CAPE, "Kandarin Monastery"); // interact with this cape sleep(random(2300,2800)); //sleep for the loading screen (you can use a conditional sleep) if(!kandarinarea.contains(myPlayer())) { door = objects.closest("Door"); if(door.hasAction("Open")) // it will only open a door if it has the action "Open" so if the door is already open it will not execute this { door.interact("Open"); sleep(random(800,1400)); getWalking().walkPath(Arrays.asList(toarea1)); //this walks a predefined path, most people prefer using the webwalker RS2Object towerdoor = getObjects().closest("Tower door"); // defining a new RS2Object, this is bad practice, make sure you define your variable globally way up in the script to prevent junk buildup (everytime it executes this line it makes a new variable) if(towerdoor.hasAction("Open")) { towerdoor.interact("Open"); sleep(random(800,1000)); } } else { getWalking().walkPath(Arrays.asList(toarea1)); towerdoor = getObjects().closest("Tower door"); if(towerdoor.hasAction("Open")) { towerdoor.interact("Open"); sleep(random(800,1000)); } } } getWalking().webWalk(new Position[] {ladder}); // webwalking to a certain position called ladder which was globally defined above trapdoor = objects.closest("Trapdoor"); if(trapdoor.hasAction("Open")) // if the trapdoor is closed then execute the first portion, else just execute the second portion (aka else statement) { trapdoor.interact("Open"); sleep(random(600,1000)); trapdoor.interact("Climb-down"); } else { trapdoor.interact("Climb-down"); } sleep(random(1600,2000)); getWalking().webWalk(position); while(myPlayer().isMoving()){ // this is really bad practice, use a WalkingEvent, never use a while loop like this sleep(300); } break; case BANK: state = "BANKING"; count1 = getInventory().getAmount("Unicorn horn"); // the amount of unicorn horns in the inventory bank = objects.closest("Bank chest"); if(bank != null) { bank.interact("Use"); sleep(400); while(myPlayer().isMoving()) { sleep(300); } } // this is bad practice, what should have been done is if(bank is open) { execute banking portion } else { execute getting to bank and opening portion } if(getBank().isOpen()) { if(!getEquipment().isWearingItemThatContains(EquipmentSlot.RING, "Ring of dueling")) { getBank().depositAll(); totalcount += count1; // add the amount of unicorn horns banked to the total amount banked getBank().withdraw("Cowhide", 16); sleep(random(100,200)); getBank().withdraw("Unicorn horn", 1); sleep(random(100,200)); getBank().withdraw("Ring of dueling(8)", 1); getBank().close(); sleep(random(100,200)); getEquipment().equip(EquipmentSlot.RING, "Ring of dueling(8)"); } else { getBank().depositAll(); totalcount += count1; sleep(random(100,200)); getBank().withdraw("Cowhide", 14); sleep(random(100,200)); getBank().withdraw("Unicorn horn", 1); sleep(random(100,200)); getBank().close(); } if(getSkills().getDynamic(Skill.HITPOINTS) < 40) // if HP is below 40 { bank.interact("Use"); sleep(600); getBank().withdraw("Salmon", 4); getBank().close(); sleep(300); while(getInventory().contains("Salmon")) // while inventory contains salmon, eat them { getInventory().interact("Eat","Salmon"); sleep(600); } } } break; case TRAVEL2BANK: state = "TRAVELING"; if(!bankarea.contains(myPlayer())) { getEquipment().interact(EquipmentSlot.RING, "Castle Wars"); new ConditionalSleep(3000) // this is the conditional sleep snippet that should have been used more often, make sure you save this snippet { // the number 3000 in the line above is the timeout number (the conditional sleep will end in that time) @Override public boolean condition() throws InterruptedException { return bankarea.contains(myPlayer()); // the condition that needs to be met to end the conditional sleep earlier } }.sleep(); } break; case IDLE: break; case SUMMON: state = "SUMMONING"; if(!position.contains(myPlayer())) { getWalking().webWalk(position); // if you choose to use a webwalker this way you should always add a sleep after the getWalking() to prevent spam clicking } Entity fountain = getObjects().closest("Symbol of Life"); // needs to be defined globally to prevent junk buildup if(fountain != null) { getInventory().interact("Use", "Unicorn horn");; fountain.interact(); sleep(1250); getInventory().interact("Use", "Cowhide"); fountain.interact(); sleep(500); fountain.interact("Activate"); sleep(400); if(getDialogues().inDialogue()) { getDialogues().completeDialogue("Click here to continue"); } } sleep(1000); break; case FIGHT: state = "FIGHTING"; if (unicow != null && unicow.exists() && unicow.isAttackable()) { getInventory().deselectItem(); // failsafe since occasionally an item will be selected from the SUMMON state that will prevent combat unicow.interact("Attack"); sleep(random(400)); while(myPlayer().isUnderAttack()) // this should be a conditional sleep that returns true if the player is under attack { sleep(random(300)); } } sleep(500); break; case LOOT: state = "LOOTING"; if(horn != null) { if(getInventory().isFull() && getInventory().contains("Cowhide")) { getInventory().drop("Cowhide"); horn.interact("Take"); } else { horn.interact("Take"); } } break; } return random(200) + 200; } @Override public void onExit() { //place things that you want to happen during the exiting of the script; you can add the client to type the amount of unicow horns collected in the log } @Override public void onPaint(Graphics2D g) { long ss = (System.currentTimeMillis() - startTime) / 1000; // long ss, long mm, and long hh are used to format the timer we started way above long mm = ss / 60; long hh = mm / 60; long gainedexp = getExperienceTracker().getGainedXP(Skill.HITPOINTS) + getExperienceTracker().getGainedXP(Skill.ATTACK) + getExperienceTracker().getGainedXP(Skill.STRENGTH) + getExperienceTracker().getGainedXP(Skill.DEFENCE); // adding all the exp gained so far long gainedexphr = getExperienceTracker().getGainedXPPerHour(Skill.HITPOINTS) + getExperienceTracker().getGainedXPPerHour(Skill.ATTACK) + getExperienceTracker().getGainedXPPerHour(Skill.STRENGTH) + getExperienceTracker().getGainedXPPerHour(Skill.DEFENCE); // adding the exp/hr calculations Font font = new Font("Sans-Serif", Font.BOLD, 14); //defining a font of Sans-Serif that is bold and size 14 g.setColor(Color.WHITE); // setting the font color g.setFont(font); // setting the font equal to what was defined 2 lines above g.drawString("Status: " + state, 8, 303); // drawing these strings for this line and those below g.drawString("Exp : " + gainedexp + " (" + gainedexphr + ")", 8, 318); g.drawString("Run time: " + hh + ":" + mm%60 + ":" + ss%60 , 8, 333); g.drawString("Amount Banked: " + totalcount, 230, 333); } } Edited May 16, 2016 by justanotherkid 1 Quote Link to comment Share on other sites More sharing options...
Chris Posted May 16, 2016 Share Posted May 16, 2016 nice Try looking into ConditionalSleeps Quote Link to comment Share on other sites More sharing options...
Aiban Posted May 16, 2016 Share Posted May 16, 2016 Thanks for this will be learning from this Quote Link to comment Share on other sites More sharing options...
Pure_ Posted May 26, 2016 Share Posted May 26, 2016 You should probably avoid static time quantities in sleep. A lot of this logic should have probably been split into some kind of task-based architecture. The paint calculations should also be in another method. This is a fine first attempt but you should keep working to improve. Quote Link to comment Share on other sites More sharing options...