# SD_50 委托与事件任务系统（建在 Quest 求值器之上）

Version: 0.1
Last updated: 2026-06-15

> 玩家在 S0 接**委托 / 事件任务**（回收 / 调查 / 击杀 / 收集 / 开启 / 修复…），下层完成、回来领**请购点 / 材料 / 升级料 / 解锁**。这是经济（`SD_49`）的一大**主动收入来源**。
>
> **核心原则：不重复造系统。** 委托层**复用现有任务求值器**（`UCSObjectiveDirectorSubsystem` 的 `ConditionType` + `Notify*` 钩子），只在其上加四样新东西：**① 可重复 + 重置 · ② 请购点等经济奖励 · ③ 发放（委托板/NPC）+ 交付 · ④ per-player 进度**。一次性的故事任务仍走现有 Quest `Side`/`Hidden`（见 `SD_48` 支线小案），不改。
>
> **设计文档 ≠ 实现状态。** 数值是提案默认值、改表即调。落地前按 §14 拆单元登记到 `Docs/DevelopmentUnits.md`。
>
> **相关：** `SD_49`（经济：请购点/物品分类/红线）、`SD_48`（支线小案，复用 Quest）、`SD_33/43`（逐层玩法/推进）、`Quests.csv`/`Objectives.csv`（现有任务数据，CSV 唯一源）、`Docs/_tools/`（任务节点编辑器）、`UCSObjectiveDirectorSubsystem`（求值器）、`ACSGameState::ApplyObjectiveEvent`（发奖）、`ACSNarrativeNPC`（可对话 NPC）。

---

## 1. 定位与边界

- **委托（Commission / Contract）** = 可重复、带经济奖励、有发放与交付流程的"合同"。是经济的主动收入引擎。
- **支线小案（Side Case）** = 一次性、剧情味的调查/人性小故事（`SD_48`），走现有 Quest `Side`/`Hidden` + 世界标签揭示，奖励偏真相/残留/一次性物资。**不在本系统重做**，本系统只与它共用求值器。
- **主线（Main Quest）** = 阻塞结局的骨干推进（现有 Quest `Main`），**不是委托**，委托永远不卡主线（红线）。
- **主线钩子 = 每层终结小Boss（已定 2026-06-15）**：每层主线在终结处放一个**小Boss / 招牌收容遭遇**（boss 本体设计见 `SD_47` 招牌遭遇 + SCP 实体清单）。**击败它 = 主线首通钩子**，发**有分量、有吸引力的奖励**——解锁新区/路线、关键道具、**房卡**（可含请购点）。这条钩子**主线必经**（不是可选委托），用一次性 Objective/委托表达即可，但奖励权重高、解锁归世界（R2）。详见 `SD_49 §6`。

一句话：**主线靠世界状态自动推进、委托靠玩家主动接取重复刷、支线小案是一次性故事**——三者共用同一套 `ConditionType` 求值机器。

---

## 2. 复用什么 / 新增什么

| 维度 | 现有任务系统（复用） | 委托层（新增） |
| --- | --- | --- |
| 条件求值 | `ConditionType`（Interact/CollectItem/KillCount/ReachVolume/RepairCount/HoldTimer/WorldStateTag）+ `UCSObjectiveDirectorSubsystem` 的 `Notify*` 钩子 | 复用，不重写 |
| 完成发奖 | `ApplyObjectiveEvent`（物品/路线/配方/样本/世界标签，幂等 EventId） | **加请购点货币奖励 + 改成发给"完成者本人"**（委托是个人合同） |
| 重复 | ❌ 一次性（Completed 不再武装） | **加 ResetType + MaxCompletions + 委托板轮换** |
| 发放 | ❌ 世界状态自动激活，无"接受" | **委托板 `ACSCommissionBoard` / 可选 NPC 发放 + 玩家"接受"** |
| 交付 | ❌ 无 | **回 S0 交付（collect/recover 交物）或条件达成自动完成** |
| 归属 | 世界/共享（奖励发给所有玩家） | **per-player**（与请购点钱包同层，各接各的、奖励归完成者） |
| UI | ❌ 无任务 UI（靠 AIC 旁白） | **委托板面板 + HUD 活动委托追踪（UMG）** |
| 数据源 | `Quests.csv`/`Objectives.csv`（CSV 唯一源 + 节点图工具） | **新增 `Commissions.csv`，同管线生成** |

