diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/questhelper/QuestScript.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/questhelper/QuestScript.java index ad97b8fe97..89472ed084 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/questhelper/QuestScript.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/questhelper/QuestScript.java @@ -89,6 +89,15 @@ public class QuestScript extends Script { QuestStep dialogueStartedStep = null; + /** + * Epoch millis at which the post-dialogue cooldown expires. While + * {@code System.currentTimeMillis() < dialogueCooldownEndsAt}, the main tick + * returns early to avoid re-clicking the quest NPC and interrupting scripted + * animations or cutscenes that play between dialogue exchanges. Set on the + * transition from in-dialogue to not-in-dialogue; zero means no cooldown. + */ + private long dialogueCooldownEndsAt = 0; + public boolean run(QuestHelperConfig config, QuestHelperPlugin mQuestPlugin) { @@ -182,6 +191,9 @@ public boolean run(QuestHelperConfig config, QuestHelperPlugin mQuestPlugin) { //if there is no quest option in the dialogue, just click player location to remove // the dialogue to avoid getting stuck in an infinite loop of dialogues if (!hasOption) { + if (Rs2Dialogue.acceptQuestStartDialogue()) { + return; + } if (getQuestHelperPlugin().getSelectedQuest() != null && getQuestHelperPlugin().getSelectedQuest().getQuest().getId() == Quest.IMP_CATCHER.getId() && Microbot.getClient().getTopLevelWorldView().getPlane() == 1) { @@ -210,9 +222,16 @@ public boolean run(QuestHelperConfig config, QuestHelperPlugin mQuestPlugin) { Rs2Keyboard.keyPress(KeyEvent.VK_SPACE); return; } else { + if (dialogueStartedStep != null) { + dialogueCooldownEndsAt = System.currentTimeMillis() + Rs2Random.between(4000, 7000); + } dialogueStartedStep = null; } + if (System.currentTimeMillis() < dialogueCooldownEndsAt) { + return; + } + boolean isInCutscene = Microbot.getVarbitValue(4606) > 0; if (isInCutscene) { if (ShortestPathPlugin.getMarker() != null) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/dialogues/Rs2Dialogue.java b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/dialogues/Rs2Dialogue.java index c28d1040b5..50fea34c0d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/dialogues/Rs2Dialogue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/dialogues/Rs2Dialogue.java @@ -692,6 +692,26 @@ public static boolean handleQuestOptionDialogueSelection() { return false; } + /** + * Detects a quest-start prompt (e.g. "Would you like to start the Cook's Assistant quest?") + * and clicks the "Yes" option. Matches case-insensitively on prefix + suffix + keyword + * so it catches the OSRS convention across quests without picking up unrelated prompts + * like "Would you like to start a fire?". + * + * @return true if a quest-start prompt was detected and Yes was clicked + */ + public static boolean acceptQuestStartDialogue() { + String question = getQuestion(); + if (question == null) return false; + + String q = question.toLowerCase().trim(); + if (!q.startsWith("would you like to start")) return false; + if (!q.contains("quest")) return false; + if (!q.endsWith("?")) return false; + + return clickOption("Yes", false); + } + /** * Retrieves and strips the color tags from the text of a visible widget. *