637
docs/prd/AI_CHARACTER_VISUAL_ANIMATION_MVP_PRD_2026-04-04.md
Normal file
637
docs/prd/AI_CHARACTER_VISUAL_ANIMATION_MVP_PRD_2026-04-04.md
Normal 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. 把预览、重新生成和发布做完整
|
||||
|
||||
这样做的价值在于:
|
||||
|
||||
- 范围可控
|
||||
- 路径清晰
|
||||
- 能真正进入当前仓库
|
||||
- 后续可以在此基础上再加技能动作、剧情演出和多供应商增强路线
|
||||
|
||||
789
docs/prd/AI_NATIVE_QUEST_SYSTEM_PRD_2026-04-02.md
Normal file
789
docs/prd/AI_NATIVE_QUEST_SYSTEM_PRD_2026-04-02.md
Normal 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 原生游戏真正该有的任务结构**
|
||||
526
docs/prd/AI_NATIVE_RUNTIME_ITEM_GENERATION_DESIGN.md
Normal file
526
docs/prd/AI_NATIVE_RUNTIME_ITEM_GENERATION_DESIGN.md
Normal 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 里需要的**
|
||||
- **像系统里可控的**
|
||||
1084
docs/prd/AI_NATIVE_UNIFIED_ROLE_ATTRIBUTE_SYSTEM_PRD_2026-04-02.md
Normal file
1084
docs/prd/AI_NATIVE_UNIFIED_ROLE_ATTRIBUTE_SYSTEM_PRD_2026-04-02.md
Normal file
File diff suppressed because it is too large
Load Diff
414
docs/prd/BUILD_SYSTEM_ATTRIBUTE_SIMILARITY_PRD_2026-04-02.md
Normal file
414
docs/prd/BUILD_SYSTEM_ATTRIBUTE_SIMILARITY_PRD_2026-04-02.md
Normal 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 倍率从复杂的标签网络效应,变成可解释、可调优、可控的单标签属性适配模型。
|
||||
486
docs/prd/RUNTIME_ITEM_GENERATION_CURRENT_SYSTEM_DESIGN.md
Normal file
486
docs/prd/RUNTIME_ITEM_GENERATION_CURRENT_SYSTEM_DESIGN.md
Normal 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 交易、任务奖励、掉落统一接入同一套“运行时物品导演”。
|
||||
Reference in New Issue
Block a user