Jump to content

Handling dialogues


shaba123

Recommended Posts

Im using a burning amulet to teleport to the lava maze.

It rubs the amulet, then i need to click "Lava Maze" then "Okay, teleport to level 41 Wilderness."

But it just keeps rubbing the amulet instead of handling the dialogues. This is my code:

        for (Item item : getInventory().getItems()) {
      	  if (item != null && item.getName().contains("Burning") && item.getName().matches(".*\\d+.*")) {

      		  item.interact("Rub");
      		sleep(random(600, 1100));
      		if (dialogues.isPendingOption()){
				dialogues.selectOption("Lava Maza");
				sleep(random(800, 1100));}
      		if (dialogues.isPendingOption()){
				dialogues.selectOption("Okay teleport to level 41 Wilderness.");
				sleep(random(800, 1100));}

                   }
      	  }

 

Edited by shaba123
Link to comment
Share on other sites

There are a number of structural bad practices here which are likely causing the issue, or unreliability in the script as a whole. If you fix these, you're more likely to fix your original problem!

You're writing the script in such a way that you're expecting each line to successfully execute every time. This is not (and can never be) the case as you're interacting with a live game so there is a whole middle layer entirely out of your control (latency fluctuation, game errors, resource throttling, ...). Don't do this! Instead, endeavor to make your script stateless, i.e it is not relying on any instruction to execute successfully before immediately proceeding to another instruction.

You can achieve this by only ever having one interaction call per onLoop traversal (the interaction to execute would be determined by the current global game state). For example, a common mistake is as follows with banking:

private void withdrawTenEggs() { // An example of how NOT to withdraw 10 eggs
  getBank().open();
  getBank().withdraw("Eggs", 10);
  getBank().close();
}

As you can see, there are three consecutive instructions. What if one of them were to fail - for example, the first 'getBank().open()' ? In this situation, the withdraw would have all sorts of problems as you cannot withdraw items if the bank is not open. This will likely throw horrible errors and potentially crash the script. Also, it is worth noting that jamming static sleeps between each of these calls will not fix the problem. 

So we've seen how not to do it, but how should you do it? Take a look:

private void withdrawTenEggsProperly() { // How to properly withdraw 10 eggs
  if (getInventory().contains("Eggs")) {
    if (getBank().isOpen()) {
      getBank().close();
    }
  } else {
    if (getBank().isOpen()) {
      getBank().withdraw("Eggs", 10);
    } else {
      getBank().open();
    }
  }
}

As you can see, the above example will only ever try to do one game interaction each time it is called. Arguably this is poor design, as after calling the method you are not guaranteed to be in the state you need to be in, but luckily this is less relevant in the context of a system where the state is encapsulated externally. The benefits this approach provides far outweigh the negatives, namely that this method is much less error prone as there are no linear dependencies and will always converge to an end goal. Furthermore, this methodology capitalises on the ever-looping nature of onLoop.

Hopefully that made sense - it's important to understand why your solution is unreliable rather than to patch up the code and settle for sub-par reliability :)

Good luck, let me know if you have any further questions

Apa

  • Like 3
Link to comment
Share on other sites

48 minutes ago, Apaec said:

There are a number of structural bad practices here which are likely causing the issue, or unreliability in the script as a whole. If you fix these, you're more likely to fix your original problem!

You're writing the script in such a way that you're expecting each line to successfully execute every time. This is not (and can never be) the case as you're interacting with a live game so there is a whole middle layer entirely out of your control (latency fluctuation, game errors, resource throttling, ...). Don't do this! Instead, endeavor to make your script stateless, i.e it is not relying on any instruction to execute successfully before immediately proceeding to another instruction.

You can achieve this by only ever having one interaction call per onLoop traversal (the interaction to execute would be determined by the current global game state). For example, a common mistake is as follows with banking:


private void withdrawTenEggs() { // An example of how NOT to withdraw 10 eggs
  getBank().open();
  getBank().withdraw("Eggs", 10);
  getBank().close();
}

As you can see, there are three consecutive instructions. What if one of them were to fail - for example, the first 'getBank().open()' ? In this situation, the withdraw would have all sorts of problems as you cannot withdraw items if the bank is not open. This will likely throw horrible errors and potentially crash the script. Also, it is worth noting that jamming static sleeps between each of these calls will not fix the problem. 

So we've seen how not to do it, but how should you do it? Take a look:


private void withdrawTenEggsProperly() { // How to properly withdraw 10 eggs
  if (getInventory().contains("Eggs")) {
    if (getBank().isOpen()) {
      getBank().close();
    }
  } else {
    if (getBank().isOpen()) {
      getBank().withdraw("Eggs", 10);
    } else {
      getBank().open();
    }
  }
}

As you can see, the above example will only ever try to do one game interaction each time it is called. Arguably this is poor design, as after calling the method you are not guaranteed to be in the state you need to be in, but luckily this is less relevant in the context of a system where the state is encapsulated externally. The benefits this approach provides far outweigh the negatives, namely that this method is much less error prone as there are no linear dependencies and will always converge to an end goal. Furthermore, this methodology capitalises on the ever-looping nature of onLoop.

