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 原生游戏真正该有的任务结构**
|
||||
Reference in New Issue
Block a user