@@ -15,6 +15,7 @@
|
||||
- [FUNCTION_RUNTIME_FULL_TEST_AUDIT_2026-04-16.md](./FUNCTION_RUNTIME_FULL_TEST_AUDIT_2026-04-16.md):Function 运行时完整测试、服务端承接验证与当前门禁缺口。
|
||||
- [ITEM_AND_BUILD_PRD_AUDIT_2026-04-05.md](./ITEM_AND_BUILD_PRD_AUDIT_2026-04-05.md):物品生成与 Build 标签系统对 PRD 的落地情况。
|
||||
- [CUSTOM_WORLD_CREATOR_TOOL_AUDIT_2026-04-08.md](./CUSTOM_WORLD_CREATOR_TOOL_AUDIT_2026-04-08.md):自定义世界创作工具当前问题、体验断层和优化优先级审计。
|
||||
- [engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md](./engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md):对 `2026-04-19` 工程清理审计的当前仓库复核,区分已完成项、仍存边界问题和新的热点迁移。
|
||||
- [engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md](./engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md):未引用垃圾、旧入口残留、前后端双份真相与后端迁移项的专项审计。
|
||||
|
||||
## 推荐使用方式
|
||||
|
||||
@@ -0,0 +1,384 @@
|
||||
# 工程清理与后端边界复核审计(2026-04-20)
|
||||
|
||||
更新时间:`2026-04-20`
|
||||
|
||||
## 0. 审计目标
|
||||
|
||||
这份文档不是重复 `2026-04-19` 的原始扫描,而是基于当前仓库状态做一轮复核,重点回答三个问题:
|
||||
|
||||
1. 昨天审计里已经提出的问题,哪些今天已经真正落地。
|
||||
2. 哪些结论在当前代码里仍然成立,哪些表述需要纠正。
|
||||
3. 当前工程热点和边界问题有没有发生迁移。
|
||||
|
||||
---
|
||||
|
||||
## 1. 结论先行
|
||||
|
||||
和 `2026-04-19` 那份基线相比,当前仓库已经有一批明确进展:
|
||||
|
||||
1. **旧 Vite 本地 API 链路已经真正出清。**
|
||||
`scripts/dev-server/` 当前只剩一份 `README.md`,旧的 `localApiPlugins.ts`、角色资产插件、精灵表插件都不在仓库里了。
|
||||
2. **根目录噪音产物已经清理完成。**
|
||||
当前根目录临时日志/扫描产物扫描结果为空,`temp-build-goal-check/` 也不存在。
|
||||
3. **`server-node -> src/**` 反向依赖已经收掉。**
|
||||
当前复核没有再发现 `server-node/src/**` 直接 import 前端 `src/**` 的情况。
|
||||
4. **runtime option interaction 已经收口成后端单一真相。**
|
||||
这部分现在由 `server-node/src/modules/story/runtimeSession.ts` 统一构造,前端 `src/services/runtimeStoryService.ts` 不再本地再建一份映射表。
|
||||
|
||||
但这不代表边界问题已经结束,当前剩余问题主要集中在三块:
|
||||
|
||||
1. **前端仍保留运行时镜像与登录凭证本地真相。**
|
||||
`runtimeStoryCoordinator.ts` 仍会先写本地快照,`apiClient.ts` 仍把 token/自动登录凭证放在 `localStorage`。
|
||||
2. **NPC 聊天任务链路还没有完全后端化。**
|
||||
“聊天后挂出待接委托”已经移到后端,但“更换待接委托”这条分支仍由前端 `npcEncounterActions.ts` 触发 `generateQuestForNpcEncounter(...)`。
|
||||
3. **未接线孤岛和热点文件问题仍然明显。**
|
||||
一批 UI/Hook/Prompt 残留模块还没有正式入口;同时热点已经从已删除的旧插件链路,转移到 `CustomWorldEntityEditorModal.tsx`、`storyPromptBuilders.ts`、`runtimeProfile.ts`、`PreGameSelectionFlow.tsx`、`PlatformHomeView.tsx` 等新中心。
|
||||
|
||||
一句话判断:
|
||||
|
||||
**当前仓库已经完成“清垃圾、拆旧入口、切断后端反向依赖”的第一阶段,但还没有完成“前端退出运行时真相”和“未接线孤岛归档”的第二阶段。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 已完成项复核
|
||||
|
||||
## 2.1 旧 dev-server 链路已经不是“逻辑上废弃”,而是“代码上删除”
|
||||
|
||||
### 当前证据
|
||||
|
||||
| 项目 | 当前状态 | 结论 |
|
||||
| --- | --- | --- |
|
||||
| `scripts/dev-server/` | 当前只剩 `README.md` 一份说明文件 | 旧 Vite 本地 API 链路已从仓库代码层出清 |
|
||||
| `scripts/dev-server/README.md` | 已明确声明当前正式入口为 `scripts/dev-node.mjs + server-node/src/modules/**` | 文档与代码状态一致 |
|
||||
|
||||
### 结论
|
||||
|
||||
`2026-04-19` 文档里关于旧本地 API 插件链路的清理结论,在当前仓库里已经可以确认成立,不再只是“计划删除”。
|
||||
|
||||
---
|
||||
|
||||
## 2.2 根目录噪音产物已经从当前工作区移除
|
||||
|
||||
### 当前证据
|
||||
|
||||
| 项目 | 当前状态 | 结论 |
|
||||
| --- | --- | --- |
|
||||
| 根目录历史日志/扫描产物 | 本轮扫描结果为空 | 之前的 `.codex-*.log`、`tmp_*`、旧截图/HTML 不再占据当前工作区 |
|
||||
| `temp-build-goal-check/` | 当前不存在 | 大体量检查产物已移出当前仓库视野 |
|
||||
|
||||
### 结论
|
||||
|
||||
`2026-04-19` 文档中关于“仓库噪音产物”的问题,在当前工作区层面已经完成首轮治理。
|
||||
这部分不再是当前工程第一优先级。
|
||||
|
||||
---
|
||||
|
||||
## 2.3 `server-node -> src/**` 反向依赖已清零
|
||||
|
||||
### 当前证据
|
||||
|
||||
本轮用脚本复核 `server-node/src/**` 中所有 `import` 后,当前结果为:
|
||||
|
||||
`NO_DIRECT_SERVER_TO_FRONTEND_SRC_IMPORTS`
|
||||
|
||||
同时,仓库里已经看不到类似下面这类旧反向依赖:
|
||||
|
||||
1. `server-node -> src/services/customWorld.js`
|
||||
2. `server-node -> src/services/customWorldBuilder.js`
|
||||
3. `server-node -> src/services/customWorldCreatorIntent.js`
|
||||
4. `server-node -> src/types.js`
|
||||
|
||||
### 结论
|
||||
|
||||
`2026-04-19` 文档里“清理 `server-node -> src/**` 反向依赖”的阶段性目标,在当前仓库里已经真正落地。
|
||||
|
||||
---
|
||||
|
||||
## 2.4 runtime option interaction 已经收口到后端
|
||||
|
||||
### 当前证据
|
||||
|
||||
1. `server-node/src/modules/story/runtimeSession.ts` 当前仍保留 `buildOptionInteraction(...)`,负责构造:
|
||||
- `npcActionMap`
|
||||
- `treasureActionMap`
|
||||
2. `src/services/runtimeStoryService.ts` 当前只做:
|
||||
- 直接读取 `option.interaction`
|
||||
- 把后端返回的 interaction 投影成 `StoryOption`
|
||||
3. 前端文件里已经找不到旧的 `buildRuntimeOptionInteraction` / `npcActionMap` / `treasureActionMap` 实现。
|
||||
|
||||
### 结论
|
||||
|
||||
这项收口已经成立,当前不会再出现“前后端各维护一份 interaction 映射表”的旧问题。
|
||||
|
||||
---
|
||||
|
||||
## 2.5 浏览器端的 quest/runtime item 本地 LLM fallback 已移除
|
||||
|
||||
### 当前证据
|
||||
|
||||
1. `src/services/questDirector.ts`
|
||||
- 浏览器路径先请求 `/api/runtime/quests/generate`
|
||||
- 后端失败时只走 deterministic fallback compile
|
||||
2. `src/services/runtimeItemAiDirector.ts`
|
||||
- 浏览器路径先请求 `/api/runtime/items/runtime-intent`
|
||||
- 后端失败时只返回 deterministic fallback intents
|
||||
3. 这两个文件虽然仍保留 `requestChatMessageContent(...)` 分支,但那是非浏览器分支,不再是浏览器端正式兜底链路。
|
||||
|
||||
### 结论
|
||||
|
||||
`2026-04-19` 文档里关于“浏览器本地 LLM fallback”这部分,当前应更新为:
|
||||
|
||||
**浏览器端本地 LLM fallback 已移除,但这两个模块仍然是双环境混合实现,还没有彻底后端化。**
|
||||
|
||||
---
|
||||
|
||||
## 3. 需要纠正的旧文档表述
|
||||
|
||||
## 3.1 NPC 任务链路不是“全部后端化”,而是“挂单已后移、换单仍前触发”
|
||||
|
||||
### 需要纠正的点
|
||||
|
||||
`2026-04-19` 文档中的回填里有一条表述是:
|
||||
|
||||
“`src/hooks/story/npcEncounterActions.ts` 不再在 NPC 单轮聊天完成后本地调用 `generateQuestForNpcEncounter(...)` 再决定是否挂出待接委托。”
|
||||
|
||||
### 当前代码状态
|
||||
|
||||
这句话对“聊天后挂出待接委托”这条主链是成立的,因为当前后端 `server-node/src/modules/ai/chatOrchestrator.ts` 已经会回填 `pendingQuestOffer`。
|
||||
|
||||
但它对整条 NPC 任务链路来说并不完整,因为当前前端仍保留这条分支:
|
||||
|
||||
1. `src/hooks/story/npcEncounterActions.ts`
|
||||
2. `replacePendingNpcQuestOffer()`
|
||||
3. `generateQuestForNpcEncounter(...)`
|
||||
|
||||
也就是:
|
||||
|
||||
**待接委托的“正式挂出”已后端化,但“更换委托”仍然由前端动作流发起。**
|
||||
|
||||
### 当前应改成的结论
|
||||
|
||||
更准确的描述应该是:
|
||||
|
||||
1. NPC 单轮聊天里“是否挂出待接委托”的决定权已收回后端。
|
||||
2. 但待接委托的“换单/重抽”分支仍通过前端 `npcEncounterActions.ts -> questDirector.ts` 发起。
|
||||
|
||||
---
|
||||
|
||||
## 4. 当前仍然成立的遗留问题
|
||||
|
||||
## 4.1 未接线/仅测试引用孤岛模块仍然明显
|
||||
|
||||
本轮依赖图复核后,当前仍能确认一批高置信度孤岛模块:
|
||||
|
||||
| 模块 | 当前状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `src/components/GameShell.tsx` | `765` 行,无运行时引用 | 旧版壳层残留仍在 |
|
||||
| `src/components/custom-world-home/CustomWorldCreationHub.tsx` | `161` 行,仅测试引用 | UI 已有完成度,但仍未进入正式入口 |
|
||||
| `src/components/custom-world-home/CustomWorldCreationLauncherModal.tsx` | `147` 行,无运行时引用 | 未接线入口壳层 |
|
||||
| `src/components/custom-world-agent/CustomWorldAgentLauncherModal.tsx` | `91` 行,无运行时引用 | agent UI 孤岛仍在 |
|
||||
| `src/components/custom-world-agent/CustomWorldAgentDraftDrawer.tsx` | `116` 行,无运行时引用 | agent UI 孤岛仍在 |
|
||||
| `src/hooks/story/storyBootstrap.ts` | `250` 行,无运行时引用 | 旧 bootstrap hook 仍未归档 |
|
||||
| `src/hooks/useEquipmentFlow.ts` | `134` 行,无运行时引用 | 旧 flow hook 残留 |
|
||||
| `src/hooks/useForgeFlow.ts` | `159` 行,无运行时引用 | 旧 flow hook 残留 |
|
||||
| `src/hooks/useInventoryFlow.ts` | `100` 行,无运行时引用 | 旧 flow hook 残留 |
|
||||
| `src/services/customWorldPresentation.stub.ts` | `55` 行,无运行时引用 | 占位 stub 仍在 |
|
||||
| `src/services/typewriter.ts` | `7` 行,无运行时引用 | 小型 helper 残留 |
|
||||
| `src/prompts/customWorldOrchestratorPrompts.ts` | `9` 行,无运行时引用 | prompt source 已迁走后留下的孤岛 |
|
||||
| `src/prompts/storyOrchestratorPrompts.ts` | `6` 行,无运行时引用 | prompt source 已迁走后留下的孤岛 |
|
||||
| `src/data/buildTagSimilarity.generated.ts` | `823` 行,无运行时引用 | 生成产物未接入正式业务链路 |
|
||||
|
||||
### 说明
|
||||
|
||||
`src/data/itemOverrides.json`、`src/data/monsterOverrides.json` 这类文件虽然没有 import 引用,但会被脚本和 editor route 以路径消费,所以不计入垃圾判断。
|
||||
|
||||
### 结论
|
||||
|
||||
仓库已经完成“删旧插件”,但还没有完成“清未接线孤岛”。
|
||||
当前这批模块应该进入明确处置表:
|
||||
|
||||
1. 直接归档/删除
|
||||
2. 正式接回入口
|
||||
3. 改名/迁目录,标记为实验稿
|
||||
|
||||
---
|
||||
|
||||
## 4.2 前端仍保留运行时镜像真相
|
||||
|
||||
### 当前证据
|
||||
|
||||
1. `src/hooks/story/runtimeStoryCoordinator.ts`
|
||||
- 仍会在读状态和提交动作前先 `putSaveSnapshot(...)`
|
||||
- 仍会在响应后多次 `rehydrateSavedSnapshot(...)`
|
||||
2. `src/services/runtimeStoryService.ts`
|
||||
- 仍对响应快照做 `rehydrateSavedSnapshot(...)`
|
||||
|
||||
### 结论
|
||||
|
||||
当前运行时已经不是“前端主算”,但仍然是:
|
||||
|
||||
**前端先写一份本地镜像,再和后端会话互相回填。**
|
||||
|
||||
这说明前端还没有完全退出正式运行时状态解释层。
|
||||
|
||||
---
|
||||
|
||||
## 4.3 前端仍保留本地登录凭证真相
|
||||
|
||||
### 当前证据
|
||||
|
||||
`src/services/apiClient.ts` 当前仍把以下内容写入 `window.localStorage`:
|
||||
|
||||
1. `ACCESS_TOKEN_KEY`
|
||||
2. `AUTO_AUTH_USERNAME_KEY`
|
||||
3. `AUTO_AUTH_PASSWORD_KEY`
|
||||
|
||||
对应代码仍包括:
|
||||
|
||||
1. `window.localStorage.getItem(...)`
|
||||
2. `window.localStorage.setItem(...)`
|
||||
3. `window.localStorage.removeItem(...)`
|
||||
|
||||
### 结论
|
||||
|
||||
这一点和“前端只做表现、后端负责鉴权”的目标仍然不一致。
|
||||
尤其是自动登录用户名/密码继续存本地,风险和边界问题都还在。
|
||||
|
||||
---
|
||||
|
||||
## 4.4 quest/runtime item 仍是双环境混合实现
|
||||
|
||||
### 当前证据
|
||||
|
||||
1. `src/services/questDirector.ts`
|
||||
- 浏览器路径走 `requestJson('/api/runtime/quests/generate')`
|
||||
- 非浏览器路径仍有 `requestChatMessageContent(...)`
|
||||
2. `src/services/runtimeItemAiDirector.ts`
|
||||
- 浏览器路径走 `requestJson('/api/runtime/items/runtime-intent')`
|
||||
- 非浏览器路径仍有 `requestChatMessageContent(...)`
|
||||
3. `src/hooks/story/npcEncounterActions.ts`
|
||||
- 当前仍 import `generateQuestForNpcEncounter`
|
||||
- `replacePendingNpcQuestOffer()` 仍会调用它
|
||||
|
||||
### 结论
|
||||
|
||||
浏览器兜底已经收掉,但模块职责仍然是混合的:
|
||||
|
||||
1. 同一个文件同时承担前端 SDK 和非浏览器编排逻辑
|
||||
2. NPC 换单动作仍由前端发起服务调用
|
||||
|
||||
这部分还不能算真正后端化完成。
|
||||
|
||||
---
|
||||
|
||||
## 4.5 `src/services/ai.ts` 仍然是浏览器端正式 AI orchestration 热点
|
||||
|
||||
### 当前证据
|
||||
|
||||
`src/services/ai.ts` 当前约 `2608` 行,仍直接使用:
|
||||
|
||||
1. `requestChatMessageContent`
|
||||
2. `requestPlainTextCompletion`
|
||||
3. `streamPlainTextCompletion`
|
||||
|
||||
### 结论
|
||||
|
||||
这说明浏览器侧的大型 AI orchestration 仍然没有真正退出主工程。
|
||||
虽然部分链路已经迁走,但整体边界还没有收完。
|
||||
|
||||
---
|
||||
|
||||
## 5. 当前热点已经发生迁移
|
||||
|
||||
## 5.1 当前主要大文件快照
|
||||
|
||||
| 文件 | 当前行数 | 判断 |
|
||||
| --- | --- | --- |
|
||||
| `src/components/CustomWorldEntityEditorModal.tsx` | `4898` | 仍是前端最大热点 |
|
||||
| `server-node/src/modules/assets/characterAssetRoutes.ts` | `3181` | 仍是后端资产链路最大热点 |
|
||||
| `src/services/ai.ts` | `2608` | 浏览器 AI orchestration 热点仍在 |
|
||||
| `src/data/npcInteractions.ts` | `2409` | 仍是大型规则数据中心 |
|
||||
| `server-node/src/services/customWorldAgentFoundationDraftService.ts` | `1902` | custom world agent 后端热点上升 |
|
||||
| `src/prompts/storyPromptBuilders.ts` | `1882` | prompt source 已成为新的前端热点 |
|
||||
| `server-node/src/modules/custom-world/runtimeProfile.ts` | `1735` | custom world runtime 编译中心已转到后端 |
|
||||
| `src/components/game-shell/PreGameSelectionFlow.tsx` | `1547` | 平台/入口流程热点上升 |
|
||||
| `src/components/game-shell/PlatformHomeView.tsx` | `1522` | 平台首页热点上升 |
|
||||
| `src/services/customWorld.ts` | `1489` | 仍然大,但已明显缩小 |
|
||||
| `src/hooks/story/npcEncounterActions.ts` | `1434` | 仍然是前端 action 热点 |
|
||||
|
||||
---
|
||||
|
||||
## 5.2 热点变化判断
|
||||
|
||||
和 `2026-04-19` 相比,当前热点不是单纯“没变”,而是出现了明显迁移:
|
||||
|
||||
1. `characterAssetRoutes.ts` 从 `3579` 行降到 `3181` 行,说明资产路由已经有过一轮拆分,但仍然偏大。
|
||||
2. `src/services/customWorld.ts` 从 `2413` 行降到 `1489` 行,说明自定义世界规则已拆出一部分。
|
||||
3. `src/hooks/story/npcEncounterActions.ts` 从 `1623` 行降到 `1434` 行,说明 NPC 运行时逻辑也有收口。
|
||||
4. 新的复杂度中心开始转移到:
|
||||
- `src/prompts/storyPromptBuilders.ts`
|
||||
- `server-node/src/modules/custom-world/runtimeProfile.ts`
|
||||
- `src/components/game-shell/PreGameSelectionFlow.tsx`
|
||||
- `src/components/game-shell/PlatformHomeView.tsx`
|
||||
|
||||
### 结论
|
||||
|
||||
当前问题已经不再是“原来的热点完全没动”,而是:
|
||||
|
||||
**部分旧热点正在缩小,但复杂度正在向 prompt source、custom world runtime profile、平台入口壳层继续迁移。**
|
||||
|
||||
---
|
||||
|
||||
## 6. 最新建议执行顺序
|
||||
|
||||
### 第一阶段:先清理当前仍明确无入口的孤岛
|
||||
|
||||
1. 处理 `GameShell.tsx`
|
||||
2. 处理 `custom-world-home/*`
|
||||
3. 处理 `custom-world-agent/*`
|
||||
4. 处理 `storyBootstrap.ts`、`useEquipmentFlow.ts`、`useForgeFlow.ts`、`useInventoryFlow.ts`
|
||||
5. 处理已脱钩的 `src/prompts/*OrchestratorPrompts.ts`
|
||||
|
||||
### 第二阶段:再收运行时和鉴权真相
|
||||
|
||||
1. 收掉 `runtimeStoryCoordinator.ts` 的本地快照前置写入
|
||||
2. 收掉 `apiClient.ts` 中的自动登录用户名/密码本地持久化
|
||||
3. 优先把 token/session 统一到服务端鉴权边界
|
||||
|
||||
### 第三阶段:补完 NPC 任务链路的后端化
|
||||
|
||||
1. 把“更换待接委托”从 `npcEncounterActions.ts -> questDirector.ts` 继续迁到后端
|
||||
2. 把 `questDirector.ts` / `runtimeItemAiDirector.ts` 拆成明确的后端服务与前端 SDK 两层
|
||||
|
||||
### 第四阶段:最后拆新热点
|
||||
|
||||
1. `CustomWorldEntityEditorModal.tsx`
|
||||
2. `characterAssetRoutes.ts`
|
||||
3. `storyPromptBuilders.ts`
|
||||
4. `runtimeProfile.ts`
|
||||
5. `PreGameSelectionFlow.tsx`
|
||||
6. `PlatformHomeView.tsx`
|
||||
|
||||
---
|
||||
|
||||
## 7. 本文依据
|
||||
|
||||
文档依据:
|
||||
|
||||
1. `docs/audits/engineering/ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md`
|
||||
2. `docs/audits/engineering/CURRENT_ENGINEERING_OPTIMIZATION_PRIORITIES_2026-04-10.md`
|
||||
3. `docs/planning/EXPRESS_BACKEND_REFACTOR_PLAN_2026-04-08.md`
|
||||
4. `docs/planning/EXPRESS_BACKEND_PARALLEL_WORKSTREAM_PLAN_2026-04-08.md`
|
||||
|
||||
当前仓库复核依据:
|
||||
|
||||
1. `scripts/dev-server/README.md`
|
||||
2. `server-node/src/modules/story/runtimeSession.ts`
|
||||
3. `src/services/runtimeStoryService.ts`
|
||||
4. `src/hooks/story/runtimeStoryCoordinator.ts`
|
||||
5. `src/hooks/story/npcEncounterActions.ts`
|
||||
6. `src/services/questDirector.ts`
|
||||
7. `src/services/runtimeItemAiDirector.ts`
|
||||
8. `src/services/apiClient.ts`
|
||||
9. 当前依赖图扫描结果与当前大文件体量扫描结果
|
||||
|
||||
@@ -4,21 +4,25 @@
|
||||
|
||||
## 当前推荐入口
|
||||
|
||||
1. [ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md](./ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md)
|
||||
这一版聚焦当前仓库里的垃圾/冗余代码、旧入口残留、前后端边界未闭合点,以及下一步最该清什么、迁什么、拆什么。
|
||||
2. [ENGINEERING_OPTIMIZATION_REVIEW_2026-04-01.md](./ENGINEERING_OPTIMIZATION_REVIEW_2026-04-01.md)
|
||||
1. [ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md](./ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-20.md)
|
||||
这一版是对 `2026-04-19` 基线的当前仓库复核,明确哪些问题已经处理、哪些表述需要纠正、热点又迁移到了哪里。
|
||||
2. [ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md](./ENGINEERING_CLEANUP_AND_BACKEND_BOUNDARY_AUDIT_2026-04-19.md)
|
||||
这一版保留原始问题快照和执行回填,适合回看“为什么会有这轮清理与边界收口”。
|
||||
3. [ENGINEERING_OPTIMIZATION_REVIEW_2026-04-01.md](./ENGINEERING_OPTIMIZATION_REVIEW_2026-04-01.md)
|
||||
这一版最适合作为当前工程基线,重点从“是否真正绿色”“门禁有没有覆盖真实风险”来判断仓库状态。
|
||||
3. [ENGINEERING_OPTIMIZATION_REVIEW_2026-03-30.md](./ENGINEERING_OPTIMIZATION_REVIEW_2026-03-30.md)
|
||||
4. [ENGINEERING_OPTIMIZATION_REVIEW_2026-03-30.md](./ENGINEERING_OPTIMIZATION_REVIEW_2026-03-30.md)
|
||||
适合回看运行时主链路、Story/Combat 边界、分层过渡期问题。
|
||||
4. [ENGINEERING_OPTIMIZATION_REVIEW_2026-03-29.md](./ENGINEERING_OPTIMIZATION_REVIEW_2026-03-29.md)
|
||||
5. [ENGINEERING_OPTIMIZATION_REVIEW_2026-03-29.md](./ENGINEERING_OPTIMIZATION_REVIEW_2026-03-29.md)
|
||||
适合看第一轮系统性工程扫描,了解最早的问题基线。
|
||||
|
||||
## 融合结论
|
||||
|
||||
- 当前仓库的新重点已经从“单纯补门禁”进一步演进到“清历史残留、清无入口模块、收前后端双份真相”。
|
||||
- 当前仓库已经完成“旧 dev 插件链路删除、根目录噪音清理、`server-node -> src/**` 反向依赖切断”这批第一阶段任务。
|
||||
- 当前的新重点已经进一步收敛到三类:未接线孤岛模块、前端残留的运行时/鉴权真相、热点向 prompt/runtime profile/平台入口壳层迁移。
|
||||
- 三轮结论是一致收敛的:问题不在“有没有开始工程化”,而在“工程化是否真正覆盖了最危险的主链路”。
|
||||
- 最新一轮已经把关注点集中到质量门禁、真实绿色基线、关键模块豁免和 build warning 上。
|
||||
- `2026-04-19` 这一轮进一步把问题压实到了四类:仓库噪音、旧 dev 入口残留、前端越界运行时逻辑、巨型热点文件。
|
||||
- `2026-04-19` 这一轮把问题压实到了四类:仓库噪音、旧 dev 入口残留、前端越界运行时逻辑、巨型热点文件。
|
||||
- `2026-04-20` 这一轮进一步确认:前两类已经阶段性完成,当前真正剩下的是边界尾巴和新热点迁移。
|
||||
- 如果只是为了判断现在先做什么,直接从 `2026-04-01` 开始即可。
|
||||
- 如果是要做当前清理和边界收口,优先看 `2026-04-19`。
|
||||
- 如果是要做长期重构方案,再按 `2026-03-29 -> 2026-03-30 -> 2026-04-01 -> 2026-04-19` 的顺序回看演进。
|
||||
- 如果是要看当前清理和边界收口的最新状态,优先看 `2026-04-20`。
|
||||
- 如果是要做长期重构方案,再按 `2026-03-29 -> 2026-03-30 -> 2026-04-01 -> 2026-04-19 -> 2026-04-20` 的顺序回看演进。
|
||||
|
||||
@@ -0,0 +1,870 @@
|
||||
# 等级成长、章节经验节奏与 NPC 自动定级设计
|
||||
|
||||
更新时间:`2026-04-20`
|
||||
|
||||
## 实现进度(2026-04-20 第一批)
|
||||
|
||||
当前仓库已按本设计先落地第一批稳定能力:
|
||||
|
||||
1. 已新增 `playerProgression` 正式成长状态,包含等级、当前等级经验、总经验与下级阈值。
|
||||
2. 已新增等级基准与经验结算服务,并接入前后端存档归一化,旧存档默认回填为 `Lv.1 / 0 XP`。
|
||||
3. 已给 `QuestReward` 补上 `experience`,新生成任务会按当前等级与任务结构给出任务经验。
|
||||
4. 已将 Express 后端 `npc_quest_turn_in` 接入经验发放与升级处理,任务交付结果会反馈 `经验 +N` 与升级信息。
|
||||
5. 已在冒险主面板补充最小等级展示:`Lv.` 与细经验条;任务奖励面板可看到经验数值。
|
||||
6. 已收回任务日志里的直接领奖入口,任务奖励结算当前以 NPC 交付链路为准。
|
||||
|
||||
本轮仍未落地的部分:
|
||||
|
||||
1. 击败敌对 NPC 经验。
|
||||
2. 章节经验预算 / ledger 统计。
|
||||
3. 按章节自动定级 NPC 与运行时敌对经验掉落。
|
||||
|
||||
## 0. 目标
|
||||
|
||||
这次设计解决 5 个必须同时成立的问题:
|
||||
|
||||
1. 玩家需要正式拥有 `等级 / 当前经验 / 总经验 / 升级` 这条成长主链。
|
||||
2. 经验只从两类明确来源进入:
|
||||
- 完成任务
|
||||
- 击败敌对 NPC
|
||||
3. 同等级实体必须具备同一档 `参考强度`,不能再靠散落在各处的静态数值各自漂移。
|
||||
4. 系统需要能按章节评估玩家经验获取速度,而不是只在整体通关后回看“升太快/升太慢”。
|
||||
5. 不同章节里的 NPC 需要按章节目标等级自动定级,保证这一章的敌我强度、经验产出和升级节奏互相闭合。
|
||||
|
||||
一句话结论:
|
||||
|
||||
**等级必须成为后端统一裁决的成长基线;章节必须先产出“目标玩家等级带 + 经验预算”,再由这套预算反推任务经验、击杀经验和本章 NPC 自动等级。**
|
||||
|
||||
---
|
||||
|
||||
## 1. 基于当前仓库的判断
|
||||
|
||||
结合当前代码与文档,现状已经有足够好的骨架,但等级系统这一层还完全缺位。
|
||||
|
||||
### 1.1 已经具备的基础
|
||||
|
||||
1. `src/data/questFlow.ts`
|
||||
|
||||
- 已有 `QuestLogEntry / QuestStep / QuestProgressSignal / chapter quest`。
|
||||
- 已经能把场景章节任务接到运行时主链。
|
||||
|
||||
2. `server-node/src/modules/quest/questStoryActionService.ts`
|
||||
|
||||
- 已经把 `接任务 / 交任务` 收回后端。
|
||||
- 任务结算时已经集中处理货币、背包、好感变化。
|
||||
|
||||
3. `server-node/src/modules/quest/questRuntimeSignalService.ts`
|
||||
|
||||
- 已经会在 `npc_chat / 击败敌对 NPC / 宝藏 / 切磋` 后投递 quest signal。
|
||||
|
||||
4. `src/services/storyEngine/chapterDirector.ts`
|
||||
|
||||
- 已经能用当前场景章节任务推导 `opening -> expansion -> turning_point -> climax -> aftermath`。
|
||||
|
||||
5. `src/types/customWorld.ts`
|
||||
|
||||
- 已经有 `sceneChapterBlueprints`,说明章节顺序、幕推进和 NPC 编排已经有正式挂点。
|
||||
|
||||
6. `src/types/attributes.ts`、`src/data/hostileNpcPresets.ts`
|
||||
- 已经有统一属性画像、怪物/NPC 统一实体方向。
|
||||
- 当前敌对实体已有 `baseStats / attributeProfile / behaviorVectors`,可以继续向“同级同参考强度”收束。
|
||||
|
||||
### 1.2 当前缺口
|
||||
|
||||
当前最核心的缺口有 6 个:
|
||||
|
||||
1. `GameState` 没有玩家等级成长状态。
|
||||
2. `QuestReward` 没有经验字段。
|
||||
3. `SceneHostileNpc / SceneNpc` 没有正式等级和击杀经验字段。
|
||||
4. 当前 hostile preset 的 `hp/maxHp` 仍是静态绝对值,不受章节节奏控制。
|
||||
5. 章节系统没有“本章目标入场等级 / 出章等级 / 经验预算”的结构。
|
||||
6. 没有“按章节自动定级”的编译器,也没有“本章经验是否超发/欠发”的记账面板。
|
||||
|
||||
一句话总结:
|
||||
|
||||
**现在仓库里已经有章节、任务、NPC 和属性系统,但还没有“成长预算层”,所以强度、奖励和章节节奏仍然缺少同一把尺。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心决策
|
||||
|
||||
## 2.1 等级、经验与 NPC 定级全部由 Express 后端裁决
|
||||
|
||||
必须坚持:
|
||||
|
||||
1. 前端只展示 `等级 / 经验条 / 升级结果 / NPC 等级徽标`。
|
||||
2. 经验发放、升级、章节经验预算、NPC 自动定级全部在 Express 后端计算。
|
||||
3. 前端不本地推演“这次应该升几级”“这个 NPC 应该是多少级”。
|
||||
|
||||
推荐新增领域目录:
|
||||
|
||||
- `server-node/src/modules/progression/`
|
||||
|
||||
建议首批模块:
|
||||
|
||||
- `levelBenchmarks.ts`
|
||||
- `playerProgressionService.ts`
|
||||
- `chapterProgressionPlanner.ts`
|
||||
- `chapterExperienceLedger.ts`
|
||||
- `npcLevelResolver.ts`
|
||||
- `progressionRuntimeSignalService.ts`
|
||||
|
||||
## 2.2 MVP 经验来源只认两类事件
|
||||
|
||||
首版只允许两类正式经验来源:
|
||||
|
||||
1. `quest_turned_in`
|
||||
|
||||
- 任务真正交付时发经验。
|
||||
- 不在“接任务”“任务 ready_to_turn_in”时发经验。
|
||||
|
||||
2. `hostile_npc_defeated`
|
||||
- 仅限敌对 NPC / 怪物胜利结算后发经验。
|
||||
- 不对 `npc_spar_completed`、普通聊天、观察、宝藏直接发经验。
|
||||
|
||||
这样做的原因是:
|
||||
|
||||
1. 最容易和当前后端任务/战斗链路接上。
|
||||
2. 经验来源清晰,便于做章节预算。
|
||||
3. 避免系统一开始就被碎片经验源冲散。
|
||||
|
||||
## 2.3 同等级 = 同参考强度
|
||||
|
||||
这是本次设计最重要的规则:
|
||||
|
||||
1. 等级是所有可比较实体共享的强度基线。
|
||||
2. 同等级玩家、敌对 NPC、可战斗剧情 NPC,必须共享同一档 `参考强度`。
|
||||
3. 世界属性 schema 只决定“强在哪种风格上”,不决定“同级谁天然强一截”。
|
||||
|
||||
也就是说:
|
||||
|
||||
- `Lv.8` 的重甲敌人和 `Lv.8` 的迅捷刺客可以打法不同
|
||||
- 但两者的 `参考强度预算` 必须是同一档
|
||||
|
||||
真正的强弱差只允许来自:
|
||||
|
||||
1. 等级差
|
||||
2. 装备 / Build / Buff / Debuff
|
||||
3. 章节中明确声明的 `boss / elite` 角色通过更高等级体现,而不是同级偷加隐藏倍数
|
||||
|
||||
## 2.4 章节先出经验预算,再反推等级
|
||||
|
||||
章节设计从这次开始必须按下面顺序计算:
|
||||
|
||||
```text
|
||||
章节顺序
|
||||
-> 本章玩家目标入场等级 / 出章等级
|
||||
-> 本章总经验预算
|
||||
-> 任务经验份额 / 击杀经验份额
|
||||
-> 本章 NPC 自动等级
|
||||
-> 本章实际经验记账与偏差评估
|
||||
```
|
||||
|
||||
不能反过来先手写一堆 NPC 强度,再看玩家能不能接住。
|
||||
|
||||
## 2.5 UI 只做极简表达
|
||||
|
||||
为了符合当前项目“UI 不默认堆规则说明”的约束,前台只建议新增 4 个轻量展示:
|
||||
|
||||
1. 玩家信息区:
|
||||
|
||||
- `Lv. X`
|
||||
- 一条细经验条
|
||||
|
||||
2. 敌对 NPC 名牌:
|
||||
|
||||
- `Lv. X`
|
||||
|
||||
3. 任务交付结果:
|
||||
|
||||
- `经验 +N`
|
||||
|
||||
4. 升级提示:
|
||||
- 单条 toast 或单行系统反馈
|
||||
|
||||
不在界面里默认放:
|
||||
|
||||
- 经验公式说明
|
||||
- 章节经验预算说明
|
||||
- 等级规则解释文案
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据结构设计
|
||||
|
||||
## 3.1 玩家成长状态
|
||||
|
||||
建议新增:
|
||||
|
||||
```ts
|
||||
export interface PlayerProgressionState {
|
||||
level: number;
|
||||
currentLevelXp: number;
|
||||
totalXp: number;
|
||||
xpToNextLevel: number;
|
||||
pendingLevelUps?: number;
|
||||
lastGrantedSource?: 'quest' | 'hostile_npc' | null;
|
||||
}
|
||||
```
|
||||
|
||||
挂载位置建议:
|
||||
|
||||
- `src/types/game.ts`
|
||||
- `GameState.playerProgression`
|
||||
|
||||
原则:
|
||||
|
||||
1. 这不是 `runtimeStats` 的一部分。
|
||||
2. `runtimeStats` 继续做统计计数。
|
||||
3. `playerProgression` 是正式玩法状态。
|
||||
|
||||
## 3.2 等级基准表
|
||||
|
||||
建议新增:
|
||||
|
||||
```ts
|
||||
export interface LevelBenchmark {
|
||||
level: number;
|
||||
xpToNextLevel: number;
|
||||
cumulativeXpRequired: number;
|
||||
referenceStrength: number;
|
||||
baseHp: number;
|
||||
baseMana: number;
|
||||
baselineDamageScale: number;
|
||||
}
|
||||
```
|
||||
|
||||
单一真相源建议放在:
|
||||
|
||||
- `server-node/src/modules/progression/levelBenchmarks.ts`
|
||||
|
||||
前端只通过后端投影拿结果,不自己保存第二份表。
|
||||
|
||||
## 3.3 实体等级档案
|
||||
|
||||
建议新增:
|
||||
|
||||
```ts
|
||||
export type ProgressionRole =
|
||||
| 'guide'
|
||||
| 'ambient'
|
||||
| 'support'
|
||||
| 'hostile_standard'
|
||||
| 'hostile_elite'
|
||||
| 'hostile_boss'
|
||||
| 'rival';
|
||||
|
||||
export interface EntityLevelProfile {
|
||||
level: number;
|
||||
referenceStrength: number;
|
||||
chapterId?: string | null;
|
||||
chapterIndex?: number | null;
|
||||
progressionRole: ProgressionRole;
|
||||
source: 'chapter_auto' | 'preset_override' | 'manual';
|
||||
}
|
||||
```
|
||||
|
||||
建议接入:
|
||||
|
||||
- `src/types/scene.ts`
|
||||
- `SceneNpc.levelProfile?: EntityLevelProfile`
|
||||
- `SceneHostileNpc.levelProfile?: EntityLevelProfile`
|
||||
|
||||
## 3.4 任务奖励扩展
|
||||
|
||||
建议扩展:
|
||||
|
||||
```ts
|
||||
export interface QuestReward {
|
||||
affinityBonus: number;
|
||||
currency: number;
|
||||
experience: number;
|
||||
items: InventoryItem[];
|
||||
storyHint?: string;
|
||||
intel?: { ... };
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
1. 经验是任务奖励的一等字段。
|
||||
2. 经验文本不走 story hint 兜底。
|
||||
3. 任务经验由后端编译,不交给 AI 决定。
|
||||
|
||||
## 3.5 敌对 NPC 经验掉落
|
||||
|
||||
建议扩展:
|
||||
|
||||
```ts
|
||||
export interface SceneHostileNpc {
|
||||
...
|
||||
experienceReward?: number;
|
||||
}
|
||||
```
|
||||
|
||||
首版只给运行时敌对 NPC 挂经验值,不强行把它沉到所有 preset 原始数据中。
|
||||
|
||||
原因:
|
||||
|
||||
1. 经验应该跟章节定级一起编译。
|
||||
2. 同一个 hostile preset 出现在不同章节时,等级和经验都应不同。
|
||||
3. 静态 preset 继续只表达“风格”和“原型”,不再表达最终强度。
|
||||
|
||||
## 3.6 章节成长计划
|
||||
|
||||
建议新增运行时编译结果:
|
||||
|
||||
```ts
|
||||
export interface ChapterProgressionPlan {
|
||||
chapterId: string;
|
||||
chapterIndex: number;
|
||||
totalChapters: number;
|
||||
entryPseudoLevel: number;
|
||||
exitPseudoLevel: number;
|
||||
entryLevel: number;
|
||||
exitLevel: number;
|
||||
totalXpBudget: number;
|
||||
questXpBudget: number;
|
||||
hostileXpBudget: number;
|
||||
expectedHostileDefeatCount: number;
|
||||
paceBand: 'opening_fast' | 'steady' | 'pressure' | 'finale_dense';
|
||||
}
|
||||
```
|
||||
|
||||
建议作为后端运行时编译结果缓存,不作为创作者直接编辑字段。
|
||||
|
||||
## 3.7 章节经验记账
|
||||
|
||||
建议新增:
|
||||
|
||||
```ts
|
||||
export interface ChapterExperienceLedger {
|
||||
chapterId: string;
|
||||
chapterIndex: number;
|
||||
levelAtEntry: number;
|
||||
levelAtExit?: number | null;
|
||||
plannedTotalXp: number;
|
||||
plannedQuestXp: number;
|
||||
plannedHostileXp: number;
|
||||
actualQuestXp: number;
|
||||
actualHostileXp: number;
|
||||
expectedHostileDefeatCount: number;
|
||||
actualHostileDefeatCount: number;
|
||||
}
|
||||
```
|
||||
|
||||
用途:
|
||||
|
||||
1. 评估每一章经验速度。
|
||||
2. 判断本章是否超发/欠发。
|
||||
3. 为下一轮调参提供依据。
|
||||
|
||||
---
|
||||
|
||||
## 4. 等级曲线与参考强度
|
||||
|
||||
## 4.1 首版等级目标
|
||||
|
||||
首版建议:
|
||||
|
||||
1. 系统支持 `Lv.1 ~ Lv.20`
|
||||
2. 当前主线正常通章目标不是满级
|
||||
3. 标准单轮战役通关目标等级建议落在 `Lv.14 ~ Lv.15`
|
||||
|
||||
这样做的原因是:
|
||||
|
||||
1. 级差足够表达章节成长
|
||||
2. 不会让前期升级过细、后期又没有空间
|
||||
3. 还保留后续营地、精英支线、长期养成的余量
|
||||
|
||||
## 4.2 升级经验公式
|
||||
|
||||
建议基线公式:
|
||||
|
||||
```ts
|
||||
xpToNextLevel(level) = 60 + 20 * (level - 1) + 8 * (level - 1) * (level - 1);
|
||||
```
|
||||
|
||||
由此生成 `LevelBenchmark[]`,不在业务代码里散落重复公式。
|
||||
|
||||
说明:
|
||||
|
||||
1. 前期升级快,便于建立成长反馈
|
||||
2. 中后期门槛逐步拉开,避免章节尾段失控
|
||||
3. 可直接序列化成常量表用于测试
|
||||
|
||||
## 4.3 参考强度公式
|
||||
|
||||
建议基线公式:
|
||||
|
||||
```ts
|
||||
referenceStrength(level) =
|
||||
100 + 16 * (level - 1) + 6 * (level - 1) * (level - 1);
|
||||
```
|
||||
|
||||
并同步产出:
|
||||
|
||||
```ts
|
||||
baseHp(level);
|
||||
baseMana(level);
|
||||
baselineDamageScale(level);
|
||||
```
|
||||
|
||||
重要约束:
|
||||
|
||||
1. `referenceStrength` 是同级比较标尺。
|
||||
2. style 只允许在同一档预算内重分布,不允许抬高总强度。
|
||||
3. `elite / boss` 不允许用同级隐藏倍率偷强度,必须通过更高等级体现。
|
||||
|
||||
## 4.4 现有静态数值如何迁移
|
||||
|
||||
当前 `src/data/hostileNpcPresets.ts` 里的:
|
||||
|
||||
- `baseStats.hp`
|
||||
- `baseStats.maxHp`
|
||||
- `speed`
|
||||
- `attackRange`
|
||||
|
||||
不建议继续全部视为最终强度。
|
||||
|
||||
迁移原则:
|
||||
|
||||
1. `attackRange / speed` 继续保留为战斗风格参数。
|
||||
2. `hp / maxHp` 改为“风格形状参考”,最终值由 `等级基准 + 风格分布` 决定。
|
||||
3. 现有 preset 的高血量、高机动、高压制,只用于决定“同级下怎么分布”,不改变同级总参考强度。
|
||||
|
||||
---
|
||||
|
||||
## 5. 经验发放规则
|
||||
|
||||
## 5.1 任务经验
|
||||
|
||||
任务经验只在 `turn_in` 时发放。
|
||||
|
||||
建议公式:
|
||||
|
||||
```ts
|
||||
baseQuestXp(targetLevel) = xpToNextLevel(targetLevel) * 0.45;
|
||||
|
||||
questXp =
|
||||
baseQuestXp(targetLevel) *
|
||||
stepCountMultiplier *
|
||||
narrativeTypeMultiplier *
|
||||
urgencyMultiplier;
|
||||
```
|
||||
|
||||
建议倍率:
|
||||
|
||||
| 条件 | 倍率 |
|
||||
| ------------------------------------------ | ------ |
|
||||
| `steps = 1` | `0.85` |
|
||||
| `steps = 2` | `1.0` |
|
||||
| `steps >= 3` | `1.12` |
|
||||
| `investigation / retrieval / relationship` | `1.0` |
|
||||
| `trial / bounty` | `1.08` |
|
||||
| `urgency = high` | `1.05` |
|
||||
|
||||
最终规则:
|
||||
|
||||
1. 结果四舍五入到 `5` 的倍数。
|
||||
2. 章节主任务优先从本章 `questXpBudget` 出数。
|
||||
3. 普通 NPC 支线如果不绑定章节,则按 `targetLevel` 单独计算。
|
||||
|
||||
## 5.2 击败敌对 NPC 经验
|
||||
|
||||
建议公式:
|
||||
|
||||
```ts
|
||||
baseKillXp(targetLevel) = xpToNextLevel(targetLevel) * 0.08;
|
||||
|
||||
killXp =
|
||||
baseKillXp(targetLevel) *
|
||||
stageMultiplier *
|
||||
levelDeltaMultiplier *
|
||||
repeatPenalty;
|
||||
```
|
||||
|
||||
建议倍率:
|
||||
|
||||
| 条件 | 倍率 |
|
||||
| -------------------------------- | ----------------- |
|
||||
| `opening` | `0.9` |
|
||||
| `expansion` | `1.0` |
|
||||
| `turning_point` | `1.05` |
|
||||
| `climax` | `1.15` |
|
||||
| 玩家高于目标 `2` 级 | `0.7` |
|
||||
| 玩家高于目标 `4` 级 | `0.3` |
|
||||
| 玩家低于目标 `2` 级 | `1.15` |
|
||||
| 同章同类敌对实体超过预计击杀数后 | `0.5 -> 0.2 -> 0` |
|
||||
|
||||
解释:
|
||||
|
||||
1. 同章重复刷怪必须衰减。
|
||||
2. 击杀经验要响应等级差,避免低章 farming。
|
||||
3. 高潮压轴敌人可以给更多经验,但仍受章节预算约束。
|
||||
|
||||
## 5.3 经验发放顺序
|
||||
|
||||
推荐统一顺序:
|
||||
|
||||
```text
|
||||
规则动作成功
|
||||
-> 生成经验 grant
|
||||
-> 写入 playerProgression.totalXp / currentLevelXp
|
||||
-> 处理升级
|
||||
-> 回写章节 ledger
|
||||
-> 生成前端提示
|
||||
```
|
||||
|
||||
不要把经验结算拆在前端多个回调里各自加一次。
|
||||
|
||||
---
|
||||
|
||||
## 6. 章节经验速度评估
|
||||
|
||||
## 6.1 章节顺序来源
|
||||
|
||||
章节索引 `chapterIndex` 建议按下面顺序解析:
|
||||
|
||||
1. 有 `campaign pack` 时,优先用 campaign 正式顺序
|
||||
2. 否则有 `sceneChapterBlueprints` 时,用蓝图顺序
|
||||
3. 再否则,对 `landmarks` 从营地出发做最短路径排序
|
||||
4. 若存在并列,则回退到稳定的 landmark 原始顺序
|
||||
|
||||
这样才能给每章一个稳定的“这是第几章”。
|
||||
|
||||
## 6.2 目标等级带
|
||||
|
||||
建议先计算“伪等级进度”,再换算成经验预算:
|
||||
|
||||
```ts
|
||||
chapterBoundaryPseudoLevel(i) =
|
||||
1 + curve(i / totalChapters) * (terminalStoryLevel - 1);
|
||||
```
|
||||
|
||||
建议 `curve` 用轻微前快后稳的函数:
|
||||
|
||||
```ts
|
||||
curve(progress) = Math.pow(progress, 0.92);
|
||||
```
|
||||
|
||||
随后:
|
||||
|
||||
```ts
|
||||
entryPseudoLevel = chapterBoundaryPseudoLevel(chapterIndex - 1);
|
||||
exitPseudoLevel = chapterBoundaryPseudoLevel(chapterIndex);
|
||||
chapterXpBudget =
|
||||
xpForPseudoLevel(exitPseudoLevel) - xpForPseudoLevel(entryPseudoLevel);
|
||||
```
|
||||
|
||||
这样做的好处是:
|
||||
|
||||
1. 每一章都有明确的入章/出章目标
|
||||
2. 等级增幅随章节自然变慢
|
||||
3. 经验速度评估可以直接落成表格
|
||||
|
||||
## 6.3 章节经验份额
|
||||
|
||||
默认建议:
|
||||
|
||||
| 章节类型 | 任务经验占比 | 击杀经验占比 |
|
||||
| --------------- | ------------ | ------------ |
|
||||
| 调查/关系型章节 | `75%` | `25%` |
|
||||
| 平衡型章节 | `65%` | `35%` |
|
||||
| 战斗/试炼型章节 | `55%` | `45%` |
|
||||
|
||||
章节类型判定可由下面几项共同决定:
|
||||
|
||||
1. `SceneChapterBlueprint.acts` 数量
|
||||
2. 当前章节 hostile NPC 数量
|
||||
3. 当前章节任务 step 中战斗目标占比
|
||||
4. `dangerLevel`
|
||||
5. linked thread 是否为主线高压线程
|
||||
|
||||
## 6.4 实际速度评估规则
|
||||
|
||||
每章结束后,至少计算下面三个值:
|
||||
|
||||
1. `actualTotalXp / plannedTotalXp`
|
||||
2. `actualHostileXp / plannedHostileXp`
|
||||
3. `levelAtExit - plannedExitLevel`
|
||||
|
||||
建议判定:
|
||||
|
||||
| 偏差 | 判断 |
|
||||
| ----------- | -------- |
|
||||
| `±10%` 内 | 正常 |
|
||||
| `10% ~ 20%` | 需观察 |
|
||||
| `> 20%` | 必须调参 |
|
||||
|
||||
这就是“评估每一章获得经验速度”的正式口径,不再用主观感觉判断。
|
||||
|
||||
---
|
||||
|
||||
## 7. NPC 自动定级规则
|
||||
|
||||
## 7.1 默认角色分类
|
||||
|
||||
建议默认按当前幕和敌我属性推导 `progressionRole`:
|
||||
|
||||
1. 当前幕 `primaryNpcId`
|
||||
|
||||
- 若 hostile:`hostile_elite` 或 `hostile_boss`
|
||||
- 若非 hostile:`guide` 或 `rival`
|
||||
|
||||
2. 非主角色 hostile NPC
|
||||
|
||||
- `hostile_standard`
|
||||
|
||||
3. 非主角色友方 NPC
|
||||
- `support` 或 `ambient`
|
||||
|
||||
如需修正,再允许章节蓝图加可选 override,但不要求创作者每次手填。
|
||||
|
||||
## 7.2 等级锚点
|
||||
|
||||
每章先得到:
|
||||
|
||||
1. `entryLevel`
|
||||
2. `exitLevel`
|
||||
|
||||
然后按当前阶段得到阶段锚点:
|
||||
|
||||
| 阶段 | 目标锚点 |
|
||||
| --------------- | ----------------------------- |
|
||||
| `opening` | 接近 `entryLevel` |
|
||||
| `expansion` | `entryLevel ~ exitLevel` 中段 |
|
||||
| `turning_point` | 接近 `exitLevel` |
|
||||
| `climax` | `exitLevel` |
|
||||
| `aftermath` | `exitLevel - 1` 或持平 |
|
||||
|
||||
## 7.3 最终定级
|
||||
|
||||
建议公式:
|
||||
|
||||
```ts
|
||||
baseStageLevel = interpolate(entryLevel, exitLevel, stageProgress);
|
||||
|
||||
npcLevel = round(baseStageLevel) + roleOffset(progressionRole);
|
||||
```
|
||||
|
||||
建议 offset:
|
||||
|
||||
| role | offset |
|
||||
| ------------------ | -------- |
|
||||
| `ambient` | `-1` |
|
||||
| `support` | `0` |
|
||||
| `guide` | `0` |
|
||||
| `rival` | `0 ~ +1` |
|
||||
| `hostile_standard` | `0` |
|
||||
| `hostile_elite` | `+1` |
|
||||
| `hostile_boss` | `+2` |
|
||||
|
||||
约束:
|
||||
|
||||
1. 统一 clamp 到 `1 ~ terminalStoryLevel + 2`
|
||||
2. 不允许出现“第 3 章普通怪高于第 6 章精英”的跨章倒挂
|
||||
3. `hostile_boss` 如果需要更强,必须给更高等级,不准同级偷倍数
|
||||
|
||||
## 7.4 同级不同风格
|
||||
|
||||
NPC 等级确定后,再把 `referenceStrength` 套到具体风格:
|
||||
|
||||
1. 重装型:
|
||||
|
||||
- 生命占比更高
|
||||
- 爆发占比更低
|
||||
|
||||
2. 迅捷型:
|
||||
|
||||
- 生命占比更低
|
||||
- 出手与压制占比更高
|
||||
|
||||
3. 控场型:
|
||||
- 法力/控制预算更高
|
||||
|
||||
但这一步只能做“分布调整”,不能改变同级总参考强度。
|
||||
|
||||
---
|
||||
|
||||
## 8. 与当前仓库的接入点
|
||||
|
||||
## 8.1 第一批必须改的类型
|
||||
|
||||
1. `src/types/game.ts`
|
||||
|
||||
- 新增 `playerProgression`
|
||||
|
||||
2. `src/types/story.ts`
|
||||
|
||||
- `QuestReward.experience`
|
||||
|
||||
3. `src/types/scene.ts`
|
||||
|
||||
- `SceneNpc.levelProfile`
|
||||
- `SceneHostileNpc.levelProfile`
|
||||
- `SceneHostileNpc.experienceReward`
|
||||
|
||||
4. `packages/shared/src/contracts/story.ts`
|
||||
- 如果需要让前后端合同正式共享等级展示字段,在这里补最小契约
|
||||
|
||||
## 8.2 第一批必须改的后端模块
|
||||
|
||||
1. `server-node/src/modules/quest/questStoryActionService.ts`
|
||||
|
||||
- `resolveQuestTurnInAction(...)` 里追加任务经验发放
|
||||
|
||||
2. `server-node/src/modules/quest/questRuntimeSignalService.ts`
|
||||
|
||||
- 保持 quest signal 职责
|
||||
- 不直接负责经验裁决,只把可用信号交给 progression 模块
|
||||
|
||||
3. `server-node/src/modules/combat/**`
|
||||
|
||||
- 在胜利结算后发 hostile NPC 经验
|
||||
|
||||
4. `server-node/src/modules/story/**`
|
||||
|
||||
- 在切章、进场、恢复场景时接入章节成长计划与 ledger
|
||||
|
||||
5. 新增 `server-node/src/modules/progression/**`
|
||||
- 成为等级、经验、章节定级唯一真相源
|
||||
|
||||
## 8.3 第一批不建议重写的部分
|
||||
|
||||
这轮不建议一开始就重写:
|
||||
|
||||
1. 整套前端战斗 UI
|
||||
2. 整套属性系统
|
||||
3. Quest UI 大面板结构
|
||||
4. 所有 hostile preset 原始配置文件
|
||||
|
||||
更稳的做法是:
|
||||
|
||||
1. 先让后端算出等级与经验
|
||||
2. 再把结果投影到现有运行时字段
|
||||
3. 最后再逐步清理旧静态强度残留
|
||||
|
||||
---
|
||||
|
||||
## 9. 迁移策略
|
||||
|
||||
## 9.1 旧存档兼容
|
||||
|
||||
旧存档没有 `playerProgression` 时:
|
||||
|
||||
1. 默认初始化为 `Lv.1`
|
||||
2. `totalXp = 0`
|
||||
3. `currentLevelXp = 0`
|
||||
4. `xpToNextLevel = benchmark[1].xpToNextLevel`
|
||||
|
||||
如果后续希望更平滑,可在第二轮增加“按当前章节进度反推起始等级”的迁移脚本,但首版先不要让迁移复杂化。
|
||||
|
||||
## 9.2 旧 hostile preset 兼容
|
||||
|
||||
旧 preset 里的 `hp/maxHp` 首版处理建议:
|
||||
|
||||
1. 先保留原字段作为 style hint
|
||||
2. 运行时用 level benchmark 覆盖最终 `hp/maxHp`
|
||||
3. 保证当前素材和行为标签不需要重做
|
||||
|
||||
## 9.3 旧任务兼容
|
||||
|
||||
旧任务没有 `reward.experience` 时:
|
||||
|
||||
1. 默认按 `0` 处理
|
||||
2. 仅新生成或重新编译的任务带经验
|
||||
3. 章节主任务优先切到新编译链
|
||||
|
||||
---
|
||||
|
||||
## 10. 开发顺序
|
||||
|
||||
## 阶段 A:先把等级状态立住
|
||||
|
||||
先做:
|
||||
|
||||
1. `PlayerProgressionState`
|
||||
2. `LevelBenchmark[]`
|
||||
3. 经验加点与升级服务
|
||||
|
||||
验收:
|
||||
|
||||
1. 后端能正确加经验与升级
|
||||
2. 前端能稳定展示 `Lv. X / 经验条`
|
||||
|
||||
## 阶段 B:接任务经验
|
||||
|
||||
先做:
|
||||
|
||||
1. `QuestReward.experience`
|
||||
2. `quest turn-in` 经验发放
|
||||
3. 任务结果文案里补 `经验 +N`
|
||||
|
||||
验收:
|
||||
|
||||
1. 交付任务后能加经验
|
||||
2. 升级时能正确连跳
|
||||
|
||||
## 阶段 C:接章节预算与 NPC 自动定级
|
||||
|
||||
先做:
|
||||
|
||||
1. `ChapterProgressionPlan`
|
||||
2. `npcLevelResolver`
|
||||
3. runtime hostile NPC 经验值生成
|
||||
|
||||
验收:
|
||||
|
||||
1. 进入不同章节时 NPC 等级自动变化
|
||||
2. 同级不同风格但参考强度一致
|
||||
|
||||
## 阶段 D:接击败敌对 NPC 经验与章节 ledger
|
||||
|
||||
先做:
|
||||
|
||||
1. hostile defeat 经验
|
||||
2. `ChapterExperienceLedger`
|
||||
3. 章节偏差评估输出
|
||||
|
||||
验收:
|
||||
|
||||
1. 每章都能看到计划/实际经验偏差
|
||||
2. 重复刷同章敌对 NPC 不会破坏曲线
|
||||
|
||||
---
|
||||
|
||||
## 11. 验收标准
|
||||
|
||||
做到下面这些,才算这次等级系统设计真正落地:
|
||||
|
||||
1. 玩家正式拥有 `等级 + 经验 + 升级` 主链。
|
||||
2. 经验来源只通过后端发放,前端不本地算经验。
|
||||
3. 同等级实体共享同一档 `参考强度`。
|
||||
4. 每章都能生成 `入章等级 / 出章等级 / 经验预算`。
|
||||
5. 每章的 NPC 都能按章节自动定级。
|
||||
6. 完成任务、击败敌对 NPC 都能稳定获得经验。
|
||||
7. 章节结束后能评估“这一章经验速度是否正常”。
|
||||
8. 现有任务、章节、属性和 hostile NPC 主链不被推翻,只是在其上新增成长预算层。
|
||||
|
||||
---
|
||||
|
||||
## 12. 最后结论
|
||||
|
||||
这次等级系统设计的重点,不是简单在 UI 上加一个 `Lv.1`,而是把当前仓库里已经存在的:
|
||||
|
||||
1. 章节闭环
|
||||
2. 任务结算
|
||||
3. 敌对 NPC 胜利事件
|
||||
4. 统一属性与 hostile preset
|
||||
|
||||
收束到一条新的成长主链:
|
||||
|
||||
**章节先给出目标等级与经验速度,系统再按这套速度自动设置 NPC 等级,并把任务交付与击败敌对 NPC 统一变成可控的经验入口。**
|
||||
|
||||
这样之后,等级不再只是一个展示数字,而会真正变成:
|
||||
|
||||
- 玩家成长速度的刻度
|
||||
- 同级参考强度的刻度
|
||||
- 章节节奏是否合理的刻度
|
||||
- 不同章节 NPC 强度自动落位的刻度
|
||||
@@ -1,6 +1,6 @@
|
||||
# 平台层 UI 去像素化刷新设计
|
||||
|
||||
更新时间:`2026-04-19`
|
||||
更新时间:`2026-04-20`
|
||||
|
||||
## 1. 目标
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
- 设置面板必须支持平台亮色 / 暗色主题切换,并复用同一套平台 token 驱动登录页、首页、详情页与二三级面板
|
||||
- 首页移动端底部 Tab 与桌面侧边导航的图标底座、图标颜色、文字状态必须全部由平台 token 驱动;暗色主题下不得出现过浅底座和错误文字色,亮色主题下不得残留旧灰蓝 inactive 状态
|
||||
- 首页、存档页、作品详情这类平台主导航与局部 Tab 的 active fill、active shadow、icon shell fill 必须全部来自主题 token;暗色主题禁止继续复用亮色主题的粉橘高光、白色 active 底座
|
||||
- 创作链路中的吸顶返回栏、目录 Tab 条、搜索工具条也必须走平台亮暗主题 token;暗色主题禁止继续写死暖白渐变或浅粉背景作为顶部衬底
|
||||
- “我的”页账号主卡必须跟随平台亮 / 暗主题联动,不允许继续写死浅色渐变卡面与 `slate` 系按钮
|
||||
|
||||
## 4. 交互与布局约束
|
||||
@@ -99,6 +100,8 @@
|
||||
- 新样式优先沉淀为平台专用 class / theme token,避免把游戏内像素 class 改坏
|
||||
- 平台默认挂载亮色主题 class,旧紫蓝方案保留为暗色主题 class
|
||||
- 亮色主题需要补齐统一的 overlay、progress track、status pill token,登录弹层与二三级功能面板禁止继续沿用旧深色遮罩与紫蓝强调残留
|
||||
- 亮色主题下平台壳层与各个 Tab 页的 page stage 必须以暖白底为主,禁止继续让高饱和深粉底或旧深色底透成页面主背景
|
||||
- 亮色主题下平台主内容区、page stage、移动端底部 Tab 容器都必须使用接近实色的暖白底,禁止继续用高透明度浅色层叠在深底上造成整体发灰
|
||||
- 平台态中仍保留旧 Tailwind 深色类的历史组件,必须通过平台 remap 容器或平台专用 class 统一收口,不能放任 `bg-[#111318]`、`bg-black/*`、`bg-white/*` 这类旧类在亮色主题下直接裸露
|
||||
- 编辑弹窗保留业务结构与表单逻辑,只替换壳层样式
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
- [CUSTOM_WORLD_TEMPLATE_DECOUPLING_AND_CROSS_GENRE_GENERALIZATION_DESIGN_2026-04-08.md](./CUSTOM_WORLD_TEMPLATE_DECOUPLING_AND_CROSS_GENRE_GENERALIZATION_DESIGN_2026-04-08.md):把自定义世界从武侠/仙侠模板依赖迁到跨题材通用设定层的优化设计。
|
||||
- [CUSTOM_WORLD_SELF_OWNED_SETTING_LAYER_OPTIMIZATION_2026-04-08.md](./CUSTOM_WORLD_SELF_OWNED_SETTING_LAYER_OPTIMIZATION_2026-04-08.md):把模板依赖逐步迁成自定义世界自有设定层,并保证不破坏当前生成流程的优化方案。
|
||||
- [AI_NATIVE_RUNTIME_ITEM_SYSTEM_REDESIGN_2026-04-02.md](./AI_NATIVE_RUNTIME_ITEM_SYSTEM_REDESIGN_2026-04-02.md):运行时物品生成系统重设计。
|
||||
- [LEVEL_PROGRESS_AND_CHAPTER_NPC_AUTO_SCALING_DESIGN_2026-04-20.md](./LEVEL_PROGRESS_AND_CHAPTER_NPC_AUTO_SCALING_DESIGN_2026-04-20.md):等级成长、章节经验节奏与 NPC 自动定级设计。
|
||||
- [RPG_NARRATIVE_PLANNING_FULL_PIPELINE_WORKFLOW_2026-04-12.md](./RPG_NARRATIVE_PLANNING_FULL_PIPELINE_WORKFLOW_2026-04-12.md):专业剧情策划构建 RPG 游戏全剧情的工作流程与交付模板。
|
||||
- [EQUIPMENT_BUILD_AND_FORGE_LOOP_SYSTEM_DESIGN.md](./EQUIPMENT_BUILD_AND_FORGE_LOOP_SYSTEM_DESIGN.md):配装构筑与合成/锻造闭环设计。
|
||||
- [COMPANION_FIRST_CONTACT_RELATIONSHIP_AND_PRIVATE_CHAT_DESIGN_2026-04-04.md](./COMPANION_FIRST_CONTACT_RELATIONSHIP_AND_PRIVATE_CHAT_DESIGN_2026-04-04.md):角色首遇感、关系分层解锁、私聊系统设计。
|
||||
@@ -31,4 +32,5 @@
|
||||
- 做“高好感聊天里如何顺着上下文自然抛出委托、并让任务在聊天内领取”的需求时,优先看新增的聊天委托流程设计稿。
|
||||
- 做剧情引擎章节化、场景闭环、章节任务接入时,优先看新增的场景章节设计稿。
|
||||
- 做“单章节体验还缺什么、该补哪种情感 / 抉择 / 试炼模块”时,优先看新增的章节对标补强设计稿。
|
||||
- 做等级成长、任务/击败敌对 NPC 发经验、章节经验速度评估、NPC 自动定级时,优先看新增的等级系统设计稿。
|
||||
- 如果要判断是否符合目标,再和 `docs/prd/` 中对应 PRD 对照阅读。
|
||||
|
||||
@@ -254,58 +254,49 @@ MVP 支持三种主形象输入方式:
|
||||
|
||||
MVP 必须与当前项目可扮演角色动作槽位对齐。
|
||||
|
||||
当前落地实现补充约束(`2026-04-19`):
|
||||
当前落地实现补充约束(`2026-04-20`):
|
||||
|
||||
- 角色资产工坊默认固定生成入口收敛为 `idle / run / attack / die`
|
||||
- `hurt` 不再作为固定按钮动作
|
||||
- 角色资产工坊固定生成入口仍为 `idle / run / attack / die`
|
||||
- `run / attack` 是固定基础必生成动作
|
||||
- `idle / die` 改为固定可选动作,不再作为发布硬门槛
|
||||
- `idle` 未生成时默认直接使用主图静止显示
|
||||
- `die` 未生成时默认播放一段基于主图的倒地过渡动画,并最终停在翻转倒地姿态
|
||||
- 角色已配置的每个技能,都必须在技能编辑面板里补出对应动作预览
|
||||
- 图生视频默认走火山方舟 `Seedance` 首尾帧方案
|
||||
- 接口请求体中的两张参考图分别固定为 `first_frame / last_frame`
|
||||
- 固定参数为 `1:1`、`480p`、`4 秒`、单次 `1` 个视频
|
||||
- 提示词中的动作名统一传英文动作名
|
||||
|
||||
第一版要求以下基础动作槽位不能为空:
|
||||
第一版动作生成按下面两层规则落地:
|
||||
|
||||
| 动作槽位 | 是否必填 | 备注 |
|
||||
| --- | --- | --- |
|
||||
| `idle` | 必填 | 循环动作 |
|
||||
| `acquire` | 必填 | 可由短变体衍生 |
|
||||
| `attack` | 必填 | 一次性动作 |
|
||||
| `run` | 必填 | 循环动作 |
|
||||
| `jump` | 必填 | 一次性动作 |
|
||||
| `double_jump` | 必填 | 可由跳跃二次变体生成 |
|
||||
| `jump_attack` | 必填 | 一次性动作 |
|
||||
| `dash` | 必填 | 一次性动作 |
|
||||
| `hurt` | 必填 | 一次性动作 |
|
||||
| `die` | 必填 | 一次性动作 |
|
||||
| `climb` | 必填 | 可由模板生成 |
|
||||
| `wall_slide` | 必填 | 可由攀爬停帧变体生成 |
|
||||
| 类别 | 动作槽位 | 是否必填 | 备注 |
|
||||
| -------- | ------------------------------- | -------- | -------------------------------------------------- |
|
||||
| 基础动作 | `run` | 必填 | 角色移动主循环动作 |
|
||||
| 基础动作 | `attack` | 必填 | 角色普通攻击主动作 |
|
||||
| 技能动作 | `skills[*].actionPreviewConfig` | 必填 | 当前角色每个已配置技能都要有独立动作资源 |
|
||||
| 可选动作 | `idle` | 可选 | 缺失时默认走主图静止待机 |
|
||||
| 可选动作 | `die` | 可选 | 缺失时默认走主图倒地过渡动画,最终停在翻转倒地姿态 |
|
||||
|
||||
这里“不能为空”指的是:
|
||||
这里“必生成”指的是:
|
||||
|
||||
- 每个槽位必须最终指向一套可播放的资源
|
||||
- 允许少量槽位由近似动作衍生
|
||||
- 但不允许在运行时读到空动画映射
|
||||
- `run / attack` 必须最终指向可播放资源
|
||||
- 每个已配置技能都必须带独立 `actionPreviewConfig`
|
||||
- 发布判定不再要求 `idle / die` 一定存在动画映射
|
||||
- 运行时仍然不能出现无可用表现;`idle / die` 的缺口由默认兜底承担
|
||||
|
||||
## 8.2 技能动作要求
|
||||
|
||||
本期不要求自动补齐:
|
||||
本期不再要求把整套固定技能枚举一次性自动补齐,但对“角色当前实际配置的技能”改为必做:
|
||||
|
||||
- `skill1`
|
||||
- `skill1_jump`
|
||||
- `skill1_bullet`
|
||||
- `skill1_bullet_fx`
|
||||
- `skill2`
|
||||
- `skill2_jump`
|
||||
- `skill3`
|
||||
- `skill3_jump`
|
||||
- `skill3_bullet`
|
||||
- `skill3_bullet_fx`
|
||||
- `skill4`
|
||||
- 不要求预先把 `skill1 / skill2 / skill3 / skill4` 这套历史枚举全部补满
|
||||
- 只要求当前角色 `skills` 数组里的每个技能都生成独立动作预览
|
||||
- 技能动作生成入口继续放在技能编辑面板逐个处理,不塞进固定四按钮里
|
||||
|
||||
结论:
|
||||
|
||||
- 技能动作本期可选
|
||||
- 基础动作本期必做
|
||||
- 技能动作从“固定枚举可选”调整为“按角色已配技能必做”
|
||||
- 固定基础动作收敛为 `run / attack`
|
||||
- `idle / die` 保留为可选增强动作
|
||||
|
||||
## 8.3 动作生成方式
|
||||
|
||||
@@ -606,7 +597,7 @@ type GeneratedCharacterAnimationAsset = {
|
||||
|
||||
目标:
|
||||
|
||||
- 让基础动作槽位全部非空,并可一键发布
|
||||
- 让必生成动作全部就绪,并为 `idle / die` 提供明确默认兜底
|
||||
|
||||
产出:
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
在 `CustomWorldAgentDraftDetailPanel` 中,当当前卡类型为:
|
||||
|
||||
```ts
|
||||
kind === 'character'
|
||||
kind === 'character';
|
||||
```
|
||||
|
||||
显示按钮:
|
||||
@@ -239,11 +239,19 @@ kind === 'character'
|
||||
|
||||
基于主图生成当前工坊支持的核心动作:
|
||||
|
||||
1. `run`
|
||||
2. `attack`
|
||||
|
||||
可选增强动作:
|
||||
|
||||
1. `idle`
|
||||
2. `run`
|
||||
3. `attack`
|
||||
4. `hurt`
|
||||
5. `die`
|
||||
2. `die`
|
||||
|
||||
补充约束:
|
||||
|
||||
1. `run / attack` 为固定必生成动作
|
||||
2. 角色已配置技能时,对应技能动作也属于必生成动作
|
||||
3. `idle / die` 只作为可选增强,缺失时分别走主图静止 / 主图倒地过渡动画兜底,死亡动画最终停在翻转倒地姿态
|
||||
|
||||
### 阶段 D:动作发布
|
||||
|
||||
@@ -350,15 +358,15 @@ type CustomWorldRoleAssetStatus =
|
||||
发布主图成功后,必须写回:
|
||||
|
||||
```ts
|
||||
imageSrc
|
||||
generatedVisualAssetId
|
||||
imageSrc;
|
||||
generatedVisualAssetId;
|
||||
```
|
||||
|
||||
发布动作成功后,必须写回:
|
||||
|
||||
```ts
|
||||
generatedAnimationSetId
|
||||
animationMap
|
||||
generatedAnimationSetId;
|
||||
animationMap;
|
||||
```
|
||||
|
||||
### 明确要求
|
||||
@@ -440,8 +448,8 @@ type SyncRoleAssetsResult = {
|
||||
### 输入
|
||||
|
||||
```ts
|
||||
buildRoleAssetStudioContext(snapshot, roleId)
|
||||
applyRoleAssetPublishResult(snapshot, payload)
|
||||
buildRoleAssetStudioContext(snapshot, roleId);
|
||||
applyRoleAssetPublishResult(snapshot, payload);
|
||||
```
|
||||
|
||||
### 说明
|
||||
@@ -465,8 +473,8 @@ applyRoleAssetPublishResult(snapshot, payload)
|
||||
### 导出函数建议
|
||||
|
||||
```ts
|
||||
rebuildRoleAssetCoverage(draftProfile)
|
||||
mergeRoleAssetIntoDraftProfile(draftProfile, payload)
|
||||
rebuildRoleAssetCoverage(draftProfile);
|
||||
mergeRoleAssetIntoDraftProfile(draftProfile, payload);
|
||||
```
|
||||
|
||||
## 10.3 修改 `customWorldAgentOrchestrator.ts`
|
||||
@@ -598,7 +606,7 @@ showRoleAssetStudio: boolean;
|
||||
3. 统一回调:
|
||||
|
||||
```ts
|
||||
onPublishSuccess(payload)
|
||||
onPublishSuccess(payload);
|
||||
```
|
||||
|
||||
### `onPublishSuccess` 最小字段
|
||||
|
||||
@@ -39,9 +39,11 @@
|
||||
目标用户分三类:
|
||||
|
||||
1. 轻创作者
|
||||
|
||||
- 有世界灵感,但不擅长结构化填表
|
||||
|
||||
2. 中度创作者
|
||||
|
||||
- 愿意精修角色、地点、主线第一幕,但不想维护大量底层字段
|
||||
|
||||
3. 重度创作者
|
||||
@@ -138,37 +140,48 @@
|
||||
本次 PRD 必须复用以下现有基础:
|
||||
|
||||
1. `src/services/customWorldCreatorIntent.ts`
|
||||
|
||||
- 已有创作者意图、锚点包、锁定状态的基础结构
|
||||
|
||||
2. `src/types/customWorld.ts`
|
||||
|
||||
- 已有 `creatorIntent / anchorPack / lockState / generationMode / generationStatus`
|
||||
|
||||
3. `src/services/aiService.ts`
|
||||
|
||||
- 已有自定义世界 session 与生成 API 客户端
|
||||
|
||||
4. `server-node/src/services/customWorldSessionStore.ts`
|
||||
|
||||
- 已有澄清问题与 session 的基础概念
|
||||
|
||||
5. `server-node/src/services/customWorldGenerationService.ts`
|
||||
|
||||
- 已有分阶段生成骨架
|
||||
|
||||
6. `src/components/game-shell/PreGameSelectionFlow.tsx`
|
||||
|
||||
- 已有世界创建流程入口
|
||||
|
||||
7. `src/components/CustomWorldResultView.tsx`
|
||||
|
||||
- 已有结果页壳层
|
||||
|
||||
8. `src/components/CustomWorldRoleAssetStudioModal.tsx`
|
||||
|
||||
- 已有角色主图与核心动作资产工坊原型
|
||||
|
||||
9. `src/services/ai.ts`
|
||||
|
||||
- 已有 `generateCustomWorldSceneImage(...)` 场景图生成入口
|
||||
|
||||
10. `server-node/src/modules/assets/characterAssetRoutes.ts`
|
||||
- 已有角色主图发布、角色动作发布、动作模板等资产路由
|
||||
|
||||
- 已有角色主图发布、角色动作发布、动作模板等资产路由
|
||||
|
||||
11. `server-node/src/routes/runtimeRoutes.ts`
|
||||
- 已有 `/custom-world/scene-image` 场景背景图生成路由
|
||||
|
||||
- 已有 `/custom-world/scene-image` 场景背景图生成路由
|
||||
|
||||
## 3.2 必须替换或重构的现有行为
|
||||
|
||||
@@ -220,6 +233,7 @@
|
||||
最终必须输出两类产物:
|
||||
|
||||
1. 创作工作产物
|
||||
|
||||
- 世界圣经摘要
|
||||
- 关键角色卡
|
||||
- 关键地点卡
|
||||
@@ -478,9 +492,11 @@ type CustomWorldAssetPriorityTier = 'hero' | 'featured' | 'supporting';
|
||||
判定规则:
|
||||
|
||||
1. `hero`
|
||||
|
||||
- 所有 `playableNpcs`
|
||||
|
||||
2. `featured`
|
||||
|
||||
- 被锁定的 `storyNpcs`
|
||||
- 主线第一幕直接关联的 `storyNpcs`
|
||||
- 势力代表角色
|
||||
@@ -499,6 +515,7 @@ type CustomWorldScenePriorityTier = 'key' | 'supporting';
|
||||
判定规则:
|
||||
|
||||
1. `key`
|
||||
|
||||
- `camp`
|
||||
- 被锁定的 `landmark`
|
||||
- 主线第一幕直接关联的 `landmark`
|
||||
@@ -530,32 +547,43 @@ type CustomWorldScenePriorityTier = 'key' | 'supporting';
|
||||
|
||||
### 动作抽卡策略
|
||||
|
||||
角色动作不能一开始就把完整核心动作集全部抽出来。
|
||||
角色动作不能一开始就把所有动作一次性抽完。
|
||||
|
||||
必须采用两段式:
|
||||
必须采用“先必需、再增强”的两层策略:
|
||||
|
||||
#### 阶段 A:动作试片
|
||||
#### 阶段 A:基础必需动作
|
||||
|
||||
每个角色先只生成:
|
||||
每个角色先生成:
|
||||
|
||||
1. `idle`
|
||||
1. `run`
|
||||
2. `attack`
|
||||
|
||||
用途:
|
||||
|
||||
1. 检查角色一致性是否稳定
|
||||
2. 检查动作风格是否匹配
|
||||
2. 检查移动和出手两条主动作是否可用
|
||||
3. 检查武器、衣摆和轮廓是否容易漂移
|
||||
|
||||
#### 阶段 B:完整核心动作集
|
||||
#### 阶段 B:技能动作补齐
|
||||
|
||||
只有当动作试片确认通过后,才允许生成:
|
||||
当角色基础动作通过后,再逐个补当前角色已经配置的技能动作。
|
||||
|
||||
1. `run`
|
||||
2. `hurt`
|
||||
3. `die`
|
||||
要求:
|
||||
|
||||
加上已确认的 `idle / attack`,组成当前阶段完整核心动作集。
|
||||
1. 每个技能都必须有独立 `actionPreviewConfig`
|
||||
2. 技能动作入口放在技能编辑面板,不并入固定四按钮
|
||||
|
||||
#### 可选增强动作
|
||||
|
||||
以下动作不再作为发布硬门槛,可按需要补:
|
||||
|
||||
1. `idle`
|
||||
2. `die`
|
||||
|
||||
默认兜底:
|
||||
|
||||
1. `idle` 缺失时使用主图静止
|
||||
2. `die` 缺失时使用主图倒地过渡动画,最终停在翻转倒地姿态
|
||||
|
||||
### 场景图抽卡策略
|
||||
|
||||
@@ -616,16 +644,26 @@ type CustomWorldScenePriorityTier = 'key' | 'supporting';
|
||||
|
||||
发布前,每个角色至少需要以下动作槽位可用:
|
||||
|
||||
1. `idle`
|
||||
2. `run`
|
||||
3. `attack`
|
||||
4. `hurt`
|
||||
5. `die`
|
||||
1. `run`
|
||||
2. `attack`
|
||||
3. 当前角色 `skills` 中每个技能的 `actionPreviewConfig`
|
||||
|
||||
判定方式:
|
||||
|
||||
1. `generatedAnimationSetId` 非空
|
||||
2. `animationMap` 中以上 5 个槽位都存在有效映射
|
||||
2. `animationMap` 中至少存在有效的 `run / attack`
|
||||
3. `skills` 数组里的每个技能都带有效 `actionPreviewConfig`
|
||||
|
||||
可选动作:
|
||||
|
||||
1. `idle`
|
||||
2. `die`
|
||||
|
||||
说明:
|
||||
|
||||
1. `idle / die` 不再是发布硬门槛
|
||||
2. `idle` 缺失时运行时默认使用主图静止
|
||||
3. `die` 缺失时运行时默认播放主图倒地过渡动画,最终停在翻转倒地姿态
|
||||
|
||||
说明:
|
||||
|
||||
@@ -664,34 +702,34 @@ type CustomWorldAgentStage =
|
||||
|
||||
## 6.2 状态迁移规则
|
||||
|
||||
| 当前阶段 | 触发 | 下一阶段 |
|
||||
| --- | --- | --- |
|
||||
| `collecting_intent` | 最小锚点不足,Agent 追问 | `clarifying` |
|
||||
| `clarifying` | 用户补齐锚点 | `foundation_review` |
|
||||
| `collecting_intent` | 用户信息已足够并请求底稿 | `foundation_review` |
|
||||
| `foundation_review` | 用户精修关键对象 | `object_refining` |
|
||||
| `object_refining` | 用户请求生成角色或场景资产 | `visual_refining` |
|
||||
| `visual_refining` | 关键角色与场景资产进入可用状态 | `long_tail_review` |
|
||||
| `object_refining` | 用户明确跳过人工精修并走自动补齐 | `long_tail_review` |
|
||||
| `long_tail_review` | 用户请求发布 | `ready_to_publish` |
|
||||
| `ready_to_publish` | 发布成功 | `published` |
|
||||
| 任意阶段 | 发生不可恢复错误 | `error` |
|
||||
| 当前阶段 | 触发 | 下一阶段 |
|
||||
| ------------------- | -------------------------------- | ------------------- |
|
||||
| `collecting_intent` | 最小锚点不足,Agent 追问 | `clarifying` |
|
||||
| `clarifying` | 用户补齐锚点 | `foundation_review` |
|
||||
| `collecting_intent` | 用户信息已足够并请求底稿 | `foundation_review` |
|
||||
| `foundation_review` | 用户精修关键对象 | `object_refining` |
|
||||
| `object_refining` | 用户请求生成角色或场景资产 | `visual_refining` |
|
||||
| `visual_refining` | 关键角色与场景资产进入可用状态 | `long_tail_review` |
|
||||
| `object_refining` | 用户明确跳过人工精修并走自动补齐 | `long_tail_review` |
|
||||
| `long_tail_review` | 用户请求发布 | `ready_to_publish` |
|
||||
| `ready_to_publish` | 发布成功 | `published` |
|
||||
| 任意阶段 | 发生不可恢复错误 | `error` |
|
||||
|
||||
## 6.3 阶段显示规则
|
||||
|
||||
前端顶部摘要区必须展示当前阶段中文标签:
|
||||
|
||||
| 阶段 | 展示文案 |
|
||||
| --- | --- |
|
||||
| 阶段 | 展示文案 |
|
||||
| ------------------- | ------------ |
|
||||
| `collecting_intent` | 收集世界锚点 |
|
||||
| `clarifying` | 补充关键设定 |
|
||||
| `clarifying` | 补充关键设定 |
|
||||
| `foundation_review` | 校对世界底稿 |
|
||||
| `object_refining` | 精修关键对象 |
|
||||
| `visual_refining` | 生成视觉资产 |
|
||||
| `long_tail_review` | 补全长尾内容 |
|
||||
| `ready_to_publish` | 准备发布 |
|
||||
| `published` | 已发布 |
|
||||
| `error` | 处理异常 |
|
||||
| `object_refining` | 精修关键对象 |
|
||||
| `visual_refining` | 生成视觉资产 |
|
||||
| `long_tail_review` | 补全长尾内容 |
|
||||
| `ready_to_publish` | 准备发布 |
|
||||
| `published` | 已发布 |
|
||||
| `error` | 处理异常 |
|
||||
|
||||
---
|
||||
|
||||
@@ -980,7 +1018,15 @@ interface SendCustomWorldAgentMessageResponse {
|
||||
type CustomWorldAgentActionRequest =
|
||||
| { action: 'lock_cards'; cardIds: string[] }
|
||||
| { action: 'unlock_cards'; cardIds: string[] }
|
||||
| { action: 'regenerate_scope'; scope: 'focus_card' | 'long_tail_npcs' | 'long_tail_landmarks' | 'sidequest_seeds'; targetCardId?: string | null }
|
||||
| {
|
||||
action: 'regenerate_scope';
|
||||
scope:
|
||||
| 'focus_card'
|
||||
| 'long_tail_npcs'
|
||||
| 'long_tail_landmarks'
|
||||
| 'sidequest_seeds';
|
||||
targetCardId?: string | null;
|
||||
}
|
||||
| { action: 'draft_foundation' }
|
||||
| { action: 'generate_role_assets'; roleIds: string[] }
|
||||
| {
|
||||
@@ -1909,9 +1955,12 @@ Agent 会话每次 operation 完成后自动保存 session snapshot。
|
||||
15. `src/components/custom-world-agent/CustomWorldAgentDraftDetailPanel.tsx`
|
||||
16. `src/components/custom-world-agent/CustomWorldSceneAssetStudioModal.tsx`
|
||||
17. `src/components/CustomWorldRoleAssetStudioModal.tsx`
|
||||
- 改成 Agent 可调用版
|
||||
|
||||
- 改成 Agent 可调用版
|
||||
|
||||
18. `src/components/asset-studio/characterAssetWorkflowPersistence.ts`
|
||||
- 继续复用现有资产接口客户端
|
||||
|
||||
- 继续复用现有资产接口客户端
|
||||
|
||||
## 15.3 backend
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
- 技能冷却要按“本次动作结束后”推进
|
||||
- 恢复类动作可额外提供冷却推进收益
|
||||
- 物品动作在战斗态下也算一次战斗回合
|
||||
- 战斗中使用物品要先结算物品恢复 / buff / 额外冷却收益,再结算这一回合是否承受敌方单次反击
|
||||
|
||||
### 4.3 结果文本
|
||||
|
||||
@@ -200,6 +201,12 @@ ongoing battle 的本地/后端结果文本只负责说明这一次动作结算
|
||||
5. 前端支持 disabled battle option 展示
|
||||
6. 文档、测试同步更新
|
||||
|
||||
补充落地备注(2026-04-20):
|
||||
|
||||
- `inventory_use` 在战斗中按战斗动作结算,而不是按非战斗库存动作直接短路返回
|
||||
- 战斗态 `inventory_use` 使用后要消费物品、累计 `itemsUsed`、推进 1 回合基础冷却,再叠加物品自带的 `cooldownReduction`
|
||||
- 若物品动作结算后战斗仍在继续,`storyText` 直接等于本次战斗结果文本,不触发 AI 续写
|
||||
|
||||
本期不做:
|
||||
|
||||
1. 新增复杂目标选择 UI
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# “我的”Tab 设置与账号安全 PRD
|
||||
|
||||
更新时间:`2026-04-19`
|
||||
更新时间:`2026-04-20`
|
||||
|
||||
## 0. 目标
|
||||
|
||||
@@ -56,7 +56,12 @@
|
||||
|
||||
## 3. 信息架构
|
||||
|
||||
设置中心建议固定为五段:
|
||||
设置中心首层固定为两段:
|
||||
|
||||
1. 主题外观
|
||||
2. 账号信息
|
||||
|
||||
其中“账号信息”二级面板固定承载以下内容:
|
||||
|
||||
1. 账号概况
|
||||
2. 当前安全状态
|
||||
@@ -66,10 +71,14 @@
|
||||
|
||||
交互层级要求补充为:
|
||||
|
||||
1. 设置首页只展示分区入口与危险操作,不在首页内联展开具体详情
|
||||
1. 设置首页只展示“主题外观”“账号信息”两个分区入口与危险操作,不在首页内联展开具体详情
|
||||
2. 点击任一分区入口后,必须进入独立二级面板
|
||||
3. 二级面板负责单一任务,不允许把详情继续堆在入口列表下面
|
||||
4. 更换手机号属于独立操作面板,不允许在账号概况面板内直接展开表单
|
||||
3. 安全状态、登录设备、操作记录不再作为首页独立入口,统一归入“账号信息”二级面板
|
||||
4. 更换手机号属于独立操作面板,不允许在账号信息面板内直接展开表单
|
||||
5. 设置首页头部只保留一套主标题,不允许在内容区再重复放置“设置首页”“选择要管理的内容”这类二次标题块
|
||||
6. 子面板导航动作必须单一明确;同一层面板内有“返回”时,不再同时展示“关闭”
|
||||
7. 设置首页与各级子面板都必须定义单一滚动容器,列表内容必须可稳定滚动,禁止外层与内层同时争夺滚动
|
||||
8. 二级或三级面板打开后,下层内容必须进入不可交互状态,并把焦点主动转移到当前面板内;禁止对仍保留焦点的祖先节点使用 `aria-hidden`
|
||||
|
||||
底部保留两个危险操作按钮:
|
||||
|
||||
@@ -87,7 +96,6 @@
|
||||
- 登录方式
|
||||
- 手机号脱敏值
|
||||
- 微信绑定状态
|
||||
- 账号状态
|
||||
|
||||
这里只看信息,不做大编辑动作。
|
||||
|
||||
@@ -201,11 +209,14 @@
|
||||
|
||||
1. 设置继续采用当前账号弹窗基础形态即可
|
||||
2. 移动端优先底部弹层,桌面端可居中弹窗
|
||||
3. 设置首页只保留分区入口,不直接承载分区详情内容
|
||||
4. 分区详情必须通过独立子面板承载,移动端优先使用全宽底部子弹层,桌面端使用覆盖在设置首页之上的居中子面板
|
||||
3. 设置首页只保留“主题外观”“账号信息”两个入口,不再单独展示安全状态、登录设备、操作记录入口
|
||||
4. “账号信息”二级面板直接承载账号概况、安全状态、登录设备、操作记录四块内容,移动端优先纵向滚动,桌面端保持同一面板内稳定扫读
|
||||
5. 更换手机号必须通过独立操作面板完成,不再使用当前面板内联展开表单
|
||||
6. 危险操作按钮与普通按钮必须明显区分
|
||||
7. 设置首页标题处禁止展示手机号、脱敏手机号或手机号形态的 displayName
|
||||
8. 设置首页不额外堆砌规则说明文案,标题下直接进入可操作内容
|
||||
9. 子面板采用覆盖式独立面板承载详情,返回上一级时恢复首页,不在同层同时出现双导航动作
|
||||
10. 面板切换必须保证键盘焦点始终停留在当前活跃面板内,返回上一级后焦点恢复到触发入口
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 平台“存档”Tab PRD
|
||||
|
||||
更新时间:`2026-04-19`
|
||||
更新时间:`2026-04-20`
|
||||
|
||||
## 0. 目标
|
||||
|
||||
@@ -84,15 +84,13 @@
|
||||
|
||||
## 3.1 存档 Tab 首屏结构
|
||||
|
||||
页面由两部分组成:
|
||||
页面首屏直接展示存档列表,不再单独保留顶部“最近存档”摘要卡。
|
||||
|
||||
1. 顶部摘要卡
|
||||
2. 存档列表
|
||||
列表容器本身需要承担首屏入口作用:
|
||||
|
||||
顶部摘要卡用于表达:
|
||||
|
||||
- 当前共有多少个可恢复存档
|
||||
- 最近一次更新的存档是谁
|
||||
- 用户进入“存档”Tab 后第一屏就看到可恢复存档列表
|
||||
- 不额外重复展示首个存档的大卡摘要
|
||||
- 存档数量、排序状态如需表达,应收敛在列表标题或轻量状态信息中
|
||||
|
||||
不要在 UI 中默认堆规则说明文案,只保留简洁的状态表达。
|
||||
|
||||
|
||||
@@ -274,6 +274,14 @@
|
||||
- 当前固定动作入口收敛为 `idle / run / attack / die`,不再内置固定 `hurt`
|
||||
- 提示词里传给视频模型的动作名统一使用英文动作名
|
||||
|
||||
实现更新(`2026-04-20`):
|
||||
|
||||
- `run / attack` 是当前固定动作入口里的基础必生成动作
|
||||
- `idle / die` 改为可选增强动作,不再作为资产完成度硬门槛
|
||||
- `idle` 缺失时运行时默认使用主图静止
|
||||
- `die` 缺失时运行时默认播放一段基于主图的倒地过渡动画,并最终停在翻转倒地姿态
|
||||
- 技能动作不走固定按钮,但对当前角色 `skills` 中的每个技能都属于必生成动作
|
||||
|
||||
## 5.3 补充路线:腾讯云相关能力
|
||||
|
||||
腾讯云相关接口里,`提交图片跳舞任务` 提供了:
|
||||
@@ -435,6 +443,11 @@
|
||||
|
||||
系统自动选择对应参考视频模板。
|
||||
|
||||
其中:
|
||||
|
||||
- `run / attack` 属于固定必生成动作
|
||||
- `idle / die` 属于固定可选动作,未生成时走默认兜底
|
||||
|
||||
`jump`、`hurt` 这类扩展动作不再作为当前编辑器固定按钮,改为后续扩展动作槽位或手动补齐。
|
||||
|
||||
### B. 视频驱动
|
||||
@@ -941,7 +954,7 @@ draft
|
||||
|
||||
### 12.1 基础动作槽位必须非空
|
||||
|
||||
第一版要求以下基础动作槽位全部有内容:
|
||||
第一版要求以下动作能力按“必生成 / 可选兜底”拆开:
|
||||
|
||||
当前编辑器固定生成入口补充说明(`2026-04-19`):
|
||||
|
||||
@@ -949,47 +962,33 @@ draft
|
||||
- `hurt` 不再作为固定生成按钮
|
||||
- 如果运行时仍需 `hurt` 资源,应通过后续扩展动作槽位或手动补齐
|
||||
|
||||
| 动作槽位 | 是否必填 | 建议来源 |
|
||||
| ------------- | -------- | ------------------------- |
|
||||
| `idle` | 必填 | 模板生成 |
|
||||
| `acquire` | 必填 | 可由短持物 / 抬手动作生成 |
|
||||
| `attack` | 必填 | 模板生成 |
|
||||
| `run` | 必填 | 模板生成 |
|
||||
| `jump` | 必填 | 模板生成 |
|
||||
| `double_jump` | 必填 | 可由跳跃二次变体生成 |
|
||||
| `jump_attack` | 必填 | 跳跃攻击模板 |
|
||||
| `dash` | 必填 | 冲刺模板 |
|
||||
| `hurt` | 必填 | 受击模板 |
|
||||
| `die` | 必填 | 倒地 / 消散模板 |
|
||||
| `climb` | 必填 | 攀爬模板 |
|
||||
| `wall_slide` | 必填 | 可由攀爬或停滞帧变体生成 |
|
||||
| 动作能力 | 是否必填 | 建议来源 |
|
||||
| ------------------------------- | -------- | ---------------------------------------------------------- |
|
||||
| `run` | 必填 | 模板生成 |
|
||||
| `attack` | 必填 | 模板生成 |
|
||||
| `skills[*].actionPreviewConfig` | 必填 | 技能编辑面板逐个生成 |
|
||||
| `idle` | 可选 | 模板生成;缺失时默认主图静止 |
|
||||
| `die` | 可选 | 模板生成;缺失时默认主图倒地过渡动画,最终停在翻转倒地姿态 |
|
||||
|
||||
这里“不能为空”指的是:
|
||||
这里“必填”指的是:
|
||||
|
||||
- 每个基础动作槽位必须能挂到一套可播放资产
|
||||
- 不允许在运行时出现 `null` 或空映射
|
||||
- 个别低优先动作允许由近似动作衍生,但槽位本身必须有有效资源
|
||||
- `run / attack` 必须能挂到一套可播放资产
|
||||
- 角色当前每个技能都必须有可播放的 `actionPreviewConfig`
|
||||
- `idle / die` 不再进入“缺失即阻塞发布”的判断
|
||||
- 运行时表现仍然不能空白;`idle / die` 的缺口由默认兜底承接
|
||||
|
||||
### 12.2 技能动作不是第一版强制项
|
||||
### 12.2 技能动作改为“按角色已配技能强制”
|
||||
|
||||
第一版可选:
|
||||
第一版不再要求预留整套固定技能枚举,但要求:
|
||||
|
||||
- `skill1`
|
||||
- `skill1_jump`
|
||||
- `skill1_bullet`
|
||||
- `skill1_bullet_fx`
|
||||
- `skill2`
|
||||
- `skill2_jump`
|
||||
- `skill3`
|
||||
- `skill3_jump`
|
||||
- `skill3_bullet`
|
||||
- `skill3_bullet_fx`
|
||||
- `skill4`
|
||||
- 当前角色 `skills` 数组里的每个技能都要补出 `actionPreviewConfig`
|
||||
- 技能动作继续在技能编辑面板逐个生成,不并入固定四按钮
|
||||
|
||||
策略建议:
|
||||
|
||||
- 基础动作先全量补齐
|
||||
- 技能动作后续按角色职业差异再补
|
||||
- 先补 `run / attack`
|
||||
- 再逐个补当前角色已有技能动作
|
||||
- `idle / die` 作为可选增强按需要补
|
||||
- 投射物与特效优先继续复用当前项目已有素材与技能特效系统
|
||||
|
||||
### 12.3 第一阶段优先模板
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
# 场景多幕创作与流程改造实施进度 2026-04-20
|
||||
|
||||
更新时间:`2026-04-20`
|
||||
|
||||
## 1. 本轮落地范围
|
||||
|
||||
本轮先完成 `scene_chapter` 的第一批基础链路,让“场景章节 -> 多幕 -> 主角色 -> 幕背景/相遇 NPC”真正进入现有创作工具和草稿系统。
|
||||
|
||||
本轮目标不是一次性做完 PRD 全量能力,而是先把下面这条主干打通:
|
||||
|
||||
1. 草稿层可以承载 `scene chapter / scene act`
|
||||
2. 草稿编译器可以把 `scene_chapter` 编译成正式卡片
|
||||
3. 创作页可以看到、打开、编辑 `scene_chapter`
|
||||
4. 编辑后的幕信息可以正确写回草稿
|
||||
5. 运行时共享层先具备读取幕背景、主角色、相遇 NPC 池的基础能力
|
||||
|
||||
## 2. 本轮已落地
|
||||
|
||||
## 2.1 草稿与运行时结构
|
||||
|
||||
已补齐多幕相关结构:
|
||||
|
||||
1. `CustomWorldFoundationDraftProfile.sceneChapters`
|
||||
2. `CustomWorldFoundationDraftSceneChapter`
|
||||
3. `CustomWorldFoundationDraftSceneAct`
|
||||
4. `CustomWorldProfile.sceneChapterBlueprints`
|
||||
5. `StoryEngineMemoryState.currentSceneActState`
|
||||
|
||||
同时补齐了地点/营地草稿里的 `imageSrc`,避免幕背景回落时丢失现有场景图资产引用。
|
||||
|
||||
## 2.2 scene_chapter 草稿编译
|
||||
|
||||
`server-node/src/services/customWorldAgentDraftCompiler.ts` 已完成第一批接入:
|
||||
|
||||
1. `scene_chapter` 正式进入草稿编译结果
|
||||
2. 支持从显式 `sceneChapters` 或地点/章节数据回退生成场景章节卡
|
||||
3. 每张卡会编译出场景摘要、幕结构总览、每幕背景图、主角色、辅助 NPC、幕目标、过渡钩子
|
||||
4. 每幕生成动态可编辑 section id
|
||||
5. 已增加基础警告:
|
||||
- 幕数不足
|
||||
- 缺背景图
|
||||
- 缺相遇 NPC
|
||||
- 主角色不在第一位
|
||||
- 缺线程挂钩
|
||||
- NPC 或线程引用失配
|
||||
|
||||
## 2.3 scene_chapter 草稿编辑
|
||||
|
||||
`server-node/src/services/customWorldAgentDraftEditService.ts` 已支持:
|
||||
|
||||
1. 编辑场景章节标题、摘要
|
||||
2. 编辑每幕标题、摘要、背景图链接、相遇 NPC、幕目标、过渡钩子
|
||||
3. `encounterNpcIds` 支持用角色 id 或角色名回写
|
||||
4. 回写后自动用第一位 NPC 覆盖 `primaryNpcId`
|
||||
|
||||
`server-node/src/services/customWorldAgentChangeSummaryService.ts` 也已支持解析 `scene_chapter` 标题。
|
||||
|
||||
## 2.4 创作页展示
|
||||
|
||||
前端已完成第一批接入:
|
||||
|
||||
1. 草稿抽屉正式加入 `scene_chapter` 分组
|
||||
2. `scene_chapter` 分组顺序位于 `chapter` 后、`thread` 前
|
||||
3. 详情面板已支持 `场景章节` 类型标签
|
||||
4. 幕背景 section 在详情面板里会直接渲染图片预览
|
||||
5. 编辑面板已支持幕摘要 / 相遇 NPC / 幕目标 / 过渡钩子等动态多行字段
|
||||
|
||||
## 2.5 运行时基础层
|
||||
|
||||
本轮同步补齐了幕运行的基础读取能力,便于下一轮继续接游戏流程:
|
||||
|
||||
1. 当前幕背景图优先覆盖场景默认背景
|
||||
2. 当前幕相遇 NPC 池可参与场景相遇过滤
|
||||
3. 当前幕主角色与负好感有限聊天的判定 helper 已建立
|
||||
4. 场景预览层已能识别“负好感主角色不直接自动开战”的基础分支
|
||||
|
||||
## 3. 当前仍未完成
|
||||
|
||||
下面这些仍属于 PRD 未完项,需要下一轮继续:
|
||||
|
||||
1. 创作页里的“新增幕 / 删除幕 / 调整幕顺序”交互
|
||||
2. 背景图配置与 NPC 配置的独立面板化交互
|
||||
3. 发布期 `qualityFindings` / blocker 的正式接入
|
||||
4. `SceneActRuntimeState` 的完整推进与持久化
|
||||
5. 当前幕主角色负好感 `5` 轮聊天限制的前后端完整闭环
|
||||
6. 第 `5` 轮“铺垫式收束”提示与强制退出聊天态
|
||||
7. 幕切换后的系统提示与 Adventure 面板状态展示
|
||||
|
||||
## 4. 下一轮建议顺序
|
||||
|
||||
建议下一轮按下面顺序继续:
|
||||
|
||||
1. 先补 `SceneActRuntimeState` 初始化与幕推进
|
||||
2. 再接 `npcEncounterActions / aiService / chatOrchestrator` 的负好感有限聊天闭环
|
||||
3. 最后补创作页的幕增删改序和独立配置面板
|
||||
|
||||
这样可以先把“能跑”补齐,再把“编辑体验”补完整。
|
||||
Reference in New Issue
Block a user