Skip to main content

Dialogue & Dialogue Helper

This document covers both the high-level Dialogue Helper plugin automation and the underlying Dialog Actions SDK API.


Design Principle

OSRS dialogue is stateless: if the target widget is visible on the screen, click it; if not, do nothing. There is no signature tracking, lockout, retry backoff, or player-busy guards. Those concepts are wrong for dialogue and cause the plugin/API to suppress legitimate clicks.

Shared Action Pacing

Dialogue interactions respect the suite-wide ActionPacer ticked by PacketUtilsPlugin.onGameTick.

  • When a Quest Helper option, continue prompt, or options dialog is visible, we check ActionPacer.isReady(...) before queuing packets.
  • A paced result returns immediately without clicking, without updating the tick guard, and without logging an action.
  • After successful widget click and resume/pause delivery, the code calls ActionPacer.recordAction().
  • A local lastFiredTick field prevents duplicate sends inside the same game tick.

Stateless Dialogue Flow


Dialogue Helper Plugin

The DialogueHelperPlugin automatically advances dialogue and selects Quest Helper-aligned options.

  • Config group: n3dialoguehelper
  • Properties registration: runelite-plugin.properties (disabled by default)

Behavior (Per Game Tick)

  1. Gate on GameState.LOGGED_IN.
  2. Gate on client.getTickCount() != lastFiredTick to prevent duplicate packets in the same tick.
  3. Quest Option Scan (if autoQuestOptions):
    • Search for a widget where parentId == (219 << 16) | 1.
    • Parse the [N] prefix from its text.
    • Require ActionPacer.isReady(...).
    • Call WidgetApi.click() + WidgetApi.resumePause(id, N) + ActionPacer.recordAction().
    • Update lastFiredTick = tick and return.
  4. Continue Scan (if autoContinue):
    • Match Text.removeTags(text).trim() against "Click here to continue".
    • Require ActionPacer.isReady(...).
    • Call WidgetApi.click() + WidgetApi.resumePause(id, -1) + ActionPacer.recordAction().
    • Update lastFiredTick = tick and return.
note

Quest option selection takes precedence over continue prompts.

Configuration

KeyDefaultPurpose
autoContinuetrueClick continue prompts
autoQuestOptionstrueSelect Quest Helper–highlighted options
debugLoggingfalseInfo-level log on each action

Dialog Actions API

DialogActions wraps low-level widget detection and interaction. All write methods return InteractionResult and are paced.

Query Methods

  • isOpen(): true if any dialog type is currently visible.
  • isNPCDialog(): NPC speech widget (group 231) visible.
  • isPlayerDialog(): player speech widget (group 217) visible.
  • isOptionsDialog(): options list widget (group 219) visible.
  • isViewingOptions(): alias for isOptionsDialog().
  • isEnterInputOpen(): chatbox input (group 162) visible.
  • canContinue(): "Click here to continue" widget exists and is visible.
  • isQuestHelperMarkedOptionVisible(): true when a visible option under parent (219 << 16) | 1 has a Quest Helper [N] prefix.
  • getOptions() -> List<String>: option texts (HTML tags stripped).
  • getText() -> String: dialog body text (tags stripped; empty string if closed).
  • getName() -> String: speaker name (NPC name or player name; empty if absent).
  • hasOption(String text): case-insensitive contains check against getOptions().

Action Methods

  • continueSpace(): clicks the continue prompt dynamically.
  • chooseQuestHelperMarkedOption(): clicks the Quest Helper-marked [N] option.
  • chooseOption(int index): selects option by 0-based index.
  • chooseOption(String... options): selects first option containing any of the given strings.
  • chooseOption(Predicate<String>): selects first option matching predicate.
  • enterAmount(int amount): sends number input value.
  • enterObject(int objectId): sends object-picker input value (ResumeObjDialog).
  • enterText(String text): sends string input value.
  • enterName(String name): sends name input value.

Quest Helper Option Format

Quest Helper places options under parent (219 << 16) | 1 and prepends a [N] prefix where N is the option index (typically 1-5). Dialogue Helper parses N from the character immediately preceding the ] character.


Code Examples

Example: Basic Conversation Helper

if (DialogActions.isNPCDialog()) {
if (DialogActions.canContinue()) {
DialogActions.continueSpace();
} else if (DialogActions.hasOption("Yes")) {
DialogActions.chooseOption("Yes");
}
}

if (DialogActions.isEnterInputOpen()) {
DialogActions.enterAmount(1000);
}

Example: Custom Predicate Options

DialogActions.chooseOption(text -> text.contains("Start the quest") || text.contains("Tell me more"));

Implementation Details

  • OSRS destroys (rather than hides) dialog widgets when they close, so a null text guard is sufficient instead of an isHidden() check.
  • continueSpace() and chooseOption() route through MousePackets.tryQueueClickPacket() before sending the resume packet. A click packet failure short-circuits the action.
  • ActionPacer is static and ticked suite-wide. Do not tick it again inside feature plugins.

Testing

.\gradlew.bat test --tests com.n3plugins.dialoguehelper.* --console plain

Tests should inject WidgetApi.setAdapterForTesting(mock) and invoke ActionPacer.reset() in @Before.