---

## 3. 委托类型（玩家动词 → 现有 ConditionType）

你说的动词全部对得上现有求值条件，无需新增求值逻辑：

| 委托类型 | 玩家做什么 | 复用的 `ConditionType` | `ConditionKey` | 交付方式 |
| --- | --- | --- | --- | --- |
| **回收 Recover** | 把指定物资带回 S0 | `CollectItem` | ItemId | **回板交付**（交物换奖，塔科夫式 hand-over） |
| **收集 Collect** | 攒够某材料 | `CollectItem` | ItemId | 回板交付 / 或达量自动 |
| **击杀 Kill** | 清掉某遭遇组 N 个 | `KillCount` | EncounterGroupId | 达数**自动完成**，回板/即时领奖 |
| **调查 Investigate** | 到某点 / 查某物 | `ReachVolume` / `Interact` | VolumeId / 物体Tag | 达成自动完成 |
| **开启 Open** | 开某门/终端/容器 | `Interact` | 交互物 Tag | 达成自动完成 |
| **修复 Repair** | 修复 N 个收容节点 | `RepairCount` | EncounterId | 达数自动完成 |
| **守住 Hold** | 守设备 N 秒 | `HoldTimer` | EncounterId(秒数=Count) | 达成自动完成 |
| **解密 Decrypt** | 终端解密（守在终端读条完成） | `Interact` + `HoldTimer`（复用） | 终端 Tag（秒数=Count） | 达成自动完成 |
| **护送 Escort** | 护送 NPC/装置到目的地并存活 | **需新增护送支持**（护送 Actor + 到点存活判定；可叠 `ReachVolume`，被护送者死=失败） | EscortId | 到点自动完成；中途失败=可重接 |

> 解密直接复用现成判定；**护送是唯一要新做的一点点**（护送 Actor + "护送对象到点且存活"判定）。一条委托 = 一个（或少数几个）扁平条件，不需要 Quest 那套 Order/OR/严格顺序。复杂多步的留给 Quest。

`bRequiresTurnIn` 决定是"达成即领奖"还是"回 S0 委托板交付才领奖"。**回收/收集默认要交付**（把东西交出去），击杀/调查/开启默认自动完成。

---

## 4. 发放与领取

- **委托板 `ACSCommissionBoard`**（新 `ICSInteractable`，落点 S0，主入口）：交互打开委托面板，显示当前可接委托。这就是"接任务"。
- **NPC 发放（可选，叙事味）**：`ACSNarrativeNPC` 加一个委托钩子——某 NPC（如 Varga）在满足世界标签时提供专属委托（"帮我把 X 带回来"）。这就是"委托"。复用现有对话框架（对话末尾不是只写标签，而是可挂一条委托）。
- **接受（per-player，服务器权威）**：玩家在板上点"接受" → `RequestAcceptCommission(CommissionId)` → 服务器把该委托对**该玩家**标记 `Active`、开始按 `Notify*` 累计进度。
- **委托板槽位轮换（已定）**：板上同时挂 **6 个**可接委托，按 `Layer`/`BoardWeight` 从可用池抽、**按游戏日刷新**；完成/刷新后换新——"每次回 S0 都有新活干"，同时**天然限量防无限刷**。

### 4.5 下层随机事件（动态触发 · 已定加入）

除了 S0 委托板的"计划性"委托，**下层探索时低概率触发动态事件**——给每趟下潜意外感与新鲜活（用户：S0 为主、下层可低概率触发随机任务 / 事件 / 角色）。

