Files
Genarrative/docs/technical/M4_MODULE_NPC_COMBAT_ORCHESTRATION_BASELINE_2026-04-21.md
kdletters cbc27bad4a
Some checks failed
CI / verify (push) Has been cancelled
init with react+axum+spacetimedb
2026-04-26 18:06:23 +08:00

4.6 KiB
Raw Blame History

M4 module-npc 与 module-combat 联合编排基线2026-04-21

更新时间:2026-04-22

0. 文档目标

本文件只冻结一件事:

在不污染 module-npc 纯领域边界的前提下,把 npc_fight / npc_spar 从“只返回 BattlePending 语义”推进到“可在 spacetime-module 聚合层同步创建 battle_state”的最小联合编排口径。

这不是完整 resolve_story_action 设计,也不是完整战斗奖励编译、经验预算和剧情续写迁移。


1. 本轮落地范围

本轮只落实下面 4 件事:

  1. 明确 module-npc 继续只负责 NPC 交互语义,不直接依赖 module-combat
  2. spacetime-module 聚合层新增 resolve_npc_battle_interaction_and_return procedure。
  3. 让该 procedure 在同一事务内完成:
    • resolve_npc_interaction
    • battle_state 初始化写入
  4. 返回统一结果,供后续 spacetime-client / Axum facade 直接消费。

2. 为什么不把 battle 初始化塞进 module-npc

原因很直接:

  1. module-npc 当前职责是 npc_state / relation_state / stance_profile / interaction contract
  2. battle_state 属于 module-combat 真相,不应倒灌进 NPC 领域 crate。
  3. 如果把玩家 HP / MP、战斗生命、故事会话 ID 这些字段直接塞进 ResolveNpcInteractionInput,会把 module-npc 再次膨胀成跨子域入口。

因此本轮明确冻结为:

  1. module-npc
    • 继续只返回 BattlePending + battle_mode
  2. spacetime-module
    • 负责把 NPC 交互结果编排成真正的 battle_state

3. 新增 procedure 口径

3.1 名称

新增:

  1. resolve_npc_battle_interaction_and_return

3.2 输入

首版输入冻结为:

  1. npc_interaction
    • 原样复用 ResolveNpcInteractionInput
    • 当前只允许 npc_fight / npc_spar
  2. story_session_id
  3. actor_user_id
  4. battle_state_id
    • 允许为空
    • 为空时按 updated_at_micros 自动派生
  5. player_hp
  6. player_max_hp
  7. player_mana
  8. player_max_mana
  9. target_hp
  10. target_max_hp
  11. experience_reward
    • 由上游作为已编译好的确定奖励透传
    • 当前允许为 0
  12. reward_items
    • 类型固定为 Vec<module-runtime-item::RuntimeItemRewardItemSnapshot>
    • 只承接已经编译好的战利品快照,不在 procedure 内现场生成

3.3 输出

当前返回:

  1. interaction
    • module-npc::NpcInteractionResult
  2. battle_state
    • module-combat::BattleStateSnapshot

也就是说,这个 procedure 明确是一个聚合返回口径,不是新的底层领域真相。


4. 当前事务流程

单次调用按下面顺序执行:

  1. 校验 story_session_id / actor_user_id
  2. 校验 interaction_function_id 必须是:
    • npc_fight
    • npc_spar
  3. 先执行 resolve_npc_interaction_record
    • 写入最新 npc_state
    • 拿到 NpcInteractionResult
  4. NpcInteractionResult.battle_mode 映射出 BattleMode
  5. 组装 BattleStateInput
    • 透传 experience_reward
    • 透传 reward_items
  6. 复用 module-combatvalidate_battle_state_input
  7. 插入 battle_state
  8. 返回:
    • interaction
    • battle_state

5. 当前刻意未做

本轮明确不做下面这些扩张:

  1. 不在这个 procedure 里直接发经验
  2. 不在这个 procedure 里直接记 chapter_progression
  3. 不在这个 procedure 里直接写 story_event
  4. 不在这个 procedure 里现场计算掉落或经验预算
  5. 不在这个 procedure 里直接执行 inventory_slot 发物
  6. 不在这个 procedure 里直接接 resolve_combat_action
  7. 不在这个 procedure 里推导敌方等级、强度、掉落预算

也就是说,这一层当前只解决:

NPC 宣告开战后,如何立刻把 battle 真相表连同已编译奖励真相一起建立起来。


6. 与现有文档的关系

本文件是对下面两份基线文档的补充,而不是替代:

  1. M4_MODULE_NPC_SPACETIMEDB_BASELINE_2026-04-21.md
    • 继续定义 NPC 领域 contract
  2. M4_MODULE_COMBAT_SPACETIMEDB_BASELINE_2026-04-21.md
    • 继续定义 battle_state 与单行为战斗推进规则

新增编排只发生在 spacetime-module 聚合层。


7. 下一步建议

在这条最小联合编排稳定后,后续按下面顺序推进最稳:

  1. 把 Node 侧 monster_drop / hostile reward 编译逻辑收口到 Rust 聚合层。
  2. 再把章节自动定级、敌对经验预算和 chapter_progression 所需章节上下文收口进 battle 初始化编译器。
  3. 最后把这条链收口进完整 resolve_story_action