RPG Game Quest & Dialogue Viewer

Quest & Dialogue Viewer: How It Works

Quest & Dialogue Viewer is an internal tool for Project Isekai (Godot 4). It shows each character’s quests, dialogue scenes, idle chatter and setting notes on one browser page, with the same dialogue portraits the game uses. It reads the live project files on every request, so the page always matches what the current game would load. It only reads game files and never writes to them.

Why we built it

Our dialogue lives in two places: JSON data files and GDScript code. Quest progress is split between quests.json and stage names inside the code. Reviewing one character’s story meant opening a dozen files and guessing the order. The viewer lays it all out per character, in play order.

Architecture
serve.py: a local HTTP server using only the Python 3.9+ standard library (about 1,700 lines). No dependencies, no build step.
index.html: a single-file front end in plain JavaScript.
quest_order.json: the only hand-maintained file. It holds the quest order and a few linking hints.
/api/data rebuilds the whole data bundle from disk on each request.
/api/version returns a signature (latest modified time + file count) over data, localization, scripts and design docs. The page polls it every 2.5 seconds and reloads when it changes.
/res/… serves portrait images, limited to image files inside the project folder.
If a file is half-edited and fails to parse, the server returns the error as JSON and the page shows the cause.

Data sources
Quests: quests.json, items.json, kyle_bounties.json
Dialogue data: intro_dialogue.json, mira_cormang_dialogue.json, affinity teaching lines in npc_affinity.json, idle lines in npc_idle_dialogue.json, town requests
Text: localization CSVs, code_texts.json and the Japanese .po file. The page switches between Korean, English and Japanese.
Portraits: dialogue_portraits.json, resolved in the same order as the game’s dialogue_panel.gd (speaker key, name key, identity, then assets/ui/portraits/.png)
Extracting dialogue from GDScript

Many scenes are written in code, so the viewer parses .gd files statically, without running Godot.

It recognizes speaker/text dictionaries, row tuples, say()-style helpers, choice() menus, show_conversation() and the project’s own wrapper functions.
It resolves local variables and ternary expressions to find the real speaker and text key.
It records the enclosing if/match conditions and shows them as a readable “Shown when …” heading with the key in parentheses. Quest status checks and “which NPC you are talking to” checks are translated automatically. Other conditions use a label table.
When the same line exists in both data and code, the copies are merged.
Linking lines to quests and ordering them
A line is tied to a quest through quest IDs and constants in the surrounding code, accept() and quest event calls, stage names mapped in stage_links, and keyword hints.
QuestManager status checks place each line in a phase: offer, in progress, complete or claimed.
Inside a quest, scenes follow the script in the scenario documents. The viewer takes the > Speaker: line blocks from sections whose heading names the quest and matches them to game lines with character-trigram Dice similarity (threshold 0.45). Without a matching document it falls back to phase, stage order and source position. A manual scene_order can override both.
Quest order per protagonist comes from quest_order.json, which mirrors the progression tables in the design docs. Shared quests appear only for the protagonists who can actually receive them.
Copy with references

Any line, scene or quest can be copied together with its context: text key, speaker key, source file:line, quest ID and condition. Designers paste it straight into issues or chat.

Character settings

The settings tab combines game data (role, class, starting region, birthday, gift preferences, starting affinity, teaching tiers) with matching entries from the worldbuilding docs, each labeled with its source file.

Current scale and limits

As of September 26, 2026 it covers 51 characters, 51 quests and 182 dialogue scenes (132 from code, 19 story scenes, 18 affinity scenes, 10 town requests, 3 bounties). Extraction is heuristic: text assembled at runtime can be missed, and some links still need a hint in quest_order.json. Our quest guidelines require every new quest to be registered there.

2 Likes