- **触发**：服务器权威、低概率、有节流（每趟 / 每区上限）；**确定性种子**让主机与客户端一致（AGENTS §World：网络相关生成必须服务器权威 / 确定性）。
- **形式**：临时事件 / 遭遇 / 角色——可能是求救 NPC、一处异常读数、一群敌人、一个待解密终端。
- **任务动词**：击败 / 收集 / **护送** / **解密** 等（复用 §3 判定 + 护送新支持）。走近自动激活或就近接取；完成发请购点 / 材料，**不发关键物**（红线）。
- **一次性角色**：低概率出现的临时 NPC（幸存者 / D 级 / 可疑人物），接现有 `ACSNarrativeNPC` + 对话，挂护送 / 调查类事件。
- **与板委托区别**：板委托 = 回 S0 计划接、可重复；随机事件 = 下层临时撞见、低概率、限量、奖励适中。两者共用同一求值器 + 经济奖励路径。
- **落地**：新 `UCSDynamicEventDirector`（服务器，确定性触发 + 节流）+ 数据表 `DynamicEvents.csv`（EventId / 触发条件 / 概率 / 动词 / 奖励 / 冷却）= Commission-E 单元（§14）。

---

## 5. 交付流程（服务器权威）

```mermaid
flowchart TD
  A[玩家在委托板点交付 RequestTurnInCommission] --> B[Server]
  B --> C{该委托对该玩家 Active?}
  C -->|否| X[拒绝]
  C -->|是| D{条件达成?<br/>collect/recover: 背包有足量目标物}
  D -->|否| X
  D -->|是| E[collect/recover: RemoveItem 交出物品]
  E --> F[发奖给本玩家: AddCredits 请购点 + AddItem 材料/升级料 + 解锁标签归世界]
  F --> G[CompletionCount++ · 按 ResetType 置冷却/重抽板位]
```

- collect/recover：交付时 `RemoveItem` 把目标物交出去（消耗），再发奖——这就是"回收"的语义（把物资交回基金会换配给）。
- 击杀/调查/开启：条件达成即标记 `ReadyToTurnIn`；`bRequiresTurnIn=false` 时即时发奖、`=true` 时回板一键领。
- 发奖**只给完成者本人**（委托是个人合同，与请购点钱包同层）；唯一例外是 `RewardWorldStateTags` 这类**世界解锁仍写世界**（不按人复制，红线 R2）。

---

## 6. 奖励

| 奖励 | 字段 | 说明 |
| --- | --- | --- |
| 请购点 | `RewardCurrencyRC` | 委托的主奖励（**经济缺的那块**，接 Economy-A 钱包）。提案重复委托 50–200/次、一次性大委托更高 |
| 材料 / 升级料 | `RewardItemIds`（复用现有，`ItemId*N`） | "获取材料 / 强化"——升级料喂升级台（SD_49 §11） |
| 解锁（可选） | `RewardWorldStateTags`（复用） | 某些委托完成解锁请购台新上架 / 路线（写世界，不按人复制） |
| 配方 / 样本 | `RewardRecipeIds`/`RewardSampleIds`（复用） | 一次性委托可给，重复委托一般不给 |

**绝不发**（红线 R1/R2/R8）：关键样本 / 关键物 / 残留 / 路线权限本体 / AIM 协议 / 破坏结局变量的物品。**可重复的板委托 / 随机事件**只发**普通经济物 + 请购点**。

> **唯一例外 = 主线钩子小Boss（§1）**：作为主线必经推进，它**可以**给关键道具 / 房卡 / 路线解锁——因为那是**主线进度奖励**（解锁写世界状态、不可买卖、一次性不可刷，符合 R2/R3），不是经济刷取。用一次性 Objective 的现有奖励路径（`RewardItemIds`/`RewardRouteIds`/`RewardWorldStateTags`）发，奖励权重高、要有吸引力（用户强调）。

