737 Posted March 30 Share Posted March 30 (edited) 737 Cook's Assistant Description Does the Cook's assistant quest then stops. Can be started at any point. No inventory or bank required. Screens shots: Script: Spoiler import org.osbot.rs07.api.map.Area; import org.osbot.rs07.api.map.Position; 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.Message; import org.osbot.rs07.api.ui.Tab; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; import org.osbot.rs07.utility.ConditionalSleep; import java.awt.*; @ScriptManifest( author = "737", info = "Does the Cook's Assistant Quest", logo = "", name = "737 Cook's Assistant", version = 1 ) public class CooksAssistant extends Script { private final Area AREA_LUMBRIDGE_KITCHEN = new Area(3208, 3212, 3210, 3213); private final Area AREA_FIND_EGG = new Area(3228, 3296, 3231, 3300); private final Area AREA_FIND_BUCKET = new Area(3226, 3290, 3229, 3291); private final Area AREA_FIND_COW = new Area(3253, 3275, 3256, 3277); private final Area AREA_WHEAT_FIELD = new Area(3160, 3294, 3162, 3297); private final Area AREA_FLOUR_BIN = new Area(3166, 3305, 3167, 3305); private final Position POSITION_HOPPER = new Position(3166, 3308, 2); private final String ITEM_BUCKET = "Bucket"; private final String ITEM_BUCKET_MILK = "Bucket of milk"; private final String ITEM_POT = "Pot"; private final String ITEM_POT_FLOUR = "Pot of flour"; private final String ITEM_EGG = "Egg"; private final String ITEM_WHEAT = "Grain"; private final String ACTION_TAKE = "Take"; private final String ACTION_MILK = "Milk"; private final String ACTION_PICK = "Pick"; private final String ACTION_FILL = "Fill"; private final String ACTION_OPERATE = "Operate"; private final String ACTION_EMPTY = "Empty"; private final String ACTION_TALK = "Talk-to"; private final String OBJECT_COW = "Dairy Cow"; private final String OBJECT_WHEAT = "Wheat"; private final String OBJECT_HOPPER = "Hopper"; private final String OBJECT_HOPPER_CONTROLS = "Hopper Controls"; private final String OBJECT_FLOUR_BIN = "Flour Bin"; private final String NPC_COOK = "Cook"; private final String MESSAGE_GAME_HOPPER_FILLED = "You put the grain in the hopper"; private final String MESSAGE_GAME_HOPPER_FILLED2 = "There is already grain in the hopper"; private final String MESSAGE_GAME_HOPPER_OPERATE = "The grain slides down"; private final String MESSAGE_GAME_HOPPER_EMPTIED = "You fill a pot with the last of the flour"; private final int CONFIG_QUEST = 29; private final String[] DIALOGUE_OPTIONS_START_QUEST = { "What's wrong?", "Yes.", "I'm always happy to help a cook in distress.", "Actually, I know where to find this stuff." }; private final String WIDGET_START_QUEST = "Start the Cook\'s Assistant quest?"; private int baseSleepMs = 75; private String status = "loading..."; private boolean hopperFilled = false; private boolean wheatProcessed = false; private long startTime; private boolean handInStarted = false; @Override public void onStart() { startTime = System.currentTimeMillis(); baseSleepMs = random(50, 75); } @Override public int onLoop() throws InterruptedException { if (!getTabs().getOpen().equals(Tab.INVENTORY)) { getTabs().open(Tab.INVENTORY); } if (configs.get(CONFIG_QUEST) == 0) //quest not started { status = "Starting Quest"; startQuest(); } else if (configs.get(CONFIG_QUEST) == 2) { logger.info("Quest Complete. Stopping."); stop(); } else if (handInStarted || (getInventory().contains(ITEM_BUCKET_MILK)) && getInventory().contains(ITEM_BUCKET_MILK) && getInventory().contains(ITEM_BUCKET_MILK)) { status = "Handing in"; handInStarted = true; completeQuest(); } else if (!getInventory().contains(ITEM_POT_FLOUR)) { status = "Obtaining a pot of flour"; getPotOfFlour(); } else if (!getInventory().contains(ITEM_EGG)) { status = "Obtaining an Egg"; fetchGroundItem(ITEM_EGG, AREA_FIND_EGG); } else if (!getInventory().contains(ITEM_BUCKET_MILK)) { status = "Obtaining a Bucket of Milk"; getBucketOfMilk(); } rSleep(); return 0; } @Override public void onMessage(Message message) { if (message.getType() == Message.MessageType.GAME || message.getType() == Message.MessageType.FILTERED) { if (message.getMessage().contains(MESSAGE_GAME_HOPPER_FILLED) || message.getMessage().contains(MESSAGE_GAME_HOPPER_FILLED2)) { logger.info("Hopper was filled."); hopperFilled = true; return; } if (message.getMessage().contains(MESSAGE_GAME_HOPPER_OPERATE)) { logger.info("Wheat was processed."); hopperFilled = false; wheatProcessed = true; return; } if (message.getMessage().contains(MESSAGE_GAME_HOPPER_EMPTIED)) { wheatProcessed = false; return; } } } @Override public void onPaint(Graphics2D g) { Color color = new Color(0, 255, 0, 150); g.setColor(color); g.fillRect(5, 20, 510, 100); g.setColor(Color.red); Font fontTitle = new Font("Consolas", Font.BOLD, 16); Font font = new Font("Consolas", Font.PLAIN, 16); g.setFont(fontTitle); g.drawString("737 Cook's Assistant v1.0", 20, 40); g.setFont(font); g.drawString("Status: " + status, 20, 60); g.drawString("Time Elapsed: " + formatTime(System.currentTimeMillis() - startTime), 20, 80); Point mP = getMouse().getPosition(); g.drawLine(mP.x - 5, mP.y + 5, mP.x + 5, mP.y - 5); g.drawLine(mP.x + 5, mP.y + 5, mP.x - 5, mP.y - 5); } public void startQuest() throws InterruptedException { if (!dialogues.inDialogue()) { talkToNPC(NPC_COOK, AREA_LUMBRIDGE_KITCHEN); return; } handleDialogue(DIALOGUE_OPTIONS_START_QUEST); } public void completeQuest() throws InterruptedException { if (!dialogues.inDialogue()) { talkToNPC(NPC_COOK, AREA_LUMBRIDGE_KITCHEN); return; } handleDialogue(null); //no dialogue options for hand in } public void handleDialogue(String[] dialogueOptions) throws InterruptedException { //to make this method generic we need to modify the quest confirmation check boolean questConfirmationDialogueAvailable = !getWidgets().containingText(WIDGET_START_QUEST).isEmpty(); if (questConfirmationDialogueAvailable) { getKeyboard().typeString("1"); return; } if (dialogues.isPendingContinuation()) { dialogues.clickContinue(); sleep(random(1000, 3000)); return; } for (String dialogue : dialogueOptions) { if (dialogueExists(dialogue)) { dialogues.selectOption(dialogue); sleep(random(1000, 3000)); return; } } //if we get lost in the dialogue somehow getWalking().walk(new Position(myPosition().getX() + 1, myPosition().getY(), myPosition().getZ())); } public boolean dialogueExists(String dialogueText) { return getWidgets().containingText(dialogueText) != null; } public void talkToNPC(String npcName, Area npcArea) throws InterruptedException { if (!npcArea.contains(myPosition())) { getWalking().webWalk(npcArea); return; } NPC npc = getNpcs().closest(npcName); if (npc != null && npc.isVisible()) { if(npc.isVisible()){ npc.interact(ACTION_TALK); new ConditionalSleep(10000) { @Override public boolean condition() throws InterruptedException { return dialogues.inDialogue(); } }.sleep(); } else { getCamera().toEntity(npc); } } } public void getPotOfFlour() throws InterruptedException { if (!getInventory().contains(ITEM_POT)) { fetchGroundItem(ITEM_POT, AREA_LUMBRIDGE_KITCHEN); return; } if (!getInventory().contains(ITEM_WHEAT) && !hopperFilled && !wheatProcessed) { interactObject(OBJECT_WHEAT, ACTION_PICK, AREA_WHEAT_FIELD, new ConditionalSleep(10000) { @Override public boolean condition() throws InterruptedException { return getInventory().contains(ITEM_WHEAT); } }); return; } if (getInventory().contains(ITEM_WHEAT)) { interactObject(OBJECT_HOPPER, ACTION_FILL, POSITION_HOPPER, new ConditionalSleep(10000) { @Override public boolean condition() throws InterruptedException { return hopperFilled; } }); return; } if (hopperFilled) { interactObject(OBJECT_HOPPER_CONTROLS, ACTION_OPERATE, POSITION_HOPPER, new ConditionalSleep(10000) { @Override public boolean condition() throws InterruptedException { return wheatProcessed; } }); return; } if (wheatProcessed) { interactObject(OBJECT_FLOUR_BIN, ACTION_EMPTY, AREA_FLOUR_BIN, new ConditionalSleep(10000) { @Override public boolean condition() throws InterruptedException { return getInventory().contains(ITEM_POT_FLOUR); } }); return; } } public void getBucketOfMilk() throws InterruptedException { if (!getInventory().contains(ITEM_BUCKET)) { fetchGroundItem(ITEM_BUCKET, AREA_FIND_BUCKET); return; } interactObject(OBJECT_COW, ACTION_MILK, AREA_FIND_COW, new ConditionalSleep(10000) { @Override public boolean condition() throws InterruptedException { return (getInventory().contains(ITEM_BUCKET_MILK)); } }); } public void interactObject(String objectName, String objectAction, Area objectArea, ConditionalSleep sleep) throws InterruptedException { interactObject(objectName, objectAction, objectArea.getRandomPosition(), sleep); } public void interactObject(String objectName, String objectAction, Position position, ConditionalSleep sleep) throws InterruptedException { if (myPosition().distance(position) > 3 || myPosition().getZ() != position.getZ()) { getWalking().webWalk(position); return; } RS2Object object = getObjects().closest(objectName); if (object != null) { if (object.isVisible()) { object.interact(objectAction); sleep.sleep(); } else { getCamera().toEntity(object); } return; } } public void fetchGroundItem(String itemName, Area area) throws InterruptedException { if (!area.contains(myPosition())) { getWalking().webWalk(area); return; } GroundItem groundItem = getGroundItems().closest(itemName); if (groundItem != null) { if (groundItem.isVisible()) { groundItem.interact(ACTION_TAKE); new ConditionalSleep(10000) { @Override public boolean condition() throws InterruptedException { return (getInventory().contains(itemName)); } }.sleep(); return; } else { getCamera().toEntity(groundItem); } } } public void rSleep() throws InterruptedException { sleep(baseSleepMs + random(0, 25)); } public final String formatTime(final long ms) { long s = ms / 1000, m = s / 60, h = m / 60; s %= 60; m %= 60; h %= 24; return String.format("%02d:%02d:%02d", h, m, s); } } This is my first script. I made it for fun. Potentially I will continue writing scripts. Maybe more quests, maybe something else. I would appreciate any feedback. I come from a .NET background so my Java is so-so. Also if there are any OSbot best practices I'm not following please let me know. Thanks Edited June 2 by 737 update script 1 Quote Link to comment Share on other sites More sharing options...
TheCongregation Posted April 2 Share Posted April 2 That's really cool, I like how you've adapted it so that it's self sufficient for the quest. If you wanna collab i'd be happy to help make more quests with you perhaps something challenging like The Knight's Sword. Quote Link to comment Share on other sites More sharing options...
737 Posted June 2 Author Share Posted June 2 On 4/2/2024 at 10:52 AM, TheCongregation said: That's really cool, I like how you've adapted it so that it's self sufficient for the quest. If you wanna collab i'd be happy to help make more quests with you perhaps something challenging like The Knight's Sword. I've updated this on the forum. I may have interest in collaborating on projects in the future but am currently taking a break. Burnt out at my job. Brain is tired. Quote Link to comment Share on other sites More sharing options...
TheCongregation Posted June 2 Share Posted June 2 2 hours ago, 737 said: I've updated this on the forum. I may have interest in collaborating on projects in the future but am currently taking a break. Burnt out at my job. Brain is tired. no brains needed we got brains and brawn already Quote Link to comment Share on other sites More sharing options...