船员社交与关系
每艘船一套独立的关系系统:船员之间维护有向好感度(-100 到 +100),通过被动日增、社交任务、共餐共寝共战不断演化,并涌现出汇报链、副手、小团体与社交记忆。
船员社交与关系系统(Service.Relationship 模块)让船上的船员从“互不相干的工人”变成“有人际网络的群体”。它由两层叠加构成:
- 显式组织层(玩家直接操作):汇报链(每个船员有一个上司,构成以船长为根的树)+ 副手(军士/船长的槽位制特殊下属)。玩家在“船员组织树”面板上以拖拽方式改组,以按钮方式任免副手。
- 隐式关系层(系统涌现):好感度矩阵。每对船员之间有两个方向独立的好感值,由被动日增、主动社交任务、生活与战斗钩子驱动;高好感的船员自动聚成“小团体”并涌现领袖。
系统以船为作用域:玩家船在船只上下文初始化时挂载 RelationshipManager(ShipContext.cs),AI 船由 AIShipFactory.cs 同样挂载,因此敌船船员内部也有自己的关系网。
玩家接触入口:
- 船员组织树面板(
CrewTreePanel.cs):Report 视图(组织树 + 拖拽改组 + 草案/应用更改)、小团体视图、叠加视图;卡片上有“副手”徽章与设为/解除副手按钮。 - 船员抽屉的“记忆”页签(
CrewDrawerView.cs):短期记忆最近 10 条 + 长期记忆默认 5 条(可展开全部)。 - 游戏世界中:社交互动时双方头顶出现类型气泡(“闲聊”/“争吵”等中文标签),互动成功结束时头顶飘“±X 好感“数字(
SocialBubbleOverlay.cs)。
相关页面:船员(属性/技能/职级是本系统的输入)、任务与工作(社交任务走标准任务管线)、时间与调度(日增与衰减按游戏日触发)。
好感度矩阵(OpinionMatrix.cs)
Section titled “好感度矩阵(OpinionMatrix.cs)”- 好感是有向的:A 对 B 和 B 对 A 是两个独立数值,可以不对称。
- 取值范围 [-100, +100],写入时强制截断;没有记录的船员对默认 0。
- 矩阵为稀疏存储,只有发生过好感变化的船员对才占内存。
好感标签五分档(OpinionLabel.cs)
Section titled “好感标签五分档(OpinionLabel.cs)”| 好感值区间 | 标签 | 边界归属 |
|---|---|---|
| +50 ~ +100 | 挚友 Brother | 恰好 +50 算挚友 |
| +20 ~ +50(不含 50) | 朋友 Friend | 恰好 +20 算朋友 |
| -20 ~ +20(均不含) | 路人 Stranger | 0 / +19 / -19 都是路人 |
| -50 ~ -20(含 -20,不含 -50) | 不和 Rival | 恰好 -20 算不和 |
| -100 ~ -50(含 -50) | 死敌 Enemy | 恰好 -50 算死敌 |
分档逻辑有单元测试覆盖边界值(OpinionLabelTests.cs)。注意:当前版本中标签仅作为查询接口(GetLabel)暴露,界面与玩法均未实际消费,不直接产生工作效率加减成(见“已知限制”)。
被动日增(RelationshipManager.Tick.cs)
Section titled “被动日增(RelationshipManager.Tick.cs)”每个游戏日变更时(订阅 DateTimeManager 的日变更事件,默认游戏速度下 1 游戏日 = 24 现实秒,见 时间与调度),系统遍历全部有序船员对 (A, B),按以下规则累加当日好感增量:
| 关系条件 | A 对 B 日增量 | 说明 |
|---|---|---|
| A 的上司是 B(下对上) | +0.5/游戏日 | 方向性:下级对上级好感涨得更快 |
| B 的上司是 A(上对下) | +0.3/游戏日 | 方向性 |
| A 是 B 的副手,或 B 是 A 的副手 | +1.0/游戏日 | 双向都拿(在汇报链增量之上额外叠加) |
| A 与 B 同一个上司(同侪) | +0.3/游戏日 | 双向 |
| A 与 B 同专业(专业不为“无”) | +0.2/游戏日 | 双向 |
多个条件同时满足时求和。例:副手 A 对上司 B 且两人同专业 → A 对 B 日增 = 0.5 + 1.0 + 0.2 = +1.7/游戏日。合并后的增量整体经过一次邓巴限流(见下)再写入矩阵。
每过 7 个游戏日,矩阵中所有已存在的边(双向各算一条)统一执行:
新好感 = 旧好感 × 0.85衰减对正负好感一视同仁(敌意也会随时间淡化),且不经过邓巴限流。
由“日增 + 周衰减”可推导被动来源的长期稳态值(推导值,非代码常量):
稳态好感 ≈ 日增量 × 0.85 × 7 / (1 - 0.85) ≈ 日增量 × 39.7即单靠“下对上 +0.5/日”稳态约 +19.8(停在“路人”上限附近);叠加副手 +1.0/日后(+1.5/日)稳态约 +59.5(稳定“挚友”)。设计意图是:被动来源只能把关系顶到“朋友”门槛附近,要成为挚友需要主动社交或共同经历。
邓巴限流(DunbarThrottle.cs)
Section titled “邓巴限流(DunbarThrottle.cs)”防止大船上全员互相成为朋友的限流机制。每个船员的“深关系槽位”数:
槽位数 = 8 + floor(气质 / 2)气质(temperament)范围 1-20(CrewAttributes.cs,招募时随机生成),因此槽位数范围 8 ~ 18。“已用槽位” = 该船员对外好感 ≥ +20 的关系条数。
限流规则——只有同时满足以下四个条件时,本次好感增量 × 0.2:
- 增量为正(负向变化、衰减永不限流);
- 当前好感 < +20(已经是朋友的关系继续上涨不限流);
- 加上本次增量后将 ≥ +20(即本次会“跨线”成为朋友);
- 发起方向的船员已满槽。
也就是说:低于 +20 的关系随便发展不占槽、不受限;限的只是“满槽后还想交新朋友”的那一下跨线增长。该行为有完整单元测试(DunbarThrottleTests.cs)。限流作用于所有正向好感来源(被动日增、社交任务、共餐共寝共战)。
社交互动类型(SocialInteractionType.cs)
Section titled “社交互动类型(SocialInteractionType.cs)”共 6 种互动,成功结算时双向施加好感变化(Insult 除外,单向):
| 互动 | 持续时长 | 好感变化(双向) | 备注 |
|---|---|---|---|
| 闲聊 Chat | 3 秒 | +1 | 默认兜底类型 |
| 深聊 DeepTalk | 6 秒 | +3 | 空闲社交需好感 ≥ +20 且双方心情 > 60 |
| 讲笑话 TellJoke | 3 秒 | +0.5 | 需发起者心情 > 60 且好感 ≥ 0 |
| 传八卦 ShareGossip | 5 秒 | +1 | 需好感 > +40 |
| 争吵 Argue | 4 秒 | -2 | 冲突触发 |
| 辱骂 Insult | 2 秒 | 0(双向) + 被骂方对发起者单向 -5 | 冲突触发,非对称 |
时长单位为现实秒(任务步骤计时)。心情值来自心情组件(基础心情 50,范围 0-100,MoodComponent.cs);船员没有心情组件时按 50 处理,因此默认状态下深聊/讲笑话的心情门槛不满足。
社交任务的触发(SocialIssuer.cs)
Section titled “社交任务的触发(SocialIssuer.cs)”SocialIssuer 注册进任务管理器,每 5 现实秒扫描一次全船船员,按三档优先级产出社交任务请求:
优先级 1:冲突触发(争吵/辱骂)
- 条件:双方好感互相 < -20(两个方向都要低于 -20)+ 互为邻居(同甲板 + 切比雪夫距离 ≤ 3 格)+ 双方存活且未失能 + 目标未被其他社交预约。
- 同一有序对每次尝试后有 60 现实秒冷却。
- 每次尝试的触发概率 = (0.10 / 3600) × 5 ≈ 0.0139%(代码意图为“10%/小时”,实际叠加 60 秒冷却后有效概率约 0.83%/现实小时,见“已知限制”)。
- 类型选择:发起者对目标好感 < -50 → 辱骂 Insult;否则 → 争吵 Argue。
- 冲突触发不要求双方空闲。
优先级 2:副手日常
- 全局节拍:距上次派发 ≥ 7200 现实秒(约 2 现实小时)才再派一轮。
- 对每个有副手的主官:主官与副手都处于空闲(无任务或在“等待”任务)且副手未被社交预约 → 派发一次互动。
- 类型:30% 概率深聊 DeepTalk,70% 概率闲聊 Chat(无好感/心情门槛)。
- 不要求两人相邻——主官会走过去。
优先级 3:空闲社交
- 发起者需连续空闲 ≥ 60 现实秒(被打断则重新计时)。
- 全船并发社交任务上限 = max(5, 总人数 ÷ 10)(整除),达到上限本轮不再派发。
- 目标:第一个满足“空闲 + 未被社交预约 + 邻居(同甲板切比雪夫 ≤ 3)“的其他船员。
- 类型按顺序判定(
PickFreeSocialType):- 好感 ≥ +20 且双方心情 > 60 → 25% 概率深聊;
- 发起者心情 > 60 且好感 ≥ 0 → 20% 概率讲笑话;
- 好感 > +40 → 20% 概率传八卦(实现注明“简化跳过共同朋友判定”);
- 以上都没命中 → 闲聊。
社交任务的执行流程(Task_Socialize.cs、SocialTaskRequest.cs)
Section titled “社交任务的执行流程(Task_Socialize.cs、SocialTaskRequest.cs)”- 预约:任务创建时对目标执行“社交预约”(
Crew.cs的 ICrewReservable 实现)——同一时刻一个船员只能被一个发起者预约为社交目标,防止被多人同时搭话。 - 任务归属:任务锁定给发起者本人(私有任务,不进公共任务池竞争),工作类型为 Social,基础优先级 1(全部工作类型中最低档——“闲时才社交”,
TaskDefs.cs/ConsumerPriorityConfig.cs)。 - 步骤:发起者寻路走到目标邻近格 → 双方头顶弹出互动类型气泡(持续整个互动时长)→ 原地等待“持续时长”秒 → 成功才结算好感变化(前面任一步被打断/取消则好感不变)。
- 结算:按上表施加双向好感(经邓巴限流);辱骂额外施加被骂方单向 -5;双方头顶飘“±X 好感“数字(1 秒上漂渐隐)。
- 清理:无论任务成功、取消还是被抢占,结束时都会释放目标的社交预约。
目标方在互动期间不会中断自己手头的任务,预约只是阻止其他社交任务找上他(见“已知限制”)。
生活与战斗钩子(RelationshipHooks.cs)
Section titled “生活与战斗钩子(RelationshipHooks.cs)”| 钩子 | 触发时机 | 条件 | 好感变化 |
|---|---|---|---|
| 共餐 ShareMeal | 任一船员完成进食任务 | 其他船员也在执行进食类任务 + 同甲板切比雪夫距离 ≤ 8 格 | 双向 +0.5 |
| 同寝 ShareBed | 任一船员完成睡眠任务 | 其他船员也在执行睡眠类任务 + 同甲板曼哈顿距离 ≤ 2 格(邻床) | 双向 +0.3 |
| 共战 FoughtTogether | 本船战斗结束(战斗结束消息,见 遭遇与刷怪) | 全部存活船员 | 两两双向 +2,并各记一条短期记忆“SurvivedBattle” |
进食/睡眠钩子由对应任务的收尾步骤调用(Task_Eat.cs / Task_Sleep.cs)。
船员死亡的连锁反应(RelationshipHooks.OnCrewDied)
Section titled “船员死亡的连锁反应(RelationshipHooks.OnCrewDied)”船员死亡时(本船作用域过滤):
- 挚友哀悼:所有对死者好感 ≥ +40 的存活船员,获得心情想法“失去挚友”(-20 心情,持续 5 游戏日,配置见下文 ThoughtConfig.csv)+ 一条长期记忆“FriendDied”。
- 小团体震荡:死者所属小团体的其他存活成员:
- 死者是普通成员 → 想法“小队战友阵亡”(-10 心情,5 游戏日)+ 长期记忆“TeammateDied”;
- 死者是团体领袖 → 想法“队长阵亡”(-20 心情,10 游戏日)+ 长期记忆“LeaderDied”。
- 小团体的重算交给下一个 30 秒周期自然处理,不立即强制解散。
社交记忆(CrewMemoryStore.cs、MemoryEntry.cs、MemoryHooks.cs)
Section titled “社交记忆(CrewMemoryStore.cs、MemoryEntry.cs、MemoryHooks.cs)”每个船员有两个记忆桶(MemoryBucket):
- 长期记忆 LongTerm:永不过期、无容量上限(TTL 固定为 -1)。
- 短期记忆 ShortTerm:带 TTL(单位:游戏日)。每个游戏日变更时全部短期条目 TTL 减 1,减到 0 即删除。写入时若 TTL ≤ 0 则按 1 天兜底。
每条记忆包含:类型、时间戳(编码为 天 × 256 + 小时)、主要参与者、次要参与者(可空)、一行回忆文字。
MemoryHooks.cs 定义了 19 个记录函数及其桶/TTL 设定:
| 大类 | 记忆类型 | 桶 / TTL |
|---|---|---|
| 死亡相关 | FriendDied | 长期 |
| 死亡相关 | EnemyKilled | 短期 7 天 |
| 死亡相关 | FirstKill、KillMilestone_N | 长期 |
| 职业相关 | PromotedTo_X、DemotedFrom_X、AppointedAsDeputy、RemovedAsDeputy | 长期 |
| 职业相关 | TransferredSpecialty | 短期 14 天 |
| 战斗相关 | SurvivedBattle、BattleVictory | 短期 3 天 |
| 战斗相关 | BattleDefeat、GotSeverelyInjured、RescuedSomeone | 长期 |
| 生活相关 | AteAmazingMeal | 短期 1 天 |
| 生活相关 | GotDrunk、WitnessedFight | 短期 2 天 |
| 团体相关 | TeammateDied、LeaderDied | 长期 |
注意:当前只有 4 个钩子被实际接线触发(FriendDied、TeammateDied、LeaderDied、SurvivedBattle),其余 15 种已定义但没有调用方(见“已知限制”)。
玩家在船员抽屉“记忆”页签查看:短期最近 10 条 + 长期默认最新 5 条(可展开全部),按时间倒序。
汇报链(ReportingChain.cs)
Section titled “汇报链(ReportingChain.cs)”每个船员有一个 ManagerId 指向上司,船长是根(ManagerId 为空)。找不到合法上司的船员显示“无主”。
改组校验规则(玩家拖拽时实时反馈,ReportingError.cs):
| 规则 | 失败码 |
|---|---|
| 不能指定自己为上司 | TargetIsSelf |
| 水手(Seaman)不能带任何下属 | SubordinateCannotManage |
| 不能形成环(沿新上司的链向上爬,命中自己即环) | WouldCreateCycle |
| 设为“无上司”(变成无主)永远合法 | — |
下属人数无上限。代码保留了容量公式 容量 = 1 + floor(指挥技能 / 5)(水手恒为 0)作为 API,但不参与任何校验——ManagerCapExceeded 错误码从不返回。
自动指派(SeedDefaults / 增员):对所有非船长且无上司的船员,按“职级降序 → 指挥技能降序 → ID 升序”排序后,逐个寻找上司候选人。候选人要求:职级严格高于本人 + 不是水手;多个候选按同样的“职级降序 → 指挥降序 → ID 升序”取第一个。注意自动指派比手动拖拽更严格(手动允许平级甚至低职级带人,只要不是水手)。
减员处理:船员死亡/离船时,其全部直属下属置为无主并按上述规则重新指派;其本人若是某主官的副手,副手槽同时清空。
跨主官移动:船员被拖到新上司名下时,若他原本是旧上司的副手,副手身份自动解除。
职级体系(船长 Captain = 3 / 军士 PettyOfficer = 2 / 专家 Specialist = 1 / 水手 Seaman = 0)与指挥技能详见 船员。
副手(DeputyManager.cs)
Section titled “副手(DeputyManager.cs)”副手是槽位制的特殊汇报关系,只有军士和船长能开槽:
| 职级 | 副手槽位公式 | 取值范围 |
|---|---|---|
| 船长 Captain | 2 + (1 若 气质 ≥ 15 且 指挥 ≥ 25) | 2 ~ 3 |
| 军士 PettyOfficer | 1 + (1 若 气质 ≥ 15 且 指挥 ≥ 15) | 1 ~ 2 |
| 专家 Specialist | 0 | 0 |
| 水手 Seaman | 0 | 0 |
任命规则(失败码 DeputyError):
- 副手必须是该主官的直属下属(NotDirectSubordinate);
- 主官槽位为 0 → ManagerCannotHaveDeputy;
- 槽位已满 → NoSlotsAvailable;
- 已是别人的副手 → AlreadyDeputy(对同一主官重复任命视为成功,幂等)。
副手的系统效果(本模块内):
- 与主官的被动好感双向额外 +1.0/游戏日;
- 每约 2 现实小时一轮的“副手日常”社交(30% 深聊 / 70% 闲聊)。
副手对工作效率/成长的加成属于职级管理系统,配置见 Docs/Notion/设计/数据中心/职级配置/,不在本模块内实现。
解除时机:玩家手动解除;副手被拖到其他上司名下时自动解除;副手本人死亡/离船时自动清理。注意:主官死亡/离船时其副手的副手标记不会被清除(减员路径绕过了改组时的副手清理)——该船员被自动改派到新上司后仍带着“副手”徽章,被动日增也会按副手与新上司双向额外 +1.0,但不占新上司的副手槽、也不参与副手日常社交。槽位空出后不自动顶替。
小团体(SubgroupComputer.cs、Subgroup.cs)
Section titled “小团体(SubgroupComputer.cs、Subgroup.cs)”小团体是从好感网中自动涌现的连通群体,每 30 现实秒重算一次(RelationshipManager.Subgroup.cs),纯计算结果,不持久化:
-
候选边:所有满足
min(A 对 B, B 对 A) ≥ +20的船员对(必须双向都过线)。 -
连通分量:把候选边视作无向图,用并查集找连通分量;≥ 2 人的分量构成一个小团体。
-
领袖选举:团体内按综合评分取最高者:
评分 = 职级 × 1,000,000 + 七技能总和 × 1,000 + 指挥技能即优先级为:职级 > 技能总和 > 指挥技能 > ID 升序(评分相同时取 ID 较小者)。
-
领袖迟滞(防抖):若团体成员集合与上次重算完全一致,且现任领袖仍在,则新候选评分必须 ≥ 现任评分 ÷ 0.9(约高出 11.1%)才换人;成员集合变了则重新选举,不套迟滞。
小团体跨越汇报链——成员是否同一上司无关紧要。团体编号在每次重算后可能变化(不稳定 ID)。
界面表现:小团体视图按团体分组列出成员并标注领袖;叠加视图同时显示汇报链与小团体(CrewTreePanel.cs)。空团体提示文案明确给出形成条件:“≥2 人互相好感 ≥ +20 才会涌现”。
以下所有数值除特别标注外均为代码常量(需要程序改)。
| 项目 | 数值 | 出处 |
|---|---|---|
| 好感范围 | -100 ~ +100(写入截断) | OpinionMatrix.cs |
| 默认好感(无记录) | 0 | OpinionMatrix.cs |
| 标签阈值 | ≥+50 挚友 / ≥+20 朋友 / >-20 路人 / >-50 不和 / 其余死敌 | OpinionLabel.cs |
| 周衰减 | 每 7 游戏日,全部边 × 0.85 | RelationshipManager.Tick.cs |
| 被动稳态(推导) | ≈ 日增量 × 39.7 | 由日增 + 周衰减推导 |
被动日增(每游戏日,可叠加)
Section titled “被动日增(每游戏日,可叠加)”| 来源 | 增量 | 出处 |
|---|---|---|
| 下级 → 上级 | +0.5 | RelationshipManager.Tick.cs |
| 上级 → 下级 | +0.3 | RelationshipManager.Tick.cs |
| 副手 ↔ 主官(额外) | +1.0(双向) | RelationshipManager.Tick.cs |
| 同上司同侪 | +0.3(双向) | RelationshipManager.Tick.cs |
| 同专业 | +0.2(双向) | RelationshipManager.Tick.cs |
| 互动 | 时长(现实秒) | 好感变化 | 出处 |
|---|---|---|---|
| 闲聊 | 3 | 双向 +1 | SocialInteractionType.cs |
| 深聊 | 6 | 双向 +3 | SocialInteractionType.cs |
| 讲笑话 | 3 | 双向 +0.5 | SocialInteractionType.cs |
| 传八卦 | 5 | 双向 +1 | SocialInteractionType.cs |
| 争吵 | 4 | 双向 -2 | SocialInteractionType.cs |
| 辱骂 | 2 | 被骂方单向 -5 | SocialInteractionType.cs / Task_Socialize.cs |
社交触发参数(SocialIssuer.cs)
Section titled “社交触发参数(SocialIssuer.cs)”| 参数 | 数值 | 单位 |
|---|---|---|
| 扫描间隔 | 5 | 现实秒 |
| 空闲社交所需连续空闲 | 60 | 现实秒 |
| 副手日常派发间隔 | 7200 | 现实秒(约 2 现实小时) |
| 冲突名义概率 | 0.10 | 每现实小时(实际约 0.0083,见已知限制) |
| 冲突单次尝试概率 | ≈ 0.0139% | 每次扫描(= 0.10/3600 × 5) |
| 冲突尝试冷却 | 60 | 现实秒 / 每有序船员对 |
| 冲突好感门槛 | 双向均 < -20 | — |
| 辱骂(替代争吵)门槛 | 发起者对目标 < -50 | — |
| 副手日常深聊概率 | 30%(否则闲聊) | — |
| 空闲深聊条件 | 好感 ≥ +20 且双方心情 > 60,命中后 25% | — |
| 空闲讲笑话条件 | 发起者心情 > 60 且好感 ≥ 0,命中后 20% | — |
| 空闲传八卦条件 | 好感 > +40,命中后 20% | — |
| 并发社交上限 | max(5, 总人数 ÷ 10) | 任务数 |
| 社交任务工作优先级 | 1(最低正常档) | TaskDefs.cs / ConsumerPriorityConfig.cs |
空间判定(SpatialPredicates.cs)
Section titled “空间判定(SpatialPredicates.cs)”| 判定 | 规则 |
|---|---|
| 邻居(社交触发用) | 同甲板(y 相同)+ 切比雪夫距离 ≤ 3 格 |
| 共餐半径 | 同甲板 + 切比雪夫距离 ≤ 8 格 |
| 邻床 | 同甲板 + 曼哈顿距离 ≤ 2 格 |
钩子好感(RelationshipHooks.cs)
Section titled “钩子好感(RelationshipHooks.cs)”| 钩子 | 数值 |
|---|---|
| 共餐 | 双向 +0.5 |
| 同寝 | 双向 +0.3 |
| 共战幸存(两两) | 双向 +2 |
| 挚友哀悼判定门槛 | 生者对死者好感 ≥ +40 |
邓巴限流(DunbarThrottle.cs)
Section titled “邓巴限流(DunbarThrottle.cs)”| 参数 | 数值 |
|---|---|
| 槽位数 | 8 + floor(气质 ÷ 2),气质 1-20 → 槽位 8-18 |
| 朋友门槛 | +20 |
| 限流系数 | × 0.2(仅“满槽 + 本次跨线 + 正增量”时) |
汇报链与副手
Section titled “汇报链与副手”| 参数 | 数值 | 出处 |
|---|---|---|
| 管理容量公式(仅保留 API,不校验) | 1 + floor(指挥 ÷ 5),水手 0 | ReportingChain.cs |
| 船长副手槽 | 2 + (1 若气质 ≥ 15 且指挥 ≥ 25) | DeputyManager.cs |
| 军士副手槽 | 1 + (1 若气质 ≥ 15 且指挥 ≥ 15) | DeputyManager.cs |
| 专家/水手副手槽 | 0 | DeputyManager.cs |
| 环检测向上爬安全上限 | 1024 层 | ReportingChain.cs |
小团体(SubgroupComputer.cs)
Section titled “小团体(SubgroupComputer.cs)”| 参数 | 数值 |
|---|---|
| 成员资格 | 双向好感均 ≥ +20 的连通分量,≥ 2 人 |
| 重算间隔 | 30 现实秒 |
| 领袖评分 | 职级 × 1,000,000 + 技能总和 × 1,000 + 指挥 |
| 领袖迟滞 | 新候选评分 ≥ 现任 ÷ 0.9(约 +11.1%)才换 |
死亡心情想法(CSV 配置,策划可直接改)
Section titled “死亡心情想法(CSV 配置,策划可直接改)”来源:Assets/StreamingAssets/ThoughtConfig.csv(全表 10 行,下表为全量;本系统触发其中 3 条,其余由职级/死亡广播等系统触发):
| Id | 显示文本 | 心情变化 | 持续(游戏日) | 由本系统触发 |
|---|---|---|---|---|
| Promoted | 升职了! | +20 | 7 | 否 |
| Demoted | 被贬职 | -15 | 14 | 否 |
| RankDownMinor | 降级了 | -10 | 7 | 否 |
| TransferOther | 换了岗位 | -5 | 3 | 否 |
| CaptainMissing | 群龙无首 | -10 | -1(条件型) | 否 |
| CrewmateDied | {name} 阵亡了 | -15 | 7 | 否 |
| CaptainDied | 船长 {name} 阵亡 | -20 | 14 | 否 |
| BereavedFriend | 失去挚友 {name} | -20 | 5 | 是(好感 ≥ +40 的生者) |
| TeammateDied | 小队战友 {name} 阵亡 | -10 | 5 | 是(同小团体成员) |
| LeaderDied | 队长 {name} 阵亡 | -20 | 10 | 是(小团体领袖死亡) |
记忆 TTL(MemoryHooks.cs)
Section titled “记忆 TTL(MemoryHooks.cs)”| 记忆 | TTL(游戏日) |
|---|---|
| EnemyKilled | 7 |
| TransferredSpecialty | 14 |
| SurvivedBattle / BattleVictory | 3 |
| GotDrunk / WitnessedFight | 2 |
| AteAmazingMeal | 1 |
| 长期类(FriendDied 等 12 种) | 永久 |
与其他系统的交互
Section titled “与其他系统的交互”- 船员:气质属性决定邓巴槽位与副手扩槽;指挥技能决定副手扩槽与领袖评分;职级决定能否带人/带副手;专业相同产生被动好感。船员死亡事件驱动哀悼与团体震荡;心情组件承接死亡想法、并作为深聊/讲笑话的门槛输入。
- 任务与工作:社交任务走标准任务管线,工作类型 Social 默认优先级 1(最低正常档),任何工作或需求任务都会压过社交;进食/睡眠任务的收尾步骤回调共餐/同寝钩子。
- 时间与调度:被动日增、周衰减、记忆 TTL 按游戏日(日变更事件)走;社交触发节拍(扫描/冷却/空闲计时/副手间隔)按现实秒走——两套时间基准并存,调参时务必分清(默认速度 1 游戏日 = 24 现实秒)。
- 遭遇与刷怪:战斗结束消息驱动“共战 +2”与“SurvivedBattle”记忆,按船过滤,只奖励本船存活者。
- 船只:关系系统以船为作用域,玩家船与每艘 AI 船各有独立实例。
- 界面总览:船员组织树面板(拖拽改组草案制 + 副手按钮 + 三视图)、船员抽屉记忆页签、世界空间社交气泡与好感飘字。
- 存档:本系统完全不存档——好感矩阵、记忆、副手、小团体在重新加载后全部清零(汇报链 ManagerId 也不持久化,重载后由自动指派重建)。
配置与调参指南
Section titled “配置与调参指南”| 想调的体验 | 改哪里 | 类型 |
|---|---|---|
| 死亡哀悼的心情打击力度/时长 | Assets/StreamingAssets/ThoughtConfig.csv 的 BereavedFriend / TeammateDied / LeaderDied 行 |
CSV(策划可改) |
| 互动好感数值/时长 | SocialInteractionType.cs 的 DurationSeconds / OpinionDeltaBoth |
代码常量 |
| 辱骂的单向 -5 | Task_Socialize.cs ApplyOpinionDeltas |
代码常量 |
| 被动日增五项 | RelationshipManager.Tick.cs ApplyDailyAccruals |
代码常量 |
| 周衰减系数 0.85 / 周期 7 天 | RelationshipManager.Tick.cs |
代码常量 |
| 邓巴槽基数 8 / 限流系数 0.2 / 朋友门槛 +20 | DunbarThrottle.cs |
代码常量 |
| 冲突概率/冷却、空闲门槛、副手日常间隔、并发上限 | SocialIssuer.cs 顶部常量区 |
代码常量 |
| 空闲互动类型的概率与门槛 | SocialIssuer.cs PickFreeSocialType |
代码常量 |
| 共餐/同寝/共战好感与半径 | RelationshipHooks.cs 常量区 + SpatialPredicates.cs |
代码常量 |
| 副手槽位公式与门槛 | DeputyManager.cs GetDeputySlotCount |
代码常量 |
| 管理容量公式(当前未生效) | ReportingChain.cs GetCapacity |
代码常量 |
| 小团体门槛 +20 / 重算 30 秒 / 迟滞 0.9 | SubgroupComputer.cs + RelationshipManager.Subgroup.cs |
代码常量 |
| 记忆 TTL | MemoryHooks.cs 各 Record 函数 |
代码常量 |
| 标签五档阈值 | OpinionLabel.cs |
代码常量 |
| 气泡/飘字样式(高度/字号/颜色/1 秒漂浮) | SocialBubbleOverlay.cs |
代码常量 |
本系统没有 Unity Inspector 序列化参数;除 ThoughtConfig.csv 外全部为代码常量。
已知限制与注意事项
Section titled “已知限制与注意事项”- 全系统不存档:好感、记忆、副手、汇报链、 小团体重载即清零。设计文档(
Docs/qq/u_tyk_DPP-961-demo-loop-closure/crew-relationship-faction_design.md)明确 MVP 不存档,与船员花名册存档一起在后续版本做。 - 两套时间基准混用:被动日增/衰减/记忆 TTL 用游戏日(默认 24 现实秒一天),而社交触发全部用现实秒。后果之一:副手日常间隔 7200 现实秒,按默认速度折合 300 游戏天才一轮(且开局后要等满 7200 秒才有第一轮),远疏于设计文档“每 2 小时一次”的意图——若设计意图是游戏小时,此处差 3600 倍。
- 冲突触发的有效概率远低于注释:注释意图 10%/小时,但概率判定前先写入 60 秒冷却,导致每对每小时最多 60 次尝试 × 单次 0.0139% ≈ 0.83%/现实小时。按现实小时计的“小时”本身也与游戏小时(1 现实秒)相去甚远。
- 好感标签与小团体没有 gameplay 效果:设计中的关系区间工作效率加成(挚友 +5%、不和 -3% 等)与小团体工作加成(+3%、领袖邻近 +2%)均未实现。当前好感的实际作用仅有:冲突争吵/辱骂触发、空闲互动类型选择门槛、死亡哀悼判定(≥ +40)、小团体可视化。
- 记忆钩子大面积未接线:
MemoryHooks.cs的 19 个记录函数中只有 FriendDied、TeammateDied、LeaderDied、SurvivedBattle 被调用;升职/降职/任免副手/击杀/醉酒/美餐等 15 种记忆有定义无触发源,玩家在记忆页签只会看到死亡与战斗幸存类条目。 - 与设计文档的其他差异:
- 设计中辱骂需“好感 < -40 + 火爆特质”,实现为“发起者对目标好感 < -50”(特质系统未实装);
- 设计中讲笑话附带“双方心情 +2 持续 4 小时”,实现只加好感;
- 设计中传八卦需“共同好感 ≥ +40 的第三人”并对第三人好感 ±0.5,实现注明“简化跳过”,无第三人效果;
- 设计中“目睹友死减观察者 -10 好感”未实现(死亡只影响心情与记忆,不改好感矩阵);
- 设计中的管理人数上限(1 + floor(指挥/5))未启用——下属数量无上限,
ManagerCapExceeded错误码永不返回; - 设计中互动双方 face-to-face(目标停下手头活转身)未实现:目标只被“社交预约”,继续做自己的事;
- 设计中头顶气泡为图标,实现为中文文字标签(项目规范禁止 emoji);
- 派系/叛变(V3)完全未实装。
- 自动指派比手动更严格:自动找上司要求候选人职级严格高于本人,手动拖拽只要求对方不是水手——平级互带只能手动完成。
- 小团体编号不稳定:每次重算从 0 重新编号,界面上的“小团体 #N”在 30 秒后可能变号;领袖防抖仅在成员集合完全不变时生效。
- 辱骂与争吵都要求双向好感 < -20:单方面厌恶(一方 -30、另一方 0)不会触发任何冲突互动。
- 心情组件缺失时按基础值 50 处理,深聊/讲笑话的“心情 > 60”门槛默认不满足——心情系统不工作时空闲社交几乎只会闲聊和传八卦。