Files
TinyWaste/packages/content/src/index.ts
T
virtheart 5c41eb410b feat(HUD): 添加HUD界面资产与组件
- 新增HUD图标、面板和状态指示器资产
- 实现HUD图标组件和错误边界组件
- 重构顶部状态栏和底部导航栏
- 更新路线面板样式和交互
- 添加HUD资产清单和切片脚本
- 移除未使用的资产文件
- 调整API安全配置和生产环境设置
2026-04-29 01:24:37 +08:00

1245 lines
40 KiB
TypeScript

import type { GameContent } from '@tinywaste/game-core';
export const gameContent: GameContent = {
version: '0.1.0',
inventoryCapacity: 36,
storageCapacity: 84,
items: {
water_dirty: {
id: 'water_dirty',
name: '浑水',
desc: '简单过滤前的桶装浑水。能解渴,但会让身体吃点苦头。',
type: 'water',
stackLimit: 8,
volume: 1,
baseValue: 4,
effects: [
{ type: 'change-stat', stat: 'thirst', amount: 18 },
{ type: 'change-stat', stat: 'radiation', amount: 4 },
],
},
water_purified: {
id: 'water_purified',
name: '净水',
desc: '烧开并过滤后的安全饮用水。',
type: 'water',
stackLimit: 8,
volume: 1,
baseValue: 9,
effects: [
{ type: 'change-stat', stat: 'thirst', amount: 28 },
{ type: 'change-stat', stat: 'radiation', amount: -2 },
],
},
canned_beans: {
id: 'canned_beans',
name: '罐装豆子',
desc: '味道一般,但稳定可靠。',
type: 'food',
stackLimit: 6,
volume: 1,
baseValue: 10,
effects: [
{ type: 'change-stat', stat: 'hunger', amount: 22 },
{ type: 'change-stat', stat: 'energy', amount: 4 },
],
},
jerky: {
id: 'jerky',
name: '风干肉条',
desc: '便携,耐放,口感像旧皮带。',
type: 'food',
stackLimit: 8,
volume: 1,
baseValue: 7,
effects: [{ type: 'change-stat', stat: 'hunger', amount: 14 }],
},
herbal_tea: {
id: 'herbal_tea',
name: '草根热茶',
desc: '温热、苦涩,但能让心跳慢下来。',
type: 'water',
stackLimit: 6,
volume: 1,
baseValue: 12,
effects: [
{ type: 'change-stat', stat: 'thirst', amount: 10 },
{ type: 'change-stat', stat: 'sanity', amount: 8 },
],
},
field_bandage: {
id: 'field_bandage',
name: '野战绷带',
desc: '沾了草药的简易绷带,止血比止痛更靠谱。',
type: 'medicine',
stackLimit: 5,
volume: 1,
baseValue: 15,
effects: [
{ type: 'change-stat', stat: 'life', amount: 18 },
{ type: 'change-stat', stat: 'sanity', amount: 2 },
],
},
rad_pills: {
id: 'rad_pills',
name: '抗辐片',
desc: '味道像粉笔,但能压住身体里的灼烧感。',
type: 'medicine',
stackLimit: 4,
volume: 1,
baseValue: 20,
effects: [
{ type: 'change-stat', stat: 'radiation', amount: -18 },
{ type: 'change-stat', stat: 'sanity', amount: -4 },
],
},
mushroom_stew: {
id: 'mushroom_stew',
name: '蘑菇炖罐',
desc: '热量不高,但足够让人重新像个人。',
type: 'food',
stackLimit: 4,
volume: 2,
baseValue: 18,
effects: [
{ type: 'change-stat', stat: 'hunger', amount: 18 },
{ type: 'change-stat', stat: 'sanity', amount: 6 },
],
},
scrap_metal: {
id: 'scrap_metal',
name: '废金属',
desc: '废墟社会的硬通货之一。',
type: 'material',
stackLimit: 12,
volume: 1,
baseValue: 3,
},
wood_plank: {
id: 'wood_plank',
name: '旧木板',
desc: '潮湿、开裂,但还能用。',
type: 'material',
stackLimit: 10,
volume: 1,
baseValue: 2,
},
cloth_rag: {
id: 'cloth_rag',
name: '破布',
desc: '包扎、擦拭、打火都能凑合。',
type: 'material',
stackLimit: 12,
volume: 1,
baseValue: 2,
},
herb_bundle: {
id: 'herb_bundle',
name: '草药束',
desc: '来自雨后的田边和破墙根。',
type: 'material',
stackLimit: 10,
volume: 1,
baseValue: 5,
},
mushroom_cluster: {
id: 'mushroom_cluster',
name: '菌簇',
desc: '颜色看着危险,但煮透了还能吃。',
type: 'material',
stackLimit: 8,
volume: 1,
baseValue: 4,
},
filter_charcoal: {
id: 'filter_charcoal',
name: '过滤炭芯',
desc: '净水和自制滤芯的核心。',
type: 'material',
stackLimit: 8,
volume: 1,
baseValue: 6,
},
parts_wire: {
id: 'parts_wire',
name: '导线零件',
desc: '断头的电线、卡扣和焊片,能救急。',
type: 'material',
stackLimit: 10,
volume: 1,
baseValue: 6,
},
ammo_rifle: {
id: 'ammo_rifle',
name: '步枪弹',
desc: '数量永远嫌少。',
type: 'ammo',
stackLimit: 20,
volume: 1,
baseValue: 5,
},
shiv: {
id: 'shiv',
name: '磨尖铁片',
desc: '贴身时很有说服力。',
type: 'weapon',
stackLimit: 1,
volume: 2,
baseValue: 16,
equipSlot: 'weapon',
combat: {
damageMin: 7,
damageMax: 11,
range: 1,
hitBonus: 0.04,
critChance: 0.08,
critMult: 1.6,
},
},
crowbar: {
id: 'crowbar',
name: '撬棍',
desc: '开门、撬箱、打人都很好使。',
type: 'tool',
stackLimit: 1,
volume: 3,
baseValue: 22,
equipSlot: 'tool',
combat: {
damageMin: 9,
damageMax: 14,
range: 1,
hitBonus: 0.02,
critChance: 0.06,
critMult: 1.5,
},
},
pipe_rifle: {
id: 'pipe_rifle',
name: '管式步枪',
desc: '看着像会炸膛,但比徒手讲道理要强。',
type: 'weapon',
stackLimit: 1,
volume: 4,
baseValue: 36,
equipSlot: 'weapon',
combat: {
damageMin: 15,
damageMax: 23,
range: 4,
hitBonus: 0.12,
critChance: 0.1,
critMult: 1.8,
},
},
leather_coat: {
id: 'leather_coat',
name: '旧皮衣',
desc: '不轻,但能扛风也能扛爪子。',
type: 'armor',
stackLimit: 1,
volume: 3,
baseValue: 26,
equipSlot: 'body',
combat: {
damageMin: 0,
damageMax: 0,
range: 0,
hitBonus: 0,
armor: 2,
dodgeBonus: 0.02,
radiationResist: 1,
},
},
field_filter: {
id: 'field_filter',
name: '野外滤芯',
desc: '套在呼吸面罩和水瓶上的双用滤芯。',
type: 'quest',
stackLimit: 1,
volume: 2,
baseValue: 30,
},
metro_keycard: {
id: 'metro_keycard',
name: '地铁门禁卡',
desc: '塑料边缘已经卷起,但芯片还活着。',
type: 'quest',
stackLimit: 1,
volume: 1,
baseValue: 0,
},
},
buffs: {
warm_rest: {
id: 'warm_rest',
name: '稍微缓过来了',
desc: '这点休息让身体没那么紧绷。',
durationMin: 180,
modifiers: { sanity: 0.01 },
},
},
recipes: {
purify_water: {
id: 'purify_water',
name: '净化浑水',
desc: '把能喝和不能喝的差别,再往前推一步。',
workbenchType: 'craft',
inputs: [
{ itemId: 'water_dirty', count: 1 },
{ itemId: 'filter_charcoal', count: 1 },
],
outputs: [{ itemId: 'water_purified', count: 1 }],
timeCostMin: 18,
energyCost: 3,
},
craft_bandage: {
id: 'craft_bandage',
name: '缠一卷绷带',
desc: '草药和破布混一混,也比流血强。',
workbenchType: 'craft',
inputs: [
{ itemId: 'cloth_rag', count: 2 },
{ itemId: 'herb_bundle', count: 1 },
],
outputs: [{ itemId: 'field_bandage', count: 1 }],
timeCostMin: 16,
energyCost: 4,
},
craft_shiv: {
id: 'craft_shiv',
name: '再磨一把铁片',
desc: '野外最便宜的威慑力。',
workbenchType: 'craft',
inputs: [
{ itemId: 'scrap_metal', count: 2 },
{ itemId: 'cloth_rag', count: 1 },
],
outputs: [{ itemId: 'shiv', count: 1 }],
timeCostMin: 22,
energyCost: 5,
},
brew_tea: {
id: 'brew_tea',
name: '煮一壶草根茶',
desc: '喝下去之前像药,喝下去之后也像药。',
workbenchType: 'craft',
inputs: [
{ itemId: 'water_purified', count: 1 },
{ itemId: 'herb_bundle', count: 1 },
],
outputs: [{ itemId: 'herbal_tea', count: 1 }],
timeCostMin: 14,
energyCost: 2,
},
cook_stew: {
id: 'cook_stew',
name: '炖一锅菌菇罐头',
desc: '废土里的高级菜。',
workbenchType: 'craft',
inputs: [
{ itemId: 'mushroom_cluster', count: 1 },
{ itemId: 'canned_beans', count: 1 },
],
outputs: [{ itemId: 'mushroom_stew', count: 1 }],
timeCostMin: 28,
energyCost: 5,
},
assemble_filter: {
id: 'assemble_filter',
name: '组装野外滤芯',
desc: '没有它,往深处走就是拿器官打赌。',
workbenchType: 'craft',
requirements: [{ kind: 'quest-state', questId: 'q_signal_hunt', state: 'completed' }],
inputs: [
{ itemId: 'filter_charcoal', count: 2 },
{ itemId: 'parts_wire', count: 1 },
{ itemId: 'cloth_rag', count: 1 },
],
outputs: [{ itemId: 'field_filter', count: 1 }],
timeCostMin: 30,
energyCost: 6,
},
repair_rifle: {
id: 'repair_rifle',
name: '装一把管式步枪',
desc: '有点像工程,有点像祈祷。',
workbenchType: 'craft',
requirements: [{ kind: 'flag', flag: 'met_trader', value: true }],
inputs: [
{ itemId: 'scrap_metal', count: 4 },
{ itemId: 'parts_wire', count: 2 },
{ itemId: 'wood_plank', count: 1 },
],
outputs: [{ itemId: 'pipe_rifle', count: 1 }],
timeCostMin: 44,
energyCost: 8,
},
},
places: {
home: {
id: 'home',
name: '临时避难点',
desc: '一间被塑料布和铁皮拼起来的临时屋。这里不安全,但至少属于你。',
tags: ['home', 'safe'],
dangerLevel: 1,
services: ['craft', 'rest'],
actions: [
{
id: 'home_rain_barrel',
name: '检查雨水桶',
kind: 'resource',
desc: '夜里结的露和前天的雨还剩一点。',
timeCostMin: 18,
energyCost: 2,
risk: 0.05,
rewardHint: '稳定获取水',
stock: { initial: 2, max: 4, refreshMin: 240, amountPerRefresh: 1 },
lootTable: [{ itemId: 'water_dirty', min: 1, max: 2, chance: 1 }],
onEmptyText: '桶里只有一层灰。',
},
{
id: 'home_salvage_corner',
name: '翻整理堆角',
kind: 'scavenge',
desc: '破屋的角落总会冒出一点还没用上的东西。',
timeCostMin: 22,
energyCost: 4,
risk: 0.08,
rewardHint: '少量基础材料',
stock: { initial: 2, max: 3, refreshMin: 360, amountPerRefresh: 1 },
lootTable: [
{ itemId: 'cloth_rag', min: 1, max: 2, chance: 0.8 },
{ itemId: 'scrap_metal', min: 1, max: 2, chance: 0.7 },
{ itemId: 'wood_plank', min: 1, max: 1, chance: 0.5 },
],
onEmptyText: '这个角落已经被翻干净了。',
},
{
id: 'home_listen_radio',
name: '调一下旧收音机',
kind: 'investigate',
desc: '噪音里时不时会蹦出半截有用的话。',
timeCostMin: 14,
energyCost: 1,
risk: 0.1,
rewardHint: '可能得到线索',
eventPool: ['home_radio_note'],
},
],
},
roadside: {
id: 'roadside',
name: '近郊土路',
desc: '从避难点延伸出去的一段土路,车辙里总积着灰和碎玻璃。',
tags: ['road'],
dangerLevel: 2,
services: [],
actions: [
{
id: 'roadside_forage',
name: '路边翻草丛',
kind: 'resource',
desc: '有时能翻到蘑菇,有时能翻到麻烦。',
timeCostMin: 20,
energyCost: 4,
risk: 0.18,
rewardHint: '草药与菌类',
stock: { initial: 2, max: 3, refreshMin: 300, amountPerRefresh: 1 },
lootTable: [
{ itemId: 'herb_bundle', min: 1, max: 2, chance: 0.75 },
{ itemId: 'mushroom_cluster', min: 1, max: 1, chance: 0.55 },
],
},
{
id: 'roadside_car',
name: '搜废车后备箱',
kind: 'scavenge',
desc: '锁已经坏了,剩下的问题是谁先把它搜空。',
timeCostMin: 28,
energyCost: 5,
risk: 0.22,
rewardHint: '零件、金属、偶发补给',
stock: { initial: 2, max: 3, refreshMin: 360, amountPerRefresh: 1 },
lootTable: [
{ itemId: 'parts_wire', min: 1, max: 1, chance: 0.55 },
{ itemId: 'scrap_metal', min: 1, max: 2, chance: 0.85 },
{ itemId: 'water_dirty', min: 1, max: 1, chance: 0.35 },
],
eventPool: ['road_bandit_glimpse'],
},
],
},
old_store: {
id: 'old_store',
name: '废弃便利店',
desc: '玻璃门早就没了,里面剩下的是空包装、鼠窝和一点没被发现的东西。',
tags: ['ruins'],
dangerLevel: 4,
services: [],
actions: [
{
id: 'store_shelves',
name: '翻货架',
kind: 'scavenge',
desc: '越靠里,越有可能翻到别人没拿走的东西。',
timeCostMin: 32,
energyCost: 6,
risk: 0.32,
rewardHint: '食物与材料',
stock: { initial: 3, max: 4, refreshMin: 420, amountPerRefresh: 1 },
lootTable: [
{ itemId: 'canned_beans', min: 1, max: 1, chance: 0.45 },
{ itemId: 'scrap_metal', min: 1, max: 2, chance: 0.8 },
{ itemId: 'filter_charcoal', min: 1, max: 1, chance: 0.35 },
],
eventPool: ['store_rats', 'store_basement_cache'],
},
{
id: 'store_pharmacy',
name: '撬药柜',
kind: 'investigate',
desc: '药柜门板卡着,幸运的话还会有剩药。',
timeCostMin: 24,
energyCost: 5,
risk: 0.26,
rewardHint: '药物与线索',
stock: { initial: 1, max: 1, refreshMin: 9999, amountPerRefresh: 0 },
lootTable: [
{ itemId: 'field_bandage', min: 1, max: 1, chance: 0.65 },
{ itemId: 'rad_pills', min: 1, max: 1, chance: 0.4 },
],
eventPool: ['store_clinic_note'],
},
],
},
village_market: {
id: 'village_market',
name: '村庄集市',
desc: '用铁皮棚和布幔围起来的集市,所有人都在盯着所有人。',
tags: ['settlement', 'safe'],
dangerLevel: 2,
services: ['trade', 'rest', 'info'],
actions: [
{
id: 'market_rumors',
name: '打听风声',
kind: 'investigate',
desc: '消息要么值钱,要么要命。',
timeCostMin: 18,
energyCost: 2,
risk: 0.08,
rewardHint: '任务线索',
eventPool: ['market_broker'],
},
{
id: 'market_herbs',
name: '逛草药摊',
kind: 'resource',
desc: '有人把烂根和能治命的东西摆在了一起。',
timeCostMin: 14,
energyCost: 1,
risk: 0.04,
rewardHint: '草药和茶材',
stock: { initial: 1, max: 2, refreshMin: 360, amountPerRefresh: 1 },
lootTable: [
{ itemId: 'herb_bundle', min: 1, max: 2, chance: 1 },
{ itemId: 'filter_charcoal', min: 1, max: 1, chance: 0.4 },
],
},
],
tradeOffers: [
{
id: 'offer_clean_water',
name: '用废金属换净水',
desc: '三个废金属换一瓶净水。',
costs: [{ itemId: 'scrap_metal', count: 3 }],
gives: [{ itemId: 'water_purified', count: 1 }],
},
{
id: 'offer_bandage',
name: '用草药换绷带',
desc: '草药和破布能换别人做好的绷带。',
costs: [
{ itemId: 'herb_bundle', count: 1 },
{ itemId: 'cloth_rag', count: 1 },
],
gives: [{ itemId: 'field_bandage', count: 1 }],
},
{
id: 'offer_ammo',
name: '换一点子弹',
desc: '凑零件的人永远知道弹药的价。',
costs: [
{ itemId: 'scrap_metal', count: 4 },
{ itemId: 'parts_wire', count: 1 },
],
gives: [{ itemId: 'ammo_rifle', count: 4 }],
},
],
},
rain_farm: {
id: 'rain_farm',
name: '雨棚农地',
desc: '一片被破塑料顶棚勉强护住的试验田,泥里长着蘑菇和希望。',
tags: ['resource'],
dangerLevel: 3,
services: [],
actions: [
{
id: 'farm_mushrooms',
name: '采菌',
kind: 'resource',
desc: '棚下潮得发冷,菌类倒是长得很好。',
timeCostMin: 24,
energyCost: 4,
risk: 0.18,
rewardHint: '菌类与草药',
stock: { initial: 3, max: 4, refreshMin: 300, amountPerRefresh: 1 },
lootTable: [
{ itemId: 'mushroom_cluster', min: 1, max: 2, chance: 1 },
{ itemId: 'herb_bundle', min: 1, max: 1, chance: 0.6 },
],
},
{
id: 'farm_pump',
name: '抽一桶井水',
kind: 'resource',
desc: '水有铁锈味,但至少是水。',
timeCostMin: 20,
energyCost: 3,
risk: 0.12,
rewardHint: '稳定水源',
stock: { initial: 2, max: 3, refreshMin: 240, amountPerRefresh: 1 },
lootTable: [{ itemId: 'water_dirty', min: 1, max: 2, chance: 1 }],
eventPool: ['farm_old_diary'],
},
],
},
city_edge: {
id: 'city_edge',
name: '城市边缘',
desc: '从这里开始,楼和阴影都不再给人安全感。',
tags: ['ruins'],
dangerLevel: 5,
services: [],
modifiers: { sanity: 0.005 },
actions: [
{
id: 'city_checkpoint',
name: '搜检查站',
kind: 'scavenge',
desc: '旧路障下埋着箱子和更旧的记录。',
timeCostMin: 34,
energyCost: 6,
risk: 0.34,
rewardHint: '零件、弹药、主线线索',
stock: { initial: 2, max: 3, refreshMin: 480, amountPerRefresh: 1 },
lootTable: [
{ itemId: 'parts_wire', min: 1, max: 2, chance: 0.8 },
{ itemId: 'ammo_rifle', min: 2, max: 4, chance: 0.45 },
{ itemId: 'wood_plank', min: 1, max: 1, chance: 0.5 },
],
eventPool: ['city_signal'],
},
{
id: 'city_rooftops',
name: '观察高楼天线',
kind: 'investigate',
desc: '远处有规律的闪点,不像废墟会自己发出来的。',
timeCostMin: 26,
energyCost: 4,
risk: 0.24,
rewardHint: '得到通往地铁的情报',
eventPool: ['city_rooftop_flash'],
},
],
},
subway_entrance: {
id: 'subway_entrance',
name: '老地铁口',
desc: '闸机早已没电,黑洞洞的入口像喉咙。',
tags: ['tunnel'],
dangerLevel: 6,
services: [],
modifiers: { sanity: 0.01, radiation: 0.004 },
actions: [
{
id: 'subway_lockers',
name: '撬储物柜',
kind: 'scavenge',
desc: '还没被撬开的柜子,不是幸运就是圈套。',
timeCostMin: 32,
energyCost: 6,
risk: 0.38,
rewardHint: '装备与零件',
stock: { initial: 2, max: 2, refreshMin: 9999, amountPerRefresh: 0 },
lootTable: [
{ itemId: 'filter_charcoal', min: 1, max: 1, chance: 0.6 },
{ itemId: 'parts_wire', min: 1, max: 2, chance: 0.65 },
{ itemId: 'leather_coat', min: 1, max: 1, chance: 0.2 },
],
eventPool: ['subway_power'],
},
{
id: 'subway_concourse',
name: '摸进候车大厅',
kind: 'investigate',
desc: '有旧广播在循环,像是在等谁回应。',
timeCostMin: 28,
energyCost: 5,
risk: 0.3,
rewardHint: '推进主线',
eventPool: ['subway_echo'],
},
],
},
sewer: {
id: 'sewer',
name: '污染下水道',
desc: '潮湿、温热、充满不该活动的东西。',
tags: ['radiated', 'tunnel'],
dangerLevel: 7,
services: [],
modifiers: { radiation: 0.012, sanity: 0.014 },
actions: [
{
id: 'sewer_tunnel',
name: '深入排水隧道',
kind: 'scavenge',
desc: '越往里越像在别人胃里找路。',
timeCostMin: 36,
energyCost: 7,
risk: 0.42,
rewardHint: '高风险高收益',
stock: { initial: 2, max: 3, refreshMin: 600, amountPerRefresh: 1 },
lootTable: [
{ itemId: 'scrap_metal', min: 2, max: 3, chance: 0.8 },
{ itemId: 'parts_wire', min: 1, max: 1, chance: 0.55 },
{ itemId: 'mushroom_cluster', min: 1, max: 1, chance: 0.4 },
],
eventPool: ['sewer_stalker'],
},
{
id: 'sewer_office',
name: '搜维护办公室',
kind: 'investigate',
desc: '门牌还在,里面的秩序早就没了。',
timeCostMin: 30,
energyCost: 5,
risk: 0.32,
rewardHint: '关键任务物品',
stock: { initial: 1, max: 1, refreshMin: 9999, amountPerRefresh: 0 },
eventPool: ['sewer_keycard'],
},
],
},
vault_gate: {
id: 'vault_gate',
name: '避难所入口',
desc: '混凝土门板像一整面沉默的墙,门缝里却有电流声。',
tags: ['vault'],
dangerLevel: 8,
services: [],
actions: [
{
id: 'vault_console',
name: '接入门禁终端',
kind: 'investigate',
desc: '键盘坏了一半,但屏幕还亮着。',
timeCostMin: 24,
energyCost: 3,
risk: 0.18,
rewardHint: '终局推进',
eventPool: ['vault_console_event'],
},
],
},
},
edges: [
{ from: 'home', to: 'roadside', travelTimeMin: 24, risk: 1.1 },
{ from: 'home', to: 'rain_farm', travelTimeMin: 34, risk: 1.3 },
{ from: 'roadside', to: 'home', travelTimeMin: 24, risk: 1.0 },
{ from: 'roadside', to: 'old_store', travelTimeMin: 20, risk: 1.4 },
{ from: 'roadside', to: 'village_market', travelTimeMin: 28, risk: 1.2 },
{ from: 'rain_farm', to: 'home', travelTimeMin: 34, risk: 1.2 },
{ from: 'rain_farm', to: 'village_market', travelTimeMin: 26, risk: 1.3 },
{ from: 'old_store', to: 'roadside', travelTimeMin: 20, risk: 1.4 },
{ from: 'village_market', to: 'roadside', travelTimeMin: 28, risk: 1.2 },
{ from: 'village_market', to: 'rain_farm', travelTimeMin: 26, risk: 1.3 },
{
from: 'village_market',
to: 'city_edge',
travelTimeMin: 32,
risk: 1.8,
conditions: [{ kind: 'flag', flag: 'met_trader', value: true }],
},
{ from: 'city_edge', to: 'village_market', travelTimeMin: 32, risk: 1.7 },
{
from: 'city_edge',
to: 'subway_entrance',
travelTimeMin: 30,
risk: 2.2,
conditions: [{ kind: 'flag', flag: 'got_subway_code', value: true }],
},
{ from: 'subway_entrance', to: 'city_edge', travelTimeMin: 30, risk: 2.0 },
{
from: 'subway_entrance',
to: 'sewer',
travelTimeMin: 26,
risk: 2.5,
conditions: [{ kind: 'flag', flag: 'power_rerouted', value: true }],
},
{ from: 'sewer', to: 'subway_entrance', travelTimeMin: 26, risk: 2.4 },
{
from: 'sewer',
to: 'vault_gate',
travelTimeMin: 34,
risk: 2.8,
conditions: [{ kind: 'has-item', itemId: 'field_filter', count: 1 }],
},
{ from: 'vault_gate', to: 'sewer', travelTimeMin: 34, risk: 2.8 },
],
events: {
home_radio_note: {
id: 'home_radio_note',
title: '电波里的碎句',
text: '旧收音机里混着白噪声和一句重复播报的短句:“……有交易,有水,有人知道旧线……”',
trigger: 'action',
options: [
{
id: 'radio_focus',
text: '把频率记下来',
successText: '你把“旧线”和“集市”记在了心里。',
successEffects: [
{ type: 'log', message: '你决定去村庄集市碰碰运气。', tone: 'good' },
],
},
],
},
road_bandit_glimpse: {
id: 'road_bandit_glimpse',
title: '有人在看你',
text: '你在废车玻璃里看到一道影子迅速缩回墙后。',
trigger: 'action',
options: [
{
id: 'bandit_ignore',
text: '装作没看到,快走',
successEffects: [{ type: 'change-stat', stat: 'sanity', amount: -2 }],
successText: '你没回头,但后颈一直发紧。',
},
{
id: 'bandit_search',
text: '过去查看',
check: { attribute: 'per', difficulty: 58 },
successEffects: [
{ type: 'add-item', itemId: 'scrap_metal', count: 2 },
{ type: 'add-item', itemId: 'parts_wire', count: 1 },
],
failureEffects: [{ type: 'change-stat', stat: 'life', amount: -6 }],
successText: '人已经跑了,只留下半袋零件。',
failureText: '你刚探出头,一块飞来的碎砖擦破了手臂。',
},
],
},
store_rats: {
id: 'store_rats',
title: '货架下的尖叫',
text: '翻动纸箱时,一群肥大的变异鼠突然从货架阴影里扑了出来。',
trigger: 'action',
options: [
{
id: 'store_rats_fight',
text: '抄家伙迎上去',
successEffects: [{ type: 'start-combat', enemyId: 'rat_swarm' }],
},
{
id: 'store_rats_backoff',
text: '放弃这片货架',
timeCostMin: 6,
successEffects: [{ type: 'change-stat', stat: 'sanity', amount: -3 }],
successText: '你退了出来,鼠群在身后继续尖叫。',
},
],
},
store_basement_cache: {
id: 'store_basement_cache',
title: '地下储藏门',
text: '货架尽头有道半掩的地下门,门后传来一股潮湿冷气。',
trigger: 'action',
options: [
{
id: 'basement_pry',
text: '用撬棍撬开',
check: { attribute: 'str', difficulty: 56 },
successEffects: [
{ type: 'add-item', itemId: 'filter_charcoal', count: 1 },
{ type: 'add-item', itemId: 'water_dirty', count: 1 },
],
successText: '你在阴冷的地下格里摸到了炭芯和一瓶没漏完的水。',
failureEffects: [{ type: 'change-stat', stat: 'life', amount: -7 }],
failureText: '门板反弹回来,狠狠砸在你的前臂上。',
},
{
id: 'basement_leave',
text: '先记住位置',
successEffects: [{ type: 'change-stat', stat: 'sanity', amount: 2 }],
},
],
},
store_clinic_note: {
id: 'store_clinic_note',
title: '药柜里的便签',
text: '药柜里夹着一张潮掉的便签:“如果还能读到这张纸,去集市找老罗,他知道哪条地铁线还通电。”',
trigger: 'action',
options: [
{
id: 'clinic_note_keep',
text: '把便签收起来',
successEffects: [{ type: 'set-flag', flag: 'clinic_note_found', value: true }],
},
],
},
market_broker: {
id: 'market_broker',
title: '老罗',
text: '一个披着旧军大衣的老人用指节敲了敲桌面:“想往城里 deeper 走?拿出点诚意。”',
trigger: 'arrive',
options: [
{
id: 'broker_trade_info',
text: '递上一瓶净水换消息',
conditions: [{ kind: 'has-item', itemId: 'water_purified', count: 1 }],
successEffects: [
{ type: 'remove-item', itemId: 'water_purified', count: 1 },
{ type: 'set-flag', flag: 'met_trader', value: true },
{ type: 'unlock-recipe', recipeId: 'repair_rifle' },
{ type: 'unlock-recipe', recipeId: 'brew_tea' },
],
successText: '老罗收下水,告诉你城边检查站还能收到旧地铁维护信号。',
},
{
id: 'broker_smalltalk',
text: '先听,不交易',
successEffects: [{ type: 'set-flag', flag: 'met_trader', value: true }],
successText: '你没换到全部消息,但至少混了个脸熟。',
},
],
},
farm_old_diary: {
id: 'farm_old_diary',
title: '农棚日志',
text: '抽水机旁边夹着一本湿掉的日志,上面反复写着:“雨季之后,地下味道变了。”',
trigger: 'action',
options: [
{
id: 'farm_diary_keep',
text: '记下这句',
successEffects: [{ type: 'change-stat', stat: 'sanity', amount: 2 }],
},
],
},
city_signal: {
id: 'city_signal',
title: '检查站残讯',
text: '在检查站的桌板底下,你找到一块还能亮的终端屏。上面显示:“转入旧维护口,代号 4A。”',
trigger: 'action',
options: [
{
id: 'city_signal_record',
text: '记录地铁口代号',
successEffects: [
{ type: 'set-flag', flag: 'got_subway_code', value: true },
{ type: 'add-item', itemId: 'parts_wire', count: 1 },
],
successText: '你记下了通往老地铁口的维护代号。',
},
],
},
city_rooftop_flash: {
id: 'city_rooftop_flash',
title: '屋顶闪点',
text: '高楼天线之间,一道不自然的蓝白闪光规律地亮了一下。',
trigger: 'action',
options: [
{
id: 'rooftop_track',
text: '沿着闪光方向观察',
check: { attribute: 'per', difficulty: 60 },
successEffects: [{ type: 'set-flag', flag: 'got_subway_code', value: true }],
successText: '你确认闪点来自旧地铁维护站方向。',
failureEffects: [{ type: 'change-stat', stat: 'sanity', amount: -3 }],
failureText: '你盯得太久,反而开始怀疑自己是不是看错了。',
},
],
},
subway_power: {
id: 'subway_power',
title: '断续供电箱',
text: '储物柜后方藏着一套维护供电箱,灯带忽明忽暗。',
trigger: 'action',
options: [
{
id: 'subway_reroute_power',
text: '重新跳线',
check: { attribute: 'int', difficulty: 64 },
timeCostMin: 20,
successEffects: [
{ type: 'set-flag', flag: 'power_rerouted', value: true },
{ type: 'add-item', itemId: 'parts_wire', count: 1 },
],
successText: '几秒后,深处的绿灯终于亮了起来。',
failureEffects: [{ type: 'change-stat', stat: 'life', amount: -5 }],
failureText: '一阵爆火花蹿过来,烫得你手背发麻。',
},
],
},
subway_echo: {
id: 'subway_echo',
title: '深处回音',
text: '大厅深处的回音像有人在一层层敲门。你意识到再往下,需要呼吸过滤。',
trigger: 'action',
options: [
{
id: 'subway_echo_note',
text: '把这点记进脑子里',
successEffects: [{ type: 'change-stat', stat: 'sanity', amount: 2 }],
},
],
},
sewer_stalker: {
id: 'sewer_stalker',
title: '水声不对',
text: '隧道里的水声忽然变成了有节奏的拖拽声,有东西在接近。',
trigger: 'action',
options: [
{
id: 'sewer_stalker_fight',
text: '准备迎击',
successEffects: [{ type: 'start-combat', enemyId: 'glow_stalker' }],
},
{
id: 'sewer_stalker_hide',
text: '缩进管道死角',
check: { attribute: 'agi', difficulty: 58 },
successEffects: [{ type: 'change-stat', stat: 'sanity', amount: 1 }],
failureEffects: [{ type: 'change-stat', stat: 'life', amount: -8 }],
successText: '那团影子滑了过去,留下刺鼻的潮气。',
failureText: '你刚蹲下就被爪子扫中了肩膀。',
},
],
},
sewer_keycard: {
id: 'sewer_keycard',
title: '维护办公室抽屉',
text: '最底层抽屉卡得很死,里面露出一截发黄塑料边。',
trigger: 'action',
options: [
{
id: 'sewer_take_card',
text: '用力拽出来',
successEffects: [
{ type: 'add-item', itemId: 'metro_keycard', count: 1 },
{ type: 'set-flag', flag: 'got_keycard', value: true },
],
successText: '你拿到了地铁门禁卡,背面印着避难所后勤编号。',
},
],
},
vault_console_event: {
id: 'vault_console_event',
title: '门禁终端',
text: '屏幕上跳出一行老旧提示:“输入权限或插入后勤卡。过滤状态需达标。”',
trigger: 'action',
options: [
{
id: 'vault_insert_card',
text: '插入门禁卡,尝试启动',
conditions: [
{ kind: 'has-item', itemId: 'metro_keycard', count: 1 },
{ kind: 'has-item', itemId: 'field_filter', count: 1 },
],
successEffects: [{ type: 'set-flag', flag: 'vault_opened', value: true }],
successText: '门板深处传来沉重的机械回声,锁止结构开始一层层回退。',
},
{
id: 'vault_step_back',
text: '先退一步,确认准备',
successEffects: [{ type: 'change-stat', stat: 'sanity', amount: 2 }],
},
],
},
road_wanderer: {
id: 'road_wanderer',
title: '路边的求助声',
text: '一辆翻覆的车旁边,有人虚弱地问你有没有水。',
trigger: 'travel',
options: [
{
id: 'wanderer_share',
text: '给他一瓶浑水',
conditions: [{ kind: 'has-item', itemId: 'water_dirty', count: 1 }],
successEffects: [
{ type: 'remove-item', itemId: 'water_dirty', count: 1 },
{ type: 'add-item', itemId: 'herb_bundle', count: 1 },
],
successText: '那人把最后一束干草药塞给了你。',
},
{
id: 'wanderer_leave',
text: '继续赶路',
successEffects: [{ type: 'change-stat', stat: 'sanity', amount: -2 }],
successText: '你没有回头,但那声"算了"跟了你一路。',
},
],
},
},
enemies: {
rat_swarm: {
id: 'rat_swarm',
name: '变异鼠群',
desc: '不大,但数量和牙都很多。',
life: 24,
damageMin: 4,
damageMax: 8,
armor: 0,
range: 1,
hitRate: 0.52,
escapePressure: 0.12,
lootTable: [
{ itemId: 'cloth_rag', min: 1, max: 1, chance: 0.45 },
{ itemId: 'mushroom_cluster', min: 1, max: 1, chance: 0.3 },
],
},
scavenger: {
id: 'scavenger',
name: '落单拾荒者',
desc: '又瘦又急,眼神比刀子先到。',
life: 34,
damageMin: 6,
damageMax: 10,
armor: 1,
range: 2,
hitRate: 0.58,
escapePressure: 0.18,
lootTable: [
{ itemId: 'scrap_metal', min: 1, max: 2, chance: 0.9 },
{ itemId: 'water_dirty', min: 1, max: 1, chance: 0.35 },
],
},
feral_dog: {
id: 'feral_dog',
name: '疯狗',
desc: '骨架外露,动作快得像要散架。',
life: 28,
damageMin: 5,
damageMax: 11,
armor: 0,
range: 1,
hitRate: 0.6,
escapePressure: 0.2,
lootTable: [{ itemId: 'jerky', min: 1, max: 1, chance: 0.3 }],
},
tunnel_raider: {
id: 'tunnel_raider',
name: '地铁劫徒',
desc: '知道该在什么时候要命,也知道该在什么时候要弹药。',
life: 42,
damageMin: 8,
damageMax: 13,
armor: 2,
range: 3,
hitRate: 0.64,
escapePressure: 0.25,
lootTable: [
{ itemId: 'ammo_rifle', min: 2, max: 4, chance: 0.55 },
{ itemId: 'parts_wire', min: 1, max: 1, chance: 0.5 },
],
},
glow_stalker: {
id: 'glow_stalker',
name: '荧光潜伏者',
desc: '像被辐射烫过又被下水道养大的东西。',
life: 48,
damageMin: 9,
damageMax: 15,
armor: 1,
range: 1,
hitRate: 0.66,
escapePressure: 0.28,
lootTable: [
{ itemId: 'scrap_metal', min: 2, max: 3, chance: 0.8 },
{ itemId: 'filter_charcoal', min: 1, max: 1, chance: 0.45 },
],
},
},
quests: {
q_tutorial_water: {
id: 'q_tutorial_water',
title: '先把水烧开',
desc: '你需要先证明自己能活过今天。',
type: 'tutorial',
autoStart: [],
steps: [
{ id: 'q1_step1', text: '做出 1 瓶净水', kind: 'have-item', itemId: 'water_purified', count: 1 },
{ id: 'q1_step2', text: '去一趟村庄集市', kind: 'reach-place', placeId: 'village_market' },
],
rewards: [{ type: 'unlock-recipe', recipeId: 'cook_stew' }],
},
q_market_contact: {
id: 'q_market_contact',
title: '和老罗搭上线',
desc: '想往城市深处走,集市里的消息是唯一捷径。',
type: 'main',
autoStart: [{ kind: 'quest-state', questId: 'q_tutorial_water', state: 'completed' }],
steps: [
{ id: 'q2_step1', text: '在集市见到老罗', kind: 'flag', flag: 'met_trader', value: true },
{ id: 'q2_step2', text: '前往城市边缘', kind: 'reach-place', placeId: 'city_edge' },
],
rewards: [{ type: 'unlock-recipe', recipeId: 'repair_rifle' }],
},
q_signal_hunt: {
id: 'q_signal_hunt',
title: '追踪旧信号',
desc: '检查站和高楼天线都在指向同一个地方:老地铁口。',
type: 'main',
autoStart: [{ kind: 'quest-state', questId: 'q_market_contact', state: 'completed' }],
steps: [
{ id: 'q3_step1', text: '找到地铁代号', kind: 'flag', flag: 'got_subway_code', value: true },
{ id: 'q3_step2', text: '前往老地铁口', kind: 'reach-place', placeId: 'subway_entrance' },
{ id: 'q3_step3', text: '恢复地铁供电', kind: 'flag', flag: 'power_rerouted', value: true },
],
rewards: [{ type: 'unlock-recipe', recipeId: 'assemble_filter' }],
},
q_sewer_route: {
id: 'q_sewer_route',
title: '从下水道进去',
desc: '深处的空气和污水会先杀死没有准备的人。',
type: 'main',
autoStart: [{ kind: 'quest-state', questId: 'q_signal_hunt', state: 'completed' }],
steps: [
{ id: 'q4_step1', text: '做出野外滤芯', kind: 'have-item', itemId: 'field_filter', count: 1 },
{ id: 'q4_step2', text: '进入污染下水道', kind: 'reach-place', placeId: 'sewer' },
{ id: 'q4_step3', text: '找到门禁卡', kind: 'have-item', itemId: 'metro_keycard', count: 1 },
],
rewards: [{ type: 'log', message: '现在,你有资格去试试那道混凝土门。', tone: 'good' }],
},
q_vault_gate: {
id: 'q_vault_gate',
title: '打开避难所',
desc: '最后的门槛不会问你准备好了没。',
type: 'main',
autoStart: [{ kind: 'quest-state', questId: 'q_sewer_route', state: 'completed' }],
steps: [
{ id: 'q5_step1', text: '抵达避难所入口', kind: 'reach-place', placeId: 'vault_gate' },
{ id: 'q5_step2', text: '启动门禁终端', kind: 'flag', flag: 'vault_opened', value: true },
],
rewards: [{ type: 'log', message: '厚重门板正在开启。', tone: 'good' }],
},
},
travelEventPool: ['road_wanderer'],
};
export default gameContent;