Jump to content
Frequently Asked Questions
  • Are you not able to open the client? Try following our getting started guide
  • Still not working? Try downloading and running JarFix
  • Help! My bot doesn't do anything! Enable fresh start in client settings and restart the client
  • How to purchase with PayPal/OSRS/Crypto gold? You can purchase vouchers from other users
  • Open-Source Cook's Assistant Script


    TheHitchhiker

    Recommended Posts

    So I am currently working on some scripts and I have spent some time developing a quester for Cook's Assistant. Albeit simple, as of the moment this is the largest script I have been working on and I figured I'd share the code here for both critique and perhaps to help another Dreambot Novice.  I have included all notes/references and what-have-you.

    I will paste the code here for archival reasons and because it isn't anything I'd link on my GitHub atm. 

    This project absorbed some Areas, webwalking, and just overall reference from various places on the forum but I relied heavily on the implementation by @Before (The post). Different from Before's script, I provided functionality to gather items for the quest if you didn't have them already in your inventory. 

    As a sort of a "Hello World" to the Dreambot API I have learned a lot from this exercise and I will improve upon it more based on any suggestions. I have some questions and or concerns that I was hoping someone would be able to speak more about:

    1.  I had a lot of problems with conditional loops (while/do-while) running infinitely when the script was paused or stopped and I would have to just restart the client. I attempted to add a simple iteration count that would break the loop if it went on for too long but that didn't really prevent the issue from happening.  Ultimately I decided to mostly avoid them.
    2.  Because of issue 1 and my reluctance to develop very procedural code, I had the idea of in the future creating a subtask list where all i would need to do is call a tasknode in the onLoop method based on some condition. I feel as if it would be far cleaner than choosing methods from a switch statement or something similar. Not to mention that could possibly make it easier to randomize the order of the tasks.

    Thanks!

    Code:

    import org.dreambot.api.methods.Calculations;
    import org.dreambot.api.methods.map.Area;
    import org.dreambot.api.methods.quest.Quest;
    import org.dreambot.api.methods.tabs.Tab;
    import org.dreambot.api.script.AbstractScript;
    import org.dreambot.api.script.Category;
    import org.dreambot.api.script.ScriptManifest;
    import org.dreambot.api.wrappers.interactive.GameObject;
    import org.dreambot.api.wrappers.items.GroundItem;
    import java.util.Random;
    @ScriptManifest(
            author = "Hitchhiker",
            description = "Completes Cook's Assistant. The script will gather all the items needed if you don't already have them in your inventory." +
                    "ie. Bucket, Pot. Script will complete quicker if these items area already had so for maximum efficiency this " +
                    "should be ran after the completion of Tutorial Island. Script can be started from anywhere in the world at ground level.",
            category = Category.QUEST,
            version = 0.01,
            name = "Cook's Assistant Quester (Free Edition)"
    )
    public class Main extends AbstractScript {
        public Random Rand = new Random();
        public Area cookArea = new Area(3207,3217,3210,3212,0);
        public Area wheatArea = new Area(3162,3289,3166,3285,0);
        public Area windmillArea = new Area(3165,3300,3168,3302,0);
        public Area cookBasementArea = new Area(3208,9618,3210,9615);
        public Area eggArea = new Area(3227,3300,3230,3298);
        public Area dairyCowArea = new Area(3254,3278,3259,3273);
        public Area bucketArea = new Area(3213, 9624, 3216, 9622);
        public static final String COOK = "Cook";
        public static final String DAIRYCOW = "Dairy cow";
        public boolean StartCooksAssistant() {
            /*
            TravelTo(cookArea);
            if (!getDialogues().inDialogue() && !getLocalPlayer().isMoving()) {
                getNpcs().closest(COOK).interact("Talk-to");
            }
            while (getDialogues().canContinue()) {
                getDialogues().clickContinue();
            }
            getDialogues().chooseOption(1);
            //there should be a total of 2 dialogs each of which is option 1
            */
            getTabs().openWithMouse(Tab.QUEST);
            if (!getQuests().isStarted(Quest.COOKS_ASSISTANT))
            {
                TravelTo(cookArea);
                getNpcs().closest(COOK).interact("Talk-to");
                getDialogues().continueDialogue();
                sleep(600+Rand.nextInt(600));
                getDialogues().chooseOption(getDialogues().getOptionIndexContaining("What's wrong?"));
                sleep(600+Rand.nextInt(600));
                for (int i = 0; i < 3; i++) {
                    getDialogues().continueDialogue();
                    sleep(600+Rand.nextInt(600));
                }
                getDialogues().chooseOption(getDialogues().getOptionIndexContaining("I'm always happy to"));
                for (int i = 0; i < 3; i++) {
                    getDialogues().continueDialogue();
                    sleep(600+Rand.nextInt(600));
                }
            }
            return true;
        }
        public boolean GetEgg() {
            if (!getInventory().contains("Egg")) {
                TravelTo(eggArea);
                GetGroundItemIfNeeded("Egg");
            }
            return true;
        }
        public boolean GetPot() {
            if (!getInventory().contains("Pot")) {
                TravelTo(cookArea);
                GetGroundItemIfNeeded("Pot");
            }
            return true;
        }
        public boolean GetBucket() {
            if (!getInventory().contains("Bucket")) {
                TravelTo(cookArea);
                int tryCount = 0;
                /*while (getLocalPlayer().getZ() == 0 || tryCount < 5){*/
                    ClosestSpecifiedGameObjectInteract("Trapdoor","Climb-down");
                    //sleepWhile( () -> !cookBasementArea.contains(getLocalPlayer()), Calculations.random(3000, 4000));
                //}
                sleep(Calculations.random(4000,5000));
                //Walk to bucket
                TravelTo(bucketArea);
                GetGroundItemIfNeeded("Bucket");
                //Walk to ladder
                TravelTo(cookBasementArea);
                sleep(Calculations.random(2000,3000));
                ClimbClosestLadder(1,true);
            }
            return true;
        }
        public boolean GetMilk() {
            TravelTo(dairyCowArea);
            if (!getInventory().contains("Bucket of milk")) {
                getGameObjects().closest(DAIRYCOW).interact("Milk");
                sleepWhile( () -> !getInventory().contains("Bucket of Milk"), Calculations.random(35000, 40000));
            }
            return true;
        }
        public boolean GetGrain() {
            if (!getInventory().contains("Grain")) {
                TravelTo(wheatArea);
                sleepUntil(() -> getLocalPlayer().isStandingStill(), Rand.nextInt(6000));
                while (!getInventory().contains("Grain")) {
                    ClosestSpecifiedGameObjectInteractConditional("Gate", "Open", "Open", true);
                    sleepUntil(() -> getLocalPlayer().isStandingStill(), 1000+Rand.nextInt(500));
                    GameObject wheat = getGameObjects().closest("Wheat");
                    if (wheat.hasAction("Pick") && wheat != null) {
                        wheat.interact("Pick");
                        sleep(5000 + Rand.nextInt(500));
                    }
                }
                //In case it has been closed
                ClosestSpecifiedGameObjectInteractConditional("Gate", "Open", "Open", true);
                sleepUntil(() -> getLocalPlayer().isStandingStill(), 1000+Rand.nextInt(500));
            }
            return getInventory().contains("Grain");
        }
        public boolean GetFlour() {
            if (getInventory().contains("Flour")) {
                log("Flour Acquired!");
                return true;
            }
            else {
                if (!getInventory().contains("Pot")) {
                    GetPot();
                }
                else {
                    if (!getInventory().contains("Grain"))
                        GetGrain();
                    TravelTo(windmillArea);
                    sleep(Calculations.random(1000,2000));
                    while (getGameObjects().closest("Large Door").hasAction("Open")) {
                        ClosestSpecifiedGameObjectInteractConditional("Large Door", "Open", "Open", true);
                    }
                    //TravelTo(flourMill);
                    ClimbClosestLadder(2,true);
                    GameObject hopper = getGameObjects().closest("Hopper");
                    if (hopper != null) {
                        getInventory().get("Grain").useOn(hopper);
                        log("Put grain in hopper");
                    }
                    sleep(Calculations.random(4000,5000));
                    ClosestSpecifiedGameObjectInteract("Hopper controls", "Operate");
                    sleep(Calculations.random(4000,5000));
                    ClimbClosestLadder(2,false);
                    while (!getInventory().contains("Pot of flour") && getGameObjects().closest("Flour bin").hasAction("Empty")) {
                        ClosestSpecifiedGameObjectInteract("Flour bin", "Empty");
                    }
                    sleep(Rand.nextInt(600) + 1000);
                }
            }
            log("We got flour");
            return true;
        }
        public boolean CompleteCooksAssistant() {
            TravelTo(cookArea);
            getNpcs().closest(COOK).interact("Talk-to");
            for (int i = 0; i < 9; i++) {
                getDialogues().continueDialogue();
                sleep(600+Rand.nextInt(600));
            }
            return true;
        }
        public void GetGroundItemIfNeeded(String itemToGet) {
            while (!getInventory().contains(itemToGet)) {
                GroundItem item = getGroundItems().closest(itemToGet);
                if (item != null) {
                    item.interact("Take");
                    //this sleepwhile could be broken by something interupting the grabbing action
                    //for instance if the item is out of reach it wont try again to grab it
                    //found here: https://dreambot.org/forums/index.php?/topic/7671-how-to-correctly-wait-until-actions-have-happend/
                    sleepWhile( () -> !getInventory().contains(itemToGet), Calculations.random(35000, 40000));
                }
            }
        }
        public void TravelTo(Area destination) {
            //clicks really frequently when close to location
            //think i fixed this by changing this
            //getWalking().walk(destination.getCenter()); from getRandom()
            //https://dreambot.org/forums/index.php?/topic/4512-walking-a-path-with-doors/
    
            /*
            while (!destination.contains(getLocalPlayer())) {
                getWalking().walk(destination.getCenter());
                sleepUntil(() -> getWalking().getDestination().distance() < Calculations.random(5, 7) , Calculations.random(3400, 4250));
                sleep(Calculations.random(300, 600));
                sleepUntil(
                        () -> !getLocalPlayer().isMoving()
                                || getLocalPlayer().distance(
                                getClient().getDestination()) < Calculations.random(
                                7, 12), Calculations.random(5000, 6666));
    
            }
            */
    
            //Walking algorithm modified from Before's Cooks Assistant quest bot
            //issues: since this will sleep until the user has stopped moving + some random time there is a lot of standing around
            //however it does not have the issue of spam clicking once you get close to the destination
            while (!destination.contains(getLocalPlayer()) && !destination.contains(getWalking().getDestination())) {
                getWalking().walk(destination.getRandomTile());
                //sleep(2000+Rand.nextInt(1000));
                sleepUntil(() -> getLocalPlayer().isStandingStill(), Rand.nextInt(6000));
            }
        }
        public boolean ClimbClosestLadder(int floors, boolean isUp) {
            //add a z change counter and return true only if zchange == floors
            String directionToClimb = "";
            if (isUp == true)
                directionToClimb = "Climb-up";
            else
                directionToClimb = "Climb-down";
            for (int i = 0; i < floors; i++) {
                int zStart = getLocalPlayer().getZ();
                GameObject ladder = getGameObjects().closest("Ladder");
                if (ladder != null) {
                    int attempts = 0;
                    while (zStart == getLocalPlayer().getZ() /*&& !getLocalPlayer().isInCombat()*/ && attempts < 10) {
                        attempts++;
                        ladder.interact(directionToClimb);
                        sleepUntil(() -> getLocalPlayer().isStandingStill(), Rand.nextInt(6000));
                    }
                }
            }
            return true;
        }
        public boolean ClosestSpecifiedGameObjectInteract(String gameObjectName, String interactOption) {
            //I feel like a sleep for until is not animating would be sufficeint but if that doesnt work i could do a sleep based on how far the player is from the game object
            GameObject closestSpecifiedGameObject = getGameObjects().closest(gameObjectName);
            if (closestSpecifiedGameObject != null) {
                closestSpecifiedGameObject.interact(interactOption);
                //sleepUntil(() -> getLocalPlayer().isStandingStill(), Rand.nextInt(6000));
                sleep(Calculations.random(2000,3000));
                return true;
            }
            else
                return false;
        }
        public boolean ClosestSpecifiedGameObjectInteractConditional(String gameObjectName, String interactOption, String interactConditionalOption, boolean hasOption) {
            GameObject closestSpecifiedGameObject = getGameObjects().closest(gameObjectName);
            if (closestSpecifiedGameObject != null) {
                if (hasOption == true) {
                    if (closestSpecifiedGameObject.hasAction(interactConditionalOption)) {
                        closestSpecifiedGameObject.interact(interactOption);
                        sleepUntil(() -> getLocalPlayer().isStandingStill(), Rand.nextInt(6000));
                        return true;
                    }
                } else {
                    if (!closestSpecifiedGameObject.hasAction(interactConditionalOption)) {
                        closestSpecifiedGameObject.interact(interactOption);
                        sleepUntil(() -> getLocalPlayer().isStandingStill(), Rand.nextInt(6000));
                        return true;
                    }
                }
            }
            return false;
        }
    
        @Override
        public void onStart()
        {
            getTabs().openWithMouse(Tab.QUEST);
            if (getQuests().isFinished(Quest.COOKS_ASSISTANT))
            {
                log("Quest is already completed");
                stop();
            }
        }
    
        @Override
        public int onLoop() {
            log("Starting Cook's Assistant...");
            StartCooksAssistant();
            log("Getting pot...");
            GetPot();
            log("Getting bucket...");
            GetBucket();
            log("Getting egg...");
            GetEgg();
            log("Getting milk...");
            GetMilk();
            log("Getting flour...");
            GetFlour();
            log("Finishing Quest...");
            CompleteCooksAssistant();
            log("Terminating Script");
            stop();
    
            return 0;
        }
    }

     

    Link to comment
    Share on other sites

    Hey, nice job on your first script. There's some room for improvement, but that comes with practice and experience with the API. Do some research on Player Settings, Nodes, Enums, and States.

    Link to comment
    Share on other sites

    • 4 weeks later...

    Archived

    This topic is now archived and is closed to further replies.

    ×
    ×
    • Create New...

    Important Information

    We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.