Jump to content

Need help selecting the right dialogue option


Alakazizam

Recommended Posts

So I typically just do something along the lines of

if(dialogues.isPendingOption()){
                    if(dialogues.selectOption("This")){}
                    else if(dialogues.selectOption("That")){}
                    else if(dialogues.selectOption("The other")){}
                }

I'm running into the issue where there's an option that contains the word "That" but is not only the word "That" but it is still trying to select it even though it's not what I need selected right here.
Is there a way to make sure the dialogue option will only be selected if it contains ALL of what is in the string in the code?

Link to comment
Share on other sites

Do you mean there are multiple options to select but all of them have the same text?
There are different overloads of selectOptions. You probably want the one that takes in an int. 

https://osbot.org/api/org/osbot/rs07/api/Dialogues.html

Also does typing in the exact string not work?

Edited by yfoo
Link to comment
Share on other sites

12 hours ago, Alakazizam said:

So I typically just do something along the lines of

if(dialogues.isPendingOption()){
                    if(dialogues.selectOption("This")){}
                    else if(dialogues.selectOption("That")){}
                    else if(dialogues.selectOption("The other")){}
                }

I'm running into the issue where there's an option that contains the word "That" but is not only the word "That" but it is still trying to select it even though it's not what I need selected right here.
Is there a way to make sure the dialogue option will only be selected if it contains ALL of what is in the string in the code?

Could always write something yourself with widgets? :)

RS2widget myOption = script.getWidgets().getWidgetContainingText(219, "My text");
if(myOptyion !+ null && myOption.isVisible()){
   myOption.interact();
}


or even write that method yourself using equals instead of contains :)

RS2Widget myOption = script.getWidgets().getAll().stream()
                        .filter(w -> w.getRootId() == 219)
                        .filter(w -> w.getMessage().equals("My Text"))
                        .findFirst().orElse(null);

if(myOption !+ null && myOption.isVisible()){
   myOption.interact();
}

 

Edited by Khaleesi
  • Like 1
Link to comment
Share on other sites

8 hours ago, Khaleesi said:

Could always write something yourself with widgets? :)

RS2widget myOption = script.getWidgets().getWidgetContainingText(219, "My text");
if(myOptyion !+ null && myOption.isVisible()){
   myOption.interact();
}


or even write that method yourself using equals instead of contains :)

RS2Widget myOption = script.getWidgets().getAll().stream()
                        .filter(w -> w.getRootId() == 219)
                        .filter(w -> w.getMessage().equals("My Text"))
                        .findFirst().orElse(null);

if(myOption !+ null && myOption.isVisible()){
   myOption.interact();
}

 

Yeah that's what I wound up doing. Working on a plank script and sometimes I'm just trying to get the logs to the sawmill so having an option 'Sawmill' will select to send to the sawmill of the amount from the previous trip which would set it to less than a full amount after restocking.

 

