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

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

View File

@@ -0,0 +1,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 原生游戏真正该有的任务结构**