物品与库存
This content is not available in your language yet.
全船物品一律装在“容器”里流转:物品堆(数量 + 动态属性)→ 容器格子(带白名单)→ 容器注册表(找货)→ 资源预留(任务锁货)→ 船员搬运。本页讲清楚堆叠、容器、预留、地面物品与搬运的全部规则与数值。
本游戏没有“全局背包”。木头、煤炭、食物、弹药等一切物品都必须实际存在于某个容器中,容器分三类宿主:
- 建筑容器:每个建筑最多拥有输入(Input)/ 输出(Output)/ 存储(Storage)三个容器,容量由
BuildingContainerConfig.csv配置(见下文容量表)。 - 地面容器:物品掉在甲板某一格时,该格会自动生成一个地面容器(默认 20 格),物品以九宫格图标显示在地板上。
- 船员随身背包:每名船员有一个 10 格背包(代码常量,
Crew.cs),仅用于搬运途中临时持有物品。
在游戏循环中的位置:生产(生产与制作)产出进输出容器 → 搬运任务把物品送进仓库或下一个建筑的输入容器 → 消耗系统(修建 / 武器装弹 / 锅炉补煤 / 进食饮水)从仓库取走。整条链路由资源预留系统保证“一份货不会被两个任务同时盯上”。
玩家接触物品系统的入口:
| 入口 | 行为 | 出处 |
|---|---|---|
| “船上物品”常驻面板(屏幕左侧) | 每 0.2 秒聚合全船非生产建筑的三类容器,按物品 + 鲜/陈状态分行显示总数 | ShipInventoryPanel.cs |
| 点击建筑 / 地面物品 | 在鼠标点击位置弹出容器内容浮窗(含输入/输出/存储分区、生产进度),每 0.3 秒刷新内容,同一建筑期间位置不动 | ContainerPopupManager.cs |
| 地面物品九宫格图标 | 每格地面容器最多显示 9 个物品图标,超出部分显示 “+N” | FloorItemVisualManager.cs |
| 鼠标悬停建筑(仅开发面板开启时显示文字) | 浮动水晶指示器 + 容器调试文本 | BuildingHoverManager.cs |
物品堆与堆叠上限
Section titled “物品堆与堆叠上限”物品在容器里的最小单位是物品堆(ItemStack.cs):物品 ID + 数量 + 一组动态属性(年龄 / 新鲜度 / 耐久 / 饱食 / 品质)。
- 堆叠上限来自
StaticItemConfig.csv的MaxStackSize列(策划可直接改,改后需重新运行 Tools → CSV Code Generator)。 - 配置缺失时回退到代码常量 50(
ItemStack.cs中MAX_STACK_SIZE)。 MaxStackSize ≤ 1的物品完全不可堆叠也不可合并(当前表中只有 Monster 怪物 = 1)。
合并与拆分规则
Section titled “合并与拆分规则”两个物品堆可以合并,当且仅当同时满足(ItemStack.cs):
- 物品 ID 相同;
- 堆叠上限 > 1(不可堆叠物品直接拒绝);
- 目标堆未满;
- 双方的动态属性类型集合完全一致(例如都带 Age + Hungry;值可以不同)。
合并数量公式:
本次合并量 = min(目标堆上限 − 目标堆当前数量, 来源堆数量)合并是“目标加、来源减”的真转移;来源堆剩余部分留在原地继续找下一个格子。
拆分:从一个堆里分出 n 个(n 必须严格小于当前数量),动态属性原样克隆到新堆。容器间转移只取走一格的一部分时,内部即走拆分。
合并时的属性结算(不同属性规则不同,详见下节)——这是策划要重点理解的机制:把新货倒进旧货堆,旧货的年龄/新鲜度会被摊薄而不是取最差值。
物品动态属性
Section titled “物品动态属性”每个物品堆可携带最多 5 种动态属性,是否携带由 StaticItemConfig.csv 的 Use* 开关决定(属性默认值 Default*、上限 Max* 同表配置):
| 属性 | 值域 | 单位 | 合并结算规则 | 出处 |
|---|---|---|---|---|
| Age 年龄 | 0 ~ MaxAge | 游戏天 | 按数量加权平均,四舍五入取整 | Age.cs |
| Freshness 新鲜度 | 0 ~ MaxFreshness(默认 100) | 百分比 | 按数量加权平均 | Freshness.cs |
| HP 耐久 | 0 ~ MaxHP | 点 | 按数量加权平均,四舍五入取整 | HP.cs |
| Hungry 饱食恢复 | 0 ~ MaxHungry(默认 100) | 百分比 | 按数量加权平均 | Hungry.cs |
| Quality 品质 | 0=差 / 1=普通 / 2=优质 / 3=史诗 | 等级 | 取较高品质;但低品质一方数量 ≥ 高品质一方 3 倍时,取数量多的一方 | Quality.cs |
加权平均公式(Age / Freshness / HP / Hungry 通用):
合并后属性值 = (目标堆值 × 目标堆原数量 + 来源值 × 本次并入数量) ÷ (目标堆原数量 + 本次并入数量)设计意图(Age.cs 代码注释明示):避免“1 滴老货污染整桶”的棘轮问题;副作用是玩家可以持续补新货摊薄老货——这是有意的玩法,鼓励主动轮转库存。
注意:CSV 中的 UseThirst / DefaultThirst / MaxThirst(解渴值)不会成为物品堆属性(没有对应属性类),它由船员需求系统直接读配置使用。
保质期与腐烂
Section titled “保质期与腐烂”带 Age 属性且 FreshDays ≥ 0 的物品会逐日变质(ShelfLifeSystem.cs,每艘船一个实例,订阅日切事件,见 时间与调度):
- 每过 1 游戏天,全船所有容器内带 Age 属性且 FreshDays ≥ 0 的物品堆年龄 +1(FreshDays = -1 的物品被跳过,年龄不增长)。
- 三段状态(
FreshnessState.cs):
| 状态 | 判定 | 对玩家的价值 |
|---|---|---|
| 新鲜 Fresh | 年龄 ≤ FreshDays | 100% |
| 陈旧 Stale | FreshDays < 年龄 ≤ FreshDays + StaleDays | 50%(饱食/解渴恢复量、出售价统一打 5 折,代码常量 StaleValueMultiplier = 0.5,FreshnessState.cs) |
| 腐烂 | 年龄 > FreshDays + StaleDays | 整堆消失,原地转化为 RotItemId 指定的物品(等量) |
- 腐烂预警:年龄恰好等于 FreshDays + StaleDays 那天(即“明天就烂”)触发预警事件,UI 弹提示,给玩家整整一天去消耗 / 出售 / 再加工。
- 腐烂整堆消失前会先清掉该格子上所有人的预留,防止任务系统永远认为这批货还被锁着。
- 腐烂转化物(如腐食)如果被目标容器白名单拒收,会直接丢弃(仅日志告警)。
当前会腐烂的物品(StaticItemConfig.csv):
| 物品 | 新鲜段(天) | 陈旧段(天) | 腐烂于第几天 | 转化为 |
|---|---|---|---|---|
| DrinkableWater 饮用水 | 10 | 8 | 第 19 天 | StaleWater 臭水 |
| MonsterMeat 怪物肉 | 3 | 2 | 第 6 天 | RottenFood 腐食 |
| CookedMeal 熟食 | 18 | 12 | 第 31 天 | RottenFood 腐食 |
| Grog 格罗格酒 | 36 | 24 | 第 61 天 | StaleWater 臭水 |
容器(BaseContainer.cs)= 固定数量的格子(ContainerSlot.cs),每格放一个物品堆。容量即格子数。
入库流程(两阶段)(AddHandler.cs):
- 先逐格尝试并入已有的同物品格子(受合并规则约束);
- 剩余部分按堆叠上限切块放入空格(按格子序号从小到大找第一个白名单允许的空格)。
部分入库:空间只够装一部分时,操作仍返回成功并报告实际入库数量——容器满时多出的部分会被截断。
**白名单过滤(Filter)**两级,均为白名单语义(空 = 不限制):
- 容器级:限制整个容器收什么(如武器输入容器只收对应弹药)。
- 格子级:限制单个格子收什么。典型用法是多弹药武器:AA 炮输入容器 2 格、2 种消耗品时,每种弹药独占
容量 ÷ 弹药种数个格子,防止单一弹药占满(BuildingComponentContainers.cs自动根据WeaponConsumptionConfig.csv的 Item1~Item4 生成,详见武器与弹药)。
容器三类型(ContainerType.cs),语义直接决定搬运 AI 的行为:
| 类型 | 用途 | 可作搬运来源? | 可作搬运目标? |
|---|---|---|---|
| Input 输入 | 建筑加工原料区 | 否(防止船员从引擎输入区偷煤导致生产中断,回归测试 ContainerRegistryInputExclusionTests.cs) |
否(只能由定向投料任务写入) |
| Output 输出 | 生产产出区 | 是 | 否 |
| Storage 存储 | 通用仓库 | 是 | 是(唯一合法目标) |
各建筑容器容量(BuildingContainerConfig.csv 全量,单位:格;未配置的建筑三容器容量均为 0,墙 / 楼梯等不暴露容器):
| 建筑 | 输入 | 输出 | 存储 |
|---|---|---|---|
| WaterPump 水泵 | 0 | 1 | 0 |
| Boiler 锅炉 | 3 | 3 | 0 |
| Engine 引擎 | 1 | 1 | 0 |
| ButcherTable 屠宰台 | 2 | 2 | 0 |
| Galley 厨房 | 3 | 2 | 0 |
| AmmoBench 弹药工作台 | 3 | 3 | 0 |
| Brewery 酿酒坊 | 3 | 2 | 0 |
| WoodContainer 木箱 | 0 | 0 | 30 |
| PurchaseBox 采购箱 | 0 | 0 | 100 |
| MagicContainer 魔法容器 | 0 | 0 | 100 |
| WaterBarrel 水桶 | 0 | 0 | 1 |
| Cannon_Prod / MachineGun_Prod / Flame_Prod(量产武器) | 1 | 0 | 0 |
| AA_Gun_Prod | 2 | 0 | 0 |
| Cannon_Dev / MachineGun_Dev / Flame_Dev(开发武器) | 1 | 0 | 0 |
| AA_Gun_Dev | 2 | 0 | 0 |
特殊容器:
| 容器 | 容量 | 行为 | 出处 |
|---|---|---|---|
| 船员随身背包 | 10 格 | 搬运途中临时持有 | Crew.cs(代码常量) |
| 地面容器 | 20 格(代码常量 DEFAULT_FLOOR_CAPACITY) |
按格子坐标自动创建/销毁 | FloorContainerManager.cs |
| 单格容器 | 1 格 | 装备槽类场景 | OneGridContainer.cs |
| 开发者容器 | 默认 50 格 | 取之不尽:移除永远成功不扣数量、查询总数恒为 999999、预留永远成功(见开发者工具) | DevContainer.cs |
容器注册表与找货规则
Section titled “容器注册表与找货规则”所有建筑容器与地面容器统一注册到容器注册表(ContainerRegistry.cs,每艘船一个实例)。任务系统找货 / 找仓位只通过它:
- 找来源(FindSources):遍历所有注册容器,跳过 Input 容器、跳过施工格上的地面容器;只统计可用数量(扣除预留)> 0 的容器;按直线距离(格,欧几里得,非寻路距离)从近到远排序,截取前 N 个候选。
- 找目标(FindTargets):只接受 Storage 类型且不是地面容器的容器,且可接纳数量 > 0;同样按直线距离从近到远排序。
- 各业务的候选数 N:建筑生产取料预检 50 / 实际派单 8(
ProductionFetchIssuer.cs),施工取料 8(FetchRequest.cs),锅炉补煤 8(SupplyBoilerRequest.cs),武器装弹 12(ReloadTurretRequest.cs),进食饮水 1(NeedRequestHelper.cs)。
资源预留系统(任务如何锁货)
Section titled “资源预留系统(任务如何锁货)”这是物流稳定性的核心(ContainerReservationManager.cs,每个容器内置一个)。
概念:任务创建时在来源容器登记“我要 N 个 X”。物品物理上不动,仍躺在原格子里,但这 N 个对其他任务隐形。
可用数量 = 物理总数 − 所有人的预留总数规则细则:
- 预留按(物品 ID,预留者 ID)记账,并落实到具体格子:按格子序号从小到大,在已有该物品且尚有未预留余量的格子上分配。不能预留“未来才会有”的货。
- 预留申请量 > 当前可用量 → 整笔失败(不做部分预留)。
- 同一份货不可能被两个预留者重复锁定(测试佐证
ContainerReserveTests.cs)。 - 取货特权:操作者从容器取货时,可取上限 = 可用数量 + 自己的预留量;优先从自己预留的格子取(
RemoveHandler.cs)。无操作者 ID 的“系统操作”只能动可用部分,绝不会碰别人预留的份额。 - 取走 / 转出后,按格子精确地自动释放等量预留——取多少释放多少,剩余预留继续有效。
- 预留不跟随物品转移:货从 A 容器搬到 B 容器后,A 上的预留被释放,B 上不会自动产生新预留。
- 每个任务用全局唯一的预留者 ID(如生产取料的
ProdFetch_建筑_物品_批次_随机串,ProductionFetchIssuer.cs),避免跨任务串号。 - 兜底释放:任务无论完成、取消还是失败,结束时统一释放其名下所有剩余预留(
TaskBase.cs+ResourceReservation.cs)——不存在超时机制,靠任务生命周期保证。 - 特殊清理:腐烂整堆消失前释放该格全部预留;水桶泄漏每次只漏 1 个单位时按数量精确扣减预留(“漏掉的这 1 份谁倒霉算谁的”,
ContainerReservationManager.cs注释)。
策划答疑:为什么界面显示有货,任务却说没货 / 卖不掉?
| 现象 | 原因 |
|---|---|
| 面板显示有 50 木头,施工却报“材料不足” | 已有别的任务预留了这批木头:找货只看可用数量,面板显示的是物理总数(不扣预留,ShipInventoryPanel.cs) |
| 引擎输入区明明有煤,别的锅炉不来拿 | Input 容器永远不作为搬运来源(防偷料保护) |
| 施工蓝图脚下堆着材料,别处的需求不来拿 | 施工格(建筑处于框架状态)上的地面容器被排除出来源(施工现场材料保护,ContainerRegistry.cs) |
| 货卡在厨房输出区,“船上物品”面板看不到 | 面板只统计非生产建筑(不在 ProductionBuildingConfig.csv 里的建筑)的容器,生产中间品不计入“可用资源” |
| 出售时交易界面数量比面板少 | 交易出售只扫 Storage 类型容器(PlayerTrader.cs,见交易) |
地面物品与拾取
Section titled “地面物品与拾取”物品落地 = 该格自动创建一个 20 格的地面容器(FloorContainerManager.cs):
- 来源:搬运任务中断时丢下携带物、
Task_Haul把材料送到施工格旁、船员失禁在脚下产生 1 个粪便(Crew.cs)。怪物战利品掉落走独立的 Loot 系统,不直接生成地面容器(见战利品与掉落)。 - 可视化(
FloorItemVisualManager.cs):每格按 3×3 九宫格摆放物品图标(始终面向相机),最多 9 个,超出显示 “+N” 标签。图标尺寸 0.3、离地高度 0.1(Unity Inspector 序列化字段);九宫格间距 0.25(代码常量)。无图标资源的物品显示按物品 ID 哈希取色的色块(5 色备选,Inspector 字段)。 - 拾回:地面容器默认注册为 Storage 类型,所以可以作为搬运来源被任务取走(施工格除外);但永远不会被选为搬运目标——散落地面的物品只会被搬进建筑仓库,不会从仓库搬到地上。
- 自动清理:每发生 50 次“获取或创建地面容器”操作就清扫一遍空容器(代码常量
CLEANUP_INTERVAL);地面容器总数 ≥ 500 打警告日志、≥ 1000 打错误日志(仅日志,不阻止创建)。 - 地板被摧毁:该格地面容器连同里面所有物品直接消失(材料丢失,仅日志告警)。
物品搬运流程(端到端)
Section titled “物品搬运流程(端到端)”以“厨房缺怪物肉”为例(任务与工作 提供任务框架):
- 发单:生产派发器发现输入容器缺料,通过容器注册表找最近的合法来源(直线距离排序)。
- 锁货:在来源容器上预留所需数量;预留失败则尝试下一个候选来源。
- 建任务:生成搬运任务(送地面用
Task_Haul.cs,送建筑输入容器用Task_HaulToContainer.cs),任务构造时把预留登记到自己名下。 - 可分配检查:任务被船员领取前持续校验“预留还在吗”(结果缓存 0.5 秒,代码常量,
TaskBase.cs);预留失效(如货腐烂被清)则任务显示“预约失效”且无法分配。 - 执行四步:走到来源 → 拾取(先释放预留,再把货转移进船员 10 格背包,进入携带状态,
Steps.Carry.cs)→ 走到目的地 → 放置(从背包转移进目标容器,Steps.Place.cs)。 - 中断兜底:任务中途取消 / 失败时,携带中的物品自动丢到船员脚下的地面容器(
TaskBase.cs的携带清理);未消费的预留由任务结束流程统一释放。 - 放置失败:目标容器装不下全部数量时放置步骤整体失败(转移要求一次容纳全部,不做部分转移,
TransferHandler.cs),物品随后按中断流程丢到地面。
公式与数值(集中表)
Section titled “公式与数值(集中表)”| 公式 | 出处 |
|---|---|
| 本次合并量 = min(堆叠上限 − 目标堆数量, 来源堆数量) | ItemStack.cs |
| 合并后属性值 = (目标值×目标原数量 + 来源值×并入数量) ÷ (目标原数量 + 并入数量)(Age/HP 四舍五入) | ItemProperty.cs |
| 品质合并 = 高品质方获胜;若低品质方数量 ≥ 高品质方 × 3 则数量方获胜 | Quality.cs |
| 可用数量 = 物理总数 − 全部预留 | ContainerReservationManager.cs |
| 操作者可取量 = 可用数量 + 自己的预留量 | RemoveHandler.cs |
| 腐烂条件:年龄 > FreshDays + StaleDays;预警:年龄 = FreshDays + StaleDays | ShelfLifeSystem.cs |
| 陈旧品价值 = 原值 × 0.5 | FreshnessState.cs(代码常量) |
| 武器格子白名单:每种弹药独占 输入容量 ÷ 弹药种数 个格子 | BuildingComponentContainers.cs |
| 数值 | 值 | 单位 | 来源类型 | 出处 |
|---|---|---|---|---|
| 堆叠上限回退值 | 50 | 个 | 代码常量 | ItemStack.cs |
| 船员背包容量 | 10 | 格 | 代码常量 | Crew.cs |
| 地面容器容量 | 20 | 格 | 代码常量 | FloorContainerManager.cs |
| 地面容器清理周期 | 每 50 次操作 | 次 | 代码常量 | FloorContainerManager.cs |
| 地面容器数量警告 / 错误阈值 | 500 / 1000 | 个 | 代码常量 | FloorContainerManager.cs |
| 地面图标上限 / 间距 | 9 个 / 0.25 | 个 / 世界单位 | 代码常量 | FloorItemVisualManager.cs |
| 地面图标尺寸 / 离地高度 | 0.3 / 0.1 | 世界单位 | Inspector 序列化字段 | FloorItemVisualManager.cs |
| 开发者容器虚拟存量 | 999999 | 个 | 代码常量 | DevContainer.cs |
| 任务可分配检查缓存 | 0.5 | 秒 | 代码常量 | TaskBase.cs |
| 船上物品面板刷新 | 0.2 | 秒 | 代码常量 | ShipInventoryPanel.cs |
| 容器浮窗刷新 | 0.3 | 秒 | 代码常量 | ContainerPopupManager.cs |
| 找货候选数:生产预检/派单、施工、锅炉、装弹、进食饮水 | 50/8、8、8、12、1 | 个 | 代码常量 | ProductionFetchIssuer.cs 等 |
| 陈旧品价值系数 | 0.5 | 倍 | 代码常量 | FreshnessState.cs |
物品总表(StaticItemConfig.csv,全量 29 行,CSV 配置,策划可直接改)
Section titled “物品总表(StaticItemConfig.csv,全量 29 行,CSV 配置,策划可直接改)”列含义:堆叠上限 = 单格最多叠多少;动态属性列出该物品携带的属性及默认值;“鲜/陈(天)“为 -1 表示永不变质。
| ItemId | 名称 | 类型 | 堆叠上限 | 动态属性(默认值) | 鲜/陈(天) | 腐烂转化 |
|---|---|---|---|---|---|---|
| Monster | 怪物 | Consumable | 1 | HP 100/100、Age 10(上限 100)、品质 1、饱食 50 | -1(不走保质期) | — |
| SaltPork | 咸肉 | Food | 20 | 品质 1、饱食 40 | -1 | — |
| DrinkableWater | 饮用水 | Food | 50 | Age 0(上限 19);解渴 50 | 10 / 8 | StaleWater |
| Water | 水(工业) | Resource | 50 | 无 | -1 | — |
| Steam | 蒸汽 | Resource | 50 | 无 | -1 | — |
| Bullet | 子弹 | Resource | 50 | 无 | -1 | — |
| CannonShell | 炮弹 | Resource | 200 | 无 | -1 | — |
| Fuel | 燃料 | Resource | 500 | 无 | -1 | — |
| AA_Gun_Bullet | AA 子弹 | Resource | 50 | 无 | -1 | — |
| Wood | 木头 | Material | 100 | 无 | -1 | — |
| Stone | 石头 | Material | 100 | 无 | -1 | — |
| IronPlate | 铁板 | Material | 50 | 无 | -1 | — |
| Feces | 粪便 | Waste | 10 | 无 | -1 | — |
| Coal | 煤炭 | Resource | 100 | 无 | -1 | — |
| MonsterCorpse | 怪物尸体 | Material | 5 | 新鲜度 100/100 | -1 | — |
| MonsterMeat | 怪物肉 | Food | 20 | 新鲜度 100/100、Age 0(上限 6)、饱食 15 | 3 / 2 | RottenFood |
| BeastOil | 兽油 | Resource | 50 | 无 | -1 | — |
| CookedMeal | 熟食 | Food | 20 | Age 0(上限 31)、饱食 50 | 18 / 12 | RottenFood |
| BlackPowder | 黑火药 | Resource | 50 | 无 | -1 | — |
| MonsterBrew | 怪物酒 | Food | 30 | 品质 1;解渴 50;含酒精,单次饮用血醇 +40,自动饮用优先级 -1(不自动喝) | -1 | — |
| Grog | 格罗格酒 | Food | 50 | Age 0(上限 61)、品质 1;解渴 50;含酒精,单次饮用血醇 +10,优先级 20 | 36 / 24 | StaleWater |
| RottenFood | 腐食 | Waste | 50 | 品质 1 | -1 | — |
| StaleWater | 臭水 | Waste | 50 | 品质 1 | -1 | — |
| LuxuryWine | 奢侈红酒 | Resource | 30 | 无 | -1 | — |
| LuxuryTobacco | 奢侈烟草 | Resource | 30 | 无 | -1 | — |
| LuxuryCloth | 奢侈布匹 | Resource | 30 | 无 | -1 | — |
| LuxuryArtillery | 奢侈火炮 | Resource | 30 | 无 | -1 | — |
| LuxuryCoffee | 奢侈咖啡 | Resource | 30 | 无 | -1 | — |
| LuxurySilk | 奢侈丝绸 | Resource | 30 | 无 | -1 | — |
注:解渴值(Thirst 列)与饮用优先级由需求系统直接读取,不挂在物品堆上;完整逐列表格另见物品数据表与配置表总览。
与其他系统的交互
Section titled “与其他系统的交互”- 生产与制作:生产建筑通过输入/输出容器吞吐物料;取料派单走预留 + 搬运链路(
ProductionFetchIssuer.cs)。 - 修建:施工取料把材料搬到蓝图旁的地面容器;施工格地面容器受“来源排除”保护不被挪用。
- 任务与工作:预留的生命周期与任务绑定;搬运任务的步骤组合(走→拾→走→放)。
- 船员:10 格随身背包;失禁产生粪便;进食饮水从容器预留并取货。
- 武器与弹药:武器输入容器自动生成弹药白名单与格子分配;装弹任务找货候选 12 个。
- 交易:出售只扫 Storage 容器;陈旧食物饮品出售价打 5 折。
- 战利品与掉落:怪物掉落走独立 Loot 系统,收集后才进入容器体系。
- 时间与调度:保质期系统挂在“每游戏日”日切事件上。
- 存档:容器经专用序列化类(
SerializableContainerData.cs)保存容量 / 白名单 / 物品及属性;预留不进存档(见已知限制)。 - 界面总览:船上物品面板、容器浮窗、地面物品图标的归属层级。
- 开发者工具:无限物品的开发者容器;编辑器容器监视窗口(
ContainerMonitorWindow.cs);悬停调试文本由开发面板开关。
配置与调参指南
Section titled “配置与调参指南”| 想调什么 | 改哪里 | 注意 |
|---|---|---|
| 某物品堆叠上限 | StaticItemConfig.csv 的 MaxStackSize 列 |
改完跑 Tools → CSV Code Generator → Generate All |
| 给物品加 / 删动态属性 | 同表 Use* / Default* / Max* 列 |
Age、Hungry、HP、Freshness 还要求对应 Max > 0 才会真正挂上属性 |
| 让某物品会腐烂 | 同表 UseAge=true、FreshDays / StaleDays / RotItemId |
MaxAge 必须 ≥ FreshDays + StaleDays + 1,否则年龄被钳在上限永远到不了腐烂阈值(现有四种腐烂物均精确等于该值) |
| 某建筑容器容量 | BuildingContainerConfig.csv 对应行 |
容量 0 = 不创建该容器;新建筑不配行则三容器全无 |
| 武器吃什么弹药(输入白名单) | WeaponConsumptionConfig.csv 的 Item1~Item4 |
白名单与格子分配自动生成 |
| 陈旧品打折力度 | FreshnessState.cs 的 StaleValueMultiplier(现 0.5) |
代码常量,需程序改 |
| 船员背包容量 | Crew.cs 构造背包处(现 10) |
代码常量,需程序改 |
| 地面容器格数 / 清理频率 | FloorContainerManager.cs(现 20 格 / 每 50 次操作) |
代码常量,需程序改 |
| 地面图标大小 / 离地高度 / 占位色 | FloorItemVisualManager 组件的 Inspector 字段 |
运行时自动创建的单例对象,改默认值需改脚本序列化初值 |
| 找货候选数量 / 排序 | 各请求类(ProductionFetchIssuer.cs、FetchRequest.cs 等)传入的 maxResults |
代码常量,需程序改 |
| 面板 / 浮窗刷新频率 | ShipInventoryPanel.cs(0.2 秒)、ContainerPopupManager.cs(0.3 秒) |
代码常量,需程序改 |
已知限制与注意事项
Section titled “已知限制与注意事项”- 预留不进存档:
SerializableContainerData.cs的预留转换是空实现(代码注释“暂时跳过,可后续完善”)。读档后所有预留清零,依赖任务系统重新发单建立预留。 - 找货用直线距离:来源排序按格子坐标欧几里得距离,不是寻路距离——隔着一层甲板的“近”仓库可能实际绕路很远。
- 预留锁数量不锁实物:系统操作(无操作者)取走可用份额时,物理上可能恰好动了你预留的那一格的实物,但数量账目守恒,预留者随后取货仍然成功(测试佐证
ContainerReserveTests.cs)。 - 部分入库会静默截断:容器满时入库返回“成功 + 实际数量”,超出部分不退回;腐烂转化物被白名单拒收时直接丢弃(仅日志)。
- 转移不支持部分成功:目标装不下全部数量时整笔失败(
TransferHandler.cs预校验),搬运任务随即把货丢在地上。 - 地板摧毁 = 物品蒸发:该格地面容器及全部内容直接删除,无掉落保护。
- 摊薄合并可被刻意利用:往陈旧堆里持续倒新货可把平均年龄压回新鲜段——代码注释明确这是有意设计(鼓励轮转库存),调保质期数值时要把这个回血手段算进去。
- 不可堆叠物品的“同属性合并 1 个”分支是死代码:
ItemStack.cs的可合并量计算里有 MaxStackSize ≤ 1 时按属性全同合并 1 个的逻辑,但合并前置检查对不可堆叠物品直接拒绝,该分支实际不可达。 - 按物品堆实例移除不会自动释放预留(
RemoveHandler.cs中RemoveStackHandler注释明示由调用方负责);生产路径主要走“按物品 ID 移除”,该路径有自动精确释放。 - 怪物(Monster)带 Age 属性但 FreshDays = -1,保质期系统完全跳过它,年龄不会逐日增长——Age 10 只是静态档案值。
- 待重构标记(代码 TODO):
FloorItemVisualManager.cs应改用统一单例基类;BuildingHoverManager.cs计划重构为挂在建筑上的分布式悬停组件。 - 属性合并依赖反射:物品堆合并属性时通过反射调用各属性的合并方法(
ItemStack.cs),与项目“运行时禁反射”的规约存在出入,属于历史遗留实现。