if(dialogues.isPendingOption()){
                    if(widgets.get(219, 1, 1) != null && widgets.get(219, 1, 1).isVisible()){
                        RS2Widget myWid = widgets.get(219, 1, 1);
                        if(myWid.getMessage().equals("Take to sawmill: 26 x Mahogany logs")){
                            if(inventory.contains("Mahogany logs")) {
                                if (dialogues.selectOption("Take to sawmill: 26 x Mahogany logs")) {}
                            } else {
                                useLogsOnButler();
                            }
                        } else if(myWid.getMessage().equals("Take to sawmill: 26 x Teak logs")){
                            if(inventory.contains("Teak logs")) {
                                if (dialogues.selectOption("Take to sawmill: 26 x Teak logs")) {}
                            } else {
                                useLogsOnButler();
                            }
                        }
                    }
  
  //etc.

This is pretty much what I have going on now.

Link to comment
Share on other sites

15 hours ago, yfoo said:

Do you mean there are multiple options to select but all of them have the same text?
There are different overloads of selectOptions. You probably want the one that takes in an int. 

https://osbot.org/api/org/osbot/rs07/api/Dialogues.html

Also does typing in the exact string not work?

I have an option to select 'Sawmill' for sending logs to the sawmill with the POH butler. But this also selects options like 'Take to sawmill: 12 x Teak planks' because it contains 'sawmill' in the text
I pretty much want it to only select that option if it says 'Take to sawmill: 26 x Teak planks' otherwise I'd want it to use the logs on the butler and then tell him to take 26

Link to comment
Share on other sites

11 hours ago, Alakazizam said:

I have an option to select 'Sawmill' for sending logs to the sawmill with the POH butler. But this also selects options like 'Take to sawmill: 12 x Teak planks' because it contains 'sawmill' in the text
I pretty much want it to only select that option if it says 'Take to sawmill: 26 x Teak planks' otherwise I'd want it to use the logs on the butler and then tell him to take 26

In that case, I would handle it by...
- first determining if you are using Teak/Mahogany based on inventory. (ex: boolean isTeak)
- Using widgets.containingText("Take To Sawmill") to get a List<Rs2Widget> of all the dialog options with the corresponding string. 
- Then based on "isTeak" search the List<Rs2Widget> for a rs2widget whose message ( rs2Widget.getMessage() ) contains both the correct log type AND 26. 

- Interact with the found widget. 

Link to comment
Share on other sites

It looks like 

if(dialogues.isPendingOption()){
                    if(widgets.get(219, 1, 1) != null && widgets.get(219, 1, 1).isVisible()){
                        RS2Widget myWid = widgets.get(219, 1, 1);
                        if(myWid.getMessage().equals("Take to sawmill: 26 x Mahogany logs")){
                            if(inventory.contains("Mahogany logs")) {
                                if (dialogues.selectOption("Take to sawmill: 26 x Mahogany logs")) {}
                            } else {
                                useLogsOnButler();
                            }
                        } else if(myWid.getMessage().equals("Take to sawmill: 26 x Teak logs")){
                            if(inventory.contains("Teak logs")) {
                                if (dialogues.selectOption("Take to sawmill: 26 x Teak logs")) {}
                            } else {
                                useLogsOnButler();
                            }
                        }
                    }
  
  //etc.

should work but its bad practice to refer to widgets with more than root id, I think I read this in the SDN guidelines. Even if this is not going on SDN, good idea anyway. 


Separate note. Put...
 

RS2Widget myWid = widgets.get(219, 1, 1); 


Above 
 

if(widgets.get(219, 1, 1) != null && widgets.get(219, 1, 1).isVisible())


Then change the if to 
 

if(myWid != null && myWid.isVisible())

So you don't make 3 calls to get the same widget.
 

Edited by yfoo
Link to comment
Share on other sites

17 hours ago, Alakazizam said:

Yeah that's what I wound up doing. Working on a plank script and sometimes I'm just trying to get the logs to the sawmill so having an option 'Sawmill' will select to send to the sawmill of the amount from the previous trip which would set it to less than a full amount after restocking.

 

if(dialogues.isPendingOption()){
                    if(widgets.get(219, 1, 1) != null && widgets.get(219, 1, 1).isVisible()){
                        RS2Widget myWid = widgets.get(219, 1, 1);
                        if(myWid.getMessage().equals("Take to sawmill: 26 x Mahogany logs")){
                            if(inventory.contains("Mahogany logs")) {
                                if (dialogues.selectOption("Take to sawmill: 26 x Mahogany logs")) {}
                            } else {
                                useLogsOnButler();
                            }
                        } else if(myWid.getMessage().equals("Take to sawmill: 26 x Teak logs")){
                            if(inventory.contains("Teak logs")) {
                                if (dialogues.selectOption("Take to sawmill: 26 x Teak logs")) {}
                            } else {
                                useLogsOnButler();
                            }
                        }
                    }
  
  //etc.

This is pretty much what I have going on now.

You can put multiple messages in there if you wanna do it like that, 

if (dialogues.selectOption("Take to sawmill: 26 x Mahogany logs", "Take to sawmill: 26 x Teak logs")) {}


and you can just improve this piece of code like this: (widget ids can change once in a while if new things get added or UI changes)

RS2Widget toSawmillWidget = getWidgets().getWidgetContainingText(219, "Take to sawmill:");
        if (toSawmillWidget != null && toSawmillWidget.isVisible()) {
            // Either interact
            if(toSawmillWidget.interact()){
                
            }
            
            //OR do a keyboard press, usually it's alway on 1 I assume?
            if(getKeyboard().typeKey('1')){
                
            }
        }else{
            useLogsOnButler(logName);
        }

 

Edited by Khaleesi
  • Like 1
Link to comment
Share on other sites

13 hours ago, yfoo said:

It looks like 

if(dialogues.isPendingOption()){
                    if(widgets.get(219, 1, 1) != null && widgets.get(219, 1, 1).isVisible()){
                        RS2Widget myWid = widgets.get(219, 1, 1);
                        if(myWid.getMessage().equals("Take to sawmill: 26 x Mahogany logs")){
                            if(inventory.contains("Mahogany logs")) {
                                if (dialogues.selectOption("Take to sawmill: 26 x Mahogany logs")) {}
                            } else {
                                useLogsOnButler();
                            }
                        } else if(myWid.getMessage().equals("Take to sawmill: 26 x Teak logs")){
                            if(inventory.contains("Teak logs")) {
                                if (dialogues.selectOption("Take to sawmill: 26 x Teak logs")) {}
                            } else {
                                useLogsOnButler();
                            }
                        }
                    }
  
  //etc.

should work but its bad practice to refer to widgets with more than root id, I think I read this in the SDN guidelines. Even if this is not going on SDN, good idea anyway. 


Separate note. Put...
 

RS2Widget myWid = widgets.get(219, 1, 1); 


Above 
 

if(widgets.get(219, 1, 1) != null && widgets.get(219, 1, 1).isVisible())


Then change the if to 
 

if(myWid != null && myWid.isVisible())

So you don't make 3 calls to get the same widget.
 

Will it not hang up and throw a null pointer error if I try to set myWid to a widget that might not be there by putting it above that null check? 
I'll look into those script rules though, I'm still fairly nooby lol

Link to comment
Share on other sites

13 hours ago, yfoo said:

It looks like 

if(dialogues.isPendingOption()){
                    if(widgets.get(219, 1, 1) != null && widgets.get(219, 1, 1).isVisible()){
                        RS2Widget myWid = widgets.get(219, 1, 1);
                        if(myWid.getMessage().equals("Take to sawmill: 26 x Mahogany logs")){
                            if(inventory.contains("Mahogany logs")) {
                                if (dialogues.selectOption("Take to sawmill: 26 x Mahogany logs")) {}
                            } else {
                                useLogsOnButler();
                            }
                        } else if(myWid.getMessage().equals("Take to sawmill: 26 x Teak logs")){
                            if(inventory.contains("Teak logs")) {
                                if (dialogues.selectOption("Take to sawmill: 26 x Teak logs")) {}
                            } else {
                                useLogsOnButler();
                            }
                        }
                    }
  
  //etc.

should work but its bad practice to refer to widgets with more than root id, I think I read this in the SDN guidelines. Even if this is not going on SDN, good idea anyway. 


Separate note. Put...
 

RS2Widget myWid = widgets.get(219, 1, 1); 


Above 
 

if(widgets.get(219, 1, 1) != null && widgets.get(219, 1, 1).isVisible())


Then change the if to 
 

if(myWid != null && myWid.isVisible())

So you don't make 3 calls to get the same widget.
 

That's good to know, but I don't think I can stack them up like this in this case because I only want it to go with the mahogany option if there are mahogany logs in inventory, otherwise I'd want it to use the logs the player has in inventory on the butler. This script just takes the highest tear logs from the bank and brings them over for planks to be made, you don't manually set what you'll be making or anything like that so it could finish up teaks and then start on oaks.

But like I said, I never knew you could do that, so good to know.

Link to comment
Share on other sites

52 minutes ago, Alakazizam said:

Will it not hang up and throw a null pointer error if I try to set myWid to a widget that might not be there by putting it above that null check? 
I'll look into those script rules though, I'm still fairly nooby lol


 

RS2Widget myWid = widgets.get(219, 1, 1); 

You are referring to this line right? Its ok to do because I am assigning an Object reference here. An object reference is just like a regular variable assignment (ex: int myint = 1;) except it deals with a class (ex: Rs2Widget, ArrayList, String) instead of a primitive (int, double, boolean). Remember, in Java an object reference can be assigned to null.

Assuming the widgets.get() returns null, a null pointer will only occur if I attempt to do something with it without null checking, (Such as myWid.isVisible()). Thats why I still have your original null check just modified to use myWid. 

if(myWid != null && myWid.isVisible())



Watch this video to get a more indepth explanation of primitives vs references.

 

Edited by yfoo
  • Heart 1
Link to comment
Share on other sites

I do this for option in dialog, not sure if it applies here, if you know the exact string to use, I make an array with all options:
 

public static String[] ThurgoDialog = new String[] {
	"Something else.", 
	"Would you like a redberry pie?", 
	"Can you make a special sword for me?",
    	"About that sword...", 
	"Can you make that replacement sword now?"
};

And then I use this method to handle dialogs, feed it an NPC name as a string and the array of options from above. It will talk to the NPC and then if a dialog is pending with continue it just continues, and if the option shows up it uses the options from the array:

private void handleDialog(String npcName, String[] dialogOptions) {
        if (npcs.closest(npcName) != null) {
            if (!getDialogues().inDialogue()) {
                npcs.closest(npcName).interact("Talk-to");
                Sleep.sleepUntil(() -> getDialogues().inDialogue(), 5000);

            } else if (getDialogues().isPendingContinuation()) {
                getDialogues().clickContinue();
                Sleep.sleepUntil(() -> !getDialogues().isPendingContinuation(), MethodProvider.random(600,1200));

            } else if (getDialogues().isPendingOption()) {
                for (String option : dialogOptions) {
                    if (getDialogues().selectOption(option)) {
                        Sleep.sleepUntil(() -> !getDialogues().isPendingOption(), MethodProvider.random(600,1200));
                        break;
                    }
                }
            }
        }
    }

Maybe handy at some point :/

Edited by Wacky Jacky
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...