Cataclysm-DDA 灾变后价格体系实战指南:price_postapoc 从货币锚点到实战配置
【免费下载链接】Cataclysm-DDACataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.项目地址: https://gitcode.com/GitHub_Trending/ca/Cataclysm-DDA
你正在写第一个模组,给自制的抗生素填灾变后价格——填多少?这几乎是每个 CDDA(Cataclysm-DDA)模组作者绕不开的问题:price_postapoc字段决定了物品在灾后经济里的全部身价。本文直接从仓库里的真实配置与引擎源码出发,回答三件事:postapoc 定价的"尺子"从哪来、引擎如何把这个数字算成屏幕上显示的价格、以及你给新物品定价时怎样不出错。
如果你想边读边翻源码,可以先拉一份仓库(只读参考即可):
git clone https://gitcode.com/GitHub_Trending/ca/Cataclysm-DDA先造一把尺子:250 cent 的货币锚点
结论先行:CDDA 的灾后定价有一把统一的"市尺"——自由商人本票(merch)= 一片肉干 = 250 cent。所有物品的price_postapoc都是围绕这把尺子换算的,就像菜市场的斤两必须先统一单位。
那为什么偏偏是肉干?依据写在 doc/design-balance-lore/POSTAPOC_PRICE_GUIDE.md 里:一片肉干能保鲜24 天、含347 卡路里——耐放、顶饱、好携带,是天然的硬通货等价物。文档还给幸存者经济划了两条参考线:
- 每天带回2000 cent(约 8 片肉干)等值货物 → 勉强维持温饱;
- 每天带回4000 cent→ 已经过得不错。
设计任务奖励或商人库存时,用这两条线反推玩家需要的搜刮劳动量,就是一个现成的平衡校准器。
仓库里 data/json/items/generic/currency.json 实现了多种派系货币,压缩成一张对照表(单位 cent,1 USD = 100 cent):
| id | 名称 | 灾变前价 | 灾变后价 | 发行方 |
|---|---|---|---|---|
FMCNote | merch | 50 USD | 250(= 1 片肉干) | 自由商人(避难所中心) |
RobofacCoin | Hub 01 金币 | 900 USD | 5000(= 20 张 merch) | Hub 01(约一盎司低纯度金) |
FlatCoin | FlatCoin | 5 cent | 250 | 校园交换代币(压扁的米奇币) |
signed_chit | chit | 5 cent | 250 | 个人/机构签名纸片 |
icon | icon | 2 USD | 250 | 新英格兰教会社区 |
规律一目了然:除了 Hub 01 金币靠实体黄金撑起 5000 cent 的高位,其余社区货币全部锚定 250 cent——"一张票 = 一片肉干"。去中心化的末日里各自印钱,但单位是同一把尺,换算才不会被毁掉。而 FMCNote 的注释把这套哲学说得最直白:
"price": "50 USD", "price_postapoc": "2 USD 50 cent", "//": "$50 bills have substantial pre-Cataclysm value, but are worth 1 meat jerky"同一张 50 美元大钞,灾后只值 1 片肉干——票面金额失效,购买力接管定价。
CDDA 物品价格档位:可得性 × 实用性的定价区间表
给定尺子之后,一个物品具体值多少?设计文档的答案是两个旋钮:可得性(常见/稀有)× 实用性(无用/理论用途/实用)。各档位区间(cent):
| 可得性 | 实用性 | 价格区间 | 直觉理解 |
|---|---|---|---|
| 常见 | 原材料 | ~0–25/kg | 要么白送,要么只能大宗批发 |
| 常见 | 无实用 | 0 | 遍地都是的杂物 = 废品 |
| 常见 | 有理论用途 | ~10 | "好像有点用" |
| 常见 | 实用 | ~250–2000 | 日常真正用得上的东西 |
| 稀有 | 无实用 | ~10–50 | 难得但没用的纪念品 |
| 稀有 | 有理论用途 | ~100–500 | 稀有且"可能派上用场" |
| 稀有 | 有相当大用途 | ~1000–15000 | 稀有硬货,价差最大 |
表里还藏着一条硬性红线:任何物品不得超过 15000 cent。为什么设上限?文档的理由很朴素:游戏里的经济规模是小社区级别的,15000"基本就是任何人愿意为单件物品支付的极限"。没有这条红线,天价物品会让 NPC 交易、任务奖励等系统直接失衡——对模组作者来说,它同时也是一道清晰的自查边界。
食品另有一套三因子模型(卡路里 × 保存性 × 营养度):肉干250、高热量罐装高能食品可达500、低卡易腐的垃圾食品低至50。这个"保存性"因子不是玄学,引擎层面真的有对应实现,下面细说。
price_postapoc 引擎实现:字段定义、回退与动态折价
配置写得再对,最终也是引擎在替你算账。这一节从源码走读四个关键点,看完你就知道物品信息界面显示的价格是怎么来的。
price 与 price_postapoc 字段定义:默认堆叠语义
src/itype.h 里两个字段的注释信息量很大:
/** Value before the Cataclysm. Price given is for a default-sized stack. */ units::money price = 0_cent; /** Value after the Cataclysm, dependent upon practical usages. Price given is for a default-sized stack. */ units::money price_post = -1_cent;两个关键点:价格永远针对"默认堆叠尺寸"给出(后面堆叠换算全靠这一句);price_post的初值-1_cent表示"未指定"。
JSON 侧的解析在 src/item_factory.cpp:
optional( jo, was_loaded, "price", price, not_negative_money, 0_cent ); optional( jo, was_loaded, "price_postapoc", price_post, not_negative_money, -1_cent );也就是说,JSON 里键名是price_postapoc,缺省时记为 -1。
未填 price_postapoc 会发生什么
不是报错,而是悄悄回退到灾变前价格。还是 src/item_factory.cpp:
// use pre-Cataclysm price as default if post-cataclysm price unspecified if( obj.price_post < 0_cent ) { obj.price_post = obj.price; }所以"不写"也是一种设计选择:物品按灾变前价值参与交易。但对大多数模组物品来说,这恰恰是最常见的疏漏——一张忘了改价的 160 USD 棒球棒,在避难所黑市上会被当奢侈品卖(正确做法见下一节实战走查)。
按 charges / stack_size 折算:整箱价与单瓶价
"整箱价与单瓶价"是理解堆叠换算最好的类比:JSON 里写的是整箱价,交易时按你手里还剩几瓶折算。src/item.cpp 的price_no_contents里:
if( count_by_charges() || made_of( phase_id::LIQUID ) ) { // price from json data is for default-sized stack price *= charges / static_cast< double >( type->stack_size ); }一瓶stack_size: 200的药只用了 15 剂量,实际价格就是整箱价的 15/200。
腐烂、损坏与污秽:动态折价
设计文档强调食品要看"保存性",因为引擎真的会按新鲜度动态扣钱,同样是 src/item.cpp:
if( rotten() ) { return 0; // 彻底腐烂:一文不值 } ... if( damage() > 0 ) { // maximal damage level is 5, maximal reduction is 80% of the value. price -= price * static_cast<double>( std::max( 0, damage_level() - 1 ) ) / 5; } ... // Nominal price for perfectly fresh food, decreasing linearly as it gets closer to expiry if( is_food() ) { price *= ( 1.0 - get_relative_rot() ); // 越接近过期越便宜,线性衰减 } if( is_filthy() ) { price = std::max( price - PRICE_FILTHY_MALUS, 0 ); // PRICE_FILTHY_MALUS = 100 cent }三条规则各管一事:
- 腐烂:
get_relative_rot()从 0(新鲜)到 1(烂透)线性扣价,归零前食品的实际交易价值会一路缩水——这就是"易腐食品别填高价"的引擎依据; - 损坏:5 级损坏最多打到 2 折(80% 减值);
- 污秽:固定扣 100 cent 且下限为 0。满地都是的脏衣物直接归零,贵重装备只掉一成——源码注释里解释得很直白:"common clothing ends up with no value (it'severywhere)"。
最后,src/item.cpp 的item::price()会用visit_items递归累加所有内容物(容器里的物品、枪械/工具模组),"装满补给的背包"是逐层加出来的总价;而 src/item_info.cpp 在物品信息界面同时展示两个价格:
const int price_preapoc = price( false ) * batch; const int price_postapoc = price( true ) * batch;practical参数为false走price、为true走price_post。所以游戏里对照看一眼两个数字:如果两者一模一样,多半就是没填price_postapoc触发了回退。
CDDA 模组定价实战:从判断稀缺性到写出 JSON 配置
方法论走完,挑仓库里两件真实物品完整走一遍:先常见武器,后稀缺药品。
实战一:铝制棒球棒(bat_metal)
真实配置在 data/json/items/melee/bludgeons.json:
{ "id": "bat_metal", "name": { "str": "aluminum bat" }, "price": "160 USD", "price_postapoc": "12 USD 50 cent", "melee_damage": { "bash": 22 }, "qualities": [ [ "HAMMER", 1 ] ], "flags": [ "DURABLE_MELEE", "BELT_CLIP" ] }定价走查:
- 可得性:球场、公园、体育用品店随处可搜刮 →常见;
- 实用性:22 点钝击伤害 + 敲砸锤品质,是实打实的武器兼工具 →实用;
- 落档:常见 × 实用 = 250–2000 cent 区间,
12 USD 50 cent(1250 cent)落在区间上沿,对一件耐用的近战武器完全合理; - 注意:灾变前价格是 160 USD,如果这里漏写
price_postapoc,引擎回退后这根球棒会在避难所按 16000 cent 的天价出售——直接击穿 15000 上限。
你可以直接抄走这个模板:
{ "id": "my_mod_item", "type": "TOOL", "name": { "str": "my tool" }, "price": "灾变前价", "price_postapoc": "先按档位表选档,再落数" }实战二:抗生素(antibiotics)
真实配置在 data/json/items/comestibles/med.json:
{ "id": "antibiotics", "type": "ITEM", "subtypes": [ "COMESTIBLE" ], "comestible_type": "MED", "name": { "str_sp": "antibiotics" }, "weight": "611 mg", "volume": "1 ml", "price": "45 cent", "price_postapoc": "2 USD", "use_action": [ "ANTIBIOTIC" ], "flags": [ "NPC_SAFE", "IRREPLACEABLE_CONSUMABLE", "WATER_DISSOLVE", "NO_TEMP" ] }这件物品值得拆开看三层:
- 单价锚定:这是单片药(611 mg、1 ml),
2 USD= 200 cent/剂。而设计文档里那个经典基准——"400 USD 一组 200 剂量的抗生素"——换算下来单价正好也是 200 cent/剂。文档示例与线上真实配置殊途同归,说明 200 cent/剂就是"救命药"的手感基准; - 档位核对:处方药灾变后无法生产,落在"稀有 × 有相当大用途"档下沿,与常见实用物品(250–2000)衔接,不突兀;
- 标志补全:
IRREPLACEABLE_CONSUMABLE已经在列——药品属于"存量只减不增"的不可再生消耗品,这个标志的用途见结尾。
踩坑清单:price_postapoc 常见错误自查
提交你的物品 JSON 之前,过一遍这张清单 ⚠️
- 整组价误当单价:JSON 价格针对"默认堆叠尺寸"。设了
stack_size的物品,先除以堆叠数反算单价,确认它落在合理档位(400 USD 一组 ≠ 400 USD 一剂)。 - 漏写 price_postapoc:引擎会静默回退到灾变前价,物品界面两个价格会一模一样——看到相同数值就是信号。
- 突破 15000 cent 上限:再好的物品也不该超过"150 美元"。
- 该加 IRREPLACEABLE_CONSUMABLE 没加:药品、不可装填的弹药、咖啡茶叶等灾变前消耗品都应带上,它在 data/json/flags.json 中正式注册(
"type": "json_flag")。 - 易腐食品填了天价:引擎会按新鲜度线性折价,放三天的罐头和满新鲜度的不是一个价。
- 便宜物品被污秽打零:100 cent 的固定污秽扣减对低价物品是致命的(50 cent 的脏物 → 0)。
- 食品没按三因子:卡路里 × 保存性 × 营养度——肉干 250、罐装高能 ~500、垃圾食品 ~50,先对标这三档。
结语:一个正在等待接线的涨价钩子
把price_postapoc想成"灾变后世界的秤":250 cent 的肉干锚定单位,可得性与实用性两个旋钮决定落档,引擎再叠上堆叠折算、腐烂衰减与污秽扣减,最终得出交易价。照着档位表选数、用清单自查,你的模组物品就能无缝嵌入这套经济。
还有一个值得留意的伏笔:设计文档末尾明确写着,未来会实现一个让IRREPLACEABLE_CONSUMABLE物品随时间自动涨价的机制——存量的抗生素与弹药会越来越贵。今天给不可再生消耗品打上这个标志,就是提前为那条尚未接线的通胀曲线占好位。
【免费下载链接】Cataclysm-DDACataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.项目地址: https://gitcode.com/GitHub_Trending/ca/Cataclysm-DDA
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考