初始仓库迁移
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-04 23:57:06 +08:00
parent 80986b790d
commit c49c64896a
18446 changed files with 532435 additions and 2 deletions

View File

@@ -0,0 +1,637 @@
# AI 角色形象与角色动画 MVP PRD
更新时间:`2026-04-04`
## 0. 一句话结论
本次 MVP 要做的不是一个泛化的“AI 动画平台”,而是一个能直接服务当前项目角色资产生产的最小闭环:
1. 用户先输入角色形象设定并上传参考图,或直接上传现成角色素材
2. 系统生成或规范化出一张**符合当前游戏侧视角色素材视角**的主形象图
3. 用户确认主形象后,再为该角色生成与当前项目可扮演角色动作槽位匹配的基础动作集
4. 用户可预览、重新生成,并最终发布为当前仓库可直接读取的角色资产
一句话说:
**MVP 先解决“怎么稳定产出能进游戏的角色主形象和基础动作”,而不是先追求所有技能动作和复杂演出。**
---
## 1. 背景
当前仓库已经有:
- 可扮演角色与角色型 NPC
- `CharacterAnimator` 运行时播放链路
- 角色预设与 override 机制
- 本地 API 插件机制
- NPC 静态形象编辑器
但当前缺少一条可用的角色资产生产链:
1. 角色主形象仍依赖手工素材整理
2. 动作资产缺少“从角色设定到可播放动作集”的编辑器闭环
3. 没有把“AI 生成结果”稳定沉淀为当前项目的标准角色资源
因此本期 MVP 的目标不是重做运行时战斗系统,而是补齐:
- 主形象生产
- 基础动作生产
- 预览与重新生成
- 发布到现有角色资源体系
---
## 2. MVP 要解决的问题
## 2.1 用户侧问题
当前如果想给项目新增一个角色,成本很高:
- 要先准备适合当前游戏视角的主形象
- 再补动作资源
- 还要手工整理资源目录和配置
MVP 要把这件事改成一个编辑器工作流。
## 2.2 项目侧问题
当前项目并不适合把 AI 直接放进运行时实时生成动作,因为:
- 运行时需要稳定、可回放、可测试的资源
- 战斗和剧情都依赖固定动作槽位
- 生成结果如果不资产化,会让维护成本失控
所以 MVP 的正确方向是:
**把 AI 用在编辑器里的资产生产链,而不是运行时即时生成。**
---
## 3. MVP 目标
## 3.1 产品目标
提供一个最小可用的“角色资产工坊”,满足以下闭环:
1. 生成或上传角色主形象
2. 预览并重选角色主形象
3. 基于主形象生成基础动作
4. 预览并重选动作结果
5. 发布为当前项目可直接使用的角色资源
## 3.2 技术目标
MVP 必须满足:
1. 只依赖国内可用模型与服务
2. 只生成当前项目能消费的标准资产
3. 不改动现有战斗规则与剧情规则
4. 生成结果必须走本地后处理与发布流程
5. 运行时只读本地标准化资产
## 3.3 成功标准
当以下条件同时成立时,视为 MVP 成功:
1. 编辑器里可以完成“主形象 -> 基础动作 -> 发布”闭环
2. 发布后的角色能被当前 `CharacterAnimator` 播放
3. 基础动作槽位不存在空映射
4. 用户可以对主形象和动作分别进行重新生成
---
## 4. 非目标
本期不做:
1. 不做运行时实时动画生成
2. 不做怪物动画生成链路
3. 不做通用 NPC 群像流水线
4. 不做技能动作全自动补齐
5. 不做批量生产多个角色的自动流水线
6. 不做多供应商路由调度
说明:
- 本期只先做好**单角色、单次编辑器操作**的最小闭环
- 技能动作可后续补,但**基础动作槽位不能为空**
---
## 5. 目标用户与使用场景
## 5.1 目标用户
- 项目策划
- 项目美术 / 技术美术
- 负责角色内容生产的开发者
## 5.2 核心使用场景
### 场景 A新建角色
用户输入角色设定词、参考图,生成当前项目风格可用的主形象和基础动作。
### 场景 B已有角色素材导入
用户已有一张角色图,希望快速裁切、规范化,并继续生成基础动作。
### 场景 C已有角色动作质量不满意
用户不改主形象,只重新生成单个或多个动作槽位。
---
## 6. MVP 用户流程
## 6.1 阶段 A主形象生成 / 导入
1. 用户选择角色
2. 输入角色形象设定文本
3. 上传角色参考图,或直接上传现成角色素材
4. 系统做尺寸、裁剪、构图校验
5. 提交生成或规范化任务
6. 返回多个候选预览图
7. 用户可:
- 预览
- 重新生成
- 设为当前主形象
## 6.2 阶段 B基础动作生成
1. 用户基于已确认主形象进入动作页
2. 系统展示当前基础动作槽位状态
3. 用户选择:
- 直接使用动作模板
- 上传参考动作视频
4. 提交动作生成任务
5. 生成完成后进入动作预览
6. 用户可:
- 保留结果
- 重新生成单动作
- 替换当前动作
## 6.3 阶段 C发布
只有在基础动作槽位全部有有效资源时,才允许发布。
发布后:
1. 写入主形象资源
2. 写入动画资源
3. 生成 manifest
4. 更新角色 override / 映射关系
---
## 7. 主形象阶段需求
## 7.1 输入方式
MVP 支持三种主形象输入方式:
1. 文生图
- 用户输入形象设定
2. 图生图
- 用户输入形象设定并上传参考图
3. 直接上传素材
- 用户上传已有角色图,不强制重新生成
## 7.2 视角要求
主形象必须贴近当前项目现有角色素材体系:
- 2D 侧视动作素材视角
- 单人全身
- 人物朝向右侧
- 脚底完整可见
- 武器和关键轮廓完整
- 不做正面立绘
- 不做强透视镜头
这是硬约束,不是美术建议。
原因:
- 当前项目运行时通过镜像处理左右朝向
- 如果主形象不是侧视动作素材视角,后续动作生成和运行时挂接都会失真
## 7.3 尺寸与裁剪要求
推荐规格:
- 推荐输入:`1024x1536`
- 可接受比例:`2:3``3:4`
- 最低建议:短边 `>= 768`
- 统一输出标准图:`1024x1536`
构图要求:
- 角色主体占画面高度约 `70% ~ 85%`
- 头顶保留少量留白
- 脚底必须完整露出
- 背景尽量简单
- 只允许单角色
## 7.4 主形象阶段交互要求
用户必须可以:
- 查看候选结果
- 放大预览
- 丢弃某个候选
- 基于同样输入重新生成
- 选择一个候选作为主形象
用户不能直接跳过主形象确认进入动作阶段,除非已经锁定主形象。
---
## 8. 动作阶段需求
## 8.1 基础动作槽位要求
MVP 必须与当前项目可扮演角色动作槽位对齐。
第一版要求以下基础动作槽位不能为空:
| 动作槽位 | 是否必填 | 备注 |
| --- | --- | --- |
| `idle` | 必填 | 循环动作 |
| `acquire` | 必填 | 可由短变体衍生 |
| `attack` | 必填 | 一次性动作 |
| `run` | 必填 | 循环动作 |
| `jump` | 必填 | 一次性动作 |
| `double_jump` | 必填 | 可由跳跃二次变体生成 |
| `jump_attack` | 必填 | 一次性动作 |
| `dash` | 必填 | 一次性动作 |
| `hurt` | 必填 | 一次性动作 |
| `die` | 必填 | 一次性动作 |
| `climb` | 必填 | 可由模板生成 |
| `wall_slide` | 必填 | 可由攀爬停帧变体生成 |
这里“不能为空”指的是:
- 每个槽位必须最终指向一套可播放的资源
- 允许少量槽位由近似动作衍生
- 但不允许在运行时读到空动画映射
## 8.2 技能动作要求
本期不要求自动补齐:
- `skill1`
- `skill1_jump`
- `skill1_bullet`
- `skill1_bullet_fx`
- `skill2`
- `skill2_jump`
- `skill3`
- `skill3_jump`
- `skill3_bullet`
- `skill3_bullet_fx`
- `skill4`
结论:
- 技能动作本期可选
- 基础动作本期必做
## 8.3 动作生成方式
MVP 支持两种方式:
1. 模板动作生成
- 用户选择动作模板
2. 参考视频驱动
- 用户上传参考动作视频
优先级:
- 基础动作优先走模板
- 个性化动作再用参考视频驱动
## 8.4 动作阶段交互要求
用户必须可以:
- 查看每个动作槽位当前状态
- 单独预览某个动作
- 单独重新生成某个动作
- 保留某些已满意动作,只重生其余动作
- 在所有基础动作齐全后再发布
---
## 9. 生成策略约束
## 9.1 角色一致性优先
动作生成阶段只能使用已锁定的主形象,不允许每个动作重新随机生成角色外观。
## 9.2 首尾帧控制
参考用户提供的视频方向MVP 固化以下策略:
### 循环动作
- `idle`
- `run`
要求首尾姿态尽量接近,便于循环。
### 一次性动作
- `attack`
- `jump_attack`
- `hurt`
- `die`
要求末帧清晰,不与下一动作切换冲突。
## 9.3 高分辨率生成,低分辨率落地
MVP 不要求模型直接输出最终像素逐帧。
正确流程是:
1. 生成较稳定的高分辨率动作视频
2. 本地解帧、对齐、清理
3. 再转成当前项目可用的像素化资产
---
## 10. 技术方案边界
## 10.1 模型选择
MVP 统一采用国内可用的阿里云百炼方案:
- 主形象生成:`wan2.7-image-pro` / `wan2.7-image`
- 动作生成:`wan2.2-animate-move`
- 高质量换角动作:`wan2.2-animate-mix`
选择理由:
1. 国内可用
2. 图像和动作链路在同一平台
3. 便于 MVP 先收敛到单平台实现
## 10.2 本地后处理
MVP 必须包含本地后处理:
1. 解帧
2. 主体裁切
3. 背景清理
4. 稳帧
5. 像素化
6. 打包 Sprite Sheet
7. 输出 manifest
## 10.3 运行时边界
运行时不直接请求第三方模型接口。
运行时只读取:
- 主形象标准资源
- 动画标准资源
- override / manifest 配置
---
## 11. MVP 数据与接口
## 11.1 角色主形象资源
建议最小结构:
```ts
type GeneratedCharacterVisualAsset = {
id: string;
characterId: string;
sourceMode: 'text-to-image' | 'image-to-image' | 'upload';
masterImagePath: string;
previewImagePaths: string[];
width: number;
height: number;
facing: 'right';
locked: boolean;
};
```
## 11.2 角色动画资源
```ts
type GeneratedCharacterAnimationAsset = {
id: string;
characterId: string;
visualAssetId: string;
action: string;
frameCount: number;
fps: number;
loop: boolean;
spriteSheetPath: string;
framePaths: string[];
previewVideoPath: string;
};
```
## 11.3 最小接口
建议新增:
- `POST /api/character-visual/jobs`
- `GET /api/character-visual/jobs/:id`
- `POST /api/character-visual/publish`
- `POST /api/animation/jobs`
- `GET /api/animation/jobs/:id`
- `GET /api/animation/templates`
- `POST /api/animation/publish`
职责:
### `POST /api/character-visual/jobs`
- 创建主形象生成或规范化任务
### `GET /api/character-visual/jobs/:id`
- 查询主形象任务状态与结果
### `POST /api/character-visual/publish`
- 锁定主形象并写入主形象 manifest
### `POST /api/animation/jobs`
- 创建动作生成任务
### `GET /api/animation/jobs/:id`
- 查询动作任务状态与结果
### `GET /api/animation/templates`
- 返回动作模板列表
### `POST /api/animation/publish`
- 发布动作资源并更新动画映射
---
## 12. 与当前仓库的接入点
第一批建议接入:
- `src/components/CharacterAnimator.tsx`
- `src/types/characters.ts`
- `src/data/characterOverrides.json`
- `scripts/dev-server/localApiPlugins.ts`
建议新增:
- `src/components/CharacterAssetStudio.tsx`
- `src/data/characterAnimationOverrides.json`
- 角色主形象 manifest 读取逻辑
- 动画 manifest 读取逻辑
运行时优先级建议:
1. 角色 AI 生成动画 override
2. 角色原始 `animationMap`
3. 默认回退动画
---
## 13. 验收标准
## 13.1 主形象验收
1. 用户可以通过文生图 / 图生图 / 直接上传素材三种方式得到主形象
2. 主形象视角符合当前项目侧视角色素材要求
3. 主形象可预览、可重新生成、可锁定
## 13.2 动作验收
1. 所有基础动作槽位均有有效资源
2. 用户可以单独预览和重新生成某个动作
3. 发布后动作能被当前 `CharacterAnimator` 播放
## 13.3 资产验收
1. 发布后可生成主形象资源目录
2. 发布后可生成动画资源目录
3. 可生成对应 manifest / override 映射
## 13.4 体验验收
1. 用户不需要手工整理最终资源目录
2. 用户不需要每次都从头重做全部动作
3. 主形象和动作两阶段都可回看和重生
---
## 14. 风险与对策
## 14.1 风险:主形象视角不稳定
对策:
- 把“侧视、朝右、全身、脚底完整”作为硬校验
- 不合格结果不允许直接进入动作阶段
## 14.2 风险:动作循环不自然
对策:
- `idle``run` 强制使用循环模板优先
- 引入首尾帧接近度校验
## 14.3 风险基础动作槽位过多MVP 开发压力大
对策:
- 允许 `acquire``double_jump``wall_slide` 等少数槽位由近似动作衍生
- 但运行时最终槽位仍必须非空
## 14.4 风险:生成成本过高
对策:
- 先只支持单角色编辑
- 基础动作优先模板化
- 仅对不满意动作单独重生
---
## 15. MVP 开发顺序
## 阶段 1主形象闭环
目标:
- 跑通主形象生成 / 上传 / 预览 / 锁定
产出:
- `CharacterAssetStudio` 的主形象页
- 主形象任务 API
- 主形象 manifest
## 阶段 2基础动作闭环
目标:
- 跑通单动作生成、预览与替换
产出:
- 动作任务 API
- 动作模板列表
- 预览与重新生成流程
## 阶段 3基础动作补齐与发布
目标:
- 让基础动作槽位全部非空,并可一键发布
产出:
- 动作状态面板
- 发布逻辑
- override / manifest 写入
## 阶段 4运行时接入
目标:
- 让发布后的角色直接在现有运行时播放
产出:
- `CharacterAnimator` 读取生成动画能力
- 角色 override 映射接入
---
## 16. 最终结论
对当前仓库来说,最可落地的 MVP 不是“先做一个很强的 AI 动画系统”,而是:
1. 先固定角色主形象生产流程
2. 再固定基础动作生产流程
3. 只补能进当前项目运行时的最小动作集
4. 把预览、重新生成和发布做完整
这样做的价值在于:
- 范围可控
- 路径清晰
- 能真正进入当前仓库
- 后续可以在此基础上再加技能动作、剧情演出和多供应商增强路线

