Line IDs in all dialogue and monologue pool files renamed from the old location-scoped format (e.g. the-terminal_d_039) to the new NPC-scoped format (e.g. kael-davan_d_001) per the D-035 Sprint 15 amendment. Changes: - 20 dialogue pool files across 3 locations renamed - 14 monologue pool files (detective + smuggler) renamed - Schema descriptions updated in dialogue/monologue schema files - Authoring style guide and design docs updated with new examples - Multi-location NPCs (kael-davan, pc-detective, pc-smuggler) given globally unique cross-file sequences to satisfy XREF uniqueness check The location-scoped scheme already caused a collision (the-terminal_d_039 appearing in multiple NPC files) and would not scale to procedurally generated NPC populations (D-029). Zero content changes — pure ID substitution. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
230 lines
8.2 KiB
JSON
230 lines
8.2 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "monologue-pool.schema.json",
|
|
"title": "Monologue Line Pool",
|
|
"description": "Tagged monologue lines, hard-partitioned by character (D-032, D-035). Monologue lines carry all 6 D-035 structural tags for schema compliance, but role/access/trust are fixed constants for player-character internal voice (role=player_character, access=[public], trust=surface). The engine does not gate monologue on access or trust — these tags exist for taxonomy uniformity only.",
|
|
"type": "object",
|
|
"required": ["character", "location", "lines"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"character": {
|
|
"type": "string",
|
|
"enum": ["smuggler", "detective"],
|
|
"description": "Playable character this pool belongs to (hard partition per D-032). All lines in this pool belong to this character."
|
|
},
|
|
"location": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9-]*$",
|
|
"description": "Location slug, or 'general' for location-independent lines."
|
|
},
|
|
"lines": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/monologue_line" },
|
|
"minItems": 1
|
|
}
|
|
},
|
|
"$defs": {
|
|
"monologue_line": {
|
|
"type": "object",
|
|
"required": ["id", "text", "role", "access", "trust", "situation", "trigger"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"pattern": "^[a-z][a-z0-9-]*_m_[sd]_[0-9]{3}$",
|
|
"description": "Stable line ID: {npc-slug}_m_{s|d}_{###} (e.g. pc-smuggler_m_s_001, pc-detective_m_d_001). s = smuggler, d = detective. NPC-scoped per D-035 Sprint 15 amendment — each NPC has an independent sequence starting at _001."
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 256,
|
|
"description": "Line text — 256 char hard cap, aim for ≤160 to avoid line wrap"
|
|
},
|
|
"role": {
|
|
"type": "string",
|
|
"const": "player_character",
|
|
"description": "D-035 structural tag — always player_character for monologue. Monologue is the player character's internal voice."
|
|
},
|
|
"access": {
|
|
"type": "array",
|
|
"items": { "const": "public" },
|
|
"minItems": 1,
|
|
"maxItems": 1,
|
|
"description": "D-035 structural tag — always [public] for monologue. No access gating applies to internal voice."
|
|
},
|
|
"trust": {
|
|
"type": "string",
|
|
"const": "surface",
|
|
"description": "D-035 structural tag — always surface for monologue. No trust gating applies to internal voice."
|
|
},
|
|
"situation": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"enum": [
|
|
"arrival",
|
|
"shift_start",
|
|
"shift_end",
|
|
"shift_transition",
|
|
"bar_evening",
|
|
"night_shift",
|
|
"investigation",
|
|
"confrontation",
|
|
"social",
|
|
"alone",
|
|
"emergency",
|
|
"routine",
|
|
"observation",
|
|
"greeting"
|
|
]
|
|
},
|
|
"minItems": 1,
|
|
"uniqueItems": true,
|
|
"description": "D-035 structural tag: situations in which this monologue line is contextually appropriate. 14 v0.1 values. The engine selects using trigger; situation provides additional authoring context for filtering by the caller. NOTE: 'greeting' is not yet in server/src/content/line_pool.rs Situation enum."
|
|
},
|
|
"trigger": {
|
|
"type": "string",
|
|
"enum": [
|
|
"enter_location",
|
|
"observe_npc",
|
|
"hear_sound",
|
|
"observe_anomaly",
|
|
"post_conversation",
|
|
"discover_evidence",
|
|
"witness_interaction",
|
|
"time_idle",
|
|
"return_visit"
|
|
],
|
|
"description": "What causes this line to fire. 9 v0.1 trigger types (D-035 monologue-specific tag)."
|
|
},
|
|
"prerequisites": {
|
|
"description": "Knowledge state gate (D-035 monologue-specific tag). null or omitted = unconditional. Conditions are AND-evaluated. Uses FactIds from the knowledge vocabulary (#368, D-041).",
|
|
"oneOf": [
|
|
{ "type": "null" },
|
|
{
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"facts": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/fact_prerequisite" }
|
|
},
|
|
"entity_attributes": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/attribute_prerequisite" }
|
|
},
|
|
"relationship": {
|
|
"type": "object",
|
|
"required": ["target", "state"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"target": { "type": "string" },
|
|
"state": {
|
|
"type": "string",
|
|
"enum": ["unknown", "known", "friendly", "person_of_interest", "hostile"]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"topic": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"enum": [
|
|
"colleague",
|
|
"routine",
|
|
"cargo",
|
|
"money",
|
|
"trust",
|
|
"danger",
|
|
"institution",
|
|
"personal",
|
|
"investigation"
|
|
]
|
|
},
|
|
"uniqueItems": true,
|
|
"description": "D-035 selection tag: topic tags for weighted selection. 9 v0.1 values. Optional."
|
|
},
|
|
"mood": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"enum": [
|
|
"anxious",
|
|
"frustrated",
|
|
"content",
|
|
"suspicious",
|
|
"warm",
|
|
"hostile",
|
|
"relieved",
|
|
"focused"
|
|
]
|
|
},
|
|
"uniqueItems": true,
|
|
"description": "D-035 selection tag: mood tags for weighted selection. 8 v0.1 values, renamed Sprint 14 to match voice guide vocabulary. Neutral = untagged."
|
|
},
|
|
"priority": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 10,
|
|
"default": 5,
|
|
"description": "Selection priority (higher = more likely to fire when multiple lines are eligible). Default: 5."
|
|
},
|
|
"cooldown": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"default": 0,
|
|
"description": "Minimum simulation ticks before this line can fire again. Default: 0."
|
|
},
|
|
"tags": {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"description": "D-035 selection tag: freeform tags. Not consumed by the selection pipeline."
|
|
},
|
|
"dual_lens": {
|
|
"type": "object",
|
|
"description": "Authoring-only: notes on how this line reads differently for smuggler vs detective. NOT consumed by engine.",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"smuggler": { "type": "string" },
|
|
"detective": { "type": "string" }
|
|
}
|
|
},
|
|
"notes": {
|
|
"type": "string",
|
|
"description": "Authoring-only: freeform author notes. NOT consumed by engine."
|
|
}
|
|
}
|
|
},
|
|
"fact_prerequisite": {
|
|
"type": "object",
|
|
"required": ["fact_id", "min_confidence"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"fact_id": {
|
|
"type": "string",
|
|
"description": "FactId from the knowledge vocabulary (#368, D-041)."
|
|
},
|
|
"min_confidence": {
|
|
"type": "string",
|
|
"enum": ["suspects", "knows_of", "knows_details", "direct"],
|
|
"description": "Minimum D-041 confidence level required."
|
|
}
|
|
}
|
|
},
|
|
"attribute_prerequisite": {
|
|
"type": "object",
|
|
"required": ["entity", "key", "value"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"entity": { "type": "string" },
|
|
"key": { "type": "string" },
|
|
"value": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
}
|