Gessa Docs
Recipes

Recipe

NPC dialog conversations and press-to-talk prompts

The player walks up to a villager and a speech box appears, or presses a key to open a shopkeeper's menu, or picks a reply that branches the conversation. There is no InteractableComponent or dialog component (stripped); dialog is a trigger, a UI panel, and branching state.
engine v1.0.234since script-semantic-patch-ops.v1, action-catalog.v1.0.232, ui.v1, persistence.v1, rendering.v1Copy for LLM

Use this for

talking to an NPC and showing a dialog box; a press-to-talk prompt near a character; branching conversation choices; a quest giver or shopkeeper that shows text; a floating interact label

Not for

physical doors and levers (see doors-buttons-and-interactions); the pickup or inventory itself (see inventory-and-item-pickups); AI-generated dialogue text (no LLM host op, see capability-ceiling)

Pairs with: Doors buttons levers and press-to-interact, UI HUD panels widgets and world nameplates, Inventory item pickups keys and equipping, Input mapping actions bindings keyboard mouse gamepad touch

The recipe

Author the panel with project_create_ui_panel and the logic with project_apply_script_semantic_patch using the ai_safe op pack.

  1. Show it is talkable: a floating TextRenderableComponent prompt over the NPC (textSource:"static", text:"Talk [E]"), toggled on while the player is in range.
  2. Detect intent: give the NPC a trigger ColliderComponent (collision:"trigger") and addTriggerHandler for proximity, or declare an interact action (see doors-buttons-and-interactions) and addActionHandler { "actionKey":"interact" } for a press-to-talk.
  3. Open the dialog: in a GessaScript body (replaceScriptFromGessaScript) call ctx.ui.openPanel on a dialog panel and ctx.ui.setWidgetValue to fill the speaker name and the current line.
  4. Branch on choices: store the conversation node in durable state with writeTypedStateValue (a dialogNode field); when the player picks a reply, advance the node and setBooleanState any flags (met, quest accepted). Read back with readTypedStateValue to gate later branches.
  5. Close and react: ctx.ui.closePanel when the talk ends, and emitCustomEvent a quest.accepted or shop.open event other systems (inventory, match) act on.

Pitfalls

  • Dialogue TEXT is authored content you write into the panel; there is no LLM or text-generation host op to write lines at runtime (see capability-ceiling).
  • Keep the conversation node in durable state, not a local variable, so a reload or a second interaction resumes the right branch.
  • Gate the open on proximity; an interact action fires everywhere, so confirm the player is near this NPC before opening its panel (the door-handler lesson).
  • The prompt label is presentation only; the actual talk is the panel plus the handler, not the TextRenderableComponent.

Verify

  • simulation_run (qa.run.start) to prove approaching or pressing interact opens the dialog and a choice advances the branch.
  • project_get_graph_snapshot to confirm the trigger or interact handler and the dialog panel exist.
Was this helpful?Report an issueContact support

On this page