View File

@@ -0,0 +1,789 @@
# AI 原生游戏任务系统 PRD
更新时间:`2026-04-02`
## 0. 设计目标
这份方案针对当前仓库,回答的是:
**如果要把现有“接受任务 -> 推进 -> 完成 -> 交付”的轻量任务链路,升级成真正的 AI 原生任务系统,应该怎样设计,才能既让任务更像从当前剧情里长出来,又不把规则、奖励和平衡交给模型失控决定?**
这里的“AI 原生”不是指:
- 让模型随时随地自由生成一个任务标题和奖励
- 让模型直接修改任务状态、数值或掉落
- 让任务系统变成纯文案系统
这里的“AI 原生”指的是:
- AI 负责理解当前故事局面,生成任务语义、动机、话术、阶段转折和关系变化
- 本地规则负责验证任务是否合法、如何推进、何时完成、奖励如何结算、存档如何兼容
- 任务系统不再只是“静态模板挂在 NPC 身上”,而是“从当前局面推导出来的可控任务合约”
一句话总结:
**AI 决定这份任务在叙事上是什么,本地规则决定它在系统上如何成立。**
## 1. 当前系统现状
从当前仓库实现看,任务系统已经有一个可工作的最小闭环:
- `src/data/questFlow.ts`
- 负责构造任务、接受任务、推进任务、完成任务、交付任务
- `src/hooks/story/npcEncounterActions.ts`
- 负责 NPC 交互里的 `quest_accept` / `quest_turn_in`
- `src/hooks/useStoryGeneration.ts`
- 负责在战斗、宝藏、NPC 交互后更新 quest progress
- `src/types/story.ts`
- 当前 `QuestLogEntry` 是运行时任务主结构
- `src/components/AdventurePanel.tsx`
- 负责任务 UI 展示与奖励领取
当前系统已经支持:
1. NPC 提供任务
2. 玩家接受任务
3. 击败怪物 / 调查宝藏 / 与 NPC 切磋 三类目标推进
4. 任务完成后领取奖励
5. 奖励影响货币、背包和 NPC affinity
这说明基础闭环是成立的,问题不在“有没有任务系统”,而在于:
- 当前任务更像“局部规则脚手架”还不是“AI 原生任务系统”
- AI 目前主要参与任务文案氛围和选项重写,没有真正参与任务语义生成
- 任务结构太扁平,无法承载阶段变化、关系转折、后续分支和任务记忆
## 2. 当前系统的核心限制
## 2.1 任务来源仍然偏静态
当前 `buildQuestForEncounter(...)` 的生成逻辑,本质还是:
- 看当前 scene 有没有 hostile npc
- 没有就看 monsterIds
- 再没有就看 treasureHints
- 最后 fallback 到 spar
这套逻辑稳定,但仍然是:
**本地 if/else 在选任务类型AI 只是在外围写故事。**
结果是:
- 任务叙事贴合度有限
- 任务动机比较像通用模板
- 很难让任务明显体现“为什么偏偏是这个 NPC、这个时刻、这个场景、这个玩家”
## 2.2 任务结构只有“单目标单阶段”
当前 `QuestLogEntry.objective` 只有:
- `kind`
- `targetMonsterId`
- `targetNpcId`
- `targetSceneId`
- `requiredCount`
它适合最小任务闭环,但不适合承载:
- 多阶段任务
- 前置调查 -> 中段确认 -> 最终结算
- NPC 关系驱动的任务升级
- 同一任务在不同世界/场景下的变体
- 任务完成方式差异带来的后续影响
## 2.3 任务状态过粗
当前状态只有:
- `active`
- `completed`
- `turned_in`
这会导致任务系统无法表达:
- 已发现但未正式接取
- 已接受但未激活下一阶段
- 已满足隐藏条件但未显式揭示
- 已失败 / 已过期 / 已被替代
- 已分支到不同结局
## 2.4 奖励是固定规则,不随任务语义演化
当前奖励主要由 `buildQuestReward(worldType, roleText)` 生成。
优点:
- 稳定
- 易控
- 好测试
问题:
- 奖励和任务语义绑定弱
- 很难体现“这个 NPC 因为什么给你这份奖励”
- 不能承载 AI 原生任务中更重要的“关系、线索、世界信息、后续机会”
## 2.5 AI 没有任务层专属 contract
当前 `StoryGenerationContext` 很强,但任务相关信息还没有独立建模。于是:
- prompt 里只能把任务作为周边信息描述
- AI 无法明确返回“任务意图”
- 本地也无法验证 AI 给出的任务建议是否合法
这意味着任务系统还没有形成:
**专门面向任务设计的 AI <-> Rule contract**
## 3. 设计原则
## 3.1 AI 负责叙事,本地负责规则
这是本项目已经验证有效的核心边界,这次任务系统继续沿用。
AI 负责:
- 为什么现在出现这份任务
- 任务在关系和剧情上的意义
- 任务目标的话术表达
- 阶段推进时的语义转折
- 奖励在叙事上的来源解释
本地负责:
- 任务是否能生成
- 任务目标类型是否合法
- 可推进事件有哪些
- 任务进度如何累计
- 奖励数值、掉落、affinity、货币如何结算
- 存档结构与兼容
## 3.2 任务必须是“当前局面的产物”
AI 原生任务不应是抽象模板,而应明确绑定:
1. 当前 scene / landmark / threat
2. 当前 NPC 的身份、态度、关系阶段
3. 最近几条 story history
4. 玩家当前状态、build 缺口、队伍关系
5. 当前世界观与 custom world profile
如果一份任务脱离这些上下文也成立那它就还不是“AI 原生任务”。
## 3.3 任务应优先表达“意图”,再编译成“合约”
不要让 AI 直接返回最终 `QuestLogEntry`
更稳的方式是:
1. AI 先返回任务意图 `QuestIntent`
2. 本地把它编译成可执行的 `QuestContract`
3. 再由运行时把 `QuestContract` 映射成 UI 所需的 `QuestLogEntry`
这样能保证:
- AI 足够自由地表达语义
- 本地仍然保留最终裁决权
- 系统容易测试、回放和做 fallback
## 3.4 任务系统必须兼容“AI 不可用”
这个项目所有关键玩法都应该支持 fallback。
所以 AI 原生任务系统必须允许:
- AI 在线时,任务更贴剧情、更像当前局面的自然产物
- AI 离线时,任务仍可退回 deterministic builder
也就是说:
**AI 提升任务质量,但不成为任务闭环的单点故障。**
## 4. 建议的系统分层
建议把新任务系统拆成 5 层。
## 4.1 任务上下文采样层
先从当前运行时抽取一个统一的任务上下文:
```ts
type QuestGenerationContext = {
worldType: WorldType | null;
customWorldProfile?: CustomWorldProfile | null;
currentSceneId?: string | null;
currentSceneName?: string | null;
currentSceneDescription?: string | null;
issuerNpcId?: string | null;
issuerNpcName?: string | null;
issuerNpcContext?: string | null;
issuerAffinity?: number | null;
issuerDisclosureStage?: NpcDisclosureStage | null;
issuerWarmthStage?: NpcWarmthStage | null;
encounterKind?: "npc" | "monster" | "treasure" | "none";
recentStoryMoments: StoryMoment[];
playerCharacter: Character;
playerHp: number;
playerMaxHp: number;
playerMana: number;
playerMaxMana: number;
playerInventory: InventoryItem[];
playerEquipment: EquipmentLoadout;
activeCompanions: CompanionState[];
rosterCompanions: CompanionState[];
currentQuestSummary: Array<{
id: string;
title: string;
status: QuestStatus;
issuerNpcId: string;
}>;
};
```
这一层的目标不是直接生成任务,而是先回答:
**这次任务生成到底发生在什么局面里?**
## 4.2 AI 任务意图层
让 AI 只返回“任务意图”,而不是最终任务实例:
```ts
type QuestIntent = {
narrativeType: "bounty" | "escort" | "investigation" | "retrieval" | "relationship" | "trial";
dramaticNeed: string;
issuerGoal: string;
playerHook: string;
worldReason: string;
recommendedObjectiveKinds: Array<
"defeat_monster" | "inspect_treasure" | "spar_with_npc" | "deliver_item" | "reach_scene" | "talk_to_npc"
>;
urgency: "low" | "medium" | "high";
intimacy: "transactional" | "cooperative" | "trust_based";
rewardTheme: "currency" | "resource" | "relationship" | "intel" | "rare_item";
followupHooks: string[];
};
```
重点是:
- AI 告诉系统这份任务“像什么”
- 不直接决定最终字段值
- 不直接操作运行时状态
## 4.3 本地任务编译层
本地根据 `QuestIntent + QuestGenerationContext` 编译出真正可执行的任务合约:
```ts
type QuestContract = {
id: string;
issuerNpcId: string;
questArchetype: QuestIntent["narrativeType"];
title: string;
description: string;
summary: string;
steps: QuestStep[];
rewards: QuestRewardPackage;
narrativeBindings: QuestNarrativeBinding;
failPolicy: "never" | "leave_scene" | "issuer_hostile" | "time_window";
};
type QuestStep = {
id: string;
kind:
| "defeat_monster"
| "inspect_treasure"
| "spar_with_npc"
| "deliver_item"
| "reach_scene"
| "talk_to_npc";
targetSceneId?: string;
targetNpcId?: string;
targetMonsterId?: string;
targetItemId?: string;
requiredCount: number;
progress: number;
revealText: string;
completeText: string;
};
```
这层的职责是:
- 将 AI 的语义建议裁剪到系统允许的任务范式内
- 确保每一个 step 都能被现有事件流推进
- 给每一个任务生成稳定 id、稳定状态和可存档结构
## 4.4 任务运行时推进层
运行时只认本地任务合约和事件。
建议新增统一的任务推进事件:
```ts
type QuestProgressSignal =
| { kind: "monster_defeated"; sceneId?: string | null; monsterId: string }
| { kind: "treasure_inspected"; sceneId?: string | null }
| { kind: "npc_spar_completed"; npcId: string }
| { kind: "npc_talk_completed"; npcId: string }
| { kind: "scene_reached"; sceneId: string }
| { kind: "item_delivered"; npcId: string; itemId: string; quantity: number };
```
然后统一走:
- `applyQuestProgressSignal(contract, signal)`
而不是继续把推进逻辑分散到多处手写 helper。
这样做的价值是:
- 后续加新任务种类时,只需扩展 signal 与 compiler
- `useStoryGeneration` 只负责发 signal不负责理解具体任务细节
- 测试可以直接覆盖“某信号输入 -> 某任务状态输出”
## 4.5 任务叙事回写层
AI 原生任务真正有价值的一层,不只是“生成任务”,而是“在任务推进时改写故事”。
建议在以下节点允许 AI 回写叙事:
1. 任务生成时
2. 新阶段解锁时
3. 任务完成但未交付时
4. 交付奖励时
5. 完成方式影响关系时
这层应该只接收:
- 已经确定的任务 contract
- 已经发生的规则结果
而不是允许 AI 反向篡改规则结果。
## 5. 建议的数据结构升级
建议不要直接推翻当前 `QuestLogEntry`,而是在现有结构上新增一层 metadata。
## 5.1 新增任务元数据
```ts
type QuestNarrativeBinding = {
origin: "fallback_builder" | "ai_compiled";
narrativeType: "bounty" | "escort" | "investigation" | "retrieval" | "relationship" | "trial";
dramaticNeed: string;
issuerGoal: string;
playerHook: string;
worldReason: string;
followupHooks: string[];
};
type QuestRewardPackage = {
currency: number;
affinityBonus: number;
items: InventoryItem[];
intel?: {
codexEntry?: string;
rumorText?: string;
unlockedSceneId?: string;
};
};
```
## 5.2 扩展现有 QuestLogEntry
```ts
interface QuestLogEntry {
id: string;
issuerNpcId: string;
issuerNpcName: string;
sceneId: string | null;
title: string;
description: string;
summary: string;
objective: LegacyQuestObjective;
progress: number;
status: QuestStatus;
completionNotified?: boolean;
reward: QuestReward;
rewardText: string;
narrativeBinding?: QuestNarrativeBinding;
steps?: QuestStep[];
activeStepId?: string | null;
visibleStage?: number;
hiddenFlags?: string[];
}
```
这样做的原因是:
- UI 可以先继续读旧字段
- 新逻辑逐步切到 `steps`
- 旧存档仍然能兼容
## 5.3 扩展任务状态
建议未来把任务状态扩展为:
```ts
type QuestStatus =
| "discovered"
| "active"
| "ready_to_turn_in"
| "completed"
| "turned_in"
| "failed"
| "expired";
```
MVP 阶段不一定要一次性全上,但至少建议引入:
- `discovered`
- `ready_to_turn_in`
因为 AI 原生任务里,“被感知到”与“正式接取”往往不是同一刻。
## 6. AI 任务 contract 设计
## 6.1 新增专用 prompt contract
建议新增专用任务生成接口,而不是继续把任务生成混在通用 story completion 里。
建议新增:
- `src/services/questDirector.ts`
- `src/services/questPrompt.ts`
- `src/services/questTypes.ts`
AI 返回格式建议如下:
```json
{
"intent": {
"narrativeType": "investigation",
"dramaticNeed": "NPC 怀疑附近遗迹并不安全,但不敢直接深入",
"issuerGoal": "确认遗迹是否值得继续接近",
"playerHook": "玩家当前正好在此地,并且具备应对未知风险的能力",
"worldReason": "最近场景和对话都指向此处存在被掩盖的旧痕迹",
"recommendedObjectiveKinds": ["inspect_treasure", "talk_to_npc"],
"urgency": "medium",
"intimacy": "cooperative",
"rewardTheme": "intel",
"followupHooks": ["遗迹背后的旧势力", "NPC 曾经来过这里"]
}
}
```
重点规则:
- 只允许输出意图,不允许直接输出奖励数值
- 只允许使用本地支持的 objective kinds
- 只描述建议,不越权改状态
## 6.2 AI 负责的字段
AI 可以负责:
- `title` 的语义方向
- `description` 的叙事质感
- `summary` 的自然语言表达
- `dramaticNeed`
- `issuerGoal`
- `playerHook`
- `worldReason`
- `followupHooks`
AI 不负责:
- `id`
- `requiredCount`
- `status`
- `progress`
- `currency`
- `affinityBonus`
- 直接生成超出规则支持范围的 objective
## 6.3 本地编译时的裁决逻辑
本地应当做如下校验:
1. objective kind 是否在 allowlist 内
2. 当前 scene / npc / monster / treasure 是否真的存在
3. 当前 NPC 是否已存在未完成任务
4. 当前任务是否会与现有任务重复或冲突
5. 奖励是否符合 rarity / economy / relationship budget
如果 AI 返回不合法:
- 降级到 deterministic builder
- 但仍可保留 AI 提供的部分叙事字段作为文案参考
## 7. 任务生成时机设计
建议不是每次点 NPC 都无条件生成任务,而是让系统先判断“是否值得生成任务机会”。
## 7.1 建议的触发点
适合生成任务机会的节点:
1. 初次与某 NPC 深入互动
2. 某 NPC affinity 达到新阶段
3. 某场景首次发现异常实体或藏宝线索
4. 某条最近剧情暗示了未解决的局面
5. 玩家在当前区域停留较久且缺少明确目标
## 7.2 不建议触发的节点
以下节点不建议频繁生成任务:
- 每次普通聊天都生成任务
- 每次旅行都自动冒出新任务
- 当前已有多个未完成任务时继续塞新任务
- AI 仅凭最近一句话就突然变出高强度委托
## 7.3 任务机会判断器
建议先做本地 `questOpportunityEvaluator`
```ts
type QuestOpportunity = {
shouldOffer: boolean;
reason: string;
suggestedIssuerNpcId?: string;
suggestedThreatType?: "monster" | "treasure" | "relationship" | "travel";
};
```
这层先判断“该不该生成”,再决定“交给 AI 生成什么”。
这样能避免模型过度产出任务。
## 8. 任务推进设计
## 8.1 从“单字段进度”升级到“步骤机”
当前任务推进是:
- 一个 objective
- 一个 progress
建议升级为:
- 多 step
- 每个 step 自己推进
- active step 决定当前 UI 展示
例如:
```ts
[
{
id: "step_investigate_ruins",
kind: "inspect_treasure",
targetSceneId: "ruins_gate",
requiredCount: 1
},
{
id: "step_report_back",
kind: "talk_to_npc",
targetNpcId: "npc_scholar_lin",
requiredCount: 1
}
]
```
这样任务就能表达:
- 先调查
- 再回报
- 再领取奖励
## 8.2 允许“隐式推进,显式揭示”
AI 原生任务最有意思的一点,是任务可以先发生推进,再在叙事上被揭示。
例如:
- 玩家在探索时先完成了调查
- 回去交谈时 NPC 才明确说出“你已经替我确认了那里的情况”
这意味着系统上应允许:
- step 已完成
-`visibleStage` 仍未切换到下一步,直到触发 reveal
这样任务会更像故事,而不是机械 checklist。
## 9. 奖励设计
## 9.1 奖励不只是一包货币和道具
AI 原生任务里,奖励至少应拆成 4 类:
1. 经济奖励
- currency
- item bundles
2. 关系奖励
- affinity
- disclosure stage / warmth stage 解锁
3. 信息奖励
- rumor
- codex entry
- 场景/势力线索
4. 机会奖励
- 解锁新 scene
- 解锁新 NPC 交互
- 解锁后续任务机会
## 9.2 AI 负责解释奖励来源,不负责定奖励数值
建议奖励设计继续遵守:
- AI 解释“为什么这个 NPC 给这些”
- 本地决定“究竟给多少”
例如:
- AI 可说:这是 NPC 私藏的旧护符、只愿交给值得信任的人
- 本地则决定:这是 `rare relic + affinityBonus 12 + currency 72`
## 10. UI 表达建议
当前 `AdventurePanel` 已经有不错的任务面板基础AI 原生任务系统建议补的不是“更多卡片”,而是“更多阶段感”。
建议新增以下 UI 信息:
1. 任务来源语义
- 谁委托
- 为什么此刻委托
2. 当前阶段标题
- 当前不是只看进度条,还要看“现在在做哪一步”
3. 任务关系状态
- 交易型 / 协作型 / 信任型
4. 任务后续钩子
- 这件事可能会牵出什么
UI 上不建议直接暴露给玩家的内部字段:
- `dramaticNeed`
- `followupHooks` 原始数组
- 所有 hidden flags
这些字段应该被整理成更自然的面板文案。
## 11. 与当前仓库的接入点建议
## 11.1 第一批建议改动的文件
建议先从以下文件接入:
- `src/types/story.ts`
- 扩展 `QuestLogEntry`
- `src/services/aiTypes.ts`
- 增加任务生成上下文
- `src/data/questFlow.ts`
- 增加 contract compiler 和 step progression
- `src/hooks/story/npcEncounterActions.ts`
-`quest_accept` 改为“机会判断 -> AI 意图 -> 本地编译”
- `src/services/prompt.ts`
- 不直接负责任务生成,拆出 `questPrompt.ts`
## 11.2 第一批不建议碰的区域
这轮不建议一开始就深入改:
- `AdventurePanel` 的整体结构
- `useStoryGeneration` 的全部 orchestrator
- 所有现存 AI story prompt
原因是任务系统已经是主链路的一部分,第一步应该先把 contract 立住,而不是把整个 story 系统一起重写。
## 12. MVP 落地顺序
## 阶段 A先做任务 contract不改全部表现
新增:
- `src/services/questTypes.ts`
- `src/services/questDirector.ts`
- `src/services/questPrompt.ts`
目标:
- AI 能返回 `QuestIntent`
- 本地能编译成 `QuestContract`
- 旧 UI 仍然照常显示
## 阶段 B把 NPC 接任务改成 AI 原生生成
先只改:
- `quest_accept`
此时:
- 仍沿用现有三种基础 objective kind
- 但 title / description / rewardText / followupHooks 开始变成上下文生成
这是最稳的切入点,因为:
- 影响面小
- 可回退
- 容易观察质量提升
## 阶段 C把任务推进改成 step + signal
重点改:
- `applyQuestProgressFromMonsterVictory`
- `applyQuestProgressFromTreasure`
- `applyQuestProgressFromSpar`
把它们收口到统一 signal reducer。
## 阶段 D把交付奖励与后续机会联动起来
`quest_turn_in` 不再只是:
- 发货币
- 发道具
- 加 affinity
而是还能:
- 写入 rumor / intel
- 解锁后续任务机会
- 改变 NPC 对话阶段
## 13. 为什么这套方案适合当前仓库
这套方案不是重做一套新玩法,而是顺着仓库已经验证过的边界继续深化:
1. 仓库已经验证“AI 负责叙事,本地负责规则”是正确方向
2. 仓库已经有现成的 quest UI、quest status、quest reward、npc affinity 链路
3. 当前 `useStoryGeneration` 已经在汇总 story/combat/treasure/npc 事件,天然适合继续发 quest signal
4. 当前 `StoryGenerationContext` 已经足够强,只是还缺一个任务专用 contract
所以这次真正缺的不是“再加一个任务面板”,而是:
**把任务从‘规则附属物’升级成‘叙事与规则之间的正式中介层’。**
## 14. 最后结论
对这个项目来说,理想的 AI 原生任务系统不应该做成“AI 随机发委托”,而应该做成:
1. 系统先判断当前局面是否值得生成任务机会
2. AI 根据世界、场景、NPC、最近剧情和玩家状态生成任务意图
3. 本地将任务意图编译成稳定、可测试、可持久化的任务合约
4. 运行时通过统一 signal 推进任务步骤
5. AI 在任务生成、阶段切换、完成交付时回写叙事质感
6. 奖励既包括资源,也包括关系、情报和后续机会
这样生成出来的任务,才会同时满足三件事:
- **像从当前剧情里自然长出来的**
- **像系统里可验证、可推进、可存档的**
- **像 AI 原生游戏真正该有的任务结构**