---

## 7. 重复与刷新（防无限刷 = R4）

- `ResetType`：`Never`（一次性故事委托）/ `Session`（每次游戏会话重置）/ `Daily`（按游戏日刷新）。
- `MaxCompletions`：可完成次数上限（`Never` 类=1；`Daily` 类按日给几次；无限类谨慎用、且奖励压低）。
- **委托板限量轮换**：板上同时只 N 个槽、按日/按回 S0 部分刷新——结构性限制每趟能刷多少。
- **红线 R4**：可重复委托=奖励适中 + 关键物不发 + 板位有限 + 日刷新，确保不成为"刷钱跳进度"。大额一次性奖励只给一次性委托 / 支线小案。

---

## 8. per-player 与多人

| 维度 | 规则 |
| --- | --- |
| 接受 / 进度 / 完成次数 | **每人独立**（与请购点钱包同层，存玩家档） |
| 奖励 | 请购点/材料**归完成/交付者本人**；世界解锁型仍归世界（一人解锁全队享，R9） |
| 同一委托 | 多名玩家可各自接同一条、各自完成 |
| 击杀/收集计数（团队助攻计入 · 已定 · 重点） | **队友帮打也算**：一次击杀 / 收集，**所有"已接该委托且在场参与"的玩家各自 +1 进度**（物品不克隆、只各自推进各自委托）。用户强调**这块必须做扎实**——服务器权威判定"参与"（在场距离 / 造成伤害 / 拾取归属），防一人刷全队、防重复计数、防未参与白嫖 |
| 协作 | PvE 鼓励组队做委托：一起打怪 / 搜物，各自委托同步推进；不抢、不互斥 |

---

## 9. 数据 schema（新增 `Commissions.csv`，走现有生成管线）

管线：编辑 `Data/Source/Commissions.csv` → `python Scripts\GenerateGameData.py` → `Data/Generated/*` → `UCSItemDataSubsystem` 查表。生成器校验：`ConditionType` 合法、`ItemId/EncounterGroupId` 等引用存在、奖励不含关键类、`RewardCurrencyRC≥0`。

```
CommissionId, Title, Desc, IssuerId, Layer, CommissionType, ConditionType, ConditionKey, ConditionCount,
bRequiresTurnIn, RewardCurrencyRC, RewardItemIds, RewardWorldStateTags, PrereqWorldStateTags,
ResetType, MaxCompletions, BoardWeight, SortOrder
```

示例行：
```
Com_L0_Recover_Relics, 回收旧物件, 把测试区的旧物件带回 S0, Board_S0, L0, Recover, CollectItem, Coll_OldRelic, 3, 1, 80, , , Site.ReachedS0, Daily, 2, 10, 1
Com_L1_Cull_Mutants, 清理污染变异体, 净化层变异体过多, Board_S0, L1, Kill, KillCount, EG_L1_Mutant, 5, 0, 120, Mat_FilterCore*2, , Access.L1, Daily, 1, 8, 2
Com_L2_Investigate_Spore, 调查孢子源, 标记孢子异常读数点, NPC_Varga, L2, Investigate, ReachVolume, Vol_L2_SporeSource, 1, 0, 150, , Buy.AntiSpore, Access.L2, Never, 1, 5, 3
Com_L1_Open_SealedWing, 开启封锁侧厅, 用门卡打开被封侧厅, Board_S0, L1, Open, Interact, Door_L1_SealedWing, 1, 0, 100, , , Access.L1, Never, 1, 6, 4
```

**存档（接玩家档，per-player）**：`FCSPlayerSaveData` 新增 `TArray<FCSCommissionState> Commissions`：
```cpp
struct FCSCommissionState { FName CommissionId; ECSCommissionState State; int32 Progress; int32 CompletionCount; int32 LastResetDay; };
// ECSCommissionState: Available / Active / ReadyToTurnIn / CoolingDown
```

---

## 10. 运行时架构（服务器权威，复用求值器）

