NPC dialogue
Usage guide of npc.dialogue: dialogue documents, typed lines, up to four choices that run actions, the talk_to mission step, settings and defaults, the dialogue.lines service, events, hooks and the HUD variables.
Talking to NPCs (npc.dialogue) #
Make an NPC talk: the player interacts with it, its lines are typed on screen, and the player may pick between up to four choices that run actions or lead to another dialogue. The quest side (givers, talk_to steps) is described in the quests guide; the NPCs themselves in the NPC guide. Readable offline: gripforge docs npc-dialogue, or the MCP tool gripforge_docs (topic npc-dialogue).
What it is for #
npc.dialogue owns the conversation: which text to show for an NPC and a topic, how it is typed, when it moves on, what a choice does. It registers every NPC that has something to say with interaction.use ("Talk to <name>"), so the player starts a conversation with the interaction key. It shows nothing by itself beyond HUD variables and the presentation module (the speaker, the line typed so far and up to four choices); the look is the HUD's.
Turn it on #
gripforge_gamekit_install { project_id: "gkp_…", id: "npc.dialogue" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "npc.dialogue",
config: { "charsPerSecond": 50, "pauseWorld": true } }
It requires npc.behavior, interaction.use, hud.bind and game.engine. An NPC is known by the id of its document in npcs (the npc.brain.npcId of npc.core, or a component dialogue.npc set to that id on a placed instance). The simplest content is the dialogue.lines of the NPC document:
{ "id": "elder", "name": "Elder", "dialogue": { "lines": { "greet": ["Hi.", "Bye."] } } }
First example #
<!-- test: kits/game_engine/host/tests/npc_dialogue.rs::a_choice_runs_its_actions_and_continues_to_the_next_dialogue --> A dialogues document with a choice that runs an action and continues with another dialogue:
{ "id": "d_offer", "npc": "elder", "topic": "offer", "speaker": "Old Elder", "lines": ["Help?"],
"choices": [ { "id": "yes", "text": "Yes", "next": "d_thanks", "then": [ { "set_var": { "path": "helped", "value": true } } ] } ] }
{ "id": "d_thanks", "topic": "thanks", "lines": ["Thanks."] }
Calling dialogue.lines.say(npc, "offer") with the entity id of the NPC (or interacting) opens the conversation; the line is typed, the variable dialogue.choice.1 reads "Yes", key 1 picks it, the action runs, and d_thanks follows. A talk_to mission step on topic thanks completes when that dialogue ends.
Settings and defaults #
| Setting | Type | Default | Meaning |
|---|---|---|---|
charsPerSecond | number, 5 to 200 | 40 | typing speed of a line |
autoAdvanceSeconds | number, 0 to 30 | 4 | a fully typed line moves on by itself after this delay; 0 turns it off. The last line of a dialogue with choices always waits |
pauseWorld | boolean | false | pause the game during the conversation (the dialogue clock keeps running) |
All three are open to mods.
Content: the dialogues collection #
| Field | Meaning |
|---|---|
id | required, unique; a choice next or say can name it |
npc | npcs document that offers it as a topic; without it the dialogue is reached by id only |
topic | default greet |
speaker | default: the name of the NPC document |
lines | required, at least one string |
choices | up to 4 of { id, text, next?, then? }; next is a dialogue id or a topic of the same NPC (absent: the dialogue ends); then is a list of trigger actions run when picked |
A key (topic or dialogue id) resolves to the dialogues document with that id, then to a document of this NPC with that topic, then to dialogue.lines[key] of the NPC document. Texts go through i18n.text when that kit is installed, so a line can be a translation key.
Services, events, variables, hooks #
dialogue.lines(service):say(npc, topic?)opens a conversation,current()describes the running one,active(),advance(),choose(index | id),end(reason?),topics(npc).start_dialogue(action): open a dialogue without an interaction (a cut-in),{ npc?, dialogue? }. Ignored while another one runs. Mission steptalk_to { npc?, topic? }completes when a dialogue of that NPC (and topic) ends byfinishedorchoice.dialogue.started,dialogue.choice,dialogue.ended(events):{ npc, npcId, topic }, plus{ choice, index }and{ reason }. The reasons arefinished,choice,cancelled,walked_away,despawned, or the one given toend().dialogue.refused(event): a hook cancelled a start or a choice.dialogue.active,dialogue.speaker,dialogue.text,dialogue.choices,dialogue.choice.1todialogue.choice.4(variables): for the HUD;dialogue.textis the line typed so far.dialogue.next,dialogue.choice_1todialogue.choice_4(actions of the input map): next line (E,Enter, mouse button 2 by default) and choices (keys1to4).dialogue.nextfinishes the typing of the line, then goes to the next one.dialogue.start(hook): before a dialogue opens;topicis mutable; cancellable.dialogue.choose(hook): before a choice is taken;choiceis mutable; cancellable (the choices keep waiting).dialogue.advance(hook): before a line is revealed or advanced, withoriginauto,inputorservice; cancellable. A voice kit uses it to hold the automatic advance while a clip plays.
Hooks and modding #
A mod can change the three settings and replace or add dialogues documents; hooks let a game or a mod rewrite the topic, refuse a start, or swap a choice. The conversation is saved with the game and resumes on the same line.
Engines #
The conversation logic is the same Rust code on the web, natively and in the engine wrappers. The line, the speaker and the choices are HUD variables, drawn by the HUD of each engine.
When it does not do what you expect #
- The NPC cannot be talked to: it has no document in
npcsand nodialogue.npccomponent, or nothing to say (no dialogue and nodialogue.lines). - Nothing opens and
dialogue.refusedfires: adialogue.starttap cancelled it. - A second dialogue does not start: one conversation runs at a time.
- The conversation closes by itself: the player walked more than 6 metres away (
walked_away), or the NPC was removed (despawned). - A choice list is cut: only the first four choices exist.
- A line does not advance by itself:
autoAdvanceSecondsis 0, or it is the last line and choices wait.
Limits #
No branching beyond four choices per dialogue, no conditions on choices (put them in the then actions or in separate dialogues), no voice (see the voice kit of the quests guide), no camera work.
Versions #
Kit 1.4.0; service dialogue.lines 1.1.0. 1.4.0 added the dialogue.advance hook.