Data model
Everything ChatMapper produces — JSON, XML, .cmp, Yarn, the HTML player —
is a view of one model. Learn it once and every export is obvious. The
JSON format page is the normative key-by-key
specification; this page is the model in prose.
Project
Section titled “Project”A project is one document. It has a Title, Author, Description, a
primary Language (en-US), a Version string recording which schema
version wrote it (informational), a project-level UserScript in Lua that
runs once at the start of a playthrough, and Assets.
Project├── Language, Title, Version, Author, Description, UserScript├── Assets│ ├── Actors[] — characters; one has IsPlayer = "True"│ ├── Items[] — objects, and quests in some engines│ ├── Locations[] — places│ ├── UserVariables[] — named state with an initial value│ └── Conversations[] — each a graph of DialogNodes└── _editor — editor-only metadata; may be ignored or strippedAssets
Section titled “Assets”Actors, Items, Locations and UserVariables share one shape: an
integer ID unique within its own collection, and a Fields map.
{ "ID": 2, "Fields": { "Name": "Ferryman", "IsPlayer": "False", "Description": "Works the last crossing." } }Every field value is a string. "True", "30", "[]" — regardless of
the field’s declared type. Coerce at the boundary of your code, once, and
never write a non-string value back.
Conventional fields:
| Collection | Fields |
|---|---|
| Actors | Name, IsPlayer, Description, Pictures, Age, Gender |
| Items | Name, Description, Pictures, Purpose, Scene |
| Locations | Name, Description, Pictures |
| UserVariables | Name, Initial Value, Description |
Projects add their own fields freely (see Extending).
Variables are keyed by name
Section titled “Variables are keyed by name”Lua only ever says Variable["has_token"]. The variable’s ID is editor
bookkeeping — and ChatMapper XML has no ID attribute on <UserVariable> at
all, so IDs do not survive a JSON → XML → JSON trip. Key variables by
Fields.Name; treat the ID as advisory.
Initial values
Section titled “Initial values”Initial Value is a string that a runtime should coerce: "True"/"False"
(case-insensitive) to boolean, a numeric string to a number, anything else
stays text. The simulator, the HTML player and the reference parser all use
that rule.
Conversations
Section titled “Conversations”A conversation is a directed graph of dialogue nodes — a tree in the common case, but cycles (hubs, loops) and merges are legal and common.
{ "ID": 1, "NodeColor": "White", "Fields": { "Title": "Asking for passage", "Actor": "1", "Conversant": "2", "Primary Location": "1" }, "DialogNodes": [ … ]}IDis unique across conversations.Fields.ActorandFields.Conversantare stringified actor IDs ("2", never"Ferryman").""and"-1"both mean unset. They are defaults that new nodes inherit in the editor; the node’s own values are what a runtime uses.- Exactly one node has
IsRoot: true. Conventionally its ID is0and its title isSTART.
Dialogue nodes
Section titled “Dialogue nodes”A node is one beat: a line, a choice, or a structural group.
| Key | Meaning |
|---|---|
ID | Unique within the conversation. |
ConversationID | Must equal the owning conversation’s ID. |
IsRoot | The start marker. Never spoken, even if it has text. |
IsGroup | Structural: not played; its children are the choice set. |
ConditionsString | Lua expression; empty means always true. |
UserScript | Lua statements run when the node is entered. |
FalseConditionAction | 0/"Block" — drop the node when the condition fails. 1/"Passthrough" — offer its children instead. |
ConditionPriority | 1 High … 5 Low, 3 Normal. Lower wins. |
DelaySimStatus | Hold the node’s status update until the next choice set is built. |
NodeColor | Canvas tint, a name ("Green") or the legacy integer. |
Fields | The text and metadata below. |
OutgoingLinks | Links out of this node. |
Node fields
Section titled “Node fields”| Field | Meaning |
|---|---|
Title | Author-facing label. Never shown to players. |
Actor | Stringified actor ID — who speaks. |
Conversant | Stringified actor ID — who is spoken to. |
Dialogue Text | The spoken line. |
Menu Text | Present ⇒ this node is a player choice; the value is the button label. Absent ⇒ the node plays automatically. |
Parenthetical | Delivery note (wearily). |
Audio Files, Video File, Animation Files, Pictures | Media references. |
The distinction that matters most: Dialogue Text is what is spoken;
Menu Text is what appears on a choice button. A player-choice node
usually has both — the button label and what the player then says — and they
are often the same string.
Media fields
Section titled “Media fields”Audio Files, Animation Files and Pictures are lists, serialised as
a bracketed, semicolon-separated string: "[intro_01.mp3;intro_02.mp3]".
Empty is "[]". Video File is a single reference. References are
filenames (or URLs); the files themselves are delivered separately, or
inside a CMPKG.
Audio pairs with sentence splits by position: a line
"One.|Two." with "[a.mp3;b.mp3]" plays a.mp3 over One. and b.mp3
over Two.
Localised text
Section titled “Localised text”Additional languages are stored as extra fields on the node, titled with the
locale: a de-DE translation of Dialogue Text lives in a field titled
de-DE (the Desktop convention), and a translated Menu Text in
Menu Text de-DE. The project’s _editor.languages lists the locales the
editor knows about; a runtime can also discover them by scanning field titles
that look like locales.
Links live on the origin node and name their destination by conversation and node ID:
{ "Filename": null, "OriginConvoID": 1, "DestinationConvoID": 1, "OriginDialogID": 3, "DestinationDialogID": 5 }OriginConvoID/OriginDialogIDmust match the node the link sits on.DestinationConvoIDmay name a different conversation — a cross-conversation jump, fully supported.Filenameis non-null only for a link into a different project file. Most hosts, including Unity’s Dialogue System, cannot follow those; leave itnull.
Link order on a node is menu order.
Node colours
Section titled “Node colours”Canonical form is the name; the integer is the legacy Desktop enum and is accepted on read.
| Name | Legacy int |
|---|---|
Red | 0 |
Orange | 1 |
Yellow | 2 |
Green | 3 |
LightBlue | 4 |
DarkBlue | 5 |
Pink | 6 |
Purple | 7 |
White | (none — the serialised default) |
_editor
Section titled “_editor”One top-level object for editor-only metadata: canvas positions, layout direction, collapsed subtrees, custom field templates and per-field type hints, extra languages, reviewer notes and review status. It is stripped from interchange exports and any consumer may ignore it. Never put anything there that the project’s meaning depends on. Details in Extending the format.
Identity and ordering
Section titled “Identity and ordering”- Conversation IDs are global; node IDs are per conversation. A node is
addressed by the pair
(ConversationID, ID). - Asset IDs are per collection: actor 1 and item 1 are unrelated.
DialogNodesorder is document order and carries no meaning; link order does.
- JSON format — the normative spec with a complete example.
- Runtime semantics — what to do with all this at play time.