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
  • Try asking for help in the chatbox
  • How to check if quest is complete only once?


    trtl
     Share

    Recommended Posts

    Here's my snippet:

    public int onLoop() {
    
            boolean nearRedbeard = NEARREDBEARD.contains(getLocalPlayer());
            boolean questCheck;
    
            if (questCheck == null) {
                Tabs.openWithMouse(Tab.QUEST);
            }
            if (!FreeQuest.PIRATES_TREASURE.isFinished()) {
                questCheck = true;
                if (Walking.getDestinationDistance() > Calculations.random(4, 6)) {
                    sleep(Calculations.random(900, 1500));
                } else if (!nearRedbeard) {
                    Walking.walk(NEARREDBEARD.getRandomTile());
                    sleep(Calculations.random(1080, 1240));
                }
                NPC redbeard = NPCs.closest(REDBEARD_FILTER);
    ...

    This gives me an error for the uninitiated bool variable questCheck, although I'm not sure how I should be checking if I've already looked at the quest tab. I'm trying to prevent it from constantly moving to open the quest tab onLoop... Thoughts?

    Link to comment
    Share on other sites

    4 hours ago, trtl said:

    Here's my snippet:

    public int onLoop() {
    
            boolean nearRedbeard = NEARREDBEARD.contains(getLocalPlayer());
            boolean questCheck;
    
            if (questCheck == null) {
                Tabs.openWithMouse(Tab.QUEST);
            }
            if (!FreeQuest.PIRATES_TREASURE.isFinished()) {
                questCheck = true;
                if (Walking.getDestinationDistance() > Calculations.random(4, 6)) {
                    sleep(Calculations.random(900, 1500));
                } else if (!nearRedbeard) {
                    Walking.walk(NEARREDBEARD.getRandomTile());
                    sleep(Calculations.random(1080, 1240));
                }
                NPC redbeard = NPCs.closest(REDBEARD_FILTER);
    ...

    This gives me an error for the uninitiated bool variable questCheck, although I'm not sure how I should be checking if I've already looked at the quest tab. I'm trying to prevent it from constantly moving to open the quest tab onLoop... Thoughts?

    Hey there!

    So I see a few things without really look much at all.

    Firstly, a boolean can not do this condition

    if (questCheck == null) {

    this is because a boolean can only be 2 values. "TRUE" or "FALSE". It can never be "NULL".

    Second, if you would like to do an action ONCE at the start (such as checking if a quest is already completed) then you would never want it inside the "onLoop" method. You can easily add this check into "onStart" method.

    For example you can do this:

    	@Override
    	public void onStart() {
    		if (FreeQuest.PIRATES_TREASURE.isFinished())
    			isPiratesTreasureDone = true;
    	}

     

    Hopefully this all helps and let us know if you have anymore questions  :)

    Link to comment
    Share on other sites

    4 hours ago, trtl said:

    This gives me an error for the uninitiated bool variable questCheck, although I'm not sure how I should be checking if I've already looked at the quest tab. I'm trying to prevent it from constantly moving to open the quest tab onLoop... Thoughts?

    To avoid it moving there if its already open use:
     

    if(Tabs.isOpen(Tab.QUEST) || Tabs.openWithMouse(Tab.QUEST))
    

    This way you're only attempting to open it if its not already open
    I like to use the return value within an if statement personally. That way you guarantee its success in case there is a miss click or something else

    Link to comment
    Share on other sites

    23 hours ago, Bryno said:

    Hey there!

    So I see a few things without really look much at all.

    Firstly, a boolean can not do this condition

    if (questCheck == null) {

    this is because a boolean can only be 2 values. "TRUE" or "FALSE". It can never be "NULL".

    Second, if you would like to do an action ONCE at the start (such as checking if a quest is already completed) then you would never want it inside the "onLoop" method. You can easily add this check into "onStart" method.

    For example you can do this:

    	@Override
    	public void onStart() {
    		if (FreeQuest.PIRATES_TREASURE.isFinished())
    			isPiratesTreasureDone = true;
    	}

     

    Hopefully this all helps and let us know if you have anymore questions  :)

    I was aware the boolean can't be used like that (after trying that out), was just showing my attempt to help illustrate what I was trying to accomplish.

    Thank you, that bit about doing it within onStart is exactly what I needed, I hadn't thought to use that yet and that'll be a bit of info that will help me a ton moving forward!

     

    22 hours ago, Axolotl said:

    To avoid it moving there if its already open use:
     

    if(Tabs.isOpen(Tab.QUEST) || Tabs.openWithMouse(Tab.QUEST))
    

    This way you're only attempting to open it if its not already open
    I like to use the return value within an if statement personally. That way you guarantee its success in case there is a miss click or something else

    This is an interesting bit of code I hadn't though of either, although I think it would also result in a bit of an apparent bot-like maneuver. (keeping the quest tab open all the time seems strange to me and might be a potential way to trigger a bot flag if detection methods continue to evolve. Probably not the case now I'm sure though)

    For the return value, you're referring to my usage of sleep right? I'll definitely keep that in mind as I continue learning how to script, makes a lot of sense. PS: Thanks again for your help with the quest detection code!

    Edit: Looks like I can't use sleep within the return value (returns void instead of an int) but I guess it works the same way without it so no big deal.

    Edit2: Didn't have much time today to work on this further but here's where I got on this portion of the script. If you see anything else wrong or done poorly I'd greatly appreciate any more advice you guys might have for me. So far it seems to be working well enough.

    public boolean piratesTreasureDone;
    
        public void onStart() {
            log("Welcome to trtlFisher!");
            Tabs.openWithMouse(Tab.QUEST);
            if (FreeQuest.PIRATES_TREASURE.isFinished()) {
                boolean piratesTreasureDone = true;
            } else {
                boolean piratesTreasureDone = false;
            }
        }
    
    ...
      
        public final String REDBEARD = "Redbeard Frank";
        public final Filter<NPC> REDBEARD_FILTER = new Filter<NPC>() {
            @Override
            public boolean match(NPC npc) {
                if (npc == null){
                    return false;
                }
    
                return npc.getName().equals(REDBEARD);
            }
        };
          
          final Area NEARREDBEARD = new Area(3052,3254,3055,3252);
    
    ...
      
              @Override
        public int onLoop() {
    
            boolean nearRedbeard = NEARREDBEARD.contains(getLocalPlayer());
    
            if (!piratesTreasureDone) {
    
                boolean piratesTreasureStarted = false;
    
                if (FreeQuest.PIRATES_TREASURE.isStarted()) {
                    piratesTreasureStarted = true;
                } else {
                    piratesTreasureStarted = false;
                }
    
                if (Walking.getDestinationDistance() > Calculations.random(4, 6)) {
                    return Calculations.random(900, 1500);
                } else if (!nearRedbeard) {
                    Walking.walk(NEARREDBEARD.getRandomTile());
                    log("Walking towards Redbeard");
                    return Calculations.random(1080, 1240);
                }
    
                NPC redbeard = NPCs.closest(REDBEARD_FILTER);
    
                if (!Dialogues.inDialogue() && !piratesTreasureStarted) {
                    log("Talking to Redbeard");
                    redbeard.interact("Talk-to");
                    return Calculations.random(1250, 1500);
                }
    
                final String[] OPTIONS = {"I'm in search of treasure.", "Ok, I will bring you some rum"};
    
                if (Dialogues.inDialogue() && !Dialogues.continueDialogue()) {
                    for(String option : OPTIONS) {
                        sleep(420, 840);
                        if (Dialogues.chooseOption(option)) {
                            break;
                        }
                    }
                } else if (Dialogues.continueDialogue()) {
                    sleep(250, 500);
                    Dialogues.continueDialogue();
                }
    
                // Next: need to script steps after getting quest started
            }
    
            return Calculations.random(320, 480);
        }

     

    Edited by trtl
    Link to comment
    Share on other sites

    @trtl I don't mean to use the sleep within the if, but rather boolean return values from other methods.
    You also won't need it to stay on the quest tab, especially if you're using switch case's with a progress int to tell you what to do, it would likely just be one of the cases, then in the next case you can tell it to open inventory, or if you want it somewhat randomized just use some random math to determine:
     

    int shouldOpen = Rand.nextInt(Calculations.random(5, 20));
    if(shouldOpen == 0)
    {
        if(Tabs.openWithMouse(Tab.INVENTORY) || Tabs.isOpen(Tab.INVENTORY))
            log("Opened inventory");
    }

    random.nextInt is beautiful as it allows for 0-max and is a lot more complex than simply:

    Calculations.random(0, 20);


    If you are doing a quest, I'd recommend a structure kinda like this:

    private int questProgress = 0;
    
    public void quest()
    {
        if(FreeQuest.PIRATES_TREASURE.isFinished())
        {
            end();
            return;
        }
        switch(questProgress)
        {
            case 0:
            {
                getQuestProgress();
                break;
            }
            case 1:
            {
                //go to NPC to start quest
                break;
            }
            case 2:
            {
                //etc...
                break;
            }
        }
    }
    
    private void getQuestProgress()
    {
        //find out what part the player is currently at in the quest and set the questProgress int to this
    }
    
    private void end()
    {
        //tell the gameManager to pick a new state or just send a log message that quest is done and end script
    }

    switch case's will be your best friend when it comes to structured things needing to be done. Avoid the use of too many if/else statements if possible, switch cases are much better for this type of task.

    Depending on how complex your quest or quests become, I'd recommend creating some helper classes that have solely static methods. For example a Dialogue helper, so you don't have to keep trying the same stuff over and over when you need it to interact with NPC's for continue / specific dialogues

    Edited by Axolotl
    Link to comment
    Share on other sites

    3 hours ago, Axolotl said:

    @trtl I don't mean to use the sleep within the if, but rather boolean return values from other methods.
    You also won't need it to stay on the quest tab, especially if you're using switch case's with a progress int to tell you what to do, it would likely just be one of the cases, then in the next case you can tell it to open inventory, or if you want it somewhat randomized just use some random math to determine:
     

    int shouldOpen = Rand.nextInt(Calculations.random(5, 20));
    if(shouldOpen == 0)
    {
        if(Tabs.openWithMouse(Tab.INVENTORY) || Tabs.isOpen(Tab.INVENTORY))
            log("Opened inventory");
    }

    random.nextInt is beautiful as it allows for 0-max and is a lot more complex than simply:

    Calculations.random(0, 20);


    If you are doing a quest, I'd recommend a structure kinda like this:

    private int questProgress = 0;
    
    public void quest()
    {
        if(FreeQuest.PIRATES_TREASURE.isFinished())
        {
            end();
            return;
        }
        switch(questProgress)
        {
            case 0:
            {
                getQuestProgress();
                break;
            }
            case 1:
            {
                //go to NPC to start quest
                break;
            }
            case 2:
            {
                //etc...
                break;
            }
        }
    }
    
    private void getQuestProgress()
    {
        //find out what part the player is currently at in the quest and set the questProgress int to this
    }
    
    private void end()
    {
        //tell the gameManager to pick a new state or just send a log message that quest is done and end script
    }

    switch case's will be your best friend when it comes to structured things needing to be done. Avoid the use of too many if/else statements if possible, switch cases are much better for this type of task.

    Depending on how complex your quest or quests become, I'd recommend creating some helper classes that have solely static methods. For example a Dialogue helper, so you don't have to keep trying the same stuff over and over when you need it to interact with NPC's for continue / specific dialogues

    I definitely do need to change this up, it's getting very confusing & heavy-handed trying to continue developing the script. I originally started with the node layout but I felt like I needed to simplify what I was doing as it was getting convoluted and confusing me, but maybe now I know a little more and that will be better for me. This is definitely a script with more steps than the first couple I made...

    It was more or less working well until I got to trying to detect the status of the store's raw shrimps/anchovies stock, and implementing some hopping functionality. Totally borked things up lol. If you want to see the complete mess of if's I ended up with:

    	final Area NEARREDBEARD = new Area(3048,3254,3055,3251);
        final Area NEARDEPOSITBOX = new Area(3044,3235,3046,3234);
        final Area NEARBOATS = new Area(3026,3225,3029,3212);
        final Area NEARFISHSHOP = new Area(3011,3229,3017,3222);
        final Area GPFISHSPOT = new Area(2986,3179,2998,3144);
        final Area GPFISHSPOT1 = new Area(2987,3178,2988,3174);
        final Area GPFISHSPOT2 = new Area(2997,3160,2998,3157);
    
        public boolean piratesTreasureDone;
        public boolean hopped;
        public boolean storeFull;
    
        int storeShrimps;
        int storeAnchovies;
    
        Widget fishShopWindow = Widgets.getWidget(300);
    
        public final String REDBEARD = "Redbeard Frank";
        public final Filter<NPC> REDBEARD_FILTER = new Filter<NPC>() {
            @Override
            public boolean match(NPC npc) {
                if (npc == null){
                    return false;
                }
    
                return npc.getName().equals(REDBEARD);
            }
        };
        public final String GPFISHNPC = "Fishing spot";
        public final Filter<NPC> GPFISHNPC_FILTER = new Filter<NPC>() {
            @Override
            public boolean match(NPC npc) {
                if (npc == null){
                    return false;
                }
    
                return npc.getName().equals(GPFISHNPC);
            }
        };
        public final String FISHSHOPNPC = "Gerrant";
        public final Filter<NPC> FISHSHOPNPC_FILTER = new Filter<NPC>() {
            @Override
            public boolean match(NPC npc) {
                if (npc == null){
                    return false;
                }
    
                return npc.getName().equals(FISHSHOPNPC);
            }
        };
    
        public void onStart() {
            log("Welcome to trtlFisher!");
    
            if (!Tab.QUEST.isOpen()) {
                Tabs.openWithMouse(Tab.QUEST);
            }
    
            if (FreeQuest.PIRATES_TREASURE.isFinished()) {
                boolean piratesTreasureDone = true;
            } else {
                boolean piratesTreasureDone = false;
            }
        }
    
        public void onExit() {
            log("Fine, fuck you too.");
        }
    
        @Override
        public int onLoop() {
    
            boolean nearRedbeard = NEARREDBEARD.contains(getLocalPlayer());
            boolean nearGPFishSpot = GPFISHSPOT.contains(getLocalPlayer());
            boolean nearGPFishSpot1 = GPFISHSPOT1.contains(getLocalPlayer());
            boolean nearGPFishSpot2 = GPFISHSPOT2.contains(getLocalPlayer());
            boolean nearFishShop = NEARFISHSHOP.contains(getLocalPlayer());
    
            if (!piratesTreasureDone) {
    
                boolean piratesTreasureStarted;
                piratesTreasureStarted = FreeQuest.PIRATES_TREASURE.isStarted();
                if (Walking.getDestinationDistance() > Calculations.random(4, 6)) {
                    return Calculations.random(800, 1200);
                } else if (!piratesTreasureStarted && !nearRedbeard) {
                    Walking.walk(NEARREDBEARD.getRandomTile());
                    log("Walking towards Redbeard");
                    return Calculations.random(800, 1200);
                }
    
                NPC redbeard = NPCs.closest(REDBEARD_FILTER);
                if (!Dialogues.inDialogue() && !piratesTreasureStarted) {
                    log("Talking to Redbeard");
                    redbeard.interact("Talk-to");
                    return Calculations.random(1250, 1500);
                }
    
                final String[] OPTIONS = {"I'm in search of treasure.", "Ok, I will bring you some rum"};
                if (Dialogues.inDialogue() && !Dialogues.continueDialogue()) {
                    for(String option : OPTIONS) {
                        sleep(420, 840);
                        if (Dialogues.chooseOption(option)) {
                            break;
                        }
                    }
                } else if (Dialogues.continueDialogue()) {
                    sleep(250, 500);
                    Dialogues.continueDialogue();
                    return Calculations.random(10, 100);
                }
    
                if (piratesTreasureStarted && nearFishShop && (Inventory.contains("Raw shrimps") || Inventory.contains("Raw anchovies"))) {
                    log("Checking shop inventory...");
                    if (fishShopWindow.isVisible()) {
                        storeShrimps = Shop.get("Raw shrimps").getAmount();
                        log(storeShrimps);
                        storeAnchovies = Shop.get("Raw anchovies").getAmount();
                        log(storeAnchovies);
                        if (storeShrimps == 50 || storeAnchovies == 50) {
                            log("Shop full, hopping worlds");
                            storeFull = true;
                            World world = Worlds.getRandomWorld(w -> w.isF2P() && !w.isPVP() && w.getMinimumLevel() == 0);
                            WorldHopper.hopWorld(world);
                            hopped = true;
                            return Calculations.random(10, 100);
                        } else if (storeShrimps < 50 && storeAnchovies < 50) {
                            storeFull = false;
                            return Calculations.random(10, 100);
                        }
                        return Calculations.random(10, 100);
                    }
                    return Calculations.random(10, 100);
                }
    
                if (Inventory.count("Coins") > 30 && piratesTreasureStarted && !Inventory.isFull() && !hopped) {
                    //will need to flip condition once fully tested
                    if (Walking.getDestinationDistance() > Calculations.random(4, 6)) {
                        return Calculations.random(800, 1200);
                    } else if (!nearGPFishSpot) {
                        Walking.walk(GPFISHSPOT.getCenter().getRandomizedTile());
                        log("Walking towards GP fishing spot");
                        return Calculations.random(800, 1200);
                    }
    
                    NPC gpFish = NPCs.closest(GPFISHNPC_FILTER);
    
                    if (nearGPFishSpot && !Inventory.isFull() && getLocalPlayer().getAnimation() != 621 && gpFish != null) {
                        log("Fishing...");
                        gpFish.interact("Small Net");
                        sleep(1000,5000);
                        if (!Tab.INVENTORY.isOpen()) {
                            Tabs.openWithMouse(Tab.INVENTORY);
                        }
                        return Calculations.random(4000, 6000);
                    } else if (getLocalPlayer().getAnimation() == 621) {
                        // Do nothing
                        return Calculations.random(10000, 15000);
                    } else if (nearGPFishSpot && gpFish == null) {
                        if (Walking.getDestinationDistance() > Calculations.random(4, 6)) {
                            return Calculations.random(800, 1200);
                        } else if (nearGPFishSpot && !nearGPFishSpot1) {
                            Walking.walk(GPFISHSPOT1.getRandomTile());
                            log("No spot detected, Walking towards GP fishing spot 1");
                            return Calculations.random(3000, 6000);
                        } else if (nearGPFishSpot && !nearGPFishSpot2) {
                            Walking.walk(GPFISHSPOT2.getRandomTile());
                            log("No spot detected, Walking towards GP fishing spot 2");
                            return Calculations.random(3000, 6000);
                        }
                    }
                }
    
                if ((Inventory.count("Coins") > 30 && piratesTreasureStarted && nearFishShop && (Inventory.isFull() || Inventory.contains("Raw shrimps") || Inventory.contains("Raw anchovies"))) || (nearFishShop && hopped)) {
                    log("Done fishing for GP!");
                    NPC fishShopNPC = NPCs.closest(FISHSHOPNPC_FILTER);
                    if (!Dialogues.inDialogue()) {
                        log("Trading with fishing shop NPC");
                        fishShopNPC.interact("Trade");
                        sleep(3000,5000);
                        if (fishShopWindow != null) {
                            if (Inventory.contains("Raw shrimps")) {
                                log("Selling raw shrimp");
                                Inventory.interact("Raw shrimps", "Sell 50");
                                return Calculations.random(10, 100);
                            }
                            if (Inventory.contains("Raw anchovies")) {
                                log("Selling raw anchovies");
                                Inventory.interact("Raw anchovies", "Sell 50");
                                return Calculations.random(10, 100);
                            }
                        }
                        return Calculations.random(2000, 3000);
                    }
                } else if (Inventory.count("Coins") > 30 && piratesTreasureStarted && !nearFishShop && Inventory.isFull()) {
                    if (Walking.getDestinationDistance() <= Calculations.random(4, 6)) {
                        Walking.walk(NEARFISHSHOP.getCenter().getRandomizedTile());
                        log("Walking towards fishing shop");
                    }
                    return Calculations.random(800, 1200);
                }
            }

    I was in a bit of a rush since I don't get too much time to work on scripting, but I think next time I'll completely rework it into a state or node based layout again, including what I've learned since the last time. What you said about using progress ints sounds like it will be key to keeping it from blowing up in size & dirtiness like this script. Do you have any recommendations for specific script sources I could look at with excellent documentation? I'm not a Java developer (obviously LOL) and that would be a major help I think. Also what does 0-max mean?

    Thanks again @Axolotl!

    Link to comment
    Share on other sites

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now
     Share

    ×
    ×
    • 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.