View File

@@ -0,0 +1,526 @@
# AI 原生游戏的运行时物品生成设计建议
更新时间:`2026-04-02`
## 0. 设计目标
这份方案针对当前项目,回答的是:
**如果要把运行时物品生成做成“AI 原生”,应该怎样设计,才能既贴合背景 / NPC / 当前事件,又不会把数值系统做崩。**
这里的“AI 原生”不是指“让模型直接胡乱造装备”,而是指:
- 物品的**语义、出处、命名、关系、叙事理由**由 AI 根据上下文生成
- 物品的**稀有度、build 标签、数值预算、持久化结果**由本地规则编译和裁剪
一句话:
**AI 决定这是什么,规则决定它能做什么。**
## 1. 设计原则
## 1.1 物品必须是“当前故事的一部分”
运行时物品不该只是“随机掉了个稀有剑”。
每个重要物品都至少回答 4 个问题:
1. 它为什么会出现在这里?
2. 它和哪个场景背景有关?
3. 它和哪个 NPC / 势力 / 怪物有关?
4. 它对当前玩家 build 为什么有意义?
## 1.2 物品收益以“标签倾向”优先,纯数值为辅
建议把 AI 原生物品的主要收益做成两大类:
1. **获得 build 标签**
- 永久标签:主要由装备 / 稀有饰品 / 关键遗物提供
- 限时标签:主要由消耗品 / 临时护符 / 战场符箓提供
2. **少量直接数值**
- 只做补充,不做主菜
- 避免数值碾压 build 语义
也就是说,运行时物品的第一身份应该是:
**“把玩家的构筑推向某种风格”**
而不是:
**“给一个更大的攻击数字”**
## 1.3 物品生成必须显式读取上下文
建议运行时物品生成必须至少读取以下上下文:
- 世界背景
- 当前场景 / 地标 / 氛围
- 当前 encounter / 相关 NPC / 相关怪物
- 最近 1~3 个关键剧情行为
- 玩家当前装备与激活 build 标签
- 玩家当前缺口
- 续航不够
- 控场不足
- 缺切后
- 缺护体
- 当前奖励渠道
- 宝藏
- 交易
- 委托
- 掉落
- 观察所得
## 1.4 AI 只产出“意图”,本地编译成成品
不要让 AI 直接返回最终 `InventoryItem`
建议让 AI 先返回的是“物品意图”:
- 物品主题
- 物品来源
- 关联对象
- 倾向标签
- 永久 / 限时
- 用途类型
然后本地再把它编译成:
- `category`
- `rarity`
- `tags`
- `statProfile`
- `useProfile`
- `buildProfile`
- `value`
这样才能稳定、可测试、可平衡。
## 2. 建议的系统结构
建议把新系统拆成 4 层。
## 2.1 上下文采样层
输入一份统一的 `RuntimeItemContext`
```ts
type RuntimeItemContext = {
worldType: WorldType | null;
customWorldProfile?: CustomWorldProfile | null;
sceneId?: string | null;
sceneName?: string | null;
sceneDescription?: string | null;
landmarkHints?: string[];
encounter?: Encounter | null;
relatedNpcState?: NpcPersistentState | null;
recentStoryMoments: StoryMoment[];
playerCharacter: Character;
playerEquipment: EquipmentLoadout;
activeBuildBuffs: TimedBuildBuff[];
activeBuildTags: string[];
generationChannel: "treasure" | "npc_trade" | "npc_reward" | "monster_drop" | "quest_reward" | "discovery";
};
```
这一层的目标不是做物品,而是把“这次生成到底是在什么局面下发生”说清楚。
## 2.2 AI 意图层
让模型只生成一个轻量蓝图:
```ts
type RuntimeItemIntent = {
narrativeTheme: string;
sourceKind: "npc" | "scene" | "monster" | "faction" | "quest" | "ancient";
sourceName: string;
reasonToAppear: string;
itemArchetype: "equipment" | "consumable" | "material" | "relic" | "quest";
permanence: "permanent" | "timed";
desiredBuildTags: string[];
desiredStatBias: Array<"hp" | "mana" | "outgoing" | "mitigation" | "cooldown">;
relationHooks: string[];
};
```
重点是:
- AI 负责“它像什么”
- 不负责“最终数值是多少”
## 2.3 本地编译层
本地把 `RuntimeItemIntent` 编译成正式物品:
- 先做标签规范化
-`normalizeBuildTags`
- 再判定品类
- 装备 / 消耗品 / 材料 / 稀有品 / 剧情物
- 再套预算
- rarity budget
- stat budget
- tag budget
- duration budget
- 最后写入:
- `buildProfile`
- `statProfile`
- `useProfile`
- `value`
## 2.4 叙事回写层
物品成品生成后,再把这些信息回写到叙事文本:
- 它看起来像什么
- 它为什么来自这个 NPC / 地点
- 它和哪条线索或关系有关
- 玩家为什么会觉得“这东西确实该在这里出现”
这一步仍然可以交给 AI但只能读“已经生成好的成品”。
## 3. 建议的物品类型设计
## 3.1 永久 build 标签物品
适合:
- 武器
- 护甲
- 饰品
- 关键遗物
建议规则:
- 常规装备最多给 `1` 个核心永久标签
- 稀有或史诗装备可给 `1` 个核心标签 + `1` 个协同标签
- 传说物品可以额外充当 set / faction / NPC build 锚点
示例:
- “渡口缉索短刃”
- 永久标签:`快袭`
- 协同标签:`追击`
- 小量数值:`outgoingDamageBonus`
- “镇河旧誓铜符”
- 永久标签:`守御`
- 协同标签:`护体`
- 小量数值:`maxManaBonus`
## 3.2 限时 build 标签物品
适合:
- 药剂
- 符箓
- 临时护符
- 战场应急工具
建议规则:
- 只通过 `useProfile.buildBuffs` 生效
- 持续 `1~3` 回合
- 一次最多提供 `1~2` 个标签
- 可叠加刷新时长,但不建议无限堆层
示例:
- “雾沼息行符”
- `2` 回合获得:`风行``游击`
- “火工催压油”
- `1` 回合获得:`爆发`
- 同时 `cooldownReduction: 1`
## 3.3 少量直接数值物品
适合做补充,而不是 build 主轴。
建议预算:
- 武器:
- `outgoingDamageBonus` 小幅增加
- 护甲:
- `maxHpBonus`
- 或少量 `incomingDamageMultiplier`
- 饰品:
- `maxManaBonus`
- 或轻量 `outgoingDamageBonus`
- 消耗品:
- `hpRestore`
- `manaRestore`
- `cooldownReduction`
建议约束:
- 常规运行时随机物品,数值权重应低于标签权重
- 不要让一个完全无标签的高数值物品压过语义鲜明的 build 物品
## 4. 如何保证“高度贴合背景和 NPC”
## 4.1 生成必须绑定三个锚点
建议每个 AI 原生物品至少有三个锚点:
1. **场景锚点**
- 例如矿道、渡口、祭坛、雾林、裂界前线
2. **关系锚点**
- 某个 NPC、某个势力、某类怪物、某段旧事
3. **玩法锚点**
- 玩家当前 build 缺口或当前风险
如果一个候选物品说不清这三个锚点,就不要发。
## 4.2 命名要使用世界词汇表,不要只按品类随机拼接
建议名字由三部分组成:
```text
来源词 + 关系词 + 品类词
```
例如:
- “锁风渡缉索短刃”
- “药谷回岚灵露”
- “断碑旧誓护心佩”
- “裂界巡守压纹符”
来源词来自:
- 场景 / 地标
- NPC 身份
- 势力 / 流派
- 当前任务线
而不是仅仅:
- 稀有前缀 + 武器名
## 4.3 描述文案要回答“为什么现在拿到它”
建议每个重要物品描述都带一句运行时来源理由:
- 是谁留下的
- 是从谁身上掉的
- 为什么这时能交易给你
- 为什么这次观察能发现它
这样玩家会感觉它是叙事结果,而不是系统掉表。
## 5. 建议的平衡规则
## 5.1 稀有度决定预算,不直接决定强度飞跃
建议把稀有度主要用于控制:
- 可带多少标签
- 是否允许 set / faction 锚点
- 叙事权重和经济价值
而不是简单理解为:
- 稀有度越高,数值就暴涨
建议预算参考:
| 稀有度 | 永久标签 | 限时标签 | 数值预算 |
| --- | --- | --- | --- |
| common | 0~1 | 1 | 很小 |
| uncommon | 1 | 1~2 | 小 |
| rare | 1+1协同 | 2 | 中等偏小 |
| epic | 2 或 set 锚点 | 2 | 中等 |
| legendary | 2 + 关系锚点 | 2~3 | 中等,但仍受上限约束 |
## 5.2 当前阶段优先支持“补短板”和“定方向”
建议运行时物品生成时,优先做这两类决策:
1. **补短板**
- 玩家 build 缺续航,就更容易拿到 `回复 / 续战 / 护体`
- 玩家 build 缺切后,就更容易拿到 `快袭 / 突进 / 风行`
2. **定方向**
- 当玩家已经有明显 build 倾向时,再投放协同物品,把这条路做深
不建议一味“追高强度”,否则玩家会频繁被迫换流派。
## 5.3 运行时物品要避免频繁彻底改流派
建议把随机物品对 build 的影响控制为:
- 大多数时候:
- 强化现有方向
- 或提供邻近方向
- 少数特殊奖励:
- 才允许提供“转流派锚点”
这样玩家会觉得构筑在成长,而不是被系统不断推翻。
## 6. 建议的接入点
## 6.1 宝藏奖励
当前最适合先改的是 `resolveTreasureReward`
建议把它升级为:
- 先收集:
- scene preset
- treasure hint
- 最近事件
- 当前遭遇 NPC / 怪物痕迹
- 再生成 1 个上下文物品
- 剩余奖励继续走稳定资源:
- 货币
- 基础材料
- 常规补给
这样宝藏会从“奖励池”变成“叙事发现”。
## 6.2 NPC 交易 / 赠礼 / 帮助
建议给 NPC 增加“关系定制物品”出口:
- 商人:
- 卖与你当前 build 有关、但带其身份烙印的物品
- 帮助奖励:
- 给限时道具或一次性符箓
- 高好感 NPC
- 才会给带永久 build 标签的私人遗物/信物
这样交易和关系系统就会真正联动。
## 6.3 怪物掉落
建议掉落分两层:
1. 基础掉落
- 继续走 preset / material / loot table
2. 语义掉落
- 从怪物生态、战斗风格、所在场景生成一个 build 倾向物品或精粹
例如:
- 重甲守卫掉:
- `守御精粹`
- `护体甲片`
- 雾林刺客掉:
- `快袭羽饰`
- `风行药囊`
## 6.4 委托奖励
任务奖励最适合给:
- 带关系来源的永久物品
- 剧情关键 rare / relic
- 能把玩家 build 往下一个阶段推一把的奖励
这类物品最适合绑定:
- 委托发布人
- 委托目标
- 地标
- 任务线真相
## 7. 建议新增的数据结构
建议在不推翻现有 `InventoryItem` 的前提下,新增一层来源元数据。
```ts
type RuntimeItemNarrativeBinding = {
generationChannel: "treasure" | "npc_trade" | "npc_reward" | "monster_drop" | "quest_reward" | "discovery";
sceneId?: string;
sceneName?: string;
relatedNpcId?: string;
relatedNpcName?: string;
relatedMonsterId?: string;
relatedFaction?: string;
storyReason: string;
eventHook?: string;
};
type RuntimeItemMetadata = {
origin: "catalog" | "procedural" | "ai_compiled";
seedKey?: string;
narrativeBinding?: RuntimeItemNarrativeBinding;
};
```
然后在 `InventoryItem` 上增加可选字段:
```ts
interface InventoryItem {
runtimeMetadata?: RuntimeItemMetadata;
}
```
这样后面 UI、日志、剧情回放都能解释
**这个物品到底从哪来。**
## 8. 推荐的最小落地顺序
建议不要一步把所有入口都改成 AI 原生,而是分三阶段。
## 阶段 A先做“上下文编译器”不改所有入口
新增:
- `src/data/runtimeItemDirector.ts`
- `src/data/runtimeItemCompiler.ts`
- `src/types/runtimeItem.ts`
先只负责:
- 接收上下文
- 生成意图
- 编译成 `InventoryItem`
## 阶段 B先接一个入口验证
优先接:
- `treasureInteractions.ts`
因为它最独立,风险最小,最容易观察“贴合背景”的提升。
## 阶段 C再接 NPC 与任务
等宝藏验证稳定后,再接:
- NPC 交易
- NPC 帮助奖励
- 任务奖励
最后再考虑怪物掉落的 AI 原生语义层。
## 9. 这套方案和当前仓库为什么契合
这套方案不是另起炉灶,而是直接复用当前仓库已经有的能力:
- 复用 `InventoryItem`
- 复用 `ItemStatProfile`
- 复用 `ItemUseProfile`
- 复用 `ItemBuildProfile`
- 复用 `normalizeBuildTags`
- 复用 `TimedBuildBuff`
- 复用装备、背包、锻造、build 结算
- 复用“AI 叙事,本地规则结算”的总边界
所以它不是推翻当前系统,而是补上当前系统最缺的那一层:
**上下文感知的运行时物品导演。**
## 10. 最后结论
对这个项目来说,理想的 AI 原生运行时物品生成不应该做成“AI 随机喷装备”,而应该做成:
1. AI 根据场景、背景、NPC、最近事件和玩家 build先生成物品语义意图。
2. 本地规则把这个意图编译成带永久或限时 build 标签、并附带少量数值加成的正式物品。
3. 物品必须能解释“为什么它会在这里,由谁带来,对当前玩家为什么有意义”。
4. 宝藏、交易、任务、掉落都逐步接入同一套导演层。
这样生成出来的物品才会同时满足三件事:
- **像故事里长出来的**
- **像 build 里需要的**
- **像系统里可控的**

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,414 @@
# Build 系统重构 PRD标签-属性相似度模型
更新时间:`2026-04-02`
## 1. 背景
当前 Build 系统的核心实现位于:
- `src/data/buildDamage.ts`
- `src/data/buildTags.ts`
- `src/data/buildTagSimilarity.generated.ts`
现状不是“标签各自独立生效”,而是:
1. 先收集角色标签、装备标签、套装标签、Buff 标签。
2. 再计算“每个标签与其他所有标签”的相似度。
3. 用标签之间的整体相互作用,得到最终 `buildDamageMultiplier`
这套机制已经能跑,但存在 4 个明显问题:
1. 解释成本高。玩家很难理解“为什么我多带一个标签,所有旧标签的贡献都变了”。
2. 平衡难度高。任意新增一个标签,都会对整个标签集合产生连锁影响。
3. 角色感不够强。当前倍率更像“标签团簇强度”,而不是“这个标签是否适合当前角色属性”。
4. 扩展不稳定。策划继续扩标签、套装、Buff 时,组合爆炸会越来越明显。
因此,本次重构目标是把 Build 系统从“标签互相影响”改为“标签分别匹配玩家扮演角色的属性画像”,让每个标签的收益来源更直观、更可控。
## 2. 目标
### 2.1 产品目标
建立一套新的 Build 计算模型:
- 不再计算标签与标签之间的互相影响。
- 改为计算“每个标签”和“角色每个属性”的相似度。
- 再根据角色属性分布,决定该标签的修正加成倍数。
- 所有标签的总收益由“单标签贡献求和”得到,而不是由“标签网络效应”得到。
### 2.2 设计目标
新系统需要满足:
1. 可解释:每个标签为什么强、强在哪个属性上,都能拆出来看。
2. 可控:新增一个标签,只影响它自己的贡献,不扰动全局。
3. 贴角色:敏捷型角色更容易吃满“突进/快剑/追击”类标签,智力/精神型角色更容易吃满“法修/法力/符阵”类标签。
4. 可扩展装备、Buff、套装仍然可以继续产出标签但标签结算方式统一且稳定。
### 2.3 非目标
本期不做:
1. 不重做掉落、锻造、拆解循环。
2. 不引入防御端 Build 抗性系统。
3. 不重新设计角色基础四维属性。
4. 不依赖运行时在线 embedding 服务。
## 3. 核心方案
## 3.1 基本思想
每个 Build 标签不再和其他标签比较,而是改为和以下 4 个角色属性做比较:
- `strength`
- `agility`
- `intelligence`
- `spirit`
每个标签都会拥有一个“属性亲和度向量”,表示它分别贴近哪类属性。
示例:
- `快剑`:更偏 `agility`,次偏 `strength`
- `重击`:更偏 `strength`
- `法修`:更偏 `intelligence`
- `护体`:偏 `spirit + strength`
- `符阵`:偏 `intelligence + spirit`
角色自身也有属性分布。系统将角色属性归一化后,与标签属性亲和度做匹配,得到该标签在当前角色身上的“适配度”。
最终伤害加成不再来自“标签互相增幅”,而来自“每个标签在当前角色上的适配度贡献”。
## 3.2 新公式
### 角色属性权重
```ts
roleAttributeWeight[attr] = character.attributes[attr] / totalAttributes
```
其中:
```ts
totalAttributes =
strength + agility + intelligence + spirit
```
### 标签属性亲和度
每个标签维护一个四维向量:
```ts
tagAttributeAffinity = {
strength: 0~1,
agility: 0~1,
intelligence: 0~1,
spirit: 0~1,
}
```
### 单标签适配度
```ts
tagFitScore(tag, character) =
sum(attr in [str, agi, int, spr])(
roleAttributeWeight[attr] * tagAttributeAffinity[attr]
)
```
`tagFitScore` 结果区间固定在 `0 ~ 1`
### 单标签加成倍数
```ts
tagBonusMultiplier =
1 + baseTagBonus * tagFitScore * sourceCoefficient
```
建议首版参数:
- `baseTagBonus = 0.12`
- `sourceCoefficient`
- Buff 标签:`1.0`
- 角色固有标签:`0.9`
- 武器标签:`0.85`
- 防具标签:`0.75`
- 饰品标签:`0.8`
- 套装合成标签:`0.9`
### 最终 Build 总倍率
为了避免标签过多时指数膨胀,首版采用“加法累计,再转倍率”的方式:
```ts
buildBonus =
clamp(sum(eachTagBonusDelta), 0, 0.6)
buildDamageMultiplier = 1 + buildBonus
```
其中:
```ts
eachTagBonusDelta = baseTagBonus * tagFitScore * sourceCoefficient
```
这意味着:
- 标签越多,总收益越高。
- 但每个标签只看自己和角色属性是否匹配。
- 新增一个标签,不会反向修改旧标签贡献。
## 3.3 示例
角色属性:
- `strength = 8`
- `agility = 10`
- `intelligence = 4`
- `spirit = 3`
归一化后:
- `strength = 0.32`
- `agility = 0.40`
- `intelligence = 0.16`
- `spirit = 0.12`
标签亲和度假设:
```ts
: { strength: 0.35, agility: 1.0, intelligence: 0.1, spirit: 0.05 }
: { strength: 0.45, agility: 0.95, intelligence: 0.0, spirit: 0.0 }
: { strength: 0.0, agility: 0.1, intelligence: 1.0, spirit: 0.6 }
```
则:
```ts
fit = 0.32*0.35 + 0.40*1.0 + 0.16*0.1 + 0.12*0.05 = 0.534
fit = 0.32*0.45 + 0.40*0.95 = 0.524
fit = 0.40*0.1 + 0.16*1.0 + 0.12*0.6 = 0.272
```
可以直观看到:
- 同样是标签,`快剑/突进` 对敏捷角色收益高。
- `法修` 在这名角色身上的收益明显偏低。
- 原因不再是“它和其他标签不合群”,而是“它和当前角色属性画像不匹配”。
## 4. 数据结构改造
## 4.1 `BuildTagDefinition` 扩展
当前 `src/types/build.ts` 中的 `BuildTagDefinition` 需要新增:
```ts
attributeAffinity: {
strength: number;
agility: number;
intelligence: number;
spirit: number;
};
```
完整建议:
```ts
interface BuildTagDefinition {
id: string;
label: string;
category: BuildTagCategory;
aliases: string[];
description: string;
attributeAffinity: {
strength: number;
agility: number;
intelligence: number;
spirit: number;
};
}
```
## 4.2 运行时明细结构
`src/data/buildDamage.ts` 需要将当前的 `BuildDamageBreakdown` 从“标签两两贡献表”改成“标签-属性贡献表”:
```ts
type BuildDamageBreakdown = {
tags: string[];
buildDamageBonus: number;
buildDamageMultiplier: number;
rows: Array<{
label: string;
source: 'buff' | 'character' | 'equipment' | 'set' | 'monster';
fitScore: number;
sourceCoefficient: number;
bonusDelta: number;
attributeContributions: {
strength: number;
agility: number;
intelligence: number;
spirit: number;
};
}>;
};
```
这样 UI 或调试日志能直接回答:
- 这个标签吃的是哪条属性
- 吃了多少
- 为什么它比另一个标签强
## 4.3 相似度来源
当前仓库已有 `src/data/buildTagSimilarity.generated.ts`,但新方案不再以“标签-标签相似度矩阵”为主数据源。
建议改为新增:
- `src/data/buildTagAttributeAffinity.ts`
用于存放标签到四维属性的静态向量。
首版推荐手工维护,原因:
1. 标签总量不大,人工校准更稳定。
2. 当前目标是产品可控性,不是自动发现语义簇。
3. 四维属性向量远比标签两两矩阵更容易审表和平衡。
后续如果要半自动化,可再增加脚本从标签描述中生成建议值,但运行时仍只读取本地静态表。
## 5. 标签来源规则
标签来源不变,计算方式变化。
### 保留来源
1. 角色固有 `combatTags`
2. 装备 `buildProfile.tags`
3. 套装标签
4. Buff 标签
### 新规则
1. 所有标签统一做规范化和去重。
2. 每个标签独立计算与角色属性的适配度。
3. 不再计算标签与标签之间的 pair / product / cluster。
4. 套装标签本质上仍是标签,只是 `sourceCoefficient` 更高。
## 6. 伤害接入方式
当前 `calculateOutgoingDamage()` 的接法可以保留:
```ts
finalDamage =
round(
baseDamage
* functionMultiplier
* equipmentMultiplier
* buildDamageMultiplier
)
```
本次只替换 `buildDamageMultiplier` 的来源,不改整体伤害主链路。
## 7. 与旧系统的关键差异
| 维度 | 旧系统 | 新系统 |
| --- | --- | --- |
| 核心逻辑 | 标签之间互相影响 | 标签分别匹配角色属性 |
| 新增标签的影响范围 | 会扰动整个标签集合 | 只影响自身贡献 |
| 可解释性 | 低 | 高 |
| 平衡成本 | 高 | 低 |
| 角色属性参与感 | 弱 | 强 |
| 套装/装备/Buff 接入 | 已支持 | 继续支持 |
## 8. 实施方案
### 阶段 A数据层
1.`src/types/build.ts` 扩展 `BuildTagDefinition.attributeAffinity`
2.`src/data/buildTags.ts` 为所有规范标签补齐四维亲和度
3. 新增 `src/data/buildTagAttributeAffinity.ts` 或直接内联到标签注册表
### 阶段 B规则层
1. 重写 `src/data/buildDamage.ts`
2. 删除或下线标签两两 `contributionRows` 计算
3. 新增 `tagFitScore``bonusDelta``attributeContributions` 计算
### 阶段 C展示层
1. 调整 Build 面板展示文案
2. 从“标签协同”改成“标签适配度”
3. 为每个标签展示主属性来源,例如:
- `快剑:敏捷主导,少量力量修正`
- `法修:智力主导,精神辅助`
### 阶段 D平衡层
1. 补一份全标签四维向量审表
2. 选 5 个预设角色跑样例验证
3. 校准 `baseTagBonus``sourceCoefficient`
## 9. 验收标准
### 功能验收
1. 任意标签的贡献都可以拆解到四个属性。
2. 删除一个标签时,只减少它自己的收益,不应重算其他标签的贡献值。
3. 同一套装备给不同属性角色使用时Build 倍率应体现明显差异。
4. 套装标签、Buff 标签仍能正常进入最终 Build 倍率。
### 数值验收
1. 单标签弱匹配时收益接近 0。
2. 单标签强匹配时收益稳定且可预期。
3. 3 到 6 个高匹配标签可形成清晰 build 成型感。
4. 8 标签上限下,总 Build 加成不超过设计封顶值。
### 体验验收
1. 玩家能理解“为什么这个标签适合我当前角色”。
2. 策划能直接通过改四维向量调数,不需要反复查标签图谱。
3. 调试日志能一眼看出收益来源,而不是只能看到复杂的 pair 乘积。
## 10. 风险与对策
### 风险 1标签语义被压平
问题:
去掉标签-标签协同后Build 可能变得过于线性。
对策:
1. 保留套装标签和 Buff 标签作为高价值来源。
2.`sourceCoefficient` 区分来源权重。
3. 后续如需要,可增加“少量同流派奖励”,但必须是弱规则,不能回到全图互相影响。
### 风险 2四维向量定义主观
问题:
不同策划对“快剑更像敏捷还是力量”可能判断不同。
对策:
1. 首版先建立审表规范。
2. 每个标签必须附一句属性说明。
3. 先让预设角色覆盖主要 archetype再扩充长尾标签。
### 风险 3旧数据迁移成本
问题:
现有 `buildTagSimilarity.generated.ts` 将弱化甚至失去主要用途。
对策:
1. 本期不强制删除旧文件。
2. 新逻辑只依赖新 affinity 表。
3. 等新系统稳定后,再清理旧相似度矩阵和旧展示逻辑。
## 11. 一句话结论
本次 Build 系统重构的核心,不是再优化“标签之间怎么互相放大”,而是把判断标准改成“这个标签和当前玩家角色的属性画像有多匹配”,从而让 Build 倍率从复杂的标签网络效应,变成可解释、可调优、可控的单标签属性适配模型。

