The client is offline due to RuneScape update. You may see instance errors but this is due to the update and not actual instance errors. This should be resolved soon. Join our Discord for more information.

ACatherbyCooker



  • This script simply cooks Shrimps and/or Anchovies at Catherby for fast cooking xp starting from lvl 1. When no fish left, it stops.

    A practical example would be to fish and bank shrimps & anchovies at Draynor from lvl 1-30 fishing (lvl req. to catch Salmons).
    Then with all the shrimps and anchovies you'll have stored just go to Catherby's bank and start this script to let it cook them all. You'd be like 30 fishing and 30 cooking.

    Another practical thing you could do is to edit the fish names and cook whatever you want.

    WARNING: the custom random events handler checks for the presence of lamp and will level-up prayer so if you don't want that, comment out the checkLamp() method to bypass it.

    So here is the code:

    import org.rspeer.runetek.adapter.component.InterfaceComponent;
    import org.rspeer.runetek.adapter.component.Item;
    import org.rspeer.runetek.adapter.scene.Npc;
    import org.rspeer.runetek.adapter.scene.Player;
    import org.rspeer.runetek.adapter.scene.SceneObject;
    import org.rspeer.runetek.api.commons.StopWatch;
    import org.rspeer.runetek.api.commons.Time;
    import org.rspeer.runetek.api.commons.math.Random;
    import org.rspeer.runetek.api.component.Bank;
    import org.rspeer.runetek.api.component.Dialog;
    import org.rspeer.runetek.api.component.Interfaces;
    import org.rspeer.runetek.api.component.Production;
    import org.rspeer.runetek.api.component.tab.Inventory;
    import org.rspeer.runetek.api.component.tab.Skill;
    import org.rspeer.runetek.api.component.tab.Skills;
    import org.rspeer.runetek.api.movement.Movement;
    import org.rspeer.runetek.api.movement.position.Area;
    import org.rspeer.runetek.api.movement.position.Position;
    import org.rspeer.runetek.api.scene.Npcs;
    import org.rspeer.runetek.api.scene.Players;
    import org.rspeer.runetek.api.scene.SceneObjects;
    import org.rspeer.runetek.event.listeners.RenderListener;
    import org.rspeer.runetek.event.types.RenderEvent;
    import org.rspeer.script.Script;
    import org.rspeer.script.ScriptCategory;
    import org.rspeer.script.ScriptMeta;
    import org.rspeer.ui.Log;
    
    import java.awt.*;
    import java.util.Arrays;
    
    @ScriptMeta(version = 0.01, name = "ACatherbyCooker", desc = "Cooks shrimps & anchovies in Catherby", developer = "1234567Alex", category = ScriptCategory.COOKING)
    public final class ACatherbyCooker extends Script implements RenderListener {
    
        //Timers
        private static StopWatch stopWatch = StopWatch.start();
        private static long secondsPlayed = 0;
        private static final int MAX_RUNTIME = (Random.nextInt(80, 200) * 60); //minutes * 60 to convert in usable seconds
        private static long timeOfLastAnimation = 0;
        private static final int PLAYER_MIN_REACTION_TIME = 250;
    
        //Resources
        private static final String COOKING_TOOL_NAME = "Range";
        private static final String COOKING_TOOL_ACTION = "Cook";
        private static final String[] RAW_FISH_NAMES = {
                "Raw shrimps",
                "Raw anchovies"
        };
        private static final String[] COOKED_FISH_NAMES = {
                "Shrimps",
                "Anchovies"
        };
    
        //Areas
        private static final Area COOKING_AREA = Area.rectangular(2815, 3443, 2817, 3439);
        private static final Position CATHERBY_BANKBOOTH_POS = new Position(2809, 3442);
    
        //Status
        private static String status = "Initial";
        private static int actionsCounter = 0;
    
        //Skill
        private static final Skill TRAINING_SKILL = Skill.COOKING;
        private static final int COOKING_INIT_XP = Skills.getExperience(TRAINING_SKILL);
    
    
        @Override
        public void onStart() {
            Log.info("Started " + getMeta().name() + " script.");
    
        }
    
        @Override
        public int loop() {
    
            //Custom random events handling
            handleRandoms();
    
            //Main tasks
            checkRunToggle();
            if (needBanking()) {
                doBanking();
            } else if (needCooking()) {
                doCooking();
            }
    
            //Script Timeout check
            if (secondsPlayed > MAX_RUNTIME) {
                Log.severe("Max runtime reached - stopping...");
                setStopping(true);
            }
    
            return Random.low(200, 400);
        }
    
        private boolean needBanking() {
            return !Inventory.contains(RAW_FISH_NAMES);
        }
    
        private void doBanking() {
            if (!Players.getLocal().isMoving()) {
                if (!Bank.isOpen()) {
                    Log.info("Need to bank...");
                    randomAFK();
                    if (checkDialog())
                        reactionTimeInterval();
                    openBankBooth(CATHERBY_BANKBOOTH_POS);
                }
                if (Bank.isOpen()) {
                    status = "Bank is open";
                    Log.info("Bank is open, banking...");
                    if (!Inventory.isEmpty()) {
                        actionsCounter += Inventory.getCount(COOKED_FISH_NAMES);
                        reactionTimeInterval();
                        Bank.depositInventory();
                        Time.sleepUntil(Inventory::isEmpty, Random.nextInt(1000, 1500));
                    }
                    if (Bank.contains(RAW_FISH_NAMES)) {
                        if (Bank.contains(RAW_FISH_NAMES[0])) {
                            reactionTimeInterval();
                            Bank.withdrawAll(RAW_FISH_NAMES[0]);
                            Time.sleepUntil(() -> Inventory.contains(RAW_FISH_NAMES[0]), 2000);
                            reactionTimeInterval();
                        }
                        if (!Inventory.isFull() && Bank.contains(RAW_FISH_NAMES[1])) {
                            reactionTimeInterval();
                            Bank.withdrawAll(RAW_FISH_NAMES[1]);
                            Time.sleepUntil(() -> Inventory.contains(RAW_FISH_NAMES[1]), 2000);
                        }
                    } else {
                        Log.severe("No " + Arrays.toString(RAW_FISH_NAMES) + " found in Bank & Inventory, stopping script...");
                        setStopping(true);
                    }
                }
                reactionTimeInterval();
            }
        }
    
        private void openBankBooth(Position bankBoothPos) {
            SceneObject bankBooth = SceneObjects.newQuery().names("Bank booth").on(bankBoothPos).results().first();
            if (bankBooth != null && bankBooth.interact("Bank")) {
                Log.info("Interacted bank booth, waiting bank to be opened");
                status = "To booth";
                Time.sleepUntil(Bank::isOpen, Random.low(7000, 10000));
            }
        }
    
        private boolean needCooking() {
            Player local = Players.getLocal();
            if (local.isAnimating()) {
                timeOfLastAnimation = System.currentTimeMillis();
                return false;
            }
            return Inventory.contains(RAW_FISH_NAMES)
                    && System.currentTimeMillis() > timeOfLastAnimation + Random.low(500, 900)
                    || Dialog.canContinue();
        }
    
        private void doCooking() {
            status = "Need to cook";
            SceneObject cookingRange = SceneObjects.newQuery().names(COOKING_TOOL_NAME).results().nearest();
            if (cookingRange != null) {
                if (!Bank.isOpen()) {
                    randomAFK();
                    checkDialog();
                } else {
                    Bank.close();
                    reactionTimeInterval();
                }
                cookingRange.interact(COOKING_TOOL_ACTION);
                status = "Trying to cook";
                Time.sleepUntil(Production::isOpen, 15000);
                if (Production.isOpen()) {
                    reactionTimeInterval();
                    Production.initiate();
                    Time.sleepUntil(() -> !needCooking(), 25000);
                }
                if (!needCooking()) {
                    status = "Cooking";
                    Log.fine("Now cooking...");
                }
            } else {
                Movement.walkToRandomized(COOKING_AREA.getCenter());
                Log.info("Walking to cooking area");
                Time.sleep(3000, 6000);
            }
        }
    
    
        private void reactionTimeInterval() {
            Time.sleep(Random.low(PLAYER_MIN_REACTION_TIME, 1000));
        }
    
        private void randomAFK() {
            int afkTime = (Random.low(PLAYER_MIN_REACTION_TIME, Random.low(500, 15000)));
            status = "Random AFK";
            Log.info("Random AFK time: " + afkTime);
            Time.sleep(afkTime);
        }
    
        private boolean checkDialog() {
            if (Dialog.canContinue()) {
                Time.sleep(250, 600);
                Dialog.processContinue();
                Log.info("Closed a dialog message.");
                Time.sleep(250, 600);
                return true;
            }
            return false;
        }
    
        private void checkRunToggle() {
            if (!Movement.isRunEnabled() && Movement.getRunEnergy() > Random.nextInt(20, 35)) { //make sure run is always on
                Movement.toggleRun(true);
                Log.info("Toggled running mode back on.");
                Time.sleep(350, 1200);
            }
        }
    
        /**
         * Handle random event by Koko and Drakeshe - thanks!
         */
        private void handleRandoms() {
            checkLamp();
    
            Npc event = Npcs.getNearest(npc -> npc.containsAction("Dismiss") && npc.getTarget() == Players.getLocal());
            if (event == null)
                return;
    
            String eventName = event.getName();
            Log.severe("Random event live now : " + eventName);
            if ((eventName.equals("Genie") || eventName.equals("Drunken Dwarf") || eventName.equals("Dr Jekyll")
                    || eventName.equals("Rick Turpentine"))
                    && event.isPositionWalkable()) {
                if (eventName.equals("Genie") && Inventory.isFull()) {
                    Item dropRawFish = Inventory.getFirst(RAW_FISH_NAMES);
                    if (dropRawFish != null && dropRawFish.interact("Drop")) {
                        Time.sleep(500, 1000);
                    } else {
                        Item dropCookedFish = Inventory.getFirst(COOKED_FISH_NAMES);
                        if (dropCookedFish != null && dropCookedFish.interact("Drop")) {
                            Time.sleep(500, 1000);
                        }
                    }
                }
                if (!org.rspeer.runetek.api.component.Dialog.isOpen()) {
                    Time.sleep(600, 1800);
                    event.interact(x -> true);
                    Time.sleepUntil(org.rspeer.runetek.api.component.Dialog::isOpen, 1000, 10000);
                    Time.sleep(250, 1000);
                }
                while (org.rspeer.runetek.api.component.Dialog.canContinue()) {
                    org.rspeer.runetek.api.component.Dialog.processContinue();
                    Time.sleepWhile(() -> org.rspeer.runetek.api.component.Dialog.isOpen() || org.rspeer.runetek.api.component.Dialog.isProcessing(), 3000);
                    Time.sleep(250, 700);
                }
            } else {
                Time.sleep(600, 1800);
                event.interact("Dismiss");
            }
    
            Time.sleep(1000, 2000);
        }
    
        /**
         * Random event related. Verify if inventory has a lamp that needs to be activated.
         */
        private static void checkLamp() {
            if (Inventory.contains("Lamp")) {
                if (!Interfaces.isOpen(134)) {
                    Inventory.getFirst("Lamp").interact("Rub");
                    Time.sleepUntil(() -> Interfaces.isOpen(134), 500, 10000);
                }
                if (Interfaces.isOpen(134)) {
                    InterfaceComponent prayer = Interfaces.getComponent(134, 9);//Get prayer XP from the lamp
                    InterfaceComponent confirm = Interfaces.getComponent(134, 26);
                    prayer.interact("Advance Prayer");
                    Time.sleep(1000, 1500);
                    confirm.interact("Ok");
                    Time.sleepUntil(() -> !Interfaces.isOpen(134), 500, 10000);
                }
                if (org.rspeer.runetek.api.component.Dialog.canContinue()) {
                    Dialog.processContinue();
                    Time.sleep(300, 450);
                }
            }
        }
    
        @Override
        public void notify(RenderEvent e) {
            secondsPlayed = stopWatch.getElapsed().getSeconds();
            if (secondsPlayed <= 0)
                return;
    
            long actionsPerHour = actionsCounter * 3600 / secondsPlayed;
            int gainedXp = Skills.getExperience(TRAINING_SKILL) - COOKING_INIT_XP;
    
            //Initialize our graphics
            Graphics g = e.getSource();
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            int y = 38;
            int x = 9;
            int w = 240;
            int h = 100;
            //Background semi-transparent fill
            g.setColor(new Color(0, 0, 0, 120));
            g.fillRect(x - 3, 38 - 14, w, h);
    
            g2.setColor(Color.white);
            g2.drawString("Runtime: " + stopWatch.toElapsedString() + " (" + (status != null ? status : "") + ")", x, y);
            g2.setColor(Color.lightGray);
            g2.drawString("Max time: " + (MAX_RUNTIME / 60) + " min.", x, y += 20);
            g2.setColor(Color.white);
            g2.drawString("Cooked: " + actionsCounter + " (" + actionsPerHour + " /h)", x, y += 20);
    
            if (gainedXp > 0) {
                float xpPerHour = (int) stopWatch.getHourlyRate(gainedXp);
                g2.drawString("+ " + TRAINING_SKILL + " XP: " + gainedXp + " (" + (int) (xpPerHour / 1000) + "k /h)", x, y += 20);
                int xpLeft = Skills.getExperienceToNextLevel(TRAINING_SKILL);
                float timeToNextLevel = (xpLeft / xpPerHour) * 60;
                int curLvl = Skills.getLevel(TRAINING_SKILL);
                int nxtLvl = curLvl + 1;
                g2.setColor(Color.lightGray);
                g2.drawString("   -> Lvl " + curLvl + " to " + nxtLvl + " in " + (int) timeToNextLevel + " minutes", x, y += 20);
            }
        }
    
        @Override
        public void onStop() {
            Log.info("Stopped " + getMeta().name() + " script.");
    
        }
    }
    

    Please feel free to comment and post improved source-code


 

54
Online

16.6k
Users

1.4k
Topics

19.2k
Posts