| 关注点 | 落点 |
| --- | --- |
| 委托定义查表 | `UCSItemDataSubsystem`（加 `FCSCommissionDefinition` + `LoadCommissionsCsv` + getter） |
| 委托进度/状态 | **per-player**，挂 `ACSPlayerState`（与钱包同层，复制 OwnerOnly + RepNotify 给本机 UI），存玩家档 |
| 求值 | **复用 `UCSObjectiveDirectorSubsystem` 的 `Notify*`**——给这些调用点补"触发玩家"上下文，转给委托进度更新（新 `UCSCommissionComponent`/或导演里加一支 per-player 委托表）。**不复制粘贴求值逻辑** |
| 接受/交付事务 | 玩家请求走 owning `ACSPlayerController`：`RequestAcceptCommission` / `RequestTurnInCommission` → `Server*` RPC → 校验→改真值（同合成/经济的"校验→扣→产出"） |
| 发奖 | 复用 `ApplyObjectiveEvent` 的物品/标签路径 + **新的 per-player 请购点发放**（`PlayerState->AddCredits`），不发给全队 |
| 委托板 / NPC | `ACSCommissionBoard`(`ICSInteractable`) + `ACSNarrativeNPC` 委托钩子；交互经玩家拥有的交互组件路由（不让客户端直接对板发 Server RPC） |

**架构选择（提案）**：进度走 per-player 的 `UCSCommissionComponent`（挂 PlayerState 或 Controller），求值复用 ObjectiveDirector 的 Notify 流（director 既推进世界 Quest，也把带玩家上下文的事件转给该玩家的委托组件）。Quest 的世界级一次性逻辑**完全不动**。

---

## 11. UI（UMG，接现有迁移方向）

- **委托板面板 `WBP_CommissionBoard`**：分类标签（回收/调查/击杀/收集/开启）+ 可接委托列表（标题/层级/条件/奖励预览/接受钮）+ 进行中（进度条/计数）+ 可交付（交付钮）+ 已完成/冷却。图标复用经济页那套 game-icons 风（钻石/无人机/生物危害…）。
- **HUD 活动委托追踪**：HUD 角落显示当前已接委托的简短目标 + 进度（如"清理变异体 3/5"），事件驱动刷新（不轮询）。这也补上了项目目前"没有任务 HUD"的缺口。
- UI 只显示复制状态 + 发请求，不持权威（AGENTS §UI）。设计稿可在 `UI/UI_QuestHUD.html` 基础上扩。

---

## 12. 与 SD_48 支线小案的关系

- **支线小案 = 一次性故事**（失踪研究员/没寄出的家书/想带异常逃跑的人…）：走现有 Quest `Side`/`Hidden` + 揭示标签，奖励=残留/真相/一次性物资。**不是委托**，但**共用 `ConditionType` 求值器**。
- **委托 = 可重复合同**：本系统。
- 两者可交织：一条支线小案的某一步可以"顺手"挂一条委托式奖励，但小案的剧情完成仍是一次性 Quest。
- 好处：玩家在 S0 看到的"能接的活"= 委托板（重复经济活）+ NPC/终端浮现的支线小案（故事活），都靠同一套底层。

---

## 13. 防剥削

| 风险 | 对策 |
| --- | --- |
| 委托刷钱跳进度 | 委托不发关键物/路线/AIM；奖励适中；R4 |
| 无限刷重复委托 | 板位有限 N 槽 + 日刷新 + `MaxCompletions` 上限 |
| 交付刷取（交假物/重复交付） | 服务器校验背包真有目标物再 `RemoveItem`；完成次数服务器记账、幂等 |
| 多人重复领同一世界奖励 | 经济奖励 per-player；世界解锁型只写一次世界状态（不按人复制） |
| 接了不做占板 | 可设过期/可放弃（`RequestAbandonCommission`） |

---

## 14. 落地单元拆分（号从 111 起，依赖 Economy-A 钱包）