View File

@@ -0,0 +1,486 @@
# 当前运行时物品生成系统设计整理
更新时间:`2026-04-02`
## 0. 目标
这份文档只回答一个问题:
**当前仓库里,运行时物品是怎么被“定义、生成、发放、使用、转化、进入 build 结算”的。**
它不是未来方案,而是对现状的结构化整理,方便后续继续扩展 AI 原生玩法。
## 1. 当前系统的总体判断
当前仓库里的运行时物品系统,不是“纯 AI 生成”,而是一个 **本地规则驱动 + 局部程序化生成 + AI 负责叙事文本** 的体系。
它大体由 5 层组成:
1. **物品骨架层**
-`InventoryItem``ItemStatProfile``ItemUseProfile``ItemBuildProfile` 承载运行时能力。
2. **基础生成层**
-`src/data/itemCatalog.ts` + `src/data/itemDesign.ts` 从素材路径推导出物品目录与设计元数据。
3. **运行时发放层**
- 在初始背包、NPC 库存、宝藏奖励、怪物掉落、拆解/锻造/重铸、自定义世界运行时生成等入口,把物品真正放进 `GameState`
4. **战斗/背包生效层**
- 装备通过 `equipmentEffects.ts` 生效,消耗品通过 `inventoryEffects.ts` 生效build 标签通过 `buildTags.ts` + `buildDamage.ts` 生效。
5. **叙事包装层**
- AI 负责把这些本地规则已经确定的结果写成剧情、聊天、宝藏描述、选项文案,但 **AI 当前并不直接产出结构化运行时物品**
一句话概括:
**当前系统已经有“运行时物品玩法骨架”,但还没有“与具体背景 / 当前 NPC / 当前事件强绑定的 AI 原生物品导演层”。**
## 2. 当前核心数据结构
### 2.1 `InventoryItem`
运行时所有物品最终都落到 `InventoryItem`
- 基础身份:`id``category``name``quantity``rarity`
- 通用标签:`tags`
- 世界/表现:`iconSrc``description``worldAffinity``worldProfiles`
- 装备信息:`equipmentSlotId`
- 数值能力:`statProfile`
- 使用能力:`useProfile`
- build 能力:`buildProfile`
- 经济能力:`value`
这意味着当前系统已经允许同一个物品同时具备:
- 装备加成
- 消耗品效果
- build 标签
- 世界观文案
- 经济价值
### 2.2 `ItemStatProfile`
当前可直接进入数值结算的字段主要是:
- `maxHpBonus`
- `maxManaBonus`
- `outgoingDamageBonus`
- `incomingDamageMultiplier`
这套结构已经足够支撑“少量直接数值提升”的物品设计。
### 2.3 `ItemUseProfile`
当前消耗品/可使用物品可提供:
- `hpRestore`
- `manaRestore`
- `cooldownReduction`
- `buildBuffs`
这意味着当前系统已经具备“限时 build 标签道具”的基础承载能力。
### 2.4 `ItemBuildProfile`
当前 build 相关物品数据包括:
- `role`
- `tags`
- `setId`
- `setName`
- `pieceName`
- `synergy`
- `craftTags`
- `forgeRank`
这说明当前物品系统已经不仅仅是“数值装备”,而是已经向 **build / 套装 / 锻造** 方向扩展。
## 3. 当前物品是如何被生成出来的
## 3.1 素材目录 -> 物品目录
`src/data/itemCatalog.ts` 负责把素材路径转成 `ItemCatalogEntry`
- 先从素材路径推导:
- `category`
- `rarity`
- `tags`
- `name`
- 再调用 `src/data/itemDesign.ts` 补充更完整的设计:
- `statProfile`
- `useProfile`
- `buildProfile`
- `value`
- 世界观名称/描述
也就是说,当前项目里相当一部分物品,不是手工逐个写死的,而是 **“素材驱动 + 规则推导”**。
## 3.2 `itemDesign.ts` 的设计角色
`src/data/itemDesign.ts` 是当前最重要的“物品规则设计器”。
它会按素材族系推导出不同风格物品:
- `Armory` 系列
- 生成武器/护甲
- 自动带 `buildProfile`
- 自动挂 `setId / setName / pieceName / synergy`
- `Jewelry` 系列
- 生成饰品
- 偏向 `relic` 与 build 补位
- `Potions` 系列
- 生成消耗品
- 可恢复 HP / Mana / 冷却
- 部分药剂会生成 `buildBuffs`
- `Gems` / `Skills` / `Librarium` 系列
- 生成稀有品、法器、技能相关物品
- 部分带 build 倾向
这层已经是“半程序化设计”,不是纯静态表。
## 3.3 自定义世界运行时程序化生成
`src/data/customWorldRuntime.ts` 提供了另一条明显不同的生成链:
- 输入:
- `CustomWorldProfile`
- `seedKey`
- 查询条件:`categories / preferredTags / keywords / rarityFloor / count`
- 输出:
- 运行时即时程序化物品
它的特点是:
- 基于世界档案与种子稳定生成
- 可以按角色、用途、标签、关键词筛选
- 能生成:
- 武器
- 护甲
- 饰品
- 消耗品
- 材料
- 稀有品
- 专属物品
当前它已经被用于:
- 自定义世界角色初始装备
- 自定义世界角色初始背包
- 自定义世界 NPC 角色库存
但这条链目前更像 **“主题化程序物品池”**还不是“事件级、NPC级、场景级实时定制物品”。
## 4. 当前运行时有哪些物品发放入口
## 4.1 玩家初始物品
玩家开局物品主要来自两条链:
1. `buildInitialPlayerInventory`
- 来自 `npcInteractions.ts`
- 普通世界走角色预设背包
- 自定义世界走 `buildCustomWorldStarterInventoryItems`
2. `buildInitialEquipmentLoadout`
- 来自 `equipmentEffects.ts`
- 根据角色预设初始装备,转成可装备的 `InventoryItem`
这说明玩家初始 build 其实已经部分依赖物品体系,而不是只靠角色裸属性。
## 4.2 NPC 库存
`buildInitialNpcState` 会给每个 NPC 建立运行时库存:
- 角色型 NPC
- 从角色装备 + 角色背包推导
- 怪物型 encounter
- 从怪物 preset 的 `lootTable` 推导
- 普通场景 NPC
- 从职业/身份模板库存推导
- 自定义世界 NPC
- 可走 `buildRuntimeCustomWorldInventoryItems`
因此当前 NPC 交易、赠礼、击败掉落,已经都能围绕同一套 `InventoryItem[]` 进行。
## 4.3 宝藏奖励
`src/data/treasureInteractions.ts` 负责宝藏奖励:
- 根据世界类型选择奖励池
- 根据 encounter 信息和 action 做 seed
- 产出:
- 稀有品
- 消耗品
- 材料
- HP / Mana 恢复
- 货币
这条链已经是运行时生成,但目前仍然是 **世界模板池级别**,不是“根据当前场景背景 / 当前 NPC / 最近事件”深度定制。
## 4.4 怪物掉落 / NPC 击败掉落
当前掉落主要有两种:
1. 怪物 preset 自带 `lootTable`
2. NPC 击败后,从 `npcState.inventory` 里按玩家收益排序取高价值物品
这里的核心是:
**当前系统已经把“掉落”统一成库存消费问题,而不是单独的一套特殊奖励系统。**
## 4.5 拆解 / 合成 / 锻造 / 重铸
`src/data/forgeSystem.ts` 已经形成第二类运行时物品生成入口:
- `executeDismantleItem`
- 把装备拆成基础材料 + 标签精粹
- `executeForgeRecipe`
- 消耗材料生成成品装备
- `executeReforgeItem`
- 保留原物品基础上重投 build 标签并增强数值
这说明运行时物品系统已经不只是“掉落 -> 使用”,而是进入了:
**掉落 -> 持有 -> 拆解 -> 再生产 -> build 迭代**
的循环。
## 5. 当前物品如何进入玩法结算
## 5.1 装备生效
`src/data/equipmentEffects.ts` 会把 `EquipmentLoadout` 汇总为:
- `maxHpBonus`
- `maxManaBonus`
- `outgoingDamageMultiplier`
- `incomingDamageMultiplier`
当前实现已经会优先读取 `statProfile`,没有时才走 rarity fallback。
这意味着:
- 装备的直接数值提升已经真实生效
- 不是只在 UI 显示
## 5.2 build 标签生效
`src/data/buildTags.ts` + `src/data/buildDamage.ts` 已经形成完整 build 入口:
- 角色 `combatTags`
- 装备 `buildProfile.tags`
- 套装标签
- 限时 `TimedBuildBuff`
会被统一整理为激活标签集,再计算 build 伤害乘区。
当前 build 标签来源已经包括:
- 角色
- 怪物
- 装备
- 套装
- 消耗品/技能 buff
## 5.3 消耗品生效
`src/data/inventoryEffects.ts` + `src/hooks/useInventoryFlow.ts` 会在使用物品时:
- 恢复 HP
- 恢复 Mana
- 推进技能冷却
- 追加 `activeBuildBuffs`
这意味着当前系统已经存在:
- **直接恢复型物品**
- **节奏调整型物品**
- **限时 build 强化型物品**
三种雏形。
## 6. 当前 AI 在物品系统里的角色
当前 AI 与物品系统的关系主要有两种:
## 6.1 自定义世界“离线式”生成
`src/services/customWorld.ts` + `src/services/customWorldBuilder.ts` 会让 AI 生成:
- 世界名
- playable NPC
- story NPC
- 关键物品样本
- 地标
然后本地再把这些骨架扩展成更大的世界档案。
这时 AI 的角色是:
**提供世界观语义骨架,而不是直接在单次 encounter 里临场造出一个可结算物品。**
## 6.2 运行时叙事包装
`prompt.ts` 和相关 story flow 里AI 主要负责:
- 剧情文本
- 对话
- 选项文案
- 氛围描述
但当前 AI 不负责:
- 直接返回结构化物品
- 决定物品数值是否合法
- 决定 build 标签是否合法
- 决定库存如何变更
这与仓库已有开发经验文档里的原则一致:
**AI 负责解释世界,本地规则负责改动世界。**
## 7. 当前系统的优点
## 7.1 已有统一物品骨架
`InventoryItem` 已经足够承载:
- 永久装备
- 消耗品
- build 标签
- 世界观描述
- 经济系统
后续不需要另起一套物品结构。
## 7.2 已有 build 玩法骨架
当前系统已经支持:
- 装备 build 标签
- 套装 build 标签
- 消耗品限时 build buff
- 角色/怪物 combatTags
这让“物品影响 build”不再只是概念。
## 7.3 已有多个运行时入口
当前物品已经能从这些入口进入游戏:
- 初始背包
- 初始装备
- NPC 库存
- 宝藏
- 怪物掉落
- 击败 NPC
- 合成
- 拆解
- 锻造
- 重铸
- 自定义世界程序化生成
系统入口已经比较完整。
## 7.4 本地规则边界明确
当前实现最大的稳定性来源,是物品最终由本地规则落库和结算:
- 可测试
- 可复现
- 可存档兼容
- 不依赖模型临场稳定性
这非常适合继续向 AI 原生玩法演化。
## 8. 当前系统的主要缺口
## 8.1 非自定义世界的运行时发放仍偏模板池
当前普通世界的宝藏、NPC 库存、基础奖励,更多还是:
- 世界模板
- 身份模板
- 怪物 preset
而不是根据以下上下文动态拼装:
- 当前场景背景
- 当前 NPC 动机
- 当前事件阶段
- 最近剧情行为
- 玩家当前 build 缺口
## 8.2 宝藏与物品的叙事绑定不够深
当前宝藏奖励会根据世界类型变化,但还没有强绑定:
- 地标
- scene preset
- treasure hint
- 相关 NPC
- 最近发生的事件
所以“玩法可用”,但“故事贴脸感”还不够强。
## 8.3 自定义世界运行时物品偏“主题生成”,还不是“关系生成”
`customWorldRuntime.ts` 已经能做:
- 世界主题相关
- 标签/关键词相关
- 角色用途相关
但还没有直接把以下关系结构编进物品:
- 这个物品和哪个 NPC 有关系
- 为什么在这个时刻出现
- 它与哪个任务/线索绑定
- 它是否属于某个 faction / 场景 / 地标
## 8.4 一些运行时奖励没有补足完整 build 元数据
例如部分宝藏奖励和 NPC 模板奖励,当前只是简单 `InventoryItem`
-`category / rarity / tags`
- 但未必有完整 `statProfile / useProfile / buildProfile`
这会导致它们更像资源或商品,而不是强 build 物品。
## 8.5 缺少“物品生成导演层”
当前系统缺的不是单个函数,而是一层明确的运行时物品导演:
- 输入当前上下文
- 决定掉落/奖励/商店/赠礼候选
- 决定叙事来源
- 决定 build 倾向
- 决定是永久收益还是限时收益
- 决定数值预算
这层目前分散在:
- `treasureInteractions.ts`
- `npcInteractions.ts`
- `customWorldRuntime.ts`
- `forgeSystem.ts`
之间,还没有统一起来。
## 9. 对当前系统的结论
当前仓库里的“运行时物品生成系统”已经不是空白,反而已经具备了很好的扩展前提:
- 有统一物品数据结构
- 有 build 标签体系
- 有限时 buff 体系
- 有装备/消耗品/材料/稀有品的分类
- 有宝藏、NPC、掉落、锻造等运行时入口
- 有自定义世界程序化物品能力
- 有明确的“AI 叙事、本地规则结算”边界
但它现在更像:
**“规则系统已经就位AI 原生上下文驱动物品导演还没补上。”**
后续如果要继续往 AI 原生游戏推进,最值得补的不是推翻现有系统,而是:
1. 在现有 `InventoryItem` 体系上增加上下文生成层。
2. 让物品生成同时读取场景、NPC、剧情、build 缺口。
3. 让 AI 负责物品语义与叙事来源,本地规则负责编译成可结算物品。
4. 把宝藏、NPC 交易、任务奖励、掉落统一接入同一套“运行时物品导演”。