Hopefully that made sense - it's important to understand why your solution is unreliable rather than to patch up the code and settle for sub-par reliability :)

Good luck, let me know if you have any further questions

Apa

Thank you so much, i understand what you are saying, i knew what i was doing wasn't the correct way but i did it anyway, silly me! This can get really frustrating when you cant work something out but it pays off when you finally understand why something is not working!

 

This is what i have now can you have a look and tell me whats wrong please, im still having the same problem, the dialogue is open but it doesn't click anything :

 

if (dialogues.isPendingOption()){					 // if dialogue is waiting for option
			dialogues.selectOption("Lava Maza"); 	// if "lava maze" is on dialogue, click it.
			sleep(random(200, 600));}
      	else if (dialogues.isPendingOption()) {  	//else
   dialogues.selectOption("Okay, teleport to level 41 Wilderness.");  // if "Okay, teleport to level 41 Wilderness." is on dialogue, click it.
      		sleep(random(200, 600));}
      	else { 										//else if dialogue is not open,  rub amulet
      		item.interact("Rub");
		sleep(random(1000, 1500));

I left little notes at the side to show what im trying to achieve and what i thought i had done correctly.

Edited by shaba123
Link to comment
Share on other sites

10 minutes ago, shaba123 said:

Thank you so much, i understand what you are saying, i knew what i was doing wasn't the correct way but i did it anyway, silly me! This can get really frustrating when you cant work something out but it pays off when you finally understand why something is not working!

 

This is what i have now can you have a look and tell me whats wrong please, im still having the same problem, the dialogue is open but it doesn't click anything :

 


if (dialogues.isPendingOption()){					 // if dialogue is waiting for option
			dialogues.selectOption("Lava Maza"); 	// if "lava maze" is on dialogue, click it.
			sleep(random(200, 600));}
      	else if (dialogues.isPendingOption()) {  	//else
   dialogues.selectOption("Okay, teleport to level 41 Wilderness.");  // if "Okay, teleport to level 41 Wilderness." is on dialogue, click it.
      		sleep(random(200, 600));}
      	else { 										//else if dialogue is not open,  rub amulet
      		item.interact("Rub");
		sleep(random(1000, 1500));

I left little notes at the side to show what im trying to achieve and what i thought i had done correctly.

I am a noob but I will chime in here.

 

You are close but your if statements are the same so it will never make it to the "else if" you need to do something like :

 

I would do something like:

 

if (dialogue.isPendingContunuation){

dialogue.completeDailogue("Okay, teleport to level 41 Wilderness.", "Lava Maze")

}

 

This will attempt to complete dialogue using these options if they exist.

 

Link to comment
Share on other sites

37 minutes ago, shaba123 said:

Thank you so much, i understand what you are saying, i knew what i was doing wasn't the correct way but i did it anyway, silly me! This can get really frustrating when you cant work something out but it pays off when you finally understand why something is not working!

 

This is what i have now can you have a look and tell me whats wrong please, im still having the same problem, the dialogue is open but it doesn't click anything :

 


if (dialogues.isPendingOption()){					 // if dialogue is waiting for option
			dialogues.selectOption("Lava Maza"); 	// if "lava maze" is on dialogue, click it.
			sleep(random(200, 600));}
      	else if (dialogues.isPendingOption()) {  	//else
   dialogues.selectOption("Okay, teleport to level 41 Wilderness.");  // if "Okay, teleport to level 41 Wilderness." is on dialogue, click it.
      		sleep(random(200, 600));}
      	else { 										//else if dialogue is not open,  rub amulet
      		item.interact("Rub");
		sleep(random(1000, 1500));

I left little notes at the side to show what im trying to achieve and what i thought i had done correctly.

It's seems like you're a bit confused on the structure of 'if', 'else if', and 'else', otherwise you wouldn't have put the same check twice.

Only one of those is allowed to execute. If the first statement returns true, the body of that if-statement is ran, and the else/else-ifs are ignored. If the second one returns true after the first returned false, then you run only the body of that one.

Examples:

if(true) {

   //Runs only this

} else if(true) { //This is not even evaluated because the first thing returned true.

  // Does not run

} else {

   //Does not run

}

||||||||||||||||||||||||||||||

if(false) {

} else if(true) {

   //This runs

} else {

}

|||||||||||||||||||||||||||||

if(false) {

} else if(false) {

} else {

    //This runs

}

^ This is why it's useless to make the dialogues.isPendingOption() check twice in a row. You're just going to check it immediately after if it initially returns false (and it will almost definitely also return false), or you're not going to check it at all if the first statement returns true.

 

If I'm being honest though, I don't know how your code compiles at all because of its 3 consecutive open brackets and lack of closed brackets.

Edited by Team Cape
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...