| 单元 | 目标 | 依赖 |
| --- | --- | --- |
| **111 Commission-A 委托地基（单类型打通）** | `Commissions.csv` + `FCSCommissionDefinition` 查表 + per-player 委托状态（存档）+ 复用 ObjectiveDirector 求值（先打通 **Kill + Collect/Recover** 两类）+ 接受/交付事务 + 发请购点（接 Economy-A）。无 UI 先用 GM/exec 验证 | 105 Economy-A |
| **112 Commission-B 全类型 + 重置/轮换** | 补 Investigate/Open/Repair/Hold；`ResetType`(Daily/Session/Never)+`MaxCompletions`+委托板槽位轮换；过期/放弃 | 111 |
| **113 Commission-C 委托板 + HUD UI** | `ACSCommissionBoard`(ICSInteractable) + `WBP_CommissionBoard`（接受/进度/交付/奖励预览）+ HUD 活动委托追踪（补任务 HUD 缺口） | 111、112 |
| **114 Commission-D NPC 发放 + 支线小案接入** | `ACSNarrativeNPC` 委托钩子（NPC 发专属委托）+ 把 SD_48 几条支线小案做成一次性委托/Quest 示范 | 113、（叙事 NPC 单元） |
| **115 Commission-E 下层随机事件 + 护送/解密** | 新 `UCSDynamicEventDirector`（服务器确定性触发 + 节流）+ `DynamicEvents.csv`；**护送**新支持（护送 Actor + 到点存活判定）、**解密**复用 Interact+HoldTimer；下层低概率刷事件/角色发经济奖励（§4.5） | 112、113、敌人生成器 |

> **主线钩子小Boss不在本系统单独立单元**——boss 本体 / 招牌遭遇见敌人 / SCP 实体单元（`SD_47`/`SD_45`/实体清单）；首通奖励用**现有 Quest/Objective 的奖励路径**接（击败 = `KillCount` 条件 → `RewardItemIds`/`RewardRouteIds`/`RewardWorldStateTags`），不需要委托系统新代码。

每单元：服务器权威、表驱动、配套 UMG、编译（双目标）+ Listen Server + 客户端 PIE 验过再下一个。

---

## 15. 示例委托（味道示范）

- **L0｜回收·旧物件**：把测试区 3 件"旧物件"带回 S0 委托板交付 → +80 RC。每日可接 2 次。（教学回收交付循环）
- **L1｜击杀·清理变异体**：清掉净化层污染变异体 5 个 → 自动完成 → +120 RC + 过滤芯×2。每日 1 次。
- **L2｜调查·孢子源**：到孢子异常读数点标记 → +150 RC + 解锁请购台"抗孢子装备"上架。一次性（Varga 发）。
- **L1｜开启·封锁侧厅**：用消耗门卡开被封侧厅 → +100 RC。一次性（开了就开了）。
- **L5｜守住·冷却调节**：守住冷却设备 60 秒 → +200 RC + 升级料。（接现有 HoldTimer）

---

## 16. 决策记录（已定 2026-06-15）

1. **发放主入口**【已定】：S0 委托板为主 + NPC 发专属委托为辅 + **下层低概率随机事件**（§4.5）。
2. **板位刷新**【已定，由作者定】：按游戏日刷新、同时挂 6 个槽。
3. **团队助攻**【已定 · 重点】：队友帮打**计入**（在场参与即各自推进），**必须做扎实**（§8）。
4. **过期 / 放弃**【已定】：不强制过期，可放弃换新。
5. **重复委托奖励曲线**【已定，由作者定】：当日内随完成次数轻微递减（防刷），次日刷新回满。
6. **首通 = 一次性委托 + 主线小Boss钩子**【已定】：首通用一次性 Objective/委托实现；主线钩子=每层终结小Boss，击败发**有分量、有吸引力**的奖励（解锁 / 关键道具 / 房卡），主线必经（§1）。
