justanotherkid Posted May 16, 2016 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
Pure_ Posted May 26, 2016 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.