Files
zeling_v2/Docs/DesignSpec/14_NarrativeSystem.md
2026-05-08 11:04:00 +08:00

7.0 KiB
Raw Permalink Blame History

14 · 叙事系统规范

所属文档集 ← 返回索引
摘要对话系统、世界标记、NPC 状态管理与三结局触发逻辑。


目录

  1. 叙事设计原则
  2. 对话系统
  3. 世界标记系统
  4. NPC 状态管理
  5. 任务系统
  6. 结局触发系统
  7. 叙事事件目录

1. 叙事设计原则

原则 说明
环境叙事优先 通过场景、图鉴和道具描述讲述故事,减少强制对话
非线性探索 玩家可按任意顺序解锁叙事内容
状态感知 NPC 的对话随玩家进程改变(不重复同一句话)
数据驱动 所有对话树、条件和触发均为数据,不硬编码

2. 对话系统

2.1 对话数据模型

DataModel DialogueData {
    dialogueId      : ID
    speakerId       : ID                  // NPC ID 或 "player"
    ──────────────────────────────────
    nodes           : List<DialogueNode>
    entryNodeId     : ID                  // 起始节点
}

DataModel DialogueNode {
    nodeId          : ID
    type            : DialogueNodeType    // Text / Choice / Condition / Action
    ──────────────────────────────────
    // type = Text:
    text            : Optional<String>    // 支持本地化 Key
    portrait        : Optional<PortraitID>
    nextNodeId      : Optional<ID>        // null = 对话结束

    // type = Choice:
    choices         : Optional<List<DialogueChoice>>

    // type = Condition:
    condition       : Optional<DialogueCondition>
    trueNodeId      : Optional<ID>
    falseNodeId     : Optional<ID>

    // type = Action:
    action          : Optional<DialogueAction>
    nextNodeId      : Optional<ID>
}

DataModel DialogueChoice {
    choiceText      : String
    nextNodeId      : ID
    availableCondition: Optional<DialogueCondition>  // null=始终显示
}

2.2 对话条件类型

DataModel DialogueCondition {
    conditionType   : DialogueConditionType
    targetId        : Optional<ID>
    value           : Optional<Number>
}
条件类型 说明
HasAbility 玩家已解锁某能力
HasItem 玩家持有某物品
WorldFlagTrue 某世界标记为 true
QuestStageIs 某任务处于指定阶段
BossDefeated 某 Boss 已被击败
FirstVisit 玩家第一次和此 NPC 对话

2.3 对话动作类型

动作类型 说明
SetWorldFlag 设置世界标记
GiveItem 给予物品
GiveGeo 给予 Geo
UnlockAbility 解锁能力
AdvanceQuest 推进任务阶段
PlayCutscene 播放过场动画

3. 世界标记系统

3.1 世界标记规范

WorldFlags: Map<String, Boolean>
  • 存储于 ProgressionSaveData.worldFlags
  • Key 为字符串,建议命名格式:区域_事件_描述(如 region1_boss_firstEncounter
  • 标记只能设为 true不支持撤销设计保证单向性
  • 叙事系统、门控系统、AI 系统均可读取世界标记

3.2 设置世界标记的来源

来源 说明
对话动作 SetWorldFlag 对话选择/到达某节点时触发
门控开启 某些门控开启时自动设置
Boss 死亡 OnBossDefeated 事件触发时自动设置
收集品拾取 特定关键收集品触发
手动触发器 场景中的触发区域触碰时

4. NPC 状态管理

4.1 NPC 数据模型

DataModel NPCData {
    npcId           : ID
    displayName     : String
    ──────────────────────────────────
    locations       : List<NPCLocationEntry>  // NPC 在不同阶段的位置
    dialogueVersions: List<NPCDialogueVersion> // 不同进程阶段的对话
}

DataModel NPCLocationEntry {
    condition       : Optional<DialogueCondition>  // 满足时位于此处null=默认)
    roomId          : ID
    position        : Vector2
}

DataModel NPCDialogueVersion {
    condition       : Optional<DialogueCondition>  // 满足时使用此对话null=默认)
    dialogueId      : ID
    priority        : Integer   // 多个条件同时满足时取最高优先级
}

4.2 对话版本选取规则

玩家与 NPC 交互时:

  枚举 NPCData.dialogueVersions按 priority 降序)
  → 找第一个 condition 满足(或 condition 为 null的版本
  → 使用该版本的 dialogueId 开始对话

  若无任何版本满足 → 使用默认兜底对话("......"

5. 任务系统

5.1 任务数据模型

DataModel QuestData {
    questId         : ID
    displayName     : String
    description     : String
    ──────────────────────────────────
    stages          : List<QuestStageData>
    rewardOnComplete: Optional<QuestReward>
}

DataModel QuestStageData {
    stageIndex      : Integer
    description     : String
    completionCondition: DialogueCondition  // 推进到下一阶段的条件
}

DataModel QuestReward {
    geoAmount       : Optional<Integer>
    itemIds         : List<ID>
    abilityId       : Optional<ID>
    worldFlagsToSet : List<String>
}

6. 结局触发系统

6.1 结局条件回顾

(详细条件见 09_ProgressionSystem.md 第 5 节)

结局 类型 核心条件
结局 A 普通 击败最终 Boss
结局 B 完全 Boss 全清 + 主线剧情完整 + 关键 NPC 任务
结局 C 隐藏 结局 B + 隐藏世界标记序列激活

6.2 结局判定流程

最终 Boss 死亡时:

  检查结局 C 条件(最严格)
  ├─ 满足 → 触发结局 C
  └─ 不满足 →

    检查结局 B 条件
    ├─ 满足 → 触发结局 B
    └─ 不满足 → 触发结局 A

触发结局 X:
  → 发出 OnEndingTriggered 事件endingType
  → 播放对应过场动画序列
  → 记录到 SaveDataendingUnlocked
  → 游戏结束流程

7. 叙事事件目录

事件 触发时机 载荷
OnDialogueStarted 开始对话 dialogueId, npcId
OnDialogueNodeReached 到达对话节点 nodeId
OnDialogueChoiceMade 玩家做出选择 choiceIndex, nextNodeId
OnDialogueEnded 对话结束 dialogueId
OnWorldFlagSet 世界标记变更 flagKey
OnQuestStarted 任务开始 questId
OnQuestAdvanced 任务推进 questId, newStage
OnQuestCompleted 任务完成 questId
OnEndingTriggered 结局触发 endingType
OnCutsceneStarted 过场动画开始 cutsceneId
OnCutsceneEnded 过场动画结束 cutsceneId