JavaScript must be enabled to play.
Browser lacks capabilities required to play.
Upgrade or switch to another browser.
Loading…
………… …… 你醒来了 一段描述 [[进去|走廊]]
<<link "背包">> <<navigate "go" "backpack">> <</link>> <<link "载具">> <<navigate "go" "ship">> <</link>> <<link "备忘录">> <<navigate "go" "note">> <</link>>
架子上罗列着所有库存。 <<nobr>> <<set _s_store = State.variables.store>> <<set _s_items = State.variables.items>> <<set _s_cats = Object.keys(_s_store)>> <<for _ci = 0; _ci < _s_cats.length; _ci++>> <<set _cat = _s_cats[_ci]>> <<set _val = _s_store[_cat]>> <<if Array.isArray(_val)>> <<set _filled = _val.filter(x => x.quantity > 0)>> <<if _filled.length > 0>> <div class="inv-category"><<print _cat>></div> <div class="inv-grid"> <<for _ii = 0; _ii < _filled.length; _ii++>> <<set _entry = _filled[_ii]>> <<capture _entry>> <<set _def = _s_items[_entry.id]>> <<set _rarity = _def.rarity === "稀有" ? " rare" : (_def.rarity === "传说" ? " legendary" : "")>> <span class="inv-item<<print _rarity>>"><<link _def.name>><<set $selectitem = _entry.id>><<goto "仓库物品页面">><</link>><span class="item-qty">×<<print _entry.quantity>><<freshnessTag _entry>></span></span> <</capture>> <</for>> </div> <</if>> <</if>> <</for>> <</nobr>> [[炼金室]]
<<nobr>> <div id="sc-status"> <<include "侧边栏状态">> </div> <</nobr>>
/* 主角 */ <<set $hunger =100>> <<set $water =100>> <<set $power =100>> <<set $life =100>> <<set $san =100>> <<set $tre=0>> <<set $magic =100>> <<set $tem=20>> <<set $wet=0>> <<set $outdoor =0>> <<set $inwater=0>> <<set $fire=0>> <<set $bath=0>> <<set $cloth=0>> /* 世界 */ <<set $minute =0>> <<set $hour =7>> <<set $day =1>> <<set $season =1>> <<set $showhour =7>> <<set $showday =1>> <<set $showminute =0>> <<set $showseason =1>> <<set $showweather=['冰封','风雪','炎热','雾气','晴朗','阴云','小雨','大雨','大风','暴风雨']>> <<set $viewweather=['frozen','snow','hot','fog','clear','cloudy','lightrain','heavyrain','windy','storm']>> <<set $weather =3>> <<set $timepass =0>> <<set $hourpass =0>> <<set $seasontem=20>> <<set $wavetem=0>> <<set $weatem=[-15,-10,5,-2,0,-2,-4,-5,-4,-6]>> /*六维运算*/ <<set $hungerlim =-4320>> <<set $waterlim =-1440>> <<set $hungerpass =0>> <<set $waterpass =0>> <<set $lifepass =0>> <<set $sanpass =0>> <<set $powerpass =0>> <<set $worldtem=20>> <<set $tempass=0>> <<set $wetpass=0>> <<set $heatpass=-120>> <<set $addtem=0>> <<set $coldpass=0>> /*载具*/ <<set $depth =200>> <<set $fuel=40000>> <<set $fuelMax=300>> <<set $shell=100>> <<set $sys=100>> /* 地图 */ <<set $spdmax=1000>> <<set $sailspd=0>> <<set $sailtime=0>>/* 航行计划时间 */ <<set $sailpass=0>>/* 已航行 */ <<set $maptype="sand">>/* 当前地区 */ <<set $map=10>>/* 当前坐标 */ <<set $maplim=100>> /* 当前地区跨度 */ <<set $depthwave=0>>/* 深度变化区域 */ <<set $depthspd=0>>/* 深度变化速度 */ <<set $depthpass=0>>/* 深度变化跨度 */ <<set $depthnoc=100>> <<set $depthdeep=300>>/* 当前最大深度 */ <<set $mapinfo = { sand: { type: "沙海床", depthmin: 20, depthmax: 10000, spanmin: 30000, spanmax: 200000, weight: 40, spdmax: 2, spdmin: -2 }, flat: { type: "岩海床", depthmin: 200, depthmax: 500, spanmin: 20000, spanmax: 70000, weight: 30, spdmax: -3, spdmin: 3 }, cliff: { type: "峭壁", depthmin: 200, depthmax: 10000, spanmin: 20000, spanmax: 60000, weight: 10, spdmax: 5, spdmin: -5 }, grass: { type: "海草床", depthmin: 20, depthmax: 200, spanmin: 20000, spanmax: 80000, weight: 10, spdmax: 2, spdmin: -2 }, reef: { type: "珊瑚礁", depthmin: 20, depthmax: 200, spanmin: 20000, spanmax: 60000, weight: 5, spdmax: 3, spdmin: -3 }, forest: { type: "海藻森林", depthmin: 200, depthmax: 600, spanmin: 30000, spanmax: 80000, weight: 5, spdmax: 3, spdmin: -3 } }>> <<set $mapnow=100>> <<set $fishing= 0>> /*背包物品系统*/ <<set $specialPassages = ["backpack", "背包物品页面", "ship"]>> // 将“背包”和“状态”片段标记为特殊片段 /* 物品总览属性 */ /* 烹饪状态 */ <<set $cookMethod = "">> <<set $cookIngredients = []>> <<set $cookTimer = 0>> <<set $cookFinalTime = 0>> <<set $cookDuration = 20>> <<set $cookSuccessMin = 5>> <<set $cookSuccessMax = 18>> <<set $cookPerfectMin = 8>> <<set $cookPerfectMax = 15>> <<set $cookResultId = "">> <<set $fridge = [null,null,null,null,null,null,null,null]>> <<set $assembleResult = "">> <<set $assembleSlot = 0>> <<set $selectFridgeSlot = 0>> <<set $cookRecipeName = "">> <<set $cookQuality = "">> /* 事件 */ <<set $activeEvent = 0>> <<set $eventLog = []>> <<set $eventPass = 0>> <<set $eventTimer = 0>> //初始化组// <<include "ViewDefs">> <<include "StoreDefs">> <<include "ItemDefs">> <<include "FishingDefs">> <<include "RecipeDefs">> <<include "CookTemplates">> <<include "CookFragments">> <<include "DisassemblyDefs">> <<include "AlchemyItemDefs">> <<include "AlchemyDefs">> /* 炼金状态 */ <<set $alchemyInstrument = "">> <<set $alchemyMaterials = []>> <<set $alchemyTimer = 0>> /* 船只子系统 */ <<set $shipOxygen = 100>> <<set $shipSystems = { propulsion:true, fishing:true, oxygen:true, heating:true, storage:true }>> <<set $shipUpgrades = { speed:0, armor:0, insulation:0, capacity:0, sonar:0 }>> <<set $upgrades = { hull: 0, pressure: 0, thruster: 0, arm: 0, oxygen_sys: 0, fuel_tank: 0, kitchen: 0, alchemy: 0 }>> /* ═══ 探索系统 ═══ */ /* 区域背景丰富度(0-100):决定随机鱼获和碎片事件触发概率,会被探索消耗 */ <<set $regionRichness = 60>> /* 当前激活的世界场景对象,null=无场景 */ <<set $worldScene = null>> /* 记录的坐标书签 [{label, bookmarkType, terrainReq, depthReq, exhausted}] */ <<set $bookmarks = []>> <<set $largeScene = 0>> <<set $temporalEvent = 0>> <<set $temporalLog = "">> <<set $showBookmarks = false>> /* 当前模式: "travel"=航行中 / "explore"=锚定探索 */ <<set $sailMode = "travel">> <<set $activeMicroEvent = null>> <<set $wsChild = null>> /* 当前交互中的场景子事件 */ <<set $activeSmallEvent = null>> /* 事件调度系统 */ <<set $currentContext = "sailing">> /* 当前上下文: sailing / anchored / outside */ <<set $pendingEvent = null>> /* 跨上下文待处理事件 */ <<set $envEffects = []>> /* 持久环境影响列表(影响类事件) */ <<set $ecoBonds = {}>> /* 生态驻留好感记录(好感类事件) */ <<set $combatState = null>> /* 当前战斗状态对象 */ <<set $activeCombat = null>> /* 当前进行中战斗 */ <<set $combatEnemyTable = null>> /* 战斗敌人定义表(lazy init)*/ <<set $combatLog = "">> /* 本回合战斗结果文本 */ <<set $combatReturn = null>> /* 战斗结束后返回的 passage */ <<set $npcState = null>> /* 当前 NPC 交互状态 */ <<set $activeNpc = null>> /* 当前相遇的 NPC 对象 */ <<set $metNpcs = {}>> /* 已相遇 NPC 记录 {npcId: {firstDay, meetCount}} */ <<set $npcSpawnCooldown = 0>> /* NPC 出现冷却(天数) */ <<set $npcReturn = null>> /* NPC 交互结束后返回的 passage */ <<set $questFlags = {}>> /* 主线/支线旗标 */ <<set $questProgress = 0>> /* 主线当前节点索引(指向 $questChain) */ <<set $questLog = []>> /* 日记条目数组 [{id,title,text,day,type}] */ <<set $sideQuestProgress = {}>> /* 支线进度 {sqId: nodeIndex} */ <<set $sideQuestLog = {}>> /* 支线日记 {sqId: [{title,text,day}]} */ <<set $questNotify = "">> /* 最近一条任务提示文本 */ <<set $lastMicroText = "">> <<set $lastSmallEventText = "">> <<set $activeHuntItems = []>> /* 当前可交互的内联微型事件ID列表 */ <<set $lastHuntText = "">> /* 微型事件结果文本 */ <<set $lastEnvText = "">> <<exploreDefs>> /* 初始化碎片池和环境采集定义 */ /* 环境采集结果文本 */ /* 每次探索搜索的丰富度消耗范围(ExploreDefs会覆盖此值) */ <<set $exploreSearchCost = { min: 3, max: 7 }>> <<set $lastExploreText = "">> <<set $exploreLog = []>> /* ═══ 仓外探索系统 ═══ */ <<set $divingMode = false>> /* 是否在仓外 */ <<set $diveOxygen = 100>> /* 当前氧气 0-100 */ <<set $diveCold = 0>> /* 水温冷压积累 0-100 */ <<set $diveStepsOut = 0>> /* 已深入步数 */ <<set $diveStepCostO2 = 4>> /* 每步氧气消耗(diveInit时按深度覆盖) */ <<set $diveStepTime = 3>> /* 每步游戏时间消耗(分钟) */ <<set $diveChain = []>> /* 当前探索路线(批次二填充) */ <<set $diveChainSub = []>> /* 分叉路线 */ <<set $diveIdx = 0>> /* 当前位置指针 */ <<set $diveLog = "">> <<set $diveInteractResult = "">> <<set $wsLastActionText = "">> <<set $diveO2Dead = false>> <<set $worldSceneQueue = []>> <<set $worldSceneQueueIdx = 0>> <<set $wsLastActionLoot = "">> <<set $devMode = true>> <<set $diveOxygenMax = 100>> <<set $lastUpgradeText = "">> /* DEV:测试时开启,发布前改为 false */ <<set $diveChainTerrain = "">> /* 最近行动描述文本 */ <<set $diveArmBlocked = {}>> /* {sceneId:[elem,...]} 被障碍物阻塞的仓外元素 */ <<set $diveArmCleared = {}>> /* {sceneId:[elem,...]} 已被机械臂清除的障碍 */ <<set $diveShowIntro = false>>/* 出仓首帧显示简介 */ <<set $diveIntro = "">> /* ═══ 多方向区域选择 ═══ */ /* 预生成的3个下一区域选项 [{type, depth, maplim, label}] */ <<set $nextAreas = []>> /* 是否已完成预生成 0/1 */ <<set $nextAreasReady = 0>> /* 玩家已选择的区域索引(0/1/2),-1=返回上一区域 */ <<set $selectedNextArea = 0>> /* 上一个区域快照,用于"返回"功能 {type, depth, maplim} */ <<set $prevArea = null>> <<cpDefs>>
描写当前天气状况与海况。 [[← 返回|驾驶舱]]
<<cpRoomCheck "主舱">> <<nobr>> <div style="font-size:0.8rem;color:var(--bone-dim);line-height:1.7;margin:0.35rem 0 0.5rem;">透过舷窗——<<view>></div> <<if $worldScene>> <<if $worldScene.state === "approaching">><div style="font-size:0.72rem;color:var(--amber);margin-bottom:0.25rem;">⚠ <<print $worldScene.approachDesc>></div> <<elseif $worldScene.state === "inside">><div style="font-size:0.72rem;color:var(--amber-bright);margin-bottom:0.25rem;">◆ 正处于:<<print $worldScene.name>></div> <</if>> <</if>> <</nobr>> 一段对走廊的描述 <<cpScene "主舱">> 移动 [[驾驶舱]] | [[炼金室]] | [[浴室]] [[卧室]] | [[厨房]] | [[农场]] [[供能室]] | [[机械室]] | [[出舱]]
<<view>> 黄铜的操作台在你面前。 <<link "开始">> <<goto "航行">> <</link>> [[返回|走廊]]
<<nobr>> <<if !$fuelDefs>><<fuelDefs>><</if>> /* ── 标题 ── */ <div style="font-size:0.9rem;color:var(--amber-bright);margin-bottom:0.3rem;">⚙ 供能室</div> <div style="font-size:0.78rem;color:var(--bone-dim);margin-bottom:0.4rem;line-height:1.7;"> 嗡嗡的低频震动从机壁传来。仪表板上密密麻麻排列着压力计和温度表,正中央是一块厚重的铸铁舱门——燃料槽的注入口。 </div> /* ── 燃料槽状态 ── */ <<set _gfPct = Math.max(0,Math.min(100,Math.floor(($fuel||0)/$fuelMax*100)))>> <<set _gfCol = _gfPct > 40 ? "var(--teal-bright)" : _gfPct > 15 ? "var(--amber)" : "var(--danger-bright)">> <div style="border:1px solid var(--border-dim);border-radius:3px;padding:0.3rem 0.5rem;margin-bottom:0.4rem;"> <div style="display:flex;justify-content:space-between;font-size:0.72rem;color:var(--bone-dim);margin-bottom:0.15rem;"> <span>⛽ 燃料槽</span> <span style="color:<<print _gfCol>>;"><<print Math.floor($fuel||0)>> / <<print $fuelMax>></span> </div> <div style="background:var(--bg-panel);border:1px solid var(--border-dim);height:6px;border-radius:3px;overflow:hidden;"> <div style="height:100%;width:<<print _gfPct>>%;background:<<print _gfCol>>;transition:width 0.4s;"></div> </div> <<if $driftMode>> <div style="font-size:0.72rem;color:var(--danger-bright);margin-top:0.15rem;">‼ 燃料耗尽——引擎停转中</div> <</if>> </div> /* ── 可用燃料物品 ── */ <<set _gFuelIds = ["coal","wood","oil","fish_oil","algae_block","mineral_fuel"]>> <<set _gFuelList = []>> <<for _gfi = 0; _gfi < _gFuelIds.length; _gfi++>> <<set _gfId = _gFuelIds[_gfi]>> <<set _gfType = ($items[_gfId] ? $items[_gfId].type : "")>> <<set _gfQty = 0>> <<if _gfType && $store[_gfType]>> <<for _gfj = 0; _gfj < $store[_gfType].length; _gfj++>> <<if $store[_gfType][_gfj].id === _gfId>><<set _gfQty += $store[_gfType][_gfj].quantity>><</if>> <</for>> <</if>> <<if _gfType && $backpack[_gfType]>> <<for _gfj = 0; _gfj < $backpack[_gfType].length; _gfj++>> <<if $backpack[_gfType][_gfj].id === _gfId>><<set _gfQty += $backpack[_gfType][_gfj].quantity>><</if>> <</for>> <</if>> <<if _gfQty > 0>> <<run _gFuelList.push({id:_gfId, qty:_gfQty, val:$fuelDefs[_gfId]})>> <</if>> <</for>> <<if _gFuelList.length === 0>> <div style="font-size:0.78rem;color:var(--bone-dim);opacity:0.55;margin-bottom:0.4rem;"> 货舱和背包中没有可用的燃料物品。 </div> <<else>> <div style="font-size:0.72rem;color:var(--bone-dim);margin-bottom:0.15rem;">可用燃料:</div> <<for _gli = 0; _gli < _gFuelList.length; _gli++>> <<set _gl = _gFuelList[_gli]>> <<capture _gl>> <<set _glName = ($items[_gl.id] ? $items[_gl.id].name : _gl.id)>> <div style="border-left:2px solid var(--amber-dim);padding:0.15rem 0.4rem;margin-bottom:0.2rem;font-size:0.76rem;"> <span style="color:var(--bone);"><<print _glName>></span> <span style="font-size:0.69rem;color:var(--bone-dim);margin-left:0.3rem;">热值+<<print _gl.val>>/个 · 库存<<print _gl.qty>>个</span><br> /* +1 */ <<set _gl1Label = "加入×1">> <<link _gl1Label>><<addFuel _gl.id 1>><<goto "供能室">><</link>> <span style="opacity:0.4;margin:0 0.2rem;">·</span> /* +10 */ <<if _gl.qty >= 10>> <<set _gl10Label = "×10">> <<link _gl10Label>><<addFuel _gl.id 10>><<goto "供能室">><</link>> <<else>> <span style="opacity:0.25;">×10</span> <</if>> <span style="opacity:0.4;margin:0 0.2rem;">·</span> /* +100 */ <<if _gl.qty >= 100>> <<set _gl100Label = "×100">> <<link _gl100Label>><<addFuel _gl.id 100>><<goto "供能室">><</link>> <<else>> <span style="opacity:0.25;">×100</span> <</if>> <span style="opacity:0.4;margin:0 0.2rem;">·</span> /* 全部 */ <<set _glAllLabel = "全部加入(×" + _gl.qty + ")">> <<link _glAllLabel>><<addFuel _gl.id "all">><<goto "供能室">><</link>> </div> <</capture>> <</for>> <</if>> /* ── 操作结果 ── */ <<if $lastFuelText>> <div style="font-size:0.74rem;color:var(--teal-bright);border-left:2px solid var(--teal-bright);padding:0.1rem 0.35rem;margin-bottom:0.3rem;"> <<print $lastFuelText>> </div> <<set $lastFuelText = "">> <</if>> <div style="border-top:1px solid var(--border-dim);margin-top:0.35rem;padding-top:0.3rem;"> <span style="font-size:0.72rem;color:var(--bone-dim);">设备升级请前往 </span> [[机械室]] </div> <div style="margin-top:0.5rem;font-size:0.75rem;">[[← 返回走廊|走廊]]</div> <</nobr>>
<<cpRoomCheck "厨房">> <div style="font-size:0.8rem;color:var(--bone-dim);line-height:1.7;margin:0.35rem 0 0.5rem;">透过舷窗——<<view>></div> <<if $worldScene>> <<if $worldScene.state === "approaching">><div style="font-size:0.72rem;color:var(--amber);margin-bottom:0.25rem;">⚠ <<print $worldScene.approachDesc>></div> <<elseif $worldScene.state === "inside">><div style="font-size:0.72rem;color:var(--amber-bright);margin-bottom:0.25rem;">◆ 正处于:<<print $worldScene.name>></div> <</if>> <</if>> <<nobr>> <div style="margin-bottom:0.8rem;"> 在厨房里,铜锅和烤架整整齐齐地摆放着,炉火的余温还在。 </div> <<cpScene "厨房">> <div style="font-size:0.82rem;color:var(--bone-dim);margin-bottom:0.5rem;">选择烹饪方式:</div> <<set _kLv = Number($upgrades ? $upgrades.kitchen : 0) || 0>> <div class="action-row" style="flex-wrap:wrap;gap:0.4rem;margin-bottom:0.6rem;"> /* Lv0+ 始终可用 */ <<link "明火烤">><<set $cookMethod = "明火烤">><<set $cookIngredients = []>><<goto "烹饪选材">><</link>> <<link "生食">><<set $cookMethod = "生食">><<set $cookIngredients = []>><<goto "烹饪选材">><</link>> /* Lv1+ */ <<if _kLv >= 1>> <<link "铜锅炖">><<set $cookMethod = "铜锅炖">><<set $cookIngredients = []>><<goto "烹饪选材">><</link>> <<else>><span style="opacity:0.3;font-size:0.8rem;" title="需要厨房设备 Lv1">铜锅炖🔒</span><</if>> /* Lv2+ */ <<if _kLv >= 2>> <<link "清蒸">><<set $cookMethod = "清蒸">><<set $cookIngredients = []>><<goto "烹饪选材">><</link>> <<link "煎炒">><<set $cookMethod = "煎炒">><<set $cookIngredients = []>><<goto "烹饪选材">><</link>> <<else>><span style="opacity:0.3;font-size:0.8rem;" title="需要厨房设备 Lv2">清蒸🔒</span> <span style="opacity:0.3;font-size:0.8rem;" title="需要厨房设备 Lv2">煎炒🔒</span><</if>> /* Lv3 */ <<if _kLv >= 3>> <<link "油炸">><<set $cookMethod = "油炸">><<set $cookIngredients = []>><<goto "烹饪选材">><</link>> <<else>><span style="opacity:0.3;font-size:0.8rem;" title="需要厨房设备 Lv3">油炸🔒</span><</if>> </div> <<if _kLv < 3>> <div style="font-size:0.7rem;color:var(--bone-dim);opacity:0.55;margin-bottom:0.5rem;">🔒 可在机械室升级「厨房设备」解锁更多烹饪方式</div> <</if>> <div style="height:1px;background:var(--border-dim);margin:0.5rem 0;"></div> <<nobr>> <<set _ki_count = $fridge ? $fridge.filter(x => x !== null).length : 0>> <</nobr>> <span style="font-size:0.82rem;color:var(--bone-dim);">冰箱 <span style="color:var(--amber-bright);"><<print _ki_count>>/8</span></span> [[查看冰箱|冰箱]] [[返回|走廊]] <</nobr>>
<<nobr>> <<cpRoomCheck "仓库">> <div style="font-size:0.85rem;color:var(--bone-dim);margin-bottom:0.8rem;line-height:1.7;"> 你的工作室兼仓库。仪器在昏黄的灯光下静静等待,架子上的材料散发着微弱的元素气息。 </div> <<cpScene "仓库">> <div style="font-size:0.82rem;color:var(--bone-dim);margin-bottom:0.4rem;">仪器</div> <<set _aLv = Number($upgrades ? $upgrades.alchemy : 0) || 0>> <div class="action-row" style="flex-wrap:wrap;gap:0.4rem;margin-bottom:0.6rem;"> /* Lv0+ 始终可用 */ <<link "精炼台">><<set $alchemyInstrument="精炼台">><<set $alchemyMaterials=[]>><<goto "精炼台">><</link>> /* Lv1+ 溶解皿(黑化)*/ <<if _aLv >= 1>> <<link "溶解皿(黑化)">><<set $alchemyInstrument="溶解皿">><<set $alchemyMaterials=[]>><<goto "炼金选材">><</link>> <<else>><span style="opacity:0.3;font-size:0.8rem;" title="需要炼金台 Lv1">溶解皿🔒</span><</if>> /* Lv2+ 蒸馏器 + 凝结炉 */ <<if _aLv >= 2>> <<link "蒸馏器(白化)">><<set $alchemyInstrument="蒸馏器">><<set $alchemyMaterials=[]>><<goto "炼金选材">><</link>> <<link "凝结炉(黄化)">><<set $alchemyInstrument="凝结炉">><<set $alchemyMaterials=[]>><<goto "炼金选材">><</link>> <<else>> <span style="opacity:0.3;font-size:0.8rem;" title="需要炼金台 Lv2">蒸馏器🔒</span> <span style="opacity:0.3;font-size:0.8rem;" title="需要炼金台 Lv2">凝结炉🔒</span> <</if>> /* Lv3 赤化炉 */ <<if _aLv >= 3>> <<link "赤化炉(赤化)">><<set $alchemyInstrument="赤化炉">><<set $alchemyMaterials=[]>><<goto "炼金选材">><</link>> <<else>><span style="opacity:0.3;font-size:0.8rem;" title="需要炼金台 Lv3">赤化炉🔒</span><</if>> </div> <<if _aLv < 3>> <div style="font-size:0.7rem;color:var(--bone-dim);opacity:0.55;margin-bottom:0.5rem;">🔒 可在机械室升级「炼金台扩充」解锁更多仪器</div> <</if>> <div style="height:1px;background:var(--border-dim);margin:0.5rem 0;"></div> [[仓库|store]] [[天窗|天窗]] [[返回走廊|走廊]] <</nobr>>
<<cpRoomCheck "休息室">> 一段描述 <<cpScene "休息室">> [[书桌]] [[床铺]] [[返回|走廊]]
一段描述 [[镜子]] [[浴缸]] [[返回|走廊]]
一段描述 [[种植箱]] [[鱼缸]] [[返回|走廊]]
<<nobr>> <<cpRoomCheck "舱外">> /* 深度阈值判断 */ <<if $depth <= 0>> <<set _diveZone = "surface">> <<set _canDive = true>> <<elseif $depth <= 50>> <<set _diveZone = "shallow">> <<set _canDive = true>> <<elseif $depth <= 300>> <<set _diveZone = "mid">> <<set _canDive = true>> <<else>> <<set _diveZone = "deep">> <<set _canDive = false>> <</if>> /* 舱门描述 */ <div style="font-size:0.84rem;color:var(--bone);line-height:1.85;margin-bottom:0.4rem;"> <<if _diveZone === "surface">> 舱门开启后是开放的海面,水面平静或翻涌,取决于当前天气。 <<elseif _diveZone === "shallow">> 舷窗外水压尚在可承受范围,轮廓清晰可辨。<br> <span style="font-size:0.78rem;color:var(--bone-dim);"><<print $mapinfo[$maptype].type>> · $depth m · 约 <<print Math.floor(100/3*3)>> 分钟可用时间</span> <<elseif _diveZone === "mid">> 水压明显,视线有限,氧气消耗较快,出仓需做好准备。<br> <span style="font-size:0.78rem;color:var(--amber);"><<print $mapinfo[$maptype].type>> · $depth m · 约 <<print Math.floor(100/10*3)>> 分钟可用时间</span> <<else>> <span style="color:var(--danger-bright);">当前深度 <<print $depth>>m 超出无装备出仓限制(≤300m),无法安全出仓。</span> <</if>> </div> <<cpScene "舱外">> <<if _canDive>> <div style="font-size:0.8rem;"><<link "▶ 出仓下水">><<diveInit>><<set $currentContext = "outside">><<goto "仓外探索">><</link>></div> <<else>> <div style="opacity:0.45;font-size:0.8rem;">▶ 出仓下水(深度超限)</div> <</if>> [[← 返回走廊|走廊]] <</nobr>>
<<nobr>> <<widget "time" >> <<set $hourpass =Math.floor($timepass/60)>> /*饥饿扣血*/ <<if $hunger==0>> <<set $hungerlim+=$timepass>> <<if $hungerlim>0>> <<set $life-=Math.floor($hungerlim/60)>> <<set $hungerlim=$hungerlim%60>> <<endif>> <<endif>> <<if $hunger>0>> <<set $hungerlim=-4320>> <<endif>> /*口渴扣血*/ <<if $water==0>> <<set $waterlim+=$timepass>> <<if $waterlim>0>> <<set $life-=Math.floor($waterlim/60)>> <<set $waterlim=$waterlim%60>> <<endif>> <<endif>> <<if $water>0>> <<set $waterlim=-1440>> <<endif>> /*食水时间变化*/ <<set $hungerpass +=$timepass>> <<set $waterpass +=$timepass>> <<set $hunger -=Math.floor($hungerpass/15)>> <<set $water -=Math.floor($waterpass/15)>> /*食水上下限控制*/ <<if $hunger <0 >> <<set $hunger = 0>> <<endif>> <<if $water <0 >> <<set $water = 0>> <<endif>> <<if $hunger>100>> <<set $hunger = 100>> <<endif>> <<if $water>100>> <<set $water = 100>> <<endif>> <<set $hungerpass =$hungerpass%15>> <<set $waterpass =$waterpass%15>> /*体力变化上下限*/ <<if $power <0>> <<set $power =0>> <<endif>> <<if $hunger>0 && $water>0 >> <<set $powerpass+= $timepass>> <<set $power +=Math.floor($powerpass/5)>> <<set $powerpass= $powerpass%5>> <<if $power >100 >> <<set $power=100>> <<endif>> <<endif>> <<if $hunger<10 || $water<10 || $life<50 >> <<if $power >20 >> <<set $power=20>> <<endif>> <<endif>> <<set $powerpass=0>> /*生命恢复*/ <<if $hunger>0 && $water>0 >> <<set $lifepass+=$timepass>> <<set $life +=Math.floor($lifepass/360)>> <<set $lifepass=$lifepass%360>> <<if $life >100 >> <<set $life=100>> <<endif>> <<endif>> /*时间进制*/ <<set $minute += $timepass%60>> <<set $hour += $hourpass>> <<if $minute >= 60>> <<set $hour += 1>> <<set $minute = $minute - 60>> <<endif>> <<if $minute < 10 >> <<set $showminute = '0'+$minute>> <<else>> <<set $showminute = $minute>> <<endif>> <<if $hour >= 24 >> <<set $hour = $hour - 24>> <<set $day += 1>> <<set $showday += 1>> <<decayItems>> <<set $wavetem to random(-1,3)>> <<set $weather to random(1,9)>> <<endif>> <<if $hour < 10 >> <<set $showhour = '0' + $hour>> <<else>> <<set $showhour = $hour>> <<endif>> <<if $showday >= 34 && $season <4 >> <<set $showday = $showday - 33>> <<set $season += 1>> <<endif>> <<if $season==4 && $showday>=2>> <<set $showday = $showday - 1>> <<set $season = 1>> <<endif>> <<if $season == 1>> <<set $showseason = '丰饶'>> <<else>> <<if $season == 2>> <<set $showseason = '日曜'>> <<else>> <<if $season == 3>> <<set $showseason = '凛冬'>> <<else>> <<set $showseason='冰封'>> <<endif>> <<endif>> <<endif>> /*天气*/ <<if $season==4>> <<set $weather=0>> <<else>> <<if $season ==2 && $weather==1 >> <<set $weather = 2>> <<else>> <<if $season ==3 && $weather==2 >> <<set $weather =1>> <<else>> <<if $season ==1 && $weather<3 >> <<set $weather +=2 >> <<endif>> <<endif>> <<endif>> <<endif>> /*环境温度判定*/ <<if $season==1 >> <<if $showday==1>> <<set $seasontem=15>> <<else>> <<set $seasontem=15+Math.floor($showday/3)>> <<endif>> <<endif>> <<if $season==2 >> <<if $showday==1>> <<set $seasontem=26>> <<else>> <<if $showday<21>> <<set $seasontem=26+Math.floor($showday/2)>> <<else>> <<if $showday==21>> <<set $seasontem=35>> <<else>> <<set $seasontem=35-($showday-21)*2>> <<endif>> <<endif>> <<endif>> <<endif>> <<if $season==3 >> <<if $showday==1>> <<set $seasontem=10>> <<else>> <<set $seasontem=10-Math.floor($showday/3)>> <<endif>> <<endif>> <<if $season==3 && $seasontem <0 >> <<set $seasontem=0>> <<endif>> <<if $depth == -1 >> <<set _worldtem=$weatem[$weather]+$seasontem+$wavetem>> <<else>> <<if $depth<200>> <<set _worldtem=$seasontem+$wavetem>> <<else>> <<if $depth<1000>> <<set _worldtem = Math.floor($seasontem / 5)>> <<else>> <<set _worldtem=0>> <<endif>> <<endif>> <<endif>> <<if $outdoor==0 && _worldtem < 10>> <<set $worldtem=_worldtem+3>> <<else>> <<if $outdoor==0 && _worldtem >30 >> <<set $worldtem=_worldtem-3>> <<else>> <<set $worldtem= _worldtem>> <<endif>> <<endif>> /*湿度判定*/ <<if $outdoor == 1>> <<if $weather == 6>> <<set $wetpass += $timepass>> <<set $wet += Math.floor($wetpass / 3)>> <<set $wetpass = $wetpass % 3>> <<elseif $weather == 7>> <<set $wetpass += $timepass>> <<set $wet += $wetpass>> <<set $wetpass = 0>> <<elseif $weather == 9>> <<set $wetpass += $timepass * 2>> <<set $wet += $wetpass>> <<set $wetpass = 0>> <<endif>> <<endif>> <<if $outdoor == 1 && $weather == 2>> <<set $wetpass += $timepass>> <<set $wet -= Math.floor($wetpass / 2)>> <<set $wetpass = $wetpass % 2>> <<elseif $outdoor == 1 && $weather == 4>> <<set $wetpass += $timepass>> <<set $wet -= Math.floor($wetpass / 4)>> <<set $wetpass = $wetpass % 4>> <<elseif $worldtem >= 30>> <<set $wetpass += $timepass>> <<set $wet -= Math.floor($wetpass / 3)>> <<set $wetpass = $wetpass % 3>> <<endif>> <<if $inwater==1>> <<set $wet=100>> <<endif>> <<if $fire == 1>> <<set $wetpass += $timepass>> <<set $wet -= Math.floor($wetpass / 3)>> <<set $wetpass = $wetpass % 3>> <<endif>> <<set $wetpass=0>> <<if $wet<0>> <<set $wet=0>> <<endif>> <<if $wet>100>> <<set $wet=100>> <<endif>> <<if $wet>50>> <<set $wettem=$cloth+Math.floor($wet/10)>> <<else>> <<if $wet>20>> <<set $wettem=Math.floor($wet/8)>> <<else>> <<set $wettem=0>> <<endif>> <<endif>> /*自身温度*/ <<set $tem=$worldtem+$cloth-$wettem+$addtem>> <<if $bath>0>> <<set $tem=$bath>> <<endif>> <<set _cozy=0>> <<if $tem >= 18 && $tem <= 26>> <<set _cozy = -5>> <<set $heatpass -=$timepass*2 >> <<set $coldpass-=$timepass*2>> <<elseif $tem >= 32>> <<set _cozy = 5>> <<set $coldpass-=$timepass*3>> <<set $water-=$timepass/20>> <<if $tem>37>> <<set $heatpass += $timepass*2>> <<else>> <<set $heatpass+= $timepass>> <<endif>> <<if $heatpass >= 0>> <<set $health -= $timepass>> <<endif>> <<elseif $tem <= 10>> <<set _cozy = 5>> <<set $heatpass -=$timepass*3 >> <<if $power>50>> <<set $power=50>> <<endif>> <<if $tem<=0>> <<set $coldpass += $timepass*2>> <<else>> <<set $coldpass+= $timepass>> <<endif>> <<set $coldpass += $timepass>> <<if $coldpass >= 0>> <<set $health -=$timepass>> <<endif>> <<else>> <<set _cozy = 0>> <<set $heatpass -= $timepass>> <<set $coldpass-=$timepass>> <<endif>> <<if $heatpass<-120>> <<set $heatpass=-120>> <<endif>> <<if $coldpass<-120>> <<set $coldpass=-120>> <<endif>> <<if $life <0 >> <<set $life = 0>> <<endif>> /*压力变化*/ <<set _tre to random(20,25)>> <<if $life<25>> <<set _life=Math.floor((100-$life)/2)>> <<else>> <<if $life<50>> <<set _life=8+Math.floor((100-$life)/7)>> <<else>> <<if $life<90>> <<set _life=3+Math.floor((100-$life)/10)>> <<else>> <<if $life==100>> <<set _life=-5>> <<else>> <<set _life=0>> <<endif>> <<endif>> <<endif>> <<endif>> <<if $hunger<25>> <<set _hun=5+Math.floor((100-$hunger)/10)>> <<else>> <<if $hunger<50>> <<set _hun=Math.floor((100-$hunger)/10)>> <<else>> <<if $hunger>80>> <<set _hun=-5>> <<else>> <<set _hun=0>> <<endif>> <<endif>> <<endif>> <<if $water<25>> <<set _wat=5+Math.floor((100-$water)/10)>> <<else>> <<if $water<50>> <<set _wat=Math.floor((100-$water)/10)>> <<else>> <<if $water>80>> <<set _wat=-5>> <<else>> <<set _wat=0>> <<endif>> <<endif>> <<endif>> <<set $tre=_tre+_hun+_wat+_life+_cozy>> <<if $tre <0>> <<set $tre =0>> <<endif>> <<if $tre >100>> <<set $tre =100>> <<endif>> /*san check*/ <<if $tre>80 && $tre<100>> <<set $sanpass+=$timepass>> <<set $san -=Math.floor($sanpass/60)>> <<set $sanpass=$sanpass%60>> <<else>> <<if $tre==100>> <<set $sanpass+=$timepass>> <<set $san-=10>> <<set $san -=Math.floor($sanpass/30)>> <<set $sanpass=$sanpass%30>> <<else>> <<if $tre<=15>> <<set $sanpass+=$timepass>> <<set $san +=Math.floor($sanpass/30)>> <<set $sanpass=$sanpass%30>> <<endif>> <<endif>> <<endif>> <<if $san <0 >> <<set $san=0>> <<endif>> <<if $san >100 >> <<set $san = 100>> <<endif>> <<cpTick>> <<set $hourpass = 0>> <<set $timepass =0>> <</widget>> <</nobr>>
<<nobr>> <<if !$questChain>><<questDefs>><</if>> <div style="max-width:520px;padding:0.5rem 0.6rem;"> <div style="font-size:0.9rem;color:var(--bone);margin-bottom:0.4rem;border-bottom:1px solid var(--border-dim);padding-bottom:0.2rem;">📓 航行日记</div> <<if $questLog && $questLog.length > 0>> <div style="margin-bottom:0.5rem;"> <div style="font-size:0.72rem;color:var(--bone-dim);margin-bottom:0.15rem;letter-spacing:0.05em;">── 主线 ──</div> <<for _dki = $questLog.length - 1; _dki >= 0; _dki-->> <<set _dke = $questLog[_dki]>> <div style="margin-bottom:0.4rem;border-left:2px solid var(--teal-bright);padding:0.2rem 0.45rem;"> <div style="font-size:0.74rem;color:var(--teal-bright);margin-bottom:0.06rem;"><<print _dke.title>><span style="color:var(--bone-dim);font-size:0.68rem;"> · 第<<print _dke.day>>日</span></div> <div style="font-size:0.82rem;color:var(--bone);line-height:1.85;"><<print _dke.text>></div> </div> <</for>> </div> <<else>> <div style="font-size:0.82rem;color:var(--bone-dim);font-style:italic;margin-bottom:0.4rem;">日记本是空的。也许等你出海探索之后,会有些值得记录的事。</div> <</if>> <<set _dkSqKeys = $sideQuestLog ? Object.keys($sideQuestLog) : []>> <<if _dkSqKeys.length > 0>> <div style="border-top:1px solid var(--border-dim);padding-top:0.3rem;margin-top:0.2rem;"> <div style="font-size:0.72rem;color:var(--bone-dim);margin-bottom:0.15rem;letter-spacing:0.05em;">── 支线 ──</div> <<for _dksi = 0; _dksi < _dkSqKeys.length; _dksi++>> <<set _dkSqId = _dkSqKeys[_dksi]>> <<set _dkSqDef = $sideQuestDefs ? $sideQuestDefs[_dkSqId] : null>> <<set _dkSqLog = $sideQuestLog[_dkSqId]>> <<if _dkSqLog && _dkSqLog.length > 0>> <div style="margin-bottom:0.4rem;"> <div style="font-size:0.72rem;color:var(--amber-bright);margin-bottom:0.08rem;"><<print _dkSqDef ? _dkSqDef.title : _dkSqId>></div> <<for _dkni = _dkSqLog.length - 1; _dkni >= 0; _dkni-->> <<set _dkne = _dkSqLog[_dkni]>> <div style="margin-bottom:0.25rem;border-left:2px solid var(--amber-bright);padding:0.15rem 0.4rem;"> <div style="font-size:0.72rem;color:var(--amber-bright);margin-bottom:0.04rem;"><<print _dkne.title>><span style="color:var(--bone-dim);font-size:0.68rem;"> · 第<<print _dkne.day>>日</span></div> <div style="font-size:0.8rem;color:var(--bone);line-height:1.8;"><<print _dkne.text>></div> </div> <</for>> </div> <</if>> <</for>> </div> <</if>> <<nobr>> <div id="cheat-panel"> <input id="cheat-input" type="text" placeholder="写点什么…" /> <<link "确认">> <<set _cheatVal = document.getElementById("cheat-input").value.trim().toLowerCase()>> <<if _cheatVal === "viona">> <<if !$activeCpIds.includes("viona")>> <<set _cpInitNow = $day * 1440 + $hour * 60 + $minute>> <<set $cps.viona.lastTickTime = _cpInitNow>> <<set $cps.viona.actionEndTime = _cpInitNow + 480>> <<run $activeCpIds.push("viona")>> <div class="cheat-result">维奥娜加入了。</div> <<else>> <div class="cheat-result">她已经在船上了。</div> <</if>> <<else>> <div class="cheat-result">无效代码。</div> <</if>> <</link>> </div> <</nobr>> </div> [[返回|卧室]] <</nobr>>
一段描述 [[休息]] [[算了|卧室]]
<div style="font-size:0.8rem;color:var(--bone-dim);line-height:1.7;margin:0.35rem 0 0.5rem;">透过舷窗——<<view>></div> <<if $worldScene>> <<if $worldScene.state === "approaching">><div style="font-size:0.72rem;color:var(--amber);margin-bottom:0.25rem;">⚠ <<print $worldScene.approachDesc>></div> <<elseif $worldScene.state === "inside">><div style="font-size:0.72rem;color:var(--amber-bright);margin-bottom:0.25rem;">◆ 正处于:<<print $worldScene.name>></div> <</if>> <</if>> <<link 休息1h>> <<goto "小睡一会">> <<set $timepass=60>> <</link>> <<link 休息8h>> <<goto "睡觉">> <<set $timepass=480>> <</link>> [[起床|卧室]]
描写水培种植系统,可种植蔬菜与海草类作物。 [[← 返回|农场]]
描写鱼缸养殖系统,可暂养活体渔获。 [[← 返回|农场]]
描写镜中映像与角色状态反馈。 [[← 返回|浴室]]
描写浴缸使用体验与状态变化。 [[← 返回|浴室]]
描写水面出舱后的环境,可进行水面相关活动。 [[← 返回|出舱]]
描写出舱下水的准备流程与风险评估。 [[← 返回|出舱]]
<<nobr>> <<widget "additem">> <<set _ai_id = $args[0]>> <<set _ai_qty = $args[1]>> <<set _ai_def = State.variables.items[_ai_id]>> <<if !_ai_def>> <<print "错误:未知物品 " + _ai_id>> <<else>> <<set _ai_type = _ai_def.type>> <<if !$store[_ai_type]>><<set $store[_ai_type] = []>><</if>> /* 按当天日期分批(同日入库合并) */ <<set _ai_today = $day || 0>> <<set _ai_idx = -1>> <<for _ai_i = 0; _ai_i < $store[_ai_type].length; _ai_i++>> <<set _ai_e = $store[_ai_type][_ai_i]>> <<if _ai_e.id === _ai_id && (_ai_e.addedDay === _ai_today || (!_ai_e.addedDay && _ai_today === 0))>> <<set _ai_idx = _ai_i>> <<break>> <</if>> <</for>> <<if _ai_idx >= 0>> <<set $store[_ai_type][_ai_idx].quantity += _ai_qty>> <<else>> <<set _ai_newEntry = { id: _ai_id, quantity: _ai_qty, addedDay: _ai_today }>> <<run State.variables.store[_ai_type].push(_ai_newEntry)>> <</if>> <<print "获得 " + _ai_qty + " × " + _ai_def.name>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "removeitem">> <<set _ri_id = $args[0]>> <<set _ri_qty = $args[1]>> <<set _ri_def = State.variables.items[_ri_id]>> <<if !_ri_def>> <<print "错误:未知物品 " + _ri_id>> <<else>> <<set _ri_type = _ri_def.type>> <<set _ri_idx = -1>> <<if $store[_ri_type]>> <<for _ri_i = 0; _ri_i < $store[_ri_type].length; _ri_i++>> <<if $store[_ri_type][_ri_i].id === _ri_id>> <<set _ri_idx = _ri_i>> <<break>> <</if>> <</for>> <</if>> <<if _ri_idx < 0>> <<print "仓库中没有:" + _ri_def.name>> <<elseif $store[_ri_type][_ri_idx].quantity < _ri_qty>> <<print _ri_def.name + " 数量不足(现有 " + $store[_ri_type][_ri_idx].quantity + ")">> <<else>> <<set $store[_ri_type][_ri_idx].quantity -= _ri_qty>> <<print "消耗 " + _ri_qty + " × " + _ri_def.name>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "view">> /* 时段判定 */ <<if $showhour >= 5 && $showhour < 7>> <<set _time = "dusk">> <<elseif $showhour >= 7 && $showhour < 17>> <<set _time = "day">> <<elseif $showhour >= 17 && $showhour < 19>> <<set _time = "dawn">> <<else>> <<set _time = "night">> <</if>> <<set _weather = $viewweather[$weather]>> <<set _depth = $depth>> /* 地形判定:靠近海底100米内显示地形,否则显示水中 */ <<set _rawTerrain = ($depthdeep - _depth <= 100) ? $maptype : "water">> /* 安全fallback:若viewmap中没有该地形则使用sand */ <<set _terrain = ($viewmap[_rawTerrain] !== undefined) ? _rawTerrain : "sand">> /* 光照等级判定 */ <<set _lightKey = _time + "_" + _weather>> <<if $viewlight.bright.hasOwnProperty(_lightKey)>> <<set _lightLevel = "bright">> <<elseif $viewlight.hazy.hasOwnProperty(_lightKey)>> <<set _lightLevel = "hazy">> <<elseif $viewlight.dim.hasOwnProperty(_lightKey)>> <<set _lightLevel = "dim">> <<else>> <<set _lightLevel = "dark">> <</if>> /* 安全fallback:若该地形缺少当前光照等级的描述,降级到dim或dark */ <<if $viewmap[_terrain][_lightLevel] === undefined>> <<if $viewmap[_terrain].dim !== undefined>> <<set _lightLevel = "dim">> <<else>> <<set _lightLevel = "dark">> <</if>> <</if>> <<set _output = "">> /* 表层(0-80米):显示天气光照 + 地形 */ <<if _depth <= 80>> <<set _output = $viewlight[_lightLevel][_lightKey] || "">> <<set _output += "。" + $viewmap[_terrain][_lightLevel]>> /* 中层(80-300米):看不清海面,只显示地形 */ <<elseif _depth <= 300>> <<set _output = "这里有些难以看清海面的状况," + $viewmap[_terrain][_lightLevel]>> /* 深层(300-1000米):光照强制降为dim,deep强制降为dark */ <<elseif _depth <= 1000>> <<if _lightLevel === "bright" || _lightLevel === "hazy">> <<set _lightLevel = "dim">> <</if>> /* 降级后再次安全检查 */ <<if $viewmap[_terrain][_lightLevel] === undefined>> <<set _lightLevel = "dark">> <</if>> <<set _output = "光线难以企及," + $viewmap[_terrain][_lightLevel]>> /* 深渊(1000米+):永夜 */ <<else>> <<set _output = $viewmap[_terrain].dark || "无边的黑暗吞噬了一切,深渊在船底沉默延伸。">> <</if>> /* ── 提取纯天色句(不含地形)供场景覆盖态使用 ── */ <<if _depth > 1000>> <<set _lightOnly = "">> <<elseif _depth > 300>> <<set _lightOnly = "光线难以企及,深处只有探照灯的光锥。">> <<elseif _depth > 80>> <<set _lightOnly = "这里看不到海面,探照灯是唯一的光源。">> <<else>> <<set _lightOnly = ($viewlight[_lightLevel] && $viewlight[_lightLevel][_lightKey]) ? $viewlight[_lightLevel][_lightKey] + "。" : "">> <</if>> /* ── 四状态渲染逻辑 ── */ <<set _vOut = _output>> /* 状态1:worldScene 锚定中(次级中型事件) */ <<if $worldScene && $worldScene.state === "inside">> <<if !$wsDefs>><<worldSceneDefs>><</if>> <<set _wsViewD = ($wsDefs[$worldScene.id] && $wsDefs[$worldScene.id].viewDesc) ? $wsDefs[$worldScene.id].viewDesc : "">> <<if $largeScene && typeof $largeScene === "object" && $largeScene.state === "active" && $largeScene.viewDesc>> /* 大型场景内的次级场景:天色 + 大场景氛围 + 次级场景特写 */ <<set _vOut = _lightOnly + $largeScene.viewDesc + (_wsViewD ? " " + _wsViewD : "")>> <<else>> /* 独立 worldScene:天色 + 场景描述 */ <<set _vOut = _lightOnly + (_wsViewD ? _wsViewD : _output)>> <</if>> /* 状态2:大型场景内巡航(无锚定子场景) */ <<elseif $largeScene && typeof $largeScene === "object" && $largeScene.state === "active">> <<set _vOut = _lightOnly + ($largeScene.viewDesc ? $largeScene.viewDesc : "")>> /* 状态2b:大型场景淡出(leaving)— 恢复地形描述,附加淡显离开提示 */ <<elseif $largeScene && typeof $largeScene === "object" && $largeScene.state === "leaving">> <<set _lsLeaveHint = (typeof $largeScene.leaveHint === "string" && $largeScene.leaveHint) ? $largeScene.leaveHint : "">> <<set _vOut = _output + (_lsLeaveHint ? "<br><span style=\"opacity:0.55;font-style:italic\">" + _lsLeaveHint + "</span>" : "")>> /* 状态3:正在接近大型场景(approachHint 在 spawn 时已固定为字符串)*/ <<elseif $largeScene && typeof $largeScene === "object" && $largeScene.state === "approaching">> <<set _lsHint = (typeof $largeScene.approachHint === "string") ? $largeScene.approachHint : "">> <<set _vOut = _output + (_lsHint ? "<br><span style=\"opacity:0.75;font-style:italic\">" + _lsHint + "</span>" : "")>> /* 状态4:中型事件(activeEvent,无大型场景) */ <<elseif $activeEvent && $activeEvent.id>> <<if !$eventDefs>><<eventTable>><</if>> <<if $eventDefs[$activeEvent.id] && $eventDefs[$activeEvent.id].viewDesc>><<set _vOut = $eventDefs[$activeEvent.id].viewDesc>><</if>> <</if>> <<print _vOut>> <</widget>> <</nobr>>
<<nobr>> <<for _category range Object.keys($store)>> <<set _item = $store[_category].find(item => $selectitem===_itemId)>> <<if _item>> <<set _quantity=_item.quantity>> <<break>> <<endif>> <</for>> <</nobr>> <<for _i = 0; _i < _keys.length; _i++>> <<set _totalWeight += $mapinfo[_keys[_i]].weight>> <</for>> <<set _randomNum = Math.random() * _totalWeight>> <<set _cumulativeWeight = 0>> <<set _randomKey = "">> <<for _i = 0; _i < _keys.length; _i++>> <<set _cumulativeWeight += $mapinfo[_keys[_i]].weight>> <<if _randomNum < _cumulativeWeight>> <<set $maptype = _keys[_i]>> <<set $mapnow = 0>> <<set $map = 0>> <<break>> <</if>> <</for>>
<<nobr>> <<widget "disassemble">> <<set _ds_id = $args[0]>> <<set _ds_isNpc = ($args[1] === true)>> <<set _ds_def = State.variables.items[_ds_id]>> <<if !_ds_def>> <<set $lastDisassembleText = "未知物品。">> <<else>> <<set _ds_type = _ds_def.type>> <<set _ds_idx = -1>> <<if $store[_ds_type]>> <<for _ds_i = 0; _ds_i < $store[_ds_type].length; _ds_i++>> <<if $store[_ds_type][_ds_i].id === _ds_id>> <<set _ds_idx = _ds_i>> <<break>> <</if>> <</for>> <</if>> <<if _ds_idx < 0 || $store[_ds_type][_ds_idx].quantity <= 0>> <<set $lastDisassembleText = "仓库中没有 " + _ds_def.name + "。">> <<else>> <<set _ds_rules = State.variables.disassemblyRules[_ds_id]>> <<if !_ds_rules>> <<set $lastDisassembleText = _ds_def.name + " 无法分解。">> <<else>> /* 直接扣除 */ <<set $store[_ds_type][_ds_idx].quantity -= 1>> <<set _ds_log = "分解 " + _ds_def.name + ",获得:">> <<set _ds_got = false>> <<set _ds_rares = []>> <<for _di = 0; _di < _ds_rules.length; _di++>> <<set _dr = _ds_rules[_di]>> <<set _dq = 0>> <<if _dr.chance !== undefined>> <<if Math.random() < _dr.chance>> <<if _dr.minQty !== undefined && _dr.maxQty !== undefined>> <<set _dq = Math.floor(Math.random() * (_dr.maxQty - _dr.minQty + 1)) + _dr.minQty>> <<else>> <<set _dq = 1>> <</if>> <</if>> <<else>> <<set _dq = Math.floor(Math.random() * (_dr.maxQty - _dr.minQty + 1)) + _dr.minQty>> <</if>> <<if _dq > 0>> <<additem _dr.id _dq>> <<set _ds_got = true>> <<set _out_name = State.variables.items[_dr.id] ? State.variables.items[_dr.id].name : _dr.id>> <<if _dr.rare>> <<run _ds_rares.push(_out_name + "×" + _dq)>> <<else>> <<set _ds_log += _out_name + "×" + _dq + " ">> <</if>> <</if>> <</for>> <<if !_ds_got>> <<set _ds_log += "(无)">> <</if>> <<if _ds_rares.length > 0>> <<set _ds_log += " ★稀有:" + _ds_rares.join("、")>> <</if>> /* 时间消耗:拆解耗时 15-30 分钟 */ <<set _ds_time = Math.floor(Math.random() * 16) + 15>> <<if !_ds_isNpc>><<set $timepass += _ds_time>><<time>><</if>> /* 体力消耗:消耗 2-5 点体力 */ <<set _ds_pow = Math.floor(Math.random() * 4) + 2>> <<if !_ds_isNpc>> <<set $power -= _ds_pow>> <<if $power < 0>><<set $power = 0>><</if>> <</if>> <<set _ds_log += "(耗时" + _ds_time + "分钟,消耗体力" + _ds_pow + "点">> /* 小概率划伤 15% */ <<if !_ds_isNpc && Math.random() < 0.15>> <<set _ds_cut = Math.floor(Math.random() * 4) + 1>> <<set $life -= _ds_cut>> <<if $life < 0>><<set $life = 0>><</if>> <<set _ds_log += ",操作时被划伤失去" + _ds_cut + "点生命">> <</if>> <<set _ds_log += ")">> <<set $lastDisassembleText = _ds_log>> <</if>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<set _vDef = State.variables.items[$selectitem]>> <<finditem State.variables.store $selectitem>> <<set _vEntry = _foundItem>> <<if !$lastTakeText>><<set $lastTakeText = "">><</if>> <div class="item-detail"> <div class="item-detail-name"><<print _vDef.name>></div> <div class="item-detail-meta"> <<if _vDef.element>><span class="ether-badge <<print _vDef.element === '水' ? 'water' : (_vDef.element === '火' ? 'fire' : (_vDef.element === '土' ? 'earth' : 'wind'))>>"><<print _vDef.element>></span><</if>> <<if _vDef.form>><span class="form-badge"><<print _vDef.form>></span><</if>> <<if _vDef.rarity>><span class="item-tag rare"><<print _vDef.rarity>></span><</if>> <span style="color:var(--bone-dim);font-size:0.72rem;"><<print _vDef.type>><<if _vDef.subtype>> · <<print _vDef.subtype>><</if>></span> </div> <<if _vDef.desc>> <p style="font-size:0.85rem;line-height:1.7;color:var(--bone-dim);margin:0.6rem 0 0.4rem;border-left:2px solid var(--border);padding-left:0.8rem;"><<print _vDef.desc>></p> <</if>> <<if _vEntry>> <p style="font-size:0.82rem;color:var(--bone-dim);">库存:<strong><<print _vEntry.quantity>></strong></p> <</if>> </div> <<set _canDisassemble = State.variables.disassemblyRules[$selectitem] !== undefined>> <<if _canDisassemble>> <<set _dsFlav = State.variables.disassemblyFlavors>> <<if _dsFlav>> <<set _flav_key = (_vDef.subtype && _dsFlav[_vDef.subtype]) ? _vDef.subtype : (_dsFlav[_vDef.type] ? _vDef.type : "")>> <<if _flav_key>> <p style="font-size:0.8rem;color:var(--bone-dim);font-style:italic;margin:0.3rem 0;"><<print _dsFlav[_flav_key]>></p> <</if>> <</if>> <<link "分解一个">> <<set $lastTakeText = "">> <<disassemble $selectitem>> <<goto "仓库物品页面">> <</link>> <</if>> <<if $lastDisassembleText>> <div class="event-result"><<print $lastDisassembleText>></div> <<set $lastDisassembleText = "">> <</if>> <<if $lastTakeText>> <div class="event-result"><<print $lastTakeText>></div> <<set $lastTakeText = "">> <</if>> <div class="action-row"> <<link "取出 1 份">><<take $selectitem 1>><<goto "仓库物品页面">><</link>> <<link "取出全部">><<takeAll $selectitem>><<goto "仓库物品页面">><</link>> </div> [[返回仓库|store]] <</nobr>>
<<widget "navigate">> <<nobr>> <<if $args[0] === "go">> /* 如果目标片段不是特殊片段,则记录当前片段 */ <<if !$specialPassages.includes(passage())>> <<set $returnPassage = passage()>> /* 记录当前片段 */ <</if>> <<goto $args[1]>> /* 跳转到目标片段 */ <<elseif $args[0] === "back">> /* 返回记录的片段 */ <<if $returnPassage>> <<goto $returnPassage>> /* 返回记录的片段 */ <<else>> <<print "无法返回,未记录原片段。">> <<endif>> <<else>> <<print "无效的导航指令。">> <<endif>> <</nobr>> <</widget>>
<<nobr>> <<set _bp = State.variables.backpack>> <<set _bpitems = State.variables.items>> <<set _bp_cats = Object.keys(_bp)>> <<set _bp_anyContent = false>> <<for _bci = 0; _bci < _bp_cats.length; _bci++>> <<set _bc = _bp_cats[_bci]>> <<set _bval = _bp[_bc]>> <<set _bHas = false>> <<if Array.isArray(_bval)>> <<if _bval.filter(x => x.quantity > 0).length > 0>> <<set _bHas = true>> <</if>> <</if>> <<if _bHas>> <<set _bp_anyContent = true>> <div class="inv-category"><<print _bc>></div> <<set _bfilled = _bval.filter(x => x.quantity > 0)>> <div class="inv-grid"> <<for _bii = 0; _bii < _bfilled.length; _bii++>> <<capture _bii, _bfilled>> <<set _bentry = _bfilled[_bii]>> <<set _bdef = _bpitems[_bentry.id]>> <<if _bdef>> <span class="inv-item"><<link _bdef.name>> <<set $selectitem = _bentry.id>> <<set $selectsource = "backpack">> <<goto "背包物品页面">> <</link>><span class="item-qty">×<<print _bentry.quantity>><<freshnessTag _bentry>></span></span> <<else>> <span class="inv-item" style="color:var(--bone-dim);font-size:0.75rem;">?未知(<<print _bentry.id>>)×<<print _bentry.quantity>></span> <</if>> <</capture>> <</for>> </div> <</if>> <</for>> <<if !_bp_anyContent>> <p style="color:var(--bone-dim);font-size:0.85rem;">背包是空的。</p> <</if>> <</nobr>> <<link "关闭背包">><<navigate "back">><</link>>
拆解定义 <<set $disassemblyRules = { /* ══ 鱼类 ══ */ "salmon": [ { id: "fish_meat", minQty: 2, maxQty: 4 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_blood", minQty: 1, maxQty: 1 }, { id: "fish_scale", minQty: 1, maxQty: 3 }, { id: "fish_roe", minQty: 0, maxQty: 2, chance: 0.4 }, { id: "fish_liver", minQty: 0, maxQty: 1, chance: 0.3 }, /* 稀有产物 */ { id: "pearl_dust", minQty: 1, maxQty: 1, chance: 0.02, rare: true } ], "seabass": [ { id: "fish_meat", minQty: 2, maxQty: 3 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_blood", minQty: 1, maxQty: 1 }, { id: "fish_scale", minQty: 1, maxQty: 2 }, { id: "gill_membrane", minQty: 0, maxQty: 1, chance: 0.5 } ], "tuna": [ { id: "fish_meat", minQty: 4, maxQty: 7 }, { id: "fish_bone", minQty: 2, maxQty: 3 }, { id: "fish_blood", minQty: 2, maxQty: 3 }, { id: "fish_scale", minQty: 1, maxQty: 3 }, { id: "fish_liver", minQty: 1, maxQty: 1 }, { id: "swim_bladder", minQty: 0, maxQty: 1, chance: 0.6 }, /* 稀有 */ { id: "deep_eye", minQty: 1, maxQty: 1, chance: 0.015, rare: true } ], "sardine": [ { id: "fish_meat", minQty: 1, maxQty: 1 }, { id: "fish_bone", minQty: 1, maxQty: 1 }, { id: "fish_blood", minQty: 0, maxQty: 1, chance: 0.5 } ], "herring": [ { id: "fish_meat", minQty: 1, maxQty: 1 }, { id: "fish_bone", minQty: 1, maxQty: 1 }, { id: "fish_roe", minQty: 0, maxQty: 1, chance: 0.35 } ], "grouper": [ { id: "fish_meat", minQty: 2, maxQty: 4 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_blood", minQty: 1, maxQty: 2 }, { id: "gill_membrane", minQty: 1, maxQty: 1 }, { id: "fish_scale", minQty: 2, maxQty: 3 } ], "mahi": [ { id: "fish_meat", minQty: 3, maxQty: 5 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_blood", minQty: 1, maxQty: 2 }, { id: "fin_membrane", minQty: 1, maxQty: 2 }, { id: "fish_scale", minQty: 2, maxQty: 4 } ], "cod": [ { id: "fish_meat", minQty: 2, maxQty: 4 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_liver", minQty: 1, maxQty: 1 }, { id: "swim_bladder", minQty: 0, maxQty: 1, chance: 0.55 } ], "eel": [ { id: "fish_meat", minQty: 1, maxQty: 3 }, { id: "fish_blood", minQty: 1, maxQty: 2 }, { id: "bile", minQty: 0, maxQty: 1, chance: 0.4 }, /* 稀有 */ { id: "current_stone", minQty: 1, maxQty: 1, chance: 0.025, rare: true } ], "flounder": [ { id: "fish_meat", minQty: 2, maxQty: 3 }, { id: "fish_bone", minQty: 1, maxQty: 1 }, { id: "fish_scale", minQty: 2, maxQty: 4 }, { id: "sand_extract", minQty: 0, maxQty: 1, chance: 0.3 } ], "mackerel": [ { id: "fish_meat", minQty: 1, maxQty: 3 }, { id: "fish_bone", minQty: 1, maxQty: 1 }, { id: "fish_blood", minQty: 1, maxQty: 1 }, { id: "fish_scale", minQty: 1, maxQty: 2 } ], "bream": [ { id: "fish_meat", minQty: 2, maxQty: 3 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_scale", minQty: 2, maxQty: 3 }, { id: "fish_roe", minQty: 0, maxQty: 2, chance: 0.45 } ], "anchovy": [ { id: "fish_meat", minQty: 1, maxQty: 1 }, { id: "fish_bone", minQty: 1, maxQty: 1 } ], "barracuda": [ { id: "fish_meat", minQty: 2, maxQty: 4 }, { id: "fish_bone", minQty: 2, maxQty: 3 }, { id: "fish_blood", minQty: 2, maxQty: 3 }, { id: "bile", minQty: 1, maxQty: 1 } ], "hairtail": [ { id: "fish_meat", minQty: 2, maxQty: 3 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_scale", minQty: 3, maxQty: 5 }, { id: "char_scale", minQty: 0, maxQty: 1, chance: 0.2 } ], "sunfish": [ { id: "fish_meat", minQty: 5, maxQty: 9 }, { id: "fish_bone", minQty: 2, maxQty: 3 }, { id: "fish_blood", minQty: 2, maxQty: 4 }, { id: "swim_bladder", minQty: 1, maxQty: 2 }, { id: "fin_membrane", minQty: 2, maxQty: 3 }, /* 稀有 */ { id: "deep_eye", minQty: 1, maxQty: 2, chance: 0.08, rare: true }, { id: "pearl_dust", minQty: 1, maxQty: 1, chance: 0.05, rare: true } ], "anglerfish": [ { id: "fish_meat", minQty: 2, maxQty: 4 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "bile", minQty: 1, maxQty: 2 }, { id: "fish_liver", minQty: 1, maxQty: 1 }, /* 稀有 */ { id: "deep_eye", minQty: 1, maxQty: 1, chance: 0.12, rare: true }, { id: "ember_crystal", minQty: 1, maxQty: 1, chance: 0.03, rare: true } ], "seahorse": [ { id: "fish_bone", minQty: 1, maxQty: 1 }, { id: "fish_blood", minQty: 1, maxQty: 1 }, /* 稀有 */ { id: "current_stone", minQty: 1, maxQty: 1, chance: 0.08, rare: true }, { id: "pearl_dust", minQty: 1, maxQty: 1, chance: 0.1, rare: true } ], /* ══ 贝类 ══ */ "scallop": [ { id: "shell_meat", minQty: 1, maxQty: 2 }, { id: "shell_frag", minQty: 1, maxQty: 2 }, { id: "shell_powder",minQty: 0, maxQty: 1, chance: 0.4 } ], "clam": [ { id: "shell_meat", minQty: 1, maxQty: 1 }, { id: "shell_frag", minQty: 1, maxQty: 2 }, { id: "pearl", minQty: 1, maxQty: 1, chance: 0.05, rare: true } ], "oyster": [ { id: "shell_meat", minQty: 1, maxQty: 1 }, { id: "shell_frag", minQty: 1, maxQty: 1 }, { id: "pearl", minQty: 1, maxQty: 1, chance: 0.08, rare: true }, { id: "blackpearl", minQty: 1, maxQty: 1, chance: 0.01, rare: true } ], "mussel": [ { id: "shell_meat", minQty: 1, maxQty: 2 }, { id: "shell_frag", minQty: 1, maxQty: 2 } ], "conch": [ { id: "shell_meat", minQty: 1, maxQty: 2 }, { id: "shell_frag", minQty: 1, maxQty: 1 }, { id: "shell_powder",minQty: 1, maxQty: 2 } ], /* ══ 虾蟹类 ══ */ "prawn": [ { id: "shrimp_meat", minQty: 1, maxQty: 2 }, { id: "shell_frag", minQty: 0, maxQty: 1, chance: 0.5 } ], "lobster": [ { id: "shrimp_meat", minQty: 2, maxQty: 4 }, { id: "crab_shell", minQty: 1, maxQty: 2 }, { id: "shell_powder",minQty: 0, maxQty: 1, chance: 0.3 } ], "mantisshrimp": [ { id: "shrimp_meat", minQty: 1, maxQty: 2 }, { id: "crab_shell", minQty: 1, maxQty: 1 } ], "sweetshrimp": [ { id: "shrimp_meat", minQty: 1, maxQty: 1 } ], "cherryshrimp": [ { id: "shrimp_meat", minQty: 1, maxQty: 1 } ], "kingcrab": [ { id: "crab_meat", minQty: 3, maxQty: 5 }, { id: "crab_shell", minQty: 2, maxQty: 3 }, { id: "shell_powder",minQty: 1, maxQty: 2 }, /* 稀有 */ { id: "ember_crystal", minQty: 1, maxQty: 1, chance: 0.03, rare: true } ], "snowcrab": [ { id: "crab_meat", minQty: 2, maxQty: 4 }, { id: "crab_shell", minQty: 2, maxQty: 3 }, { id: "shell_powder",minQty: 1, maxQty: 1 } ], "bluecrab": [ { id: "crab_meat", minQty: 1, maxQty: 3 }, { id: "crab_shell", minQty: 1, maxQty: 2 } ], "swimmingcrab": [ { id: "crab_meat", minQty: 1, maxQty: 3 }, { id: "crab_shell", minQty: 1, maxQty: 2 } ], "flowercrab": [ { id: "crab_meat", minQty: 1, maxQty: 2 }, { id: "crab_shell", minQty: 1, maxQty: 2 }, { id: "coral_frag", minQty: 0, maxQty: 1, chance: 0.25 } ], "redcrab": [ { id: "crab_meat", minQty: 1, maxQty: 2 }, { id: "crab_shell", minQty: 1, maxQty: 2 }, { id: "coral_frag", minQty: 0, maxQty: 1, chance: 0.35 } ], /* ══ 头足类 ══ */ "squid": [ { id: "octopus_meat",minQty: 1, maxQty: 3 }, { id: "fish_blood", minQty: 1, maxQty: 1 }, { id: "fin_membrane",minQty: 1, maxQty: 2 }, { id: "air_sac", minQty: 0, maxQty: 1, chance: 0.5 } ], "cuttlefish": [ { id: "octopus_meat",minQty: 1, maxQty: 2 }, { id: "fish_blood", minQty: 1, maxQty: 2 }, { id: "shell_frag", minQty: 1, maxQty: 1 }, /* 乌贼骨 */ { id: "seawater_ext",minQty: 0, maxQty: 1, chance: 0.4 } ], "octopus": [ { id: "octopus_meat",minQty: 2, maxQty: 4 }, { id: "fish_blood", minQty: 1, maxQty: 2 }, { id: "gill_membrane",minQty:0, maxQty: 1, chance: 0.4 }, /* 稀有 */ { id: "deep_eye", minQty: 1, maxQty: 1, chance: 0.04, rare: true } ], /* ══ 棘皮/其他 ══ */ "seaurchin": [ { id: "urchin_roe", minQty: 1, maxQty: 2 }, { id: "urchin_spine_core", minQty: 1, maxQty: 1 }, { id: "shell_powder",minQty: 1, maxQty: 2 } ], "starfish": [ { id: "shell_frag", minQty: 1, maxQty: 2 }, { id: "bone_ash", minQty: 0, maxQty: 1, chance: 0.4 }, /* 稀有 */ { id: "current_stone",minQty:1, maxQty: 1, chance: 0.02, rare: true } ], "jellyfish": [ { id: "seajelly", minQty: 1, maxQty: 2 }, { id: "jellyfilm", minQty: 1, maxQty: 1 }, { id: "jellyfluid", minQty: 0, maxQty: 1, chance: 0.6 } ], /* ══ 藻类 ══ */ "kelp": [ { id: "dried_kelp", minQty: 1, maxQty: 3 }, { id: "kelp_fiber", minQty: 1, maxQty: 2 }, { id: "seawater_ext",minQty: 0, maxQty: 1, chance: 0.3 } ], "wakame": [ { id: "dried_kelp", minQty: 1, maxQty: 2 }, { id: "kelp_fiber", minQty: 1, maxQty: 1 } ], "nori": [ { id: "dried_nori", minQty: 1, maxQty: 2 }, { id: "seagrass_str",minQty: 0, maxQty: 1, chance: 0.5 } ], "agarcoral": [ { id: "dried_nori", minQty: 1, maxQty: 1 }, { id: "coral_frag", minQty: 1, maxQty: 1 }, { id: "shell_powder",minQty: 0, maxQty: 1, chance: 0.4 } ], /* ══ 残骸 ══ */ "wreck_steel": [ { id: "metal", minQty: 2, maxQty: 5 }, { id: "iron", minQty: 0, maxQty: 2, chance: 0.4 }, { id: "glass", minQty: 0, maxQty: 2, chance: 0.3 }, { id: "rubber_seal", minQty: 0, maxQty: 1, chance: 0.2 } ], "wreck_wood": [ { id: "wood", minQty: 2, maxQty: 5 }, { id: "rope", minQty: 0, maxQty: 2, chance: 0.5 }, { id: "coal", minQty: 0, maxQty: 2, chance: 0.3 } ], "god_bone_frag": [ { id: "bone_ash", minQty: 1, maxQty: 2 }, { id: "fish_bone", minQty: 1, maxQty: 3 }, /* 稀有 */ { id: "ember_crystal",minQty:1, maxQty: 1, chance: 0.06, rare: true }, { id: "god_ember", minQty: 1, maxQty: 1, chance: 0.008, rare: true } ], "creature_husk": [ { id: "crab_shell", minQty: 1, maxQty: 2 }, { id: "bone_ash", minQty: 1, maxQty: 2 }, { id: "bile", minQty: 0, maxQty: 1, chance: 0.5 }, /* 稀有 */ { id: "deep_eye", minQty: 1, maxQty: 1, chance: 0.05, rare: true } ] }>>
描写天窗外的水下景象与光线变化。 [[← 返回|炼金室]]
<<nobr>> <<widget "take">> <<set _tk_id = $args[0]>> <<set _tk_qty = $args[1]>> <<set _tk_def = State.variables.items[_tk_id]>> <<if !_tk_def>> <<print "错误:未知物品 " + _tk_id>> <<else>> <<set _tk_type = _tk_def.type>> /* 在仓库找索引 */ <<set _tk_stIdx = -1>> <<if $store[_tk_type]>> <<for _tk_i = 0; _tk_i < $store[_tk_type].length; _tk_i++>> <<if $store[_tk_type][_tk_i].id === _tk_id>> <<set _tk_stIdx = _tk_i>> <<break>> <</if>> <</for>> <</if>> <<if _tk_stIdx < 0 || $store[_tk_type][_tk_stIdx].quantity < _tk_qty>> <<print "仓库中 " + _tk_def.name + " 数量不足">> <<else>> /* 记录来源条目的 addedDay */ <<set _tk_srcDay = $store[_tk_type][_tk_stIdx].addedDay>> /* 从仓库扣除 */ <<set $store[_tk_type][_tk_stIdx].quantity -= _tk_qty>> /* 向背包添加:按 addedDay 分批 */ <<if !$backpack[_tk_type]>><<set $backpack[_tk_type] = []>><</if>> <<set _tk_bpIdx = -1>> <<for _tk_i = 0; _tk_i < $backpack[_tk_type].length; _tk_i++>> <<set _tk_bpe = $backpack[_tk_type][_tk_i]>> <<if _tk_bpe.id === _tk_id>> <<if (!_tk_srcDay && !_tk_bpe.addedDay) || _tk_bpe.addedDay === _tk_srcDay>> <<set _tk_bpIdx = _tk_i>> <<break>> <</if>> <</if>> <</for>> <<if _tk_bpIdx >= 0>> <<set $backpack[_tk_type][_tk_bpIdx].quantity += _tk_qty>> <<else>> <<set _tk_newEntry = { id: _tk_id, quantity: _tk_qty }>> <<if _tk_srcDay>><<set _tk_newEntry.addedDay = _tk_srcDay>><</if>> <<run State.variables.backpack[_tk_type].push(_tk_newEntry)>> <</if>> <<print "取出 " + _tk_qty + " × " + _tk_def.name>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "put">> <<set _pt_id = $args[0]>> <<set _pt_qty = $args[1]>> <<set _pt_def = State.variables.items[_pt_id]>> <<if !_pt_def>> <<print "错误:未知物品 " + _pt_id>> <<else>> <<set _pt_type = _pt_def.type>> /* 在背包中找索引 */ <<set _pt_bpIdx = -1>> <<if $backpack[_pt_type]>> <<for _pt_i = 0; _pt_i < $backpack[_pt_type].length; _pt_i++>> <<if $backpack[_pt_type][_pt_i].id === _pt_id>> <<set _pt_bpIdx = _pt_i>> <<break>> <</if>> <</for>> <</if>> <<if _pt_bpIdx < 0 || $backpack[_pt_type][_pt_bpIdx].quantity < _pt_qty>> <<print "背包中 " + _pt_def.name + " 数量不足">> <<else>> /* 从背包扣除 */ <<set $backpack[_pt_type][_pt_bpIdx].quantity -= _pt_qty>> /* 直接向仓库添加(不经过 additem,避免 $storeUsed 未初始化问题) */ <<if !$store[_pt_type]>> <<set $store[_pt_type] = []>> <</if>> <<set _pt_stIdx = -1>> <<for _pt_i = 0; _pt_i < $store[_pt_type].length; _pt_i++>> /* 同天入库的批次合并,否则新建(支持腐败分批) */ <<set _pt_ent = $store[_pt_type][_pt_i]>> <<if _pt_ent.id === _pt_id && (!_pt_ent.addedDay || !$backpack[_pt_type][_pt_bpIdx].addedDay || _pt_ent.addedDay === $backpack[_pt_type][_pt_bpIdx].addedDay)>> <<set _pt_stIdx = _pt_i>> <<break>> <</if>> <</for>> <<if _pt_stIdx >= 0>> <<set $store[_pt_type][_pt_stIdx].quantity += _pt_qty>> <<else>> <<set _pt_newEntry = { id: _pt_id, quantity: _pt_qty }>> <<if $backpack[_pt_type][_pt_bpIdx].addedDay>> <<set _pt_newEntry.addedDay = $backpack[_pt_type][_pt_bpIdx].addedDay>> <</if>> <<run State.variables.store[_pt_type].push(_pt_newEntry)>> <</if>> <<print "放回 " + _pt_qty + " × " + _pt_def.name>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<set _bvDef = State.variables.items[$selectitem]>> <<finditem State.variables.backpack $selectitem>> <<set _bvEntry = _foundItem>> <<if !$lastTakeText>><<set $lastTakeText = "">><</if>> <<if !_bvDef>> <p style="color:var(--danger-bright);">物品数据缺失(ID:<<print $selectitem>>)</p> [[返回背包|backpack]] <<else>> <div class="item-detail"> <div class="item-detail-name"><<print _bvDef.name>></div> <div class="item-detail-meta"> <<if _bvDef.element>><span class="ether-badge <<print _bvDef.element === '水' ? 'water' : (_bvDef.element === '火' ? 'fire' : (_bvDef.element === '土' ? 'earth' : 'wind'))>>"><<print _bvDef.element>></span><</if>> <<if _bvDef.form>><span class="form-badge"><<print _bvDef.form>></span><</if>> <<if _bvDef.rarity>><span class="item-tag rare"><<print _bvDef.rarity>></span><</if>> <span style="color:var(--bone-dim);font-size:0.72rem;"><<print _bvDef.type>><<if _bvDef.subtype>> · <<print _bvDef.subtype>><</if>></span> </div> <<if _bvDef.desc>> <p style="font-size:0.85rem;line-height:1.7;color:var(--bone-dim);margin:0.6rem 0 0.4rem;border-left:2px solid var(--border);padding-left:0.8rem;"><<print _bvDef.desc>></p> <</if>> <<if _bvEntry>> <p style="font-size:0.82rem;color:var(--bone-dim);">持有:<strong><<print _bvEntry.quantity>></strong></p> <</if>> </div> <<if $lastTakeText>> <div class="event-result"><<print $lastTakeText>></div> <<set $lastTakeText = "">> <</if>> <div class="action-row"> <<link "放回仓库 1 份">><<put $selectitem 1>><<goto "背包物品页面">><</link>> <<link "全部放回">><<putAll $selectitem>><<goto "背包物品页面">><</link>> </div> <<if _bvEntry && _bvEntry.addedDay !== undefined>> <<set _fi_sd = $spoilDays ? ($spoilDays[$selectitem] || 0) : 0>> <<if _fi_sd > 0>> <<set _fi_age = $day - _bvEntry.addedDay>> <<set _fi_stage = Math.floor(_fi_age / _fi_sd * 3)>> <<set _fi_left = _fi_sd - _fi_age>> <<if _fi_stage <= 0>> <p style="font-size:0.78rem;color:#8bc4a0;">✦ 新鲜 剩余约 <<print Math.max(_fi_left, 0)>> 天</p> <<elseif _fi_stage === 1>> <p style="font-size:0.78rem;color:var(--amber);">⚠ 开始变质 约 <<print Math.max(_fi_left, 0)>> 天后腐烂</p> <<elseif _fi_stage === 2>> <p style="font-size:0.78rem;color:var(--danger-bright);">⚠ 严重腐败 已超过最佳食用期</p> <</if>> <</if>> <</if>> [[返回背包|backpack]] <</if>> <</nobr>>
<<nobr>> <<widget "eventTable">> /* condition 函数已移到 checkEvent 内联,此处只保留纯数据 */ <<set $eventDefs = { "island_ruin": { tier: "medium", name: "废弃礁岛", type: "stable", desc: "声呐显示前方有一片礁岩隆起,隐约可见人工建筑的残骸。", baseChance: 0.003, actions: ["出仓探索","忽略离开"] }, "wreckage": { tier: "medium", name: "沉船残骸", type: "stable", desc: "一艘庞大的船体横卧在海床上,锈迹斑斑,但结构依然完整。", baseChance: 0.004, actions: ["出仓探索","忽略离开"] }, "god_bone_field": { tier: "medium", name: "神骨原野", type: "stable", desc: "巨大的骨骸从海床刺出,像是某种无法想象的存在留下的遗迹。安定值在这里悄悄流失。", baseChance: 0.002, sanDrain: true, actions: ["出仓探索","忽略离开"] }, "sealed_container": { tier: "small", name: "密封容器", type: "stable", desc: "一个完好的金属容器漂浮在水中,表面印着已经磨损的标志。", baseChance: 0.005, actions: ["打捞","忽略离开"] }, "creature_swarm": { tier: "small", name: "生物群聚", type: "unstable", timerRange: [120,300], desc: "大量发光生物聚集在潜艇周围,随着它们的涌动,渔获概率大幅提升。", baseChance: 0.002, actions: ["开始捕鱼","忽略继续"] }, "thermal_vent": { tier: "small", name: "热泉喷发", type: "unstable", timerRange: [60,180], desc: "海床出现热泉活动,周围水温骤升,一些深层生物被迫上浮。", baseChance: 0.0015, actions: ["采集热泉提取物","忽略继续"] }, "fog_anomaly": { tier: "small", name: "异常雾障", type: "unstable", timerRange: [180,480], desc: "一片不自然的浓雾笼罩水面,声呐出现干扰,导航精度下降。", baseChance: 0.003, actions: ["等待消散","强行穿越"] }, "mutant_creature": { tier: "small", name: "异变生物", type: "unstable", timerRange: [30,90], desc: "一个体型异常的扭曲生物正在靠近潜艇,发出不规律的声波。", baseChance: 0.004, sanDrain: true, actions: ["驱离","观察记录","紧急下潜逃离"] }, /* ─ 新增中型事件 ─ */ "thermal_field": { tier: "medium", name: "热泉群落", type: "stable", desc: "多处热液喷口同时活跃,泉口周围密布着化学合成生物群落,地温异常升高。视线被热浪扰动,隐约看见罕见矿物的结晶。", viewDesc: "泉口的热浪让视野持续扭曲,橙红色的菌席覆盖了海床,零星的结晶从泥土里刺出,像是这片海底在低语某种秘密。", baseChance: 0.002, actions: ["出仓采集","观察记录","忽略离开"] }, "salt_lake": { tier: "medium", name: "海底盐湖", type: "stable", desc: "海床上出现一片清晰的液体边界,卤水比周围海水密度更高,静静地汇聚在低洼处,边缘有奇异的白色结晶环。", viewDesc: "卤水池的边界如镜面般清晰,反射着探照灯光。池面比周围深邃,呈现出几乎黑色的浓稠质感,四周白色盐晶随水流轻颤。", baseChance: 0.0015, actions: ["采集卤水样本","靠近探查边缘","忽略离开"] }, "biolum_bloom": { tier: "medium", name: "发光生物潮", type: "unstable", timerRange: [300, 900], desc: "大量发光浮游生物形成光毯,视野范围内一片蓝白色的流动光芒,能见度异常增加,但也会引来捕食者。", viewDesc: "无数微小的蓝白光点在水中漂流,连成流动的光幕,光线从四面八方涌来,这一刻的深海像是有了自己的极光。", baseChance: 0.002, actions: ["利用光照捕捞","静待观察","加速离开"] }, "debris_field": { tier: "medium", name: "沉降残骸带", type: "stable", desc: "大量混杂物从某处上方缓缓沉降——金属碎片、木料、绳索、不明容器,来源不明,物品密集到影响行进。", viewDesc: "各种残骸在水中缓慢旋转下落,探照灯在碎片间投下复杂的阴影,这片区域像是某场灾难留下的无声注脚。", baseChance: 0.003, actions: ["停船打捞","穿越残骸带","绕行离开"] }, "giant_kelp": { tier: "medium", name: "巨藻密林", type: "stable", desc: "前方出现一片极为密集的巨藻群落,藻茎粗如人臂,高度超出声呐可测范围,构成几乎不透光的立体迷宫。", viewDesc: "巨藻茎干如柱林排列,遮蔽了一切远处的光线,只有头顶隐约透下零碎的光晕,探照灯在藻茎间切出一道明亮的狭长光柱。", baseChance: 0.002, actions: ["进入采集","寻找通道穿越","绕行"] }, "hunting_pack": { tier: "medium", name: "捕猎者群体", type: "unstable", timerRange: [120, 360], desc: "声呐捕捉到大量高速移动的生物信号,是一群正在追逐猎物的顶级捕食者——跟随或许能收获猎物残余。", viewDesc: "几道矫健的身影在远处高速穿梭,偶尔能看到它们绕到光柱边缘的轮廓,然后又消失进黑暗——整片水域因此产生了一种不安的颤动。", baseChance: 0.0018, sanDrain: true, actions: ["尾随跟踪","驱赶猎食","立刻撤离"] } } >> <</widget>> <</nobr>>
<<nobr>> <<if !$shipSystems>> <<set $shipSystems = { propulsion:true, fishing:true, oxygen:true, heating:true, storage:true }>> <</if>> <<if !$shipUpgrades>> <<set $shipUpgrades = { speed:0, armor:0, insulation:0, capacity:0, sonar:0 }>> <</if>> <<if !$shipOxygen>><<set $shipOxygen = 100>><</if>> <<set _sh_hcol = $shell < 25 ? "var(--danger-bright)" : $shell < 50 ? "var(--amber)" : "var(--teal-bright)">> <<set _sh_fcol = $fuel < 5000 ? "var(--danger-bright)" : $fuel < 15000 ? "var(--amber)" : "var(--bone-dim)">> <<set _sh_ocol = $shipOxygen < 20 ? "var(--danger-bright)" : $shipOxygen < 50 ? "var(--amber)" : "var(--bone-dim)">> <<set _sh_fpct = Math.floor($fuel / ($fuelMax||300) * 100)>> <div style="font-size:0.9rem;color:var(--amber-bright);margin-bottom:0.7rem;letter-spacing:0.05em;">载具状态</div> <div style="font-size:0.82rem;line-height:2;color:var(--bone-dim);"> <div> 船体耐久 <span style="color:<<print _sh_hcol>>;"><<print Math.round($shell*10)/10>></span>/100 <span style="display:inline-block;background:var(--bg-panel);border:1px solid var(--border);width:80px;height:8px;border-radius:4px;vertical-align:middle;overflow:hidden;margin-left:0.4rem;"> <span style="display:block;height:100%;width:<<print $shell>>%;background:<<print _sh_hcol>>;"></span> </span> </div> <div> 燃料储量 <span style="color:<<print _sh_fcol>>;"><<print _sh_fpct>>%</span> (<<print Math.floor($fuel/1000)>>k) <span style="display:inline-block;background:var(--bg-panel);border:1px solid var(--border);width:80px;height:8px;border-radius:4px;vertical-align:middle;overflow:hidden;margin-left:0.4rem;"> <span style="display:block;height:100%;width:<<print _sh_fpct>>%;background:<<print _sh_fcol>>;"></span> </span> </div> <div> 供氧储备 <span style="color:<<print _sh_ocol>>;"><<print $shipOxygen>></span>/100 </div> </div> <div style="height:1px;background:var(--border-dim);margin:0.6rem 0;"></div> <div style="font-size:0.78rem;color:var(--bone-dim);margin-bottom:0.3rem;">子系统</div> <div style="font-size:0.8rem;line-height:1.9;"> <<set _sys_names = [["propulsion","推进系统"],["fishing","捕鱼系统"],["oxygen","供氧系统"],["heating","供暖系统"],["storage","仓储系统"]]>> <<for _shi = 0; _shi < _sys_names.length; _shi++>> <<set _syk = _sys_names[_shi][0]>> <<set _syn = _sys_names[_shi][1]>> <<set _syok = $shipSystems[_syk]>> <div> <span style="color:<<print _syok ? 'var(--teal-bright)' : 'var(--danger-bright)'>>;"><<print _syok ? "●" : "✕">></span> <<capture _syk, _syn>><<link _syn>><<set $selectShipSystem = _syk>><<goto "船只系统详情">><</link>><</capture>> </div> <</for>> </div> <div style="height:1px;background:var(--border-dim);margin:0.6rem 0;"></div> <div style="font-size:0.78rem;color:var(--bone-dim);margin-bottom:0.3rem;">升级等级</div> <div style="font-size:0.78rem;line-height:1.9;color:var(--bone-dim);"> <<set _upg_names = [["speed","航速"],["armor","装甲"],["insulation","隔热"],["capacity","容量"],["sonar","声呐"]]>> <<for _upi = 0; _upi < _upg_names.length; _upi++>> <<set _upk = _upg_names[_upi][0]>> <<set _uln = _upg_names[_upi][1]>> <<set _ulv = $shipUpgrades[_upk] || 0>> <div> <<capture _upk, _uln, _ulv>><<link _uln>><<set $selectShipUpgrade = _upk>><<goto "船只升级详情">><</link>><</capture>> <<for _ulvi = 0; _ulvi < 3; _ulvi++>><<print _ulvi < _ulv ? "◆" : "◇">><</for>> <span style="opacity:0.6;font-size:0.72rem;"> Lv.<<print _ulv>></span> </div> <</for>> </div> <<if $shell < 50>> <div style="margin-top:0.6rem;font-size:0.78rem;color:var(--danger-bright);border:1px solid var(--danger-bright);padding:0.3rem 0.6rem;border-radius:4px;"> ⚠ 船体耐久不足,需要尽快进行维修。 </div> <</if>> <<if $fuel < 5000>> <div style="margin-top:0.4rem;font-size:0.78rem;color:var(--amber);border:1px solid var(--amber-dim);padding:0.3rem 0.6rem;border-radius:4px;"> ⚠ 燃料不足,无法长途航行。 </div> <</if>> <div class="action-row" style="margin-top:1rem;"> <<link "关闭">><<navigate "back">><</link>> </div> <</nobr>>
<<nobr>> <<if !$selectShipUpgrade>> <div style="font-size:0.88rem;color:var(--amber-bright);margin-bottom:0.5rem;">升级系统</div> <div style="font-size:0.8rem;color:var(--bone-dim);">未选择升级项目。</div> <<else>> <<set _upg_defs = { speed: { name:"航速推进", desc:"提升引擎推力,增加最高航速上限。", mats:[ ["metal",3],["gears",2],["coal",2] ] }, armor: { name:"装甲加固", desc:"强化船体外壳,增强耐久与抗压能力。", mats:[ ["metal",5],["fish_scale",3] ] }, insulation:{ name:"隔热层", desc:"减少深海环境对燃料消耗的影响。", mats:[ ["glass",2],["fish_organ",2],["ruber",2] ] }, capacity: { name:"仓储扩容", desc:"增加船内存储空间。", mats:[ ["wood",4],["metal",2],["gears",1] ] }, sonar: { name:"声呐升级", desc:"提升声呐探测范围与精度。", mats:[ ["gears",3],["glass",2],["fish_bone",2] ] } }>> <<set _ud = _upg_defs[$selectShipUpgrade]>> <<set _ulv = $shipUpgrades[$selectShipUpgrade] || 0>> <<if _ud>> <div style="font-size:0.88rem;color:var(--amber-bright);margin-bottom:0.4rem;"><<print _ud.name>></div> <div style="font-size:0.78rem;color:var(--bone-dim);margin-bottom:0.5rem;"><<print _ud.desc>></div> <div style="font-size:0.78rem;margin-bottom:0.3rem;"> 当前等级:<<for _lv=0;_lv<3;_lv++>><<print _lv < _ulv ? "◆" : "◇">><</for>> Lv.<<print _ulv>> </div> <<if _ulv >= 3>> <div style="font-size:0.8rem;color:var(--teal-bright);">已达最高等级。</div> <<else>> <div style="font-size:0.78rem;color:var(--bone-dim);margin-bottom:0.3rem;">升级所需材料:</div> <<for _mi=0; _mi < _ud.mats.length; _mi++>> <<set _mId = _ud.mats[_mi][0]>> <<set _mQty = _ud.mats[_mi][1]>> <<set _mDef = $items[_mId]>> <<set _mHave = 0>> <<finditem _mId "backpack">><<set _mHave += _found_qty>> <<finditem _mId "store">><<set _mHave += _found_qty>> <<set _mEnough = _mHave >= _mQty>> <div style="font-size:0.78rem;<<print _mEnough ? 'color:var(--teal-bright)' : 'color:var(--danger-bright)'>>;"> <<print _mDef ? _mDef.name : _mId>> ×<<print _mQty>>(持有:<<print _mHave>>) </div> <</for>> <div style="margin-top:0.5rem;"> <<link "确认升级">> <<set _canUpgrade = true>> <<for _cmi=0; _cmi < _ud.mats.length; _cmi++>> <<set _cmId = _ud.mats[_cmi][0]>> <<set _cmQty = _ud.mats[_cmi][1]>> <<set _cmHave = 0>> <<finditem _cmId "backpack">><<set _cmHave += _found_qty>> <<finditem _cmId "store">><<set _cmHave += _found_qty>> <<if _cmHave < _cmQty>><<set _canUpgrade = false>><</if>> <</for>> <<if _canUpgrade>> <<for _rmi=0; _rmi < _ud.mats.length; _rmi++>> <<set _rmId = _ud.mats[_rmi][0]>> <<set _rmQty = _ud.mats[_rmi][1]>> <<removeitem _rmId _rmQty "backpack">> <<removeitem _rmId _rmQty "store">> <</for>> <<set $shipUpgrades[$selectShipUpgrade] += 1>> <<else>> <<set $upgradeFailMsg = "材料不足,无法升级。">> <</if>> <<goto "船只升级详情">> <</link>> </div> <<if $upgradeFailMsg>><div style="color:var(--danger-bright);font-size:0.78rem;margin-top:0.3rem;"><<print $upgradeFailMsg>><<set $upgradeFailMsg = "">></div><</if>> <</if>> <<else>> <div style="font-size:0.8rem;color:var(--bone-dim);">未知升级项目。</div> <</if>> <</if>> <div style="margin-top:1rem;">[[← 返回载具|ship]]</div> <</nobr>>
描写子系统详情与维修操作(占位)。 [[← 返回载具|ship]]
<<nobr>> <div id="sail-info">随着引擎轰鸣,潜艇开始了运作…</div> <<repeat 1s>> <<sail>> <<time>> <<replace "#sc-status">><<include "侧边栏状态">><</replace>> <<replace "#sail-info">> <span style="font-size:0.73rem;color:var(--bone-dim);">$showseason季 第$showday日 $showhour:$showminute 船舱$worldtem°</span><br> <<cpRoomCheck "驾驶舱">> /* ══ 舷窗 ══ */ <div style="border:1px solid var(--border-dim);border-radius:3px;padding:0.4rem 0.5rem;margin-bottom:0.35rem;font-size:0.84rem;color:var(--bone);line-height:1.85;"> <div style="margin-bottom:0.15rem;"><<view>></div> <<if $activeEvent>> <div style="margin-top:0.25rem;border-top:1px solid var(--border-dim);padding-top:0.2rem;"> <span style="color:var(--amber-bright);font-size:0.72rem;">▲ <<print $activeEvent.name>></span><<if $activeEvent.type === "unstable">><span style="color:var(--danger-bright);font-size:0.7rem;"> · 剩余<<print $eventTimer>>秒</span><</if>><br> <span style="color:var(--bone-dim);font-size:0.8rem;"><<print $activeEvent.desc>></span><br> <<for _eai = 0; _eai < $activeEvent.actions.length; _eai++>><<set _ea = $activeEvent.actions[_eai]>><<capture _ea>><<link _ea>><<resolveEvent _ea>><</link>> <</capture>><</for>> <<if $lastEventText>><div style="color:var(--teal-bright);font-size:0.75rem;margin-top:0.08rem;"><<print $lastEventText>></div><<set $lastEventText = "">><</if>> </div> <</if>> <<if $activeSmallEvent>> <<if !$smallEventDefs>><<smallEventTable>><</if>> <<set _snId = String($activeSmallEvent.id)>> <<set _snDef = $smallEventDefs[_snId]>> <<if _snDef>> <div style="margin-top:0.15rem;border-top:1px solid var(--border-dim);padding-top:0.12rem;font-size:0.76rem;"> ⚑ <<print _snDef.name>><span style="color:var(--bone-dim);font-size:0.68rem;"> · 锚定后可在探索模式处理</span> </div> <<else>><<set $activeSmallEvent = null>> <</if>> <</if>> <<if $lastSmallEventText>> <div style="margin-top:0.15rem;color:var(--bone-dim);font-size:0.78rem;"><<print $lastSmallEventText>></div> <<set $lastSmallEventText = "">> <</if>> <<if $fishing == 1>><<fish>><<fishStatus>><</if>> </div> /* ══ 仪表 ══ */ <div style="font-size:0.73rem;color:var(--bone-dim);margin-bottom:0.25rem;"> 地形:$mapinfo[$maptype].type<br>当前深度:<<print $depth>> m 可达深度:<<print $depthdeep>> m 坐标:$mapspan / $maplimspan <<set _fPct = Math.max(0,Math.min(100,Math.floor(($fuel||0)/$fuelMax*100)))>> <<set _fCol = _fPct > 40 ? "var(--teal-bright)" : _fPct > 15 ? "var(--amber)" : "var(--danger-bright)">> <div style="display:flex;align-items:center;gap:0.35rem;font-size:0.68rem;color:var(--bone-dim);margin-top:0.12rem;"> <span>⛽ 燃料</span> <div style="flex:1;height:3px;background:var(--bg-panel);border:1px solid var(--border-dim);border-radius:2px;"><div style="height:100%;width:<<print _fPct>>%;background:<<print _fCol>>;transition:width 0.5s;"></div></div> <span style="color:<<print _fCol>>;"><<print Math.floor($fuel||0)>>/<<print $fuelMax>></span> </div> <<if $temporalEvent && $temporalEvent !== 0>> <<set _teP = Math.min(100, Math.floor($temporalEvent.prog))>> ⚑ <<print $temporalEvent.name>> <span style="display:inline-block;width:3.5rem;height:3px;background:var(--bg-panel);border:1px solid var(--border-dim);vertical-align:middle;"><span style="display:block;height:100%;width:<<print _teP>>%;background:var(--amber);"></span></span> <</if>> <<if $temporalLog>><div style="color:var(--amber);margin-top:0.05rem;"><<print $temporalLog>></div><<set $temporalLog = "">><</if>> </div> /* ══ 操作台 ══ */ <div style="font-size:0.82rem;margin-bottom:0.25rem;"> /* ── 漂流警告 ── */ <<if $driftMode>> <div style="border:2px solid var(--danger-bright);padding:0.3rem 0.5rem;margin-bottom:0.25rem;font-size:0.8rem;color:var(--danger-bright);background:rgba(180,30,30,0.08);border-radius:3px;"> ‼ 燃料耗尽,引擎停转。 <span style="font-size:0.72rem;opacity:0.8;display:block;margin-top:0.06rem;">下潜已禁用。可前往供能室补充燃料后恢复航行。</span> </div> <</if>> /* 上浮:漂流时也可用 */ <<if $depth > -1>><<link "上浮">><<set $depth -= 1>><</link>><<else>><span style="opacity:0.35;">上浮</span><</if>> · <span style="color:var(--amber-bright);">$depth m</span> · <<if !$driftMode && $depth < $depthdeep>><<link "下潜">><<set $depth += 1>><</link>><<elseif $driftMode>><span style="opacity:0.25;text-decoration:line-through;">下潜</span><<else>><span style="opacity:0.35;">下潜</span><</if>> <br> <<if $sailspd > 0>><<link "减速">><<set $sailspd = Math.max($sailspd-5, 0)>><</link>><<else>><span style="opacity:0.35;">减速</span><</if>> · <span style="color:var(--amber-bright);">×$sailspd</span> · <<if $sailspd < $spdmax>><<link "加速">><<set $sailspd = Math.min($sailspd+5, $spdmax)>><</link>><<else>><span style="opacity:0.35;">加速</span><</if>> </div> /* ── 雷达:转向选择 ── */ <<if $nextAreasReady === 1>> <div style="border-left:2px solid var(--amber-dim);padding:0.25rem 0.5rem;margin-bottom:0.3rem;font-size:0.78rem;"> <div style="color:var(--amber-bright);margin-bottom:0.15rem;">雷达:前方$mapinfo[$maptype].type边缘在即</div> <<set _btnLabels = []>> <<for _nai = 0; _nai < $nextAreas.length; _nai++>> <<set _na = $nextAreas[_nai]>> <<set _btnLabels[_nai] = _na.dir + ":" + _na.label + "(" + _na.depth + "m)">> <</for>> <<for _nai = 0; _nai < $nextAreas.length; _nai++>> <<set _bl = _btnLabels[_nai]>> <<capture _nai, _bl>> <div style="line-height:1.7;"><<if $selectedNextArea === _nai>><span style="color:var(--amber-bright);">▶ <<print _bl>></span><<else>><<link _bl>><<set $selectedNextArea = _nai>><</link>><</if>></div> <</capture>> <</for>> <<if $prevArea !== null>> <<set _retLabel = "返回:" + ($mapinfo[$prevArea.type] ? $mapinfo[$prevArea.type].type : $prevArea.type)>> <div style="border-top:1px solid var(--border-dim);margin-top:0.1rem;padding-top:0.1rem;line-height:1.7;"> <<if $selectedNextArea === -1>><span style="color:var(--teal-bright);">▶ <<print _retLabel>></span><<else>><<link _retLabel>><<set $selectedNextArea = -1>><</link>><</if>> </div> <</if>> </div> <</if>> /* ══ 位置提示条(仪表盘上方,统一大中型事件) ══ */ <<set _navState = "normal">> <<if $largeScene && typeof $largeScene === "object" && $largeScene.state === "approaching">> <<set _navState = "ls_approach">> <<elseif $largeScene && typeof $largeScene === "object" && $largeScene.state === "leaving">> <<set _navState = "ls_leaving">> <<elseif $largeScene && typeof $largeScene === "object" && $largeScene.state === "active">> <<if $worldScene && $worldScene.state === "inside">> <<set _navState = "ls_zone">> <<elseif $worldScene && $worldScene.state === "approaching">> <<set _navState = "ls_zone_approach">> <<else>> <<set _navState = "ls_active">> <</if>> <<elseif $worldScene && $worldScene.state === "inside">> <<set _navState = "ws_only">> <<elseif $worldScene && $worldScene.state === "approaching">> <<set _navState = "ws_approach">> <</if>> <<if _navState !== "normal">> <div style="display:flex;align-items:center;gap:0.3rem;font-size:0.72rem;padding:0.18rem 0.4rem;margin-bottom:0.2rem;border-radius:2px;background:rgba(180,140,60,0.07);border:1px solid var(--amber-dim);"> <<if _navState === "ls_leaving">> <span style="color:var(--bone-dim);opacity:0.4;">←</span> <span style="color:var(--bone-dim);opacity:0.5;">已离开 <b style="color:var(--bone-dim);"><<print $largeScene.name>></b></span> <<elseif _navState === "ls_approach">> <span style="color:var(--amber);opacity:0.8;">▷</span> <span style="color:var(--amber-dim);">正在接近 <b style="color:var(--amber);"><<print $largeScene.name>></b></span> <<elseif _navState === "ls_active">> <span style="color:var(--amber);">◈</span> <span style="color:var(--bone-dim);">当前位于 <b style="color:var(--amber);"><<print $largeScene.name>></b></span> /* zone 标签行 */ <div style="display:flex;gap:0.25rem;flex-wrap:wrap;margin-left:0.3rem;"> <<for _lzui=0; _lzui<$largeScene.zones.length; _lzui++>> <<set _lzU=$largeScene.zones[_lzui]>><<set _lzSt=_lzU.st>> <<capture _lzU,_lzSt>> <<if _lzSt==="done">><span style="font-size:0.67rem;color:var(--bone-dim);border:1px solid var(--bone-dim);padding:0 0.18rem;border-radius:2px;opacity:0.45;">✓<<print _lzU.name>></span> <<elseif _lzSt==="arriving">><span style="font-size:0.67rem;color:var(--teal-bright);border:1px solid var(--teal-bright);padding:0 0.18rem;border-radius:2px;">▸<<print _lzU.name>></span> <<else>><span style="font-size:0.67rem;color:var(--border-dim);border:1px solid var(--border-dim);padding:0 0.18rem;border-radius:2px;"><<print _lzU.name>></span><</if>> <</capture>> <</for>> </div> <<elseif _navState === "ls_zone" || _navState === "ls_zone_approach">> <span style="color:var(--amber);">◈</span> <span style="color:var(--bone-dim);"> 当前位于 <b style="color:var(--amber);"><<print $largeScene.name>></b> <span style="opacity:0.5;margin:0 0.2rem;">·</span> <b style="color:var(--teal-bright);"><<print $worldScene.name>></b> </span> <<elseif _navState === "ws_only">> <span style="color:var(--teal-bright);">◈</span> <span style="color:var(--bone-dim);">当前位于 <b style="color:var(--teal-bright);"><<print $worldScene.name>></b></span> <<elseif _navState === "ws_approach">> <span style="color:var(--amber-dim);">▷</span> <span style="color:var(--bone-dim);">正在接近 <b style="color:var(--amber);"><<print $worldScene.name>></b> <span style="opacity:0.6;font-size:0.69rem;"> <<print $worldScene.approachDesc>></span></span> <</if>> </div> <</if>> /* ── 渔具 ── */ <div style="font-size:0.78rem;color:var(--bone-dim);margin-bottom:0.3rem;"> <<if $fishing == 0>><<link "投渔具">><<set $fishing = 1>><</link>><<else>><<link "收渔具">><<set $fishing = 0>><</link>><</if>> · <<if $fishingLight == "关闭">><<link "开灯">><<set $fishingLight = "开启">><</link>><<else>><<link "关灯">><<set $fishingLight = "关闭">><</link>><</if>> · <<link $fishingGear>><<if $fishingGear == "垂钓">><<set $fishingGear = "渔网">><<else>><<set $fishingGear = "垂钓">><</if>><</link>> · <<link $fishingBait>><<if $fishingBait == "内脏碎肉">><<set $fishingBait = "血饵">><<elseif $fishingBait == "血饵">><<set $fishingBait = "草饵">><<else>><<set $fishingBait = "内脏碎肉">><</if>><</link>> </div> /* ── 锚定按钮(中型场景inside时附加提示) ── */ <<if $worldScene && $worldScene.state === "inside">> <div style="font-size:0.73rem;color:var(--bone-dim);margin-bottom:0.1rem;">场景内有 <<print $worldScene.children.length>> 个可互动点 · 锚定后进入</div> <</if>> <div style="font-size:0.76rem;margin-bottom:0.4rem;"><<link "⚓ 锚定,切换探索模式">><<set $sailMode = "explore">><<set $sailspd = 0>><<set $lastSmallEventText = "">><<set $currentContext = "anchored">><<goto "探索">><</link>></div> /* ── 书签 ── */ <div style="font-size:0.74rem;margin-top:0.2rem;"> <<set _bmLabel = $showBookmarks ? "▾ 航行记录" : "▸ 航行记录">><<link _bmLabel>><<set $showBookmarks = !$showBookmarks>><</link>> <<if $showBookmarks>><div style="margin-top:0.2rem;max-height:10rem;overflow-y:auto;"><<bookmarkPanel>></div><</if>> </div> <<cpScene "驾驶舱">> <</replace>> <</repeat>> [[终止航行|驾驶舱][$sailspd to 0]] <</nobr>>
<<nobr>> <div id="sail-info">⚓ 锚定探索中…</div> <<repeat 1s>> <<time>> <<replace "#sc-status">><<include "侧边栏状态">><</replace>> <<replace "#sail-info">> <span style="font-size:0.73rem;color:var(--bone-dim);">$showseason季 第$showday日 $showhour:$showminute 船舱$worldtem°</span><br> /* ══ 舷窗 ══ */ <div style="border:1px solid var(--border-dim);border-radius:3px;padding:0.4rem 0.5rem;margin-bottom:0.35rem;font-size:0.84rem;color:var(--bone);line-height:1.85;"> /* 基础环境描述 */ <div style="margin-bottom:0.2rem;"><<view>></div> /* 中型场景子事件——焦点显示模式 */ <<if $worldScene && $worldScene.state === "inside">> <<if !$wsChildDefs>><<worldSceneDefs>><</if>> <div style="margin-top:0.3rem;border-top:1px solid var(--amber-dim);padding-top:0.25rem;"> /* ── 子事件状态行 ── */ <div style="display:flex;flex-wrap:wrap;gap:0.25rem 0.3rem;font-size:0.74rem;margin-bottom:0.2rem;"> <<for _wci = 0; _wci < $worldScene.children.length; _wci++>> <<set _wcid = $worldScene.children[_wci]>> <<set _wcd = $wsChildDefs[_wcid]>> <<if _wcd>> /* 判断状态 */ <<set _wcDone = false>> <<if $worldScene.doneCids>> <<for _dci2=0; _dci2 < $worldScene.doneCids.length; _dci2++>> <<if $worldScene.doneCids[_dci2] === _wcid>><<set _wcDone = true>><</if>> <</for>> <</if>> <<set _wcActive = ($wsChild && $wsChild.id === _wcid)>> <<if _wcDone>> <span style="opacity:0.3;text-decoration:line-through;">✓ <<print _wcd.name>></span> <<elseif _wcActive>> <span style="color:var(--teal-bright);">▸ <<print _wcd.name>></span> <<else>> <<capture _wcid, _wcd>> <<set _wcLinkLabel = _wcd.name>> <<link _wcLinkLabel>><<set $wsChild = {id:_wcid,name:_wcd.name,stageIdx:0,stageDesc:_wcd.stages[0].desc,actions:_wcd.stages[0].actions,lootLog:""}>><<goto "探索">><</link>> <</capture>> <</if>> <</if>> <</for>> </div> /* ── 当前焦点详情块 ── */ <<if $wsChild>> <<worldSceneDefs>> <<set _wcFocusDef = $wsChildDefs[$wsChild.id]>> <<if _wcFocusDef>> <<set _wcFocusStage = _wcFocusDef.stages[Number($wsChild.stageIdx)||0] || _wcFocusDef.stages[0]>> <div style="border-top:1px solid var(--border-dim);padding-top:0.2rem;margin-top:0.05rem;"> <div style="font-size:0.73rem;color:var(--bone-dim);margin-bottom:0.06rem;">── 焦点:<<print _wcFocusDef.name>></div> <div style="color:var(--bone-dim);font-size:0.82rem;margin-bottom:0.1rem;"><<print _wcFocusStage.desc>></div> /* 进行中:显示当前阶段结果 */ <<if $wsChild.actionText>> <div style="border-left:2px solid var(--teal-bright);padding:0.12rem 0.4rem;margin-bottom:0.1rem;font-size:0.8rem;color:var(--bone);"><<print $wsChild.actionText>></div> <</if>> <<if $wsChild.lootLog>> <div style="font-size:0.73rem;opacity:0.75;margin-bottom:0.08rem;">累计收获:<<print $wsChild.lootLog>></div> <</if>> <div style="font-size:0.8rem;"> <<set _wcArmLv = Number($upgrades ? $upgrades.arm : 0) || 0>> <<for _wcai = 0; _wcai < _wcFocusStage.actions.length; _wcai++>> <<set _wca = _wcFocusStage.actions[_wcai]>> /* 关键词判断需臂等级 */ <<set _wcaNeedFine = (_wca.indexOf("精密") >= 0 || _wca.indexOf("精细") >= 0)>> <<set _wcaNeedBasic = (!_wcaNeedFine && (_wca.indexOf("机械臂") >= 0 || _wca.indexOf("撬开") >= 0 || _wca.indexOf("拆卸") >= 0 || _wca.indexOf("清除障碍") >= 0))>> <<if _wcaNeedFine && _wcArmLv < 2>> <div style="opacity:0.35;font-size:0.8rem;margin-bottom:0.06rem;"><<print _wca>><span style="font-size:0.67rem;color:var(--amber-dim);"> [需精密机械臂 — 机械室升至Lv2]</span></div> <<elseif _wcaNeedBasic && _wcArmLv < 1>> <div style="opacity:0.35;font-size:0.8rem;margin-bottom:0.06rem;"><<print _wca>><span style="font-size:0.67rem;color:var(--bone-dim);"> [需加装机械臂 — 机械室Lv1]</span></div> <<else>> <<capture _wca>><<link _wca>><<resolveWsChild _wca>><</link>> <</capture>> <</if>> <</for>> /* ── 机械臂远程清除面板(障碍物列表) ── */ <<if _wcArmLv >= 1 && $diveArmBlocked>> <<set _rcp_ids = Object.keys($diveArmBlocked)>> <<set _rcp_any = false>> <<for _rcpi = 0; _rcpi < _rcp_ids.length; _rcpi++>> <<set _rcp_sid = _rcp_ids[_rcpi]>> <<for _rcpj = 0; _rcpj < $diveArmBlocked[_rcp_sid].length; _rcpj++>> <<set _rcp_elem = $diveArmBlocked[_rcp_sid][_rcpj]>> <<set _rcp_cleared = ($diveArmCleared && $diveArmCleared[_rcp_sid] && $diveArmCleared[_rcp_sid].indexOf(_rcp_elem) >= 0)>> <<if !_rcp_cleared>><<set _rcp_any = true>><</if>> <</for>> <</for>> <<if _rcp_any>> <div style="border-top:1px dashed var(--amber-dim);margin-top:0.25rem;padding-top:0.2rem;"> <div style="font-size:0.71rem;color:var(--amber-dim);margin-bottom:0.1rem;">🦾 机械臂可清除的仓外障碍:</div> <<for _rcpi = 0; _rcpi < _rcp_ids.length; _rcpi++>> <<set _rcp_sid = _rcp_ids[_rcpi]>> <<for _rcpj = 0; _rcpj < $diveArmBlocked[_rcp_sid].length; _rcpj++>> <<set _rcp_elem = $diveArmBlocked[_rcp_sid][_rcpj]>> <<set _rcp_cleared = ($diveArmCleared && $diveArmCleared[_rcp_sid] && $diveArmCleared[_rcp_sid].indexOf(_rcp_elem) >= 0)>> <<if !_rcp_cleared>> <<capture _rcp_sid, _rcp_elem>> <<link "清除障碍:" + _rcp_elem>> <<if !$diveArmCleared>><<set $diveArmCleared = {}>><</if>> <<if !$diveArmCleared[_rcp_sid]>><<set $diveArmCleared[_rcp_sid] = []>><</if>> <<run $diveArmCleared[_rcp_sid].push(_rcp_elem)>> <<goto "探索">> <</link>><br> <</capture>> <</if>> <</for>> <</for>> </div> <</if>> <</if>> <<link "[收起]">><<set $wsChild = null>><<goto "探索">><</link>> </div> </div> <</if>> <</if>> /* 最后一次行动结果(事件结束后持续显示)*/ <<if !$wsChild && $wsLastActionText>> <div style="border-left:2px solid var(--teal-bright);padding:0.15rem 0.45rem;margin:0.1rem 0 0.15rem;font-size:0.8rem;color:var(--bone);"><<print $wsLastActionText>></div> <<if $wsLastActionLoot>> <div style="font-size:0.73rem;opacity:0.75;margin-bottom:0.1rem;">获得:<<print $wsLastActionLoot>></div> <</if>> <div style="font-size:0.72rem;"><<link "[ 确认 ]">><<set $wsLastActionText = "">><<set $wsLastActionLoot = "">><<goto "探索">><</link>></div> <</if>> /* 离开此地 */ <div style="margin-top:0.2rem;font-size:0.73rem;opacity:0.45;"><<link "[ 离开此地 ]">><<set $worldScene.state = "done">><<set $wsChild = null>><<set $wsLastActionText = "">><<set $wsLastActionLoot = "">><</link>></div> </div> <</if>> /* 小型事件(如有)*/ <<if $activeSmallEvent>> <<smallEventTable>> <<set _seId3 = String($activeSmallEvent.id)>> <<set _seIdx3 = Number($activeSmallEvent.stageIdx)>> <<set _seDef3 = $smallEventDefs[_seId3]>> <<if _seDef3>> <<set _seStg3 = _seDef3.stages[_seIdx3] || _seDef3.stages[0]>> <div style="margin-top:0.3rem;border-top:1px solid var(--border-dim);padding-top:0.2rem;"> <div style="color:var(--teal-bright);font-size:0.76rem;margin-bottom:0.05rem;">— <<print _seDef3.name>></div> <div style="color:var(--bone-dim);"><<print _seStg3.desc>></div> <<if $activeSmallEvent.lootLog>><div style="font-size:0.75rem;opacity:0.75;margin-top:0.05rem;">收获:<<print $activeSmallEvent.lootLog>></div><</if>> <<if _seStg3.actions>> <div style="margin-top:0.12rem;"><<for _sa3i = 0; _sa3i < _seStg3.actions.length; _sa3i++>><<set _sa3 = _seStg3.actions[_sa3i]>><<capture _sa3>><<link _sa3>><<resolveSmallEvent _sa3>><</link>> <</capture>><</for>></div> <</if>> </div> <<else>> <<set $activeSmallEvent = null>> <</if>> <</if>> /* 微型事件碎片 + 探索结果文本 */ <<if $activeHuntItems && $activeHuntItems.length > 0>> <<if !$microEventDefs>><<microEventTable>><</if>> <<for _hii = 0; _hii < $activeHuntItems.length; _hii++>> <<set _hid = $activeHuntItems[_hii]>> <<set _hdef = $microEventDefs[_hid]>> <<if _hdef>> <<capture _hid, _hdef>> <div style="margin-top:0.2rem;color:var(--bone-dim);"><<print _hdef.fragmentText>> <span style="white-space:nowrap;"><<link _hdef.actionLabel>><<resolveMicroEvent _hid>><</link>> <span style="opacity:0.4;font-size:0.72rem;"><<link "[略过]">><<set _ignoreNew = []>><<for _ignI = 0; _ignI < $activeHuntItems.length; _ignI++>><<if $activeHuntItems[_ignI] !== _hid>><<set _ignoreNew[_ignoreNew.length] = $activeHuntItems[_ignI]>><</if>><</for>><<set $activeHuntItems = _ignoreNew>><</link>></span></span></div> <</capture>> <</if>> <</for>> <</if>> <<if $lastHuntText>><div style="margin-top:0.15rem;color:var(--bone-dim);opacity:0.85;"><<print $lastHuntText>></div><<set $lastHuntText = "">><</if>> <<if $lastExploreText>><div style="margin-top:0.15rem;color:var(--bone-dim);"><<print $lastExploreText>></div><</if>> <<if $lastSmallEventText>><div style="margin-top:0.15rem;color:var(--bone-dim);"><<print $lastSmallEventText>></div><<set $lastSmallEventText = "">><</if>> </div> /* ══ 位置提示条(仪表盘上方)══ */ <<set _exState = "normal">> <<if $largeScene && typeof $largeScene === "object" && $largeScene.state === "approaching">> <<set _exState = "ls_approach">> <<elseif $largeScene && typeof $largeScene === "object" && $largeScene.state === "leaving">> <<set _exState = "ls_leaving">> <<elseif $largeScene && typeof $largeScene === "object" && $largeScene.state === "active">> <<if $worldScene && $worldScene.state === "inside">> <<set _exState = "ls_zone">> <<elseif $worldScene && $worldScene.state === "approaching">> <<set _exState = "ls_zone_approach">> <<else>> <<set _exState = "ls_active">> <</if>> <<elseif $worldScene && $worldScene.state === "inside">> <<set _exState = "ws_only">> <<elseif $worldScene && $worldScene.state === "approaching">> <<set _exState = "ws_approach">> <</if>> <<if _exState !== "normal">> <div style="display:flex;align-items:center;gap:0.3rem;font-size:0.72rem;padding:0.18rem 0.4rem;margin-bottom:0.2rem;border-radius:2px;background:rgba(180,140,60,0.07);border:1px solid var(--amber-dim);"> <<if _exState === "ls_leaving">> <span style="color:var(--bone-dim);opacity:0.4;">←</span> <span style="color:var(--bone-dim);opacity:0.5;">已离开 <b style="color:var(--bone-dim);"><<print $largeScene.name>></b></span> <<elseif _exState === "ls_approach">> <span style="color:var(--amber);opacity:0.8;">▷</span> <span style="color:var(--amber-dim);">正在接近 <b style="color:var(--amber);"><<print $largeScene.name>></b></span> <<elseif _exState === "ls_active">> <span style="color:var(--amber);">◈</span> <span style="color:var(--bone-dim);">当前位于 <b style="color:var(--amber);"><<print $largeScene.name>></b></span> <<elseif _exState === "ls_zone" || _exState === "ls_zone_approach">> <span style="color:var(--amber);">◈</span> <span style="color:var(--bone-dim);"> 当前位于 <b style="color:var(--amber);"><<print $largeScene.name>></b> <span style="opacity:0.5;margin:0 0.2rem;">·</span> <b style="color:var(--teal-bright);"><<print $worldScene.name>></b> <<if _exState === "ls_zone">><span style="opacity:0.6;font-size:0.69rem;"> 锚定以进行探索</span><</if>> </span> <<elseif _exState === "ws_only">> <span style="color:var(--teal-bright);">◈</span> <span style="color:var(--bone-dim);">当前位于 <b style="color:var(--teal-bright);"><<print $worldScene.name>></b> <span style="opacity:0.6;font-size:0.69rem;">锚定以进行探索</span></span> <<elseif _exState === "ws_approach">> <span style="color:var(--teal-bright);opacity:0.7;">▷</span> <span style="color:var(--bone-dim);">正在接近 <b style="color:var(--teal-bright);"><<print $worldScene.name>></b></span> <</if>> </div> <</if>> /* ══ 操作台 ══ */ <span style="font-size:0.73rem;color:var(--bone-dim);">⚓ $mapinfo[$maptype].type 深$depth m / 底$depthdeep m</span><br> <<set _ri = Math.max(0, Math.min(100, Math.floor(Number($regionRichness)||0)))>> <<set _ric = _ri > 50 ? "var(--teal-bright)" : _ri > 20 ? "var(--amber)" : "var(--danger-bright)">> <div style="display:flex;justify-content:space-between;font-size:0.68rem;color:var(--bone-dim);margin:0.15rem 0 0.05rem;"> <span>区域丰富度</span><span style="color:<<print _ric>>;"><<print _ri>>/100</span> </div> <div style="background:var(--bg-panel);border:1px solid var(--border-dim);height:4px;border-radius:2px;overflow:hidden;margin-bottom:0.3rem;"><div style="height:100%;width:<<print _ri>>%;background:<<print _ric>>;"></div></div> <<set _emin = ($exploreSearchCost && typeof $exploreSearchCost.min === "number") ? $exploreSearchCost.min : 3>> <<if _ri >= _emin>> <div style="margin-bottom:0.2rem;"><<link "🔍 搜索周围环境">><<exploreSearch>><</link>></div> <<else>> <div style="margin-bottom:0.2rem;opacity:0.4;">🔍 区域已无新发现</div> <</if>> <<if !$envHarvestDefs>><<exploreDefs>><</if>> <<set _ehd = $envHarvestDefs[$maptype]>> <<if _ehd>> <<set _eLabel = "⛏ " + _ehd.label>> <div style="font-size:0.78rem;margin-bottom:0.2rem;"><<link _eLabel>><<exploreDefs>><<set _ehd2 = $envHarvestDefs[$maptype]>><<set _ehLog = "">><<if _ehd2 && _ehd2.loot>><<for _eli = 0; _eli < _ehd2.loot.length; _eli++>><<set _el = _ehd2.loot[_eli]>><<set _elq = _el.qty[0] + Math.floor(Math.random() * (_el.qty[1] - _el.qty[0] + 1))>><<if _elq > 0>><<additem _el.id _elq>><<if $items && $items[_el.id]>><<set _ehLog = _ehLog + $items[_el.id].name + "×" + _elq + " ">><</if>><</if>><</for>><</if>><<set $lastEnvText = (_ehd2 ? _ehd2.text : "") + (_ehLog ? " " + _ehLog : "")>><</link>></div> <</if>> <<if $lastEnvText>><div style="font-size:0.76rem;color:var(--bone-dim);opacity:0.75;margin-bottom:0.2rem;"><<print $lastEnvText>></div><<set $lastEnvText = "">><</if>> <div style="font-size:0.76rem;margin-bottom:0.4rem;"><<link "▶ 起锚,恢复航行">><<set $sailMode = "travel">><<set $lastExploreText = "">><<set $activeHuntItems = []>><<set $lastHuntText = "">><<set $currentContext = "sailing">><<goto "航行">><</link>></div> /* ── 书签 ── */ <div style="font-size:0.74rem;margin-top:0.2rem;"> <<set _bmLabel = $showBookmarks ? "▾ 航行记录" : "▸ 航行记录">><<link _bmLabel>><<set $showBookmarks = !$showBookmarks>><</link>> <<if $showBookmarks>><div style="margin-top:0.2rem;max-height:10rem;overflow-y:auto;"><<bookmarkPanel>></div><</if>> </div> <</replace>> <</repeat>> [[终止航行|驾驶舱][$sailspd to 0]] <</nobr>>
<<nobr>> <<widget "sail">> <<set $map += $sailspd>> <<set $sailpass += 1>> <<set $depthpass += $sailspd>> <<set $timepass += 1>> /* 更新跨度显示 */ <<set $mapspan = Math.floor($map / 50)>> <<set $maplimspan = Math.floor($maplim / 50)>> /* ═══ 预生成下一区域选项(3个方向) ═══ */ <<if $maplim - $map < 2000 && $nextAreasReady != 1>> <<set $nextAreas = []>> <<set _keys = Object.keys($mapinfo)>> <<set _usedTypes = [$maptype]>> /* 初始即排除当前地形 */ /* ── 方向0·直行:只从深度兼容地形加权随机 ── */ <<set _compat = []>><<set _compatW = []>><<set _compatTotalW = 0>> <<for _ki = 0; _ki < _keys.length; _ki++>> <<set _kinfo = $mapinfo[_keys[_ki]]>> <<if $depthdeep >= _kinfo.depthmin && $depthdeep <= _kinfo.depthmax>> <<run _compat.push(_keys[_ki])>> <<run _compatW.push(_kinfo.weight)>> <<set _compatTotalW += _kinfo.weight>> <</if>> <</for>> /* 过滤掉当前地形,避免直行也重复 */ <<set _compat2 = []>><<set _compatW2 = []>><<set _compatTotalW2 = 0>> <<for _ki = 0; _ki < _compat.length; _ki++>> <<if _compat[_ki] !== $maptype>> <<set _compat2[_compat2.length] = _compat[_ki]>> <<set _compatW2[_compatW2.length] = _compatW[_ki]>> <<set _compatTotalW2 += _compatW[_ki]>> <</if>> <</for>> /* 若过滤后为空(极端情况),回退到含当前地形 */ <<if _compat2.length === 0>><<set _compat2 = _compat>><<set _compatW2 = _compatW>><<set _compatTotalW2 = _compatTotalW>><</if>> <<if _compatTotalW2 <= 0>><<run _compat2.push("sand")>><<run _compatW2.push(1)>><<set _compatTotalW2 = 1>><</if>> <<set _r0 = Math.random() * _compatTotalW2>><<set _cw = 0>><<set _t0 = _compat2[0]>> <<for _ki = 0; _ki < _compat2.length; _ki++>> <<set _cw += _compatW2[_ki]>> <<if _r0 < _cw>><<set _t0 = _compat2[_ki]>><<break>><</if>> <</for>> <<set _i0 = $mapinfo[_t0]>> <<set _d0 = Math.min(_i0.depthmax, Math.max(_i0.depthmin, $depthdeep + Math.floor(Math.random()*201)-100))>> <<set _ml0 = _i0.spanmin + Math.floor(Math.random()*(_i0.spanmax-_i0.spanmin+1))>> <<run $nextAreas.push({type:_t0,depth:_d0,maplim:_ml0,label:_i0.type,dir:"直行",transition:false})>> <<run _usedTypes.push(_t0)>> /* ── 方向1·左转 / 方向2·右转:所有地形可选,深度取最接近当前的合法值 ── */ <<set _dirs = ["向左转舵","向右转舵"]>> <<for _di = 0; _di < 2; _di++>> /* 加权随机,跳过已用地形 */ <<set _altW = 0>> <<for _ki = 0; _ki < _keys.length; _ki++>> <<set _inU = false>> <<for _ui = 0; _ui < _usedTypes.length; _ui++>><<if _usedTypes[_ui]===_keys[_ki]>><<set _inU=true>><<break>><</if>><</for>> <<if !_inU>><<set _altW += $mapinfo[_keys[_ki]].weight>><</if>> <</for>> <<if _altW <= 0>><<break>><</if>> <<set _ralt = Math.random() * _altW>><<set _calt = 0>><<set _talt = "">> <<for _ki = 0; _ki < _keys.length; _ki++>> <<set _inU = false>> <<for _ui = 0; _ui < _usedTypes.length; _ui++>><<if _usedTypes[_ui]===_keys[_ki]>><<set _inU=true>><<break>><</if>><</for>> <<if !_inU>><<set _calt += $mapinfo[_keys[_ki]].weight>><<if _ralt < _calt>><<set _talt = _keys[_ki]>><<break>><</if>><</if>> <</for>> <<if !_talt>><<break>><</if>> <<set _ialt = $mapinfo[_talt]>> /* 深度:夹到合法范围内,尽量靠近当前深度 */ <<set _dalt = Math.min(_ialt.depthmax, Math.max(_ialt.depthmin, $depthdeep + Math.floor(Math.random()*401)-200))>> <<set _trans = ($depthdeep < _ialt.depthmin || $depthdeep > _ialt.depthmax)>> <<set _mlalt = _ialt.spanmin + Math.floor(Math.random()*(_ialt.spanmax-_ialt.spanmin+1))>> <<set _dirLabel = _dirs[_di]>> <<run $nextAreas.push({type:_talt,depth:_dalt,maplim:_mlalt,label:_ialt.type,dir:_dirLabel,transition:_trans})>> <<run _usedTypes.push(_talt)>> <</for>> <<set $nextAreasReady = 1>> <<set $selectedNextArea = 0>> <</if>> /* ═══ 区域过渡 ═══ */ <<if $map >= $maplim>> /* 存档当前区域为"上一区域"(用于返回功能) */ <<set $prevArea = { type:$maptype, depth:$depthdeep, maplim:$maplim }>> <<if $selectedNextArea === -1 && $prevArea !== null>> /* 返回上一区域 */ <<set $maptype = $prevArea.type>> <<set $depthdeep = $prevArea.depth>> <<set $maplim = $prevArea.maplim>> <<elseif $nextAreasReady === 1 && $nextAreas.length > 0>> /* 进入玩家选择(或默认选中)的区域 */ <<set _chosen = $nextAreas[$selectedNextArea] || $nextAreas[0]>> <<set $maptype = _chosen.type>> <<set $maplim = _chosen.maplim>> /* 深度过渡:将depthnoc夹到新地形合法范围内 */ <<set _cInfo = $mapinfo[_chosen.type]>> <<if _cInfo>> <<if $depthnoc < _cInfo.depthmin>><<set $depthnoc = _cInfo.depthmin>><</if>> <<if $depthnoc > _cInfo.depthmax>><<set $depthnoc = _cInfo.depthmax>><</if>> <</if>> <<set $depthdeep = Math.floor($depthnoc)>> <<else>> /* 后备方案 */ <<set $maptype = "sand">> <<set $depthdeep = Math.min(Math.max($depthdeep,20),10000)>> <<set $maplim = 80000>> <</if>> <<set $map = 0>> <<set $depthnoc = $depthdeep>> <<set $nextAreasReady = 0>> <<set $nextAreas = []>> /* 进入新区域时设置初始丰富度 */ <<set _richBase = { sand:20, flat:30, cliff:35, grass:55, reef:70, vent:60, abyss:10 }>> <<set $regionRichness = (_richBase[$maptype] || 30) + Math.floor(Math.random() * 20)>> /* 进入新区域:重置事件队列,生成大/中型场景 */ <<set $worldScene = null>> <<set $wsChild = null>> <<set $wsLastActionText = "">> <<set $wsLastActionLoot = "">> <<set $largeScene = 0>> <<set $worldSceneQueue = []>> <<set $worldSceneQueueIdx = 0>> <<set _bmAutoL = ($mapinfo[$maptype] ? $mapinfo[$maptype].type : $maptype) + " " + $depthdeep + "m">> <<addBookmark _bmAutoL "auto">> <<spawnLargeScene>> <<if !$largeScene || $largeScene === 0>><<spawnWorldScene>><</if>> <</if>> /* regionRichness 被动缓慢恢复(每秒+0.02,约83分钟从0回到100) */ <<if $regionRichness < 100>> <<set $regionRichness = Math.min(100, (Number($regionRichness)||0) + 0.02)>> <</if>> /* 深度变化 */ <<set _depthSpd = Number($depthspd)>> <<if isNaN(_depthSpd)>> <<set _depthSpd = 0>> /* 或者设置一个默认值 */ <</if>> <<set $depthnoc = Number($depthnoc) + _depthSpd * Math.floor($sailspd / 50)>> /* 硬截断:不允许突破当前地形的深度范围 */ <<set _dMin = $mapinfo[$maptype] ? $mapinfo[$maptype].depthmin : 20>> <<set _dMax = $mapinfo[$maptype] ? $mapinfo[$maptype].depthmax : 10000>> <<if $depthnoc < _dMin>><<set $depthnoc = _dMin>><</if>> <<if $depthnoc > _dMax>><<set $depthnoc = _dMax>><</if>> <<set $depthdeep = Math.floor($depthnoc)>> <<if $depth > $depthdeep>> <<set $depth = $depthdeep>> <</if>> /* 判断是否需要重置 depthwave 和 depthspd */ <<if $depthpass > $depthwave || $depthdeep >= $mapinfo[$maptype].depthmax || $depthdeep <= $mapinfo[$maptype].depthmin>> <<set $depthwave = Math.floor(Math.random() * 4001) + 1000>> <<set $depthspd = (Math.random() * ($mapinfo[$maptype].spdmax - $mapinfo[$maptype].spdmin) + $mapinfo[$maptype].spdmin).toFixed(1)>> <<set $depthpass = 0>> <</if>> /* ═══ WorldScene 队列检测 ═══ */ /* 检查当前 $worldScene 状态转换 */ <<if $worldScene && typeof $worldScene === "object">> <<if $worldScene.state === "pending" && $map >= $worldScene.approachAt>> <<set $worldScene.state = "approaching">> <</if>> <<if $worldScene.state === "approaching" && $map >= $worldScene.mapStart>> <<set $worldScene.state = "inside">> <<set $sailspd = 0>> <</if>> <<if $map > $worldScene.mapEnd && $worldScene.state !== "done">> <<set $worldScene.state = "done">> <<set $wsChild = null>> /* 同步写回队列 */ <<if $worldSceneQueue && $worldSceneQueueIdx < $worldSceneQueue.length>> <<set $worldSceneQueue[$worldSceneQueueIdx].state = "done">> <</if>> /* 推进到队列中的下一个 */ <<if $worldSceneQueue && $worldSceneQueueIdx + 1 < $worldSceneQueue.length>> <<set $worldSceneQueueIdx = $worldSceneQueueIdx + 1>> <<set $worldScene = $worldSceneQueue[$worldSceneQueueIdx]>> <</if>> <</if>> <</if>> /* ═══ LargeScene 状态机 ═══ */ <<if $largeScene && typeof $largeScene === "object" && $largeScene.state !== "done">> /* approaching → active */ <<if $largeScene.state === "approaching" && $map >= $largeScene.approachEnd>> <<set $largeScene.state = "active">> <</if>> /* active 期间 zone 触发 */ <<if $largeScene.state === "active">> <<for _lzi = 0; _lzi < $largeScene.zones.length; _lzi++>> <<set _lz = $largeScene.zones[_lzi]>> <<if _lz.st === "pending" && $map >= _lz.zoneAt>> <<set $largeScene.zones[_lzi].st = "arriving">> <<set $largeScene.activeZone = _lzi>> <<if !$worldScene || $worldScene.state === "done">> <<worldSceneDefs>> <<set _lzDef = $wsDefs[_lz.wsType]>> <<if _lzDef>> <<set _lzStart = $map>> <<set _lzEnd = _lzStart + _lzDef.spanMin + Math.floor(Math.random()*(_lzDef.spanMax-_lzDef.spanMin+1))>> <<set _lzAppr = Math.max(0, _lzStart - 800)>> <<set $worldScene = {id:_lz.wsType, name:_lz.name, state:"inside", approachDesc:"前方出现" + _lz.name, approachAt:_lzAppr, mapStart:_lzStart, mapEnd:_lzEnd, children:_lzDef.children, doneCids:[]}>> <<set $sailspd = 0>> <</if>> <</if>> <</if>> <<if _lz.st === "arriving" && $worldScene && $worldScene.state === "done">> <<set $largeScene.zones[_lzi].st = "done">> <</if>> <</for>> /* 所有 zone 完成 → leaving */ <<set _lzAllDone = 1>> <<for _lzi = 0; _lzi < $largeScene.zones.length; _lzi++>> <<if $largeScene.zones[_lzi].st !== "done">><<set _lzAllDone = 0>><<break>><</if>> <</for>> <<if _lzAllDone>><<set $largeScene.state = "leaving">><</if>> <</if>> /* leaving → done */ <<if $largeScene.state === "leaving" && $map >= $largeScene.leaveEnd>> <<set $largeScene.state = "done">> <</if>> <</if>> /* temporal event tick */ <<if $temporalEvent && $temporalEvent !== 0>><<resolveTemporalEvent>><</if>> <<if !$temporalEvent && $sailspd > 0>><<spawnTemporalEvent>><</if>> /* ══ 燃料消耗 ══ */ <<if !$fuelDefs>><<fuelDefs>><</if>> <<set _fDepth = $depth>> /* 隔热层减少燃料深度系数 */ <<set _fHullLv = Number($upgrades ? $upgrades.hull : 0) || 0>> <<set _fHullMod = [0, 0.3, 0.6, 1.0][_fHullLv] || 0>> <<set _fDepthBase = (_fDepth > 800) ? 4.0 : (_fDepth > 300) ? 2.5 : (_fDepth > 100) ? 1.5 : 1.0>> <<set _fDepthFactor = Math.max(1.0, _fDepthBase - _fHullMod)>> <<set _fSpdFactor = ($spdmax > 0 && $sailspd > 0) ? ($sailspd / $spdmax) : 0>> <<set _fBurn = 0.05 + _fSpdFactor * 0.15 * _fDepthFactor>> /* 加压舱安全深度:超限时额外损耗 $shell */ <<set _fPressLv = Number($upgrades ? $upgrades.pressure : 0) || 0>> <<set _fSafeDepth = [300, 600, 1500, 5000][_fPressLv] || 300>> <<if $depth > _fSafeDepth>> <<set _fOverDepth = $depth - _fSafeDepth>> <<set _fHullDmg = Math.max(0, 0.02 * (1 - _fHullLv * 0.2) * (_fOverDepth / 100))>> <<set $shell = Math.max(0, ($shell||100) - _fHullDmg)>> <</if>> <<set $fuel = Math.max(0, $fuel - _fBurn)>> /* 燃料耗尽:进入漂流状态 */ <<if $fuel <= 0 && !$driftMode>> <<set $driftMode = true>> <<set $sailspd = 0>> <</if>> /* 漂流状态:强制停止,禁用下潜(UI层控制),不强制上浮 */ <<if $driftMode>> <<set $sailspd = 0>> <</if>> /* 加了燃料后自动解除漂流 */ <<if $driftMode && $fuel > 5>><<set $driftMode = false>><</if>> <<checkEnvEffects>> <<checkEvent>> <<tickEvent>> <</widget>> <</nobr>>
<<nobr>> <<set $fishingBait = "内脏碎肉">> <<set $fishingGear = "垂钓">> <<set $fishingLight = "关闭">> <div id="fishing-info">捕鱼信息将显示在这里...</div> <<repeat 1s>> <<fish>> <<time>> <<replace "#fishing-info">> $showseason季 第$showday日 $showhour:$showminute<br> 地形:$mapinfo[$maptype].type 船舱温度:$worldtem<br><br> 当前坐标:$mapspan 单位<br> 当前深度:$depth米<br> 海底深度:$depthdeep米 <br> <br> 最新情况:<<print $lastCatchText >><br> <br> 饱腹:$hunger <br> 饮水:$water<br> 体力:$power<br> 生命:$life<br> 压力:$tre<br> 安定:$san<br> 魔力:$magic<br> <br> <<if $fishingLight == "关闭">> <<link "开启灯光">> <<set $fishingLight = "开启">> <</link>> <<else>> <<link "关闭灯光">> <<set $fishingLight = "关闭">> <</link>> <</if>> <<link "切换渔具">> <<if $fishingGear == "垂钓">> <<set $fishingGear = "渔网">> <<else>> <<set $fishingGear = "垂钓">> <</if>> <</link>> <<link "更换鱼饵">> <<if $fishingBait == "内脏碎肉">> <<set $fishingBait = "血饵">> <<elseif $fishingBait == "血饵">> <<set $fishingBait = "草饵">> <<else>> <<set $fishingBait = "内脏碎肉">> <</if>> <</link>> <br> <<if $depth > -1>> <<link "排水上浮">> <<set $depth -= 1>> <</link>> <<else>> <<print "目前位于水面">> <</if>> <<if $depth < $depthdeep>> <<link "加压下潜">> <<set $depth += 1>> <</link>> <<else>> <<print "目前位于海底">> <</if>> <</replace>> <</repeat>> [[终止捕鱼|驾驶舱]] <</nobr>>
<<nobr>> <<widget "cpScene">> /* 调用:<<cpScene "当前房间名">> 遍历所有激活 CP,在房间内匹配并渲染一行场景描述 */ <<if $activeCpIds && $activeCpIds.length > 0>> <<for _csI = 0; _csI < $activeCpIds.length; _csI++>> <<set _csId = $activeCpIds[_csI]>> <<set _csCp = $cps[_csId]>> <<if _csCp && _csCp.location === $args[0]>> <<cpSceneRender _csId>> <</if>> <</for>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "fish">> <<set _catchResult = "">> <<set _catchItem = "">> <<if !$fishingConfig>> <<set _catchResult = "系统错误:fishingConfig 未定义">> <<set $lastCatchText = _catchResult>> <</if>> <<if !$lightCondition>> <<set $lightCondition = "朦胧">> <!--- 设置默认值 ---> <</if>> /* === 环境权重计算 === */ <<set _totalWeightMultiplier = 1>> /* 1. 水深权重 */ <<set _depthKey = "">> <<if $depth <= 50>> <<set _depthKey = "0-50">> <<elseif $depth <= 150>> <<set _depthKey = "50-150">> <<elseif $depth <= 300>> <<set _depthKey = "150-300">> <<elseif $depth <= 1000>> <<set _depthKey = "300-1000">> <<else>> <<set _depthKey = "1000+">> <</if>> /* 2. 地形权重 */ <<set _terrainKey = "">> <<if $depthdeep - $depth <= 20>> <<set _terrainKey = "底栖">> <<elseif $maptype == "sand">> <<set _terrainKey = "沙海床">> <<elseif $maptype == "flat">> <<set _terrainKey = "岩海床">> <<elseif $maptype == "cliff">> <<set _terrainKey = "峭壁">> <<elseif $maptype == "grass">> <<set _terrainKey = "海草床">> <<elseif $maptype == "reef">> <<set _terrainKey = "珊瑚礁">> <<elseif $maptype == "forest">> <<set _terrainKey = "海藻森林">> <<else>> <<set _terrainKey = "开阔水域">> <</if>> /* 3. 温度权重 */ <<set _tempWeight = 1>> <<if $worldtem >= 18 && $worldtem <= 26>> <<set _tempWeight = 1.2>> <!--- 最佳温度区间 ---> <<elseif $worldtem >= 14 && $worldtem < 18>> <<set _tempWeight = 0.9>> <<elseif $worldtem > 26 && $worldtem <= 30>> <<set _tempWeight = 0.9>> <<elseif $worldtem >= 10 && $worldtem < 14>> <<set _tempWeight = 0.7>> <<elseif $worldtem > 30 && $worldtem <= 34>> <<set _tempWeight = 0.7>> <<else>> <<set _tempWeight = 0.4>> <!--- 极端温度 ---> <</if>> <<set _totalWeightMultiplier = _totalWeightMultiplier * _tempWeight>> /* === 渔获池筛选 === */ <<set _fishingPool = []>> <<if $pools>> <<set _itemKeys = Object.keys($pools)>> <<for _i = 0; _i < _itemKeys.length; _i++>> <<set _itemKey = _itemKeys[_i]>> <<set _item = $pools[_itemKey]>> <<if !_item.tags>> <<set _item.tags = []>> <</if>> <<set _fishingPool.push(_itemKey)>> <</for>> <</if>> <<set _baseChance = 3>> <<if random(1, 100) <= _baseChance and _fishingPool.length > 0>> <<set _weightedPool = []>> <<set _totalWeight = 0>> <<for _i = 0; _i < _fishingPool.length; _i++>> <<set _itemKey = _fishingPool[_i]>> <<set _item = $pools[_itemKey]>> <<set _weight = _item.baseWeight>> /* 1. 水深权重计算 */ <<set _depthMultiplier = 1>> <<if _item.customWeights && _item.customWeights.depth && _item.customWeights.depth[_depthKey]>> /* 使用物种专属水深权重 */ <<set _depthMultiplier = _item.customWeights.depth[_depthKey]>> <<elseif $fishingConfig.depthWeights && $fishingConfig.depthWeights[_depthKey]>> /* Fallback: 使用通用水深权重 */ <<set _depthTags = ["浅层", "中层", "深层"]>> <<set _bestDepthWeight = 0.1>> <<for _j = 0; _j < _item.tags.length; _j++>> <<set _tag = _item.tags[_j]>> <<if _depthTags.includes(_tag) && $fishingConfig.depthWeights[_depthKey][_tag] > _bestDepthWeight>> <<set _bestDepthWeight = $fishingConfig.depthWeights[_depthKey][_tag]>> <</if>> <</for>> <<set _depthMultiplier = _bestDepthWeight>> <</if>> <<set _weight = _weight * _depthMultiplier>> /* 2. 地形权重计算 */ <<set _terrainMultiplier = 1>> <<if _item.customWeights && _item.customWeights.terrain && _item.customWeights.terrain[_terrainKey]>> /* 使用物种专属地形权重 */ <<set _terrainMultiplier = _item.customWeights.terrain[_terrainKey]>> <<elseif $fishingConfig.terrainWeights && $fishingConfig.terrainWeights[_terrainKey]>> /* Fallback: 使用通用地形权重 */ <<set _terrainTags = ["开阔水域", "沙海床", "岩海床", "珊瑚礁", "海草床", "海藻森林", "峭壁", "底栖"]>> <<set _bestTerrainWeight = 0.1>> <<for _j = 0; _j < _item.tags.length; _j++>> <<set _tag = _item.tags[_j]>> <<if _terrainTags.includes(_tag) && $fishingConfig.terrainWeights[_terrainKey][_tag] > _bestTerrainWeight>> <<set _bestTerrainWeight = $fishingConfig.terrainWeights[_terrainKey][_tag]>> <</if>> <</for>> <<set _terrainMultiplier = _bestTerrainWeight>> <</if>> <<set _weight = _weight * _terrainMultiplier>> /* 3. 光照权重计算 */ <<set _lightMultiplier = 1>> <<if _item.customWeights && _item.customWeights.light && _item.customWeights.light[_lightLevel]>> /* 使用物种专属光照权重 */ <<set _lightMultiplier = _item.customWeights.light[_lightLevel]>> <<elseif $fishingConfig.lightWeights && $fishingConfig.lightWeights[_lightLevel]>> /* Fallback: 使用通用光照权重 + 行为标签叠加 */ <<set _behaviorMultiplier = 1>> <<set _behaviorTags = ["日行性", "夜行性", "趋光性", "群居", "洄游性"]>> <<for _j = 0; _j < _item.tags.length; _j++>> <<set _tag = _item.tags[_j]>> <<if _behaviorTags.includes(_tag) && $fishingConfig.lightWeights[_lightLevel][_tag]>> <<set _behaviorMultiplier = _behaviorMultiplier * $fishingConfig.lightWeights[_lightLevel][_tag]>> <</if>> <</for>> <<set _lightMultiplier = _behaviorMultiplier>> <</if>> <<set _weight = _weight * _lightMultiplier>> /* 4. 温度权重(保持不变) */ <<set _weight = _weight * _tempWeight>> /* 5. 灯光加成(保持不变) */ <<if $fishingLight == "开启">> <<for _j = 0; _j < _item.tags.length; _j++>> <<set _tag = _item.tags[_j]>> <<if $fishingConfig.lightBonus && $fishingConfig.lightBonus[_tag]>> <<set _weight = _weight * $fishingConfig.lightBonus[_tag]>> <</if>> <</for>> <</if>> /* 6. 渔具匹配(保持不变) */ <<set _gearTags = $fishingConfig.gearTags ? $fishingConfig.gearTags[$fishingGear] : null>> <<if _gearTags>> <<for _j = 0; _j < _gearTags.length; _j++>> <<set _gearTag = _gearTags[_j]>> <<if _item.tags.includes(_gearTag)>> <<set _weight = _weight * 1.5>> <</if>> <</for>> <</if>> /* 6b. 渔具专属过滤 */ <<if $fishingGear === "垂钓">> <<set _hookDef = State.variables.items[_itemKey]>> <<if _hookDef && _hookDef.subtype === "鱼类">> <<elseif _hookDef && (_hookDef.subtype === "藻类" || _hookDef.subtype === "其他")>> <<set _weight = _weight * 0.05>> <<else>> <<set _weight = 0>> <</if>> <<elseif $fishingGear === "渔网">> <<set _netDef = State.variables.items[_itemKey]>> <<if _netDef && (_netDef.subtype === "贝类" || (_netDef.tags && _netDef.tags.includes("底栖")))>> <<if $depthdeep - $depth > 100>> <<set _weight = 0>> <</if>> <</if>> <</if>> /* 7. 鱼饵匹配(保持不变) */ <<set _baitTags = $fishingConfig.baitTags ? $fishingConfig.baitTags[$fishingBait] : null>> <<if _baitTags>> <<for _j = 0; _j < _baitTags.length; _j++>> <<set _baitTag = _baitTags[_j]>> <<if _item.tags.includes(_baitTag)>> <<set _weight = _weight * 2.0>> <</if>> <</for>> <</if>> /* 只有权重大于0的鱼种才加入池子 */ <<if _weight > 0>> <<set _weightedPool.push({key: _itemKey, weight: _weight})>> <<set _totalWeight = _totalWeight + _weight>> <</if>> <</for>> /* 按权重随机选择 */ <<if _totalWeight > 0>> <<set _randomWeight = random(0, _totalWeight)>> <<set _currentSum = 0>> <<for _i = 0; _i < _weightedPool.length; _i++>> <<set _weightedItem = _weightedPool[_i]>> <<set _currentSum = _currentSum + _weightedItem.weight>> <<if _randomWeight <= _currentSum>> <<set _catchItem = _weightedItem.key>> <<break>> <</if>> <</for>> <<set _caughtItem = $pools[_catchItem]>> <<set _catchResult = "收获!捕获了:" + _caughtItem.name>> <<additem _catchItem 1>> <</if>> <</if>> /* 如果没有捕获任何东西 */ <<if !_catchItem>> <<set _waitingTexts = ["水波轻轻晃动...", "似乎有影子游过...", "继续等待中..."]>> <<set _catchResult = _waitingTexts[random(0, _waitingTexts.length - 1)]>> <</if>> /* 设置结果 */ <<set $lastCatchText = _catchResult>> <</widget>> <</nobr>>
<<nobr>> <<if !$cookIngredients>><<set $cookIngredients = []>><</if>> /* 扫描背包中所有食材(type=食材,排除调料) */ <<set _cs_food = []>> <<set _cs_bpCats = Object.keys($backpack)>> <<for _cs_ci = 0; _cs_ci < _cs_bpCats.length; _cs_ci++>> <<set _cs_cat = _cs_bpCats[_cs_ci]>> <<set _cs_list = $backpack[_cs_cat]>> <<if Array.isArray(_cs_list)>> <<for _cs_i = 0; _cs_i < _cs_list.length; _cs_i++>> <<if _cs_list[_cs_i].quantity > 0>> <<set _cs_def = State.variables.items[_cs_list[_cs_i].id]>> <<if _cs_def && _cs_def.type === "食材" && _cs_def.foodtags && !_cs_def.foodtags.includes("调料")>> <<run _cs_food.push({ id: _cs_list[_cs_i].id, qty: _cs_list[_cs_i].quantity, name: _cs_def.name, tags: _cs_def.foodtags })>> <</if>> <</if>> <</for>> <</if>> <</for>> **烹饪方式:**<<print $cookMethod>> **已选食材(<<print $cookIngredients.length>>/3):** <<if $cookIngredients.length > 0>> <<for _si = 0; _si < $cookIngredients.length; _si++>> <<capture _si>> <<set _sid = $cookIngredients[_si]>> <<link "[ ✕ " + State.variables.items[_sid].name + " ]" "烹饪选材">> <<run State.variables.cookIngredients.splice(_si, 1)>> <</link>> <</capture>> <</for>> <<else>> (还未选择任何食材) <</if>> --- **可用食材:** <<if _cs_food.length === 0>> 背包里没有可用的食材。 <<else>> <<for _fi = 0; _fi < _cs_food.length; _fi++>> <<capture _fi, _cs_food>> <<set _fitem = _cs_food[_fi]>> <<set _fsel = $cookIngredients.includes(_fitem.id)>> <<if _fsel>> ●<<print _fitem.name>> ×<<print _fitem.qty>> _(已选)_ <<elseif $cookIngredients.length >= 3>> ○<<print _fitem.name>> ×<<print _fitem.qty>>(已选满3种) <<else>> <<link "○ " + _fitem.name + " ×" + _fitem.qty + " [+]" "烹饪选材">> <<run State.variables.cookIngredients.push(_fitem.id)>> <</link>> <</if>> <</capture>> <</for>> <</if>> --- <<if $cookIngredients.length > 0>> <<link "▶ 开始烹饪" "烹饪进行">> <<matchRecipe>> <<set $cookTimer = 0>> <</link>> <</if>> [[← 返回选方式|厨房]] <</nobr>>
<<nobr>> <<widget "finditem">> <<set _fi_container = $args[0]>> <<set _fi_itemId = $args[1]>> <<set _foundItem = null>> <<set _foundCategory = "">> <<set _fi_categories = Object.keys(_fi_container)>> <<for _fi_i = 0; _fi_i < _fi_categories.length; _fi_i++>> <<set _fi_cat = _fi_categories[_fi_i]>> <<set _fi_val = _fi_container[_fi_cat]>> /* 渔获是嵌套对象,需要再遍历一层 */ <<if _fi_cat === "渔获" && typeof _fi_val === "object" && !Array.isArray(_fi_val)>> <<set _fi_subs = Object.keys(_fi_val)>> <<for _fi_j = 0; _fi_j < _fi_subs.length; _fi_j++>> <<set _fi_sub = _fi_subs[_fi_j]>> <<set _fi_arr = _fi_val[_fi_sub]>> <<if Array.isArray(_fi_arr)>> <<set _fi_match = _fi_arr.find(x => x.id === _fi_itemId)>> <<if _fi_match>> <<set _foundItem = _fi_match>> <<set _foundCategory = "渔获." + _fi_sub>> <<break>> <</if>> <</if>> <</for>> <<elseif Array.isArray(_fi_val)>> <<set _fi_match = _fi_val.find(x => x.id === _fi_itemId)>> <<if _fi_match>> <<set _foundItem = _fi_match>> <<set _foundCategory = _fi_cat>> <<break>> <</if>> <</if>> <<if _foundItem !== null>> <<break>> <</if>> <</for>> <</widget>> <</nobr>>
<<nobr>> <<widget "checkEvent">> <<if !$activeEvent && !$activeSmallEvent && $eventPass >= 60 && $sailspd > 0>> <<set $eventPass += 1>> /* ══ 中型事件:内联条件,不调用 .condition() ══ */ <<set _evCandIds = []>> /* island_ruin: 浅水沙/礁 */ <<if $depth <= 50 && ($maptype === "sand" || $maptype === "reef")>> <<set _evCandIds[_evCandIds.length] = "island_ruin">> <</if>> /* wreckage: 深水沙/岩 */ <<if $depth >= 100 && ($maptype === "sand" || $maptype === "flat")>> <<set _evCandIds[_evCandIds.length] = "wreckage">> <</if>> /* god_bone_field: 极深峭壁 */ <<if $depth >= 300 && $maptype === "cliff">> <<set _evCandIds[_evCandIds.length] = "god_bone_field">> <</if>> /* sealed_container: 浅水通用 */ <<if $depth <= 200>> <<set _evCandIds[_evCandIds.length] = "sealed_container">> <</if>> /* creature_swarm: 中层水域 */ <<if $depth >= 50 && $depth <= 500>> <<set _evCandIds[_evCandIds.length] = "creature_swarm">> <</if>> /* thermal_vent: 深水岩/峭壁 */ <<if $depth >= 500 && ($maptype === "flat" || $maptype === "cliff")>> <<set _evCandIds[_evCandIds.length] = "thermal_vent">> <</if>> /* fog_anomaly: 极浅,特定天气 */ <<if $depth <= 30 && ($weather === 3 || $weather === 6)>> <<set _evCandIds[_evCandIds.length] = "fog_anomaly">> <</if>> /* mutant_creature: 低安定值深水 */ <<if $san <= 60 && $depth >= 100>> <<set _evCandIds[_evCandIds.length] = "mutant_creature">> <</if>> /* thermal_field: 深水岩/峭壁 */ <<if $depth >= 400 && ($maptype === "flat" || $maptype === "cliff")>> <<set _evCandIds[_evCandIds.length] = "thermal_field">> <</if>> /* salt_lake: 沙/岩平底,中深度 */ <<if $depth >= 200 && $depth <= 2000 && ($maptype === "sand" || $maptype === "flat")>> <<set _evCandIds[_evCandIds.length] = "salt_lake">> <</if>> /* biolum_bloom: 中浅水通用 */ <<if $depth <= 400>> <<set _evCandIds[_evCandIds.length] = "biolum_bloom">> <</if>> /* debris_field: 通用(沉降不限地形) */ <<if $depth <= 1000>> <<set _evCandIds[_evCandIds.length] = "debris_field">> <</if>> /* giant_kelp: grass/forest 型地形浅中水 */ <<if $depth <= 300 && ($maptype === "grass" || $maptype === "forest")>> <<set _evCandIds[_evCandIds.length] = "giant_kelp">> <</if>> /* hunting_pack: 开放水域,中层 */ <<if $depth >= 50 && $depth <= 800>> <<set _evCandIds[_evCandIds.length] = "hunting_pack">> <</if>> /* Fisher-Yates 乱序 */ <<for _ei = _evCandIds.length - 1; _ei > 0; _ei-->> <<set _ej = Math.floor(Math.random() * (_ei + 1))>> <<set _etmp = _evCandIds[_ei]>> <<set _evCandIds[_ei] = _evCandIds[_ej]>> <<set _evCandIds[_ej] = _etmp>> <</for>> /* 逐一掷骰,找到就触发 */ <<if !$eventDefs>><<eventTable>><</if>> <<for _ei = 0; _ei < _evCandIds.length; _ei++>> <<set _evd = $eventDefs[_evCandIds[_ei]]>> <<if _evd && Math.random() < _evd.baseChance>> <<set $eventTimer = 0>> <<if _evd.type === "unstable" && _evd.timerRange>> <<set $eventTimer = _evd.timerRange[0] + Math.floor(Math.random() * (_evd.timerRange[1] - _evd.timerRange[0] + 1))>> <</if>> <<set $activeEvent = {id:_evCandIds[_ei], name:_evd.name, desc:_evd.desc, type:_evd.type, actions:_evd.actions}>> <<set $sailspd = 0>> <<set $fishing = 0>> <<set $eventPass = 0>> <<break>> <</if>> <</for>> /* ══ 未触发中型事件时检查小型事件(由 spawnSmallEvent 统一调度) ══ */ <<if !$activeEvent>> <<spawnSmallEvent "sailing">> <<if $pendingEvent>> <<set $activeSmallEvent = $pendingEvent>> <<set $pendingEvent = null>> <<set $sailspd = 0>> <<set $eventPass = 0>> <</if>> <</if>> /* ══ NPC 遭遇(中型事件模板)══ */ <<if !$activeEvent && !$activeSmallEvent>> <<if !$npcDefTable>><<npcDefs>><</if>> <<set _npcCoolOk = (!$npcSpawnCooldown || $npcSpawnCooldown <= ($day||0))>> <<if _npcCoolOk && Math.random() < 0.0008>> <<set _npcPool = []>> <<set _npcKeys = Object.keys($npcDefTable)>> <<for _ni = 0; _ni < _npcKeys.length; _ni++>> <<set _nd = $npcDefTable[_npcKeys[_ni]]>> <<set _nOk = (_nd.condition === "always")>> <<set _nInCtx = false>> <<for _nci = 0; _nci < _nd.spawnCtx.length; _nci++>> <<if _nd.spawnCtx[_nci] === "sailing">><<set _nInCtx = true>><</if>> <</for>> <<if _nOk && _nInCtx>> <<for _nwi = 0; _nwi < _nd.weight; _nwi++>><<run _npcPool.push(_npcKeys[_ni])>><</for>> <</if>> <</for>> <<if _npcPool.length > 0>> <<set _npcPickId = _npcPool[Math.floor(Math.random() * _npcPool.length)]>> <<set $activeNpc = $npcDefTable[_npcPickId]>> <<set $activeEvent = {id:"npc_"+_npcPickId, name:$activeNpc.name, desc:"一艘不明船只靠近,对方发来接触信号。", type:"event", actions:["前去交谈","无视离开"]}>> <<set $sailspd = 0>> <<set $eventPass = 0>> <</if>> <</if>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "tickEvent">> <<if $activeEvent && $activeEvent.type === "unstable">> <<set $eventTimer -= 1>> <<if $eventTimer <= 0>> <<run $eventLog.push({ id: $activeEvent.id, name: $activeEvent.name, outcome: "消散" })>> <<set $activeEvent = 0>> <<set $eventTimer = 0>> <<set $eventPass = 0>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "fishStatus">> <<set _fs_depthKey = "0-50">> <<if $depth <= 50>> <<set _fs_depthKey = "0-50">> <<elseif $depth <= 150>> <<set _fs_depthKey = "50-150">> <<elseif $depth <= 300>> <<set _fs_depthKey = "150-300">> <<elseif $depth <= 1000>> <<set _fs_depthKey = "300-1000">> <<else>> <<set _fs_depthKey = "1000+">> <</if>> <<set _fs_terrainKey = "开阔水域">> <<if $depthdeep - $depth <= 20>> <<set _fs_terrainKey = "底栖">> <<elseif $maptype === "sand">> <<set _fs_terrainKey = "沙海床">> <<elseif $maptype === "flat">> <<set _fs_terrainKey = "岩海床">> <<elseif $maptype === "cliff">> <<set _fs_terrainKey = "峭壁">> <<elseif $maptype === "grass">> <<set _fs_terrainKey = "海草床">> <<elseif $maptype === "reef">> <<set _fs_terrainKey = "珊瑚礁">> <<elseif $maptype === "forest">> <<set _fs_terrainKey = "海藻森林">> <</if>> <<set _fs_totalWeight = 0>> <<set _fs_topSpecies = []>> <<if $pools>> <<set _fs_keys = Object.keys($pools)>> <<for _fi = 0; _fi < _fs_keys.length; _fi++>> <<set _fs_sp = $pools[_fs_keys[_fi]]>> <<set _fs_w = Number(_fs_sp.baseWeight) || 1>> <<if _fs_sp.customWeights && _fs_sp.customWeights.depth>> <<set _fs_dm = _fs_sp.customWeights.depth[_fs_depthKey]>> <<if _fs_dm !== undefined>> <<set _fs_w *= Number(_fs_dm)>> <</if>> <</if>> <<if _fs_sp.customWeights && _fs_sp.customWeights.terrain>> <<set _fs_tm = _fs_sp.customWeights.terrain[_fs_terrainKey]>> <<if _fs_tm !== undefined>> <<set _fs_w *= Number(_fs_tm)>> <</if>> <</if>> <<if _fs_w > 0>> <<set _fs_totalWeight += _fs_w>> <<if _fs_w >= 5>> <<run _fs_topSpecies.push({ name: _fs_sp.name, weight: _fs_w, tags: (_fs_sp.tags || []) })>> <</if>> <</if>> <</for>> <</if>> /* ── 渔具状态描述 ── */ <<set _fs_gearDesc = "">> <<if $fishingGear === "渔网">> <<if _fs_terrainKey === "沙海床" || _fs_terrainKey === "底栖">> <<set _fs_gearDesc = "渔网沿海底拖行,卷起一团灰白色的沙尘,细小的生物随沉积物一同涌入网口。">> <<elseif _fs_terrainKey === "珊瑚礁">> <<set _fs_gearDesc = "渔网在礁盘间穿行,网绳与珊瑚枝桠轻轻碰擦,发出低沉的摩擦声。">> <<elseif _fs_terrainKey === "海草床">> <<set _fs_gearDesc = "渔网穿过密集的海草丛,叶片被网绳拂过,偶尔有小型生物慌乱地从网眼逃脱。">> <<elseif _fs_terrainKey === "岩海床">> <<set _fs_gearDesc = "渔网在岩面上磕磕绊绊地前行,石块碰撞的震动沿绳索传回船内。">> <<elseif _fs_terrainKey === "峭壁">> <<set _fs_gearDesc = "渔网悬于峭壁旁侧,随洋流起伏,壁面上附着的生物对它保持着警惕的距离。">> <<elseif _fs_terrainKey === "海藻森林">> <<set _fs_gearDesc = "渔网在巨藻林中铺展,大片藻叶缓慢飘过网面,辨别猎物的难度大幅上升。">> <<elseif $depth <= 50>> <<set _fs_gearDesc = "渔网在浅水中张开,能隐约看见网影下方涌动的鱼群轮廓。">> <<else>> <<set _fs_gearDesc = "渔网在深水中静静展开,四周一片漆黑,只有触碰网绳的生物才会引发细微震动。">> <</if>> <<else>> <<if $fishingBait === "内脏碎肉">> <<set _fs_gearDesc = "鱼线末端挂着腥气四溢的内脏碎肉,腥味在水中缓慢扩散。">> <<elseif $fishingBait === "血饵">> <<set _fs_gearDesc = "血饵在水中晕开暗红丝缕,随洋流向远处蔓延,嗅觉敏锐的猎手也许正在循迹而来。">> <<elseif $fishingBait === "草饵">> <<set _fs_gearDesc = "草饵静静悬在水中,颜色与周围植被相近,适合诱引藻类间觅食的草食性鱼类。">> <<else>> <<set _fs_gearDesc = "鱼钩空悬于水中,好奇的小鱼靠近嗅探后迅速游走。">> <</if>> <<if $fishingLight === "开启">> <<set _fs_gearDesc += "潜艇灯光在黑暗中晕开昏黄,趋光性生物正朝这里聚集。">> <</if>> <</if>> /* ── 生物密度描述 ── */ <<set _fs_spCount = $pools ? Math.max(Object.keys($pools).length, 1) : 1>> <<set _fs_avgW = _fs_totalWeight / _fs_spCount>> <<set _fs_density = "">> <<if _fs_avgW >= 6>> <<set _fs_density = "这片水域生机盎然——">> <<elseif _fs_avgW >= 3.5>> <<set _fs_density = "水中偶有生物的轮廓掠过——">> <<elseif _fs_avgW >= 1.5>> <<set _fs_density = "周围相当平静,偶尔才能捕捉到一丝生命的迹象——">> <<else>> <<set _fs_density = "这里如同死寂,水压将所有声音都压得沉默——">> <</if>> /* ── 标志性生物描述 ── */ <<set _fs_spDesc = "">> <<if _fs_topSpecies.length > 0>> <<set _fs_mi = Math.floor(Math.random() * _fs_topSpecies.length)>> <<set _fs_msp = _fs_topSpecies[_fs_mi]>> <<set _fs_beh = "在附近游弋。">> <<if _fs_msp.tags.includes("群居")>> <<set _fs_beh = "成群穿越视野,留下短暂的涡流。">> <<elseif _fs_msp.tags.includes("底栖")>> <<set _fs_beh = "紧贴海床缓慢移动,几乎与沉积物融为一体。">> <<elseif _fs_msp.tags.includes("掠食性") || _fs_msp.tags.includes("肉食性")>> <<set _fs_beh = "大幅度巡游,保持着掠食者特有的警觉与从容。">> <<elseif _fs_msp.tags.includes("趋光性") && $fishingLight === "开启">> <<set _fs_beh = "被灯光吸引,在光晕边缘徘徊。">> <<elseif _fs_msp.tags.includes("夜行性") && ($showhour >= 20 || $showhour <= 5)>> <<set _fs_beh = "趁着黑暗悄悄活跃,动作格外敏锐。">> <</if>> <<set _fs_spDesc = _fs_msp.name + _fs_beh>> <<if _fs_topSpecies.length >= 2 && Math.random() < 0.35>> <<set _fs_si2 = (_fs_mi + 1 + Math.floor(Math.random() * (_fs_topSpecies.length - 1))) % _fs_topSpecies.length>> <<set _fs_sp2 = _fs_topSpecies[_fs_si2]>> <<set _fs_spDesc += "远处还有" + _fs_sp2.name + "的身影一闪而过。">> <</if>> <<else>> <<set _fs_spDesc = "没有任何已知生物的踪迹。">> <</if>> <div class="fish-status"><div class="fish-status-gear"></div><div class="fish-status-density"><<print _fs_density>><<print _fs_gearDesc>></div></div> <</widget>> <</nobr>>
<<nobr>> <<widget "resolveEvent">> <<set _re_action = $args[0]>> <<if !$activeEvent>> <<return>> <</if>> <<set _re_id = $activeEvent.id>> <<set _re_name = $activeEvent.name>> <<if _re_id === "sealed_container" && _re_action === "打捞">> <<set _re_rolls = [ { id: "metal", qty: [1,3] }, { id: "wood", qty: [0,2] }, { id: "rope", qty: [0,2] }, { id: "coal", qty: [0,3] } ]>> <<set _re_log = "打捞所得:">> <<for _ri = 0; _ri < _re_rolls.length; _ri++>> <<set _rr = _re_rolls[_ri]>> <<set _rq = Math.floor(Math.random() * (_rr.qty[1] - _rr.qty[0] + 1)) + _rr.qty[0]>> <<if _rq > 0>> <<additem _rr.id _rq>> <<set _re_log += State.variables.items[_rr.id].name + "×" + _rq + " ">> <</if>> <</for>> <<set $lastEventText = _re_log>> <<elseif _re_id === "thermal_vent" && _re_action === "采集热泉提取物">> <<additem "thermal_ext" 1>> <<set $lastEventText = "采集到热泉提取物×1">> <<elseif _re_id === "creature_swarm" && _re_action === "开始捕鱼">> <<set $fishing = 1>> <<set $lastEventText = "开始在群聚中捕鱼,渔获概率大幅提升!">> <<return>> <<elseif _re_action === "观察记录">> <<set $san -= 5>> <<set $lastEventText = "记录下了异变生物的特征,安定值轻微下降。">> <<elseif _re_action === "紧急下潜逃离">> <<if $depth < $depthdeep>> <<set $depth = Math.min($depth + 50, $depthdeep)>> <</if>> <<set $lastEventText = "紧急下潜,生物消失在上方的黑暗中。">> <<elseif _re_id === "thermal_field" && _re_action === "出仓采集">> <<additem "ember_crystal" 1>><<additem "sulfur_dust" 2>> <<set $lastEventText = "采集到热液结晶和硫磺粉末,温度计显示出仓时温度高了十几度。">> <<elseif _re_id === "thermal_field" && _re_action === "观察记录">> <<set $san = Math.min(100, $san + 3)>> <<set $lastEventText = "详细记录了热泉的活动规律和生物分布,科学价值不低。安定值微升。">> <<elseif _re_id === "salt_lake" && _re_action === "采集卤水样本">> <<additem "seawater_ext" 3>><<additem "sand_extract" 1>> <<set $lastEventText = "采集了高浓度卤水和边缘盐晶,样本密封保存。">> <<elseif _re_id === "salt_lake" && _re_action === "靠近探查边缘">> <<set _saltRoll = Math.random()>> <<if _saltRoll < 0.4>> <<additem "ember_crystal" 1>> <<set $lastEventText = "边缘的盐晶形态异常,里面封存着罕见的矿物结晶——是火系晶石。">> <<elseif _saltRoll < 0.7>> <<set $lastEventText = "卤水边缘密度梯度导致浮力异常,费了不少时间才稳住姿态。">> <<else>> <<additem "seawater_ext" 2>> <<set $lastEventText = "边缘堆积了不少析出的盐矿,顺手采走了几块。">> <</if>> <<elseif _re_id === "biolum_bloom" && _re_action === "利用光照捕捞">> <<additem "sardine" 3>><<additem "anchovy" 2>><<additem "jellyfluid" 1>> <<set $lastEventText = "发光体吸引来大批趋光鱼群,顺势大丰收,还捞到了几只水母。">> <<elseif _re_id === "biolum_bloom" && _re_action === "静待观察">> <<set $san = Math.min(100, $san + 5)>> <<set $lastEventText = "这片蓝白色的流动光芒让人心情平静,难得的景象。安定值回升。">> <<elseif _re_id === "debris_field" && _re_action === "停船打捞">> <<additem "metal" 3>><<additem "wood" 2>><<additem "rope" 2>> <<set _debrisRoll = Math.random()>> <<if _debrisRoll < 0.2>> <<additem "relic_log" 1>> <<set $lastEventText = "打捞到大量材料,还发现了一个密封防水包,里面有几页残存的日志。">> <<else>> <<set $lastEventText = "打捞到金属碎片、木料和绳索,这些东西到港后能卖个好价钱。">> <</if>> <<elseif _re_id === "debris_field" && _re_action === "穿越残骸带">> <<set _pierceRoll = Math.random()>> <<if _pierceRoll < 0.3>> <<set $lastEventText = "顺利穿越,只有几次轻微碰撞。">> <<else>> <<additem "metal" 1>> <<set $lastEventText = "穿越时顺手挂住几块不错的金属碎片,带走了。">> <</if>> <<elseif _re_id === "giant_kelp" && _re_action === "进入采集">> <<additem "kelp" 6>><<additem "kelp_fiber" 2>> <<set $lastEventText = "深入密林采集,收获大量巨藻和纤维,但出来时费了些周折。">> <<elseif _re_id === "giant_kelp" && _re_action === "寻找通道穿越">> <<set _kelpRoll = Math.random()>> <<if _kelpRoll < 0.5>> <<additem "kelp" 2>> <<set $lastEventText = "找到了一条相对宽敞的通道,顺利穿越,还顺带割了些藻茎。">> <<else>> <<set $lastEventText = "通道多次折回,花了很长时间才穿过密林。">> <</if>> <<elseif _re_id === "hunting_pack" && _re_action === "尾随跟踪">> <<additem "fish_roe" 2>><<additem "sardine" 2>> <<set $san = Math.max(0, $san - 5)>> <<set $lastEventText = "在捕猎者后方跟随,捡拾到被遗弃的鱼卵和受伤逃窜的小鱼,但安定值有些下降。">> <<elseif _re_id === "hunting_pack" && _re_action === "驱赶猎食">> <<set $san = Math.max(0, $san - 10)>> <<set $lastEventText = "驱赶捕食者时形势一度紧张,最终它们离去,但留下了一段令人不安的对峙记忆。安定值下降。">> <<elseif _re_id.indexOf("npc_") === 0 && _re_action === "前去交谈">> <<set $activeEvent = 0>> <<set $eventTimer = 0>> <<set $eventPass = 0>> <<set $npcReturn = "航行">> <<goto "NPC_对话">> <<elseif _re_id.indexOf("npc_") === 0 && _re_action === "无视离开">> <<set $activeNpc = null>> <<set $npcSpawnCooldown = ($day||0) + 3>> <<set $lastEventText = "无视了对方的信号,对方船只渐渐远去。">> <<elseif _re_id.indexOf("quest_") === 0 && _re_action === "查看日志">> /* 主线通知 → 跳转书桌 */ <<set $activeEvent = 0>> <<set $eventTimer = 0>> <<set $eventPass = 0>> <<goto "书桌">> <<elseif _re_id.indexOf("quest_") === 0 && _re_action === "稍后再看">> <<set $lastEventText = "日记待查阅。">> <<else>> <<set $lastEventText = "已处理。">> <</if>> <<run $eventLog.push({ id: _re_id, name: _re_name, outcome: _re_action })>> <<set $activeEvent = 0>> <<set $eventTimer = 0>> <<set $eventPass = 0>> <</widget>> <</nobr>>
<<nobr>> <<widget "cpDefs">> <<set $cps = {}>> <<set $activeCpIds = []>> /* ══════════════════════════════════════════ Viona 模板 新增 CP 时复制整块,修改各字段内容即可 ══════════════════════════════════════════ */ <<set $cps.viona = { /* ── 基础信息 ── */ id : "viona", name : "维奥娜", /* ── 五维数值 (0-100) ── */ hunger : 85, water : 90, energy : 70, mood : 1, /* 0=低落 1=平常 2=愉快 */ calm : 1, /* 0=不安 1=平静 2=安心 */ /* ── 状态 tag ── */ wet : false, injured : 0, /* 0=无 1=轻伤 2=重伤 */ sick : false, /* ── 数值速率倍率 ── */ hungerRate : 1.0, waterRate : 1.0, /* ── 精力速率(每分钟)── */ energyRates : { sleep : 0.18, rest : 0.06, normal : -0.025, heavy : -0.12 }, /* ── 意图触发阈值 ── */ intentThresholds : { sleepAt : 22, napAt : 45, eatAt : 28, drinkAt : 28 }, /* ── 自由活动权重 ── 只列出该角色会做的行动,不写的行动不会触发 权重数值越大越常做,不需要加和为特定值 */ activityWeights : { outside : 20, watch : 20, disassemble : 15, exercise : 15, cook : 15, tidy : 10, nap : 5 }, /* ── 烹饪方式列表(随机从中选) ── */ cookMethods : ["明火烤", "铜锅炖", "煎炒"], /* ── 偏好食材 id 列表(烹饪时优先取用,赠食时心情+1档)── */ foodPrefs : [], drinkPrefs : [], /* ── 可分解鱼获 id 列表 ── */ fishIds : ["fish_meat", "eel", "anglerfish", "kingcrab"], /* ══ 场景文本 ══ sceneTexts : 房间内一行简短描述(<<cpSceneRender>> 使用) detailTexts : 详情页完整描述(<<cp详情>> 使用) 两者均按 action 分组,支持字符串或数组(数组时随机取一条) actionDetail 变量可在文本中用 {detail} 占位,渲染时自动替换 */ sceneTexts : { sleep : "被子隆起卷成一团,轻轻起伏着,维奥娜睡着了。", nap : "维奥娜靠在角落里打盹,神情放松。", eat : [ "维奥娜坐在桌边狼吞虎咽。", "维奥娜端着碗,吃得挺专心的。" ], outside : "舱门半掩着,维奥娜出去了。", watch : "维奥娜倚在舷窗边,目光顺着水流漫漫飘远。", disassemble : "维奥娜蹲在角落里,正在处理今天的渔获。", exercise : "维奥娜在舱内做着某种训练,动作重复而专注。", cook : "厨房飘出一点气味,维奥娜在做饭。", tidy : "维奥娜在仓库里翻翻整整,搬动箱子的声音偶尔传出来。" }, detailTexts : { sleep : "维奥娜蜷缩在铺位上,被子裹得严实,呼吸平稳绵长。", nap : "维奥娜靠着墙角小睡,头微微低着,看起来睡得不深。", eat : [ "维奥娜坐在厨房的小桌旁,盘子里不知道盛了什么,吃得很认真。", "维奥娜端着碗站在角落,一口一口吃得挺满足的样子。" ], outside : "舱门通道只留下一片水渍,也不知道她现在在哪,但可以确定的是,她一定会回家的。", watch : "维奥娜靠在驾驶舱的舷窗边,视线顺着黑暗的水流漫游,也不知道在想什么。", disassemble : "维奥娜在仓库里处理渔获,刀工利落,偶尔把什么东西顺手扔进收纳箱里。", exercise : "维奥娜正在舱内练习,汗珠沿着额边滑落,神情专注,不像打算搭理人的样子。", cook : "维奥娜在厨房里忙活,锅铲碰撞声不时传来,她偶尔低头对着什么皱一下眉。", tidy : "维奥娜把仓库里的箱子重新归置了一遍,虽说没什么实际效果,但看起来整齐多了。" }, /* ── 位置与行动 ── */ location : "休息室", action : "sleep", actionEndTime : 0, actionDetail : "", /* ── 通知 ── */ pendingNotify : { text: "", expire: -1 }, notifyCooldown : 0, /* ── 主动事件 ── */ proactiveCooldown : 0, lastChatDay : 0, /* ── 记忆 ── */ recentMemory : { tag: "", day: 0, expire: -1 }, bond : 50, /* ── tick 基准 ── */ lastTickTime : 0 }>> /* ── 时间基准初始化 ── */ <<set _cpInitNow = ($day || 1) * 1440 + ($hour || 7) * 60 + ($minute || 0)>> <<set $cps.viona.actionEndTime = _cpInitNow + 480>> <<set $cps.viona.lastTickTime = _cpInitNow>> /* ── 激活 viona ── 其他 CP 攻略后在剧情节点执行: <<set $cps.xxx = { id:"xxx", name:"...", sceneTexts:{...}, ... }>> <<set $cps.xxx.lastTickTime = $day*1440+$hour*60+$minute>> <<run $activeCpIds.push("xxx")>> */ <</widget>> <</nobr>>
<<set $items = { /* ══════════════════════════════════════════ 渔获 · 鱼类 ══════════════════════════════════════════ */ salmon: { size: 2, name: "鲑鱼", type: "渔获", subtype: "鱼类", baseWeight: 8, desc: "洄游性鱼类,身披银红斑纹。肉质丰腴,是上好的食材,骨骼中隐约含有某种微弱的元素响应。" }, seabass: { size: 2, name: "鲈鱼", type: "渔获", subtype: "鱼类", baseWeight: 9, desc: "常见的浅海鱼种,警觉性高。鱼鳃膜极薄,炼金师将其用于过滤微量元素。" }, tuna: { size: 3, name: "金枪鱼", type: "渔获", subtype: "鱼类", baseWeight: 3, desc: "体型巨大的掠食者,终生不停游动。深红色的肌肉中储存着大量血液,是血液系炼金原料的来源之一。" }, sardine: { size: 1, name: "沙丁鱼", type: "渔获", subtype: "鱼类", baseWeight: 12, desc: "成群结队的小型鱼类,在夜间会被灯光大量吸引。数量庞大,是大型掠食者的主要食物来源。" }, herring: { size: 1, name: "鲱鱼", type: "渔获", subtype: "鱼类", baseWeight: 11, desc: "银白色鱼群在浅海中形成壮观的队列。繁殖期会产大量鱼卵,可供食用或炼金提取。" }, grouper: { size: 2, name: "石斑鱼", type: "渔获", subtype: "鱼类", baseWeight: 6, desc: "礁岩地带的伏击者,色彩斑斓。鳃膜构造特殊,能在高压环境下正常呼吸。" }, mahi: { size: 2, name: "鲯鳅", type: "渔获", subtype: "鱼类", baseWeight: 5, desc: "开阔水域的速游者,拥有艳丽的黄绿色泽。鳍膜宽大,晒干后可作为轻质炼金材料。" }, cod: { size: 2, name: "鳕鱼", type: "渔获", subtype: "鱼类", baseWeight: 8, desc: "冷水域常见食用鱼,鱼肝富含油脂。大航海时代各国船队的主要蛋白质来源,盐腌后可长期保存。" }, eel: { size: 2, name: "鳗鱼", type: "渔获", subtype: "鱼类", baseWeight: 6, desc: "修长光滑的深海过客,胆囊分泌的胆汁气味异常刺鼻。有报告指出在神域边缘附近捕获的鳗鱼体内出现不明结晶。" }, flounder: { size: 2, name: "比目鱼", type: "渔获", subtype: "鱼类", baseWeight: 7, desc: "扁平的底栖鱼类,双眼位于同侧。藏匿于沙层之中,鱼鳞颗粒细密,磨成粉末后带有轻微的土元素响应。" }, mackerel: { size: 1, name: "鲭鱼", type: "渔获", subtype: "鱼类", baseWeight: 10, desc: "中层水域的群游鱼类,背部有深色波纹。脂肪含量高,烟熏处理后风味极佳。" }, bream: { size: 2, name: "鲷鱼", type: "渔获", subtype: "鱼类", baseWeight: 7, desc: "礁岩区常见的中型鱼,因肉质鲜甜在贸易时代曾是贵族餐桌的常客。繁殖期鱼卵品质极高。" }, anchovy: { size: 1, name: "凤尾鱼", type: "渔获", subtype: "鱼类", baseWeight: 12, desc: "细小的滤食性鱼类,是整个海洋食物链的基石。个体虽小,大量聚集时形成的生物量不可忽视。" }, barracuda: { size: 2, name: "梭子鱼", type: "渔获", subtype: "鱼类", baseWeight: 5, desc: "凶猛的掠食性鱼类,牙齿锋利如刀。血液腥气浓重,胆汁中含有高浓度的火系催化成分。" }, hairtail: { size: 1, name: "带鱼", type: "渔获", subtype: "鱼类", baseWeight: 8, desc: "细长如银带,夜间受光源吸引浮出深层。鱼鳞极薄且密,经特殊处理后会产生轻微的灼烧性粉末。" }, sunfish: { size: 4, name: "翻车鱼", type: "渔获", subtype: "鱼类", baseWeight: 1, rarity: "稀有", desc: "形态怪异的巨型硬骨鱼,像是海洋开了一个玩笑。体内含有大量海水提炼物,偶有深海目结构存在于其眼部。" }, anglerfish: { size: 3, name: "鮟鱇", type: "渔获", subtype: "鱼类", baseWeight: 1, rarity: "稀有", desc: "黑暗深处的发光陷阱。额头的发光器官至今机制不明,但炼金师证实其中存在稳定的火系能量残留,胆汁毒性极强。" }, /* ══════════════════════════════════════════ 渔获 · 贝类 ══════════════════════════════════════════ */ scallop: { size: 1, name: "扇贝", type: "渔获", subtype: "贝类", baseWeight: 9, desc: "双壳扇形,依靠喷水游动。闭壳肌肥厚鲜美,外壳磨碎后是常见的土系粉末原料。" }, clam: { size: 1, name: "蛤蜊", type: "渔获", subtype: "贝类", baseWeight: 10, desc: "沙层中的隐居者,壳纹如年轮记录着岁月。偶有珍珠孕育其中,虽小却圆润光洁。" }, oyster: { size: 1, name: "牡蛎", type: "渔获", subtype: "贝类", baseWeight: 8, desc: "礁石上的滤食者,其肉质被誉为海中之乳。孕育珍珠的概率高于其他贝类,黑珍珠极为罕见。" }, mussel: { size: 1, name: "贻贝", type: "渔获", subtype: "贝类", baseWeight: 10, desc: "用足丝附着礁岩,成片聚生。肉质深色,味道浓郁,壳薄而坚,是常见的建造辅材。" }, conch: { size: 1, name: "海螺", type: "渔获", subtype: "贝类", baseWeight: 7, desc: "旋涡状外壳内深藏肥美螺肉,磨碎后的螺粉具有较高的水系亲和性。空壳可用作简易信号器。" }, seaurchin: { size: 1, name: "海胆", type: "渔获", subtype: "贝类", baseWeight: 7, desc: "棘刺密布的球形生物,卵巢(海胆黄)鲜美至极。棘刺核心密度极高,是土系核心材料之一。" }, /* ══════════════════════════════════════════ 渔获 · 虾类 ══════════════════════════════════════════ */ prawn: { size: 1, name: "对虾", type: "渔获", subtype: "虾类", baseWeight: 9, desc: "常见的中型虾类,肉质弹嫩。外壳薄而半透明,整体食用价值高于炼金价值。" }, lobster: { size: 2, name: "龙虾", type: "渔获", subtype: "虾类", baseWeight: 2, rarity: "稀有", desc: "礁岩区的甲壳霸主,夜间独自觅食。坚硬的甲壳富含结构性土元素,蟹甲粉末是常见炼金耗材。" }, mantisshrimp: { size: 1, name: "皮皮虾", type: "渔获", subtype: "虾类", baseWeight: 7, desc: "拥有强力打击螯肢,能以极快速度破碎贝壳。捕捉时需谨慎——它们对玻璃制容器有天然的破坏欲。" }, sweetshrimp: { size: 1, name: "甜虾", type: "渔获", subtype: "虾类", baseWeight: 10, desc: "小型浅粉色虾类,肉质甘甜细腻。通常成群出现,是浅海渔网的常见收获。" }, cherryshrimp: { size: 1, name: "樱虾", type: "渔获", subtype: "虾类", baseWeight: 11, desc: "体色鲜红如樱花,群游时将海面染成一片艳色。体型极小,通常整体烹饪食用。" }, /* ══════════════════════════════════════════ 渔获 · 蟹类 ══════════════════════════════════════════ */ kingcrab: { size: 3, name: "帝王蟹", type: "渔获", subtype: "蟹类", baseWeight: 2, rarity: "稀有", desc: "体型巨大的深冷水霸主,蟹腿张开可达一米以上。甲壳极度坚硬,偶尔内部会形成类似烬晶的结晶体,成因不明。" }, snowcrab: { size: 3, name: "雪蟹", type: "渔获", subtype: "蟹类", baseWeight: 2, rarity: "稀有", desc: "峭壁地形的专属居民,洁白的甲壳如覆霜雪。只在极深的悬崖壁面活动,蟹肉鲜甜,甲壳粉末纯净。" }, bluecrab: { size: 2, name: "蓝蟹", type: "渔获", subtype: "蟹类", baseWeight: 8, desc: "行动敏捷的中型蟹,蓝色螯足颇具辨识度。适应性强,从浅海到中层都有分布。" }, swimmingcrab: { size: 2, name: "梭子蟹", type: "渔获", subtype: "蟹类", baseWeight: 8, desc: "善于游泳的蟹类,后足特化为桨状。是最常见的食用蟹种,肉质饱满,蟹黄丰腴。" }, flowercrab: { size: 2, name: "花蟹", type: "渔获", subtype: "蟹类", baseWeight: 7, desc: "甲壳上有美丽的花纹,多见于珊瑚礁区域。因栖息环境的关系,甲壳中偶有珊瑚碎屑附着。" }, redcrab: { size: 2, name: "红蟹", type: "渔获", subtype: "蟹类", baseWeight: 5, desc: "珊瑚礁的鲜艳住客,通体橙红。甲壳颜色来自特殊色素沉积,与珊瑚的矿物成分存在某种关联。" }, /* ══════════════════════════════════════════ 渔获 · 头足类 ══════════════════════════════════════════ */ squid: { size: 1, name: "鱿鱼", type: "渔获", subtype: "头足", baseWeight: 9, desc: "高速游动的群居捕食者,夜间趋光性强。气囊能精确控制浮力,是风系炼金材料的重要来源。" }, cuttlefish: { size: 2, name: "墨鱼", type: "渔获", subtype: "头足", baseWeight: 8, desc: "伪装大师,能瞬间改变体色。体内的乌贼骨是天然的水系晶体材料,墨汁有特殊的显影功效。" }, octopus: { size: 2, name: "章鱼", type: "渔获", subtype: "头足", baseWeight: 7, desc: "极度智慧的八腕生物,据称能感知到神域的微弱波动。深眼腺体中偶有特殊结晶,成因尚待研究。" }, /* ══════════════════════════════════════════ 渔获 · 藻类 ══════════════════════════════════════════ */ kelp: { size: 1, name: "海带", type: "渔获", subtype: "藻类", baseWeight: 10, foodtags: ["海草"], desc: "随洋流摇曳的宽叶藻类,纤维坚韧。晒干后可食用,提取的海水矿物盐带有水系亲和性。" }, wakame: { size: 1, name: "裙带菜", type: "渔获", subtype: "藻类", baseWeight: 9, foodtags: ["海草"], desc: "叶缘如裙摆般舒展,质地柔滑。是汤品和腌渍食品的上等食材,纤维品质不亚于海带。" }, nori: { size: 1, name: "紫菜", type: "渔获", subtype: "藻类", baseWeight: 10, foodtags: ["海草"], desc: "薄如蝉翼的暗紫色藻类,富含矿物质。晒干后体积大幅缩小,草丝状纤维可用于炼金。" }, agarcoral: { size: 1, name: "石花菜", type: "渔获", subtype: "藻类", baseWeight: 5, foodtags: ["海草"], desc: "生长于珊瑚礁和岩面的红藻,结构坚硬。加热后释放胶质,是制作凝冻食品和炼金凝固剂的原料。" }, /* ══════════════════════════════════════════ 渔获 · 占位(事件可获取,不出现在主列表) ══════════════════════════════════════════ */ seahorse: { size: 1, name: "海马", type: "渔获", subtype: "鱼类", baseWeight: 1, rarity: "稀有", desc: "微小的甲胄骑士,由雄性孵育后代。骨骼与普通鱼类截然不同,其流涌石亲和性已被多名炼金师证实。" }, starfish: { size: 1, name: "海星", type: "渔获", subtype: "其他", baseWeight: 6, desc: "五辐对称的底栖生物,具有惊人的再生能力。骨骼碎烧后的骨灰纯度较高,偶有流涌石亲和性。" }, jellyfish: { size: 1, name: "水母", type: "渔获", subtype: "其他", baseWeight: 8, desc: "漂浮于中层水域的半透明幽灵。体液富含水系元素,膜体经提炼可得到纯净的水系膜质材料。" }, /* ══════════════════════════════════════════ 食材 foodtags 用于烹饪系统匹配食谱 ══════════════════════════════════════════ */ /* ── 通用鱼肉 ── */ fish_meat: { size: 1, name: "鱼肉", type: "食材", foodtags: ["鱼"], desc: "处理干净的鱼肉块,肉质紧实,适合多种烹饪方式。" }, fish_roe: { size: 1, name: "鱼卵", type: "食材", foodtags: ["鱼", "腥"], desc: "新鲜的鱼卵,腥气浓重但营养丰富,盐腌后风味大变。" }, /* ── 各鱼专属肉 ── */ salmon_meat: { size: 1, name: "鲑鱼肉", type: "食材", foodtags: ["鱼"], desc: "鲑鱼剔除的大块嫩肉,带着天然粉红色,油脂丰富,适合任何烹饪方式。" }, seabass_meat: { size: 1, name: "鲈鱼肉", type: "食材", foodtags: ["鱼"], desc: "鲈鱼洁白细腻的肌肉,几乎无刺,是海鱼中食用价值最高的种类之一。" }, tuna_meat: { size: 1, name: "金枪鱼肉", type: "食材", foodtags: ["鱼"], desc: "深红色大块肌肉,含大量血铁质,生食最能体现其价值。" }, sardine_meat: { size: 1, name: "沙丁鱼肉", type: "食材", foodtags: ["鱼"], desc: "细碎的沙丁鱼肉,脂肪丰富,盐腌后风味转化为浓郁鲜香。" }, herring_meat: { size: 1, name: "鲱鱼肉", type: "食材", foodtags: ["鱼"], desc: "鲱鱼银白色肌肉,油脂均匀,最适合腌制和烟熏处理。" }, grouper_meat: { size: 1, name: "石斑肉", type: "食材", foodtags: ["鱼"], desc: "石斑鱼厚实的白色肌肉,质感弹滑,是底层鱼中品质最高的食材。" }, mahi_meat: { size: 1, name: "鲯鳅肉", type: "食材", foodtags: ["鱼"], desc: "粉白色鱼肉,肉质较硬但风味独特,烤制时散发天然甜香。" }, cod_meat: { size: 1, name: "鳕鱼肉", type: "食材", foodtags: ["鱼"], desc: "雪白厚实的鳕鱼肉,片状剥落,淡而鲜美,是船上最可靠的蛋白质来源。" }, eel_meat: { size: 1, name: "鳗鱼肉", type: "食材", foodtags: ["鱼"], desc: "鳗鱼紧致细长的肌肉,脂肪均匀分布,烤制时渗出大量油脂。" }, flounder_meat: { size: 1, name: "比目鱼肉", type: "食材", foodtags: ["鱼"], desc: "两侧对称的白色薄片鱼肉,肉质极嫩,生食或清蒸最能保留清甜。" }, mackerel_meat: { size: 1, name: "鲭鱼肉", type: "食材", foodtags: ["鱼"], desc: "富含脂肪的深色鱼肉,腥气较重,腌制或烟熏后风味大变。" }, bream_meat: { size: 1, name: "鲷鱼肉", type: "食材", foodtags: ["鱼"], desc: "鲷鱼细腻甘甜的白肉,是所有海鱼中最接近贵族料理的食材。" }, anchovy_meat: { size: 1, name: "凤尾鱼肉", type: "食材", foodtags: ["鱼"], desc: "细小的凤尾鱼肉,腥而鲜,大量处理后可制成浓郁的鱼酱。" }, barracuda_meat: { size: 1, name: "梭子鱼肉", type: "食材", foodtags: ["鱼"], desc: "梭子鱼结实的淡红鱼肉,处理干净后滋味浓郁。" }, hairtail_meat: { size: 1, name: "带鱼肉", type: "食材", foodtags: ["鱼"], desc: "带鱼细长的白色肌肉,刺多但味道鲜甜,煎制时形成酥脆表层。" }, sunfish_meat: { size: 1, name: "翻车鱼肉", type: "食材", foodtags: ["鱼"], desc: "翻车鱼奇特的白色鱼肉,质地介于普通鱼肉和胶质之间,味道温和。" }, anglerfish_meat: { size: 1, name: "鮟鱇肉", type: "食材", foodtags: ["鱼"], desc: "鮟鱇丰腴的深海鱼肉,胶质丰富,炖煮后化为浓郁鲜甜。" }, /* ── 贝类食材 ── */ urchin_roe: { size: 1, name: "海胆黄", type: "食材", foodtags: ["贝", "鲜"], desc: "海胆的生殖腺,鲜黄色,入口即化。鲜度极为重要,需尽快食用。" }, scallop_meat: { size: 1, name: "扇贝肉", type: "食材", foodtags: ["贝"], desc: "扇贝丰腴的闭壳肌,圆润洁白,口感弹嫩,鲜甜几乎不需要调味。" }, clam_meat: { size: 1, name: "蛤蜊肉", type: "食材", foodtags: ["贝"], desc: "蛤蜊的软体,带着浓郁的海水咸鲜,是汤底提鲜的绝佳材料。" }, oyster_meat: { size: 1, name: "牡蛎肉", type: "食材", foodtags: ["贝", "鲜"], desc: "牡蛎饱满的软体,被称为海中之乳。入口即化,带着浓烈的矿物鲜味。" }, mussel_meat: { size: 1, name: "贻贝肉", type: "食材", foodtags: ["贝"], desc: "贻贝深色的肉质,鲜味浓郁,价格低廉但滋味不逊于高档贝类。" }, conch_meat: { size: 1, name: "海螺肉", type: "食材", foodtags: ["贝"], desc: "海螺肥美的螺肉,质地偏硬但口感弹脆,炒制时需要大火快炒。" }, /* ── 虾类食材 ── */ prawn_meat: { size: 1, name: "对虾肉", type: "食材", foodtags: ["虾"], desc: "对虾弹脆的白色虾肉,去壳后比例最高,是最实用的虾类食材。" }, lobster_meat: { size: 1, name: "龙虾肉", type: "食材", foodtags: ["虾"], desc: "龙虾尾部与大钳中肥美的白肉,质地厚实,是虾类中最奢华的食材。" }, mantisshrimp_meat: { size: 1, name: "皮皮虾肉", type: "食材", foodtags: ["虾"], desc: "皮皮虾甲壳下细密的白肉,鲜甜多汁,剥取费力但值得。" }, sweetshrimp_meat: { size: 1, name: "甜虾肉", type: "食材", foodtags: ["虾"], desc: "【占位】" }, cherryshrimp_meat: { size: 1, name: "樱虾肉", type: "食材", foodtags: ["虾"], desc: "【占位】" }, /* ── 蟹类食材 ── */ kingcrab_meat: { size: 1, name: "帝王蟹肉", type: "食材", foodtags: ["蟹"], desc: "帝王蟹腿中厚实的白色蟹肉,纤维分明,是所有蟹类中品质最高的食材。" }, snowcrab_meat: { size: 1, name: "雪蟹肉", type: "食材", foodtags: ["蟹"], desc: "雪蟹纤细的腿肉,洁白细嫩,汁水丰富,蟹黄金黄浓郁。" }, swimmingcrab_meat:{ size: 1, name: "梭子蟹肉", type: "食材", foodtags: ["蟹"], desc: "梭子蟹扁平体内的白色蟹肉,鲜甜程度不输大型蟹类。" }, bluecrab_meat: { size: 1, name: "蓝蟹肉", type: "食材", foodtags: ["蟹"], desc: "【占位】" }, flowercrab_meat: { size: 1, name: "花蟹肉", type: "食材", foodtags: ["蟹"], desc: "【占位】" }, redcrab_meat: { size: 1, name: "红蟹肉", type: "食材", foodtags: ["蟹"], desc: "【占位】" }, /* ── 头足类食材 ── */ octopus_meat: { size: 1, name: "八爪鱼肉", type: "食材", foodtags: ["腕足"], desc: "章鱼或鱿鱼的腕足,含有特殊氨基酸,口感Q弹。烹饪时间不足会韧如皮革。" }, squid_meat: { size: 1, name: "鱿鱼肉", type: "食材", foodtags: ["腕足"], desc: "鱿鱼筒状的外套膜肌肉,质地介于嫩滑和Q弹之间,高温快炒风味最佳。" }, cuttlefish_meat: { size: 1, name: "墨鱼肉", type: "食材", foodtags: ["腕足"], desc: "墨鱼肥厚的外套膜,含有特殊的墨囊香气,炖煮时会将汤汁染成深色。" }, /* ── 兽肉 ── */ pork: { size: 1, name: "猪肉", type: "食材", foodtags: ["兽肉"], desc: "【占位】" }, lamb: { size: 1, name: "羊肉", type: "食材", foodtags: ["兽肉"], desc: "【占位】" }, beef: { size: 1, name: "牛肉", type: "食材", foodtags: ["兽肉"], desc: "【占位】" }, turtle_meat: { size: 1, name: "海龟肉", type: "食材", foodtags: ["兽肉"], desc: "【占位】" }, manatee_meat: { size: 1, name: "海牛肉", type: "食材", foodtags: ["兽肉"], desc: "【占位】" }, whale_meat: { size: 1, name: "鲸鱼肉", type: "食材", foodtags: ["兽肉"], desc: "【占位】" }, seal_meat: { size: 1, name: "海豹肉", type: "食材", foodtags: ["兽肉"], desc: "【占位】" }, chicken_meat: { size: 1, name: "鸡肉", type: "食材", foodtags: ["兽肉"], desc: "【占位】" }, pigeon_meat: { size: 1, name: "鸽肉", type: "食材", foodtags: ["兽肉"], desc: "【占位】" }, rabbit_meat: { size: 1, name: "兔肉", type: "食材", foodtags: ["兽肉"], desc: "【占位】" }, /* ── 块茎 ── */ potato_tuber: { size: 1, name: "海薯", type: "食材", foodtags: ["块茎"], desc: "【占位】适应咸水环境的改良薯类,淀粉含量高,蒸煮后绵密。" }, kelp_tuber: { size: 1, name: "海带茎", type: "食材", foodtags: ["块茎"], desc: "【占位】海带茎部的硬质组织,口感脆爽,含有丰富的矿物质。" }, potato: { size: 1, name: "土豆", type: "食材", foodtags: ["块茎"], desc: "【占位】" }, sweet_potato: { size: 1, name: "红薯", type: "食材", foodtags: ["块茎"], desc: "【占位】" }, carrot: { size: 1, name: "胡萝卜", type: "食材", foodtags: ["块茎"], desc: "【占位】" }, taro: { size: 1, name: "芋头", type: "食材", foodtags: ["块茎"], desc: "【占位】" }, /* ── 谷物 ── */ wheat_grain: { size: 1, name: "麦子", type: "食材", foodtags: ["谷物"], desc: "【占位】干燥的小麦粒,磨粉后是制作面食的基础原料。" }, rice: { size: 1, name: "稻米", type: "食材", foodtags: ["谷物"], desc: "【占位】" }, corn: { size: 1, name: "玉米", type: "食材", foodtags: ["谷物"], desc: "【占位】" }, oats: { size: 1, name: "燕麦", type: "食材", foodtags: ["谷物"], desc: "【占位】" }, /* ── 蔬菜 ── */ tomato: { size: 1, name: "番茄", type: "食材", foodtags: ["蔬菜"], desc: "【占位】" }, cabbage: { size: 1, name: "卷心菜", type: "食材", foodtags: ["蔬菜"], desc: "【占位】" }, pea: { size: 1, name: "豌豆", type: "食材", foodtags: ["蔬菜"], desc: "【占位】" }, mushroom: { size: 1, name: "蘑菇", type: "食材", foodtags: ["蔬菜"], desc: "【占位】" }, eggplant: { size: 1, name: "茄子", type: "食材", foodtags: ["蔬菜"], desc: "【占位】" }, spinach: { size: 1, name: "菠菜", type: "食材", foodtags: ["蔬菜"], desc: "【占位】" }, /* ── 占位食材(事件可获取) ── */ seaweed_grain: { size: 1, name: "海草籽", type: "食材", foodtags: ["谷物"], desc: "【占位】某种耐盐海草的种子,营养密度高,可磨成粗糙的粉末。" }, seajelly: { size: 1, name: "水母冻", type: "食材", foodtags: ["海草", "滑"], desc: "经过处理去除毒素的水母凝冻,口感滑嫩,几乎无味,需要搭配调料才能出彩。" }, sealeaf: { size: 1, name: "海叶菜", type: "食材", foodtags: ["蔬菜"], desc: "【占位】在农场水培槽中生长的叶菜,稍有咸味,口感清脆。" }, sprout: { size: 1, name: "芽苗", type: "食材", foodtags: ["蔬菜"], desc: "【占位】各种植物的嫩芽,生长迅速,是船上最容易获得的绿色食物。" }, sea_berry: { size: 1, name: "盐渍浆果", type: "食材", foodtags: ["浆果"], desc: "【占位】用海盐轻度腌渍的浆果,酸甜咸味交织,对安定值有独特的正面影响。" }, wild_berry: { size: 1, name: "野生浆果", type: "食材", foodtags: ["浆果"], desc: "【占位】在登陆探索时偶尔能采集到的野生浆果,甜度高,种类不明。" }, shell_meat: { size: 1, name: "贝肉", type: "食材", foodtags: ["贝"], desc: "从贝壳中取出的软体组织,鲜甜多汁,生食或轻烹均可。" }, shrimp_meat: { size: 1, name: "虾肉", type: "食材", foodtags: ["虾"], desc: "弹嫩的虾体肌肉,去壳后呈半透明白色,加热后变为粉橙色。" }, crab_meat: { size: 1, name: "蟹肉", type: "食材", foodtags: ["蟹"], desc: "细腻鲜甜的蟹腿与蟹身肌肉,分拆费时但价值颇高。" }, dried_kelp: { size: 1, name: "干海带", type: "食材", foodtags: ["海草"], desc: "晒制或烘干的海带,体积大幅缩小,鲜味浓缩。泡发后可用于多种料理。" }, dried_nori: { size: 1, name: "干紫菜", type: "食材", foodtags: ["海草"], desc: "压薄后干燥的紫菜片,可直接食用或用于包裹食材。" }, salt_refined: { size: 1, name: "精盐", type: "食材", foodtags: ["调料"], desc: "经过精制的纯净食盐,是最基本的调味品,缺少它的食物会大幅降低食欲。" }, oil: { size: 1, name: "油脂", type: "食材", fuelVal: 40, foodtags: ["调料"], desc: "从鱼肝或动物组织中提取的脂肪,用于煎炒时的热媒介质,也能改善口感。" }, /* ══════════════════════════════════════════ 菜品 ══════════════════════════════════════════ */ grilled_fish: { size: 1, name: "烤鱼", type: "菜品", hunger: 30, water: -5, life: 0, power: 5, san: 0, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, fish_soup: { size: 1, name: "鱼汤", type: "菜品", hunger: 20, water: 15, life: 5, power: 0, san: 3, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, steamed_shellfish: { size: 1, name: "清蒸贝肉", type: "菜品", hunger: 25, water: 5, life: 0, power: 0, san: 5, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, seaweed_broth: { size: 1, name: "海草羹", type: "菜品", hunger: 15, water: 20, life: 3, power: 0, san: 0, magic: 2, desc: "【占位】", eatDesc: "【占位】" }, raw_urchin: { size: 1, name: "生海胆", type: "菜品", hunger: 20, water: 0, life: 0, power: 0, san: 8, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, fishstew: { size: 1, name: "杂鱼炖", type: "菜品", hunger: 40, water: 10, life: 5, power: 5, san: 2, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, seafood_feast: { size: 1, name: "海鲜盛馔", type: "菜品", hunger: 60, water: 10, life: 10, power: 20, san: 10, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, medicinal_soup: { size: 1, name: "草药鱼汤", type: "菜品", hunger: 25, water: 15, life: 20, power: 0, san: 5, magic: 5, desc: "【占位】", eatDesc: "【占位】" }, vegetable_soup: { size: 1, name: "蔬菜浓汤", type: "菜品", hunger: 20, water: 18, life: 5, power: 0, san: 5, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, bread: { size: 1, name: "杂粮饼", type: "菜品", hunger: 35, water: -8, life: 0, power: 8, san: 0, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, fish_berry_grill: { size: 1, name: "浆果烤鱼", type: "菜品", hunger: 32, water: -2, life: 3, power: 6, san: 10, magic: 0, desc: "鱼肉的焦香裹着浆果的酸甜,意外地和谐。", eatDesc: "酸味让鱼腥气消散,两种截然不同的味道在口中融合,留下一种陌生而令人愉悦的感觉。" }, salt_fish: { size: 1, name: "香煎咸鱼", type: "菜品", hunger: 28, water: -8, life: 2, power: 5, san: 5, magic: 0, desc: "盐粒在鱼皮上结晶,烤出一层硬脆的外壳。", eatDesc: "咸香直冲味蕾,鱼肉的油脂被盐提了出来,简单却令人满足。" }, fishroe_congee: { size: 1, name: "鱼子粥", type: "菜品", hunger: 25, water: 18, life: 4, power: 3, san: 6, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, seafood_congee: { size: 1, name: "海鲜粥", type: "菜品", hunger: 30, water: 20, life: 5, power: 3, san: 7, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, kelp_octo: { size: 1, name: "章鱼海草煮", type: "菜品", hunger: 26, water: 15, life: 3, power: 4, san: 5, magic: 3, desc: "【占位】", eatDesc: "【占位】" }, crab_salt: { size: 1, name: "盐焗蟹", type: "菜品", hunger: 35, water: -6, life: 3, power: 8, san: 9, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, shrimp_congee: { size: 1, name: "虾仁粥", type: "菜品", hunger: 28, water: 18, life: 4, power: 3, san: 7, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, raw_sashimi: { size: 1, name: "刺身", type: "菜品", hunger: 22, water: 0, life: 0, power: 2, san: 12, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, seafood_hotpot: { size: 1, name: "海鲜锅", type: "菜品", hunger: 40, water: 12, life: 5, power: 6, san: 8, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, braised_tentacle: { size: 1, name: "炖腕足", type: "菜品", hunger: 30, water: 10, life: 2, power: 5, san: 4, magic: 2, desc: "【占位】", eatDesc: "【占位】" }, steamed_crab: { size: 1, name: "清蒸蟹", type: "菜品", hunger: 32, water: 5, life: 3, power: 5, san: 9, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, fish_congee: { size: 1, name: "鱼粥", type: "菜品", hunger: 22, water: 20, life: 3, power: 2, san: 5, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, /* 失败保底 */ char_mess: { size: 1, name: "什锦烤", type: "菜品", hunger: 8, water: -3, life: -2, power: 0, san: -5, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, watery_stew: { size: 1, name: "乱炖", type: "菜品", hunger: 10, water: 5, life: 0, power: 0, san: -4, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, steamed_blob: { size: 1, name: "拼蒸", type: "菜品", hunger: 8, water: 3, life: 0, power: 0, san: -3, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, raw_pile: { size: 1, name: "刺身拼盘", type: "菜品", hunger: 5, water: 0, life: 0, power: 0, san: -6, magic: 0, desc: "【占位】", eatDesc: "【占位】" }, /* ══════════════════════════════════════════ 基础材料 ══════════════════════════════════════════ */ metal: { size: 2, name: "金属材料", type: "基础材料", desc: "从残骸或沉积物中回收的金属碎块,边缘锈蚀,但本体依然坚固。" }, wood: { size: 3, name: "木材", type: "基础材料", fuelVal: 8, desc: "被海水浸泡许久的木材,密度大幅降低,适合作为浮力材料或燃料。" }, gears: { size: 2, name: "零件", type: "基础材料", desc: "【占位】" }, glass: { size: 1, name: "玻璃", type: "基础材料", desc: "破碎的透明玻璃,边缘锋利。来历不明,也许曾是某艘船的舷窗。" }, rubber: { size: 1, name: "橡胶", type: "基础材料", desc: "【占位】" }, clothes: { size: 1, name: "织物", type: "基础材料", desc: "【占位】" }, /* ── 燃料 ── */ coal: { size: 2, name: "煤块", type: "基础材料", subtype: "燃料", fuelVal: 15, desc: "压缩有机物形成的固态燃料,热值稳定。是火炉和提炼装置的常用燃料。" }, fish_oil: { size: 1, name: "鱼油", type: "基础材料", subtype: "燃料", fuelVal: 12, desc: "从鱼肝和深海鱼类内脏中提炼的油脂,热值尚可,是在燃料匮乏时的实用替代品。" }, algae_block: { size: 2, name: "海藻压缩块", type: "基础材料", subtype: "燃料", fuelVal: 5, desc: "将大量海藻压制成的固态块,热值偏低但来源充足,适合作应急燃料。" }, mineral_fuel: { size: 1, name: "矿物精炼燃料", type: "稀有资源", subtype: "燃料", fuelVal: 80, desc: "从热泉矿物中提炼的高能燃料,热值极高。深海长途航行的理想能源,但极其稀有。" }, /* ── 生物副产品 ── */ fish_bone: { size: 1, name: "骨骼", type: "基础材料", subtype: "生物副产品", desc: "从鱼类骸骨中取出的骨段,钙质密集,可用于多种加工。" }, fish_organ: { size: 1, name: "内脏", type: "基础材料", subtype: "生物副产品", desc: "【占位】" }, fish_scale: { size: 1, name: "鳞甲", type: "基础材料", subtype: "生物副产品", desc: "从鱼体或甲壳类生物剥离的鳞片,排列有序,具有一定的防护性。" }, /* ── 其他占位 ── */ salt: { size: 1, name: "粗盐", type: "基础材料", desc: "从海水蒸发后析出的粗颗粒盐,含有多种微量矿物。精制后可用于烹饪。" }, pearl: { size: 1, name: "珍珠", type: "基础材料", rarity: "稀有", desc: "由贝类分泌物层层包裹异物而成,光泽温润。磨碎后是优质的水系晶体炼金材料。" }, /* ══════════════════════════════════════════ 炼金材料 · 特殊粗制(24种) ══════════════════════════════════════════ */ jellyfish_tissue: { size: 1, name: "瑰丽水母组织", type: "炼金材料", tier: "粗制", element: "火", form: "固", desc: "【占位】" }, candle_jelly_core: { size: 1, name: "烛光水母核心", type: "炼金材料", tier: "粗制", element: "风", form: "固", desc: "【占位】" }, whale_relic_bone: { size: 1, name: "鲸鱼遗骨", type: "炼金材料", tier: "粗制", element: "水", form: "固", desc: "【占位】" }, parasite: { size: 1, name: "寄生虫", type: "炼金材料", tier: "粗制", element: "土", form: "固", desc: "【占位】" }, mermaid_bone: { size: 1, name: "人鱼遗骨", type: "炼金材料", tier: "粗制", element: "风", form: "固", desc: "【占位】" }, mermaid_blood: { size: 1, name: "人鱼血液", type: "炼金材料", tier: "粗制", element: "风", form: "液", desc: "【占位】" }, vitality: { size: 1, name: "生息", type: "炼金材料", tier: "粗制", element: "水", form: "离子", desc: "【占位】" }, phosphor_flame: { size: 1, name: "磷火", type: "炼金材料", tier: "粗制", element: "风", form: "离子", desc: "【占位】" }, ambergris: { size: 1, name: "龙涎香", type: "炼金材料", tier: "粗制", element: "土", form: "固", desc: "【占位】" }, storm_flesh: { size: 1, name: "风暴血肉", type: "炼金材料", tier: "粗制", element: "火", form: "固", desc: "【占位】" }, glow_moss_juice: { size: 1, name: "发光苔藓汁液", type: "炼金材料", tier: "粗制", element: "水", form: "液", desc: "【占位】" }, salt_lake_crystal: { size: 1, name: "盐湖结晶", type: "炼金材料", tier: "粗制", element: "土", form: "离子", desc: "【占位】" }, soul_sea_slime: { size: 1, name: "灵魂海黏液", type: "炼金材料", tier: "粗制", element: "水", form: "离子", desc: "【占位】" }, soul_sea_bone: { size: 1, name: "灵魂海骨骼", type: "炼金材料", tier: "粗制", element: "土", form: "固", desc: "【占位】" }, thaumas_blood: { size: 1, name: "陶玛斯血液", type: "炼金材料", tier: "粗制", element: "土", form: "液", rarity: "稀有", desc: "【占位】" }, vent_glow_fluid: { size: 1, name: "热泉发光液", type: "炼金材料", tier: "粗制", element: "火", form: "液", desc: "【占位】" }, tubeworm_fluid: { size: 1, name: "管虫分泌物", type: "炼金材料", tier: "粗制", element: "火", form: "液", desc: "【占位】" }, glow_coral: { size: 1, name: "发光的珊瑚", type: "炼金材料", tier: "粗制", element: "水", form: "固", desc: "【占位】" }, giant_ray_sac: { size: 1, name: "巨鳐气囊", type: "炼金材料", tier: "粗制", element: "风", form: "气", desc: "【占位】" }, inscription_frag: { size: 1, name: "铭文碎片", type: "炼金材料", tier: "粗制", element: "水", form: "气", desc: "【占位】" }, surface_light: { size: 1, name: "水面浮光", type: "炼金材料", tier: "粗制", element: "风", form: "气", desc: "【占位】" }, god_bone_raw: { size: 1, name: "神骨", type: "炼金材料", tier: "粗制", element: "火", form: "气", rarity: "稀有", desc: "【占位】" }, ceto_breath: { size: 1, name: "刻托气息", type: "炼金材料", tier: "粗制", element: "土", form: "气", rarity: "稀有", desc: "【占位】" }, jade_feather: { size: 1, name: "翡翠羽毛", type: "炼金材料", tier: "粗制", element: "火", form: "离子", desc: "【占位】" }, /* ══════════════════════════════════════════ 炼金材料 · 精炼(16种,4元素×4形态) ══════════════════════════════════════════ */ ref_water_solid: { size: 1, name: "水·固", type: "炼金材料", tier: "精炼", element: "水", form: "固", desc: "【占位】" }, ref_water_liquid: { size: 1, name: "水·液", type: "炼金材料", tier: "精炼", element: "水", form: "液", desc: "【占位】" }, ref_water_gas: { size: 1, name: "水·气", type: "炼金材料", tier: "精炼", element: "水", form: "气", desc: "【占位】" }, ref_water_ion: { size: 1, name: "水·离", type: "炼金材料", tier: "精炼", element: "水", form: "离子", desc: "【占位】" }, ref_fire_solid: { size: 1, name: "火·固", type: "炼金材料", tier: "精炼", element: "火", form: "固", desc: "【占位】" }, ref_fire_liquid: { size: 1, name: "火·液", type: "炼金材料", tier: "精炼", element: "火", form: "液", desc: "【占位】" }, ref_fire_gas: { size: 1, name: "火·气", type: "炼金材料", tier: "精炼", element: "火", form: "气", desc: "【占位】" }, ref_fire_ion: { size: 1, name: "火·离", type: "炼金材料", tier: "精炼", element: "火", form: "离子", desc: "【占位】" }, ref_earth_solid: { size: 1, name: "土·固", type: "炼金材料", tier: "精炼", element: "土", form: "固", desc: "【占位】" }, ref_earth_liquid: { size: 1, name: "土·液", type: "炼金材料", tier: "精炼", element: "土", form: "液", desc: "【占位】" }, ref_earth_gas: { size: 1, name: "土·气", type: "炼金材料", tier: "精炼", element: "土", form: "气", desc: "【占位】" }, ref_earth_ion: { size: 1, name: "土·离", type: "炼金材料", tier: "精炼", element: "土", form: "离子", desc: "【占位】" }, ref_wind_solid: { size: 1, name: "风·固", type: "炼金材料", tier: "精炼", element: "风", form: "固", desc: "【占位】" }, ref_wind_liquid: { size: 1, name: "风·液", type: "炼金材料", tier: "精炼", element: "风", form: "液", desc: "【占位】" }, ref_wind_gas: { size: 1, name: "风·气", type: "炼金材料", tier: "精炼", element: "风", form: "气", desc: "【占位】" }, ref_wind_ion: { size: 1, name: "风·离", type: "炼金材料", tier: "精炼", element: "风", form: "离子", desc: "【占位】" }, /* ══════════════════════════════════════════ 四化剂 ══════════════════════════════════════════ */ agent_white: { size: 1, name: "阳光", type: "炼金材料", tier: "化剂", subtype: "白化剂", desc: "【占位】" }, agent_black: { size: 1, name: "月光", type: "炼金材料", tier: "化剂", subtype: "黑化剂", desc: "在晴朗夜晚位于海面时,可在炼金室收集。是形态转换和酊剂合成的核心消耗品。" }, agent_yellow: { size: 1, name: "星光", type: "炼金材料", tier: "化剂", subtype: "黄化剂", desc: "【占位】" }, agent_red: { size: 1, name: "以太", type: "炼金材料", tier: "化剂", subtype: "赤化剂", desc: "【占位】" }, /* ══════════════════════════════════════════ 纯粹酊剂(4种) 配方: 慈爱 = 水·液 + 风·液 + 月光 信标 = 火·气 + 土·气 + 月光 死寂 = 水·固 + 土·固 + 月光 变革 = 火·离 + 风·离 + 月光 ══════════════════════════════════════════ */ tinct_love: { size: 1, name: "慈爱酊剂", type: "纯粹酊剂", element1: "水", element2: "风", form: "液", desc: "【占位】" }, tinct_beacon: { size: 1, name: "信标酊剂", type: "纯粹酊剂", element1: "火", element2: "土", form: "气", desc: "【占位】" }, tinct_silence: { size: 1, name: "死寂酊剂", type: "纯粹酊剂", element1: "水", element2: "土", form: "固", desc: "【占位】" }, tinct_change: { size: 1, name: "变革酊剂", type: "纯粹酊剂", element1: "火", element2: "风", form: "离子", desc: "【占位】" }, /* ══════════════════════════════════════════ 贤者之石 ══════════════════════════════════════════ */ philosophers_stone: { size: 1, name: "贤者之石", type: "纯粹酊剂", rarity: "传说", desc: "【占位】" }, /* ══════════════════════════════════════════ 以太副产物 ══════════════════════════════════════════ */ ether_tainted: { size: 1, name: "污染以太", type: "以太副产物", desc: "炼金过程中产生的不稳定副产物,对精神状态有一定的负面影响,需小心处理。" }, ether_blessed: { size: 1, name: "祝福以太", type: "以太副产物", rarity: "稀有", desc: "极少数情况下精炼产生的纯净副产物,微弱的光芒令人感到安宁。" }, /* ══════════════════════════════════════════ 消耗品 ══════════════════════════════════════════ */ stabilizer: { size: 1, name: "稳定剂", type: "消耗品", desc: "使用后降低当前炼金台的以太污染度,是长期精炼的必备耗材。" }, calm_draft: { size: 1, name: "深海镇定液", type: "消耗品", desc: "服用后迅速恢复25点精神值,同时会产生短暂的感知迟钝。" }, corrode_agent: { size: 1, name: "腐蚀溶剂", type: "消耗品", desc: "强力的化学溶剂,能溶解大部分金属和有机物,用于处理特殊残骸材料。" }, silence_draft: { size: 1, name: "沉默药剂", type: "消耗品", desc: "服用后完全抑制元素感知能力约两小时,用于穿越部分神秘区域。" }, bearing_ink: { size: 1, name: "方位墨水", type: "消耗品", desc: "涂在航海图上能持续标注当前位置,持续时间约六小时。" }, sense_draft: { size: 1, name: "感知剂", type: "消耗品", desc: "服用后增强元素感知范围,可在导航界面看到隐藏的神秘生物信号。" }, catalyst: { size: 1, name: "不稳定催化剂", type: "消耗品", desc: "加入炼金配方后大幅提升反应速度,但成功率下降,失败时有副产物爆发风险。" }, heal_salve: { size: 1, name: "创伤愈合膏", type: "消耗品", desc: "外用型炼金制品,涂抹后加速皮肤和组织愈合,对深层内伤无效。" }, warmth_vial: { size: 1, name: "驱寒药剂", type: "消耗品", desc: "服用后体感温度升高10度,效果持续约半小时,适合在极寒深海区域长期作业。" }, /* ══════════════════════════════════════════ 持久物品 ══════════════════════════════════════════ */ amulet_symb: { size: 1, name: "共生护符", type: "持久物品", desc: "佩戴后与生命体征产生共振,自然生命恢复速度提升两倍。" }, rune_purify: { size: 1, name: "净化符文", type: "持久物品", desc: "刻有净化纹路的金属片,激活后能自动将产生的污染以太分解为无害物质。" }, seal_nail: { size: 1, name: "封印钉", type: "持久物品", desc: "钉入特定区域后会产生元素干扰场,阻止神秘生物在附近刷新。" }, beacon_stone: { size: 1, name: "信标石", type: "持久物品", desc: "激活后记录当前坐标,之后可随时触发自动导航返回该位置。" }, sense_bone: { size: 1, name: "感知骨", type: "持久物品", desc: "来自特殊生物的骨骼制品,持有者能在导航界面上看到海底地形的轮廓。" }, mutation_core: { size: 1, name: "变质炉心", type: "持久物品", desc: "改装后的炼金台核心,解锁强制提纯功能——以更高的以太污染风险换取更高的提炼产量。" }, /* ══════════════════════════════════════════ 设备(潜艇升级) ══════════════════════════════════════════ */ engine_boost: { size: 2, name: "强化驱动炉", type: "设备", slot: "发动机", desc: "提升最高航速上限,并降低高速航行时的燃料消耗率。" }, hull_coat: { size: 2, name: "自愈船壳涂层", type: "设备", slot: "壳甲", desc: "在船壳受损时自动分泌修复物质,缓慢恢复船体完整度。" }, depth_sensor: { size: 2, name: "深度感应器", type: "设备", slot: "传感", desc: "精确显示海底地形数据,提前预报地形变化,减少深度意外。" }, silent_hull: { size: 2, name: "静默外壳", type: "设备", slot: "壳甲", desc: "大幅降低潜艇的声纹信号,减少神秘生物的感知半径。" }, fish_lure: { size: 2, name: "生物诱引装置", type: "设备", slot: "外挂", desc: "向水中持续散布特定化学信号,被动提升附近渔获密度。" }, /* ══════════════════════════════════════════ 遗物(知识碎片,阅读后解锁配方) ══════════════════════════════════════════ */ relic_notebook: { size: 1, name: "泡水的笔记本", type: "遗物", unlock: "基础提炼配方", desc: "字迹已经大半晕开,但仍能辨认出是某位炼金师的初学笔记。其中记录了最基础的元素分离流程。" }, relic_formula: { size: 1, name: "残损配方册", type: "遗物", unlock: "稳定剂配方", desc: "皮革封面的小册子,多页粘连,解开后露出密密麻麻的配方注记。稳定剂的配方赫然在列。" }, relic_etching: { size: 1, name: "铜板蚀刻图", type: "遗物", unlock: "炼金台升级图纸", desc: "精密的铜板蚀刻,线条清晰,是某种装置的改装图纸。看起来是炼金台的升级方案。" }, relic_log: { size: 1, name: "战争日志残页", type: "遗物", unlock: "腐蚀溶剂配方", rarity: "稀有", desc: "来自伐神战争的亲历者。字里行间充斥着恐惧和狂热,记录了攻击神体时使用的特殊溶剂配方。" }, relic_god_frag: { size: 1, name: "神域碎片", type: "遗物", unlock: "祝福以太提纯", rarity: "稀有", desc: "一片来历不明的金属碎块,对其施以炼金扫描后会产生短暂的幻觉。内含的信息最终化为一种祝福以太的提炼方法。" }, /* ══════════════════════════════════════════ 残骸(可拆解) ══════════════════════════════════════════ */ wreck_steel: { size: 4, name: "钢铁残骸", type: "残骸", desc: "沉船或建筑留下的大块钢铁,锈蚀严重,但内部金属依然有用。" }, wreck_wood: { size: 5, name: "木质残骸", type: "残骸", desc: "朽烂的木制结构件,有一定概率内藏绳索或煤块。" }, god_bone_frag: { size: 3, name: "神骨碎块", type: "残骸", rarity: "稀有", desc: "神祇骸骨的碎片,密度异常,表面有难以解释的结晶生长。" }, creature_husk: { size: 3, name: "异兽外壳", type: "残骸", desc: "来自不明生物的甲壳或骨骼碎片,成分复杂,适合拆解提取多种炼金材料。" }, /* ══════════════════════════════════════════ 资源(船体维修材料) ══════════════════════════════════════════ */ iron: { size: 2, name: "铁锭", type: "资源", desc: "精炼后的铁金属,是各类设备和修理的基础材料。" }, copper: { size: 1, name: "铜板", type: "资源", desc: "展平的铜质薄板,导热性好,是传感装置和炼金台部件的常用材料。" }, rubber_seal: { size: 1, name: "橡胶密封件", type: "资源", desc: "来自船体的橡胶垫片,用于维持舱室气密性,定期需要更换。" }, fuel_cell: { size: 2, name: "燃料块", type: "资源", desc: "压缩燃料的固态模块,能量密度高,直接投入发动机即可使用。" } }>>
/* 仓库初始结构(各分类从空开始,additem自动填充) */ <<set $storeCapacity = 500>> <<set $backpackCapacity = 50>> <<set $store = { 资源: [], 渔获: [], 食材: [], 菜品: [], 炼金材料: [], 纯粹酊剂: [], 以太副产物:[], 消耗品: [], 持久物品: [], 设备: [], 遗物: [], 残骸: [], 基础材料: [] }>> <<set $backpack = { 资源: [], 渔获: [], 食材: [], 菜品: [], 炼金材料: [], 消耗品: [] }>>
<<set $disassemblyRules = { /* ══ 鱼类 ══ */ "salmon": [ { id: "salmon_meat", minQty: 2, maxQty: 4 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_blood", minQty: 1, maxQty: 1 }, { id: "fish_scale", minQty: 1, maxQty: 3 }, { id: "fish_roe", minQty: 0, maxQty: 2, chance: 0.4 }, { id: "fish_liver", minQty: 0, maxQty: 1, chance: 0.3 }, /* 稀有产物 */ { id: "pearl_dust", minQty: 1, maxQty: 1, chance: 0.02, rare: true } ], "seabass": [ { id: "seabass_meat", minQty: 2, maxQty: 3 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_blood", minQty: 1, maxQty: 1 }, { id: "fish_scale", minQty: 1, maxQty: 2 }, { id: "gill_membrane", minQty: 0, maxQty: 1, chance: 0.5 } ], "tuna": [ { id: "tuna_meat", minQty: 4, maxQty: 7 }, { id: "fish_bone", minQty: 2, maxQty: 3 }, { id: "fish_blood", minQty: 2, maxQty: 3 }, { id: "fish_scale", minQty: 1, maxQty: 3 }, { id: "fish_liver", minQty: 1, maxQty: 1 }, { id: "swim_bladder", minQty: 0, maxQty: 1, chance: 0.6 }, /* 稀有 */ { id: "deep_eye", minQty: 1, maxQty: 1, chance: 0.015, rare: true } ], "sardine": [ { id: "sardine_meat", minQty: 1, maxQty: 1 }, { id: "fish_bone", minQty: 1, maxQty: 1 }, { id: "fish_blood", minQty: 0, maxQty: 1, chance: 0.5 } ], "herring": [ { id: "herring_meat", minQty: 1, maxQty: 1 }, { id: "fish_bone", minQty: 1, maxQty: 1 }, { id: "fish_roe", minQty: 0, maxQty: 1, chance: 0.35 } ], "grouper": [ { id: "grouper_meat", minQty: 2, maxQty: 4 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_blood", minQty: 1, maxQty: 2 }, { id: "gill_membrane", minQty: 1, maxQty: 1 }, { id: "fish_scale", minQty: 2, maxQty: 3 } ], "mahi": [ { id: "mahi_meat", minQty: 3, maxQty: 5 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_blood", minQty: 1, maxQty: 2 }, { id: "fin_membrane", minQty: 1, maxQty: 2 }, { id: "fish_scale", minQty: 2, maxQty: 4 } ], "cod": [ { id: "cod_meat", minQty: 2, maxQty: 4 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_liver", minQty: 1, maxQty: 1 }, { id: "swim_bladder", minQty: 0, maxQty: 1, chance: 0.55 } ], "eel": [ { id: "eel_meat", minQty: 1, maxQty: 3 }, { id: "fish_blood", minQty: 1, maxQty: 2 }, { id: "bile", minQty: 0, maxQty: 1, chance: 0.4 }, /* 稀有 */ { id: "current_stone", minQty: 1, maxQty: 1, chance: 0.025, rare: true } ], "flounder": [ { id: "flounder_meat", minQty: 2, maxQty: 3 }, { id: "fish_bone", minQty: 1, maxQty: 1 }, { id: "fish_scale", minQty: 2, maxQty: 4 }, { id: "sand_extract", minQty: 0, maxQty: 1, chance: 0.3 } ], "mackerel": [ { id: "mackerel_meat", minQty: 1, maxQty: 3 }, { id: "fish_bone", minQty: 1, maxQty: 1 }, { id: "fish_blood", minQty: 1, maxQty: 1 }, { id: "fish_scale", minQty: 1, maxQty: 2 } ], "bream": [ { id: "bream_meat", minQty: 2, maxQty: 3 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_scale", minQty: 2, maxQty: 3 }, { id: "fish_roe", minQty: 0, maxQty: 2, chance: 0.45 } ], "anchovy": [ { id: "anchovy_meat", minQty: 1, maxQty: 1 }, { id: "fish_bone", minQty: 1, maxQty: 1 } ], "barracuda": [ { id: "barracuda_meat", minQty: 2, maxQty: 4 }, { id: "fish_bone", minQty: 2, maxQty: 3 }, { id: "fish_blood", minQty: 2, maxQty: 3 }, { id: "bile", minQty: 1, maxQty: 1 } ], "hairtail": [ { id: "hairtail_meat", minQty: 2, maxQty: 3 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "fish_scale", minQty: 3, maxQty: 5 }, { id: "char_scale", minQty: 0, maxQty: 1, chance: 0.2 } ], "sunfish": [ { id: "sunfish_meat", minQty: 5, maxQty: 9 }, { id: "fish_bone", minQty: 2, maxQty: 3 }, { id: "fish_blood", minQty: 2, maxQty: 4 }, { id: "swim_bladder", minQty: 1, maxQty: 2 }, { id: "fin_membrane", minQty: 2, maxQty: 3 }, /* 稀有 */ { id: "deep_eye", minQty: 1, maxQty: 2, chance: 0.08, rare: true }, { id: "pearl_dust", minQty: 1, maxQty: 1, chance: 0.05, rare: true } ], "anglerfish": [ { id: "anglerfish_meat", minQty: 2, maxQty: 4 }, { id: "fish_bone", minQty: 1, maxQty: 2 }, { id: "bile", minQty: 1, maxQty: 2 }, { id: "fish_liver", minQty: 1, maxQty: 1 }, /* 稀有 */ { id: "deep_eye", minQty: 1, maxQty: 1, chance: 0.12, rare: true }, { id: "ember_crystal", minQty: 1, maxQty: 1, chance: 0.03, rare: true } ], "seahorse": [ { id: "fish_bone", minQty: 1, maxQty: 1 }, { id: "fish_blood", minQty: 1, maxQty: 1 }, /* 稀有 */ { id: "current_stone", minQty: 1, maxQty: 1, chance: 0.08, rare: true }, { id: "pearl_dust", minQty: 1, maxQty: 1, chance: 0.1, rare: true } ], /* ══ 贝类 ══ */ "scallop": [ { id: "scallop_meat", minQty: 1, maxQty: 2 }, { id: "shell_frag", minQty: 1, maxQty: 2 }, { id: "shell_powder",minQty: 0, maxQty: 1, chance: 0.4 } ], "clam": [ { id: "clam_meat", minQty: 1, maxQty: 1 }, { id: "shell_frag", minQty: 1, maxQty: 2 }, { id: "pearl", minQty: 1, maxQty: 1, chance: 0.05, rare: true } ], "oyster": [ { id: "oyster_meat", minQty: 1, maxQty: 1 }, { id: "shell_frag", minQty: 1, maxQty: 1 }, { id: "pearl", minQty: 1, maxQty: 1, chance: 0.08, rare: true }, { id: "blackpearl", minQty: 1, maxQty: 1, chance: 0.01, rare: true } ], "mussel": [ { id: "mussel_meat", minQty: 1, maxQty: 2 }, { id: "shell_frag", minQty: 1, maxQty: 2 } ], "conch": [ { id: "conch_meat", minQty: 1, maxQty: 2 }, { id: "shell_frag", minQty: 1, maxQty: 1 }, { id: "shell_powder",minQty: 1, maxQty: 2 } ], /* ══ 虾蟹类 ══ */ "prawn": [ { id: "prawn_meat", minQty: 1, maxQty: 2 }, { id: "shell_frag", minQty: 0, maxQty: 1, chance: 0.5 } ], "lobster": [ { id: "lobster_meat", minQty: 2, maxQty: 4 }, { id: "crab_shell", minQty: 1, maxQty: 2 }, { id: "shell_powder",minQty: 0, maxQty: 1, chance: 0.3 } ], "mantisshrimp": [ { id: "mantisshrimp_meat", minQty: 1, maxQty: 2 }, { id: "crab_shell", minQty: 1, maxQty: 1 } ], "sweetshrimp": [ { id: "shrimp_meat", minQty: 1, maxQty: 1 } ], "cherryshrimp": [ { id: "shrimp_meat", minQty: 1, maxQty: 1 } ], "kingcrab": [ { id: "kingcrab_meat", minQty: 3, maxQty: 5 }, { id: "crab_shell", minQty: 2, maxQty: 3 }, { id: "shell_powder",minQty: 1, maxQty: 2 }, /* 稀有 */ { id: "ember_crystal", minQty: 1, maxQty: 1, chance: 0.03, rare: true } ], "snowcrab": [ { id: "snowcrab_meat", minQty: 2, maxQty: 4 }, { id: "crab_shell", minQty: 2, maxQty: 3 }, { id: "shell_powder",minQty: 1, maxQty: 1 } ], "bluecrab": [ { id: "bluecrab_meat", minQty: 1, maxQty: 3 }, { id: "crab_shell", minQty: 1, maxQty: 2 } ], "swimmingcrab": [ { id: "crab_meat", minQty: 1, maxQty: 3 }, { id: "crab_shell", minQty: 1, maxQty: 2 } ], "flowercrab": [ { id: "crab_meat", minQty: 1, maxQty: 2 }, { id: "crab_shell", minQty: 1, maxQty: 2 }, { id: "coral_frag", minQty: 0, maxQty: 1, chance: 0.25 } ], "redcrab": [ { id: "crab_meat", minQty: 1, maxQty: 2 }, { id: "crab_shell", minQty: 1, maxQty: 2 }, { id: "coral_frag", minQty: 0, maxQty: 1, chance: 0.35 } ], /* ══ 头足类 ══ */ "squid": [ { id: "squid_meat",minQty: 1, maxQty: 3 }, { id: "fish_blood", minQty: 1, maxQty: 1 }, { id: "fin_membrane",minQty: 1, maxQty: 2 }, { id: "air_sac", minQty: 0, maxQty: 1, chance: 0.5 } ], "cuttlefish": [ { id: "cuttlefish_meat",minQty: 1, maxQty: 2 }, { id: "fish_blood", minQty: 1, maxQty: 2 }, { id: "shell_frag", minQty: 1, maxQty: 1 }, /* 乌贼骨 */ { id: "seawater_ext",minQty: 0, maxQty: 1, chance: 0.4 } ], "octopus": [ { id: "octopus_meat",minQty: 2, maxQty: 4 }, { id: "fish_blood", minQty: 1, maxQty: 2 }, { id: "gill_membrane",minQty:0, maxQty: 1, chance: 0.4 }, /* 稀有 */ { id: "deep_eye", minQty: 1, maxQty: 1, chance: 0.04, rare: true } ], /* ══ 棘皮/其他 ══ */ "seaurchin": [ { id: "urchin_roe", minQty: 1, maxQty: 2 }, { id: "urchin_spine_core", minQty: 1, maxQty: 1 }, { id: "shell_powder",minQty: 1, maxQty: 2 } ], "starfish": [ { id: "shell_frag", minQty: 1, maxQty: 2 }, { id: "bone_ash", minQty: 0, maxQty: 1, chance: 0.4 }, /* 稀有 */ { id: "current_stone",minQty:1, maxQty: 1, chance: 0.02, rare: true } ], "jellyfish": [ { id: "seajelly", minQty: 1, maxQty: 2 }, { id: "jellyfilm", minQty: 1, maxQty: 1 }, { id: "jellyfluid", minQty: 0, maxQty: 1, chance: 0.6 } ], /* ══ 藻类 ══ */ "kelp": [ { id: "dried_kelp", minQty: 1, maxQty: 3 }, { id: "kelp_fiber", minQty: 1, maxQty: 2 }, { id: "seawater_ext",minQty: 0, maxQty: 1, chance: 0.3 } ], "wakame": [ { id: "dried_kelp", minQty: 1, maxQty: 2 }, { id: "kelp_fiber", minQty: 1, maxQty: 1 } ], "nori": [ { id: "dried_nori", minQty: 1, maxQty: 2 }, { id: "seagrass_str",minQty: 0, maxQty: 1, chance: 0.5 } ], "agarcoral": [ { id: "dried_nori", minQty: 1, maxQty: 1 }, { id: "coral_frag", minQty: 1, maxQty: 1 }, { id: "shell_powder",minQty: 0, maxQty: 1, chance: 0.4 } ], /* ══ 残骸 ══ */ "wreck_steel": [ { id: "metal", minQty: 2, maxQty: 5 }, { id: "iron", minQty: 0, maxQty: 2, chance: 0.4 }, { id: "glass", minQty: 0, maxQty: 2, chance: 0.3 }, { id: "rubber_seal", minQty: 0, maxQty: 1, chance: 0.2 } ], "wreck_wood": [ { id: "wood", minQty: 2, maxQty: 5 }, { id: "rope", minQty: 0, maxQty: 2, chance: 0.5 }, { id: "coal", minQty: 0, maxQty: 2, chance: 0.3 } ], "god_bone_frag": [ { id: "bone_ash", minQty: 1, maxQty: 2 }, { id: "fish_bone", minQty: 1, maxQty: 3 }, /* 稀有 */ { id: "ember_crystal",minQty:1, maxQty: 1, chance: 0.06, rare: true }, { id: "god_ember", minQty: 1, maxQty: 1, chance: 0.008, rare: true } ], "creature_husk": [ { id: "crab_shell", minQty: 1, maxQty: 2 }, { id: "bone_ash", minQty: 1, maxQty: 2 }, { id: "bile", minQty: 0, maxQty: 1, chance: 0.5 }, /* 稀有 */ { id: "deep_eye", minQty: 1, maxQty: 1, chance: 0.05, rare: true } ] }>>
<<set $fishingConfig = { lightWeights: { "强光": { "日行性": 1.2, "夜行性": 0.2, "趋光性": 0.3 }, "朦胧": { "日行性": 1.0, "夜行性": 0.4, "趋光性": 0.4 }, "昏暗": { "日行性": 0.6, "夜行性": 0.8, "趋光性": 0.6 }, "无光": { "日行性": 0.2, "夜行性": 1.4, "趋光性": 0.8 } }, lightBonus: { "日行性": 1.1, "夜行性": 0.8, "趋光性": 2.0 }, gearTags: { "渔网": ["群居"], "垂钓": ["大型"] }, baitTags: { "血饵": ["肉食性"], "草饵": ["草食性"] }, depthWeights: { "0-50": { "浅层": 1.5, // 浅层鱼在0-50米权重高 "中层": 0.8, // 中层鱼在0-50米权重低 "深层": 0.1 // 深层鱼在0-50米几乎不出现 }, "50-150": { "浅层": 1.2, "中层": 1.0, "深层": 0.3 }, "150-300": { "浅层": 0.6, "中层": 1.3, "深层": 0.8 }, "300-1000": { "浅层": 0.1, "中层": 0.7, "深层": 1.5 }, "1000+": { "浅层": 0.0, "中层": 0.2, "深层": 1.8 } }, // 地形权重配置 terrainWeights: { "沙海床": { "底栖": 1.5, "沙海床": 1.3, "开阔水域": 0.7 }, "岩海床": { "岩海床": 1.4, "底栖": 1.2, "峭壁": 1.1 }, "珊瑚礁": { "珊瑚礁": 1.6, "岩海床": 1.2 }, "海草床": { "海草床": 1.5, "底栖": 1.1 }, "海藻森林": { "海藻森林": 1.4, "日行性": 1.2 }, "开阔水域": { "开阔水域": 1.5, "洄游性": 1.3 }, "峭壁": { "峭壁": 1.5, "岩海床": 1.2 }, "底栖": { "底栖": 1.6, "沙海床": 1.1, "岩海床": 1.1 } } }>> <<set $pools = { /* ========== 鱼类 ========== */ /* 鲑鱼 - 洄游性,喜欢冷水,浅中层 */ "salmon": { name: "鲑鱼", baseWeight: 5, tags: ["中层", "洄游性", "日行性", "肉食性"], customWeights: { depth: { "0-50": 1.3, "50-150": 1.5, "150-300": 0.8, "300-1000": 0.1, "1000+": 0.0 }, terrain: { "开阔水域": 1.4, "沙海床": 0.8, "岩海床": 1.0 }, light: { "明亮": 1.2, "朦胧": 1.0, "昏暗": 0.6, "无光": 0.2 } } }, /* 鲈鱼 - 适应性强,礁石区常见,伏击型 */ "seabass": { name: "鲈鱼", baseWeight: 6, tags: ["中层", "夜行性", "肉食性", "岩海床"], customWeights: { depth: { "0-50": 1.2, "50-150": 1.5, "150-300": 1.0, "300-1000": 0.2, "1000+": 0.0 }, terrain: { "岩海床": 1.5, "珊瑚礁": 1.3, "海草床": 1.1, "沙海床": 0.7, "开阔水域": 0.5 }, light: { "明亮": 0.8, "朦胧": 1.0, "昏暗": 1.3, "无光": 1.4 } } }, /* 金枪鱼 - 大型洄游,开阔水域,难钓 */ "tuna": { name: "金枪鱼", baseWeight: 2, tags: ["中层", "洄游性", "日行性", "肉食性", "大型", "开阔水域"], customWeights: { depth: { "0-50": 0.5, "50-150": 1.8, "150-300": 1.5, "300-1000": 0.4, "1000+": 0.0 }, terrain: { "开阔水域": 2.0, "沙海床": 0.4, "岩海床": 0.5, "珊瑚礁": 0.6 }, light: { "明亮": 1.3, "朦胧": 1.0, "昏暗": 0.5, "无光": 0.2 } } }, /* 沙丁鱼 - 极常见,群居,趋光 */ "sardine": { name: "沙丁鱼", baseWeight: 12, tags: ["浅层", "趋光性", "群居", "开阔水域", "草食性"], customWeights: { depth: { "0-50": 2.0, "50-150": 1.2, "150-300": 0.3, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "开阔水域": 1.6, "沙海床": 1.0, "海草床": 1.1, "岩海床": 0.7 }, light: { "明亮": 0.8, "朦胧": 1.0, "昏暗": 1.5, "无光": 2.0 } } }, /* 鲱鱼 - 群居,浅水,冷水偏好 */ "herring": { name: "鲱鱼", baseWeight: 10, tags: ["浅层", "群居", "日行性", "开阔水域"], customWeights: { depth: { "0-50": 1.8, "50-150": 1.2, "150-300": 0.4, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "开阔水域": 1.5, "沙海床": 1.0, "海草床": 0.9 }, light: { "明亮": 1.2, "朦胧": 1.0, "昏暗": 0.7, "无光": 0.4 } } }, /* 石斑鱼 - 礁石区,夜行伏击 */ "grouper": { name: "石斑鱼", baseWeight: 4, tags: ["中层", "夜行性", "肉食性", "岩海床", "底栖", "大型"], customWeights: { depth: { "0-50": 0.6, "50-150": 1.2, "150-300": 1.5, "300-1000": 0.8, "1000+": 0.0 }, terrain: { "岩海床": 1.6, "峭壁": 1.4, "珊瑚礁": 1.3, "海草床": 0.5, "沙海床": 0.3 }, light: { "明亮": 0.7, "朦胧": 1.0, "昏暗": 1.3, "无光": 1.5 } } }, /* 鲯鳅 - 大型,开阔水域,高速洄游 */ "mahi": { name: "鲯鳅", baseWeight: 2, tags: ["中层", "洄游性", "日行性", "肉食性", "大型", "开阔水域"], customWeights: { depth: { "0-50": 1.0, "50-150": 2.0, "150-300": 1.2, "300-1000": 0.2, "1000+": 0.0 }, terrain: { "开阔水域": 2.2, "沙海床": 0.2, "岩海床": 0.3 }, light: { "明亮": 1.5, "朦胧": 1.0, "昏暗": 0.4, "无光": 0.1 } } }, /* 鳕鱼 - 冷深水,底栖 */ "cod": { name: "鳕鱼", baseWeight: 5, tags: ["深层", "底栖", "日行性", "肉食性"], customWeights: { depth: { "0-50": 0.1, "50-150": 0.5, "150-300": 1.3, "300-1000": 1.8, "1000+": 0.8 }, terrain: { "沙海床": 1.4, "岩海床": 1.3, "开阔水域": 0.8, "峭壁": 0.9 }, light: { "明亮": 1.0, "朦胧": 1.1, "昏暗": 1.2, "无光": 0.9 } } }, /* 鳗鱼 - 底栖,夜行,善藏礁缝 */ "eel": { name: "鳗鱼", baseWeight: 4, tags: ["底栖", "夜行性", "肉食性", "岩海床"], customWeights: { depth: { "0-50": 1.0, "50-150": 1.4, "150-300": 1.5, "300-1000": 0.8, "1000+": 0.2 }, terrain: { "岩海床": 1.7, "峭壁": 1.5, "珊瑚礁": 1.2, "海藻森林": 1.3, "沙海床": 0.4 }, light: { "明亮": 0.3, "朦胧": 0.7, "昏暗": 1.4, "无光": 1.8 } } }, /* 比目鱼 - 沙底伏击,底栖 */ "flounder": { name: "比目鱼", baseWeight: 5, tags: ["底栖", "日行性", "肉食性", "沙海床"], customWeights: { depth: { "0-50": 1.4, "50-150": 1.5, "150-300": 1.0, "300-1000": 0.4, "1000+": 0.0 }, terrain: { "沙海床": 2.0, "海草床": 1.2, "岩海床": 0.4, "开阔水域": 0.2 }, light: { "明亮": 1.2, "朦胧": 1.0, "昏暗": 0.8, "无光": 0.5 } } }, /* 鲭鱼 - 群居,中层,洄游 */ "mackerel": { name: "鲭鱼", baseWeight: 8, tags: ["中层", "洄游性", "群居", "肉食性", "开阔水域"], customWeights: { depth: { "0-50": 1.0, "50-150": 1.8, "150-300": 1.2, "300-1000": 0.2, "1000+": 0.0 }, terrain: { "开阔水域": 1.8, "沙海床": 0.7, "岩海床": 0.8 }, light: { "明亮": 1.3, "朦胧": 1.1, "昏暗": 0.7, "无光": 0.3 } } }, /* 鲷鱼 - 礁石区,杂食 */ "bream": { name: "鲷鱼", baseWeight: 5, tags: ["中层", "日行性", "岩海床", "珊瑚礁"], customWeights: { depth: { "0-50": 1.2, "50-150": 1.5, "150-300": 1.0, "300-1000": 0.3, "1000+": 0.0 }, terrain: { "岩海床": 1.5, "珊瑚礁": 1.6, "海草床": 1.2, "沙海床": 0.7 }, light: { "明亮": 1.3, "朦胧": 1.0, "昏暗": 0.7, "无光": 0.4 } } }, /* 凤尾鱼 - 极小,群居,浅水趋光 */ "anchovy": { name: "凤尾鱼", baseWeight: 12, tags: ["浅层", "趋光性", "群居", "开阔水域"], customWeights: { depth: { "0-50": 2.2, "50-150": 1.0, "150-300": 0.2, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "开阔水域": 1.5, "沙海床": 1.0, "海草床": 1.2 }, light: { "明亮": 0.6, "朦胧": 1.0, "昏暗": 1.6, "无光": 2.2 } } }, /* 梭子鱼 - 凶猛,开阔水域伏击 */ "barracuda": { name: "梭子鱼", baseWeight: 3, tags: ["中层", "日行性", "肉食性", "大型", "开阔水域"], customWeights: { depth: { "0-50": 1.0, "50-150": 1.8, "150-300": 1.2, "300-1000": 0.3, "1000+": 0.0 }, terrain: { "开阔水域": 1.8, "珊瑚礁": 1.4, "岩海床": 1.0, "沙海床": 0.5 }, light: { "明亮": 1.5, "朦胧": 1.2, "昏暗": 0.6, "无光": 0.3 } } }, /* 带鱼 - 深中层,夜间上浮,趋光 */ "hairtail": { name: "带鱼", baseWeight: 6, tags: ["深层", "趋光性", "夜行性", "肉食性"], customWeights: { depth: { "0-50": 0.3, "50-150": 1.2, "150-300": 1.8, "300-1000": 1.5, "1000+": 0.3 }, terrain: { "沙海床": 1.3, "开阔水域": 1.4, "峭壁": 0.9 }, light: { "明亮": 0.3, "朦胧": 0.7, "昏暗": 1.4, "无光": 2.0 } } }, /* 翻车鱼 - 极稀有,开阔深水,独行 */ "sunfish": { name: "翻车鱼", baseWeight: 1, tags: ["深层", "日行性", "大型", "开阔水域", "洄游性"], customWeights: { depth: { "0-50": 0.2, "50-150": 0.8, "150-300": 1.5, "300-1000": 2.0, "1000+": 0.5 }, terrain: { "开阔水域": 3.0, "沙海床": 0.1, "岩海床": 0.1 }, light: { "明亮": 1.5, "朦胧": 1.2, "昏暗": 0.5, "无光": 0.1 } } }, /* 鮟鱇 - 深海,极暗,独行,大型 */ "anglerfish": { name: "鮟鱇", baseWeight: 2, tags: ["深层", "底栖", "夜行性", "肉食性", "大型"], customWeights: { depth: { "0-50": 0.0, "50-150": 0.1, "150-300": 0.5, "300-1000": 1.8, "1000+": 3.0 }, terrain: { "沙海床": 1.0, "岩海床": 1.2, "峭壁": 1.5 }, light: { "明亮": 0.0, "朦胧": 0.2, "昏暗": 0.8, "无光": 2.5 } } }, /* 海马 - 极稀有,海草床,慢 */ "seahorse": { name: "海马", baseWeight: 1, tags: ["浅层", "日行性", "海草床", "珊瑚礁"], customWeights: { depth: { "0-50": 2.5, "50-150": 1.0, "150-300": 0.1, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "海草床": 3.0, "珊瑚礁": 2.0, "岩海床": 0.3, "沙海床": 0.2 }, light: { "明亮": 1.5, "朦胧": 1.0, "昏暗": 0.4, "无光": 0.1 } } }, /* ========== 贝类 ========== */ /* 扇贝 - 沙底/海草床,浅中层 */ "scallop": { name: "扇贝", baseWeight: 6, tags: ["底栖", "沙海床", "海草床"], customWeights: { depth: { "0-50": 1.3, "50-150": 1.5, "150-300": 0.7, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "沙海床": 1.5, "海草床": 1.8, "岩海床": 0.3, "开阔水域": 0.0 }, light: { "明亮": 1.0, "朦胧": 1.0, "昏暗": 0.8, "无光": 0.6 } } }, /* 蛤蜊 - 沙底埋栖 */ "clam": { name: "蛤蜊", baseWeight: 8, tags: ["底栖", "沙海床", "海草床"], customWeights: { depth: { "0-50": 1.8, "50-150": 1.2, "150-300": 0.3, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "沙海床": 2.0, "海草床": 1.3, "岩海床": 0.1, "开阔水域": 0.0 }, light: { "明亮": 1.0, "朦胧": 1.0, "昏暗": 0.9, "无光": 0.8 } } }, /* 牡蛎 - 附着岩礁,不移动 */ "oyster": { name: "牡蛎", baseWeight: 7, tags: ["底栖", "岩海床", "珊瑚礁"], customWeights: { depth: { "0-50": 2.0, "50-150": 1.2, "150-300": 0.4, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "岩海床": 2.0, "珊瑚礁": 1.8, "沙海床": 0.1, "海草床": 0.3 }, light: { "明亮": 1.0, "朦胧": 1.0, "昏暗": 0.9, "无光": 0.8 } } }, /* 贻贝 - 附岩,潮带到浅海 */ "mussel": { name: "贻贝", baseWeight: 8, tags: ["底栖", "岩海床"], customWeights: { depth: { "0-50": 2.2, "50-150": 1.0, "150-300": 0.2, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "岩海床": 2.2, "峭壁": 1.5, "珊瑚礁": 0.8, "沙海床": 0.0 }, light: { "明亮": 1.0, "朦胧": 1.0, "昏暗": 0.9, "无光": 0.7 } } }, /* 海螺 - 底栖爬行,多地形 */ "conch": { name: "海螺", baseWeight: 6, tags: ["底栖", "岩海床", "沙海床"], customWeights: { depth: { "0-50": 1.5, "50-150": 1.3, "150-300": 0.8, "300-1000": 0.2, "1000+": 0.0 }, terrain: { "岩海床": 1.6, "沙海床": 1.4, "珊瑚礁": 1.5, "海草床": 1.2 }, light: { "明亮": 1.0, "朦胧": 1.0, "昏暗": 1.0, "无光": 0.8 } } }, /* ========== 虾类 ========== */ /* 对虾 - 海草床,夜行 */ "prawn": { name: "对虾", baseWeight: 7, tags: ["底栖", "夜行性", "海草床", "群居"], customWeights: { depth: { "0-50": 1.8, "50-150": 1.4, "150-300": 0.5, "300-1000": 0.1, "1000+": 0.0 }, terrain: { "海草床": 2.2, "沙海床": 1.2, "岩海床": 0.8, "珊瑚礁": 1.0 }, light: { "明亮": 0.5, "朦胧": 0.8, "昏暗": 1.5, "无光": 2.0 } } }, /* 龙虾 - 底栖,夜行,岩礁藏身 */ "lobster": { name: "龙虾", baseWeight: 3, tags: ["底栖", "夜行性", "岩海床", "大型"], customWeights: { depth: { "0-50": 0.8, "50-150": 1.5, "150-300": 1.8, "300-1000": 0.8, "1000+": 0.1 }, terrain: { "岩海床": 2.2, "峭壁": 1.8, "珊瑚礁": 1.3, "沙海床": 0.3 }, light: { "明亮": 0.2, "朦胧": 0.6, "昏暗": 1.5, "无光": 2.2 } } }, /* 皮皮虾(虾蛄)- 沙底底栖,昼行 */ "mantisshrimp": { name: "皮皮虾", baseWeight: 5, tags: ["底栖", "日行性", "沙海床", "肉食性"], customWeights: { depth: { "0-50": 1.8, "50-150": 1.5, "150-300": 0.5, "300-1000": 0.1, "1000+": 0.0 }, terrain: { "沙海床": 2.0, "岩海床": 1.0, "海草床": 1.2, "珊瑚礁": 0.8 }, light: { "明亮": 1.4, "朦胧": 1.0, "昏暗": 0.7, "无光": 0.4 } } }, /* 甜虾 - 深冷水,密集群居 */ "sweetshrimp": { name: "甜虾", baseWeight: 5, tags: ["深层", "群居", "夜行性"], customWeights: { depth: { "0-50": 0.0, "50-150": 0.3, "150-300": 1.2, "300-1000": 2.2, "1000+": 1.5 }, terrain: { "沙海床": 1.5, "开阔水域": 1.2, "岩海床": 1.0 }, light: { "明亮": 0.1, "朦胧": 0.4, "昏暗": 1.2, "无光": 2.0 } } }, /* 樱虾 - 开阔水域,昼夜垂直洄游,趋光 */ "cherryshrimp": { name: "樱虾", baseWeight: 6, tags: ["浅层", "趋光性", "群居", "开阔水域", "洄游性"], customWeights: { depth: { "0-50": 2.0, "50-150": 1.5, "150-300": 0.5, "300-1000": 0.1, "1000+": 0.0 }, terrain: { "开阔水域": 2.5, "沙海床": 0.8 }, light: { "明亮": 0.4, "朦胧": 0.8, "昏暗": 1.5, "无光": 2.5 } } }, /* ========== 蟹类 ========== */ /* 帝王蟹 - 海藻森林,深冷水 */ "kingcrab": { name: "帝王蟹", baseWeight: 2, tags: ["底栖", "夜行性", "海藻森林", "大型"], customWeights: { depth: { "0-50": 0.1, "50-150": 0.5, "150-300": 1.5, "300-1000": 2.5, "1000+": 0.5 }, terrain: { "海藻森林": 3.0, "岩海床": 1.2, "峭壁": 1.0, "沙海床": 0.2 }, light: { "明亮": 0.2, "朦胧": 0.6, "昏暗": 1.5, "无光": 2.2 } } }, /* 雪蟹 - 峭壁深水,冷水 */ "snowcrab": { name: "雪蟹", baseWeight: 2, tags: ["底栖", "夜行性", "峭壁", "大型"], customWeights: { depth: { "0-50": 0.0, "50-150": 0.3, "150-300": 1.2, "300-1000": 2.5, "1000+": 1.5 }, terrain: { "峭壁": 3.0, "岩海床": 1.5, "海藻森林": 1.2, "沙海床": 0.3 }, light: { "明亮": 0.1, "朦胧": 0.4, "昏暗": 1.2, "无光": 2.5 } } }, /* 蓝蟹 - 海草床,半咸水域,常见 */ "bluecrab": { name: "蓝蟹", baseWeight: 6, tags: ["底栖", "夜行性", "海草床", "肉食性"], customWeights: { depth: { "0-50": 2.0, "50-150": 1.5, "150-300": 0.4, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "海草床": 2.5, "沙海床": 1.3, "岩海床": 0.7 }, light: { "明亮": 0.6, "朦胧": 0.9, "昏暗": 1.4, "无光": 1.8 } } }, /* 梭子蟹 - 沙海床,善游泳 */ "swimmingcrab": { name: "梭子蟹", baseWeight: 7, tags: ["底栖", "夜行性", "沙海床", "肉食性"], customWeights: { depth: { "0-50": 1.8, "50-150": 1.5, "150-300": 0.6, "300-1000": 0.1, "1000+": 0.0 }, terrain: { "沙海床": 2.2, "海草床": 1.3, "岩海床": 0.6 }, light: { "明亮": 0.7, "朦胧": 0.9, "昏暗": 1.4, "无光": 1.7 } } }, /* 花蟹 - 礁石/珊瑚,颜色鲜艳 */ "flowercrab": { name: "花蟹", baseWeight: 4, tags: ["底栖", "日行性", "岩海床", "珊瑚礁"], customWeights: { depth: { "0-50": 1.5, "50-150": 1.5, "150-300": 0.8, "300-1000": 0.1, "1000+": 0.0 }, terrain: { "珊瑚礁": 2.0, "岩海床": 1.8, "沙海床": 0.5, "海草床": 0.8 }, light: { "明亮": 1.4, "朦胧": 1.1, "昏暗": 0.7, "无光": 0.4 } } }, /* 红蟹 - 珊瑚礁,颜色醒目 */ "redcrab": { name: "红蟹", baseWeight: 3, tags: ["底栖", "日行性", "珊瑚礁"], customWeights: { depth: { "0-50": 1.8, "50-150": 1.5, "150-300": 0.5, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "珊瑚礁": 3.0, "岩海床": 1.2, "沙海床": 0.3 }, light: { "明亮": 1.5, "朦胧": 1.0, "昏暗": 0.6, "无光": 0.3 } } }, /* ========== 头足类 ========== */ /* 鱿鱼 - 夜间趋光,群居,中层 */ "squid": { name: "鱿鱼", baseWeight: 8, tags: ["中层", "趋光性", "夜行性", "群居", "肉食性"], customWeights: { depth: { "0-50": 0.5, "50-150": 1.8, "150-300": 1.5, "300-1000": 0.8, "1000+": 0.2 }, terrain: { "开阔水域": 1.6, "沙海床": 1.0, "岩海床": 0.8 }, light: { "明亮": 0.2, "朦胧": 0.6, "昏暗": 1.6, "无光": 2.5 } } }, /* 墨鱼 - 浅中层,礁石区,白天可见 */ "cuttlefish": { name: "墨鱼", baseWeight: 5, tags: ["中层", "日行性", "肉食性", "岩海床", "珊瑚礁"], customWeights: { depth: { "0-50": 1.3, "50-150": 1.6, "150-300": 1.2, "300-1000": 0.3, "1000+": 0.0 }, terrain: { "岩海床": 1.8, "珊瑚礁": 1.6, "海草床": 1.3, "沙海床": 0.9 }, light: { "明亮": 1.3, "朦胧": 1.0, "昏暗": 0.7, "无光": 0.4 } } }, /* 章鱼 - 底栖,夜行,藏礁缝,独行 */ "octopus": { name: "章鱼", baseWeight: 4, tags: ["底栖", "夜行性", "肉食性", "岩海床"], customWeights: { depth: { "0-50": 1.2, "50-150": 1.5, "150-300": 1.3, "300-1000": 0.6, "1000+": 0.1 }, terrain: { "岩海床": 2.0, "峭壁": 1.5, "珊瑚礁": 1.5, "海藻森林": 1.3, "沙海床": 0.5 }, light: { "明亮": 0.3, "朦胧": 0.7, "昏暗": 1.5, "无光": 2.0 } } }, /* ========== 棘皮/其他无脊椎 ========== */ /* 海胆 - 附岩,珊瑚/海藻,日行 */ "seaurchin": { name: "海胆", baseWeight: 6, tags: ["底栖", "日行性", "草食性", "海藻森林", "珊瑚礁"], customWeights: { depth: { "0-50": 1.5, "50-150": 1.8, "150-300": 1.2, "300-1000": 0.3, "1000+": 0.0 }, terrain: { "珊瑚礁": 2.2, "岩海床": 1.8, "海藻森林": 2.0, "沙海床": 0.3 }, light: { "明亮": 1.3, "朦胧": 1.0, "昏暗": 0.7, "无光": 0.4 } } }, /* 海星 - 底栖爬行,多地形 */ "starfish": { name: "海星", baseWeight: 5, tags: ["底栖", "日行性"], customWeights: { depth: { "0-50": 1.5, "50-150": 1.3, "150-300": 0.9, "300-1000": 0.3, "1000+": 0.0 }, terrain: { "岩海床": 1.6, "珊瑚礁": 1.5, "沙海床": 1.2, "海草床": 1.3 }, light: { "明亮": 1.2, "朦胧": 1.0, "昏暗": 0.8, "无光": 0.5 } } }, /* 水母 - 随流漂浮,中层,趋光,夜间聚集 */ "jellyfish": { name: "水母", baseWeight: 7, tags: ["中层", "趋光性", "开阔水域"], customWeights: { depth: { "0-50": 1.5, "50-150": 1.8, "150-300": 1.2, "300-1000": 0.5, "1000+": 0.2 }, terrain: { "开阔水域": 2.0, "沙海床": 0.8, "岩海床": 0.6 }, light: { "明亮": 0.5, "朦胧": 0.9, "昏暗": 1.5, "无光": 2.2 } } }, /* ========== 藻类 ========== */ /* 海带 - 冷水,岩礁附着,浅中层 */ "kelp": { name: "海带", baseWeight: 8, tags: ["底栖", "草食性", "岩海床", "海藻森林"], customWeights: { depth: { "0-50": 1.0, "50-150": 2.0, "150-300": 1.5, "300-1000": 0.2, "1000+": 0.0 }, terrain: { "岩海床": 2.0, "海藻森林": 3.0, "峭壁": 1.5, "沙海床": 0.1 }, light: { "明亮": 1.5, "朦胧": 1.2, "昏暗": 0.7, "无光": 0.2 } } }, /* 裙带菜 - 浅岩礁,常见 */ "wakame": { name: "裙带菜", baseWeight: 8, tags: ["底栖", "草食性", "岩海床"], customWeights: { depth: { "0-50": 2.0, "50-150": 1.5, "150-300": 0.5, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "岩海床": 2.0, "峭壁": 1.3, "珊瑚礁": 0.8, "沙海床": 0.1 }, light: { "明亮": 1.5, "朦胧": 1.2, "昏暗": 0.6, "无光": 0.1 } } }, /* 紫菜 - 极浅,礁石表面,阳光需求高 */ "nori": { name: "紫菜", baseWeight: 7, tags: ["浅层", "草食性", "岩海床"], customWeights: { depth: { "0-50": 3.0, "50-150": 0.8, "150-300": 0.1, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "岩海床": 2.2, "珊瑚礁": 1.0, "沙海床": 0.1, "开阔水域": 0.0 }, light: { "明亮": 2.0, "朦胧": 1.2, "昏暗": 0.3, "无光": 0.0 } } }, /* 石花菜 - 珊瑚礁浅层,阳光充足 */ "agarcoral": { name: "石花菜", baseWeight: 5, tags: ["浅层", "草食性", "珊瑚礁", "岩海床"], customWeights: { depth: { "0-50": 2.5, "50-150": 1.2, "150-300": 0.2, "300-1000": 0.0, "1000+": 0.0 }, terrain: { "珊瑚礁": 2.5, "岩海床": 1.8, "沙海床": 0.1 }, light: { "明亮": 2.2, "朦胧": 1.0, "昏暗": 0.2, "无光": 0.0 } } } }>> <<set $fishingTime = 90>> <<set $fishingBait = "无">> <<set $fishingGear = "垂钓">> <<set $fishingLight = "关闭">> <<set $fishingPass = 0>>
/* ── 特殊食谱标记(精确ID匹配,会影响模板名称标记,不覆盖模板) ── 这里的 specificRecipes 现在仅用于"记录",未来可扩展为特殊效果触发 */ <<set $specificRecipes = [ { id:"urchin_raw", name:"海胆生食", ingredients:["urchin_roe"], methods:["生食"], bonusSan:3 }, { id:"tuna_sashimi",name:"蓝鳍刺身", ingredients:["tuna_meat"], methods:["生食"], bonusSan:2 }, { id:"ink_stew", name:"墨汁海鲜锅", ingredients:["squid_meat"], methods:["铜锅炖"], bonusMagic:2 } ]>> /* ── 烹饪过程描述(六种方式) ── */ <<set $cookDesc = { "明火烤": [ { ratio:0, text:"食材刚放上烤架,几乎没有任何变化。" }, { ratio:0.1, text:"表面开始受热,油脂渗出,轻微的滋滋声传来。" }, { ratio:0.25, text:"香气渐渐散开,外层开始变色。" }, { ratio:0.45, text:"色泽渐渐金黄,油脂在表面冒泡,香味浓郁——差不多了。" }, { ratio:0.6, text:"火候正好,这是完美的时机。" }, { ratio:0.75, text:"边缘开始焦化,再不收手就会过了。" }, { ratio:0.88, text:"烟气变大,已经有点焦了。" }, { ratio:1.0, text:"烤焦了,黑色的烟从烤架上升起。" } ], "铜锅炖": [ { ratio:0, text:"锅里还是冷的,食材沉在底部。" }, { ratio:0.1, text:"细小气泡从锅底涌起,食材的香气随热气飘散。" }, { ratio:0.25, text:"汤汁开始沸腾,食材慢慢变软,鲜味融入汤底。" }, { ratio:0.45, text:"咕嘟声均匀,舱室里弥漫着温暖的香气——差不多了。" }, { ratio:0.6, text:"正是最佳时机,汤底鲜浓而不过分浓稠。" }, { ratio:0.75, text:"食材开始软烂,汤汁越来越浓,要糊了。" }, { ratio:0.88, text:"已经能闻到焦糊味了,锅底快糊了。" }, { ratio:1.0, text:"锅底已经糊了,焦糊味盖过一切。" } ], "清蒸": [ { ratio:0, text:"蒸汽刚开始上升,食材还是凉的。" }, { ratio:0.1, text:"蒸汽稳定,锅盖凝结水珠,食材颜色开始变化。" }, { ratio:0.25, text:"食材外层已熟,蒸汽带着鲜香扑面而来。" }, { ratio:0.45, text:"鲜味完全锁在里面——差不多了。" }, { ratio:0.6, text:"恰好熟透,肉质紧实而嫩,正是最佳时机。" }, { ratio:0.75, text:"开始过熟,食材变软塌,汁水流失。" }, { ratio:0.88, text:"已经蒸过头了,质地在退化。" }, { ratio:1.0, text:"完全蒸烂了,失去了原本的鲜嫩。" } ], "煎炒": [ { ratio:0, text:"锅还没热,食材放进去也不会有任何反应。" }, { ratio:0.1, text:"锅底开始升温,油脂受热流动,香气初现。" }, { ratio:0.25, text:"锅气升腾,食材开始变色,翻炒的声音越来越响。" }, { ratio:0.45, text:"外层已经上色,锅气将鲜香逼进了食材里——差不多了。" }, { ratio:0.6, text:"火候完美,食材外焦里嫩,香气达到顶峰。" }, { ratio:0.75, text:"时间有点长了,食材开始变老变硬。" }, { ratio:0.88, text:"锅底开始冒烟,焦糊的气味渐渐盖过食材香气。" }, { ratio:1.0, text:"锅底糊了,食材已经无法挽救。" } ], "油炸": [ { ratio:0, text:"油温还不够,食材放进去只会吸油而不会酥化。" }, { ratio:0.1, text:"油温上升,细小的气泡开始在食材周围涌现。" }, { ratio:0.25, text:"气泡变密,食材外层开始酥化,颜色逐渐变黄。" }, { ratio:0.45, text:"外层已经金黄,内里差不多熟透——差不多了。" }, { ratio:0.6, text:"完美的金黄,酥脆而不焦糊,正是最佳时机。" }, { ratio:0.75, text:"颜色开始加深,再不捞出就会变苦。" }, { ratio:0.88, text:"已经有点焦了,苦味会盖过食材本身的香气。" }, { ratio:1.0, text:"炸焦了,已经没有挽救的可能。" } ], "生食": [ { ratio:0, text:"仔细检视食材,确认新鲜度与处理方式。" }, { ratio:0.25, text:"处理食材,去除不可食用的部分,刀工决定最终呈现。" }, { ratio:0.5, text:"细心切割,保留最鲜嫩的部分,摆盘初具雏形。" }, { ratio:0.75, text:"摆盘完成,看起来很不错——可以了。" }, { ratio:0.9, text:"已经处理好了,放置太久会影响新鲜度。" }, { ratio:1.0, text:"食材开始变质,应该早点结束。" } ] }>>
<<widget "matchRecipe">> <<nobr>> /* 分类标签集合(用于判断类型) */ <<set _mr_SEAFOOD = ["鱼","虾","蟹","贝","腕足"]>> <<set _mr_CATALL = ["鱼","虾","蟹","贝","腕足","海草","蔬菜","块茎","谷物","兽肉"]>> /* 收集所有食材的分类标签 */ <<set _mr_catTags = []>> <<for _mri = 0; _mri < $cookIngredients.length; _mri++>> <<set _mr_def = State.variables.items[$cookIngredients[_mri]]>> <<if _mr_def && _mr_def.foodtags>> <<for _mrt = 0; _mrt < _mr_def.foodtags.length; _mrt++>> <<set _mr_tag = _mr_def.foodtags[_mrt]>> <<if _mr_CATALL.includes(_mr_tag) && !_mr_catTags.includes(_mr_tag)>> <<run _mr_catTags.push(_mr_tag)>> <</if>> <</for>> <</if>> <</for>> <<set _mr_hasSeafood = _mr_catTags.some(t => _mr_SEAFOOD.includes(t))>> <<set _mr_seafoodTags = _mr_catTags.filter(t => _mr_SEAFOOD.includes(t))>> <<set _mr_nonSeafood = _mr_catTags.filter(t => !_mr_SEAFOOD.includes(t))>> <<set _mr_found = false>> <<set $cookTemplate = null>> /* ── 1. 单食材路径(1种食材,使用单类模板) ── */ <<if $cookIngredients.length === 1 && _mr_catTags.length > 0>> <<set _mr_priTag = _mr_catTags[0]>> <<set _mr_sKey = _mr_priTag + "_" + $cookMethod>> <<set _mr_sTpl = $cookSingleTemplates ? $cookSingleTemplates[_mr_sKey] : null>> <<if _mr_sTpl>> <<set $cookTemplate = _mr_sTpl>> <<set $cookTemplate.id = _mr_sKey>> <<set _mr_found = true>> <</if>> <</if>> /* ── 2. 多食材路径(使用多类模板,按优先级) ── */ <<if !_mr_found && $cookIngredients.length > 1 && $cookMultiTemplates>> <<for _mrm = 0; _mrm < $cookMultiTemplates.length; _mrm++>> <<set _mr_mt = $cookMultiTemplates[_mrm]>> /* 检查方式匹配 */ <<if !_mr_mt.methods.includes($cookMethod)>><<continue>><</if>> /* 检查 seafoodOnly */ <<if _mr_mt.seafoodOnly>> <<if !_mr_hasSeafood || _mr_nonSeafood.length > 0>><<continue>><</if>> <<if _mr_seafoodTags.length < 2>><<continue>><</if>> <</if>> /* 检查 noSeafood */ <<if _mr_mt.noSeafood && _mr_hasSeafood>><<continue>><</if>> /* 检查 hasSeafood */ <<if _mr_mt.hasSeafood && !_mr_hasSeafood>><<continue>><</if>> /* 检查 requires 标签全部存在 */ <<if _mr_mt.requires>> <<set _mr_reqOk = true>> <<for _mrr = 0; _mrr < _mr_mt.requires.length; _mrr++>> <<if !_mr_catTags.includes(_mr_mt.requires[_mrr])>> <<set _mr_reqOk = false>><<break>> <</if>> <</for>> <<if !_mr_reqOk>><<continue>><</if>> <</if>> /* 命中 */ <<set $cookTemplate = _mr_mt>> <<set _mr_found = true>> <<break>> <</for>> <</if>> /* ── 3. 保底:使用方式对应的保底模板 ── */ <<if !_mr_found>> <<set _mr_fallbacks = { "明火烤": { id:"fallback_roast", name:"焦糊一团", hunger:5, water:-2, life:-1, power:0, san:-5, magic:0, dur:25, sMin:6, sMax:22, pMin:10, pMax:18, open:"火候没有控制好,", close:"最终留下一团说不清楚是什么的焦糊物。" }, "铜锅炖": { id:"fallback_stew", name:"稀烂糊", hunger:8, water:4, life:0, power:0, san:-4, magic:0, dur:35, sMin:9, sMax:31, pMin:15, pMax:26, open:"锅底开始冒出焦糊味,", close:"食材已经炖烂失去了所有形状,漂浮在浑浊的汤底里。" }, "清蒸": { id:"fallback_steam", name:"软塌蒸物", hunger:6, water:2, life:0, power:0, san:-3, magic:0, dur:28, sMin:7, sMax:25, pMin:12, pMax:21, open:"蒸汽带走了所有的水分,", close:"食材瘪缩成一团,失去了应有的形态与鲜味。" }, "煎炒": { id:"fallback_fry", name:"糊底炒物", hunger:6, water:-1, life:0, power:0, san:-4, magic:0, dur:20, sMin:5, sMax:18, pMin:8, pMax:15, open:"锅底已经糊了,", close:"焦糊味盖过了食材本身的香气,勉强能入口。" }, "油炸": { id:"fallback_deepfry",name:"炸焦一团", hunger:5, water:-2, life:-1, power:0, san:-4, magic:0, dur:22, sMin:5, sMax:19, pMin:9, pMax:16, open:"油温过高,", close:"食材在热油中迅速炭化,留下一团苦涩的焦糊物。" }, "生食": { id:"fallback_raw", name:"生拼残食", hunger:4, water:0, life:0, power:0, san:-5, magic:0, dur:15, sMin:4, sMax:13, pMin:6, pMax:11, open:"处理得不够仔细,", close:"随便拼凑的生食,入口的生腥气让人皱眉。" } }>> <<set $cookTemplate = _mr_fallbacks[$cookMethod] || _mr_fallbacks["生食"]>> <</if>> /* ── 从 template 设置计时参数 ── */ <<set $cookRecipeName = $cookTemplate.name>> <<set $cookDuration = $cookTemplate.dur || 25>> <<set $cookSuccessMin = $cookTemplate.sMin || 5>> <<set $cookSuccessMax = $cookTemplate.sMax || 20>> <<set $cookPerfectMin = $cookTemplate.pMin || 8>> <<set $cookPerfectMax = $cookTemplate.pMax || 16>> <</nobr>> <</widget>>
<<nobr>> <<if !$cookIngredients>><<set $cookIngredients = []>><</if>> /* 扫描背包可用食材 */ <<set _cs_food = []>> <<set _cs_bpCats = Object.keys($backpack)>> <<for _cs_ci = 0; _cs_ci < _cs_bpCats.length; _cs_ci++>> <<set _cs_cat = _cs_bpCats[_cs_ci]>> <<set _cs_list = $backpack[_cs_cat]>> <<if Array.isArray(_cs_list)>> <<for _cs_i = 0; _cs_i < _cs_list.length; _cs_i++>> <<if _cs_list[_cs_i].quantity > 0>> <<set _cs_def = State.variables.items[_cs_list[_cs_i].id]>> <<if _cs_def && _cs_def.type === "食材" && _cs_def.foodtags && !_cs_def.foodtags.includes("调料")>> <<run _cs_food.push({ id: _cs_list[_cs_i].id, qty: _cs_list[_cs_i].quantity, name: _cs_def.name })>> <</if>> <</if>> <</for>> <</if>> <</for>> <div style="font-size:0.78rem;color:var(--bone-dim);margin-bottom:0.4rem;"> 烹饪方式:<span style="color:var(--amber-bright);"><<print $cookMethod>></span> </div> <!-- 已选食材区 --> <div style="min-height:2.2rem;margin:0.5rem 0 0.8rem;"> <span style="font-size:0.78rem;color:var(--bone-dim);">已选(<<print $cookIngredients.length>>/3):</span> <<if $cookIngredients.length > 0>> <<for _si = 0; _si < $cookIngredients.length; _si++>> /* 关键:先在 capture 外赋值,再把两个变量都列进 capture 参数 */ <<set _sid = $cookIngredients[_si]>> <<set _sdef = State.variables.items[_sid]>> <<set _sname_cap = _sdef ? _sdef.name : _sid>> <<capture _si, _sname_cap>> <span style="display:inline-block;background:var(--bg-panel);border:1px solid var(--amber-dim);padding:0.12rem 0.45rem;margin:0.12rem;font-size:0.82rem;color:var(--amber-bright);"><<print _sname_cap>> <<link "✕">> <<run State.variables.cookIngredients.splice(_si, 1)>> <<goto "烹饪选材">> <</link>></span> <</capture>> <</for>> <<else>> <span style="color:var(--bone-dim);font-size:0.82rem;font-style:italic;">尚未选择食材</span> <</if>> </div> <hr style="border-color:var(--border-dim);margin:0.4rem 0 0.7rem;"> <!-- 可选食材区 --> <<if _cs_food.length === 0>> <p style="color:var(--bone-dim);font-size:0.85rem;">背包中没有可用食材。</p> <<else>> <div class="inv-grid"> <<for _fi = 0; _fi < _cs_food.length; _fi++>> /* 同样先赋值再 capture */ <<set _fitem_cap = _cs_food[_fi]>> <<set _fsel_cap = $cookIngredients.includes(_fitem_cap.id)>> <<capture _fi, _fitem_cap, _fsel_cap>> <<if _fsel_cap>> <span class="inv-item" style="border-color:var(--amber-dim);color:var(--amber-bright);"> <<print _fitem_cap.name>><span class="item-qty">×<<print _fitem_cap.qty>></span> </span> <<elseif $cookIngredients.length >= 3>> <span class="inv-item" style="opacity:0.4;"> <<print _fitem_cap.name>><span class="item-qty">×<<print _fitem_cap.qty>></span> </span> <<else>> <span class="inv-item"><<link _fitem_cap.name>> <<run State.variables.cookIngredients.push(_fitem_cap.id)>> <<goto "烹饪选材">> <</link>><span class="item-qty">×<<print _fitem_cap.qty>></span></span> <</if>> <</capture>> <</for>> </div> <</if>> <div class="action-row" style="margin-top:1rem;"> <<if $cookIngredients.length > 0>> <span class="btn-primary"><<link "▶ 开始烹饪">> <<matchRecipe>> <<set $cookTimer = 0>> <<goto "烹饪进行">> <</link>></span> <</if>> [[← 返回|厨房]] </div> <</nobr>>
<<nobr>> <<if !$cookTimer>><<set $cookTimer = 0>><</if>> <div style="margin-bottom:0.8rem;"> <div style="font-size:1rem;color:var(--amber-bright);"><<print $cookMethod>> — <<print $cookRecipeName>></div> <div style="font-size:0.8rem;color:var(--bone-dim);margin-top:0.2rem;"><<nobr>><<for _cci = 0; _cci < $cookIngredients.length; _cci++>><<set _cn = State.variables.items[$cookIngredients[_cci]]>><<if _cn>><<print _cn.name>><<if _cci < $cookIngredients.length-1>>、<</if>><</if>><</for>><</nobr>></div> </div> <div id="cook-view" style="min-height:160px;">等待烹饪开始……</div> <<repeat 1s>> <<set $cookTimer += 1>><<set $timepass += 1>><<time>> <<set _cv_ratio = $cookTimer / $cookDuration>> <<set _cv_desc = $cookDesc[$cookMethod]>> <<set _cv_text = _cv_desc[0].text>> <<for _cdi = _cv_desc.length - 1; _cdi >= 0; _cdi-->> <<if _cv_ratio >= _cv_desc[_cdi].ratio>> <<set _cv_text = _cv_desc[_cdi].text>> <<break>> <</if>> <</for>> <<set _cv_zone = 0>> <<if $cookTimer >= $cookSuccessMin && $cookTimer < $cookPerfectMin>> <<set _cv_zone = 1>> <<elseif $cookTimer >= $cookPerfectMin && $cookTimer <= $cookPerfectMax>> <<set _cv_zone = 2>> <<elseif $cookTimer > $cookPerfectMax && $cookTimer <= $cookSuccessMax>> <<set _cv_zone = 1>> <<elseif $cookTimer > $cookSuccessMax>> <<set _cv_zone = -1>> <</if>> <<set _pct = Math.min(Math.floor(_cv_ratio * 100), 100)>> <<set _succ_left = Math.floor($cookSuccessMin / $cookDuration * 100)>> <<set _succ_right = Math.floor($cookSuccessMax / $cookDuration * 100)>> <<set _perf_left = Math.floor($cookPerfectMin / $cookDuration * 100)>> <<set _perf_right = Math.floor($cookPerfectMax / $cookDuration * 100)>> <<set _succ_w = _succ_right - _succ_left>> <<set _perf_w = _perf_right - _perf_left>> <<replace "#cook-view">> <p style="font-size:0.88rem;color:var(--bone-dim);font-style:italic;min-height:2.5em;line-height:1.7;"><<print _cv_text>></p> <div style="font-size:0.75rem;color:var(--bone-dim);margin:0.5rem 0 0.3rem;"> <<print $cookTimer>>s / <<print $cookDuration>>s <<if _cv_zone === 2>><span style="color:#f0c060;margin-left:0.8rem;">★ 完美区间</span> <<elseif _cv_zone === 1>><span style="color:#8bc4a0;margin-left:0.8rem;">▸ 成功区间</span> <<elseif _cv_zone === -1>><span style="color:#c47070;margin-left:0.8rem;">✕ 已过时机</span> <</if>> </div> <div style="position:relative;height:10px;background:var(--bg-panel);border:1px solid var(--border-dim);border-radius:3px;margin-bottom:0.4rem;"> <div style="position:absolute;top:0;left:<<print _succ_left>>%;width:<<print _succ_w>>%;height:100%;background:rgba(139,196,160,0.18);"></div> <div style="position:absolute;top:0;left:<<print _perf_left>>%;width:<<print _perf_w>>%;height:100%;background:rgba(240,192,96,0.28);"></div> <div style="position:absolute;top:0;left:0;width:<<print _pct>>%;height:100%;background:<<if _cv_zone === 2>>var(--amber)<<elseif _cv_zone === 1>>var(--teal)<<elseif _cv_zone === -1>>var(--danger-bright)<<else>>var(--bone-dim)<</if>>;border-radius:2px;transition:width 0.85s linear;"></div> <div style="position:absolute;top:-2px;left:<<print _succ_left>>%;width:1px;height:14px;background:rgba(139,196,160,0.7);"></div> <div style="position:absolute;top:-2px;left:<<print _perf_left>>%;width:1px;height:14px;background:rgba(240,192,96,0.9);"></div> <div style="position:absolute;top:-2px;left:<<print _perf_right>>%;width:1px;height:14px;background:rgba(240,192,96,0.9);"></div> <div style="position:absolute;top:-2px;left:<<print _succ_right>>%;width:1px;height:14px;background:rgba(139,196,160,0.7);"></div> </div> <div style="font-size:0.7rem;color:var(--bone-dim);margin-bottom:0.8rem;"> <span style="color:rgba(240,192,96,0.9);">■</span> 完美 <span style="color:rgba(139,196,160,0.9);">■</span> 成功 </div> /* <<link>> 替代 <<button>>:跳转页面会自动停止 repeat,无需 <<stop>> */ <<link "■ 完成烹饪">> <<set $cookFinalTime = $cookTimer>> <<goto "烹饪结果">> <</link>> <</replace>> <</repeat>> <</nobr>>
<<nobr>> /* 品质判定 */ <<set $cookQuality = "失败">> <<if $cookFinalTime >= $cookSuccessMin && $cookFinalTime <= $cookSuccessMax>> <<set $cookQuality = "成功">> <<if $cookFinalTime >= $cookPerfectMin && $cookFinalTime <= $cookPerfectMax>> <<set $cookQuality = "完美">> <</if>> <</if>> /* 消耗背包食材(每种消耗1份) */ <<for _rci = 0; _rci < $cookIngredients.length; _rci++>> <<set _rc_id = $cookIngredients[_rci]>> <<set _rc_idef = State.variables.items[_rc_id]>> <<set _rc_type = _rc_idef ? _rc_idef.type : "食材">> <<set _rc_idx = -1>> <<if $backpack[_rc_type]>> <<for _rbi = 0; _rbi < $backpack[_rc_type].length; _rbi++>> <<if $backpack[_rc_type][_rbi].id === _rc_id>> <<set _rc_idx = _rbi>><<break>> <</if>> <</for>> <</if>> <<if _rc_idx >= 0 && $backpack[_rc_type][_rc_idx].quantity > 0>> <<set $backpack[_rc_type][_rc_idx].quantity -= 1>> <</if>> <</for>> /* 构建菜品实例并存入冰箱 */ <<assembleDish>> <<if $assembleResult === "full">> <div style="color:var(--danger-bright);font-size:0.9rem;margin-bottom:0.6rem;">冰箱已满</div> <p style="font-size:0.85rem;color:var(--bone-dim);"> <span style="color:var(--amber-bright);"><<print $cookRecipeName>></span>(<<print $cookQuality>>)做好了,但冰箱已经没有空位了。这道菜只能丢弃。 </p> <div class="action-row" style="margin-top:0.8rem;"> [[继续烹饪|厨房]] [[查看冰箱|冰箱]] </div> <<else>> <<set _cr_dish = $fridge[$assembleSlot]>> <div style="margin-bottom:0.6rem;"> <<if $cookQuality === "完美">> <div style="color:#f0c060;font-size:1.05rem;letter-spacing:0.1em;">★ 完美烹饪</div> <<elseif $cookQuality === "成功">> <div style="color:var(--teal-bright);font-size:1rem;">烹饪完成</div> <<else>> <div style="color:var(--danger-bright);font-size:1rem;">烹饪失败</div> <</if>> </div> <div class="item-detail"> <div class="item-detail-name"><<print _cr_dish.name>></div> <p style="font-size:0.85rem;line-height:1.75;color:var(--bone-dim);margin:0.5rem 0;border-left:2px solid var(--border);padding-left:0.8rem;"><<print _cr_dish.desc>></p> <div style="font-size:0.78rem;color:var(--bone-dim);margin-top:0.4rem;"> <<if _cr_dish.hunger > 0>><span style="color:#8bc4a0;">饱腹+<<print _cr_dish.hunger>></span> <</if>> <<if _cr_dish.water > 0>><span style="color:#6ab4d0;">饮水+<<print _cr_dish.water>></span> <</if>> <<if _cr_dish.life > 0>><span style="color:var(--teal-bright);">生命+<<print _cr_dish.life>></span> <</if>> <<if _cr_dish.power > 0>><span style="color:var(--amber-bright);">体力+<<print _cr_dish.power>></span> <</if>> <<if _cr_dish.san !== 0>><span style="color:<<if _cr_dish.san > 0>>var(--amber)<<else>>var(--danger-bright)<</if>>;">安定<<if _cr_dish.san > 0>>+<</if>><<print _cr_dish.san>></span> <</if>> </div> </div> <p style="font-size:0.8rem;color:var(--bone-dim);margin-top:0.5rem;">已存入冰箱(格位 <<print $assembleSlot + 1>>/8)。</p> <div class="action-row" style="margin-top:0.8rem;"> [[继续烹饪|厨房]] [[查看冰箱|冰箱]] [[离开厨房|走廊]] </div> <</if>> <</nobr>>
<<set $viewlight = { bright: { day_clear: "太阳高悬在空中,清澈温暖的光线慷慨地遍撒在每一处", day_hot: "日曜季的太阳在彰显它的威力,海水温蕴着热量,直射进水底的光线几乎让人睁不开眼睛", dusk_hot: "即使太阳已经西沉,阳光也没有收敛它的温度,水上像是燃着一层火,跳动的光线直刺进眼睛和水下的深处", dawn_clear: "难得可以看到太阳的日子,太阳逐渐把雪亮的光片撒在水面上,水体通透映着日出的光线", dawn_hot: "天空的火球正在爬升,灼热金红的阳光穿透进海水,浅层水体逐渐开始升温" }, hazy: { day_cloudy: "阴天的阳光融进了云层里,灰白发亮的云层阴暗而晃眼,大海寂静如昨", day_lightrain: "细密柔和的雨融化在灰色的空气里,海水规律而没有尽头地波荡着拍打在船身", day_windy: "凌冽的风在呼啸,在海面几乎听不到风以外的任何声音,海面被风掀起白浪层层而过", day_fog: "海面上满是没有尽头的雾气,白昼足够明亮,但灰白的天空上看不见太阳", dusk_clear: "昏暗的日光斜落在海面,一片猩红涌动,透下带着余温的光穿透海水", dusk_lightrain: "淅淅沥沥的小雨披上夕阳色,金线划落,水面烁金一片", dawn_cloudy: "天气有些阴霾,但太阳还是从东边的海平面上投来了朦胧的铂金色亮光,新的一天照常来临", dawn_lightrain: "细密的微小雨滴被日出时的阳光斜斜地照出一层亮色,晨光和细雨交织,空气里弥漫着湿润清凉的气味", dawn_windy: "狂风在凌晨灰蓝色暗淡的海上呼啸,撕扯着翻滚不息的海,光线昏沉而冰冷", dawn_fog: "初出的阳光透过海上不变的无尽雾气,投下变幻莫测的倾斜光线,一切都灰白寂静" }, dim: { day_heavyrain: "雨点拍打在海面,不过并没有阻断白昼光线充斥空气,灰白的天空高悬在海上,笼罩下又一层敲打在窗户的雨点", day_snow: "狂乱的雪和阴翳的天空遮挡了一切光线,就算是白昼也只留下一层勉强看清五指的晦暗光线,不时有尚未融化的细小冰球被打入水下,随着泡沫一起重新上浮", day_storm: "暗沉宛如泥浆的海面在暴风雨的搅动下翻滚着,暴雨云下仿佛连空间都被压缩一般,看不清一切细节,只有一层轮廓勉强可见", dusk_fog: "淡金色的光辉从日落的方向撒来,被海面笼罩的雾气折射得四散朦胧", dusk_cloudy: "阳光夕斜,云色也变得暗沉,不过仍然有亮光在远处,天色依然明亮", dusk_windy: "黄昏的天色格外暗沉,几乎看不见任何东西,只有风从海面上呼啸而过,就连水下也被搅得混乱一片", dusk_heavyrain: "暮色被沉重的雨云二次覆盖,只剩暗红的光线映照在模糊的船舱轮廓上,豆大的雨点砸在海面砸开一片昏暗", dawn_snow: "风裹挟着雪落入海面,云层死死遮住了太阳,就算是本该日出的时间点海面也一片昏沉,能见度堪堪十米", dusk_snow: "洁白的雪也在昏暗的黄昏里投下更多暗影,纷纷扬扬没有尽头,海面的一切都模糊不清", dawn_heavyrain: "雨帘浇驻在海面,水雾和厚重的云四处飘荡,但拦不住朦胧的日光从海平线上投过来", }, dark: { dusk_storm: "阳光即将消逝在无边的雷云中,狂风、暴雨、破碎的水面,大海犹如猛兽在咆哮,只有偶尔一点亮光撕破昏暗的天际", dawn_storm: "深黑的暴雨云积压在天空,只有闪电的光线才能偶尔照亮视线,初升的太阳根本无力穿透这样的风暴,汹涌的海水里满是激荡的泡沫", night_clear: "难得晴朗的夜晚,空中隐约可以看到星星,漫无边际的繁星从天际笼罩在海面,但大海依然是无尽的深黑色", night_hot: "黑夜闷热,不过至少比白天好上些许,泛着泡沫的海腥潮水波荡拍打在船体上,空气潮湿而温暗", night_cloudy: "即使是海面也只有阴冷的黑,船上的灯光也只亮在你的小窝一隅,无边的黑暗如过去数年一般统治着整个沉默的海面", night_lightrain: "淅淅沥沥的小雨敲打在海面,不是坏天气,不过当然也不美好,只是这样小的雨甚至没法打破海上黑夜的沉寂,只有细雨丝融化在潮湿的空气里", night_heavyrain: "雨点在海面激起涟漪,淅淅沥沥,从未停息,无边的黑暗笼罩着雨夜", night_windy: "狂风在海面呼啸,但无光的黑夜让一切都模糊不清,只有风依然在撕扯咆哮,海浪随着气流起伏不休,风声哭嚎着在黑夜盘旋",night_fog: "雾气笼罩了一切,夜晚的海洋黑暗无际,船上微弱的灯光也消融在仅仅伸手的范围,寂静的黑暗如水压般沉重", night_storm: "比狂风更暴烈,比大雨更窒息,只能用灾难来形容的气候在海上盘旋,本该比夜更黑暗的天空却被闪电照亮了几瞬,你的船在海水里颠簸,或许去深处会好一些", night_snow: "雪花在风中飘荡,风雪漫漫,深黑的天空让人看不清任何东西,但冰晶几乎随着海上无边无际的水声、和令人胆寒的黑暗一起钻进船舱里了" } }>> <<set $viewmap = { /* --- 地形描述 --- */ water: { bright: "明亮的光穿透海面、缓慢而轻柔地形成光柱,也穿透无边无际的海水,视线的尽头是一片茫茫的蓝色。", hazy: "果冻一样柔软的灰蓝色海水蔓延到视线的尽头。", dim: "幽暗的海水里晃悠着潜艇仅有的一点灯光,更远处被笼罩在一片深蓝中,恍惚望不到尽头", dark: "海水中缺乏参照物、几乎分不清远近,只剩潜艇偶尔扫过的短暂惨白灯光" }, sand: { bright: "起伏的沙床上隐约有水面透下的光斑,海水交织着金色的光,连扬起的沙尘都泛着金色。", hazy: "沙砾铺陈在海底,偶尔有缓慢的水流搅动,四周是一片朦胧的蓝色", dim: "微弱的光线偶尔落在海床沙丘的亮面,又随着海浪一晃消失,海床只在一片看不清晦暗里起伏", dark: "除了灯光扫过的起伏沙地看不清其他,偶尔有些小蟹从灯光里疯狂逃窜走" }, grass: { bright: "海草随着海水柔软地起伏,反射阳光、宛如风掠过草原", hazy: "海草浪一样起伏,偶尔有小鱼在其中穿行,静谧的蓝绿色草原望不到尽头。", dim: "昏暗的光线让你看不清细节,只看到一片起伏的草浪,宛如又一片汹涌的海面", dark: "潜艇灯光照亮了极小范围内交织的丝丝海草,更多只是在黑暗中起伏涌动,看不到尽头" }, reef: { bright: "阳光穿过繁杂的礁石,海葵轮流张合翕动,每一个角落都有不同的生物鱼贯四散,繁复结构的影子和反光都多彩得令人目眩。", hazy: "繁茂的礁石自顾自吞吐着海水,目之所及的每一处都有小生物在忙着自己的事,鱼群交错有如末日前最忙乱的十字路口。", dim: "昏暗错杂的光让你看不清那些小东西了,但珊瑚礁仍然令人眼花缭乱,偶尔几点光斑从失色的礁石尖端掠过,又躲进昏暗的影子里。", dark: "珊瑚礁在黑暗中成为剪影,珊瑚们反射着微弱的光,在不见五指的黑暗中点缀着荧光" }, forest: { bright: "再粗壮的海藻也没法遮挡所有光线,染着橄榄色的海藻森林一角被照亮了,阳光在巨大褐藻之间穿行,角落被映得生机盎然。", hazy: "海藻遮挡了光线,森林中比水面要昏暗些,但还是有浅黄的光线照在那些错落宽大的枝叶上", dim: "粗壮、庞大的海藻遮挡了几乎一切光线,只有缝隙里有些光漏下来,其余皆是一片阴森的晦暗", dark: "在黑暗中偶有粗壮的海藻从狭窄的灯光视野里拂过,层层叠叠的森林压缩了视距,比开阔海域更加压抑" }, rock: { bright: "崎岖起伏着的海底也被阳光照亮,死寂变得柔和了不少", hazy: "岩石嶙峋地铺在海底,光亮只落在尖处,几乎像要从海底开始搅碎一切的牙齿", dim: "嶙峋的石块在海底起伏,灰暗的海水压在海床上,目之所及只有压抑而茫茫的无尽深海", dark: "尖锐的岩石从黑暗中刺进灯光,又快速隐没进黑暗,其余一切也都不可见" }, cliff: { bright: "峭壁的岩面被光线照亮,清晰的层叠纹路和嶙峋突起投下浓厚的影,深邃的裂谷处仍是一片幽暗。", hazy: "峭壁在昏暗中轮廓模糊,起伏的岩面隐约向深处延伸,光线只落在最突出的棱角上。", dim: "周围只有嶙峋的石块构成尖锐的峡谷,光线在下发不远处就衰减了、只剩狭窄的空间通向看不见的深处。", dark: "深渊比往常更幽深,深不见底的黑暗吞噬了灯光,只有近旁崎岖的岩壁指向更深的裂谷。" }, flat: { bright: "平整的岩海床被光线清晰地照亮,硬实的地面几乎没有任何起伏,偶有藤壶和附生生物点缀其间。", hazy: "平坦的岩层向四周无尽地延伸,灰白的色调与昏暗的水色连成一片,显得空旷而单调。", dim: "岩海床在昏暗中显得冷硬而空旷,灯光照出的范围内几乎没有任何变化,只有偶尔一两处苔藓状的附生物。", dark: "黑暗中平坦的岩面只被灯光短暂地照亮一小片,四周死寂,几乎分辨不出任何细节。" } }>> <<set $viewevents = { /* --- 随机小场景 --- */ fish: { bright: "[鱼群 强光行为]", dim: "[鱼群 弱光行为]", dark: "[鱼群 无光行为]" }, bubble: { bright: "[气泡 强光行为]", dim: "[气泡 弱光行为]" } // 其他事件... }>>
<<nobr>> <<widget "takeAll">> <<set _ta_id = $args[0]>> <<set _ta_def = State.variables.items[_ta_id]>> <<if !_ta_def>> <<set $lastTakeText = "未知物品。">> <<else>> <<set _ta_type = _ta_def.type>> <<set _ta_idx = -1>> <<if $store[_ta_type]>> <<for _ta_i = 0; _ta_i < $store[_ta_type].length; _ta_i++>> <<if $store[_ta_type][_ta_i].id === _ta_id>> <<set _ta_idx = _ta_i>> <<break>> <</if>> <</for>> <</if>> <<if _ta_idx < 0 || $store[_ta_type][_ta_idx].quantity <= 0>> <<set $lastTakeText = "仓库中已经没有" + _ta_def.name + "了。">> <<else>> <<set _ta_qty = $store[_ta_type][_ta_idx].quantity>> <<take _ta_id _ta_qty>> <<set $lastTakeText = "已取出全部 " + _ta_qty + " × " + _ta_def.name>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "putAll">> <<set _pa_id = $args[0]>> <<set _pa_def = State.variables.items[_pa_id]>> <<if !_pa_def>> <<set $lastTakeText = "未知物品。">> <<else>> <<set _pa_type = _pa_def.type>> <<set _pa_idx = -1>> <<if $backpack[_pa_type]>> <<for _pa_i = 0; _pa_i < $backpack[_pa_type].length; _pa_i++>> <<if $backpack[_pa_type][_pa_i].id === _pa_id>> <<set _pa_idx = _pa_i>> <<break>> <</if>> <</for>> <</if>> <<if _pa_idx < 0 || $backpack[_pa_type][_pa_idx].quantity <= 0>> <<set $lastTakeText = "背包中已经没有" + _pa_def.name + "了。">> <<else>> <<set _pa_qty = $backpack[_pa_type][_pa_idx].quantity>> <<put _pa_id _pa_qty>> <<set $lastTakeText = "已放回 " + _pa_qty + " × " + _pa_def.name>> <</if>> <</if>> <</widget>> <</nobr>>
<<set $disassemblyFlavors = { "鱼类": "剖开鱼腹,依次取出鱼肉、内脏和骨架。手法熟练的话可以获得更多完整材料。", "贝类": "敲碎外壳或撬开双壳,小心剥离内部的软体组织,避免损坏壳质材料。", "虾类": "剥去虾壳,取出虾肉,壳质碎片也有一定的炼金价值。", "蟹类": "拆开蟹甲,挑出蟹肉和蟹黄,坚硬的甲壳粉碎后是上等的土系材料。", "头足": "分离外套膜和腕足,取出墨囊时需小心不要破裂,其中的液体有特殊用途。", "其他": "仔细处理这种特殊生物,提取可用的组织。", "藻类": "晒干或直接压榨,提取纤维和矿物浓缩物。", "残骸": "用工具撬开结构,分拣金属和木材,腐蚀部分可能带有毒性。", "炼金材料": "使用炼金台进行进一步提炼,原始材料的处理需要谨慎。", "遗物": "仔细翻阅或扫描,从中提取可用的知识与配方。" }>>
<<nobr>> <<time widget>> $showseason季 第$showday日 $showhour:$showminute<br> $showweather[$weather] / 环境 $worldtem° 体温 $tem° ———————————— /* 颜色阈值 */ <<set _c_h = $hunger < 25 ? "var(--danger-bright)" : $hunger < 50 ? "var(--amber)" : "var(--bone-dim)">> <<set _c_w = $water < 20 ? "var(--danger-bright)" : $water < 45 ? "var(--amber)" : "var(--bone-dim)">> <<set _c_p = $power < 20 ? "var(--danger-bright)" : $power < 45 ? "var(--amber)" : "var(--bone-dim)">> <<set _c_l = $life < 25 ? "var(--danger-bright)" : $life < 60 ? "var(--amber)" : "var(--bone-dim)">> <<set _c_tr = $tre >= 80 ? "var(--danger-bright)" : $tre >= 50 ? "var(--amber)" : "var(--bone-dim)">> <<set _c_tem = $tem > 37 ? "var(--danger-bright)" : $tem >= 32 ? "var(--amber)" : $tem <= 0 ? "var(--danger-bright)" : $tem <= 10 ? "var(--amber)" : "var(--bone-dim)">> /* 数值栏 */ <div style="font-size:0.78rem;line-height:1.85;color:var(--bone-dim);"> <span style="color:<<print _c_h>>;">饱腹</span> <<print $hunger>> <span style="color:<<print _c_w>>;">饮水</span> <<print $water>><br> <span style="color:<<print _c_p>>;">体力</span> <<print $power>> <span style="color:<<print _c_l>>;">生命</span> <<print $life>><br> <span style="color:<<print _c_tem>>;">体感</span> <<print $tem>>° <span style="color:<<print _c_tr>>;">压力</span> <<print $tre>><br> 安定 <<print $san>> 魔力 <<print $magic>><br> <span style="font-size:0.7rem;opacity:0.6;">潮湿 <<print $wet>></span> </div> /* 燃料条(仅在航行/出发时显示)*/ <<if $passage === "航行" || $passage === "探索" || $divingMode>> <<set _sbFuel = Math.max(0,Math.min(100,Math.floor(($fuel||0)/($fuelMax||300)*100)))>> <<set _sbFC = _sbFuel > 40 ? "var(--teal-bright)" : _sbFuel > 15 ? "var(--amber)" : "var(--danger-bright)">> <div style="display:flex;align-items:center;gap:0.25rem;font-size:0.66rem;color:var(--bone-dim);margin-bottom:0.18rem;"> <span>⛽</span> <div style="flex:1;height:3px;background:var(--bg-panel);border:1px solid var(--border-dim);border-radius:2px;"><div style="height:100%;width:<<print _sbFuel>>%;background:<<print _sbFC>>;"></div></div> <span style="color:<<print _sbFC>>;"><<print Math.floor($fuel||0)>></span> </div> <</if>> <div style="height:1px;background:var(--border-dim);margin:0.55rem 0;"></div> /* 散文描述 */ <<set _desc_parts = []>> /* 饥饿/饮水 */ <<if $hunger < 25 && $water < 20>> <<run _desc_parts.push("腹中空空如也,喉咙干得快要冒烟。")>> <<elseif $hunger < 25>> <<run _desc_parts.push("饥饿感像钝刀一样磨着胃,难以集中精神。")>> <<elseif $water < 20>> <<run _desc_parts.push("严重脱水,嘴唇皲裂,连吞口水都变得困难。")>> <<elseif $hunger < 50 && $water < 45>> <<run _desc_parts.push("有些饿,也有些渴。")>> <<elseif $hunger < 50>> <<run _desc_parts.push("胃里开始咕咕作响。")>> <<elseif $water < 45>> <<run _desc_parts.push("喉咙有点发干。")>> <<elseif $hunger >= 80 && $water >= 80>> <<run _desc_parts.push("吃饱喝足,身体舒适。")>> <</if>> /* 体力 */ <<if $power < 20>> <<run _desc_parts.push("几乎没有力气再迈出一步。")>> <<elseif $power < 45>> <<run _desc_parts.push("四肢沉重,疲惫感渗进了骨头里。")>> <<elseif $power < 70>> <<run _desc_parts.push("略感疲惫。")>> <</if>> /* 生命 */ <<if $life < 25>> <<run _desc_parts.push("伤势严峻,每次呼吸都带着刺痛,随时可能倒下。")>> <<elseif $life < 50>> <<run _desc_parts.push("身上的伤口还没愈合,行动受限。")>> <<elseif $life < 90 && $life > 60>> <<run _desc_parts.push("有些轻伤,但尚在可控范围。")>> <</if>> /* 体感温度(对齐六维阈值) */ <<if $tem > 37>> <<run _desc_parts.push("体表滚烫,头晕目眩,已经到了危险的高温极限。")>> <<elseif $tem >= 32>> <<run _desc_parts.push("热浪蒸腾,汗水不停渗出,消耗着仅剩的水分。")>> <<elseif $tem <= 0>> <<run _desc_parts.push("严寒侵骨,四肢麻木,寒冷正在蚕食生命力。")>> <<elseif $tem <= 10>> <<run _desc_parts.push("寒意透过衣物渗入,手指已经开始失去灵活。")>> <<elseif $tem >= 18 && $tem <= 26>> /* 舒适区不显示温度描述 */ <</if>> /* 压力/安定 */ <<if $tre >= 80>> <<run _desc_parts.push("神经紧绷到了极限,思维开始扭曲。")>> <<elseif $tre >= 50>> <<run _desc_parts.push("心头压着什么,难以放松。")>> <<elseif $san < 30>> <<run _desc_parts.push("精神状态堪忧,现实与幻想的边界开始模糊。")>> <</if>> /* 全好时的正面描述 */ <<if _desc_parts.length === 0>> <<if $life === 100 && $hunger >= 80 && $water >= 80 && $power >= 70 && $tem >= 18 && $tem <= 26>> <<run _desc_parts.push("身体状态绝佳,精神饱满,做好了应对一切的准备。")>> <<else>> <<run _desc_parts.push("状态尚可,没有特别需要注意的问题。")>> <</if>> <</if>> <div style="font-size:0.77rem;line-height:1.75;color:var(--bone-dim);font-style:italic;"><<print _desc_parts.join(" ")>></div> <<if $questNotify>> <div style="margin-top:0.15rem;padding:0.12rem 0.4rem;background:rgba(0,180,150,0.08);border-left:2px solid var(--teal-bright);font-size:0.71rem;color:var(--teal-bright);"> <<print $questNotify>> </div> <<set $questNotify = "">> <</if>> <</nobr>>
/* 各物品/分类的保质天数(日历天) */ <<set $spoilDays = { /* ── 鱼类(整条) ── */ salmon:3, seabass:3, tuna:3, sardine:2, herring:2, grouper:4, mahi:3, cod:3, eel:4, flounder:3, mackerel:2, bream:3, anchovy:2, barracuda:3, hairtail:2, sunfish:3, anglerfish:4, /* ── 贝/虾/蟹/头足 ── */ scallop:2, clam:2, oyster:1, mussel:2, conch:3, prawn:2, lobster:2, mantisshrimp:2, kingcrab:3, snowcrab:3, bluecrab:2, swimmingcrab:2, squid:2, cuttlefish:2, octopus:3, seahorse:5, /* ── 鱼肉(已处理) ── */ salmon_meat:2, seabass_meat:2, tuna_meat:1, sardine_meat:2, herring_meat:2, grouper_meat:2, mahi_meat:2, cod_meat:2, eel_meat:3, flounder_meat:2, mackerel_meat:2, bream_meat:2, anchovy_meat:2, barracuda_meat:2, hairtail_meat:2, sunfish_meat:2, anglerfish_meat:2, fish_meat:2, /* ── 贝肉/虾蟹肉/头足肉 ── */ scallop_meat:1, clam_meat:1, oyster_meat:1, mussel_meat:1, conch_meat:2, prawn_meat:1, lobster_meat:1, mantisshrimp_meat:1, kingcrab_meat:2, snowcrab_meat:2, bluecrab_meat:1, squid_meat:2, cuttlefish_meat:2, octopus_meat:2, shell_meat:1, shrimp_meat:1, crab_meat:2, /* ── 藻类食材 ── */ dried_kelp:30, dried_nori:30, seajelly:3, /* ── 其他食材 ── */ urchin_roe:1, octopus_meat:2, wheat_grain:60, seaweed_grain:60, potato_tuber:10, kelp_tuber:10, sealeaf:3, sprout:2, sea_berry:5, wild_berry:3, /* ── 菜品 ── */ fish_soup:2, seafood_hotpot:2, grilled_fish:2, steamed_fish:2, smoked_fish:5, sashimi:1, fish_porridge:2, seaweed_salad:2, mixed_seafood:2, char_mess:1, watery_stew:1, steamed_blob:1, raw_pile:1, fish_berry_grill:2 }>>
<<nobr>> <<widget "decayItems">> /* 遍历仓库和背包,清除腐烂条目,为腐败条目打标 */ <<set _dc_pools = [ { name: "store", data: $store }, { name: "backpack", data: $backpack } ]>> <<for _dcp = 0; _dcp < _dc_pools.length; _dcp++>> <<set _dc_pool = _dc_pools[_dcp].data>> <<set _dc_cats = Object.keys(_dc_pool)>> <<for _dcc = 0; _dcc < _dc_cats.length; _dcc++>> <<set _dc_cat = _dc_cats[_dcc]>> <<if Array.isArray(_dc_pool[_dc_cat])>> <<set _dc_arr = _dc_pool[_dc_cat]>> <<for _dci = _dc_arr.length - 1; _dci >= 0; _dci-->> <<set _dc_e = _dc_arr[_dci]>> <<if _dc_e.addedDay !== undefined>> <<set _dc_sd = ($spoilDays && $spoilDays[_dc_e.id]) ? $spoilDays[_dc_e.id] : 0>> <<if _dc_sd > 0>> <<set _dc_age = $day - _dc_e.addedDay>> /* 腐烂阶段 0-3 */ <<set _dc_stage = Math.floor(_dc_age / _dc_sd * 3)>> <<if _dc_stage >= 3>> /* 完全腐烂:记录损失后移除 */ <<if !$decayLog>><<set $decayLog = []>><</if>> <<run $decayLog.push({ id: _dc_e.id, qty: _dc_e.quantity, day: $day })>> <<run _dc_arr.splice(_dci, 1)>> <<else>> <<set $dc_arr[_dci].stage = _dc_stage>> <</if>> <</if>> <</if>> <</for>> <</if>> <</for>> <</for>> <</widget>> <</nobr>>
<<nobr>> <<widget "freshnessTag">> /* args[0] = entry(含 id, addedDay, stage) 输出一个带颜色的鲜度标签 */ <<set _ft_e = $args[0]>> <<if !_ft_e || !_ft_e.addedDay>> /* 无腐败记录,不显示标签 */ <<else>> <<set _ft_sd = $spoilDays ? ($spoilDays[_ft_e.id] || 0) : 0>> <<if _ft_sd > 0>> <<set _ft_age = $day - _ft_e.addedDay>> <<set _ft_stage = Math.floor(_ft_age / _ft_sd * 3)>> <<if _ft_stage <= 0>> <span style="color:#8bc4a0;font-size:0.68rem;margin-left:0.2rem;">新鲜</span> <<elseif _ft_stage === 1>> <span style="color:var(--amber);font-size:0.68rem;margin-left:0.2rem;">轻微变质</span> <<elseif _ft_stage === 2>> <span style="color:var(--danger-bright);font-size:0.68rem;margin-left:0.2rem;">⚠腐败</span> <</if>> <</if>> <</if>> <</widget>> <</nobr>>
/* ── 单类模板:1种食材,单一分类标签 ── key = "分类标签_烹饪方式" 当选择1种食材时命中对应 key 查询 */ <<set $cookSingleTemplates = { /* ─── 鱼 ─── */ "鱼_明火烤": { name:"烤鱼", hunger:18, water:0, life:4, power:2, san:3, magic:0, dur:25, sMin:6, sMax:22, pMin:10, pMax:18, open:"鱼肉架在炭火上,油脂渗出,滋滋作响。", close:"表皮焦香而内里鲜嫩,是最朴素也最直接的美味。" }, "鱼_清蒸": { name:"清蒸鱼", hunger:16, water:3, life:6, power:1, san:4, magic:0, dur:28, sMin:7, sMax:25, pMin:12, pMax:21, open:"鱼肉摆入蒸格,蒸汽轻柔地将热量渗入肌理。", close:"肉质细嫩,鲜味完整地保存在每一片纤维里。" }, "鱼_铜锅炖": { name:"鱼汤", hunger:15, water:12, life:5, power:1, san:3, magic:0, dur:30, sMin:8, sMax:27, pMin:14, pMax:22, open:"鱼肉入锅,汤底逐渐泛起奶白色的乳化脂肪。", close:"汤底鲜甜,喝下去从胃里暖到指尖。" }, "鱼_煎炒": { name:"煎鱼", hunger:17, water:0, life:3, power:3, san:2, magic:0, dur:20, sMin:5, sMax:18, pMin:8, pMax:15, open:"热锅冷油,鱼肉下锅的瞬间嗤嗤作响。", close:"两面金黄,外脆里嫩,锅气赋予了鱼肉额外的香气。" }, "鱼_油炸": { name:"炸鱼", hunger:20, water:-2, life:2, power:3, san:2, magic:0, dur:22, sMin:5, sMax:19, pMin:9, pMax:16, open:"鱼肉裹上薄薄的粉衣,在滚热的油中翻滚。", close:"捞出后金黄酥脆,每一口都是热油的满足感。" }, "鱼_生食": { name:"鱼刺身", hunger:12, water:2, life:3, power:0, san:5, magic:1, dur:15, sMin:4, sMax:13, pMin:6, pMax:11, open:"将最新鲜的鱼肉切成薄片,刀工决定一切。", close:"入口即化,是对食材原味最诚实的呈现。" }, /* ─── 虾 ─── */ "虾_明火烤": { name:"烤虾", hunger:16, water:0, life:3, power:2, san:3, magic:0, dur:18, sMin:5, sMax:16, pMin:8, pMax:14, open:"虾放上烤架,外壳在高温中迅速变红。", close:"弹牙的虾肉带着炭火的焦香,壳与肉之间汁水充盈。" }, "虾_清蒸": { name:"清蒸虾", hunger:14, water:3, life:4, power:1, san:3, magic:0, dur:20, sMin:5, sMax:18, pMin:9, pMax:15, open:"虾整齐排入蒸格,蒸汽升腾。", close:"虾肉Q弹鲜甜,原味丝毫未失。" }, "虾_铜锅炖": { name:"虾汤", hunger:13, water:10, life:4, power:1, san:2, magic:0, dur:25, sMin:6, sMax:22, pMin:11, pMax:18, open:"虾入锅,橙红色的虾壳将颜色渗入汤底。", close:"汤底带着淡淡的甜鲜,是简单而令人满足的一碗。" }, "虾_煎炒": { name:"炒虾", hunger:15, water:0, life:2, power:3, san:2, magic:0, dur:18, sMin:4, sMax:16, pMin:7, pMax:14, open:"虾入热锅,壳在高温下迅速锁住内部的汁水。", close:"爆炒出锅,脆嫩鲜香,火候是关键。" }, "虾_油炸": { name:"炸虾", hunger:18, water:-1, life:2, power:2, san:3, magic:0, dur:18, sMin:4, sMax:16, pMin:8, pMax:13, open:"整只虾裹粉入油,在金黄的油浪中翻腾。", close:"酥脆的外壳包裹着弹牙的虾肉,是让人忍不住多吃的口感。" }, /* ─── 蟹 ─── */ "蟹_明火烤": { name:"烤蟹", hunger:17, water:0, life:3, power:2, san:3, magic:0, dur:25, sMin:7, sMax:22, pMin:11, pMax:18, open:"蟹肉在炭火边缘慢慢受热,蟹黄逐渐凝固成金色。", close:"焦香的外壳锁住了蟹肉的鲜甜,需要耐心拆开才能取食。" }, "蟹_清蒸": { name:"清蒸蟹", hunger:15, water:2, life:5, power:1, san:5, magic:0, dur:25, sMin:6, sMax:22, pMin:11, pMax:18, open:"整只蟹摆入蒸格,蟹壳在蒸汽中逐渐由青灰转为鲜艳的橙红。", close:"掀开蟹盖,金黄的蟹黄凝固如玉,是一年中最奢侈的时刻。" }, "蟹_铜锅炖": { name:"蟹汤", hunger:14, water:11, life:4, power:1, san:3, magic:0, dur:28, sMin:7, sMax:25, pMin:12, pMax:20, open:"蟹肉入锅,蟹黄溶入汤底,汤色渐渐变得橙黄浓郁。", close:"汤底香浓,带着蟹特有的甘甜与微腥,喝完意犹未尽。" }, "蟹_煎炒": { name:"炒蟹", hunger:16, water:0, life:2, power:3, san:2, magic:0, dur:20, sMin:5, sMax:18, pMin:9, pMax:15, open:"蟹肉下锅,蟹黄在高温中散开,香气扑鼻。", close:"大火快炒,蟹肉鲜嫩不柴,蟹黄的浓香包裹每一块肉。" }, /* ─── 贝 ─── */ "贝_明火烤": { name:"烤贝", hunger:14, water:2, life:3, power:1, san:4, magic:0, dur:18, sMin:4, sMax:16, pMin:7, pMax:13, open:"贝类放上烤架,贝壳在高温中慢慢开口,汁水滋滋蒸发。", close:"贝肉微微焦化,鲜甜与炭香交织,是最简单的海边风味。" }, "贝_清蒸": { name:"清蒸贝", hunger:12, water:4, life:4, power:1, san:4, magic:0, dur:20, sMin:5, sMax:18, pMin:9, pMax:15, open:"贝类入蒸格,蒸汽引导壳肉分离,贝汁在壳内积聚。", close:"贝肉Q弹,壳内积聚的原汁是最纯粹的海味。" }, "贝_铜锅炖": { name:"贝汤", hunger:12, water:13, life:4, power:0, san:3, magic:0, dur:25, sMin:6, sMax:22, pMin:11, pMax:18, open:"贝类入锅,壳在沸腾中张开,将浓郁的贝汁释放进汤底。", close:"汤底清澈而鲜甜,有一种宁静的满足感。" }, "贝_煎炒": { name:"炒贝", hunger:13, water:1, life:2, power:2, san:3, magic:0, dur:18, sMin:4, sMax:16, pMin:7, pMax:13, open:"贝肉入热锅,高温迅速锁住水分,鲜味被封存在弹牙的肉质里。", close:"快炒出锅,口感爽脆,鲜甜中带着一丝锅气的焦香。" }, "贝_油炸": { name:"炸贝", hunger:16, water:-1, life:2, power:2, san:3, magic:0, dur:18, sMin:4, sMax:16, pMin:7, pMax:13, open:"贝肉裹上薄粉,在热油里翻滚,外层迅速酥化。", close:"咬破酥脆的外壳,内里的贝肉依然软嫩多汁。" }, "贝_生食": { name:"生贝", hunger:10, water:3, life:2, power:0, san:6, magic:1, dur:12, sMin:3, sMax:11, pMin:5, pMax:9, open:"撬开贝壳,新鲜的贝肉躺在壳内,带着海水的盐分。", close:"滑入喉咙,是最直接的海洋的味道。" }, /* ─── 腕足 ─── */ "腕足_明火烤": { name:"烤腕足", hunger:16, water:0, life:3, power:2, san:3, magic:0, dur:22, sMin:6, sMax:20, pMin:10, pMax:16, open:"腕足放上烤架,吸盘在高温中卷曲收缩,表面迅速上色。", close:"焦香与弹牙并存,是别具一格的口感体验。" }, "腕足_清蒸": { name:"清蒸腕足", hunger:14, water:3, life:4, power:1, san:3, magic:0, dur:30, sMin:7, sMax:27, pMin:13, pMax:22, open:"腕足入蒸格,蒸汽慢慢将热量渗透进厚实的肌肉层。", close:"肉质Q弹,蒸制时间是关键——过了就会韧如皮革。" }, "腕足_铜锅炖": { name:"墨汁腕足汤", hunger:15, water:10, life:4, power:1, san:3, magic:2, dur:35, sMin:9, sMax:32, pMin:16, pMax:27, open:"腕足入锅,墨囊破裂,浓郁的墨汁将汤底染成深邃的黑色。", close:"漆黑的汤底带着独特的海鲜鲜味与矿物气息,令人难以忘怀。" }, "腕足_煎炒": { name:"炒腕足", hunger:15, water:0, life:3, power:3, san:2, magic:0, dur:20, sMin:5, sMax:18, pMin:8, pMax:15, open:"腕足下热锅,大火快炒,吸盘在锅气中膨胀焦脆。", close:"火候要快,过了便老,恰到好处时弹牙鲜香。" }, "腕足_油炸": { name:"炸腕足", hunger:18, water:-1, life:2, power:3, san:2, magic:0, dur:20, sMin:5, sMax:18, pMin:8, pMax:15, open:"腕足段裹粉入油,吸盘面朝下,在热油中逐渐酥化。", close:"咬下去外脆里Q,是最受欢迎的炸海鲜形态之一。" }, "腕足_生食": { name:"生腕足刺身", hunger:11, water:2, life:2, power:0, san:4, magic:1, dur:15, sMin:4, sMax:13, pMin:6, pMax:11, open:"将腕足处理成薄切片,对刀工和食材新鲜度要求极高。", close:"晶莹剔透的切面,Q弹而带着淡淡的海水甜味。" }, /* ─── 海草 ─── */ "海草_铜锅炖": { name:"海草羹", hunger:10, water:10, life:2, power:0, san:3, magic:1, dur:20, sMin:5, sMax:18, pMin:8, pMax:14, open:"海草入锅,在热水中舒展开来,释放出淡淡的海洋气息。", close:"羹汤滑润,带着海草独特的矿物鲜味,暖胃而清爽。" }, "海草_煎炒": { name:"炒海草", hunger:8, water:3, life:1, power:1, san:2, magic:1, dur:15, sMin:4, sMax:14, pMin:6, pMax:11, open:"海草入热锅,水分迅速蒸发,叶片边缘开始变脆。", close:"口感介于脆爽与柔韧之间,有一种独特的海盐余味。" }, "海草_生食": { name:"海草沙拉", hunger:7, water:5, life:1, power:0, san:4, magic:1, dur:12, sMin:3, sMax:11, pMin:5, pMax:9, open:"将海草漂洗干净,保留最原始的海洋风味。", close:"清脆爽口,海水的咸鲜与植物的清新完美融合。" }, /* ─── 块茎 ─── */ "块茎_明火烤": { name:"烤薯", hunger:18, water:-1, life:2, power:3, san:3, magic:0, dur:25, sMin:6, sMax:22, pMin:11, pMax:18, open:"块茎裹泥放入炭火边缘,外皮在高温中逐渐焦化。", close:"外皮酥脆,内里绵软香甜,是朴素的满足感。" }, "块茎_铜锅炖": { name:"块茎浓汤", hunger:16, water:8, life:3, power:2, san:3, magic:0, dur:30, sMin:8, sMax:27, pMin:14, pMax:22, open:"块茎切块入锅,淀粉逐渐析出,汤底变得浓稠。", close:"厚实的汤底充满饱腹感,是最能驱寒的食物之一。" }, "块茎_煎炒": { name:"煎薯块", hunger:17, water:0, life:2, power:3, san:2, magic:0, dur:20, sMin:5, sMax:18, pMin:8, pMax:15, open:"块茎切片入热油锅,表面迅速焦化上色。", close:"外脆内软,吸足油脂的薯片带着令人愉悦的香气。" }, "块茎_油炸": { name:"炸薯", hunger:20, water:-2, life:1, power:3, san:3, magic:0, dur:18, sMin:4, sMax:16, pMin:7, pMax:13, open:"薯条入滚油,淀粉在高温中脱水酥化。", close:"金黄酥脆,是高热量的简单享受。" }, /* ─── 谷物 ─── */ "谷物_铜锅炖": { name:"白粥", hunger:14, water:12, life:3, power:1, san:4, magic:0, dur:30, sMin:8, sMax:27, pMin:14, pMax:22, open:"谷物入锅,在大量水中慢慢熬煮,淀粉逐渐释放。", close:"米粒开花,粥底浓稠,是病弱时最温柔的食物。" }, "谷物_煎炒": { name:"炒饭", hunger:18, water:0, life:2, power:3, san:3, magic:0, dur:20, sMin:5, sMax:18, pMin:9, pMax:15, open:"熟饭入热锅,大火翻炒,每一粒米都在锅气中分离。", close:"粒粒分明,焦香扑鼻,是快餐中的经典。" }, "谷物_油炸": { name:"炸饭团", hunger:20, water:-1, life:1, power:3, san:2, magic:0, dur:15, sMin:4, sMax:14, pMin:6, pMax:11, open:"饭团捏紧裹粉入油,外层迅速酥化定型。", close:"咬破酥壳,内里的米饭软糯,口感出人意料地丰富。" }, /* ─── 蔬菜 ─── */ "蔬菜_铜锅炖": { name:"蔬菜汤", hunger:10, water:10, life:2, power:1, san:3, magic:0, dur:20, sMin:5, sMax:18, pMin:8, pMax:14, open:"蔬菜入锅,在热水中慢慢软化,叶绿素逐渐释放。", close:"汤底清淡,带着蔬菜天然的甘甜,是轻盈的温暖。" }, "蔬菜_煎炒": { name:"炒蔬菜", hunger:9, water:2, life:2, power:2, san:3, magic:0, dur:15, sMin:4, sMax:14, pMin:6, pMax:11, open:"蔬菜入热锅,大火翻炒,水分迅速蒸发。", close:"保留了脆爽的口感和鲜亮的色泽,清淡而不失风味。" }, "蔬菜_生食": { name:"生鲜沙拉", hunger:7, water:4, life:2, power:0, san:4, magic:1, dur:10, sMin:3, sMax:9, pMin:4, pMax:8, open:"将蔬菜仔细洗净,保留最原始的状态。", close:"清脆爽口,最大程度保留了营养,适合作为其他料理的配餐。" } }>> /* ── 多类模板:2-3种食材,按优先级顺序匹配 ── 每条规则包含匹配条件和效果 seafoodTags = {鱼,虾,蟹,贝,腕足} 中任意一个 */ <<set $cookMultiTemplates = [ /* 优先级1:海鲜+谷物+蔬菜 = 杂炊 */ { id:"seafood_grain_veg", name:"海鲜杂炊", hasSeafood:true, requires:["谷物","蔬菜"], methods:["铜锅炖"], hunger:22, water:12, life:6, power:2, san:5, magic:0, dur:35, sMin:9, sMax:31, pMin:15, pMax:26, open:"锅里放入了所有能用的食材,海鲜、谷物与蔬菜各自贡献着风味。", close:"一锅大杂烩,味道复杂而令人惊喜,有一种将就中诞生的满足感。" }, /* 优先级2:海鲜+谷物 */ { id:"seafood_grain_stew", name:"海鲜粥", hasSeafood:true, requires:["谷物"], methods:["铜锅炖"], hunger:20, water:14, life:5, power:1, san:5, magic:0, dur:32, sMin:8, sMax:29, pMin:14, pMax:24, open:"谷物与海鲜同煮,淀粉逐渐释放,将汤底变得浓稠绵密。", close:"粥底融合了海鲜的鲜味,米粒开花,每一口都是温柔的满足。" }, { id:"seafood_grain_fry", name:"海鲜炒饭", hasSeafood:true, requires:["谷物"], methods:["煎炒"], hunger:22, water:0, life:4, power:3, san:4, magic:0, dur:22, sMin:5, sMax:20, pMin:9, pMax:16, open:"熟饭与海鲜同入热锅,大火翻炒,锅气将两者的香气融合在一起。", close:"粒粒分明,海鲜的鲜甜渗透进每一粒米,是最有满足感的炒饭。" }, /* 优先级3:海鲜+块茎 */ { id:"seafood_tuber_stew", name:"海鲜浓汤", hasSeafood:true, requires:["块茎"], methods:["铜锅炖"], hunger:20, water:10, life:5, power:2, san:4, magic:0, dur:32, sMin:8, sMax:29, pMin:14, pMax:24, open:"块茎的淀粉在炖煮中析出,与海鲜汁水融合,汤底越来越浓稠。", close:"浓郁厚实的奶白色汤底,海鲜的鲜与块茎的甜相互衬托。" }, /* 优先级4:海鲜+海草 */ { id:"seafood_seaweed_stew", name:"海草海鲜汤", hasSeafood:true, requires:["海草"], methods:["铜锅炖"], hunger:16, water:13, life:5, power:1, san:4, magic:1, dur:28, sMin:7, sMax:25, pMin:12, pMax:20, open:"海草与海鲜同煮,海草的矿物气息与鲜味交织在一起。", close:"汤底清澈,带着海洋深处的味道,令人心静。" }, /* 优先级5:海鲜+蔬菜 */ { id:"seafood_veg_fry", name:"海鲜炒蔬", hasSeafood:true, requires:["蔬菜"], methods:["煎炒"], hunger:17, water:2, life:4, power:3, san:4, magic:0, dur:20, sMin:5, sMax:18, pMin:8, pMax:15, open:"海鲜与蔬菜同入热锅,各自的香气在锅气中短暂碰撞。", close:"蔬菜的清脆与海鲜的鲜嫩形成对比,是均衡而色彩丰富的一盘。" }, /* 优先级6:混合海鲜(纯海鲜多种) */ { id:"seafood_mix_stew", name:"海鲜锅", seafoodOnly:true, methods:["铜锅炖"], hunger:18, water:12, life:5, power:1, san:5, magic:0, dur:32, sMin:8, sMax:29, pMin:14, pMax:24, open:"多种海鲜同入一锅,各自的鲜味在沸腾中慢慢融合。", close:"汤底集合了所有食材的精华,是一道需要耐心的料理。" }, { id:"seafood_mix_roast", name:"海鲜烤串", seafoodOnly:true, methods:["明火烤"], hunger:20, water:0, life:4, power:2, san:5, magic:0, dur:25, sMin:6, sMax:22, pMin:11, pMax:18, open:"将不同的海鲜串在一起,架上炭火,各自散发着不同的香气。", close:"一串囊括了多种风味,每一口都有不同的惊喜。" }, { id:"seafood_mix_fry", name:"海鲜炒", seafoodOnly:true, methods:["煎炒"], hunger:18, water:0, life:4, power:3, san:4, magic:0, dur:20, sMin:5, sMax:18, pMin:8, pMax:15, open:"多种海鲜同入热锅,大火翻炒,不同的质地在锅气中碰撞。", close:"层次丰富的海鲜炒,每一块都有不同的口感等待被发现。" }, { id:"seafood_mix_steam", name:"海鲜蒸", seafoodOnly:true, methods:["清蒸"], hunger:16, water:4, life:5, power:1, san:5, magic:0, dur:25, sMin:6, sMax:22, pMin:11, pMax:18, open:"多种海鲜依口感厚薄分层摆放,让蒸汽均匀渗透每一种食材。", close:"各自保留原味,又在蒸汽中完成了一次温柔的交融。" }, { id:"seafood_mix_raw", name:"海鲜拼盘", seafoodOnly:true, methods:["生食"], hunger:14, water:3, life:3, power:0, san:7, magic:1, dur:15, sMin:4, sMax:13, pMin:6, pMax:11, open:"将多种新鲜海鲜精心处理,各自切割成最适合生食的形态。", close:"一盘集合了不同形态与口感的生鲜,对食材新鲜度的极致考验。" }, /* 优先级7:非海鲜组合 */ { id:"seaweed_grain_stew", name:"海菜粥", requires:["海草","谷物"], noSeafood:true, methods:["铜锅炖"], hunger:13, water:11, life:2, power:1, san:4, magic:1, dur:28, sMin:7, sMax:25, pMin:12, pMax:20, open:"谷物与海草同煮,粥底带着淡淡的海洋清香。", close:"清淡而养胃,是简单食材组合出的朴素美味。" }, { id:"grain_tuber_stew", name:"杂粮粥", requires:["谷物","块茎"], methods:["铜锅炖"], hunger:16, water:10, life:3, power:2, san:3, magic:0, dur:30, sMin:8, sMax:27, pMin:14, pMax:22, open:"谷物与块茎同煮,两种淀粉质在炖煮中相互融合。", close:"粥底浓稠,块茎的甘甜渗透其中,是填饱肚子的最实在选择。" } ]>>
/* 每种食材在不同烹饪方式下的感官描述碎片(1-2句) 降级规则:fragments[id][method] → fragments[id]["_"] → fragments["_tag_"][method] → "" key "_tag_" 为分类兜底 */ <<set $cookFragments = { /* ─── 鱼肉 ─── */ "salmon_meat": { "明火烤": "鲑鱼肉在炭火上油脂渗出,粉红色的肌肉转变为金黄,边缘微微焦脆。", "清蒸": "鲑鱼肉在蒸汽中轻柔展开,橙粉色的纹理清晰可见,脂肪的清香随热气散开。", "铜锅炖": "鲑鱼肉融入汤底,脂肪乳化,汤色呈现乳白,带来醇厚的回甘。", "煎炒": "鲑鱼肉入锅后嗤嗤作响,外层迅速锁住汁水,焦香的表皮包裹着嫩滑的鱼肉。", "油炸": "鲑鱼肉在热油中翻滚,金黄酥脆,切开后橙色的内里冒着热气。", "生食": "鲑鱼肉切成薄片,粉红色的纹理如同绸缎,入口即化,带着淡淡的海水甘甜。" }, "cod_meat": { "明火烤": "鳕鱼肉在炭火上层层剥落,雪白的鱼肉沿纹理分离,带着淡淡的焦香。", "清蒸": "鳕鱼肉的层状纹理在蒸汽中清晰展现,用筷子轻轻一拨就成片,汁水清甜。", "铜锅炖": "鳕鱼肉在汤底慢慢软化,释放出清淡的鲜味,汤色维持透明。", "煎炒": "鳕鱼肉入热锅,表面迅速变白定型,外脆内嫩,口感清淡而鲜美。", "油炸": "鳕鱼肉片在热油中膨胀酥化,外层金黄,内里依然洁白软嫩。", "生食": "鳕鱼肉洁白如雪,切成薄片后几乎透明,鲜味清淡纯粹。" }, "tuna_meat": { "明火烤": "金枪鱼肉在炭火上迅速变色,深红转为棕色,油脂在表面渗出带着焦香。", "清蒸": "金枪鱼肉在蒸汽中保持着厚实的质地,深色的肌肉透出血铁质特有的浓郁鲜味。", "铜锅炖": "金枪鱼肉入汤,将汤底染上淡淡的红色,释放出浓厚的海鲜鲜味。", "煎炒": "金枪鱼肉入锅,表面迅速上色,内里保持粉红,大火快炒保留了汁水。", "油炸": "金枪鱼肉裹粉入油,外层酥脆,内里仍带着特有的铁腥鲜味。", "生食": "金枪鱼肉呈深红色,油脂丰富,切成厚片后在舌尖缓缓化开,是最适合生食的鱼肉之一。" }, "eel_meat": { "明火烤": "鳗鱼肉在炭火上油脂大量渗出,滴落在炭上腾起白烟,香气极其浓郁。", "清蒸": "鳗鱼肉在蒸汽中软化,脂肪均匀渗透肌肉,口感绵密而香腴。", "铜锅炖": "鳗鱼肉在汤底慢慢熬煮,大量脂肪融入汤中,汤底变得异常浓郁丰腴。", "煎炒": "鳗鱼肉入热锅,油脂迅速渗出自行润锅,焦香与脂香同时散发。", "油炸": "鳗鱼肉的高油脂在炸制时产生独特的香气,外层酥脆而内里极为软嫩。", "_": "鳗鱼特有的脂香在烹饪过程中持续散发,是少数越简单处理越出彩的食材。" }, "flounder_meat": { "清蒸": "比目鱼肉的两片薄肉在蒸汽中微微卷起,洁白如雪,鲜甜几乎不需要任何调味。", "明火烤": "比目鱼薄肉在炭火上迅速熟透,边缘焦脆,中心依然嫩滑。", "铜锅炖": "比目鱼肉在汤底几乎化开,留下清甜的鲜味而不见形状。", "生食": "比目鱼肉切成透明薄片,晶莹剔透,入口的清甜令人难忘。", "_": "比目鱼肉质极嫩,任何烹饪方式都需要控制时间,稍过就会失去独特的细腻。" }, "sardine_meat": { "明火烤": "沙丁鱼肉在炭火上脂肪渗出,腥气在高温中转化为浓郁的焦香。", "铜锅炖": "沙丁鱼肉在汤底快速散开,将丰富的脂肪释放进汤中,味道厚重而直接。", "_": "沙丁鱼肉细碎而脂肪丰富,加热后腥气转化为独特的浓郁鲜味。" }, /* ─── 贝肉 ─── */ "scallop_meat": { "明火烤": "扇贝肉在炭火边缘慢慢受热,圆润的闭壳肌微微焦化,边缘泛出金黄色。", "清蒸": "扇贝肉在蒸汽中保持着丰腴的形态,表面微微收紧,汁水锁在内里。", "铜锅炖": "扇贝肉在汤底慢慢舒展,释放出浓郁的贝汁,汤底因此带上乳白色的甜鲜。", "煎炒": "扇贝肉入热锅,两面各煎出金黄的焦壳,内里保持嫩滑,鲜甜迸发。", "生食": "扇贝肉洁白圆润,生食时鲜甜几乎不需要任何佐料,是最直接的海洋馈赠。" }, "oyster_meat": { "明火烤": "牡蛎在炭火上慢慢加热,壳边汁水沸腾,带着海水咸鲜的蒸汽腾起。", "清蒸": "牡蛎在蒸汽中保持了饱满的形态,汁水充盈在壳内,矿物鲜味极为浓郁。", "铜锅炖": "牡蛎入汤后软化,将浓烈的矿物鲜味全部释放,汤底因此格外深沉。", "生食": "牡蛎的软体光滑饱满,生食时带着海水的冷冽与矿物的复杂,入口即化。" }, "clam_meat": { "铜锅炖": "蛤蜊肉在汤底中释放出浓郁的贝汁,将清澈的汤底迅速染上深沉的鲜味。", "清蒸": "蛤蜊肉在蒸汽中收紧,壳内积聚的原汁是汤汁中最鲜甜的部分。", "煎炒": "蛤蜊肉入热锅,贝汁迅速蒸发浓缩,鲜味在瞬间变得极为集中。", "_": "蛤蜊的咸鲜味道极为浓郁,少量入菜便能提升整道料理的层次。" }, /* ─── 虾肉 ─── */ "prawn_meat": { "明火烤": "对虾在炭火上迅速变红,壳与肉之间的汁水被封存,外层微微焦脆。", "清蒸": "对虾在蒸汽中保持着弯曲的形态,弹牙的肉质在蒸汽中达到最佳口感。", "铜锅炖": "对虾入汤后橙红色的虾壳将甜鲜释放进汤底,虾肉保持弹牙。", "煎炒": "对虾入热锅,壳迅速锁住内部的汁水,大火翻炒出弹牙的口感。", "油炸": "整只对虾裹粉入油,外壳酥脆,一口咬下汁水迸发。", "生食": "对虾肉半透明,处理好后带着清甜的鲜味,是生食中口感最佳的虾类。" }, "lobster_meat": { "明火烤": "龙虾肉在炭火上受热,厚实的肌肉纤维分离,表面微焦而内里极为鲜嫩。", "清蒸": "龙虾在蒸汽中慢慢熟透,厚实的肌肉在蒸汽中保持了丰润的汁水。", "铜锅炖": "龙虾肉入汤,将浓郁的甜鲜释放进汤底,是所有海鲜中汤底最浓郁的之一。", "_": "龙虾肉厚实而鲜甜,是虾类中品质最高的食材,任何烹饪方式都难以糟蹋它。" }, /* ─── 蟹肉 ─── */ "kingcrab_meat": { "明火烤": "帝王蟹肉纤维分明,在炭火上慢慢受热,蟹黄的香气随油脂渗出。", "清蒸": "帝王蟹肉在蒸汽中保持了厚实的质地,洁白的肌肉纤维呈现美丽的条纹。", "铜锅炖": "帝王蟹腿肉入汤,将浓厚的甜鲜析入汤底,是最奢华的汤底来源。", "_": "帝王蟹肉是蟹类中最为丰厚的食材,纤维质感和甜鲜味道在海鲜中无与伦比。" }, "crab_meat": { "清蒸": "蟹肉在蒸汽中慢慢熟透,蟹黄凝固成金色,拆开后鲜甜浓郁。", "铜锅炖": "蟹肉与蟹黄在汤底中慢慢融合,将橙黄色的浓郁鲜味渗入汤底。", "_": "蟹肉细腻鲜甜,蟹黄的浓香是整道料理的灵魂。" }, /* ─── 腕足 ─── */ "squid_meat": { "明火烤": "鱿鱼筒在炭火上迅速卷曲,表面焦化,吸盘弹开,散发出特有的海鲜焦香。", "清蒸": "鱿鱼肉在蒸汽中保持着筒状,微微收紧,口感介于嫩滑与Q弹之间。", "铜锅炖": "鱿鱼肉入锅,墨汁轻微渗出,为汤底添加了一层深沉的海洋气息。", "煎炒": "鱿鱼圈入热锅,大火快炒,吸盘在锅气中膨胀,外缘微焦,口感爽脆。", "油炸": "鱿鱼圈裹粉入油,外层酥脆金黄,内里依然Q弹,是最受欢迎的炸海鲜形态。", "生食": "鱿鱼肉切成薄片,晶莹如玉,Q弹的口感与淡淡的海水甜味令人印象深刻。" }, "octopus_meat": { "铜锅炖": "章鱼肉入锅,墨囊破裂,漆黑的墨汁将汤底染成深邃的黑色,带着复杂的海洋鲜味。", "煎炒": "章鱼腕足入热锅,吸盘在高温下焦脆,大火快炒出弹牙的口感与焦香。", "明火烤": "章鱼肉在炭火上受热卷曲,吸盘变脆,表面焦化,散发浓郁的烟熏海鲜香气。", "_": "章鱼肉含有大量墨汁,烹饪时往往为料理增添深色与独特的矿物气息。" }, "cuttlefish_meat": { "铜锅炖": "墨鱼肉入汤,厚实的外套膜慢慢软化,特有的墨囊香气弥漫在汤底之中。", "煎炒": "墨鱼肉入热锅,厚实的肉质在大火中保持形状,口感比鱿鱼更为厚重扎实。", "_": "墨鱼肉厚实肥腴,口感介于鱿鱼与章鱼之间,墨囊香气是其独特之处。" }, /* ─── 海草 ─── */ "dried_kelp": { "铜锅炖": "干海带泡发后入锅,在热汤中慢慢舒展,释放出深海的矿物鲜味与淡淡的碘香。", "煎炒": "泡发的海带切段入热锅,翻炒中水分蒸发,口感从柔韧变为微脆。", "_": "干海带泡发后体积大幅增加,带着浓缩的矿物鲜味,是汤底的极佳提鲜材料。" }, "dried_nori": { "铜锅炖": "干紫菜遇水迅速软化舒展,将深绿色与浓郁的海洋鲜味释放进汤底。", "生食": "干紫菜可以直接入口,薄脆的质感在口中化开,带着淡淡的盐味与海洋清香。", "_": "干紫菜处理简单,鲜味浓缩,少量入菜便能大幅提升整体风味。" }, "seajelly": { "生食": "水母冻处理干净后呈现半透明的凝冻状,口感极为滑嫩,几乎无味,需要配合其他食材。", "清蒸": "水母冻在蒸汽中进一步凝固,口感从滑嫩转为略带弹性,保留了独特的质地。", "_": "水母冻几乎无味,其价值在于独特的滑嫩口感,以及作为其他食材风味的衬托。" }, /* ─── 块茎蔬菜 ─── */ "potato_tuber": { "明火烤": "海薯在炭火边缘慢慢受热,外皮焦化,内里的淀粉糊化为绵软的质地。", "铜锅炖": "海薯切块入锅,淀粉慢慢析出,汤底因此变得浓稠丰满。", "煎炒": "海薯切片入热油,表面迅速焦化,内里绵软,咸香的口感令人满足。", "_": "海薯淀粉含量高,任何烹饪方式都能带来饱腹感与绵密的质地。" }, "kelp_tuber": { "铜锅炖": "海带茎切段入汤,在沸腾中软化,释放出淡淡的矿物鲜味,口感保持脆爽。", "煎炒": "海带茎大火快炒,保留了脆爽的口感,表面微微焦化带来咸香。", "_": "海带茎比海带叶更为厚实,口感脆爽,矿物质含量丰富。" }, "sealeaf": { "煎炒": "海叶菜入热锅,大火翻炒,水分迅速蒸发,叶片边缘微微焦脆。", "生食": "海叶菜质地脆嫩,生食时带着淡淡的咸味与清新的植物气息。", "铜锅炖": "海叶菜入汤后迅速软化,将淡绿色与清新的植物鲜味释放进汤底。" }, "sprout": { "煎炒": "芽苗入热锅,脆嫩的茎叶在大火中迅速软化,保留了鲜亮的绿色。", "生食": "芽苗清脆多汁,生食时鲜嫩清甜,带着植物特有的清香。", "_": "芽苗生长迅速,质地脆嫩,无论何种烹饪方式都能带来清新的口感。" }, /* ─── 谷物 ─── */ "wheat_grain": { "铜锅炖": "小麦粒在大量水中慢慢熬煮,淀粉充分糊化,粥底变得绵密醇厚。", "煎炒": "熟制的小麦粒入热锅,在锅气中迅速分离,外层微脆,香气浓郁。", "_": "小麦的淀粉质地在烹饪中提供扎实的饱腹感,是耐饿的基础食材。" }, "seaweed_grain": { "铜锅炖": "海草籽在水中慢慢膨胀糊化,粥底带着淡淡的海洋清香,质地比普通粥更为细腻。", "_": "海草籽营养密度高,在熬煮中散发出淡淡的海洋气息,是特殊的谷物选择。" }, /* ─── 分类兜底 ─── */ "_鱼_": { "明火烤": "鱼肉在炭火上油脂渗出,表面逐渐焦化,鲜味被封存在内里。", "清蒸": "鱼肉在蒸汽中慢慢熟透,保留了鲜嫩的质地与天然的鲜甜。", "铜锅炖": "鱼肉在汤底中释放出清甜的鲜味,汤色随脂肪含量变得乳白或清澈。", "煎炒": "鱼肉入热锅,外层迅速定型,大火保住了内里的汁水与鲜嫩。", "油炸": "鱼肉在热油中酥化,外脆内嫩,鱼的鲜味被完好地封存其中。", "生食": "鱼肉新鲜处理,原始的海洋鲜甜不加掩饰地呈现。" }, "_虾_": { "明火烤": "虾在高温下迅速变红,壳肉之间的汁水被封存,弹牙鲜甜。", "清蒸": "虾在蒸汽中弯曲定型,肉质Q弹,鲜甜充盈。", "铜锅炖": "虾入汤后橙红色的壳将甜鲜渗入汤底,肉质保持弹牙。", "煎炒": "虾入热锅,壳锁汁水,大火翻炒出弹牙的口感。", "油炸": "虾在热油中酥化,外壳脆响,咬下去汁水迸发。", "生食": "新鲜的虾肉半透明,处理好后鲜甜清爽。" }, "_蟹_": { "明火烤": "蟹肉在炭火边慢慢受热,蟹黄的香气随油脂渗出。", "清蒸": "蟹在蒸汽中慢慢熟透,蟹黄凝固为金色,鲜甜达到顶点。", "铜锅炖": "蟹肉入汤,蟹黄溶入汤底,汤色变得橙黄浓郁。", "煎炒": "蟹肉在大火中迅速上色,蟹黄的浓香弥漫开来。", "_": "蟹的鲜甜在高温中完全释放,蟹黄是整道料理的灵魂所在。" }, "_贝_": { "明火烤": "贝类在高温下慢慢开口,汁水蒸发浓缩,鲜甜与焦香交融。", "清蒸": "贝类在蒸汽中张开,原汁积聚在壳内,是纯粹的海洋鲜甜。", "铜锅炖": "贝类入汤,壳在沸腾中开口,将浓郁的贝汁全部释放。", "煎炒": "贝肉入热锅,鲜甜被迅速封存,口感爽脆。", "油炸": "贝肉裹粉入油,外层酥脆,内里依然鲜嫩多汁。", "生食": "贝肉带着天然的海水咸鲜,生食是最诚实的呈现方式。" }, "_腕足_": { "明火烤": "腕足在炭火上卷曲,吸盘变脆,表面焦化,散发独特的烟熏海鲜香气。", "清蒸": "腕足在蒸汽中保持形态,Q弹的肌肉在蒸汽中缓缓达到最佳状态。", "铜锅炖": "腕足入汤,墨汁若隐若现,汤底带上了深沉的海洋气息。", "煎炒": "腕足在热锅中卷曲,吸盘焦脆,大火快炒出弹牙的口感。", "油炸": "腕足裹粉入油,外层酥脆,内里Q弹,是炸海鲜中口感最丰富的之一。", "生食": "腕足薄切后晶莹剔透,Q弹的口感在生食中格外突出。" }, "_海草_": { "铜锅炖": "海草在热汤中舒展,释放出矿物鲜味与淡淡的碘香。", "煎炒": "海草入热锅,水分蒸发,口感从柔韧变为微脆。", "生食": "海草漂洗后保留了海洋的原始清新,是最低调的生食食材。", "_": "海草带着来自深海的矿物气息,是料理中独特的点缀与提鲜材料。" }, "_蔬菜_": { "铜锅炖": "蔬菜在热汤中慢慢软化,为汤底带来植物的清甜与绿意。", "煎炒": "蔬菜在大火中迅速熟化,保留脆爽的口感与鲜亮的色泽。", "生食": "蔬菜清洗后保留了脆嫩的质地与天然的清甜。", "_": "蔬菜为料理增添清新的色彩与植物的天然甘甜。" }, "_块茎_": { "明火烤": "块茎在炭火中缓缓熟透,外皮焦化,内里绵软香甜。", "铜锅炖": "块茎的淀粉在炖煮中析出,让汤底变得浓稠而有饱腹感。", "煎炒": "块茎切片入热油,表面焦化,内里绵软,满足而朴素。", "_": "块茎富含淀粉,任何烹饪方式都能带来扎实的饱腹感。" }, "_谷物_": { "铜锅炖": "谷物在大量水中慢慢膨胀糊化,淀粉充分释放,粥底醇厚绵密。", "煎炒": "熟谷物在锅气中分离翻炒,每一粒都饱含香气。", "_": "谷物是最耐饿的食材,提供了稳定而持久的热量。" } }>>
<<nobr>> <<widget "assembleDish">> <<set _ad_t = $cookTemplate>> <<set _ad_ings = $cookIngredients>> <<set _ad_m = $cookMethod>> <<set _ad_q = $cookQuality>> /* 用纯 SugarCube for 循环收集碎片,不使用 <<run function>> */ <<set _ad_parts = []>> <<for _ad_i = 0; _ad_i < _ad_ings.length; _ad_i++>> <<set _ad_ingId = _ad_ings[_ad_i]>> <<set _ad_ingDef = State.variables.items[_ad_ingId]>> <<set _ad_fmap = $cookFragments ? $cookFragments[_ad_ingId] : null>> <<set _ad_frag = "">> /* 先查精确ID */ <<if _ad_fmap>> <<set _ad_frag = _ad_fmap[_ad_m] || _ad_fmap["_"] || "">> <</if>> /* 再查分类兜底 */ <<if !_ad_frag && _ad_ingDef && _ad_ingDef.foodtags>> <<for _ad_ti = 0; _ad_ti < _ad_ingDef.foodtags.length; _ad_ti++>> <<set _ad_catKey = "_" + _ad_ingDef.foodtags[_ad_ti] + "_">> <<set _ad_cmap = $cookFragments ? $cookFragments[_ad_catKey] : null>> <<if _ad_cmap>> <<set _ad_frag = _ad_cmap[_ad_m] || _ad_cmap["_"] || "">> <<if _ad_frag>><<break>><</if>> <</if>> <</for>> <</if>> <<if _ad_frag>><<run _ad_parts.push(_ad_frag)>><</if>> <</for>> <<set _ad_fragText = _ad_parts.join("")>> /* 品质修正 */ <<set _ad_mult = _ad_q === "完美" ? 1.3 : (_ad_q === "失败" ? 0.4 : 1.0)>> <<set _ad_sanBonus = _ad_q === "完美" ? 3 : (_ad_q === "失败" ? -3 : 0)>> <<set _ad_hunger = Math.round(_ad_t.hunger * _ad_mult)>> <<set _ad_water = Math.round(_ad_t.water * _ad_mult)>> <<set _ad_life = Math.round(_ad_t.life * _ad_mult)>> <<set _ad_power = Math.round(_ad_t.power * _ad_mult)>> <<set _ad_san = Math.round(_ad_t.san * _ad_mult) + _ad_sanBonus>> <<set _ad_magic = _ad_t.magic || 0>> /* 品质附加描述 */ <<set _ad_qualDesc = "">> <<if _ad_q === "完美">> <<set _ad_qualDesc = "火候拿捏得分毫不差,食材的所有潜力都被完整发挥了出来。">> <<elseif _ad_q === "失败">> <<set _ad_qualDesc = "火候没有控制好,最终结果差强人意,只能勉强果腹。">> <</if>> /* 拼接最终描述 */ <<set _ad_desc = (_ad_t.open || "") + _ad_fragText + (_ad_t.close || "") + (_ad_qualDesc ? " " + _ad_qualDesc : "")>> /* 食材名列表 */ <<set _ad_ingNames = []>> <<for _adi = 0; _adi < _ad_ings.length; _adi++>> <<set _ad_idef2 = State.variables.items[_ad_ings[_adi]]>> <<if _ad_idef2>><<run _ad_ingNames.push(_ad_idef2.name)>><</if>> <</for>> /* 构建实例 */ <<set _ad_dish = { template: _ad_t.id || "custom", name: _ad_t.name, method: _ad_m, ingredients: _ad_ings.slice(), ingNames: _ad_ingNames.slice(), quality: _ad_q, desc: _ad_desc, hunger: _ad_hunger, water: _ad_water, life: _ad_life, power: _ad_power, san: _ad_san, magic: _ad_magic, addedDay: $day || 0 }>> /* 找冰箱空位 */ <<if !$fridge>><<set $fridge = [null,null,null,null,null,null,null,null]>><</if>> <<set _ad_slot = -1>> <<for _ads = 0; _ads < $fridge.length; _ads++>> <<if $fridge[_ads] === null>> <<set _ad_slot = _ads>> <<break>> <</if>> <</for>> <<if _ad_slot < 0>> <<set $assembleResult = "full">> <<else>> <<set $fridge[_ad_slot] = _ad_dish>> <<set $assembleResult = "ok">> <<set $assembleSlot = _ad_slot>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "eatDish">> /* args[0] = 冰箱slot索引 */ <<set _ed_slot = $args[0]>> <<set _ed_dish = $fridge[_ed_slot]>> <<if _ed_dish>> <<set $hunger = Math.min(100, $hunger + (_ed_dish.hunger || 0))>> <<set $water = Math.min(100, $water + (_ed_dish.water || 0))>> <<set $life = Math.min(100, $life + (_ed_dish.life || 0))>> <<set $power = Math.min(100, $power + (_ed_dish.power || 0))>> <<set $san = Math.min(100, Math.max(0, $san + (_ed_dish.san || 0)))>> <<set $magic = Math.min(100, $magic + (_ed_dish.magic || 0))>> <<set $fridge[_ed_slot] = null>> <<set $lastEatDesc = _ed_dish.desc>> <<set $lastEatName = _ed_dish.name>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<if !$fridge>><<set $fridge = [null,null,null,null,null,null,null,null]>><</if>> <<set _fr_count = $fridge.filter(x => x !== null).length>> <div style="font-size:0.78rem;color:var(--bone-dim);margin-bottom:0.6rem;"> 冰箱储藏 <span style="color:var(--amber-bright);"><<print _fr_count>>/8</span> </div> <div class="inv-grid" style="grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:0.4rem;"> <<for _fri = 0; _fri < $fridge.length; _fri++>> <<capture _fri>> <<set _fd = $fridge[_fri]>> <<if _fd === null>> <span class="inv-item" style="opacity:0.25;font-size:0.75rem;justify-content:center;">— 空 —</span> <<else>> <<set _fd_age = ($day || 0) - (_fd.addedDay || 0)>> <<set _fd_sd = 3>>/* 冰箱内腐败速度为普通的1/3 */ <<set _fd_rawSd = $spoilDays ? ($spoilDays[_fd.template] || 2) : 2>> <<set _fd_fridgeSd = _fd_rawSd * 3>> <<set _fd_stage = _fd_fridgeSd > 0 ? Math.floor(_fd_age / _fd_fridgeSd * 3) : 0>> <<set _fd_qcol = _fd.quality === "完美" ? "#f0c060" : (_fd.quality === "失败" ? "var(--bone-dim)" : "var(--teal-bright)")>> <<set _fd_stcol = _fd_stage <= 0 ? "#8bc4a0" : (_fd_stage === 1 ? "var(--amber)" : "var(--danger-bright)")>> <<set _fd_stxt = _fd_stage <= 0 ? "新鲜" : (_fd_stage === 1 ? "变质" : "⚠腐败")>> <span class="inv-item" style="flex-direction:column;align-items:flex-start;height:auto;padding:0.4rem 0.65rem;cursor:pointer;"><<link _fd.name>> <<set $selectFridgeSlot = _fri>> <<goto "冰箱物品">> <</link>> <span style="font-size:0.7rem;color:var(--bone-dim);margin-top:0.18rem;"> <<print _fd.ingNames ? _fd.ingNames.slice(0,2).join("·") + (_fd.ingNames.length > 2 ? "…" : "") : "">> </span> <span style="font-size:0.7rem;margin-top:0.1rem;"> <span style="color:<<print _fd_qcol>>;"><<print _fd.quality>></span> <span style="color:<<print _fd_stcol>>;margin-left:0.4rem;"><<print _fd_stxt>></span> </span> </span> <</if>> <</capture>> <</for>> </div> <div class="action-row" style="margin-top:1rem;"> [[← 返回厨房|厨房]] </div> <</nobr>>
<<nobr>> <<if !$fridge || $selectFridgeSlot === undefined>><<goto "冰箱">><</if>> <<set _fi_slot = $selectFridgeSlot>> <<set _fi_d = $fridge[_fi_slot]>> <<if !_fi_d>><<goto "冰箱">><</if>> <<set _fi_age = ($day || 0) - (_fi_d.addedDay || 0)>> <<set _fi_rawSd = $spoilDays ? ($spoilDays[_fi_d.template] || 2) : 2>> <<set _fi_fridgeSd = _fi_rawSd * 3>> <<set _fi_stage = _fi_fridgeSd > 0 ? Math.floor(_fi_age / _fi_fridgeSd * 3) : 0>> <<set _fi_left = _fi_fridgeSd - _fi_age>> <<set _fi_qcol = _fi_d.quality === "完美" ? "#f0c060" : (_fi_d.quality === "失败" ? "var(--danger-bright)" : "var(--teal-bright)")>> <div class="item-detail"> <div class="item-detail-name"><<print _fi_d.name>></div> <div class="item-detail-meta" style="margin-top:0.3rem;"> <span style="color:<<print _fi_qcol>>;font-size:0.8rem;"><<print _fi_d.quality>></span> <span style="color:var(--bone-dim);font-size:0.72rem;margin-left:0.6rem;"><<print _fi_d.method>></span> <<if _fi_stage <= 0>> <span style="color:#8bc4a0;font-size:0.72rem;margin-left:0.6rem;">新鲜 · 约<<print Math.max(_fi_left,0)>>天后变质</span> <<elseif _fi_stage === 1>> <span style="color:var(--amber);font-size:0.72rem;margin-left:0.6rem;">⚠ 轻微变质 · 约<<print Math.max(_fi_left,0)>>天后腐败</span> <<else>> <span style="color:var(--danger-bright);font-size:0.72rem;margin-left:0.6rem;">⚠ 已腐败</span> <</if>> </div> <<if _fi_d.ingNames && _fi_d.ingNames.length > 0>> <p style="font-size:0.75rem;color:var(--bone-dim);margin:0.4rem 0;"> 食材:<<print _fi_d.ingNames.join("、")>> </p> <</if>> <p style="font-size:0.85rem;line-height:1.75;color:var(--bone-dim);margin:0.6rem 0;border-left:2px solid var(--border);padding-left:0.8rem;"><<print _fi_d.desc>></p> <div style="font-size:0.78rem;color:var(--bone-dim);margin:0.5rem 0;"> 食用效果: <<if _fi_d.hunger > 0>><span style="color:#8bc4a0;">饱腹+<<print _fi_d.hunger>></span> <</if>> <<if _fi_d.water > 0>><span style="color:#6ab4d0;">饮水+<<print _fi_d.water>></span> <</if>> <<if _fi_d.life > 0>><span style="color:var(--teal-bright);">生命+<<print _fi_d.life>></span> <</if>> <<if _fi_d.power > 0>><span style="color:var(--amber-bright);">体力+<<print _fi_d.power>></span> <</if>> <<if _fi_d.san !== 0>><span style="color:<<if _fi_d.san > 0>>var(--amber)<<else>>var(--danger-bright)<</if>>;">安定<<if _fi_d.san > 0>>+<</if>><<print _fi_d.san>></span> <</if>> <<if _fi_d.magic > 0>><span style="color:#a080d0;">魔力+<<print _fi_d.magic>></span><</if>> </div> </div> <div class="action-row" style="margin-top:0.8rem;"> <<link "▶ 食用">> <<eatDish _fi_slot>> <<goto "厨房">> <</link>> <<link "丢弃">> <<set $fridge[_fi_slot] = null>> <<goto "冰箱">> <</link>> [[← 返回冰箱|冰箱]] </div> <</nobr>>
<<set $items = $items || {}>> <<set $items.alch_water_s = { size:1, name:"水·固精质", type:"炼金材料", element:"水", form:"固态", desc:"具有流动性和渗透力,在分解与凝结反应中表现活跃。固态,结构稳定,适合作为仓储材料或黑化反应的输入端。" }>> <<set $items.alch_water_l = { size:1, name:"水·液精质", type:"炼金材料", element:"水", form:"液态", desc:"具有流动性和渗透力,在分解与凝结反应中表现活跃。液态,流动活跃,适合作为黑化产物或白化反应的输入端。" }>> <<set $items.alch_water_g = { size:1, name:"水·气精质", type:"炼金材料", element:"水", form:"气态", desc:"具有流动性和渗透力,在分解与凝结反应中表现活跃。气态,挥发性强,难以储存但反应迅速,适合白化产物或黄化输入。" }>> <<set $items.alch_water_i = { size:1, name:"水·离精质", type:"炼金材料", element:"水", form:"离子态", desc:"具有流动性和渗透力,在分解与凝结反应中表现活跃。离子态,高度不稳定,蕴含大量能量,是赤化炉的专属产物与输入。" }>> <<set $items.alch_fire_s = { size:1, name:"火·固精质", type:"炼金材料", element:"火", form:"固态", desc:"携带高温能量,易于触发蒸馏与升华反应。固态,结构稳定,适合作为仓储材料或黑化反应的输入端。" }>> <<set $items.alch_fire_l = { size:1, name:"火·液精质", type:"炼金材料", element:"火", form:"液态", desc:"携带高温能量,易于触发蒸馏与升华反应。液态,流动活跃,适合作为黑化产物或白化反应的输入端。" }>> <<set $items.alch_fire_g = { size:1, name:"火·气精质", type:"炼金材料", element:"火", form:"气态", desc:"携带高温能量,易于触发蒸馏与升华反应。气态,挥发性强,难以储存但反应迅速,适合白化产物或黄化输入。" }>> <<set $items.alch_fire_i = { size:1, name:"火·离精质", type:"炼金材料", element:"火", form:"离子态", desc:"携带高温能量,易于触发蒸馏与升华反应。离子态,高度不稳定,蕴含大量能量,是赤化炉的专属产物与输入。" }>> <<set $items.alch_earth_s = { size:1, name:"土·固精质", type:"炼金材料", element:"土", form:"固态", desc:"性质稳定厚重,是固化与形态锚定的理想材料。固态,结构稳定,适合作为仓储材料或黑化反应的输入端。" }>> <<set $items.alch_earth_l = { size:1, name:"土·液精质", type:"炼金材料", element:"土", form:"液态", desc:"性质稳定厚重,是固化与形态锚定的理想材料。液态,流动活跃,适合作为黑化产物或白化反应的输入端。" }>> <<set $items.alch_earth_g = { size:1, name:"土·气精质", type:"炼金材料", element:"土", form:"气态", desc:"性质稳定厚重,是固化与形态锚定的理想材料。气态,挥发性强,难以储存但反应迅速,适合白化产物或黄化输入。" }>> <<set $items.alch_earth_i = { size:1, name:"土·离精质", type:"炼金材料", element:"土", form:"离子态", desc:"性质稳定厚重,是固化与形态锚定的理想材料。离子态,高度不稳定,蕴含大量能量,是赤化炉的专属产物与输入。" }>> <<set $items.alch_wind_s = { size:1, name:"风·固精质", type:"炼金材料", element:"风", form:"固态", desc:"轻盈而具有扩散性,在气态反应与元素共鸣中表现突出。固态,结构稳定,适合作为仓储材料或黑化反应的输入端。" }>> <<set $items.alch_wind_l = { size:1, name:"风·液精质", type:"炼金材料", element:"风", form:"液态", desc:"轻盈而具有扩散性,在气态反应与元素共鸣中表现突出。液态,流动活跃,适合作为黑化产物或白化反应的输入端。" }>> <<set $items.alch_wind_g = { size:1, name:"风·气精质", type:"炼金材料", element:"风", form:"气态", desc:"轻盈而具有扩散性,在气态反应与元素共鸣中表现突出。气态,挥发性强,难以储存但反应迅速,适合白化产物或黄化输入。" }>> <<set $items.alch_wind_i = { size:1, name:"风·离精质", type:"炼金材料", element:"风", form:"离子态", desc:"轻盈而具有扩散性,在气态反应与元素共鸣中表现突出。离子态,高度不稳定,蕴含大量能量,是赤化炉的专属产物与输入。" }>> <<set $items.ether_blessed = { size:1, name:"祝福以太碎片", type:"以太副产物", desc:"白化分离时析出的洁净以太,带着隐约的温暖光晕,是稀有的炼金附产物。" }>> <<set $items.ether_corrupt = { size:1, name:"污染以太碎片", type:"以太副产物", desc:"白化分离时析出的浑浊以太,散发着不安定的气息,用途特殊但需谨慎处理。" }>> <<set $items.alch_residue = { size:1, name:"炼金杂质", type:"炼金材料", desc:"精炼或四化过程中分离出的杂质,成分复杂,可重新投入精炼台二次处理。" }>> <<set $items.alch_mixed = { size:1, name:"混杂精质", type:"炼金材料", desc:"两种不相容元素在错误条件下反应的产物,需重新精炼才能分离出有效成分。" }>> <<set $items.tincture_love = { size:1, name:"慈爱纯粹酊剂", type:"纯粹酊剂", form:"液态", desc:"水与风的共鸣产物,呈半透明的流动液体,渗透力极强,是慈爱理型力量的凝聚。" }>> <<set $items.tincture_beacon = { size:1, name:"信标纯粹酊剂", type:"纯粹酊剂", form:"气态", desc:"火与土的共鸣产物,以薄雾形态封存于特制容器,是信标理型力量的凝聚。" }>> <<set $items.tincture_silence = { size:1, name:"死寂纯粹酊剂", type:"纯粹酊剂", form:"固态", desc:"水与土的共鸣产物,沉重的深色固体,边界分明、永恒静止,是死寂理型力量的凝聚。" }>> <<set $items.tincture_change = { size:1, name:"变革纯粹酊剂", type:"纯粹酊剂", form:"离子态", desc:"风与火的共鸣产物,以不稳定的离子态存在,蕴含剧烈的变革力量,极难储存。" }>> <<set $items.philosophers_stone = { size:1, name:"贤者之石", type:"纯粹酊剂", desc:"四种纯粹酊剂融合的终极产物,外观如黑红相间的石块,内部流动着看不见的光。传说中可以改变一切物质的本质。" }>>
/* 精炼规则:原始材料 → 炼金材料 element: 水/火/土/风 form: 固/液/气/离子 ether: 以太析出概率 (0-1) etherType: "blessed"/"corrupt" */ <<set $refineRules = { fish_bone: { element:"水", form:"固", ether:0 }, fish_blood: { element:"水", form:"液", ether:0.2, etherType:"blessed" }, fish_scale: { element:"水", form:"固", ether:0 }, fish_roe: { element:"水", form:"液", ether:0.1, etherType:"blessed" }, fish_liver: { element:"水", form:"液", ether:0 }, gill_membrane: { element:"风", form:"固", ether:0 }, fin_membrane: { element:"风", form:"固", ether:0 }, air_sac: { element:"风", form:"固", ether:0 }, swim_bladder: { element:"风", form:"固", ether:0 }, jellyfluid: { element:"水", form:"液", ether:0 }, jellyfilm: { element:"水", form:"固", ether:0 }, jellyfish: { element:"水", form:"液", ether:0 }, kelp_fiber: { element:"土", form:"固", ether:0 }, seagrass_str: { element:"土", form:"固", ether:0 }, coral_frag: { element:"土", form:"固", ether:0.1, etherType:"blessed" }, shell_frag: { element:"土", form:"固", ether:0 }, shell_powder: { element:"土", form:"固", ether:0 }, crab_shell: { element:"土", form:"固", ether:0 }, urchin_spine_core:{ element:"土", form:"固", ether:0.3, etherType:"blessed" }, pearl_dust: { element:"土", form:"固", ether:0 }, pearl: { element:"土", form:"固", ether:0.15, etherType:"blessed" }, blackpearl: { element:"风", form:"固", ether:0.3, etherType:"corrupt" }, bone_ash: { element:"土", form:"固", ether:0 }, sand_extract: { element:"土", form:"液", ether:0 }, seawater_ext: { element:"水", form:"液", ether:0 }, seajelly: { element:"水", form:"液", ether:0 }, ember_crystal: { element:"火", form:"固", ether:0.8, etherType:"blessed" }, char_scale: { element:"火", form:"固", ether:0 }, coal: { element:"火", form:"固", ether:0 }, bile: { element:"火", form:"液", ether:0 }, current_stone: { element:"风", form:"固", ether:0.6, etherType:"blessed" }, god_ember: { element:"火", form:"液", ether:1.0, etherType:"blessed" }, deep_eye: { element:"水", form:"固", ether:0.4, etherType:"blessed" }, glass: { element:"土", form:"固", ether:0 }, wood: { element:"土", form:"固", ether:0 }, rope: { element:"土", form:"固", ether:0 }, metal: { element:"土", form:"固", ether:0 }, iron: { element:"土", form:"固", ether:0 }, rubber_seal: { element:"土", form:"固", ether:0 }, /* ══ 特殊粗制材料精炼规则 ══ */ jellyfish_tissue: { element:"火", form:"固", ether:0.15, etherType:"blessed" }, candle_jelly_core: { element:"风", form:"固", ether:0.2, etherType:"blessed" }, whale_relic_bone: { element:"水", form:"固", ether:0.1, etherType:"blessed" }, parasite: { element:"土", form:"固", ether:0.1, etherType:"corrupt" }, mermaid_bone: { element:"风", form:"固", ether:0.2, etherType:"blessed" }, mermaid_blood: { element:"风", form:"液", ether:0.3, etherType:"blessed" }, vitality: { element:"水", form:"离子", ether:0.4, etherType:"blessed" }, phosphor_flame: { element:"风", form:"离子", ether:0.3, etherType:"blessed" }, ambergris: { element:"土", form:"固", ether:0.2, etherType:"blessed" }, storm_flesh: { element:"火", form:"固", ether:0.15, etherType:"corrupt" }, glow_moss_juice: { element:"水", form:"液", ether:0.1, etherType:"blessed" }, salt_lake_crystal: { element:"土", form:"离子", ether:0.2, etherType:"blessed" }, soul_sea_slime: { element:"水", form:"离子", ether:0.3, etherType:"corrupt" }, soul_sea_bone: { element:"土", form:"固", ether:0.2, etherType:"corrupt" }, thaumas_blood: { element:"土", form:"液", ether:0.6, etherType:"corrupt" }, vent_glow_fluid: { element:"火", form:"液", ether:0.25, etherType:"blessed" }, tubeworm_fluid: { element:"火", form:"液", ether:0.1, etherType:"blessed" }, glow_coral: { element:"水", form:"固", ether:0.15, etherType:"blessed" }, giant_ray_sac: { element:"风", form:"气", ether:0.2, etherType:"blessed" }, inscription_frag: { element:"水", form:"气", ether:0.3, etherType:"blessed" }, surface_light: { element:"风", form:"气", ether:0.35, etherType:"blessed" }, god_bone_raw: { element:"火", form:"气", ether:0.8, etherType:"corrupt" }, ceto_breath: { element:"土", form:"气", ether:0.7, etherType:"corrupt" }, jade_feather: { element:"火", form:"离子", ether:0.4, etherType:"blessed" } }>> /* 仪器定义 instrument → { stage, single:{input,output}, tincture:{pair,result}, desc[], dur } */ <<set $alchemyInstrumentDefs = { "精炼台": { stage: "精炼", single: null, tincture: null, dur: 8, desc: [ { ratio:0, text:"将原始材料放入精炼台,开始提取其中的元素精质。" }, { ratio:0.3, text:"台面微微震动,材料的杂质开始向外析出。" }, { ratio:0.6, text:"元素精质逐渐从混合物中分离,散发出淡淡的光晕。" }, { ratio:0.85, text:"提炼接近完成,纯净的精质即将析出。" }, { ratio:1.0, text:"精炼完成。" } ] }, "溶解皿": { stage: "黑化", single: { input:"固", output:"液" }, tincture: { pair:["水","风"], result:"tincture_love" }, dur: 12, desc: [ { ratio:0, text:"将材料投入溶解皿,溶剂开始缓慢渗透固体的结构。" }, { ratio:0.25, text:"固体外层开始软化,微小的气泡从底部涌起。" }, { ratio:0.5, text:"溶解加速,材料的形态正在发生根本性的变化。" }, { ratio:0.75, text:"固体结构基本瓦解,液态精质在皿中汇聚。" }, { ratio:1.0, text:"黑化完成,固态已转化为液态。" } ] }, "蒸馏器": { stage: "白化", single: { input:"液", output:"气" }, tincture: { pair:["火","土"], result:"tincture_beacon" }, dur: 15, desc: [ { ratio:0, text:"蒸馏器开始加热,液态材料在底部缓缓升温。" }, { ratio:0.25, text:"第一缕蒸汽升起,杂质开始在冷凝管壁上沉积。" }, { ratio:0.5, text:"蒸馏稳定,纯净的气态精质向上汇聚,以太成分在此阶段分离。" }, { ratio:0.75, text:"大部分液体已转化,气态收集室中充满了精纯的蒸汽。" }, { ratio:1.0, text:"白化完成,液态已蒸馏为气态。" } ] }, "凝结炉": { stage: "黄化", single: { input:"气", output:"固" }, tincture: { pair:["水","土"], result:"tincture_silence" }, dur: 18, desc: [ { ratio:0, text:"凝结炉降温启动,气态材料在低温环境中开始失去活性。" }, { ratio:0.25, text:"气体边缘出现细小的凝结点,逐渐向中心蔓延。" }, { ratio:0.5, text:"相变正在发生,气态结构在压力与低温下开始固化。" }, { ratio:0.75, text:"固化接近完成,新形成的固态精质在炉底慢慢成形。" }, { ratio:1.0, text:"黄化完成,气态已凝结为固态。" } ] }, "赤化炉": { stage: "赤化", single: { input:null, output:"离子" }, tincture: { pair:["风","火"], result:"tincture_change" }, dur: 20, desc: [ { ratio:0, text:"赤化炉内的共鸣核心开始激活,炉腔温度急速上升。" }, { ratio:0.2, text:"材料的分子结构在极端条件下开始解离,散发出刺眼的光。" }, { ratio:0.5, text:"离子化反应剧烈进行,物质以前所未有的状态存在着。" }, { ratio:0.75, text:"反应接近顶峰,高度不稳定的离子态精质在磁场约束下汇聚。" }, { ratio:1.0, text:"赤化完成,材料已跃迁为离子态。" } ] } }>> /* 形态→仪器名对应(用于提示玩家) */ <<set $formToInstrument = { "固":"溶解皿", "液":"蒸馏器", "气":"凝结炉" }>> /* 元素对→酊剂对应 */ <<set $tincturePairs = { "水_风": "tincture_love", "风_水": "tincture_love", "火_土": "tincture_beacon", "土_火": "tincture_beacon", "水_土": "tincture_silence","土_水": "tincture_silence", "风_火": "tincture_change", "火_风": "tincture_change" }>> /* 酊剂需要在哪个仪器里制备 */ <<set $tincturePairInstrument = { "水_风": "溶解皿", "风_水": "溶解皿", "火_土": "蒸馏器", "土_火": "蒸馏器", "水_土": "凝结炉", "土_水": "凝结炉", "风_火": "赤化炉", "火_风": "赤化炉" }>>
<<nobr>> <<set _rf_cats = Object.keys($store)>> <<set _rf_mats = []>> <<for _rfc = 0; _rfc < _rf_cats.length; _rfc++>> <<set _rfl = $store[_rf_cats[_rfc]]>> <<if Array.isArray(_rfl)>> <<for _rfi = 0; _rfi < _rfl.length; _rfi++>> <<if _rfl[_rfi].quantity > 0>> <<set _rfd = State.variables.items[_rfl[_rfi].id]>> <<if $refineRules && $refineRules[_rfl[_rfi].id]>> <<run _rf_mats.push({ id:_rfl[_rfi].id, qty:_rfl[_rfi].quantity, name:_rfd ? _rfd.name : _rfl[_rfi].id })>> <</if>> <</if>> <</for>> <</if>> <</for>> <div style="font-size:0.82rem;color:var(--bone-dim);margin-bottom:0.6rem;"> 精炼台 <span style="font-size:0.75rem;opacity:0.7;">将原始材料提炼为炼金精质,同步分离以太属性</span> </div> <<if _rf_mats.length === 0>> <p style="color:var(--bone-dim);font-style:italic;font-size:0.85rem;">背包中没有可精炼的原始材料。</p> <<else>> <div class="inv-grid" style="grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:0.35rem;"> <<for _rfi2 = 0; _rfi2 < _rf_mats.length; _rfi2++>> <<capture _rfi2>> <<set _rfm = _rf_mats[_rfi2]>> <<set _rfrule = $refineRules[_rfm.id]>> <<set _rfout = "alch_" + (_rfrule.element === "水" ? "water" : _rfrule.element === "火" ? "fire" : _rfrule.element === "土" ? "earth" : "wind") + "_" + (_rfrule.form === "固" ? "s" : _rfrule.form === "液" ? "l" : _rfrule.form === "气" ? "g" : "i")>> <<set _rfoutn = State.variables.items[_rfout] ? State.variables.items[_rfout].name : _rfout>> <span class="inv-item" style="flex-direction:column;align-items:flex-start;height:auto;padding:0.4rem 0.65rem;"> <span style="color:var(--amber-bright);font-size:0.85rem;"><<print _rfm.name>></span> <span style="font-size:0.7rem;color:var(--bone-dim);margin-top:0.1rem;">×<<print _rfm.qty>> → <<print _rfoutn>></span> <<if _rfrule.ether > 0>> <span style="font-size:0.68rem;color:#a080d0;">可能析出<<print _rfrule.etherType === "blessed" ? "祝福" : "污染">>以太</span> <</if>> <<link "精炼">> <<set $alchemyInstrument = "精炼台">> <<set $alchemyMaterials = [_rfm.id]>> <<set $alchemyTimer = 0>> <<goto "炼金进行">> <</link>> </span> <</capture>> <</for>> </div> <</if>> <div class="action-row" style="margin-top:1rem;">[[← 返回炼金室|炼金室]]</div> <</nobr>>
<<nobr>> <<if !$alchemyMaterials>><<set $alchemyMaterials = []>><</if>> <<set _as_idef = $alchemyInstrumentDefs[$alchemyInstrument]>> /* 扫描背包炼金材料 */ <<set _as_mats = []>> <<set _as_cats = Object.keys($store)>> <<for _asc = 0; _asc < _as_cats.length; _asc++>> <<set _asl = $store[_as_cats[_asc]]>> <<if Array.isArray(_asl)>> <<for _asi = 0; _asi < _asl.length; _asi++>> <<if _asl[_asi].quantity > 0>> <<set _asd = State.variables.items[_asl[_asi].id]>> <<if _asd && _asd.type === "炼金材料" && _asd.element>> <<run _as_mats.push({ id:_asl[_asi].id, qty:_asl[_asi].quantity, name:_asd.name, element:_asd.element, form:_asd.form })>> <</if>> <</if>> <</for>> <</if>> <</for>> /* 预测结果 */ <<set _as_predicted = "">> <<if $alchemyMaterials.length === 1>> <<set _as_m1def = State.variables.items[$alchemyMaterials[0]]>> <<if _as_idef && _as_idef.single>> <<if _as_m1def && _as_m1def.form === _as_idef.single.input + "态">> <<set _as_outid = "alch_" + (_as_m1def.element === "水" ? "water" : _as_m1def.element === "火" ? "fire" : _as_m1def.element === "土" ? "earth" : "wind") + "_" + (_as_idef.single.output === "固" ? "s" : _as_idef.single.output === "液" ? "l" : _as_idef.single.output === "气" ? "g" : "i")>> <<set _as_outn = State.variables.items[_as_outid] ? State.variables.items[_as_outid].name : _as_outid>> <<set _as_predicted = "→ " + _as_outn>> <<else>> <<set _as_predicted = "⚠ 形态不匹配,将产生混杂精质">> <</if>> <<elseif $alchemyInstrument === "赤化炉">> <<if _as_m1def>> <<set _as_outid2 = "alch_" + (_as_m1def.element === "水" ? "water" : _as_m1def.element === "火" ? "fire" : _as_m1def.element === "土" ? "earth" : "wind") + "_i">> <<set _as_outn2 = State.variables.items[_as_outid2] ? State.variables.items[_as_outid2].name : _as_outid2>> <<set _as_predicted = "→ " + _as_outn2>> <</if>> <</if>> <<elseif $alchemyMaterials.length === 2>> <<set _as_m1d = State.variables.items[$alchemyMaterials[0]]>> <<set _as_m2d = State.variables.items[$alchemyMaterials[1]]>> <<if _as_m1d && _as_m2d>> <<set _as_pairKey = _as_m1d.element + "_" + _as_m2d.element>> <<set _as_tinRes = $tincturePairs ? $tincturePairs[_as_pairKey] : null>> <<set _as_tinInst = $tincturePairInstrument ? $tincturePairInstrument[_as_pairKey] : null>> <<if _as_tinRes && _as_tinInst === $alchemyInstrument>> <<set _as_tinName = State.variables.items[_as_tinRes] ? State.variables.items[_as_tinRes].name : _as_tinRes>> <<set _as_predicted = "→ ✦ " + _as_tinName>> <<elseif _as_m1d.element === _as_m2d.element>> <<set _as_predicted = "→ 同元素强化(产出高纯度精质)">> <<else>> <<set _as_predicted = "→ ⚠ 元素不相容,将产生混杂精质">> <</if>> <</if>> <</if>> <div style="font-size:0.82rem;color:var(--bone-dim);margin-bottom:0.4rem;"> <span style="color:var(--amber-bright);"><<print $alchemyInstrument>></span> <span style="margin-left:0.5rem;opacity:0.7;"><<print _as_idef ? _as_idef.stage : "">>阶段</span> </div> <div style="min-height:2rem;margin:0.4rem 0 0.7rem;font-size:0.82rem;"> 已选(<<print $alchemyMaterials.length>>/2): <<if $alchemyMaterials.length > 0>> <<for _assi = 0; _assi < $alchemyMaterials.length; _assi++>> <<capture _assi>> <<set _assdef = State.variables.items[$alchemyMaterials[_assi]]>> <span style="display:inline-block;background:var(--bg-panel);border:1px solid var(--amber-dim);padding:0.1rem 0.4rem;margin:0.1rem;font-size:0.8rem;color:var(--amber-bright);"> <<print _assdef ? _assdef.name : $alchemyMaterials[_assi]>> <<link "✕">><<run State.variables.alchemyMaterials.splice(_assi,1)>><<goto "炼金选材">><</link>> </span> <</capture>> <</for>> <<else>> <span style="color:var(--bone-dim);font-style:italic;">尚未选择</span> <</if>> <<if _as_predicted>> <span style="margin-left:0.5rem;color:var(--teal-bright);font-size:0.8rem;"><<print _as_predicted>></span> <</if>> </div> <div class="inv-grid" style="grid-template-columns:repeat(auto-fill,minmax(145px,1fr));gap:0.35rem;"> <<if _as_mats.length === 0>> <p style="color:var(--bone-dim);font-style:italic;font-size:0.85rem;grid-column:1/-1;">背包中没有炼金材料。</p> <<else>> <<for _asgi = 0; _asgi < _as_mats.length; _asgi++>> <<set _asgm = _as_mats[_asgi]>> <<set _asgSel = $alchemyMaterials.includes(_asgm.id)>> <<set _asgFull = $alchemyMaterials.length >= 2>> <<capture _asgi, _asgm, _asgSel, _asgFull>> <span class="inv-item" style="flex-direction:column;align-items:flex-start;height:auto;padding:0.35rem 0.6rem;<<if _asgSel>>border-color:var(--amber-bright);<</if>>"> <<if !_asgSel && !_asgFull>> <<link _asgm.name>><<run State.variables.alchemyMaterials.push(_asgm.id)>><<goto "炼金选材">><</link>> <<else>> <span style="color:<<print _asgSel ? 'var(--amber-bright)' : 'var(--bone-dim)'>>;"><<print _asgm.name>></span> <</if>> <span style="font-size:0.7rem;color:var(--bone-dim);margin-top:0.1rem;"><<print _asgm.element>>·<<print _asgm.form>> ×<<print _asgm.qty>></span> </span> <</capture>> <</for>> <</if>> </div> <div class="action-row" style="margin-top:0.8rem;"> <<if $alchemyMaterials.length > 0>> <<link "▶ 开始<<print _as_idef ? _as_idef.stage : '操作'>>">> <<set $alchemyTimer = 0>> <<goto "炼金进行">> <</link>> <</if>> <<link "← 返回">><<set $alchemyMaterials = []>><<goto "炼金室">><</link>> </div> <</nobr>>
<<nobr>><div style="font-size:1rem;color:var(--amber-bright);margin-bottom:0.3rem;"><<set _ah_idef = $alchemyInstrumentDefs ? $alchemyInstrumentDefs[$alchemyInstrument] : null>><<print $alchemyInstrument>> — <<print _ah_idef ? _ah_idef.stage : "">></div><div style="font-size:0.78rem;color:var(--bone-dim);margin-bottom:0.8rem;"><<if !$alchemyTimer>><<set $alchemyTimer = 0>><</if>><<for _apmi = 0; _apmi < $alchemyMaterials.length; _apmi++>><<set _apmd = State.variables.items[$alchemyMaterials[_apmi]]>><<if _apmd>><<print _apmd.name>><<if _apmi < $alchemyMaterials.length-1>>、<</if>><</if>><</for>></div><div id="alch-view" style="min-height:100px;">准备开始……</div><<repeat 1s>><<set _ap_idef2 = $alchemyInstrumentDefs ? $alchemyInstrumentDefs[$alchemyInstrument] : null>><<set _ap_dur = _ap_idef2 ? _ap_idef2.dur : 10>><<set $alchemyTimer += 1>><<set $timepass += 1>><<time>><<set _ap_ratio = $alchemyTimer / _ap_dur>><<set _ap_descs = _ap_idef2 ? _ap_idef2.desc : []>><<set _ap_text = _ap_descs.length > 0 ? _ap_descs[0].text : "处理中……">><<for _apdi = _ap_descs.length - 1; _apdi >= 0; _apdi-->><<if _ap_ratio >= _ap_descs[_apdi].ratio>><<set _ap_text = _ap_descs[_apdi].text>><<break>><</if>><</for>><<set _ap_pct = Math.min(Math.floor(_ap_ratio * 100), 100)>><<replace "#alch-view">><p style="font-size:0.88rem;color:var(--bone-dim);font-style:italic;min-height:2.5em;line-height:1.7;"><<print _ap_text>></p><div style="font-size:0.75rem;color:var(--bone-dim);margin:0.3rem 0;"><<print $alchemyTimer>>s / <<print _ap_dur>>s</div><div style="background:var(--bg-panel);border:1px solid var(--border-dim);height:10px;border-radius:5px;overflow:hidden;margin-bottom:0.6rem;"><div style="height:100%;width:<<print _ap_pct>>%;background:var(--amber);transition:width 0.85s linear;"></div></div><<if _ap_pct >= 100>><div><<link "▶ 完成炼金">><<goto "炼金结果">><</link>></div><</if>><</replace>><<if $alchemyTimer >= _ap_dur>><<stop>><</if>><</repeat>><</nobr>>
<<nobr>> <<set _ar_idef = $alchemyInstrumentDefs ? $alchemyInstrumentDefs[$alchemyInstrument] : null>> <<set _ar_outputs = []>> <<set _ar_msgs = []>> <<if $alchemyInstrument === "精炼台" && $alchemyMaterials.length === 1>> <<set _ar_matId = $alchemyMaterials[0]>> <<set _ar_rule = $refineRules ? $refineRules[_ar_matId] : null>> <<if _ar_rule>> <<set _ar_ek = _ar_rule.element === "水" ? "water" : _ar_rule.element === "火" ? "fire" : _ar_rule.element === "土" ? "earth" : "wind">> <<set _ar_fk = _ar_rule.form === "固" ? "s" : _ar_rule.form === "液" ? "l" : _ar_rule.form === "气" ? "g" : "i">> <<set _ar_outId = "alch_" + _ar_ek + "_" + _ar_fk>> <<run _ar_outputs.push({ id:_ar_outId, qty:1 })>> <<run _ar_msgs.push("精炼完成,获得" + (State.variables.items[_ar_outId] ? State.variables.items[_ar_outId].name : _ar_outId) + "。")>> <<if _ar_rule.ether > 0 && Math.random() < _ar_rule.ether>> <<set _ar_ethId = _ar_rule.etherType === "blessed" ? "ether_blessed" : "ether_corrupt">> <<run _ar_outputs.push({ id:_ar_ethId, qty:1 })>> <<run _ar_msgs.push("同时析出了" + (State.variables.items[_ar_ethId] ? State.variables.items[_ar_ethId].name : _ar_ethId) + "。")>> <</if>> <<removeitem _ar_matId 1>> <<else>> <<run _ar_msgs.push("没有找到对应的精炼规则,材料未被消耗。")>> <</if>> <<elseif $alchemyMaterials.length === 1>> <<set _ar_m1id = $alchemyMaterials[0]>> <<set _ar_m1def = State.variables.items[_ar_m1id]>> <<if _ar_m1def>> <<set _ar_ek2 = _ar_m1def.element === "水" ? "water" : _ar_m1def.element === "火" ? "fire" : _ar_m1def.element === "土" ? "earth" : "wind">> <<if $alchemyInstrument === "赤化炉">> <<set _ar_outId2 = "alch_" + _ar_ek2 + "_i">> <<run _ar_outputs.push({ id:_ar_outId2, qty:1 })>> <<run _ar_msgs.push("赤化完成,获得" + (State.variables.items[_ar_outId2] ? State.variables.items[_ar_outId2].name : _ar_outId2) + "。")>> <<elseif _ar_idef && _ar_idef.single>> <<set _ar_expectForm = _ar_idef.single.input + "态">> <<if _ar_m1def.form === _ar_expectForm>> <<set _ar_outFk2 = _ar_idef.single.output === "固" ? "s" : _ar_idef.single.output === "液" ? "l" : _ar_idef.single.output === "气" ? "g" : "i">> <<set _ar_outId3 = "alch_" + _ar_ek2 + "_" + _ar_outFk2>> <<run _ar_outputs.push({ id:_ar_outId3, qty:1 })>> <<run _ar_msgs.push((_ar_idef ? _ar_idef.stage : "操作") + "完成,获得" + (State.variables.items[_ar_outId3] ? State.variables.items[_ar_outId3].name : _ar_outId3) + "。")>> <<if Math.random() < 0.3>> <<run _ar_outputs.push({ id:"alch_residue", qty:1 })>> <<run _ar_msgs.push("同时产生了少量炼金杂质。")>> <</if>> <<else>> <<run _ar_outputs.push({ id:"alch_mixed", qty:1 })>> <<run _ar_msgs.push("形态不匹配,产生了混杂精质。")>> <</if>> <</if>> <<removeitem _ar_m1id 1>> <</if>> <<elseif $alchemyMaterials.length === 2>> <<set _ar_d1 = State.variables.items[$alchemyMaterials[0]]>> <<set _ar_d2 = State.variables.items[$alchemyMaterials[1]]>> <<if _ar_d1 && _ar_d2>> <<set _ar_pairKey = _ar_d1.element + "_" + _ar_d2.element>> <<set _ar_tinRes = $tincturePairs ? $tincturePairs[_ar_pairKey] : null>> <<set _ar_tinInst = $tincturePairInstrument ? $tincturePairInstrument[_ar_pairKey] : null>> <<if _ar_tinRes && _ar_tinInst === $alchemyInstrument>> <<set _ar_tinName = State.variables.items[_ar_tinRes] ? State.variables.items[_ar_tinRes].name : _ar_tinRes>> <<run _ar_outputs.push({ id:_ar_tinRes, qty:1 })>> <<run _ar_msgs.push("✦ 元素共鸣成功!获得" + _ar_tinName + "。")>> <<elseif _ar_d1.element === _ar_d2.element>> <<set _ar_ek3 = _ar_d1.element === "水" ? "water" : _ar_d1.element === "火" ? "fire" : _ar_d1.element === "土" ? "earth" : "wind">> <<set _ar_fk3 = _ar_d1.form === "固态" ? "s" : _ar_d1.form === "液态" ? "l" : _ar_d1.form === "气态" ? "g" : "i">> <<set _ar_sameOut = "alch_" + _ar_ek3 + "_" + _ar_fk3>> <<run _ar_outputs.push({ id:_ar_sameOut, qty:2 })>> <<run _ar_msgs.push("同元素强化,获得" + (State.variables.items[_ar_sameOut] ? State.variables.items[_ar_sameOut].name : _ar_sameOut) + "×2。")>> <<else>> <<run _ar_outputs.push({ id:"alch_mixed", qty:1 })>> <<run _ar_msgs.push("元素不相容,产生了混杂精质。请在正确的仪器中尝试元素共鸣。")>> <</if>> <<removeitem $alchemyMaterials[0] 1>> <<removeitem $alchemyMaterials[1] 1>> <</if>> <</if>> /* 写入背包/仓库 */ <<for _aro = 0; _aro < _ar_outputs.length; _aro++>> <<set _arDef = State.variables.items[_ar_outputs[_aro].id]>> <<if _arDef>><<additem _ar_outputs[_aro].id _ar_outputs[_aro].qty>><</if>> <</for>> /* 拼接消息 HTML(在 nobr 内完成,不混入任何裸 HTML) */ <<set _ar_msgHtml = "">> <<for _arm = 0; _arm < _ar_msgs.length; _arm++>> <<set _ar_isGold = _ar_msgs[_arm].slice(0,1) === "✦">> <<set _ar_msgHtml += "<p style='margin:0.25rem 0;" + (_ar_isGold ? "color:#f0c060;" : "") + "'>" + _ar_msgs[_arm] + "</p>">> <</for>> /* 拼接产出列表 HTML */ <<set _ar_outHtml = "">> <<for _aro2 = 0; _aro2 < _ar_outputs.length; _aro2++>> <<set _ar_od = State.variables.items[_ar_outputs[_aro2].id]>> <<set _ar_nm = _ar_od ? _ar_od.name : _ar_outputs[_aro2].id>> <<set _ar_qt = _ar_outputs[_aro2].qty>> <<set _ar_dest = (_ar_od && (_ar_od.type === "纯粹酊剂" || _ar_od.type === "以太副产物")) ? "已存入仓库" : "已存入背包">> <<set _ar_outHtml += "<div style='padding:0.1rem 0;color:var(--amber-bright);'>" + _ar_nm + " ×" + _ar_qt + "<span style='color:var(--bone-dim);font-size:0.75rem;'> → " + _ar_dest + "</span></div>">> <</for>> <<set _ar_stageLabel = _ar_idef ? _ar_idef.stage : "炼金">> <<set $alchemyMaterials = []>> <</nobr>><div style="color:var(--teal-bright);font-size:1rem;margin-bottom:0.5rem;"><<print _ar_stageLabel>>完成</div><div style="font-size:0.87rem;"><<print _ar_msgHtml>></div><<if _ar_outHtml>><div style="margin-top:0.5rem;font-size:0.78rem;border-top:1px solid var(--border-dim);padding-top:0.4rem;"><<print _ar_outHtml>></div><</if>><div style="margin-top:0.9rem;">[[继续炼金|炼金室]]</div>
<<nobr>> <<set _tg_all = [ { cat:"渔获·鱼类", ids:["salmon","seabass","tuna","sardine","herring","grouper","mahi","cod","eel","flounder","mackerel","bream","anchovy","barracuda","hairtail","sunfish","anglerfish"] }, { cat:"渔获·贝类", ids:["scallop","clam","oyster","mussel","conch","seaurchin"] }, { cat:"渔获·虾蟹头足", ids:["prawn","lobster","mantisshrimp","sweetshrimp","cherryshrimp","kingcrab","snowcrab","bluecrab","swimmingcrab","flowercrab","redcrab","squid","cuttlefish","octopus"] }, { cat:"渔获·藻类", ids:["kelp","wakame","nori","agarcoral"] }, { cat:"食材·鱼肉", ids:["fish_meat","fish_roe","salmon_meat","seabass_meat","tuna_meat","sardine_meat","herring_meat","grouper_meat","mahi_meat","cod_meat","eel_meat","flounder_meat","mackerel_meat","bream_meat","anchovy_meat","barracuda_meat","hairtail_meat","sunfish_meat","anglerfish_meat"] }, { cat:"食材·贝虾蟹头足", ids:["urchin_roe","scallop_meat","clam_meat","oyster_meat","mussel_meat","conch_meat","prawn_meat","lobster_meat","mantisshrimp_meat","sweetshrimp_meat","cherryshrimp_meat","kingcrab_meat","snowcrab_meat","bluecrab_meat","flowercrab_meat","redcrab_meat","octopus_meat","squid_meat","cuttlefish_meat"] }, { cat:"食材·兽肉", ids:["pork","lamb","beef","turtle_meat","manatee_meat","whale_meat","seal_meat","chicken_meat","pigeon_meat","rabbit_meat"] }, { cat:"食材·海草块茎谷蔬", ids:["kelp","wakame","nori","agarcoral","potato_tuber","kelp_tuber","potato","sweet_potato","carrot","taro","wheat_grain","rice","corn","oats","tomato","cabbage","pea","mushroom","eggplant","spinach"] }, { cat:"基础材料", ids:["metal","wood","gears","glass","ruber","clothes","coal","fish_oil","algae_block","mineral_fuel","fish_bone","fish_organ","fish_scale"] }, { cat:"炼金·粗制", ids:["jellyfish_tissue","candle_jelly_core","whale_relic_bone","parasite","mermaid_bone","mermaid_blood","vitality","phosphor_flame","ambergris","storm_flesh","glow_moss_juice","salt_lake_crystal","soul_sea_slime","soul_sea_bone","thaumas_blood","vent_glow_fluid","tubeworm_fluid","glow_coral","giant_ray_sac","inscription_frag","surface_light","god_bone_raw","ceto_breath","jade_feather"] }, { cat:"炼金·精炼", ids:["ref_water_solid","ref_water_liquid","ref_water_gas","ref_water_ion","ref_fire_solid","ref_fire_liquid","ref_fire_gas","ref_fire_ion","ref_earth_solid","ref_earth_liquid","ref_earth_gas","ref_earth_ion","ref_wind_solid","ref_wind_liquid","ref_wind_gas","ref_wind_ion"] }, { cat:"四化剂与酊剂", ids:["agent_white","agent_black","agent_yellow","agent_red","tinct_love","tinct_beacon","tinct_silence","tinct_change","philosophers_stone"] } ]>> <div style="font-size:0.9rem;color:var(--amber-bright);margin-bottom:0.4rem;">测试面板</div> <div style="font-size:0.75rem;color:var(--bone-dim);margin-bottom:0.8rem;">点击物品名称 → 加入背包×5</div> <<for _tgi = 0; _tgi < _tg_all.length; _tgi++>> <<set _tgg = _tg_all[_tgi]>> <div style="font-size:0.78rem;color:var(--amber-dim);margin:0.5rem 0 0.2rem;border-bottom:1px solid var(--border-dim);"><<print _tgg.cat>></div> <div style="display:flex;flex-wrap:wrap;gap:0.15rem 0.35rem;"> <<for _tii = 0; _tii < _tgg.ids.length; _tii++>> <<set _tid = _tgg.ids[_tii]>> <<set _tdef = State.variables.items[_tid]>> <<if _tdef>> <<capture _tid>> <span><<link _tdef.name>><<additem _tid 5>><<goto "测试">><</link>></span> <</capture>> <</if>> <</for>> </div> <</for>> <div style="margin-top:0.8rem;">[[← 返回走廊|走廊]]</div> <</nobr>>
<<nobr>> <<widget "exploreDefs">> /* ═══ ExploreDefs: 基础氛围碎片 + 环境采集定义 ═══ 基础氛围碎片:不含具体生物名,纯环境感知描述 搜索时抽取 1-2 条,与微型事件碎片合计 ≤ 3 条 */ <<set $exploreFragments = { sand: [ "一片起伏的沙丘在灯光下显出柔和的波浪纹,远处的沙面消失在黑暗中。", "细沙在潜艇引起的微弱水流中腾起,短暂悬浮后又缓缓落回海床。", "沙床某处有一团轻微扰动留下的浑浊,某个东西刚刚离开这里。", "一根石化的木桩斜插在沙地里,上面附生着几簇苔藓,来历不明。", "沙面因地形微微凹陷,低洼处积着一层更细腻的淤泥,颜色比周围深。" ], flat: [ "平整的岩床向深处延伸,轮廓在灯光边缘处变得模糊。", "岩面覆着一层致密的附生物,偶有气泡从其中悄然冒出。", "岩床上有一道被磨光的长痕,某种大型物体曾经拖曳过此处。", "几条岩缝向深处延伸,宽窄不一,深处在灯光里看不到尽头。", "突起的岩脊在水流中形成了背涡区,有机碎屑在此聚集沉降。" ], grass: [ "海草随水流起伏,茎叶的摆动有某种规律,像是在对水流之外的东西做出反应。", "草根处的泥沙比周围更细腻,长年不流动的积水在这里沉积了厚厚一层淤泥。", "草丛里某处有轻微扰动,泥沙雾缓缓散开,什么已经躲回草里了。", "草茎底部有些许发光的微生物,在灯光照不到的地方闪烁着蓝绿色微光。", "海草床边缘处,水流方向有细微变化,带来远处的有机物碎屑。" ], reef: [ "珊瑚礁的轮廓在灯光边缘显得复杂而密集,每一处突起都可能藏着什么。", "礁石背面有一片深色阴影区,水流在这里分叉绕行,带着有机物碎屑漂散。", "一片星珊瑚覆盖了整块礁石,珊瑚虫都伸出细小的触须在过滤水流。", "海葵的触须在水流中缓慢张合,橘红色的簇丛在昏暗中格外鲜艳。", "礁壁顶端有一块突出的岩架,下方形成庇护区,积聚了大量悬浮有机颗粒。" ], cliff: [ "峭壁向下延伸,在灯光能触及的范围内没有底端,黑暗完整地包围着这里。", "壁面有被侵蚀的凹槽,形状奇特,像是某种大型生物曾经在此摩擦过。", "岩壁上偶有气泡从微小裂隙中涌出,缓缓升向看不见的水面。", "峭壁上有黑色渗液缓缓流出,在岩面留下暗色条纹,气味浓烈。", "壁面有处突出的岩台,岩台下方聚积着沉降物,已经形成了小型沙砾堆。" ], forest: [ "茂密的巨藻从海床一直生长到视野所能触及的高度,光线穿透枝叶时呈现出斑驳的绿色。", "藻林的树冠处聚集着大量微小气泡,光线穿透时将它们映成金色。", "林底枯萎的巨藻茎已经开始腐化,成为无数附生生物的栖居之所。", "藻林边缘有处缺口,开阔区域从缺口处可见,与林内的幽暗形成对比。", "粗壮的藻茎之间留有天然的通道,水流在其中形成稳定的流向。" ], water: [ "一只水母缓慢地漂过,半透明的伞盖轻轻收缩,触须垂落如丝。", "一片细微的悬浮颗粒在灯光里漂浮,随推进水流散开又聚拢。", "远处有什么发光体划过,在黑暗中留下短暂的蓝色轨迹,随即消失。", "水中偶尔有深处涌上的冷流,温度计轻微下降了几度。", "开放水域里看不到底端,只有灯光勉强照出面前这一小片水域的轮廓。" ] }>> /* ── 环境采集定义:不消耗丰富度,产量低但稳定 ── */ <<set $envHarvestDefs = { sand: { label:"翻找沙层", text:"在浅沙层翻找了一圈。", loot:[{id:"shell_frag",qty:[1,3]},{id:"sand_extract",qty:[0,1]}] }, flat: { label:"刮取岩面", text:"刮取了岩面的附生物和渗出物。", loot:[{id:"seawater_ext",qty:[1,2]},{id:"coral_frag",qty:[0,2]}] }, reef: { label:"采集礁面", text:"采集了礁面上松动的珊瑚碎片。", loot:[{id:"coral_frag",qty:[1,3]},{id:"shell_frag",qty:[0,2]}] }, grass: { label:"收割海草", text:"收割了附近的海草,整理成束。", loot:[{id:"kelp",qty:[2,4]},{id:"seagrass_str",qty:[1,2]}] }, forest:{ label:"采集巨藻", text:"采集了大量巨藻,还提取了一些藻纤维。", loot:[{id:"kelp",qty:[3,6]},{id:"kelp_fiber",qty:[1,2]}] }, cliff: { label:"收集渗出物",text:"收集了壁面渗液和矿物堆积物。", loot:[{id:"sand_extract",qty:[1,2]},{id:"sulfur_dust",qty:[0,1]}] }, water: { label:"过滤浮游物",text:"过滤了一些浮游生物和海水提取物。", loot:[{id:"seawater_ext",qty:[1,3]},{id:"jellyfluid",qty:[0,1]}] } }>> <<set $exploreSearchCost = { min: 3, max: 7 }>> <<set $lastExploreText = "">> <<set $exploreLog = []>> <</widget>> <</nobr>>
<<nobr>> <<widget "exploreSearch">> /* ── 初始化 ── */ <<set _emin = ($exploreSearchCost && typeof $exploreSearchCost.min === "number") ? $exploreSearchCost.min : 3>> <<set _emax = ($exploreSearchCost && typeof $exploreSearchCost.max === "number") ? $exploreSearchCost.max : 7>> <<if !$exploreLog>><<set $exploreLog = []>><</if>> <<set _rich = Number($regionRichness) || 0>> /* 丰富度不足 */ <<if _rich < _emin>> <<set $lastExploreText = "这片区域已经被搜索得差不多了,暂时没有新的发现。">> <<return>> <</if>> /* 消耗丰富度 */ <<set _cost = _emin + Math.floor(Math.random() * (_emax - _emin + 1))>> <<set $regionRichness = Math.max(0, _rich - _cost)>> /* ── 选基础氛围(1-2 条,不含生物名)── */ <<if !$exploreFragments>><<exploreDefs>><</if>> <<set _pool = null>> <<if $exploreFragments[$maptype] && $exploreFragments[$maptype].length > 0>> <<set _pool = $exploreFragments[$maptype].slice()>> <<else>> <<set _pool = ["周围一片幽暗,灯光勉强照出面前这一小片水域的轮廓。","水流平静,没有特别的动静。"]>> <</if>> /* Fisher-Yates 局部乱序,取 1-2 条 */ <<set _baseN = Math.random() < 0.5 ? 1 : 2>> <<set _baseN = Math.min(_baseN, _pool.length)>> <<for _si = 0; _si < _baseN; _si++>> <<set _sj = _si + Math.floor(Math.random() * (_pool.length - _si))>> <<set _stmp = _pool[_si]>><<set _pool[_si] = _pool[_sj]>><<set _pool[_sj] = _stmp>> <</for>> <<set $lastExploreText = _pool.slice(0, _baseN).join(" ")>> <<run $exploreLog.unshift($lastExploreText)>> <<if $exploreLog.length > 5>><<run $exploreLog.pop()>><</if>> /* ── 构建微型事件候选池(hunt 优先,补充 explore) ── */ <<if !$microEventDefs>><<microEventTable>><</if>> <<set $activeHuntItems = []>> <<set $lastHuntText = "">> <<set $lastMicroText = "">> <<set _richFactor = Math.max(0, _rich) / 100>> <<set _slots = 3 - _baseN>> /* 剩余碎片槽数 */ /* 先收集满足条件的 hunt 类 ID */ <<set _huntPool = []>> <<set _mKeys = Object.keys($microEventDefs)>> <<for _mi = 0; _mi < _mKeys.length; _mi++>> <<set _md = $microEventDefs[_mKeys[_mi]]>> <<if _md.subtype !== "hunt">><<continue>><</if>> /* 地形 + 深度过滤 */ <<set _tOK = false>> <<for _ti = 0; _ti < _md.terrain.length; _ti++>> <<if _md.terrain[_ti] === $maptype>><<set _tOK = true>><<break>><</if>> <</for>> <<if _tOK && $depth >= _md.depthRange[0] && $depth <= _md.depthRange[1]>> <<set _huntPool[_huntPool.length] = _mKeys[_mi]>> <</if>> <</for>> /* 乱序后按概率×丰富度取最多 _slots 条 hunt */ <<for _si = _huntPool.length - 1; _si > 0; _si-->> <<set _sj = Math.floor(Math.random() * (_si + 1))>> <<set _stmp = _huntPool[_si]>><<set _huntPool[_si] = _huntPool[_sj]>><<set _huntPool[_sj] = _stmp>> <</for>> <<for _hi = 0; _hi < _huntPool.length && $activeHuntItems.length < _slots; _hi++>> <<set _hd = $microEventDefs[_huntPool[_hi]]>> <<if Math.random() < _hd.baseChance * _richFactor>> <<set $activeHuntItems[$activeHuntItems.length] = _huntPool[_hi]>> <</if>> <</for>> /* 若还有空槽,补充 explore 类 */ <<if $activeHuntItems.length < _slots>> <<set _expPool = []>> <<for _mi = 0; _mi < _mKeys.length; _mi++>> <<set _md = $microEventDefs[_mKeys[_mi]]>> <<if _md.subtype !== "explore">><<continue>><</if>> <<set _tOK = false>> <<for _ti = 0; _ti < _md.terrain.length; _ti++>> <<if _md.terrain[_ti] === $maptype>><<set _tOK = true>><<break>><</if>> <</for>> <<if _tOK && $depth >= _md.depthRange[0] && $depth <= _md.depthRange[1]>> <<set _expPool[_expPool.length] = _mKeys[_mi]>> <</if>> <</for>> <<for _si = _expPool.length - 1; _si > 0; _si-->> <<set _sj = Math.floor(Math.random() * (_si + 1))>> <<set _stmp = _expPool[_si]>><<set _expPool[_si] = _expPool[_sj]>><<set _expPool[_sj] = _stmp>> <</for>> <<for _ei = 0; _ei < _expPool.length && $activeHuntItems.length < _slots; _ei++>> <<set _ed = $microEventDefs[_expPool[_ei]]>> <<if Math.random() < _ed.baseChance>> <<set $activeHuntItems[$activeHuntItems.length] = _expPool[_ei]>> <</if>> <</for>> <</if>> /* ── 持久效果检查 ── */ <<checkEnvEffects>> /* ── 触发小型事件(spawnSmallEvent 调度,6% 门控,概率×15) ── */ <<if !$activeSmallEvent && Math.random() < 0.06>> <<spawnSmallEvent "anchored" 15>> <<if $pendingEvent>> <<set $activeSmallEvent = $pendingEvent>> <<set $pendingEvent = null>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "microEventTable">> <<set $microEventDefs = { /* ── explore 类:发现物品/材料,触发不依赖丰富度 ── */ "sand_glint": { subtype:"explore", terrain:["sand","flat"], depthRange:[0,500], baseChance:0.18, fragmentText:"沙面深处透出一点金属光泽。", actionLabel:"◎ 挖掘查看", outcomes:[ {weight:50,text:"是一块锈蚀的金属碎片,勉强还能用。",loot:[{id:"metal",qty:[1,2]}]}, {weight:30,text:"挖出了几块贝壳碎片,什么特别的都没有。",loot:[{id:"shell_frag",qty:[1,3]}]}, {weight:15,text:"是一枚完整的珍珠,大小适中,品相不错。",loot:[{id:"pearl",qty:[1,1]}]}, {weight:5, text:"是一块奇异的矿石晶体,表面有微弱发光。",loot:[{id:"current_stone",qty:[1,1]}]} ] }, "scallop_edge": { subtype:"explore", terrain:["sand","reef","flat"], depthRange:[0,200], baseChance:0.15, fragmentText:"礁缝里露出了一只扇贝的边角,纹理清晰,个头可观。", actionLabel:"◎ 撬起采集", outcomes:[ {weight:60,text:"成功采到一只扇贝,个头不小。",loot:[{id:"scallop",qty:[1,2]}]}, {weight:25,text:"扇贝壳里藏了颗小珍珠,意外之喜。",loot:[{id:"scallop",qty:[1,1]},{id:"pearl",qty:[1,1]}]}, {weight:15,text:"用力过猛,壳碎了,只剩些贝肉和碎壳。",loot:[{id:"shell_meat",qty:[1,2]},{id:"shell_frag",qty:[1,2]}]} ] }, "drifting_debris": { subtype:"explore", terrain:["water","sand","grass"], depthRange:[0,100], baseChance:0.12, fragmentText:"一小片木质残骸随流漂来,上面还绑着什么东西。", actionLabel:"◎ 打捞", outcomes:[ {weight:45,text:"是几段腐朽的木料,还能用。",loot:[{id:"wood",qty:[1,3]}]}, {weight:35,text:"木板上绑着一卷绳索,略有磨损但完整。",loot:[{id:"wood",qty:[1,1]},{id:"rope",qty:[1,2]}]}, {weight:15,text:"残骸里嵌着玻璃碎片和铁钉。",loot:[{id:"glass",qty:[1,1]},{id:"metal",qty:[1,2]}]}, {weight:5, text:"木板下压着一个防水皮革包,里面是几页泛黄的日志。",loot:[{id:"relic_log",qty:[1,1]}]} ] }, "kelp_tangle": { subtype:"explore", terrain:["grass","forest"], depthRange:[0,400], baseChance:0.14, fragmentText:"一团密集的海藻漂来,里面似乎卷着什么东西。", actionLabel:"◎ 清理查看", outcomes:[ {weight:40,text:"只是一团普通海藻,但量不少。",loot:[{id:"kelp",qty:[2,4]}]}, {weight:30,text:"藻团里夹着一只小章鱼,已经不动了。",loot:[{id:"octopus_meat",qty:[1,1]},{id:"kelp",qty:[1,2]}]}, {weight:20,text:"藻团中间包裹着一枚完好的海胆。",loot:[{id:"seaurchin",qty:[1,1]}]}, {weight:10,text:"海藻里缠绕着一段奇异的致密纤维。",loot:[{id:"kelp_fiber",qty:[2,3]}]} ] }, "coral_fragment": { subtype:"explore", terrain:["reef","flat"], depthRange:[10,300], baseChance:0.13, fragmentText:"礁面上有一块松动的珊瑚,颜色鲜艳,已从主体断裂。", actionLabel:"◎ 采集", outcomes:[ {weight:55,text:"采到一块品相不错的珊瑚碎片。",loot:[{id:"coral_frag",qty:[1,3]}]}, {weight:30,text:"珊瑚内部有细小的土系结晶颗粒。",loot:[{id:"coral_frag",qty:[1,2]},{id:"tinct_earth_crystal",qty:[1,1]}]}, {weight:15,text:"珊瑚里钻出了一只甜虾,外壳鲜红。",loot:[{id:"coral_frag",qty:[1,1]},{id:"sweetshrimp",qty:[1,2]}]} ] }, "cliff_seep": { subtype:"explore", terrain:["cliff"], depthRange:[100,10000], baseChance:0.10, fragmentText:"壁面渗出一股黑色液体,在水中扩散,气味浓烈。", actionLabel:"◎ 采集样本", outcomes:[ {weight:50,text:"收集到硫磺渗液,成分待分析。",loot:[{id:"sulfur_dust",qty:[1,2]}]}, {weight:30,text:"渗液中有结晶颗粒,散发微弱热量。",loot:[{id:"sulfur_dust",qty:[1,1]},{id:"ember_crystal",qty:[1,1]}]}, {weight:20,text:"渗液黏稠异常,像是某种生物分泌物。",loot:[{id:"thermal_ext",qty:[1,1]}]} ] }, "sand_creature": { subtype:"explore", terrain:["sand","flat"], depthRange:[0,300], baseChance:0.11, fragmentText:"沙面有规律地微微鼓起,节律均匀,某种东西藏在浅沙层中。", actionLabel:"◎ 挖掘捕捉", outcomes:[ {weight:40,text:"是一只埋在沙里的蛤蜊,个头挺大。",loot:[{id:"clam",qty:[1,3]}]}, {weight:30,text:"挖出几只比目鱼,在沙里扑腾。",loot:[{id:"flounder",qty:[1,2]}]}, {weight:20,text:"是一只濑尿虾,甲壳坚硬,挣扎有力。",loot:[{id:"mantisshrimp",qty:[1,1]}]}, {weight:10,text:"挖到一块岩质结构,里面有化石痕迹。",loot:[{id:"bone_ash",qty:[1,2]},{id:"shell_frag",qty:[1,2]}]} ] }, "floating_egg": { subtype:"explore", terrain:["water","grass","reef"], depthRange:[0,200], baseChance:0.09, fragmentText:"水中漂着一串半透明的卵囊,内部有细小的形状蠕动。", actionLabel:"◎ 收集", outcomes:[ {weight:50,text:"收集到一些鱼卵,新鲜度尚可。",loot:[{id:"fish_roe",qty:[1,3]}]}, {weight:30,text:"卵囊内是虾的幼体,活性较强。",loot:[{id:"shrimp_meat",qty:[1,2]}]}, {weight:20,text:"卵囊外壁有奇异的发光蛋白质,来源不明。",loot:[{id:"fish_roe",qty:[1,2]},{id:"jellyfluid",qty:[1,1]}]} ] }, /* ── hunt 类:目击描述 + 追猎行动,触发概率按丰富度缩放 ── */ "hunt_sand_eel": { subtype:"hunt", terrain:["sand"], depthRange:[0,1000], baseChance:0.55, fragmentText:"沙面留着一道新鲜的S形划痕——鳗鱼不会走远。", actionLabel:"◎ 追踪这条鳗鱼", outcomes:[ {weight:55,text:"沙层下果然有鳗鱼蜷缩其中,被灯光晃了一下来不及逃脱。",loot:[{id:"eel",qty:[1,2]}]}, {weight:30,text:"追了一段,鳗鱼钻进了更深的沙缝,没能捉到。",loot:[]}, {weight:15,text:"鳗鱼不在,但挖到了藏在洞里的比目鱼。",loot:[{id:"flounder",qty:[1,1]}]} ] }, "hunt_sand_flatfish": { subtype:"hunt", terrain:["sand","flat"], depthRange:[0,500], baseChance:0.50, fragmentText:"沙面有一块不自然的隆起,轮廓和周围的沙丘不同。", actionLabel:"◎ 挖开查看", outcomes:[ {weight:50,text:"是一条比目鱼,被惊起来在水里乱扑,轻松捞住。",loot:[{id:"flounder",qty:[1,2]}]}, {weight:25,text:"挖出来的是个蛤蜊堆,比目鱼已经跑了。",loot:[{id:"clam",qty:[1,3]}]}, {weight:15,text:"一只濑尿虾突然猛地夹了机械臂一下,但还是被捉住了。",loot:[{id:"mantisshrimp",qty:[1,1]}]}, {weight:10,text:"翻开沙层只有几只小螃蟹,夹了夹空气,各自逃散。",loot:[{id:"swimmingcrab",qty:[0,1]}]} ] }, "hunt_flat_eel": { subtype:"hunt", terrain:["flat"], depthRange:[0,1000], baseChance:0.52, fragmentText:"一条细长的鳗鱼从岩缝里探出头,打量了一眼灯光,又缩了回去。", actionLabel:"◎ 诱引捕捉", outcomes:[ {weight:50,text:"用食物残渣引了几分钟,鳗鱼探出身来,被捕捉网一扣。",loot:[{id:"eel",qty:[1,1]}]}, {weight:30,text:"鳗鱼警觉,诱了几次都不出来,最后缩回更深处。",loot:[]}, {weight:20,text:"鳗鱼缝里同时钻出来两只螃蟹,鳗鱼没捉到,但螃蟹到手了。",loot:[{id:"bluecrab",qty:[1,2]}]} ] }, "hunt_flat_urchin": { subtype:"hunt", terrain:["flat","reef"], depthRange:[0,500], baseChance:0.60, fragmentText:"几颗海胆附着在岩面上,棘刺随水流轻微颤动。", actionLabel:"◎ 撬取海胆", outcomes:[ {weight:60,text:"撬下几颗品相不错的海胆,卵巢饱满。",loot:[{id:"seaurchin",qty:[1,3]}]}, {weight:25,text:"棘刺太密,只取到碎片和少量卵。",loot:[{id:"urchin_roe",qty:[1,2]},{id:"urchin_spine_core",qty:[1,1]}]}, {weight:15,text:"岩面有五六颗,全都撬下来了。",loot:[{id:"seaurchin",qty:[2,5]}]} ] }, "hunt_grass_octopus": { subtype:"hunt", terrain:["grass"], depthRange:[0,300], baseChance:0.48, fragmentText:"草根处有一块颜色稍有不自然的区域,几乎和海草完全相同的绿色。", actionLabel:"◎ 突然捕捉", outcomes:[ {weight:50,text:"出其不意按住,章鱼喷了一口墨,但已经逃不掉了。",loot:[{id:"octopus",qty:[1,1]}]}, {weight:30,text:"章鱼喷墨遁逃,趁浑水溜走,没捉到。",loot:[]}, {weight:20,text:"章鱼被捕,慌乱中附近草丛里窜出两只虾。",loot:[{id:"octopus",qty:[1,1]},{id:"prawn",qty:[1,2]}]} ] }, "hunt_grass_bream": { subtype:"hunt", terrain:["grass","reef"], depthRange:[0,200], baseChance:0.45, fragmentText:"一条鲷鱼在草茎间缓慢穿行,时不时停下来拱一拱草根。", actionLabel:"◎ 跟踪捕捞", outcomes:[ {weight:50,text:"靠近时撒网,鲷鱼入网,银红色的鳞片哗哗作响。",loot:[{id:"bream",qty:[1,2]}]}, {weight:25,text:"鲷鱼察觉动静,一个急转猛地蹿出去,没能追上。",loot:[]}, {weight:25,text:"撒网捞到鲷鱼,草丛里还额外裹进来几条小鱼。",loot:[{id:"bream",qty:[1,1]},{id:"seabass",qty:[0,1]},{id:"sardine",qty:[0,2]}]} ] }, "hunt_reef_lobster": { subtype:"hunt", terrain:["reef"], depthRange:[0,300], baseChance:0.42, fragmentText:"珊瑚礁深处的缝隙里露出长长的龙虾触须,在水流里轻轻摆动。", actionLabel:"◎ 诱捕套索", outcomes:[ {weight:45,text:"用套索慢慢套住触须,猛地一拉,龙虾出洞,在机械臂里跑不掉。",loot:[{id:"lobster",qty:[1,1]}]}, {weight:30,text:"龙虾察觉异样,将触须完全缩回洞里。",loot:[]}, {weight:25,text:"龙虾出来了,但跑了一半,只带出些甲壳碎片。",loot:[{id:"crab_shell",qty:[1,2]}]} ] }, "hunt_reef_grouper": { subtype:"hunt", terrain:["reef"], depthRange:[10,400], baseChance:0.44, fragmentText:"礁石背面阴影区有几条石斑鱼悬浮不动,那是它们等待猎物的姿势。", actionLabel:"◎ 诱饵钓取", outcomes:[ {weight:55,text:"石斑鱼咬钩,挣扎了一会儿,被钓上来。体型不小,鱼肉肥厚。",loot:[{id:"grouper",qty:[1,2]}]}, {weight:25,text:"石斑鱼刚探出身子,灯光扫过,立刻缩回阴影里。",loot:[]}, {weight:20,text:"两条鱼同时上钩,差点拉不住,最终都收进船舱。",loot:[{id:"grouper",qty:[2,3]}]} ] }, "hunt_cliff_shadow": { subtype:"hunt", terrain:["cliff"], depthRange:[50,10000], baseChance:0.46, fragmentText:"悬空礁石的阴影区聚集着几条深水鱼,悬浮不动,不受打扰。", actionLabel:"◎ 投钩垂钓", outcomes:[ {weight:40,text:"鳕鱼咬钩,冷水鱼肉质紧实,分量十足。",loot:[{id:"cod",qty:[1,2]}]}, {weight:30,text:"上来的是一条大鳗鱼,深水品种,体色更深。",loot:[{id:"eel",qty:[1,1]}]}, {weight:20,text:"什么都没咬钩,深水鱼对诱饵不感兴趣。",loot:[]}, {weight:10,text:"钩上来一条罕见的鮟鱇,发光器官在舱内隐隐发光。",loot:[{id:"anglerfish",qty:[1,1]}]} ] }, "hunt_cliff_crab": { subtype:"hunt", terrain:["cliff","flat"], depthRange:[0,1000], baseChance:0.52, fragmentText:"几只花蟹横着爬在壁面的凹槽里,专注于觅食,没有察觉到灯光。", actionLabel:"◎ 捞取捕捉", outcomes:[ {weight:55,text:"一网扫过去,捞到好几只花蟹,还有一只扁蟹凑了进来。",loot:[{id:"flowercrab",qty:[1,3]},{id:"swimmingcrab",qty:[0,2]}]}, {weight:25,text:"花蟹感受到振动迅速横向逃窜,只抓到一只。",loot:[{id:"flowercrab",qty:[1,1]}]}, {weight:20,text:"壁面有帝王蟹,体型太大差点夹住机械臂,但最终还是被制服了。",loot:[{id:"kingcrab",qty:[1,1]}]} ] }, "hunt_forest_shadow": { subtype:"hunt", terrain:["forest"], depthRange:[50,1000], baseChance:0.40, fragmentText:"一个体型可观的鱼影在藻林深处穿梭,移动无声,动线有规律。", actionLabel:"◎ 前方埋伏", outcomes:[ {weight:40,text:"是一条大型鲈鱼,猛地扑向诱饵,被牢牢捉住。",loot:[{id:"seabass",qty:[1,2]}]}, {weight:30,text:"鱼影太快,还没布好阵型就消失进了更深的林区。",loot:[]}, {weight:20,text:"是金枪鱼!弹射力极强,挣扎中撕破了一个网眼,但终于收进了舱。",loot:[{id:"tuna",qty:[1,1]}]}, {weight:10,text:"鱼影在埋伏点附近徘徊,最终折返消失。",loot:[]} ] }, "hunt_forest_kelp": { subtype:"hunt", terrain:["forest","grass"], depthRange:[0,600], baseChance:0.48, fragmentText:"粗大的藻茎基部有不寻常的动静,藻体颤动不像是水流引起的。", actionLabel:"◎ 探查捕捉", outcomes:[ {weight:50,text:"章鱼被灯光照到,喷墨逃窜却被网兜堵住——完全没有退路。",loot:[{id:"octopus",qty:[1,1]}]}, {weight:30,text:"是鱿鱼,不是章鱼,被惊走时钻出一团墨云。",loot:[{id:"squid",qty:[1,2]}]}, {weight:20,text:"洞里有只章鱼,还带着一窝卵,放走了,只带走些附生海藻。",loot:[{id:"kelp",qty:[1,2]}]} ] }, "hunt_water_school": { subtype:"hunt", terrain:["water","sand","grass"], depthRange:[0,200], baseChance:0.58, fragmentText:"几条小鱼拦截在探照灯光柱前,越来越多,光在把它们聚拢过来。", actionLabel:"◎ 趁势撒网", outcomes:[ {weight:40,text:"网里哗哗一片银光,主要是沙丁鱼和凤尾鱼,量不少。",loot:[{id:"sardine",qty:[2,5]},{id:"anchovy",qty:[1,3]}]}, {weight:30,text:"捞到鲭鱼为主的混合鱼获,还有几条带鱼凑了进来。",loot:[{id:"mackerel",qty:[1,3]},{id:"hairtail",qty:[0,2]}]}, {weight:20,text:"光柱里混进来一条鯵鱼,个头挺大,是今天的意外收获。",loot:[{id:"mahi",qty:[1,1]},{id:"sardine",qty:[1,3]}]}, {weight:10,text:"下网太慢,鱼群绕过去了,只捞到零星几条。",loot:[{id:"anchovy",qty:[1,2]}]} ] }, "hunt_water_squid": { subtype:"hunt", terrain:["water","forest"], depthRange:[20,1000], baseChance:0.45, fragmentText:"水中有几道间歇性的蓝白色闪光——生物发光信号,靠近的话或许能捕捞到。", actionLabel:"◎ 接近捕捉", outcomes:[ {weight:50,text:"鱿鱼群还在,网一扫下去捞起好几条,触腕在网里缠来缠去。",loot:[{id:"squid",qty:[1,4]}]}, {weight:30,text:"靠近时鱿鱼集体熄灭了发光器,在黑暗中四散逃开。",loot:[]}, {weight:20,text:"捞到几条墨鱼,不是鱿鱼,但同样是不错的渔获。",loot:[{id:"cuttlefish",qty:[1,3]}]} ] } , /* ── 追加变体:同地形不同行为/鱼种 ── */ "hunt_grass_seabass": { subtype:"hunt", terrain:["grass","reef","sand"], depthRange:[0,300], baseChance:0.42, fragmentText:"一条鲈鱼悬停在草缘水中,缓慢扫视猎物,尾鳍轻轻拨水保持位置。", actionLabel:"◎ 投饵钓取", outcomes:[ {weight:55,text:"鲈鱼果断咬钩,挣扎有力但技不如人,入舱。",loot:[{id:"seabass",qty:[1,2]}]}, {weight:25,text:"鲈鱼吐钩逃脱,甩了个漂亮的转身钻进草丛。",loot:[]}, {weight:20,text:"钓到一条,草缘还有另一条受了惊动,也被顺势捞住。",loot:[{id:"seabass",qty:[2,3]}]} ] }, "hunt_grass_shrimp": { subtype:"hunt", terrain:["grass","sand"], depthRange:[0,200], baseChance:0.52, fragmentText:"草根处有几道透明的身影在移动——对虾在贴地觅食,偶尔停下拨弄什么。", actionLabel:"◎ 撒网捕捞", outcomes:[ {weight:55,text:"一网下去压住草丛,捞起大把对虾,腿脚还在挥舞。",loot:[{id:"prawn",qty:[2,5]},{id:"sweetshrimp",qty:[0,2]}]}, {weight:25,text:"对虾感受到震动跳弹逃散,只捞到零星几只。",loot:[{id:"prawn",qty:[1,2]}]}, {weight:20,text:"网里除了对虾,还裹进来几只小螃蟹凑热闹。",loot:[{id:"prawn",qty:[1,3]},{id:"swimmingcrab",qty:[1,2]}]} ] }, "hunt_reef_sweetshrimp": { subtype:"hunt", terrain:["reef","flat"], depthRange:[0,200], baseChance:0.50, fragmentText:"珊瑚缝隙里透出细长的触须,甜虾正在里面悠闲地进食。", actionLabel:"◎ 细网吸引捕捉", outcomes:[ {weight:50,text:"用细网缓慢靠近,甜虾未及反应就被一扫而入,鲜红甲壳整齐地堆在网底。",loot:[{id:"sweetshrimp",qty:[2,4]}]}, {weight:30,text:"甜虾有所察觉,后退进更深的缝隙里,无法跟进。",loot:[]}, {weight:20,text:"除了甜虾,珊瑚洞里还有一只小章鱼同框出现,一起入网。",loot:[{id:"sweetshrimp",qty:[1,2]},{id:"octopus",qty:[1,1]}]} ] }, "hunt_flat_hermitcrab": { subtype:"hunt", terrain:["flat","sand","reef"], depthRange:[0,300], baseChance:0.55, fragmentText:"几只寄居蟹拖着螺壳在岩面上缓行,壳已经磨得发白,但它们还在固执地寻找食物。", actionLabel:"◎ 顺手采集", outcomes:[ {weight:50,text:"这种寄居蟹的螺壳本身也有价值,连蟹带壳一并收入。",loot:[{id:"hermitcrab",qty:[1,3]},{id:"shell_frag",qty:[1,2]}]}, {weight:30,text:"寄居蟹缩进壳里装死,采到几只,另一些趁机夹缝里躲掉了。",loot:[{id:"hermitcrab",qty:[1,2]}]}, {weight:20,text:"在这片岩面发现大量寄居蟹,是难得的密集群落。",loot:[{id:"hermitcrab",qty:[3,6]},{id:"shell_frag",qty:[2,4]}]} ] }, "hunt_cliff_mantis": { subtype:"hunt", terrain:["cliff","flat","reef"], depthRange:[20,500], baseChance:0.45, fragmentText:"壁面凹槽里有濑尿虾在守株待兔,它挥舞着捕肢,颇有气势。", actionLabel:"◎ 夹取捕捉", outcomes:[ {weight:45,text:"机械臂从侧面接近,在它出拳前夹住——这东西打击力惊人,但终究被制服。",loot:[{id:"mantisshrimp",qty:[1,2]}]}, {weight:35,text:"濑尿虾反应极快,一击敲偏了夹臂,趁势蹦进更深裂缝。",loot:[]}, {weight:20,text:"抓到两只,壳色不同,可能是不同亚种。",loot:[{id:"mantisshrimp",qty:[2,3]}]} ] }, "hunt_forest_tuna": { subtype:"hunt", terrain:["forest","water"], depthRange:[30,400], baseChance:0.32, fragmentText:"藻林里有道迅疾的鱼影——动线太快,只隐约看到侧身的蓝色光泽,不像寻常鱼类。", actionLabel:"◎ 弓网埋伏", outcomes:[ {weight:40,text:"金枪鱼扑入弓网的那一瞬间惊天动地,舱体都感受到了冲击,但鱼已入舱。",loot:[{id:"tuna",qty:[1,1]}]}, {weight:40,text:"鱼影转向极快,识破了埋伏方向,消失在林区深处。",loot:[]}, {weight:20,text:"不是金枪鱼,是一条大型鲣鱼,速度稍慢但同样难以对付,最终制服。",loot:[{id:"bonito",qty:[1,1]}]} ] }, "hunt_water_mahi": { subtype:"hunt", terrain:["water","grass"], depthRange:[0,100], baseChance:0.30, fragmentText:"水面附近有大型鱼在高速巡游,灯光边缘捕捉到鲜艳的黄绿色侧身——是鬼头刀。", actionLabel:"◎ 拖钓追踪", outcomes:[ {weight:40,text:"鬼头刀速度极快,但咬饵之后挣扎方向可以预测,最终被拖进网兜。",loot:[{id:"mahi",qty:[1,1]}]}, {weight:35,text:"鬼头刀在高速中脱钩,溅起一片水花就消失了。",loot:[]}, {weight:25,text:"钓住一条,脱钩时引来另一条同伴凑近——顺势再下一网。",loot:[{id:"mahi",qty:[1,2]}]} ] }, "hunt_sand_clam": { subtype:"hunt", terrain:["sand","flat"], depthRange:[0,200], baseChance:0.58, fragmentText:"沙面有几处细小的水流孔在向外喷水,节律均匀——沙蛤埋在下面呼吸。", actionLabel:"◎ 挖掘采集", outcomes:[ {weight:55,text:"顺着喷水孔挖下去,果然有蛤蜊,还不小。",loot:[{id:"clam",qty:[2,5]}]}, {weight:25,text:"挖到了几只,沙层里还有更多,但深度超出了机械臂范围。",loot:[{id:"clam",qty:[1,3]}]}, {weight:20,text:"蛤蜊不在喷水孔正下方,顺着侧向扩展挖出来一堆,大小不一。",loot:[{id:"clam",qty:[3,7]}]} ] }, "hunt_reef_cuttlefish": { subtype:"hunt", terrain:["reef","flat","grass"], depthRange:[10,300], baseChance:0.44, fragmentText:"珊瑚背面有一只墨鱼停在那里,皮肤上的色彩纹路在缓缓变幻,模仿着礁石表面。", actionLabel:"◎ 快速包抄", outcomes:[ {weight:50,text:"墨鱼被围住来不及伪装,喷出一团墨云,但在黑暗里它已经离不开了。",loot:[{id:"cuttlefish",qty:[1,2]}]}, {weight:30,text:"墨鱼在喷墨的掩护下高速侧移,成功脱逃。",loot:[]}, {weight:20,text:"墨鱼被捕,墨云里顺带裹出来两只小虾。",loot:[{id:"cuttlefish",qty:[1,1]},{id:"prawn",qty:[1,2]}]} ] } }>> <</widget>> <</nobr>>
<<nobr>> <<widget "spawnMicroEvent">> <<if !$microEventDefs>><<microEventTable>><</if>> /* 构建当前有效候选列表(只存 id 字符串,避免复杂对象进入 <<run>>) */ <<set _mcIds = []>> <<set _mKeys = Object.keys($microEventDefs)>> <<set _curRich = Math.max(0, Number($regionRichness) || 0)>> <<for _mi = 0; _mi < _mKeys.length; _mi++>> <<set _md = $microEventDefs[_mKeys[_mi]]>> /* 地形检查 */ <<set _tOK = false>> <<for _ti = 0; _ti < _md.terrain.length; _ti++>> <<if _md.terrain[_ti] === $maptype>><<set _tOK = true>><<break>><</if>> <</for>> /* 深度检查 */ <<set _dOK = ($depth >= _md.depthRange[0] && $depth <= _md.depthRange[1])>> /* richnessBased:丰富度归零则跳过 */ <<set _rOK = true>> <<if _md.richnessBased && _curRich <= 0>><<set _rOK = false>><</if>> <<if _tOK && _dOK && _rOK>> <<run _mcIds.push(_mKeys[_mi])>> <</if>> <</for>> /* 逐一掷骰,第一个成功的生效 */ <<for _mi = 0; _mi < _mcIds.length; _mi++>> <<set _cId = _mcIds[_mi]>> <<set _cDef = $microEventDefs[_cId]>> /* richnessBased 事件概率随丰富度线性缩放 */ <<set _cChance = _cDef.baseChance>> <<if _cDef.richnessBased>> <<set _cChance = _cDef.baseChance * (_curRich / 100)>> <</if>> <<if Math.random() < _cChance>> <<set $activeMicroEvent = {id:_cId, name:_cDef.name, desc:_cDef.desc, action:_cDef.action}>> <<break>> <</if>> <</for>> <</widget>> <</nobr>>
<<nobr>> <<widget "resolveMicroEvent">> /* $args[0] = 微型事件 ID 结果写入 $lastHuntText,清除该 ID 出 $activeHuntItems */ <<microEventTable>> <<set _rmeId = $args[0]>> <<if !_rmeId || !$microEventDefs[_rmeId]>> <<set $lastHuntText = "(事件数据丢失)">> <<return>> <</if>> <<set _rmeDef = $microEventDefs[_rmeId]>> /* 加权随机结果 */ <<set _rmeTotalW = 0>> <<for _oi = 0; _oi < _rmeDef.outcomes.length; _oi++>> <<set _rmeTotalW += _rmeDef.outcomes[_oi].weight>> <</for>> <<set _rmeRoll = Math.random() * _rmeTotalW>> <<set _rmeCum = 0>> <<set _rmeResult = _rmeDef.outcomes[0]>> <<for _oi = 0; _oi < _rmeDef.outcomes.length; _oi++>> <<set _rmeCum += _rmeDef.outcomes[_oi].weight>> <<if _rmeRoll < _rmeCum>> <<set _rmeResult = _rmeDef.outcomes[_oi]>> <<break>> <</if>> <</for>> /* 发放战利品 */ <<set _rmeLog = "">> <<if _rmeResult.loot>> <<for _rli = 0; _rli < _rmeResult.loot.length; _rli++>> <<set _rl = _rmeResult.loot[_rli]>> <<set _rlo = _rl.qty[0]>> <<set _rhi = _rl.qty[1]>> <<set _rq = _rlo + Math.floor(Math.random() * (_rhi - _rlo + 1))>> <<if _rq > 0>> <<additem _rl.id _rq>> <<if $items && $items[_rl.id]>> <<set _rmeLog = _rmeLog + $items[_rl.id].name + "×" + _rq + " ">> <</if>> <</if>> <</for>> <</if>> /* 写结果文本 */ <<set $lastHuntText = _rmeResult.text>> <<if _rmeLog>><<set $lastHuntText = $lastHuntText + " " + _rmeLog>><</if>> /* 从 $activeHuntItems 中移除该 ID */ <<set _newHuntItems = []>> <<for _hi = 0; _hi < $activeHuntItems.length; _hi++>> <<if $activeHuntItems[_hi] !== _rmeId>> <<set _newHuntItems[_newHuntItems.length] = $activeHuntItems[_hi]>> <</if>> <</for>> <<set $activeHuntItems = _newHuntItems>> <</widget>> <</nobr>>
<<nobr>> <<widget "smallEventTable">> /* 纯数据,不含函数。条件判断内联在 checkEvent 里完成。 */ <<set $smallEventDefs = { "bream_school": { name: "鲷鱼群", terrain: ["reef","grass"], depthRange: [0,150], context: ["sailing","anchored"], baseChance: 0.003, stages: [ { desc: "声呐捕捉到密集的鱼群回波,雷达确认是鲷鱼洄游群落,数量可观。停在这里可以展开渔网捕捞。", actions: ["展开渔网(第一轮)","声呐标记后离开"] }, { desc: "第一轮渔网收回,舱底多了些银光——鲷鱼还没散,还有机会再捞一次。", actions: ["再次捕捞(最后一轮)","收网离开"] }, { desc: "两轮捕捞后鱼群已经散开,只剩零星游鱼。这一片的收益已经见底了。", actions: ["收网离开"] } ], resolve: { "展开渔网(第一轮)": { nextStage:1, loot:[{id:"bream",qty:[2,5]},{id:"seabass",qty:[0,2]}], timeCost:15, text:"第一轮渔获不错。" }, "声呐标记后离开": { nextStage:-1, loot:[], text:"在导航板上标记了此处坐标后离开。" }, "再次捕捞(最后一轮)":{ nextStage:2, loot:[{id:"bream",qty:[1,4]},{id:"grouper",qty:[0,2]}], text:"鱼群渐稀,但收获依然可观。" }, "收网离开": { nextStage:-1, loot:[], text:"收起渔网,离开了这片水域。" } } }, "crab_cluster": { name: "螃蟹聚集", terrain: ["flat","sand"], depthRange: [0,200], context: ["sailing","anchored"], baseChance: 0.0025, stages: [ { desc: "岩礁附近聚集着大量螃蟹,正在争抢什么腐食。放诱捕笼等候是个好主意。", actions: ["放置诱捕笼","直接驱网捕捞","观察后离开"] }, { desc: "诱捕笼放下约十分钟后,里面已经聚满了贪吃的螃蟹。", actions: ["收取诱捕笼"] } ], resolve: { "放置诱捕笼": { nextStage:1, loot:[], text:"诱捕笼已放置,静候片刻。" }, "直接驱网捕捞": { nextStage:-1, loot:[{id:"bluecrab",qty:[1,3]},{id:"swimmingcrab",qty:[0,2]}], text:"驱网捕到不少,但也惊散了一些。" }, "观察后离开": { nextStage:-1, loot:[], text:"观察了一会儿,记下了蟹群的迁徙规律。" }, "收取诱捕笼": { nextStage:-1, loot:[{id:"bluecrab",qty:[2,5]},{id:"flowercrab",qty:[0,2]},{id:"kingcrab",qty:[0,1]}], text:"诱捕笼的收获丰厚,甚至有一只帝王蟹挤了进来。" } } }, "vent_harvest": { name: "热液区采集", terrain: ["flat","cliff"], depthRange: [300,10000], context: ["sailing","anchored","outside"], baseChance: 0.002, stages: [ { desc: "探照灯照亮了一处活跃的热液喷口区域,周围遍布化学合成生物群落,矿物质堆积肉眼可见。", actions: ["采集表层样本","靠近深入探查","保持距离离开"] }, { desc: "靠近后发现喷口内侧有更浓缩的矿物堆积,成分更为复杂。温度极高,需小心操作。", actions: ["采集浓缩矿物","谨慎撤退"] } ], resolve: { "采集表层样本": { nextStage:-1, loot:[{id:"sulfur_dust",qty:[1,3]},{id:"thermal_ext",qty:[1,2]}], text:"采集到表层矿物和热液提取物。" }, "靠近深入探查": { nextStage:1, loot:[{id:"sulfur_dust",qty:[1,2]}], text:"靠近了喷口,发现内层矿物更为稀有。" }, "保持距离离开": { nextStage:-1, loot:[], text:"谨慎起见,记录了坐标后离开。" }, "采集浓缩矿物": { nextStage:-1, loot:[{id:"ember_crystal",qty:[1,2]},{id:"thermal_ext",qty:[1,3]},{id:"sulfur_dust",qty:[1,2]}], timeCost:20, text:"采到浓缩火系结晶和高品质热液提取物,价值不菲。" }, "谨慎撤退": { nextStage:-1, loot:[{id:"thermal_ext",qty:[1,1]}], text:"撤退时顺手带走了一瓶热液样本。" } } } , /* ══ 影响类事件(第四批) ══ */ "kelp_planting": { name: "海带种植点", terrain: ["grass","reef"], depthRange: [5,80], context: ["anchored","outside"], baseChance: 0.004, stages: [ { desc: "这片区域的基底很适合海带附着,水流稳定,光照充足——如果在这里种下海带,十天后就能有相当可观的收获。", actions: ["种植海带(消耗海带种子×2)","采集现有零散海藻","离开"] } ], resolve: { "种植海带(消耗海带种子×2)": { nextStage: -1, loot: [], timeCost: 8, text: "你在基底插入了固定桩,将海带幼苗束缚在水流中。这里会记住这片种植点,十天后可以回来收获。", envEffect: { type:"kelp_farm", terrain:"auto", depthAuto:true, growDays:10, maxHarvest:5 } }, "采集现有零散海藻": { nextStage:-1, loot:[{id:"kelp",qty:[1,3]}], timeCost:5, text:"从周围收集了一些自然生长的海藻。" }, "离开": { nextStage:-1, loot:[], text:"记下了这里的位置,以后再说。" } } }, "kelp_harvest": { name: "海带收获", terrain: ["grass","reef"], depthRange: [5,80], context: ["anchored","outside"], baseChance: 0, stages: [ { desc: "你之前种下的海带已经成熟了,浓密的绿色叶片随水流轻摇,收获量可观。", actions: ["全面收割","只收部分留种","放弃"] } ], resolve: { "全面收割": { nextStage:-1, loot:[{id:"kelp",qty:[8,15]},{id:"kelp_fiber",qty:[2,4]}], timeCost:20, text:"海带收割完毕,满载而归。这片种植点已枯竭。", harvestKelp: true }, "只收部分留种": { nextStage:-1, loot:[{id:"kelp",qty:[4,7]},{id:"kelp_fiber",qty:[1,2]}], timeCost:12, text:"收割了大部分,留下了一些让它继续生长。", harvestKelp: "partial" }, "放弃": { nextStage:-1, loot:[], text:"暂时不收,等它再长一段时间。" } } }, /* ══ 好感类占位(第四批,框架验证) ══ */ "bond_otter_family": { name: "海獭家族", terrain: ["reef","grass"], depthRange: [0,40], context: ["sailing","anchored"], baseChance: 0.0015, stages: [ { desc: "一群海獭在礁石间嬉戏,它们注意到了你,好奇地聚拢过来,用亮黑的眼睛打量着潜艇。", actions: ["投喂鱼类","静静观察","鸣笛打招呼"] } ], resolve: { "投喂鱼类": { nextStage:-1, loot:[], timeCost:5, text:"海獭们争先恐后地游来,将鱼叼走后还在玻璃旁徘徊了好一会儿。", bondGain:{ key:"otter_family", amount:2, terrain:"auto", depthAuto:true } }, "静静观察": { nextStage:-1, loot:[], timeCost:3, text:"它们很快失去了兴趣,重新开始玩耍。你把这一幕记在了航行日志里。", bondGain:{ key:"otter_family", amount:1, terrain:"auto", depthAuto:true } }, "鸣笛打招呼": { nextStage:-1, loot:[], timeCost:1, text:"笛声响起,海獭们吓了一跳,迅速散开。也许下次轻一点。", bondGain:{ key:"otter_family", amount:0, terrain:"auto", depthAuto:true } } } }, /* ══ 占位事件(第二批,仅用于测试调度逻辑) ══ */ "placeholder_sail_shallow": { name: "【占位·航行·浅水】", terrain: ["sand","reef","grass","flat"], depthRange: [0,100], context: ["sailing"], baseChance: 0.002, stages: [{ desc: "(施工中)航行-浅水占位事件。", actions: ["确认"] }], resolve: { "确认": { nextStage:-1, loot:[], text:"(施工中)占位结束。" } } }, "placeholder_sail_deep": { name: "【占位·航行·深水】", terrain: ["flat","cliff"], depthRange: [300,10000], context: ["sailing"], baseChance: 0.002, stages: [{ desc: "(施工中)航行-深水占位事件。", actions: ["确认"] }], resolve: { "确认": { nextStage:-1, loot:[], text:"(施工中)占位结束。" } } }, "placeholder_anchored_1": { name: "【占位·锚定·通用】", terrain: ["sand","reef","grass","flat","cliff"], depthRange: [0,10000], context: ["anchored"], baseChance: 0.002, stages: [{ desc: "(施工中)锚定-通用占位事件。", actions: ["确认"] }], resolve: { "确认": { nextStage:-1, loot:[], text:"(施工中)占位结束。" } } }, "placeholder_outside_1": { name: "【测试·舱外遭遇】", terrain: ["sand","reef","grass","flat","cliff"], depthRange: [0,10000], context: ["outside"], baseChance: 0.01, stages: [ { desc: "【调度测试】你在黑暗中发现了某样东西——这是一个测试遭遇,用来验证舱外小型事件是否正常显示和可以操作。", actions: ["仔细检查(消耗时间)","快速略过","忽略继续前进"] } ], resolve: { "仔细检查(消耗时间)": { nextStage:-1, loot:[{id:"metal",qty:[1,2]}], timeCost:10, text:"仔细检查后发现了一些金属碎片(调度测试通过 · timeCost=10)" }, "快速略过": { nextStage:-1, loot:[], text:"你快速扫了一眼,没有特别的东西(调度测试通过)" }, "忽略继续前进": { nextStage:-1, loot:[], text:"直接忽略,继续前进(调度测试通过)" } } }, "placeholder_all_reef": { name: "【占位·全上下文·礁】", terrain: ["reef"], depthRange: [0,300], context: ["sailing","anchored","outside"], baseChance: 0.002, stages: [{ desc: "(施工中)礁地形全上下文占位事件。", actions: ["确认"] }], resolve: { "确认": { nextStage:-1, loot:[], text:"(施工中)占位结束。" } } }, "placeholder_multistage": { name: "【占位·多阶段测试】", terrain: ["sand","flat","reef","grass","cliff"], depthRange: [0,10000], context: ["sailing","anchored"], baseChance: 0.001, stages: [ { desc: "(施工中)多阶段第一段。", actions: ["进入第二段","直接结束"] }, { desc: "(施工中)多阶段第二段。", actions: ["结束"] } ], resolve: { "进入第二段": { nextStage:1, loot:[], text:"进入第二段。" }, "直接结束": { nextStage:-1, loot:[], text:"(施工中)直接结束。" }, "结束": { nextStage:-1, loot:[], text:"(施工中)多阶段测试完成。" } } } }>> <</widget>> <</nobr>>
<<nobr>> <<widget "resolveSmallEvent">> /* 始终重新初始化定义,避免跨状态步骤后对象损坏 */ <<smallEventTable>> <<if !$activeSmallEvent>><<return>><</if>> <<set _rsId = $activeSmallEvent.id>> <<set _rsAct = $args[0]>> <<if !$smallEventDefs[_rsId]>> <<set $lastSmallEventText = "(事件数据丢失)">> <<set $activeSmallEvent = null>> <<return>> <</if>> <<set _rsDef = $smallEventDefs[_rsId]>> <<if !_rsDef.resolve[_rsAct]>> <<set $lastSmallEventText = "(未知操作)">> <<set $activeSmallEvent = null>> <<return>> <</if>> <<set _rsResult = _rsDef.resolve[_rsAct]>> /* 发放战利品 */ <<set _rsLog = $activeSmallEvent.lootLog>> <<if _rsResult.loot>> <<for _rli = 0; _rli < _rsResult.loot.length; _rli++>> <<set _rl = _rsResult.loot[_rli]>> <<set _rlo = _rl.qty[0]>> <<set _rhi = _rl.qty[1]>> <<set _rq = _rlo + Math.floor(Math.random() * (_rhi - _rlo + 1))>> <<if _rq > 0>> <<additem _rl.id _rq>> <<if $items && $items[_rl.id]>> <<set _rsLog = _rsLog + $items[_rl.id].name + "×" + _rq + " ">> <</if>> <</if>> <</for>> <</if>> /* 进入下一阶段或结束 */ <<set _rsNext = _rsResult.nextStage>> <<if _rsNext < 0 || _rsNext >= _rsDef.stages.length>> <<set $lastSmallEventText = _rsResult.text>> <<if _rsLog>><<set $lastSmallEventText = $lastSmallEventText + " 收获:" + _rsLog>><</if>> <<set $activeSmallEvent = null>> <<else>> <<set _rsNs = _rsDef.stages[_rsNext]>> <<set $activeSmallEvent.stageIdx = _rsNext>> <<set $activeSmallEvent.stageDesc = _rsResult.text + " " + _rsNs.desc>> <<set $activeSmallEvent.actions = _rsNs.actions>> <<set $activeSmallEvent.lootLog = _rsLog>> <</if>> /* timeCost:若选项定义了时间消耗,推进游戏时间 */ <<if _rsResult.timeCost && _rsResult.timeCost > 0>> <<set $timepass = _rsResult.timeCost>> <<time>> <</if>> /* questTrigger:选项完成后推进任务 */ <<if _rsResult.questTrigger>> <<questCheck _rsResult.questTrigger.type (_rsResult.questTrigger.id || "")>> <</if>> /* goto:选项可以跳转到战斗/NPC/主线占位 passage */ <<if _rsResult.goto>> <<if _rsResult.goto === "战斗" || _rsResult.goto === "战斗">> <<set $combatReturn = ($currentContext === "outside") ? "仓外探索" : ($currentContext === "anchored") ? "探索" : "航行">> <<set $combatState = { enemy: _rsResult.enemy || "未知生物", enemyHP: _rsResult.enemyHP || 30, reward: _rsResult.reward || [], sourceEvent: $activeSmallEvent ? $activeSmallEvent.id : "unknown" }>> <<set $activeSmallEvent = null>> <<goto _rsResult.goto>> <<elseif _rsResult.goto === "NPC_商店_占位" || _rsResult.goto === "NPC_对话_占位" || _rsResult.goto === "主线入口_占位">> <<set $npcReturn = ($currentContext === "outside") ? "仓外探索" : ($currentContext === "anchored") ? "探索" : "航行">> <<set $npcState = { npcId: _rsResult.npcId || "unknown_npc", npcName: _rsResult.npcName || "陌生人", shopId: _rsResult.shopId || null, sourceEvent: $activeSmallEvent ? $activeSmallEvent.id : "unknown" }>> <<set $activeSmallEvent = null>> <<goto _rsResult.goto>> <</if>> <</if>> /* envEffect:影响类事件写入 $envEffects */ <<if _rsResult.envEffect>> <<set _rsEff = _rsResult.envEffect>> <<set _rsNewEff = { type: _rsEff.type, terrain: (_rsEff.terrain === "auto") ? $maptype : _rsEff.terrain, depthMin: _rsEff.depthAuto ? Math.max(0, $depth - 20) : (_rsEff.depthMin || 0), depthMax: _rsEff.depthAuto ? $depth + 20 : (_rsEff.depthMax || 9999), plantedDay: $day || 0, harvestCount: 0, state: "growing" }>> <<run $envEffects.push(_rsNewEff)>> <</if>> /* harvestKelp:海带农场收获处理 */ <<if _rsResult.harvestKelp>> <<for _rsKi = $envEffects.length - 1; _rsKi >= 0; _rsKi-->> <<set _rsKEff = $envEffects[_rsKi]>> <<if _rsKEff.type === "kelp_farm" && _rsKEff.terrain === $maptype && $depth >= _rsKEff.depthMin && $depth <= _rsKEff.depthMax>> <<if _rsResult.harvestKelp === "partial">> <<set $envEffects[_rsKi].harvestCount += 1>> <<set $envEffects[_rsKi].plantedDay = $day || 0>> <<set $envEffects[_rsKi].state = "growing">> <<else>> /* 全面收割:超过最大次数则枯竭移除 */ <<set $envEffects[_rsKi].harvestCount += 1>> <<if $envEffects[_rsKi].harvestCount >= 5>> <<set $envEffects[_rsKi].state = "depleted">> <<run $envEffects.splice(_rsKi, 1)>> <<else>> <<set $envEffects[_rsKi].plantedDay = $day || 0>> <<set $envEffects[_rsKi].state = "growing">> <</if>> <</if>> <<break>> <</if>> <</for>> <</if>> /* bondGain:好感类事件写入 / 更新 $ecoBonds */ <<if _rsResult.bondGain>> <<set _rsBG = _rsResult.bondGain>> <<set _rsBK = _rsBG.key>> <<if !$ecoBonds[_rsBK]>> /* 首次相遇:建立档案 */ <<set $ecoBonds[_rsBK] = { terrain: (_rsBG.terrain === "auto") ? $maptype : _rsBG.terrain, depthMin: _rsBG.depthAuto ? Math.max(0, $depth - 30) : (_rsBG.depthMin || 0), depthMax: _rsBG.depthAuto ? $depth + 30 : (_rsBG.depthMax || 9999), met: true, bond: _rsBG.amount || 0, lastVisit: $day || 0, stage: 0, active: true }>> <<else>> /* 再次相遇:累加好感(冷却检查:同一天只加一次)*/ <<if ($ecoBonds[_rsBK].lastVisit || 0) < ($day || 0)>> <<set $ecoBonds[_rsBK].bond += _rsBG.amount || 0>> <<set $ecoBonds[_rsBK].lastVisit = $day || 0>> <</if>> /* stage 晋级(每10点升一阶,最高3)*/ <<if $ecoBonds[_rsBK].bond >= ($ecoBonds[_rsBK].stage + 1) * 10 && $ecoBonds[_rsBK].stage < 3>> <<set $ecoBonds[_rsBK].stage += 1>> <</if>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "spawnWorldScene">> <<if $largeScene && $largeScene !== 0 && $largeScene.state !== "done">> <</if>> <<if !$largeScene || $largeScene === 0 || $largeScene.state === "done">> <<set _wsCands = []>> <<if $depthdeep >= 80 && $depthdeep <= 600 && ($maptype === "sand" || $maptype === "flat")>> <<set _wsCands[_wsCands.length] = "wreck_site">> <</if>> <<if $depthdeep >= 150 && $depthdeep <= 1000 && ($maptype === "sand" || $maptype === "flat" || $maptype === "cliff")>> <<set _wsCands[_wsCands.length] = "whale_fall">> <</if>> <<if $depthdeep >= 20 && $depthdeep <= 300 && ($maptype === "flat" || $maptype === "reef" || $maptype === "sand")>> <<set _wsCands[_wsCands.length] = "ruin_cluster">> <</if>> <<if _wsCands.length > 0>> <<set _wsW = {"wreck_site":30,"whale_fall":15,"ruin_cluster":12}>> <<set _wsTerrainUnits = Math.floor($maplim / 50)>> <<set _wsBudget = Math.floor(_wsTerrainUnits * 0.4)>> <<set _wsCount = Math.min(6, Math.floor(_wsBudget / 70))>> <<if _wsCount > 0>> <<set _wsBufRaw = 5000>> <<set _wsSlotRaw = Math.max(3500, Math.floor(($maplim - _wsBufRaw * 2) / _wsCount))>> <<set $worldSceneQueue = []>> <<for _qsi = 0; _qsi < _wsCount; _qsi++>> /* 加权随机 */ <<set _wsTotalW = 0>> <<for _wi = 0; _wi < _wsCands.length; _wi++>><<set _wsTotalW += _wsW[_wsCands[_wi]]>><</for>> <<set _wsRoll = Math.random() * _wsTotalW>> <<set _wsCumW = 0>><<set _wsChosen = _wsCands[0]>> <<for _wi = 0; _wi < _wsCands.length; _wi++>> <<set _wsCumW += _wsW[_wsCands[_wi]]>> <<if _wsRoll < _wsCumW>><<set _wsChosen = _wsCands[_wi]>><<break>><</if>> <</for>> /* 内联字段(不用 continue,改用 if 包裹)*/ <<set _wsName = "">> <<set _wsAppr = "">> <<set _wsSpanMin = 3000>><<set _wsSpanMax = 8000>> <<set _wsKids = []>> <<if _wsChosen === "wreck_site">> <<set _wsName = "沉船区">> <<set _wsAppr = "声呐信号里出现了异常密集的金属反射点——前方可能有沉船残骸。">> <<set _wsSpanMin = 3000>><<set _wsSpanMax = 8000>> <<set _wsKids = ["wreck_cargo","wreck_engine","wreck_logbook"]>> <<elseif _wsChosen === "whale_fall">> <<set _wsName = "鲸落">> <<set _wsAppr = "有机物浓度骤升,水中弥漫着腐败的气息——前方应该有一具大型生物的尸骸。">> <<set _wsSpanMin = 4000>><<set _wsSpanMax = 10000>> <<set _wsKids = ["whale_oil","whale_bone","whale_parasite"]>> <<elseif _wsChosen === "ruin_cluster">> <<set _wsName = "水下废墟">> <<set _wsAppr = "水流带来碎石,声呐图像里出现了规则的直角轮廓——水下有人工建筑遗迹。">> <<set _wsSpanMin = 5000>><<set _wsSpanMax = 12000>> <<set _wsKids = ["ruin_loot","ruin_inscription","ruin_creature"]>> <</if>> <<if _wsName>> <<set _wsBaseAt = _wsBufRaw + _wsSlotRaw * _qsi + Math.floor(_wsSlotRaw / 2)>> <<set _wsJitter = Math.floor(_wsSlotRaw * 0.2)>> <<set _wsStart = _wsBaseAt + Math.floor(Math.random() * (_wsJitter*2+1)) - _wsJitter>> <<set _wsStart = Math.max(_wsBufRaw, Math.min($maplim - 15000, _wsStart))>> <<set _wsLen = _wsSpanMin + Math.floor(Math.random() * (_wsSpanMax - _wsSpanMin + 1))>> <<run $worldSceneQueue.push({ id:_wsChosen, name:_wsName, approachDesc:_wsAppr, state:"pending", mapStart:_wsStart, mapEnd:_wsStart + _wsLen, approachAt:_wsStart - 1500, children:_wsKids, doneCids:[] })>> <</if>> <</for>> <<if $worldSceneQueue.length > 0>> <<set $worldScene = $worldSceneQueue[0]>> <<set $worldSceneQueueIdx = 0>> <</if>> <</if>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "worldSceneDefs">> /* 纯数据,不含函数——条件判断统一在 spawnWorldScene 内完成 */ <<set $wsDefs = { "wreck_site": { name: "沉船区", type: "explore", weight: 30, spanMin: 3000, spanMax: 8000, viewDesc: "巨大的锈蚀船体横卧在视野中央,遮蔽了海床的大片区域,散落的残骸和杂物绵延数百米,这里已是另一种意义上的礁岛。", approachDesc: "声呐信号里出现了异常密集的金属反射点——前方可能有沉船残骸。", insideDesc: "一艘大型船体横卧在海床上,锈迹斑斑,甲板已经垮塌,船舱还算完整。周围散落着各种残骸。", children: ["wreck_cargo","wreck_engine","wreck_logbook"] }, "whale_fall": { name: "鲸落", type: "explore", weight: 15, spanMin: 4000, spanMax: 10000, viewDesc: "无垠的黑暗中,一具巨大的白色骨架占据着视野——肋骨高耸如拱门,骨骸规模让人难以判断距离,这里是深海最独特的生命绿洲之一。", approachDesc: "有机物浓度骤升,水中弥漫着腐败的气息——前方应该有一具大型生物的尸骸。", insideDesc: "一具巨大的鲸鱼骸骨沉卧于此,油脂已经大部分流失,骨架上密布着以此为生的小型生物群落。这里已经是一个完整的深海生态系。", children: ["whale_oil","whale_bone","whale_parasite"] }, "ruin_cluster": { name: "水下废墟", type: "explore", weight: 12, spanMin: 5000, spanMax: 12000, viewDesc: "石砌的轮廓在探照灯下若隐若现,方正的墙角和弧形的拱门告诉你这片海床曾是人造的——海草和珊瑚已经接管了这里所有的表面。", approachDesc: "水流带来碎石和腐朽木料碎屑,声呐图像里出现了规则的直角轮廓——水下有人工建筑遗迹。", insideDesc: "大片建筑残骸沉入水底,石砌的地基和墙壁之间长满了海草和珊瑚,已经与海底融为一体。", children: ["ruin_loot","ruin_inscription","ruin_creature"] } , "ph_zone": { name: "占位区域", type: "explore", weight: 0, spanMin: 2000, spanMax: 6000, viewDesc: "(内容待填充)", approachDesc: "(内容待填充)", insideDesc: "(内容待填充)", children: ["ph_child"] } }>> /* ── 子事件定义 ── */ <<set $wsChildDefs = { "wreck_cargo": { name: "货舱探查", desc: "船体中部有一个货舱,舱门已锈蚀变形,但还能撬开。不知道里面还剩下什么。", stages: [ { desc: "货舱门挤压变形,需要点力气。撬开后能看到里面还有几个金属箱。", actions: ["用机械臂强行撬开","放弃"] }, { desc: "货舱已开,几只螃蟹从里面爬出来。金属箱保存状态不一。", actions: ["搜查所有货箱","只取表层物品"] } ], resolve: { "用机械臂强行撬开": { next:1, loot:[], text:"货舱门被强行撬开,里面的物品暴露出来。" }, "放弃": { next:-1, loot:[], text:"没有撬开,留着下次。" }, "搜查所有货箱": { next:-1, loot:[{id:"metal",qty:[2,5]},{id:"rope",qty:[1,3]},{id:"glass",qty:[0,2]},{id:"coal",qty:[1,4]},{id:"wreck_steel",qty:[1,2]}], text:"仔细搜遍了所有货箱,装备舱满载而归。" }, "只取表层物品": { next:-1, loot:[{id:"metal",qty:[1,3]},{id:"rope",qty:[0,2]}], text:"只拿了最容易取到的,动作很快。" } } }, "wreck_engine": { name: "引擎室", desc: "船尾的引擎舱还有燃料管道的残骸,锈迹中混着油污。拆卸零件需要时间,但收获可观。", stages: [ { desc: "引擎室内部结构复杂,管道和零件缠绕在一起,部分已经锈死。", actions: ["仔细拆卸零件","快速搜刮油料","放弃"] } ], resolve: { "仔细拆卸零件": { next:-1, loot:[{id:"iron",qty:[2,4]},{id:"rubber_seal",qty:[1,2]},{id:"metal",qty:[1,3]},{id:"coal",qty:[0,2]}], text:"拆卸耗时较长,但零件状态比预期好。" }, "快速搜刮油料": { next:-1, loot:[{id:"oil",qty:[1,3]},{id:"coal",qty:[1,2]}], text:"管道里还剩了一些可用的油料。" }, "放弃": { next:-1, loot:[], text:"引擎室情况复杂,决定不冒险。" } } }, "wreck_logbook": { name: "船长室文件", desc: "船桥部分结构还算完整,里面可能有值钱的文件或导航器材。", stages: [ { desc: "船长室舱门已腐朽,轻轻一推就开了。书桌的抽屉里还有密封的金属盒。", actions: ["打开金属盒","搜索整个船长室"] } ], resolve: { "打开金属盒": { next:-1, loot:[{id:"relic_log",qty:[1,1]},{id:"relic_formula",qty:[0,1]},{id:"pearl",qty:[0,1]}], text:"金属盒防水性能出色,里面的文件保存完好。" }, "搜索整个船长室": { next:-1, loot:[{id:"relic_log",qty:[1,2]},{id:"relic_notebook",qty:[0,1]},{id:"glass",qty:[0,2]},{id:"metal",qty:[1,2]}], text:"花了不少时间,但搜出了几样有价值的东西。" } } }, "whale_oil": { name: "鲸脂提取", desc: "骨架缝隙中还留存着大量凝固的鲸脂,白色半透明,散发着特殊气味。需要分几次才能提取完。", stages: [ { desc: "鲸脂已经凝固在骨骼之间,需要用热切割工具把它慢慢剥离。这是一项耗时的工作。", actions: ["开始第一轮提取","放弃"] }, { desc: "第一轮结束,容器已经装了不少。骨缝深处还有更多,但需要调整姿态才能继续。", actions: ["继续深层提取","满足现有量离开"] } ], resolve: { "开始第一轮提取": { next:1, loot:[{id:"oil",qty:[2,4]}], text:"第一轮提取完成,鲸油入舱。" }, "放弃": { next:-1, loot:[], text:"气味太浓,决定放弃。" }, "继续深层提取": { next:-1, loot:[{id:"oil",qty:[2,5]},{id:"bone_ash",qty:[1,2]}], text:"深层鲸脂品质更纯,还带出来一些骨质碎末。" }, "满足现有量离开": { next:-1, loot:[], text:"收好已有的量,离开了鲸落区。" } } }, "whale_bone": { name: "骨骼采集", desc: "鲸骨体积庞大,密度惊人。部分小骨已经与骨架脱离,适合直接采集。大型骨段需要切割工具。", stages: [ { desc: "鲸骨白森森的一片,散落的碎骨和完整骨节各有价值。", actions: ["只捡散落碎骨","尝试切割骨节"] } ], resolve: { "只捡散落碎骨": { next:-1, loot:[{id:"bone_ash",qty:[2,5]},{id:"god_bone_frag",qty:[0,1]}], text:"收集了大量碎骨,装了满满一舱。" }, "尝试切割骨节": { next:-1, loot:[{id:"bone_ash",qty:[1,3]},{id:"god_bone_frag",qty:[1,2]},{id:"fish_bone",qty:[1,3]}], text:"骨节材质特殊,切割时火花四溅,最终还是割下了几块。" } } }, "whale_parasite": { name: "寄生生物", desc: "骨架上密密麻麻地附着着各种生物。其中有些体型可观的,看起来是鲸虱或大型等足类动物。", stages: [ { desc: "骨架内部的阴影区里生活着大量奇特生物,部分根本不知道是什么物种。", actions: ["捕捉样本","用灯光驱散后采集"] } ], resolve: { "捕捉样本": { next:-1, loot:[{id:"creature_husk",qty:[1,3]},{id:"deep_eye",qty:[0,1]},{id:"jellyfluid",qty:[0,2]}], text:"捕到几只,其中有一种外形极其怪异。" }, "用灯光驱散后采集": { next:-1, loot:[{id:"bone_ash",qty:[1,2]},{id:"coral_frag",qty:[1,3]},{id:"kelp",qty:[1,2]}], text:"生物散开后,骨架上露出了很多附生的材料。" } } }, "ruin_loot": { name: "废墟搜索", desc: "残破的房间里堆积着被海水泡涨的各种物品,分辨哪些还有价值需要花点时间。", stages: [ { desc: "废墟地面散落着陶器碎片、锈蚀铁件、腐朽木板。有几个密封陶罐完整地躺在角落。", actions: ["细致搜索","只取陶罐","快速翻找"] } ], resolve: { "细致搜索": { next:-1, loot:[{id:"metal",qty:[1,4]},{id:"glass",qty:[0,2]},{id:"relic_etching",qty:[0,1]},{id:"salt_refined",qty:[0,3]},{id:"coal",qty:[0,2]}], text:"翻了很久,收获颇丰,还找到了刻有文字的碎片。" }, "只取陶罐": { next:-1, loot:[{id:"salt_refined",qty:[1,3]},{id:"sand_extract",qty:[0,2]},{id:"sea_salt_crystal",qty:[0,2]}], text:"陶罐保存完好,里面装的是精盐和提取物。" }, "快速翻找": { next:-1, loot:[{id:"metal",qty:[1,2]},{id:"coal",qty:[0,2]}], text:"没花多少时间,拿了最顺手的几样。" } } }, "ruin_inscription": { name: "碑文记录", desc: "废墟中有一面石墙保存相对完好,墙面上有浮雕和刻字,内容几乎无法辨认。", stages: [ { desc: "刻字已经严重风化,但轮廓隐约可辨。这里的文字体系看起来比较古老。", actions: ["拓印记录","尝试破译","放弃"] } ], resolve: { "拓印记录": { next:-1, loot:[{id:"relic_etching",qty:[1,1]},{id:"relic_notebook",qty:[0,1]}], text:"小心地拓印了几段,细节保留得不错。" }, "尝试破译": { next:-1, loot:[{id:"relic_etching",qty:[0,1]},{id:"relic_formula",qty:[0,1]}], text:"大部分看不懂,但几个符号像是某种配方的标注。" }, "放弃": { next:-1, loot:[], text:"太难辨认了,没有浪费时间。" } } }, "ruin_creature": { name: "废墟居民", desc: "这片废墟显然已经有生物定居。移动时搅起了沉积物,一些洞穴居民开始从暗处探头。", stages: [ { desc: "几只大型龙虾占据了最深的石缝,还有一群鱼在墙洞里进出自如。", actions: ["用诱饵套龙虾","用网驱捕鱼群","静静观察后离开"] } ], resolve: { "用诱饵套龙虾": { next:-1, loot:[{id:"lobster",qty:[1,2]},{id:"bluecrab",qty:[0,2]}], text:"两只大龙虾上当,入了笼。" }, "用网驱捕鱼群": { next:-1, loot:[{id:"grouper",qty:[1,2]},{id:"seabass",qty:[0,2]},{id:"bream",qty:[0,1]}], text:"墙洞里的鱼被惊出来,撒网捞住了好几条。" }, "静静观察后离开": { next:-1, loot:[], text:"观察了一会儿,记录下了这片废墟的生态状况。" } } }, "ph_child": { name: "占位事件", desc: "(此处为占位内容,尚未填充。)", stages: [ { desc: "(占位)", actions: ["离开"] } ], resolve: { "离开": { next:-1, loot:[], text:"离开了这里。" } } } }>> <</widget>> <</nobr>>
<<nobr>> <<widget "resolveWsChild">> /* 始终重新初始化,防止序列化损坏 */ <<worldSceneDefs>> <<if !$wsChild>><<return>><</if>> <<set _action = $args[0]>> <<set _cid = $wsChild.id>> <<if !$wsChildDefs[_cid]>> <<set $wsChild = null>><<return>> <</if>> <<set _cDef = $wsChildDefs[_cid]>> <<if !_cDef.resolve[_action]>> <<set $wsChild = null>><<return>> <</if>> <<set _result = _cDef.resolve[_action]>> /* 发放战利品 */ <<set _wsLog = $wsChild.lootLog>> <<if _result.loot>> <<for _rli = 0; _rli < _result.loot.length; _rli++>> <<set _rl = _result.loot[_rli]>> <<set _rlo = _rl.qty[0]>> <<set _rhi = _rl.qty[1]>> <<set _rq = _rlo + Math.floor(Math.random() * (_rhi - _rlo + 1))>> <<if _rq > 0>> <<additem _rl.id _rq>> <<if $items && $items[_rl.id]>> <<set _wsLog = _wsLog + $items[_rl.id].name + "×" + _rq + " ">> <</if>> <</if>> <</for>> <</if>> /* 将结果文本同时写入持久变量(null后依然可读)*/ <<set $wsLastActionText = _result.text>> <<set $wsLastActionLoot = _wsLog>> /* 进入下一阶段或关闭 */ <<set _nextIdx = _result.next>> <<if _nextIdx < 0 || _nextIdx >= _cDef.stages.length>> <<if $worldScene>> <<if !$worldScene.doneCids>><<set $worldScene.doneCids = []>><</if>> <<set _alreadyDone = false>> <<for _dci = 0; _dci < $worldScene.doneCids.length; _dci++>> <<if $worldScene.doneCids[_dci] === _cid>><<set _alreadyDone = true>><</if>> <</for>> <<if !_alreadyDone>><<run $worldScene.doneCids.push(_cid)>><</if>> <</if>> <<set $wsChild = null>> <<else>> <<set _ns = _cDef.stages[_nextIdx]>> <<set $wsChild.stageIdx = _nextIdx>> <<set $wsChild.stageDesc = _result.text + " " + _ns.desc>> <<set $wsChild.actions = _ns.actions>> <<set $wsChild.lootLog = _wsLog>> <<set $wsChild.actionText = _result.text>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "largeSceneDefs">> <<set $largeDefs = { wreck_graveyard: { name: "沉船墓场", viewDesc: "这片海床密布大小不一的船体残骸,有的已完全碎裂,有的依然保持完整轮廓,规模之大让人觉得这里曾发生过什么无法言说的事。", leaveHint: "残骸密度开始减少,那片沉船墓场已经逐渐落在身后。", approachHint: [ "海床上开始出现零散的金属碎片和腐朽木料,锈迹与腐木混在沙层里,像是某场灾难的余烬。", "声呐回波开始变得复杂,前方似乎有密集的大型硬质结构——可能是大规模沉船区域的外缘。" ], dMin: 80, dMax: 800, zoneList: [ {name:"货船残骸", wsType:"wreck_site"}, {name:"军舰沉骸", wsType:"wreck_site"}, {name:"古帆船", wsType:"wreck_site"}, {name:"集装箱堆", wsType:"wreck_site"} ] }, vent_complex: { name: "热液喷口群", viewDesc: "多处热液喷口按某种规律分布在这片海床,各自形成独立生态岛屿,喷口之间是死寂的灰色荒原。", leaveHint: "水温重新降了下来,热液活动区已在身后,深处恢复了一贯的冰冷寂静。", approachHint: [ "水温开始轻微升高,舷窗外有细小气泡从海床裂缝里冒出,带着轻微的硫磺气息。", "声呐探测到海床起伏异常,有几处高温异常点正在前方聚集——是热液活跃区的边缘。" ], dMin: 400, dMax: 10000, zoneList: [ {name:"边缘喷口", wsType:"whale_fall"}, {name:"主喷口群", wsType:"whale_fall"}, {name:"矿物堆积区", wsType:"whale_fall"} ] }, ruin_district: { name: "古城遗迹带", viewDesc: "人工建筑的遗迹绵延在海床上,方正墙角和弧形拱门告诉你这里曾是聚居地,如今只剩整齐排列的基础和墙体轮廓。", leaveHint: "石砌的痕迹逐渐稀疏,那片水下古城遗迹消失在了探照灯的照射范围之外。", approachHint: [ "海床上开始出现奇怪的直线条纹和修整痕迹,石块形状过于规整,不像是自然形成的。", "前方零散分布着方正的石块,它们的排列角度太过一致——水流和地壳运动不会产生这样的规律。" ], dMin: 20, dMax: 400, zoneList: [ {name:"外围街区", wsType:"ruin_cluster"}, {name:"中心广场", wsType:"ruin_cluster"}, {name:"高台建筑", wsType:"ruin_cluster"}, {name:"地下通道入口", wsType:"ruin_cluster"} ] }, sunken_city: { name: "沉没城市", viewDesc: "(沉没城市 viewDesc 待填充)", leaveHint: "(沉没城市 leaveHint 待填充)", approachHint: [ "(沉没城市 approachHint 待填充)" ], dMin: 20, dMax: 10000, zonePool: [ {name:"商场", wsType:"ph_zone"}, {name:"公寓", wsType:"ph_zone"}, {name:"广场", wsType:"ph_zone"}, {name:"公园", wsType:"ph_zone"}, {name:"工厂", wsType:"ph_zone"}, {name:"街道", wsType:"ph_zone"}, {name:"车辆", wsType:"ph_zone"}, {name:"图书馆", wsType:"ph_zone"} ] }, seagrass_pasture: { name: "牧场", viewDesc: "(牧场 viewDesc 待填充)", leaveHint: "(牧场 leaveHint 待填充)", approachHint: [ "(牧场 approachHint 待填充)" ], dMin: 20, dMax: 200, zonePool: [ {name:"小屋", wsType:"ph_zone"}, {name:"鱼群", wsType:"ph_zone"}, {name:"海牛", wsType:"ph_zone"}, {name:"鲨鱼", wsType:"ph_zone"}, {name:"静谧的尸骨", wsType:"ph_zone"}, {name:"漂浮光", wsType:"ph_zone"} ] }, wreck_necropolis: { name: "沉船坟场", viewDesc: "(沉船坟场 viewDesc 待填充)", leaveHint: "(沉船坟场 leaveHint 待填充)", approachHint: [ "(沉船坟场 approachHint 待填充)" ], dMin: 20, dMax: 10000, zonePool: [ {name:"木帆船", wsType:"ph_zone"}, {name:"渔船", wsType:"ph_zone"}, {name:"军舰", wsType:"ph_zone"}, {name:"游轮", wsType:"ph_zone"}, {name:"小船", wsType:"ph_zone"} ] }, solid_vortex: { name: "固态漩涡", viewDesc: "(固态漩涡 viewDesc 待填充)", leaveHint: "(固态漩涡 leaveHint 待填充)", approachHint: [ "(固态漩涡 approachHint 待填充)" ], dMin: 200, dMax: 600, zoneList: [ {name:"人鱼监狱", wsType:"ph_zone"}, {name:"鲸落", wsType:"ph_zone"}, {name:"被绞死的生物",wsType:"ph_zone"} ] }, eternal_reef: { name: "永夜礁石", viewDesc: "(永夜礁石 viewDesc 待填充)", leaveHint: "(永夜礁石 leaveHint 待填充)", approachHint: [ "(永夜礁石 approachHint 待填充)" ], dMin: 20, dMax: 200, zoneList: [ {name:"海豚坟场", wsType:"ph_zone"}, {name:"新生海豚", wsType:"ph_zone"}, {name:"祝福珊瑚", wsType:"ph_zone"}, {name:"荧光生物", wsType:"ph_zone"} ] }, taumaas: { name: "陶玛斯", viewDesc: "(陶玛斯 viewDesc 待填充)", leaveHint: "(陶玛斯 leaveHint 待填充)", approachHint: [ "(陶玛斯 approachHint 待填充)" ], dMin: 20, dMax: 10000, zoneList: [ {name:"陶玛斯对话", wsType:"ph_zone"}, {name:"祝福生物群", wsType:"ph_zone"}, {name:"极光", wsType:"ph_zone"} ] }, current_confluence: { name: "洋流汇聚", viewDesc: "(洋流汇聚 viewDesc 待填充)", leaveHint: "(洋流汇聚 leaveHint 待填充)", approachHint: [ "(洋流汇聚 approachHint 待填充)" ], dMin: 20, dMax: 10000, zoneList: [ {name:"海龟群", wsType:"ph_zone"}, {name:"发光浮游生物",wsType:"ph_zone"}, {name:"欧律比亚", wsType:"ph_zone"} ] }, vent_cluster: { name: "热泉群", viewDesc: "(热泉群 viewDesc 待填充)", leaveHint: "(热泉群 leaveHint 待填充)", approachHint: [ "(热泉群 approachHint 待填充)" ], dMin: 200, dMax: 10000, zoneList: [ {name:"热泉管虫", wsType:"ph_zone"}, {name:"巨岩龙虾", wsType:"ph_zone"}, {name:"热泉发光液", wsType:"ph_zone"} ] } }>> <</widget>> <</nobr>>
<<nobr>> <<widget "spawnLargeScene">> <<if !$largeScene || $largeScene === 0>> <<largeSceneDefs>> <<set _lsCands = []>> <<if $depthdeep >= 80 && $depthdeep <= 800 && ($maptype === "sand" || $maptype === "flat")>> <<if $depthdeep >= 20 && ($maptype === "sand" || $maptype === "flat" || $maptype === "cliff" || $maptype === "grass" || $maptype === "reef" || $maptype === "forest")>> <<set _lsCands[_lsCands.length] = "sunken_city">> <</if>> <<if $depthdeep >= 20 && $depthdeep <= 200 && $maptype === "grass">> <<set _lsCands[_lsCands.length] = "seagrass_pasture">> <</if>> <<if $depthdeep >= 20 && ($maptype === "sand" || $maptype === "flat" || $maptype === "cliff" || $maptype === "grass" || $maptype === "reef" || $maptype === "forest")>> <<set _lsCands[_lsCands.length] = "wreck_necropolis">> <</if>> <<if $depthdeep >= 200 && $depthdeep <= 600 && $maptype === "forest">> <<set _lsCands[_lsCands.length] = "solid_vortex">> <</if>> <<if $depthdeep >= 20 && $depthdeep <= 200 && $maptype === "reef">> <<set _lsCands[_lsCands.length] = "eternal_reef">> <</if>> <<if $depthdeep >= 20>> <<set _lsCands[_lsCands.length] = "taumaas">> <</if>> <<if $depthdeep >= 20>> <<set _lsCands[_lsCands.length] = "current_confluence">> <</if>> <<if $depthdeep >= 200 && ($maptype === "flat" || $maptype === "cliff")>> <<set _lsCands[_lsCands.length] = "vent_cluster">> <</if>> <<set _lsCands[_lsCands.length] = "wreck_graveyard">> <</if>> <<if $depthdeep >= 400 && ($maptype === "flat" || $maptype === "cliff")>> <<set _lsCands[_lsCands.length] = "vent_complex">> <</if>> <<if $depthdeep >= 20 && $depthdeep <= 400 && ($maptype === "sand" || $maptype === "flat" || $maptype === "reef")>> <<set _lsCands[_lsCands.length] = "ruin_district">> <</if>> <<if _lsCands.length > 0 && Math.random() <= 0.15>> <<set _lsId = _lsCands[Math.floor(Math.random() * _lsCands.length)]>> <<set _lsDef = $largeDefs ? $largeDefs[_lsId] : null>> <<if _lsDef && _lsDef.zonePool && _lsDef.zonePool.length > 0>> <<set _lsPool = _lsDef.zonePool.slice()>> <<set _lsPickN = 3 + Math.floor(Math.random() * 2)>> <<for _lsi = _lsPool.length - 1; _lsi > 0; _lsi-->> <<set _lsJ = Math.floor(Math.random() * (_lsi + 1))>> <<set _lsTmp = _lsPool[_lsi]>> <<set _lsPool[_lsi] = _lsPool[_lsJ]>> <<set _lsPool[_lsJ] = _lsTmp>> <</for>> <<set _lsDef = { name: _lsDef.name, viewDesc: _lsDef.viewDesc, leaveHint: _lsDef.leaveHint, approachHint: _lsDef.approachHint, zoneList: _lsPool.slice(0, _lsPickN) }>> <</if>> <<if _lsDef && _lsDef.zoneList && _lsDef.zoneList.length > 0>> /* 有效长度 = min(900, floor(地形显示长度 × 60%)),最小200 */ <<set _lsTerrainLen = Math.floor($maplim / 50)>> <<set _lsMaxValid = Math.min(900, Math.floor(_lsTerrainLen * 0.6))>> <<if _lsMaxValid >= 200>> <<set _lsValidUnits = 200 + Math.floor(Math.random() * (_lsMaxValid - 200 + 1))>> <<set _lsValidRaw = _lsValidUnits * 50>> <<set _lsApprRaw = 2500>> <<set _lsLeaveRaw = 2500>> <<set _lsTotalRaw = _lsApprRaw + _lsValidRaw + _lsLeaveRaw>> <<set _lsBufRaw = 10000>> <<set _lsPlaceMax = $maplim - _lsTotalRaw - _lsBufRaw>> <<if _lsPlaceMax > _lsBufRaw>> <<set _lsOrigin = _lsBufRaw + Math.floor(Math.random() * (_lsPlaceMax - _lsBufRaw + 1))>> <<set _lsApprEnd = _lsOrigin + _lsApprRaw>> <<set _lsActiveEnd = _lsApprEnd + _lsValidRaw>> <<set _lsLeaveEnd = _lsActiveEnd + _lsLeaveRaw>> /* Zone 坐标:均匀 ± 20% 抖动 */ <<set _lzCount = _lsDef.zoneList.length>> <<set _lzSpacing = Math.floor(_lsValidRaw / _lzCount)>> <<set _lzArr = []>> <<for _lzi = 0; _lzi < _lzCount; _lzi++>> <<set _lzBase = _lsApprEnd + Math.floor(_lzSpacing * (_lzi + 0.5))>> <<set _lzJitter = Math.floor(_lzSpacing * 0.2)>> <<set _lzAt = _lzBase + Math.floor(Math.random() * (_lzJitter * 2 + 1)) - _lzJitter>> <<set _lzAt = Math.max(_lsApprEnd + 500, Math.min(_lsActiveEnd - 500, _lzAt))>> <<set _lzd = _lsDef.zoneList[_lzi]>> <<set _lzArr[_lzArr.length] = {name:_lzd.name, zoneAt:_lzAt, wsType:_lzd.wsType, st:"pending"}>> <</for>> <<set _lsHints = (_lsDef.approachHint && _lsDef.approachHint.length > 0) ? _lsDef.approachHint : ["前方海域出现了异常。"]>> <<set _lsPickHint = _lsHints[Math.floor(Math.random() * _lsHints.length)]>> <<set $largeScene = { id:_lsId, name:_lsDef.name, viewDesc:_lsDef.viewDesc, approachHint:_lsPickHint, leaveHint:(_lsDef.leaveHint || ""), state:"approaching", approachEnd:_lsApprEnd, activeEnd:_lsActiveEnd, leaveEnd:_lsLeaveEnd, zones:_lzArr, activeZone:-1 }>> <</if>> <</if>> <</if>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> /* ══════════════════════════════════════════════ diveInit:进入仓外时按当前深度初始化消耗参数 ══════════════════════════════════════════════ */ <<widget "diveInit">> <<set $diveOxygen = ($diveOxygenMax || 100)>> <<set $diveCold = 0>> <<set $diveStepsOut = 0>> <<set $diveLog = "">> <<set $diveChainSub = []>> <<set $diveIdx = 0>> <<set $divingMode = true>> <<set $diveArmBlocked = {}>> <<set $diveArmCleared = {}>> /* 恢复持久化链条(worldScene 内)或重新生成 */ <<if $worldScene && $worldScene.state === "inside" && $worldScene.savedChain && $worldScene.savedChain.length > 1>> <<set $diveChain = $worldScene.savedChain>> <<set $diveIdx = 0>> <<set $diveChainTerrain = $maptype>> <<else>> <<diveChainGen>> <</if>> /* 场景简介:描述玩家从哪种环境出舱 */ <<set _diTerrainName = $mapinfo[$maptype] ? $mapinfo[$maptype].type : "未知地形">> <<set _diDepthDesc = ($depth <= 10) ? "水面附近" : ($depth <= 50) ? "浅水区" : ($depth <= 200) ? "中深水域" : "深海">> <<set _diSceneCtx = "">> <<if $largeScene && typeof $largeScene === "object" && $largeScene.state === "active">> <<set _diSceneCtx = ",正处于" + $largeScene.name + "范围内">> <<elseif $worldScene && $worldScene.state === "inside">> <<set _diSceneCtx = ",锚定于" + $worldScene.name>> <</if>> <<set $diveIntro = "你推开出仓舱门,进入" + _diDepthDesc + "(" + $depth + "m)的" + _diTerrainName + _diSceneCtx + "。" + ($diveOxygen < 120 ? "氧气有限,需要尽快行动。" : "探照灯在黑暗中划出一道光锥,周围轮廓逐渐清晰。")>> <<set $diveShowIntro = true>> /* 按深度设定每步消耗: ≤50m → ~33步 约99分钟 ≤300m → ~10步 约30分钟 >300m → 极速消耗(无装备不可出) */ <<if $depth <= 50>> <<set $diveStepCostO2 = 3>> <<set $diveStepTime = 3>> <<elseif $depth <= 300>> <<set $diveStepCostO2 = 10>> <<set $diveStepTime = 3>> <<else>> <<set $diveStepCostO2 = 30>> <<set $diveStepTime = 3>> <</if>> /* 主线 auto 触发检查(每次下水)*/ <<if !$questChain>><<questDefs>><</if>> <<if $questProgress < $questChain.length && $questChain[$questProgress].trigger.type === "auto">> <<questCheck "auto">> <</if>> <</widget>> /* ══════════════════════════════════════════════ diveStep:深入一步的消耗结算 ══════════════════════════════════════════════ */ <<widget "diveStep">> /* 氧气消耗 */ <<set $diveOxygen = Math.max(0, $diveOxygen - $diveStepCostO2)>> /* 步数计数 */ <<set $diveStepsOut = $diveStepsOut + 1>> /* 时间流逝 */ <<set $timepass = $diveStepTime>> <<time>> /* 水温估算(浅水用环境温度,深水大幅下降) */ <<if $depth <= 50>> <<set _dwt = $worldtem>> <<elseif $depth <= 200>> <<set _dwt = Math.floor($worldtem * 0.6)>> <<else>> <<set _dwt = Math.max(0, Math.floor($worldtem / 5))>> <</if>> /* 冷压积累 */ <<if _dwt <= 0>> <<set $diveCold = Math.min(100, $diveCold + 20)>> <<elseif _dwt <= 5>> <<set $diveCold = Math.min(100, $diveCold + 12)>> <<elseif _dwt <= 15>> <<set $diveCold = Math.min(100, $diveCold + 6)>> <<elseif _dwt <= 20>> <<set $diveCold = Math.min(100, $diveCold + 2)>> <</if>> /* 冷压造成的实际效果 */ <<if $diveCold >= 80>> <<set $life = Math.max(0, $life - 5)>> <<set $power = Math.max(0, $power - 5)>> <<elseif $diveCold >= 50>> <<set $power = Math.max(0, $power - 3)>> <</if>> /* 氧气耗尽标记(UI 层捕获并强制显示返回)*/ <<if $diveOxygen <= 0>><<set $diveO2Dead = true>><</if>> /* 持久效果检查 */ <<checkEnvEffects>> /* 小型事件调度(无活跃事件时尝试触发) */ <<if !$activeSmallEvent>> <<spawnSmallEvent "outside">> <<if $pendingEvent>> <<set $activeSmallEvent = $pendingEvent>> <<set $pendingEvent = null>> <</if>> <</if>> /* 战斗触发(约3%/步,无小型事件且无战斗时)*/ <<if !$activeSmallEvent && !$activeCombat>> <<if Math.random() < 0.03>> <<spawnCombat>> <</if>> <</if>> <</widget>> /* ══════════════════════════════════════════════ diveReturn:返回消耗一次性结算(0.6倍去程) ══════════════════════════════════════════════ */ <<widget "diveReturn">> <<set _retO2 = Math.ceil($diveStepsOut * $diveStepCostO2 * 0.6)>> <<set _retTime = Math.max(1, Math.ceil($diveStepsOut * $diveStepTime * 0.6))>> /* 持久化:将当前 diveChain 状态(含已完成节点)同步回 worldScene */ <<if $worldScene && $worldScene.state === "inside">> <<set $worldScene.savedChain = $diveChain>> <</if>> <<set $diveOxygen = Math.max(0, $diveOxygen - _retO2)>> <<set $timepass = _retTime>> <<time>> /* 氧气耗尽惩罚 */ <<if $diveOxygen <= 0>> <<set $life = Math.max(0, $life - 25)>> <<set $san = Math.max(0, $san - 15)>> <</if>> /* 冷压结算 */ <<if $diveCold >= 80>> <<set $life = Math.max(0, $life - 10)>> <<elseif $diveCold >= 50>> <<set $power = Math.max(0, $power - 8)>> <</if>> /* 重置状态 */ <<set $divingMode = false>> <<set $diveStepsOut = 0>> <<set $diveOxygen = 100>> <<set $diveCold = 0>> <<set $diveChain = []>> <<set $diveChainSub = []>> <<set $diveIdx = 0>> <<set $diveInteractResult = "">> <<set $diveO2Dead = false>> <<set $wsLastActionText = "">> <<set $wsLastActionLoot = "">> <</widget>> /* ══════════════════════════════════════════════ diveWarn:计算预警等级,存入 _diveWarn 0=安全 1=黄色(2步冗余) 2=红色(仅剩返程量) ══════════════════════════════════════════════ */ <<widget "diveWarn">> <<set _retNeeded = Math.ceil($diveStepsOut * $diveStepCostO2 * 0.6)>> <<set _bufferO2 = _retNeeded + ($diveStepCostO2 * 2)>> <<if $diveOxygen <= _retNeeded>> <<set _diveWarn = 2>> <<elseif $diveOxygen <= _bufferO2>> <<set _diveWarn = 1>> <<else>> <<set _diveWarn = 0>> <</if>> <</widget>> /* ══════════════════════════════════════════════ diveLight:计算潜水环境光照等级 → _diveLightLevel (深度覆盖水面光照;结合 view widget 的时段/天气逻辑) ══════════════════════════════════════════════ */ <<widget "diveLight">> /* 深度优先判定(与 view widget 逻辑保持一致)*/ <<if $depth > 1000>> <<set _diveLightLevel = "dark">> <<elseif $depth > 300>> <<set _diveLightLevel = "dim">> <<if Math.random() < 0.3>><<set _diveLightLevel = "dark">><</if>> <<elseif $depth > 80>> <<set _diveLightLevel = "dim">> <<else>> /* 浅水:继承表面光照计算 */ <<if $showhour >= 7 && $showhour < 17>> <<set _dlTime = "day">> <<elseif ($showhour >= 5 && $showhour < 7) || ($showhour >= 17 && $showhour < 19)>> <<set _dlTime = "dusk">> <<elseif $showhour >= 5 && $showhour < 7>> <<set _dlTime = "dawn">> <<else>> <<set _dlTime = "night">> <</if>> <<set _dlKey = _dlTime + "_" + $viewweather[$weather]>> <<if $viewlight && $viewlight.bright && $viewlight.bright.hasOwnProperty(_dlKey)>> <<set _diveLightLevel = "bright">> <<elseif $viewlight && $viewlight.hazy && $viewlight.hazy.hasOwnProperty(_dlKey)>> <<set _diveLightLevel = "hazy">> <<elseif $viewlight && $viewlight.dim && $viewlight.dim.hasOwnProperty(_dlKey)>> <<set _diveLightLevel = "dim">> <<else>> <<set _diveLightLevel = "dark">> <</if>> <</if>> <</widget>> /* ══════════════════════════════════════════════ diveChainGen:进入时预生成 $diveChain 结构:[{type,id,desc?,terrain?,visited}] type: "frag" | "scene" | "fork" ══════════════════════════════════════════════ */ <<widget "diveChainGen">> <<diveSceneDefs>> <<diveLight>> /* 确定当前地形键:优先 worldScene,其次 largeScene 区域,最后地图地形 */ <<set _dct = $maptype>> <<if $worldScene && $worldScene.state === "inside">> <<set _dct = $maptype>> /* 先取地图基础地形 */ <<if $worldScene.id === "wreck_site">><<set _dct = "wreck">><</if>> <<if $worldScene.id === "whale_fall">><<set _dct = "sand">><</if>> <<if $worldScene.id === "ruin_cluster">><<set _dct = "flat">><</if>> <</if>> /* largeScene 额外覆盖:处于大场景中时在链开头插入场景描述节点 */ <<set _dcLargeDesc = "">> <<if $largeScene && typeof $largeScene === "object" && $largeScene.state === "active" && $largeScene.viewDesc>> <<set _dcLargeDesc = $largeScene.viewDesc>> <</if>> /* 取场景池和碎片池,找不到则用 default */ <<set _dcScenes = $diveSceneDefs[_dct] ? clone($diveSceneDefs[_dct]) : []>> <<set _dcFrags = $diveFragDefs[_dct] ? clone($diveFragDefs[_dct]) : clone($diveFragDefs.default)>> /* 洗牌碎片池 */ <<set _dcFragShuf = []>> <<for _dsi = _dcFrags.length - 1; _dsi > 0; _dsi-->> <<set _dsr = Math.floor(Math.random() * (_dsi + 1))>> <<set _dstmp = _dcFrags[_dsi]>> <<set _dcFrags[_dsi] = _dcFrags[_dsr]>> <<set _dcFrags[_dsr] = _dstmp>> <</for>> /* 洗牌场景池 */ <<for _dsi = _dcScenes.length - 1; _dsi > 0; _dsi-->> <<set _dsr = Math.floor(Math.random() * (_dsi + 1))>> <<set _dstmp = _dcScenes[_dsi]>> <<set _dcScenes[_dsi] = _dcScenes[_dsr]>> <<set _dcScenes[_dsr] = _dstmp>> <</for>> /* 场景数量:2-3个(深度越深越少)*/ <<if $depth > 300>> <<set _dcSceneCount = 1>> <<elseif $depth > 100>> <<set _dcSceneCount = 2>> <<else>> <<set _dcSceneCount = 2 + Math.floor(Math.random() * 2)>> <</if>> <<if _dcSceneCount > _dcScenes.length>><<set _dcSceneCount = _dcScenes.length>><</if>> /* 碎片数量:4-6个,分散在场景之间 */ <<set _dcFragCount = 4 + Math.floor(Math.random() * 3)>> <<if _dcFragCount > _dcFrags.length>><<set _dcFragCount = _dcFrags.length>><</if>> /* 构建 chain:frag→scene→frag→[scene→frag] 交替 */ <<set $diveChain = []>> <<set _dcFi = 0>> <<set _dcSi = 0>> /* 开头放2-3个碎片 */ <<set _dcLeadFrags = 2 + Math.floor(Math.random() * 2)>> <<if _dcLeadFrags > _dcFragCount>><<set _dcLeadFrags = _dcFragCount>><</if>> <<for _dcx = 0; _dcx < _dcLeadFrags; _dcx++>> <<if _dcFi < _dcFrags.length>> <<run $diveChain.push({type:"frag", id:"frag_"+_dcFi, text:_dcFrags[_dcFi], visited:false})>> <<set _dcFi++>> <</if>> <</for>> /* 交替放置:场景→2-3碎片 */ <<for _dcsi = 0; _dcsi < _dcSceneCount; _dcsi++>> <<if _dcSi < _dcScenes.length>> <<set _dcScene = _dcScenes[_dcSi]>> <<set _dcPfxPool = $diveLightPfx[_diveLightLevel] || $diveLightPfx.dim>> <<set _dcPfx = _dcPfxPool[Math.floor(Math.random() * _dcPfxPool.length)]>> <<set _dcSfxPool = $diveLightSfx[_diveLightLevel] || $diveLightSfx.dim>> <<set _dcComposed = _dcPfx + _dcScene.baseDesc>> <<if Math.random() < 0.5>> <<set _dcComposed += _dcSfxPool[Math.floor(Math.random() * _dcSfxPool.length)]>> <</if>> <<set _dcBlocked = _dcScene.blocked ? _dcScene.blocked : []>> <<run $diveChain.push({type:"scene", id:_dcScene.id, desc:_dcComposed, elements:_dcScene.elements, blocked:_dcBlocked, visited:false})>> <<if _dcBlocked.length > 0>> <<if !$diveArmBlocked>><<set $diveArmBlocked = {}>><</if>> <<set $diveArmBlocked[_dcScene.id] = _dcBlocked>> <</if>> <<set _dcSi++>> <</if>> <<set _dcAfterFrags = 2 + Math.floor(Math.random() * 2)>> <<for _dcx = 0; _dcx < _dcAfterFrags; _dcx++>> <<if _dcFi < _dcFrags.length>> <<run $diveChain.push({type:"frag", id:"frag_"+_dcFi, text:_dcFrags[_dcFi], visited:false})>> <<set _dcFi++>> <</if>> <</for>> <</for>> /* 大型场景描述节点:作为第一个节点 */ <<if _dcLargeDesc>> <<run $diveChain.unshift({type:"scene", id:"large_overview", desc:_dcLargeDesc, elements:[], visited:false})>> <</if>> /* ── worldScene 子事件注入:固定在第3、6、9节(0-based: 2,5,8)── */ <<if $worldScene && $worldScene.state === "inside" && $worldScene.children && $worldScene.children.length > 0>> <<if !$wsChildDefs>><<worldSceneDefs>><</if>> /* 确定待注入的 children(排除已完成的)*/ <<set _dcWsCh = []>> <<for _dcWi = 0; _dcWi < $worldScene.children.length; _dcWi++>> <<set _dcWCid = $worldScene.children[_dcWi]>> <<set _dcWDone = false>> <<if $worldScene.doneCids>> <<for _dcWdi = 0; _dcWdi < $worldScene.doneCids.length; _dcWdi++>> <<if $worldScene.doneCids[_dcWdi] === _dcWCid>><<set _dcWDone = true>><</if>> <</for>> <</if>> <<if !_dcWDone>><<run _dcWsCh.push(_dcWCid)>><</if>> <</for>> /* 在第 3、6、9 节位置(目标0-based索引 2,5,8)插入 wschild 节点 */ <<set _dcSlots = [2, 5, 8]>> <<for _dcSli = 0; _dcSli < _dcSlots.length && _dcSli < _dcWsCh.length; _dcSli++>> <<set _dcSlot = _dcSlots[_dcSli]>> <<set _dcWCid = _dcWsCh[_dcSli]>> <<set _dcWDef = $wsChildDefs[_dcWCid]>> <<if _dcWDef>> <<set _dcWNode = {type:"wschild", id:_dcWCid, name:_dcWDef.name, desc:_dcWDef.desc, stageIdx:0, stageDesc:_dcWDef.stages[0].desc, actions:_dcWDef.stages[0].actions, done:false, visited:false}>> /* splice 插入:如果链条够长就插,否则 push */ <<if _dcSlot < $diveChain.length>> <<run $diveChain.splice(_dcSlot, 0, _dcWNode)>> <<else>> <<run $diveChain.push(_dcWNode)>> <</if>> <</if>> <</for>> <</if>> /* 末尾终点标记 */ <<run $diveChain.push({type:"end", id:"end", visited:false})>> <<set $diveIdx = 0>> <<set $diveChainTerrain = _dct>> /* ── 持久化:将链条保存到 worldScene(下次下水恢复)── */ <<if $worldScene && $worldScene.state === "inside">> <<set $worldScene.savedChain = $diveChain>> <<set $worldScene.savedDoneNodes = $worldScene.savedDoneNodes || {}>> <</if>> <</widget>> /* ══════════════════════════════════════════════ diveInteract:与当前场景节点的元素交互 args[0] = element name (string) 结果写入 $diveChain[$diveIdx].done[] 全部元素完成后 → 写入 $worldScene.doneCids ══════════════════════════════════════════════ */ <<widget "diveInteract">> <<diveInteractDefs>> <<set _diElem = $args[0]>> <<set _diNode = $diveChain[$diveIdx]>> <<if !_diNode>><<return>><</if>> /* 标记该元素已处理 */ <<if !_diNode.done>><<set $diveChain[$diveIdx].done = []>><</if>> <<run $diveChain[$diveIdx].done.push(_diElem)>> /* 发放战利品 */ <<set _diDef = $diveInteractDefs[_diElem]>> <<set _diLog = "">>\n<<if _diDef && _diDef.loot>> <<for _dili = 0; _dili < _diDef.loot.length; _dili++>> <<set _dil = _diDef.loot[_dili]>> <<set _dilq = _dil.qty[0] + Math.floor(Math.random() * (_dil.qty[1] - _dil.qty[0] + 1))>> <<if _dilq > 0>> <<additem _dil.id _dilq>> <<if $items && $items[_dil.id]>> <<set _diLog = _diLog + $items[_dil.id].name + "×" + _dilq + " ">> <</if>> <</if>> <</for>> <</if>> /* 记录行动文本 → 写入 diveInteractResult(持续显示直到玩家确认)*/ <<set _diText = (_diDef && _diDef.text) ? _diDef.text : "你检查了" + _diElem + ",没有发现特别的东西。">> <<if _diLog>><<set _diText = _diText + " → 获得:" + _diLog>><</if>> <<set $diveInteractResult = _diText>> <<set $diveLog = "">> /* 小量额外氧气消耗(每次交互 +1 步)*/ <<set $diveOxygen = Math.max(0, $diveOxygen - 1)>> /* 检查是否全部元素都已处理 → 写入 worldScene.doneCids */ <<if $worldScene && $worldScene.state === "inside" && _diNode.elements>> <<set _diAllDone = true>> <<for _daei = 0; _daei < _diNode.elements.length; _daei++>> <<set _daElem = _diNode.elements[_daei]>> <<set _daFound = false>> <<if _diNode.done>> <<for _dadi = 0; _dadi < _diNode.done.length; _dadi++>> <<if _diNode.done[_dadi] === _daElem>><<set _daFound = true>><</if>> <</for>> <</if>> <<if !_daFound>><<set _diAllDone = false>><</if>> <</for>> <<if _diAllDone>> <<if !$worldScene.doneCids>><<set $worldScene.doneCids = []>><</if>> <<set _dcAlready = false>> <<for _dcdi = 0; _dcdi < $worldScene.doneCids.length; _dcdi++>> <<if $worldScene.doneCids[_dcdi] === _diNode.id>><<set _dcAlready = true>><</if>> <</for>> <<if !_dcAlready>><<run $worldScene.doneCids.push(_diNode.id)>><</if>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "diveSceneDefs">> /* ── 光照前缀池(按 _diveLightLevel 取一条) ── */ <<set $diveLightPfx = { bright: ["光线通透,","清亮的光穿透水体,","视线开阔,"], hazy: ["光线朦胧,","散射的光晕笼罩四周,","能见度尚可,"], dim: ["光线昏暗,","探照灯照出一片昏黄的锥形,","周围的轮廓若隐若现,"], dark: ["黑暗几乎是绝对的,","探照灯只能照亮眼前几米,","深渊的黑暗将一切吞没,"] }>> /* ── 光照后缀池(50%概率附加) ── */ <<set $diveLightSfx = { bright: ["水草随着微弱的水流轻轻摇曳。","远处的轮廓清晰可辨。"], hazy: ["细小颗粒在光柱里漂浮。","某些东西在光晕外若隐若现。"], dim: ["细沙被搅起后缓缓沉落。","光线边缘模糊成黑暗。"], dark: ["耳边只有自己的呼吸声。","什么都看不到,只能凭感觉前进。"] }>> /* ── 珊瑚礁场景池 ── */ <<set $diveSceneDefs = { reef: [ {id:"reef_narrow_passage", baseDesc:"珊瑚群在两侧几乎触碰到肩膀,缝隙里偶有雀鲷快速穿过,你必须侧身通行。", elements:["珊瑚","雀鲷","缝隙"]}, {id:"reef_coral_arch", baseDesc:"一道天然的珊瑚拱门横跨在前方,拱门内侧覆着海葵和管虫,细长的触手随水流微微颤动。", elements:["珊瑚拱门","海葵","管虫"]}, {id:"reef_fish_school", baseDesc:"一大群小鱼突然从左侧涌来,密集到几乎遮住视线,它们绕过你继续前行,只留下水流扰动。", elements:["鱼群","扰动"]}, {id:"reef_sand_clearing", baseDesc:"珊瑚群在这里让出了一片开阔的沙地,散落着碎贝壳和几根白色的细枝状珊瑚残骸。", elements:["沙地","贝壳","珊瑚残骸"]}, {id:"reef_eel_den", baseDesc:"一条花斑裸胸鳝把脑袋伸出礁穴,黑色的眼睛盯着你看了片刻,然后缩回了黑暗。", elements:["礁穴","裸胸鳝"]} ], sand: [ {id:"sand_flat_expanse", baseDesc:"无边无际的平坦沙海延伸到视线尽头,偶尔有沙鳐半埋在沙中,只露出眼睛。", elements:["沙海","沙鳐"]}, {id:"sand_debris_field", baseDesc:"这片区域散落着大量碎石和锈蚀的金属残片,来源不明,也许曾经有东西在这里失事。", elements:["碎石","金属残片"]}, {id:"sand_ripple_field", baseDesc:"规律的沙纹延伸数十米,像是被什么巨大的东西扫过,起伏的波纹依然清晰。", elements:["沙纹","波纹"]} ], flat: [ {id:"flat_rock_ledge", baseDesc:"岩质海床在这里形成了一道低矮的石脊,石脊上长满了石蛏和藤壶,裂缝里不时有小蟹探出螯。", elements:["石脊","石蛏","蟹"]}, {id:"flat_pillar_cluster", baseDesc:"几根天然的岩柱从海床直立而起,柱面上布满了棘皮动物留下的痕迹,颇为壮观。", elements:["岩柱","棘皮动物"]}, {id:"flat_dark_fissure", baseDesc:"海床上有一道窄而深的裂缝,往下看不到底,有水流从里面涌出,温度比周围低了一截。", elements:["裂缝","冷泉"]} ], forest: [ {id:"forest_kelp_curtain", baseDesc:"海藻形成的巨大帘幕将视线分成了两部分,穿过去需要拨开纠缠的叶片,里面有什么在动。", elements:["海藻帘","叶片"]}, {id:"forest_clearing_shaft", baseDesc:"海藻丛在这里让出了一片圆形的开口,日光从正上方直射而下,形成完美的光柱。", elements:["海藻开口","光柱"]}, {id:"forest_hidden_rock", baseDesc:"一块大礁石半掩在海藻里,石面上有大量附生生物,还有一些人工痕迹,也许是旧时捕鱼的标记。", elements:["礁石","附生生物","人工痕迹"]} ], cliff: [ {id:"cliff_wall_face", baseDesc:"垂直的峭壁从海床延伸向上,壁面密布着管虫和苔藓虫的痕迹,一些小鱼贴着壁面来回巡游。", elements:["峭壁","管虫","苔藓虫"]}, {id:"cliff_overhang", baseDesc:"峭壁在这里向外悬伸,形成了一片天然的庇护所,底部堆满了从上方落下的碎石。", elements:["悬岩","庇护所","碎石"]}, {id:"cliff_ledge_pool", baseDesc:"峭壁上有一块宽阔的岩架,上面积了一层薄薄的细沙,还有几只海星和海胆静静地趴着。", elements:["岩架","海星","海胆"]} ], grass: [ {id:"grass_dense_meadow", baseDesc:"海草密集地铺满海底,茎叶随着水流整齐地偏向同一方向,像是一片水下草原。", elements:["海草","水流"]}, {id:"grass_creature_trail", baseDesc:"草丛里有明显的压痕,什么体型不小的东西刚刚经过,压倒的草还没有完全弹起来。", elements:["压痕","草丛"]}, {id:"grass_clearing_stone", baseDesc:"海草在这里围绕着一块孤立的大石头,石头上刻着模糊的痕迹,和周围格格不入。", elements:["孤石","刻痕"]} ], wreck: [ {id:"wreck_outer_hull", baseDesc:"你沿着锈蚀的船壳缓缓前进,甲板上的锈层已经剥落成碎片,钢板之间的缝隙塞满了珊瑚和藤壶。", elements:["船壳","锈层","珊瑚"]}, {id:"wreck_corridor", baseDesc:"一条狭窄的走廊延伸到前方,墙面上的油漆早已剥落,管道从头顶横过,有几处已经断裂脱落。", elements:["走廊","管道","油漆"]}, {id:"wreck_hold", baseDesc:"一个宽阔的货舱,顶部某处破了一个洞,透进来一缕光线,把漂浮的细尘照得清晰可见。", elements:["货舱","破洞","光线"]}, {id:"wreck_bridge_view", baseDesc:"船桥的玻璃早已不见,只剩金属框架,从这里可以俯视整个船首区域,残骸的规模令人叹止。", elements:["船桥","金属框架","船首"]}, {id:"wreck_engine_exterior", baseDesc:"船尾的推进器就在眼前,巨大的螺旋桨已经锈死,上面覆满了贝类,静止在水中。", elements:["推进器","螺旋桨","贝类"]}, {id:"wreck_jammed_hatch", baseDesc:"一扇厚重的内舱门挡住了通道,铰链严重变形,锁死在半开的位置——靠人力完全无法移动。门缝里透出内舱的昏黄残影。", elements:["卡住的舱门","门缝残影","变形铰链"], blocked:["卡住的舱门"]}, {id:"wreck_collapsed_passage", baseDesc:"走廊顶部有一段坍塌,大块舱壁斜压在通道上将前方完全堵死。只有机械外力才能移开。残骸缝隙里隐约可见更深处的内容。", elements:["坍塌的舱壁","残骸缝隙","深处残影"], blocked:["坍塌的舱壁"]} ] }>> /* ── 碎片文本池(per terrain,短小的环境描写) ── */ <<set $diveFragDefs = { reef: [ "一枚贝壳从珊瑚枝间滑落,在你脚边转了半圈,停了下来。", "远处有什么东西在黑暗里轻轻移动,但当你看过去时已经不见了。", "水温在这一片略微升高,珊瑚上的颜色也更鲜艳。", "你感到轻微的水流变化,某种生物刚刚从附近游过。", "一根长长的触手从礁穴里伸出来,试探了一下,又缩了回去。", "细沙从一个地方缓缓往下流,那里也许有什么空洞。" ], sand: [ "脚下的沙随着你的移动轻轻扰起,随后慢慢沉落。", "一只小虾从沙里一跳,消失在视野边缘。", "远处有什么闪了一下,也许是金属,也许是鱼鳞。", "水流在这里几乎察觉不到,寂静得有些不寻常。", "沙地上有一道细细的划痕,像是什么东西爬过去留下的。" ], flat: [ "岩面上有一道道平行的擦痕,像是被什么工具处理过。", "一只章鱼把自己伪装成岩石,但眼睛还是出卖了它。", "水流从岩石缝隙里涌出,带着一股淡淡的硫磺气味。", "几只管虫同时收起触须,像是察觉到了什么。" ], forest: [ "海藻的叶片贴着你的面罩滑过,遮挡了片刻的视线。", "什么在海藻丛里沙沙地移动,但太密集,看不清楚。", "光线在海藻叶片间分割成细碎的斑点,投影在你手上。", "一条细长的鱼悬浮在藻叶之间,和环境融为一体。" ], cliff: [ "峭壁上的一块岩石松动了,碎屑缓缓飘落。", "一只蟹横着从岩缝里爬出来,停了一下,又爬回去了。", "峭壁上某处有水在渗出,细流汇聚后缓缓飘散。", "这里的水流比外面复杂,峭壁影响了整个水域的流向。" ], grass: [ "海草叶片随着你的移动一起摆动,像是在迎接你。", "一只比手掌还大的螺从草丛里缓缓爬过,留下一道痕迹。", "草丛深处似乎有亮光,但那不太可能——你是唯一的光源。", "水草在这里长得特别高,几乎和你一样高。" ], wreck: [ "水从船壳的某个破口涌进,带起锈粉在水中弥漫。", "走道里有什么东西松动了,在水流里轻轻撞击着金属壁。", "一张褪色的图纸贴在壁面上,内容已经无法辨认。", "地板上有脚步的痕迹——当然,那是很久以前的事了。", "船上的某扇门还保持着半开的状态,门轴已经完全锈死。", "灯座还在,灯泡早已不知去向,金属圆环空悬在头顶。" ], default: [ "寂静的水中,只有探照灯的嗡鸣陪伴着你。", "你的气泡缓缓上浮,在黑暗里消失。", "水压变化让你耳朵轻微作响,调整一下深度就好了。", "什么东西从视野边缘一闪而过,但你没有追上去。" ] }>> <</widget>> <</nobr>>
<<nobr>> <<widget "diveInteractDefs">> <<set $diveInteractDefs = { /* 珊瑚礁 */ "珊瑚": {text:"你小心地掰下几段珊瑚分枝,装进采集袋。", loot:[{id:"coral_frag", qty:[1,3]}]}, "海葵": {text:"触手轻轻贴住你的手套,海葵无害但难以采集完整。", loot:[{id:"kelp", qty:[0,1]}]}, "雀鲷": {text:"小鱼在你手边绕了一圈,留下一团金属光泽后溜走。", loot:[]}, "礁穴": {text:"你伸手探进礁穴,指尖碰到硬的东西——是一枚贝壳。", loot:[{id:"shell_frag", qty:[1,2]}]}, "裸胸鳝": {text:"保持距离,对视一会儿后它率先退回了穴里。", loot:[]}, "缝隙": {text:"缝隙深处有沙砾和几块小石,顺手捡了一些。", loot:[{id:"sand_extract", qty:[0,2]}]}, "管虫": {text:"管虫收起触须,你轻轻刮下几段空管,质地轻盈。", loot:[{id:"glass", qty:[0,1]}]}, /* 沙地 */ "沙海": {text:"把手插进沙里,细沙从指缝流过,什么也没找到。", loot:[]}, "沙鳐": {text:"沙鳐被光惊扰,拍打鳍掀起沙云,你趁机捡走了几块贝壳碎片。", loot:[{id:"shell_frag",qty:[1,2]}]}, "碎石": {text:"碎石里藏着一些不明金属碎片,来历不清。", loot:[{id:"metal", qty:[1,3]}]}, "金属残片": {text:"还算完整,切割断面有锈,但核心还保留着金属光泽。", loot:[{id:"metal", qty:[1,2]},{id:"iron",qty:[0,1]}]}, "沙纹": {text:"仔细观察波纹方向,能推断出这片区域的水流规律。", loot:[]}, "波纹": {text:"沙纹下方压着一枚完整的螺壳,你把它取了出来。", loot:[{id:"shell_frag", qty:[1,1]}]}, /* 岩床 */ "石脊": {text:"沿石脊摸索,发现一处空腔,里面藏着一团锈结块。", loot:[{id:"metal", qty:[1,2]}]}, "石蛏": {text:"掰下几只,装进采集瓶,气味刺鼻但是食材。", loot:[{id:"fish", qty:[1,2]}]}, "蟹": {text:"小蟹夹住了你的手套指头,你轻松拿走了它。", loot:[{id:"fish", qty:[1,1]}]}, "岩柱": {text:"岩柱根部沉积着厚厚一层细沙,里面有几块有棱角的矿石。", loot:[{id:"ore_frag", qty:[0,2]}]}, "棘皮动物": {text:"海星和海胆密密麻麻,你小心避开刺,捡了几颗。", loot:[{id:"creature_husk",qty:[1,2]}]}, "裂缝": {text:"裂缝边缘结有白色沉淀物,刮下来气味辛辣,是矿物结晶。", loot:[{id:"salt_refined",qty:[1,2]}]}, "冷泉": {text:"把采集瓶靠近泉眼,收集到一小瓶含硫的泉水。", loot:[{id:"sand_extract", qty:[1,2]}]}, /* 海藻森林 */ "海藻帘": {text:"拨开藻叶,发现一条窄道,叶片上有些附生小虾。", loot:[{id:"kelp", qty:[1,3]}]}, "叶片": {text:"你摘下几张宽大的藻叶,晒干可能有用。", loot:[{id:"kelp", qty:[2,4]}]}, "海藻开口": {text:"光柱里漂浮着大量浮游生物,你用滤网捞了一些。", loot:[{id:"creature_husk",qty:[0,2]}]}, "光柱": {text:"光柱中什么也没有,但很漂亮,你记录了下来。", loot:[]}, "礁石": {text:"礁石上的附生物很密集,刮下来一层有机质碎屑。", loot:[{id:"bone_ash", qty:[0,2]}]}, "附生生物": {text:"种类繁多,收集了几个样本装瓶。", loot:[{id:"creature_husk",qty:[1,2]}]}, "人工痕迹": {text:"像是凿过的切面,年代久远,留下了一个标记符号。", loot:[{id:"relic_etching",qty:[0,1]}]}, /* 峭壁 */ "峭壁": {text:"壁面上有些附着物,刮下来是彩色的软体动物碎片。", loot:[{id:"shell_frag", qty:[1,2]}]}, "悬岩": {text:"悬岩底部堆着落石,里面夹着几块有价值的矿石碎片。", loot:[{id:"ore_frag", qty:[1,2]}]}, "碎石": {text:"碎石里藏着一些不明金属碎片,来历不清。", loot:[{id:"metal", qty:[1,2]}]}, "岩架": {text:"岩架上积了薄薄一层细沙,翻开后发现几枚完整的海胆壳。", loot:[{id:"shell_frag",qty:[1,2]}]}, "海星": {text:"海星足部有粘液,掰下一条做样本,剩下的放回去了。", loot:[{id:"creature_husk",qty:[0,1]}]}, "海胆": {text:"小心取下一只,棘刺完好,内脏还在。", loot:[{id:"fish", qty:[1,1]}]}, /* 海草床 */ "海草": {text:"摘了一把,这种草晒干后可以用作填充材料。", loot:[{id:"kelp", qty:[2,3]}]}, "水流": {text:"顺着水流摸索,发现几块被冲来的碎屑。", loot:[{id:"sand_extract", qty:[0,2]}]}, "压痕": {text:"沿着压痕追了一段,什么都没找到,也许它跑得太快。", loot:[]}, "草丛": {text:"草丛里藏着一枚完整的蜗牛壳,质地光滑。", loot:[{id:"shell_frag", qty:[1,1]}]}, "孤石": {text:"刻痕旁边有一个浅坑,坑底压着一枚铸造的金属片。", loot:[{id:"metal", qty:[1,1]},{id:"relic_etching",qty:[0,1]}]}, "刻痕": {text:"符号的样式很陌生,你拓印了一份。", loot:[{id:"relic_etching",qty:[0,1]}]}, /* 沉船 */ "船壳": {text:"从锈层里抠出几块钢板碎片,还有分量。", loot:[{id:"metal", qty:[1,3]},{id:"wreck_steel",qty:[0,1]}]}, "锈层": {text:"锈层下藏着一截螺栓和一段铜管,价值有限但可用。", loot:[{id:"metal", qty:[1,2]}]}, "走廊": {text:"走廊尽头有个翻倒的金属柜,摸出两件东西。", loot:[{id:"metal", qty:[1,2]},{id:"relic_notebook",qty:[0,1]}]}, "管道": {text:"管道内还有残余油液,用小瓶收集了些。", loot:[{id:"oil", qty:[1,2]}]}, "货舱": {text:"货舱地板有几箱腐烂的货物,只有角落的金属箱还保持完好。", loot:[{id:"metal", qty:[2,4]},{id:"coal",qty:[0,3]}]}, "破洞": {text:"破洞边缘割手,你小心地检查了周围,收集了几块钢片。", loot:[{id:"wreck_steel", qty:[1,2]}]}, "金属框架": {text:"框架螺母已锈死,但你撬下了一段可用的钢条。", loot:[{id:"metal", qty:[2,3]}]}, "螺旋桨": {text:"贝类密布,你撬了几只吃食用或炼材都行。", loot:[{id:"fish", qty:[1,2]}]}, "贝类": {text:"贝类密布,你撬了几只。", loot:[{id:"fish", qty:[1,2]}]}, "推进器": {text:"你检查了推进器的机械结构,找到一块可拆下的橡胶密封件。", loot:[{id:"rubber_seal",qty:[1,1]}]} }>> <</widget>> <</nobr>>
<<nobr>> <<replace "#sc-status">><<include "侧边栏状态">><</replace>> /* ══ 场景进入简介(仅初次进入时显示)══ */ <<if $diveShowIntro>> <div style="border-left:3px solid var(--teal-bright);padding:0.3rem 0.55rem;margin-bottom:0.35rem;font-size:0.82rem;color:var(--bone);line-height:1.75;background:rgba(0,180,150,0.04);border-radius:0 3px 3px 0;"> <<print $diveIntro>> </div> <<set $diveShowIntro = false>> <</if>> /* ══ 顶部状态行 ══ */ <<diveWarn>> <<set _o2c = $diveOxygen <= 20 ? "var(--danger-bright)" : $diveOxygen <= 40 ? "var(--amber)" : "var(--teal-bright)">> <<set _cdc = $diveCold >= 80 ? "var(--danger-bright)" : $diveCold >= 50 ? "var(--amber)" : "var(--bone-dim)">> <div style="font-size:0.73rem;color:var(--bone-dim);margin-bottom:0.2rem;"> ⚓ <<print $mapinfo[$maptype].type>> · <<print $depth>>m · <<print $showseason>>季 第<<print $showday>>日 <<print $showhour>>:<<print $showminute>> <<if $worldScene && $worldScene.state === "inside">> <span style="color:var(--amber-bright);"> · <<print $worldScene.name>></span> <</if>> </div> /* 氧气 + 冷压条 */ <div style="display:flex;justify-content:space-between;font-size:0.68rem;margin-bottom:0.04rem;"> <span style="color:<<print _o2c>>;">氧气</span> <span style="color:<<print _o2c>>;"><<print $diveOxygen>>/100</span> </div> <div style="background:var(--bg-panel);border:1px solid var(--border-dim);height:5px;border-radius:2px;overflow:hidden;margin-bottom:0.12rem;"> <div style="height:100%;width:<<print $diveOxygen>>%;background:<<print _o2c>>;transition:width 0.3s;"></div> </div> <div style="display:flex;justify-content:space-between;font-size:0.68rem;margin-bottom:0.04rem;"> <span style="color:<<print _cdc>>;">水温冷压</span> <span style="color:<<print _cdc>>;"><<print $diveCold>>/100</span> </div> <div style="background:var(--bg-panel);border:1px solid var(--border-dim);height:3px;border-radius:2px;overflow:hidden;margin-bottom:0.3rem;"> <div style="height:100%;width:<<print $diveCold>>%;background:<<print _cdc>>;transition:width 0.3s;"></div> </div> /* ══ 预警横幅 ══ */ <<if $diveO2Dead>> <div style="border:2px solid var(--danger-bright);padding:0.3rem 0.5rem;margin-bottom:0.3rem;font-size:0.84rem;color:var(--danger-bright);background:rgba(180,30,30,0.08);border-radius:3px;"> ‼ 氧气耗尽——你开始窒息。必须立刻返回。 </div> <div style="font-size:0.82rem;margin-bottom:0.3rem;"> <<link "⚠ 立即返回潜艇">> <<diveReturn>> <<set $diveO2Dead = false>> <<set $diveLog = "">> <<goto "出舱">> <</link>> </div> <<elseif _diveWarn === 2>> <div style="border-left:3px solid var(--danger-bright);padding:0.25rem 0.5rem;margin-bottom:0.3rem;font-size:0.8rem;color:var(--danger-bright);"> ⚠ 氧气仅剩返程量——必须立即返回 </div> <<elseif _diveWarn === 1>> <div style="border-left:3px solid var(--amber);padding:0.25rem 0.5rem;margin-bottom:0.3rem;font-size:0.8rem;color:var(--amber);"> ⚠ 氧气有限,建议尽快返回(约剩2步余量) </div> <</if>> /* ══ 舷窗区域 ══ */ <div style="border:1px solid var(--border-dim);border-radius:3px;padding:0.45rem 0.55rem;margin-bottom:0.35rem;font-size:0.84rem;color:var(--bone);line-height:1.9;"> /* diveLog 已停用(v37+)*/ /* 交互结果面板(持续显示,需手动确认)*/ <<if $diveInteractResult>> <div style="border-left:3px solid var(--teal-bright);padding:0.25rem 0.5rem;margin-bottom:0.3rem;background:rgba(0,180,150,0.05);border-radius:0 3px 3px 0;"> <div style="font-size:0.78rem;color:var(--teal-bright);margin-bottom:0.12rem;">▸ 行动结果</div> <div style="color:var(--bone);font-size:0.84rem;line-height:1.8;"><<print $diveInteractResult>></div> </div> <div style="font-size:0.78rem;margin-bottom:0.2rem;"><<link "[ 确认 ]">><<set $diveInteractResult = "">><<goto "仓外探索">><</link>></div> <</if>> /* ══ 舱外小型事件面板 ══ */ <<if $activeSmallEvent && !$diveInteractResult>> <div style="border:1px solid var(--amber);border-radius:3px;padding:0.35rem 0.55rem;margin-bottom:0.3rem;background:rgba(180,140,60,0.05);"> <div style="font-size:0.74rem;color:var(--amber-bright);margin-bottom:0.12rem;">⚑ <<print $activeSmallEvent.name>></div> <div style="font-size:0.82rem;color:var(--bone);line-height:1.8;margin-bottom:0.2rem;"><<print $activeSmallEvent.stageDesc>></div> <div style="font-size:0.78rem;"> <<for _seai = 0; _seai < $activeSmallEvent.actions.length; _seai++>> <<set _seaAct = $activeSmallEvent.actions[_seai]>> <<capture _seaAct>> <div><<link _seaAct>> <<resolveSmallEvent _seaAct>> <<set $diveOxygen = Math.max(0, $diveOxygen - 2)>> <<if !$activeSmallEvent && $lastSmallEventText>> <<set $diveInteractResult = $lastSmallEventText>> <<set $lastSmallEventText = "">> <</if>> <<goto "仓外探索">> <</link>></div> <</capture>> <</for>> </div> </div> <</if>> /* 当前节点内容(小型事件活跃时隐藏,避免界面重叠)*/ <<if $diveChain.length > 0 && $diveIdx < $diveChain.length && !$activeSmallEvent>> <<set _dcNode = $diveChain[$diveIdx]>> <<if _dcNode.type === "frag">> /* 碎片节点:简短环境描写 */ <<if $diveIdx > 0>> <<set _dcTransPool = ["你继续向前,呼出的气泡缓缓上浮。","探照灯在黑暗中划出新的弧线,你迈出下一步。","你向前摸索,水流从身侧轻轻拂过。","脚步搅起细沙,随后重归沉寂。","你继续深入,身后的来路逐渐模糊。"]>> <<set _dcTrans = _dcTransPool[Math.floor(Math.random() * _dcTransPool.length)]>> <div style="color:var(--bone-dim);font-size:0.78rem;margin-bottom:0.08rem;"><<print _dcTrans>></div> <</if>> <div style="color:var(--bone-dim);font-style:italic;font-size:0.82rem;"><<print _dcNode.text>></div> <<elseif _dcNode.type === "scene">> /* 场景节点:完整光照合成描述 + 可交互元素 */ <<if $diveIdx > 0>> <<set _dcTransPool = ["你继续向前,呼出的气泡缓缓上浮。","探照灯在黑暗中划出新的弧线,你迈出下一步。","你向前摸索,水流从身侧轻轻拂过。","脚步搅起细沙,随后重归沉寂。","你继续深入,身后的来路逐渐模糊。"]>> <<set _dcTrans = _dcTransPool[Math.floor(Math.random() * _dcTransPool.length)]>> <div style="color:var(--bone-dim);font-size:0.78rem;margin-bottom:0.1rem;"><<print _dcTrans>></div> <</if>> <div style="color:var(--bone);margin-bottom:0.15rem;"><<print _dcNode.desc>></div> <<if _dcNode.elements && _dcNode.elements.length > 0>> <div style="font-size:0.75rem;margin-top:0.08rem;"> <<for _diei = 0; _diei < _dcNode.elements.length; _diei++>> <<set _dieElem = _dcNode.elements[_diei]>> <<set _dieDone = false>> <<if _dcNode.done>> <<for _diedi = 0; _diedi < _dcNode.done.length; _diedi++>> <<if _dcNode.done[_diedi] === _dieElem>><<set _dieDone = true>><</if>> <</for>> <</if>> <<capture _dieElem, _dieDone>> <<if _dieDone>> <span style="opacity:0.35;margin-right:0.4rem;">✓ <<print _dieElem>></span> <<else>> /* blocked 检测:舱壁/舱门等需机械臂从仓内清除后才能交互 */ <<set _dieBlocked = false>> <<if _dcNode.blocked && _dcNode.blocked.indexOf(_dieElem) >= 0>> <<set _dieClearedList = ($diveArmCleared && $diveArmCleared[_dcNode.id]) ? $diveArmCleared[_dcNode.id] : []>> <<if _dieClearedList.indexOf(_dieElem) < 0>><<set _dieBlocked = true>><</if>> <</if>> <<if _dieBlocked>> <span style="opacity:0.38;font-size:0.78rem;">🔒 <<print _dieElem>><span style="font-size:0.65rem;color:var(--amber-dim);"> [需机械臂清除·返回舱内操作]</span></span> <<else>> <<capture _dieElem>> <<set _dieLinkLabel = "◉ " + _dieElem>> <<link _dieLinkLabel>><<diveInteract _dieElem>><<goto "仓外探索">><</link>> <</capture>> <</if>> <</if>> <</capture>> <</for>> </div> <</if>> <<elseif _dcNode.type === "wschild">> /* worldScene 子事件节点 */ <<if _dcNode.done>> <div style="color:var(--bone-dim);font-size:0.82rem;">✓ <<print _dcNode.name>> — 已完成</div> <<else>> <div style="border-left:3px solid var(--amber-bright);padding:0.25rem 0.5rem;margin-bottom:0.2rem;background:rgba(180,140,60,0.05);"> <div style="font-size:0.74rem;color:var(--amber-bright);margin-bottom:0.1rem;">◈ <<print _dcNode.name>></div> <div style="font-size:0.82rem;color:var(--bone);line-height:1.8;margin-bottom:0.15rem;"><<print _dcNode.stageDesc>></div> <div style="font-size:0.78rem;"> <<for _wcai = 0; _wcai < _dcNode.actions.length; _wcai++>> <<set _wcAct = _dcNode.actions[_wcai]>> <<capture _wcAct>> <div><<link _wcAct>> <<if !$wsChildDefs>><<worldSceneDefs>><</if>> <<set _wcDef = $wsChildDefs[_dcNode.id]>> <<set _wcRes = _wcDef ? _wcDef.resolve[_wcAct] : null>> <<if _wcRes>> /* 发放战利品 */ <<set _wcLog = "">> <<if _wcRes.loot>> <<for _wcli = 0; _wcli < _wcRes.loot.length; _wcli++>> <<set _wcL = _wcRes.loot[_wcli]>> <<set _wcQ = _wcL.qty[0] + Math.floor(Math.random() * (_wcL.qty[1]-_wcL.qty[0]+1))>> <<if _wcQ > 0>> <<additem _wcL.id _wcQ>> <<if $items && $items[_wcL.id]>> <<set _wcLog = _wcLog + $items[_wcL.id].name + "×" + _wcQ + " ">> <</if>> <</if>> <</for>> <</if>> <<set _wcText = _wcRes.text + (_wcLog ? " 获得:" + _wcLog : "")>> /* 下一阶段或结束 */ <<if _wcRes.next >= 0 && _wcRes.next < _wcDef.stages.length>> <<set $diveChain[$diveIdx].stageIdx = _wcRes.next>> <<set $diveChain[$diveIdx].stageDesc = _wcText + " " + _wcDef.stages[_wcRes.next].desc>> <<set $diveChain[$diveIdx].actions = _wcDef.stages[_wcRes.next].actions>> <<else>> <<set $diveChain[$diveIdx].done = true>> /* 记录完成到 worldScene.doneCids */ <<if $worldScene && $worldScene.state === "inside">> <<if !$worldScene.doneCids>><<set $worldScene.doneCids = []>><</if>> <<set _wcAlready = false>> <<for _wcdi = 0; _wcdi < $worldScene.doneCids.length; _wcdi++>> <<if $worldScene.doneCids[_wcdi] === _dcNode.id>><<set _wcAlready = true>><</if>> <</for>> <<if !_wcAlready>><<run $worldScene.doneCids.push(_dcNode.id)>><</if>> <</if>> <</if>> <<set $diveInteractResult = _wcText>> <<set $diveOxygen = Math.max(0, $diveOxygen - 2)>> /* 同步保存到 worldScene */ <<if $worldScene && $worldScene.state === "inside">> <<set $worldScene.savedChain = $diveChain>> <</if>> <</if>> <<goto "仓外探索">> <</link>></div> <</capture>> <</for>> </div> </div> <</if>> <<elseif _dcNode.type === "end">> /* 路线终点 */ <div style="color:var(--bone-dim);font-style:italic;">探照灯扫过一片开阔的海域,这条路已经走到尽头了。前方没有更多可探索的内容,是时候考虑返回了。</div> <div style="margin-top:0.2rem;font-size:0.8rem;color:var(--amber);">← 建议返回潜艇</div> <<else>> <div style="color:var(--bone-dim);">四周一片寂静。</div> <</if>> <<else>> /* chain 为空时的兜底(不应该触发)*/ <div style="color:var(--bone-dim);"> <<diveLight>> <<if $depth <= 50>> 出仓后,海水将你轻轻托起,探照灯扫过周围的环境。 <<elseif $depth <= 150>> 探照灯光在黑暗中延伸,照出一片昏黄的锥形区域。 <<else>> 深海的压力无处不在,黑暗在探照灯的边缘等候。 <</if>> </div> <</if>> </div> /* ══ 分叉选择(批次三接入)══ */ <<if $diveChainSub.length > 0>> <div style="border:1px solid var(--amber-dim);border-radius:3px;padding:0.3rem 0.5rem;margin-bottom:0.3rem;font-size:0.8rem;"> <div style="color:var(--amber-bright);font-size:0.74rem;margin-bottom:0.15rem;">⑂ 路线分叉——选择一条继续</div> <<for _dcbi = 0; _dcbi < $diveChainSub.length; _dcbi++>> <<set _dcbr = $diveChainSub[_dcbi]>> <<capture _dcbi, _dcbr>> <div style="margin-bottom:0.08rem;"> <<link _dcbr.label>> <<set $diveChain = _dcbr.chain>> <<set $diveChainSub = []>> <<set $diveIdx = 0>> <<set $diveLog = "你选择了:" + _dcbr.label>> <<goto "仓外探索">> <</link>> </div> <</capture>> <</for>> </div> <</if>> /* ══ 操作台 ══ */ <div style="font-size:0.82rem;margin-bottom:0.15rem;"> <<if _diveWarn < 2 && !$activeSmallEvent && ($diveIdx >= $diveChain.length || !$diveChain[$diveIdx] || $diveChain[$diveIdx].type !== "end")>> <<if $diveIdx < $diveChain.length - 1>> <<set _dcCurNode = $diveChain[$diveIdx]>> <<set _dcContinueLabel = _dcCurNode && _dcCurNode.type === "scene" ? "→ 前进(场景区域)" : _dcCurNode && _dcCurNode.type === "frag" ? "→ 继续前进" : "→ 前进">> <<link _dcContinueLabel>> <<diveStep>> <<set $diveLog = "">> <<set $diveInteractResult = "">> <<set $diveChain[$diveIdx].visited = true>> <<set $diveIdx = $diveIdx + 1>> <<goto "仓外探索">> <</link>> <</if>> <</if>> <<link "← 返回潜艇">><<diveReturn>><<set $diveLog = "">><<set $currentContext = "anchored">><<goto "出舱">><</link>> </div> <div style="font-size:0.72rem;color:var(--bone-dim);margin-bottom:0.2rem;"> 已深入 <<print $diveStepsOut>> 步 · 进度 <<print $diveIdx>>/<<print $diveChain.length - 1>> · 返程消耗约 <<print Math.ceil($diveStepsOut * $diveStepCostO2 * 0.6)>> 氧气 </div> <</nobr>>
<<nobr>> <<widget "temporalEventDefs">> <<set $temporalDefs = { shadow_pursuit: { name: "追踪的阴影", viewDesc: "探照灯边缘有什么东西,速度和方向与你完全一致——它一直在跟着你。", chance: 0.006, dMin: 200, sanMax: 80, speed: 0.5, warnAt: 40, warnText: "声呐后方持续出现移动信号,速度与你惊人地吻合,已跟了很长时间了。", endText: "那个信号突然加速——撞击!潜艇剧烈震动,安定值大幅下降。", effect: "san", amount: 20, terrain: "sand flat cliff water" }, pressure_anomaly: { name: "压力异常区", viewDesc: "外壳出现细小振动——是极不规律的水压波动,来自某个方向。", chance: 0.004, dMin: 500, sanMax: 999, speed: 0.8, warnAt: 50, warnText: "压力读数开始不规律波动,幅度越来越大,船体发出金属应力声。", endText: "压力突然达到峰值,系统完整性下降,需要紧急维修。", effect: "sys", amount: 15, terrain: "flat cliff" }, deep_current: { name: "深层洋流", viewDesc: "水流方向开始变得混乱,仪表盘流速计急速跳动。", chance: 0.003, dMin: 300, sanMax: 999, speed: 1.2, warnAt: 35, warnText: "水流突然变得异常强劲,方向不断改变,潜艇开始偏离航线。", endText: "强洋流将潜艇卷入,被迫偏转,坐标向前推进。", effect: "map", amount: 5000, terrain: "sand flat cliff" } }>> <</widget>> <</nobr>>
<<nobr>> <<widget "spawnTemporalEvent">> <<if $temporalEvent>><<return>><</if>> <<temporalEventDefs>> <<set _tKeys = Object.keys($temporalDefs)>> <<for _ti = 0; _ti < _tKeys.length; _ti++>> <<set _tid = _tKeys[_ti]>> <<set _td = $temporalDefs[_tid]>> <<if _td.terrain.indexOf($maptype) < 0>><<continue>><</if>> <<if $depth < _td.dMin>><<continue>><</if>> <<if $san > _td.sanMax>><<continue>><</if>> <<if Math.random() >= _td.chance>><<continue>><</if>> <<set $temporalEvent = {id:_tid, name:_td.name, prog:0, speed:_td.speed, warnAt:_td.warnAt, warnText:_td.warnText, endText:_td.endText, effect:_td.effect, amount:_td.amount, warned:0}>> <<break>> <</for>> <</widget>> <</nobr>>
<<nobr>> <<widget "resolveTemporalEvent">> <<if !$temporalEvent>><<return>><</if>> <<set _tep = $temporalEvent.prog + $temporalEvent.speed>> <<if _tep > 100>><<set _tep = 100>><</if>> <<set $temporalEvent.prog = _tep>> <<if $temporalEvent.warned === 0 && _tep >= $temporalEvent.warnAt>> <<set $temporalEvent.warned = 1>> <<set $temporalLog = "Warning: " + $temporalEvent.warnText>> <</if>> <<if _tep >= 100>> <<set $temporalLog = $temporalEvent.endText>> <<if $temporalEvent.effect === "san">><<set $san = Math.max(0, $san - $temporalEvent.amount)>> <<elseif $temporalEvent.effect === "sys">><<set $sys = Math.max(0, $sys - $temporalEvent.amount)>> <<elseif $temporalEvent.effect === "map">><<set $map = $map + $temporalEvent.amount>> <</if>> <<set $temporalEvent = 0>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "addBookmark">> <<set _bmL = $args[0] || ($mapinfo[$maptype] ? $mapinfo[$maptype].type : $maptype)>> <<set _bmT = $args[1] || "auto">> <<set _bmLg = ($largeScene && $largeScene !== 0 && $largeScene.state === "active") ? $largeScene.name : "">> <<run $bookmarks.unshift({label:_bmL, type:_bmT, mt:$maptype, depth:$depthdeep, day:$day, lg:_bmLg})>> <<if $bookmarks.length > 20>><<run $bookmarks.pop()>><</if>> <</widget>> <<widget "bookmarkPanel">> <<if $bookmarks.length === 0>><span style="opacity:0.4;font-size:0.75rem;">尚无记录</span><<return>><</if>> <<set _bmMax = Math.min($bookmarks.length, 8)>> <<for _bmi = 0; _bmi < _bmMax; _bmi++>> <<set _bm = $bookmarks[_bmi]>> <<capture _bm>> <div style="font-size:0.73rem;color:var(--bone-dim);line-height:1.6;border-bottom:1px solid var(--border-dim);padding:0.1rem 0;"> <span style="color:var(--bone);"><<print _bm.label>></span><span style="opacity:0.5;"> · <<print _bm.mt>> <<print _bm.depth>>m · 第<<print _bm.day>>日</span><<if _bm.lg>><span style="color:var(--amber);"> [<<print _bm.lg>>]</span><</if>> </div> <</capture>> <</for>> <</widget>> <</nobr>>
<<nobr>> <<widget "fuelDefs">> <<set $fuelDefs = {coal:15, wood:8, oil:40, fish_oil:12, algae_block:5, mineral_fuel:80}>> <</widget>> /* addFuel id [qty|"all"] qty 省略=1,"all"=全部可用数量 */ <<widget "addFuel">> <<set _afId = $args[0]>> <<set _afQArg = $args[1]>> <<if !$fuelDefs>><<fuelDefs>><</if>> <<set _afVal = $fuelDefs[_afId]>> <<if !_afVal>> <<set $lastFuelText = "无法使用该物品作为燃料。">> <<else>> /* 统计可用总量 */ <<set _afType = ($items[_afId] ? $items[_afId].type : "")>> <<set _afAvail = 0>> <<if _afType && $store[_afType]>> <<for _afi = 0; _afi < $store[_afType].length; _afi++>> <<if $store[_afType][_afi].id === _afId>><<set _afAvail += $store[_afType][_afi].quantity>><</if>> <</for>> <</if>> <<if _afType && $backpack[_afType]>> <<for _afi = 0; _afi < $backpack[_afType].length; _afi++>> <<if $backpack[_afType][_afi].id === _afId>><<set _afAvail += $backpack[_afType][_afi].quantity>><</if>> <</for>> <</if>> /* 确定本次加入数量 */ <<set _afNeed = (_afQArg === "all") ? _afAvail : (Number(_afQArg) > 0 ? Number(_afQArg) : 1)>> /* 可加燃料上限:不超过槽位剩余 */ <<set _afFuelSpace = $fuelMax - $fuel>> <<set _afMaxByFuel = (_afVal > 0) ? Math.ceil(_afFuelSpace / _afVal) : 0>> <<set _afUse = Math.min(_afNeed, _afAvail, _afMaxByFuel)>> <<if _afUse <= 0>> <<set $lastFuelText = "燃料槽已满或无可用物品。">> <<else>> /* 从 store 扣除,不足再扣 backpack */ <<set _afToUse = _afUse>> <<if _afType && $store[_afType]>> <<for _afi = 0; _afi < $store[_afType].length; _afi++>> <<if $store[_afType][_afi].id === _afId && _afToUse > 0>> <<set _afTake = Math.min($store[_afType][_afi].quantity, _afToUse)>> <<set $store[_afType][_afi].quantity -= _afTake>> <<set _afToUse -= _afTake>> <</if>> <</for>> <</if>> <<if _afToUse > 0 && _afType && $backpack[_afType]>> <<for _afi = 0; _afi < $backpack[_afType].length; _afi++>> <<if $backpack[_afType][_afi].id === _afId && _afToUse > 0>> <<set _afTake = Math.min($backpack[_afType][_afi].quantity, _afToUse)>> <<set $backpack[_afType][_afi].quantity -= _afTake>> <<set _afToUse -= _afTake>> <</if>> <</for>> <</if>> <<set _afActual = _afUse - _afToUse>> <<set $fuel = Math.min($fuelMax, $fuel + _afActual * _afVal)>> <<set _afName = ($items[_afId] ? $items[_afId].name : _afId)>> <<set $lastFuelText = _afName + "×" + _afActual + " → +" + (_afActual * _afVal) + "(当前:" + Math.floor($fuel) + "/" + $fuelMax + ")">> <<if $driftMode && $fuel > 5>><<set $driftMode = false>><</if>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "upgradeDefs">> <<set $upgradeDefs = { hull: { name: "船体隔热层", desc: "强化船体外壳的隔热材料,降低深海水压和温度造成的结构损耗。", maxLevel: 3, levels: [ { label:"无防护", effect:"深海损耗基准×1.0,燃料深度系数基准" }, { label:"基础隔热", effect:"300m以深损耗-20%,深度燃料系数-0.3", cost:{metal:4, gears:2} }, { label:"复合隔热", effect:"600m以深损耗-40%,深度燃料系数-0.6", cost:{metal:8, gears:4, wood:3} }, { label:"深渊隔热", effect:"全深度损耗-60%,深度燃料系数-1.0", cost:{metal:15, gears:8, glass:3} } ] }, pressure: { name: "加压舱改造", desc: "改造压力舱结构,扩展潜艇安全作业的深度范围。", maxLevel: 3, levels: [ { label:"标准压力舱", effect:"安全深度上限300m" }, { label:"加强压力舱", effect:"安全深度上限600m", cost:{metal:6, gears:3} }, { label:"深海压力舱", effect:"安全深度上限1500m", cost:{metal:12, gears:6, glass:4} }, { label:"极深压力舱", effect:"安全深度上限5000m", cost:{metal:20, gears:12, coal:5} } ] }, thruster: { name: "推进器", desc: "升级推进系统,提升最高航行速度上限。", maxLevel: 3, levels: [ { label:"基础推进器", effect:"最高速度100" }, { label:"改良推进器", effect:"最高速度200", cost:{metal:5, gears:3} }, { label:"高效推进器", effect:"最高速度350", cost:{metal:10, gears:6, coal:4} }, { label:"涡轮推进器", effect:"最高速度500", cost:{metal:18, gears:10, coal:8} } ] }, arm: { name: "机械臂", desc: "为潜艇安装机械臂,解锁仓外探索的操作权限。", maxLevel: 2, levels: [ { label:"未安装", effect:"仓外探索只能观察,无法操作元素" }, { label:"基础机械臂", effect:"解锁粗操作:大型物品拆卸、环境资源采集", cost:{metal:8, gears:5, glass:2} }, { label:"精密机械臂", effect:"解锁精细操作:捕捉生物、拾取细小物品", cost:{metal:15, gears:10, glass:4} } ] }, oxygen_sys: { name: "氧气循环系统", desc: "升级仓外氧气装备,增加出仓可携带的氧气上限。", maxLevel: 3, levels: [ { label:"基础气瓶", effect:"出仓氧气上限100" }, { label:"扩容气瓶", effect:"出仓氧气上限160", cost:{metal:4, gears:3} }, { label:"循环呼吸器", effect:"出仓氧气上限250", cost:{metal:8, gears:5, glass:3} }, { label:"深海压力服", effect:"出仓氧气上限400", cost:{metal:15, gears:8, glass:6} } ] }, fuel_tank: { name: "燃料槽扩容", desc: "扩大燃料储存槽容积,延长续航里程。", maxLevel: 3, levels: [ { label:"标准燃料槽", effect:"燃料上限300" }, { label:"扩容燃料槽", effect:"燃料上限500", cost:{metal:4, wood:5} }, { label:"大型燃料槽", effect:"燃料上限800", cost:{metal:8, wood:8, gears:3} }, { label:"超大型燃料槽", effect:"燃料上限1400", cost:{metal:15, wood:12, gears:6} } ] }, kitchen: { name: "厨房设备扩充", desc: "扩建厨房设备,解锁更多烹饪方式。", maxLevel: 3, levels: [ { label:"基础灶台", effect:"可用:明火烤、生食", cost:{} }, { label:"铜锅安装", effect:"新增:铜锅炖", cost:{metal:3, coal:4} }, { label:"蒸笼与铁锅", effect:"新增:清蒸、煎炒", cost:{metal:6, wood:5, coal:6} }, { label:"深油炸台", effect:"新增:油炸", cost:{metal:10, wood:8, coal:8, glass:3} } ] }, alchemy: { name: "炼金台扩充", desc: "扩建炼金工作台,解锁更多相变操作。", maxLevel: 3, levels: [ { label:"精炼台", effect:"可用:精炼台(原料→精质)", cost:{} }, { label:"溶解皿", effect:"新增:溶解皿(黑化,固→液)", cost:{metal:4, glass:3} }, { label:"蒸馏器·凝结炉", effect:"新增:蒸馏器(白化)、凝结炉(黄化)", cost:{metal:8, glass:5, gears:4} }, { label:"赤化炉", effect:"新增:赤化炉(赤化,→离子态)", cost:{metal:15, glass:8, gears:8} } ] } }>> <</widget>> <</nobr>>
<<nobr>> <<widget "doUpgrade">> /* 用法:<<doUpgrade "hull">> 检查材料是否足够,足够则扣除并升级,结果写入 $lastUpgradeText */ <<set _duId = $args[0]>> <<if !$upgradeDefs>><<upgradeDefs>><</if>> <<set _duDef = $upgradeDefs[_duId]>> <<if !_duDef>> <<set $lastUpgradeText = "未知升级项:" + _duId>> <<else>> <<set _duCur = Number($upgrades[_duId]) || 0>> <<if _duCur >= _duDef.maxLevel>> <<set $lastUpgradeText = _duDef.name + "已达最高等级。">> <<else>> <<set _duNext = _duCur + 1>> <<set _duLvlDef = _duDef.levels[_duNext]>> <<set _duCost = _duLvlDef.cost>> /* 检查材料 */ <<set _duCanAfford = true>> <<set _duMissing = []>> <<set _duCostKeys = Object.keys(_duCost)>> <<for _dci = 0; _dci < _duCostKeys.length; _dci++>> <<set _dcId = _duCostKeys[_dci]>> <<set _dcReq = _duCost[_dcId]>> <<set _dcType = ($items[_dcId] ? $items[_dcId].type : "")>> <<set _dcHave = 0>> <<if _dcType && $store[_dcType]>> <<for _dci2 = 0; _dci2 < $store[_dcType].length; _dci2++>> <<if $store[_dcType][_dci2].id === _dcId>><<set _dcHave += $store[_dcType][_dci2].quantity>><</if>> <</for>> <</if>> <<if _dcType && $backpack[_dcType]>> <<for _dci2 = 0; _dci2 < $backpack[_dcType].length; _dci2++>> <<if $backpack[_dcType][_dci2].id === _dcId>><<set _dcHave += $backpack[_dcType][_dci2].quantity>><</if>> <</for>> <</if>> <<if _dcHave < _dcReq>> <<set _duCanAfford = false>> <<set _duMissName = ($items[_dcId] ? $items[_dcId].name : _dcId)>> <<run _duMissing.push(_duMissName + "×" + (_dcReq - _dcHave))>> <</if>> <</for>> <<if !_duCanAfford>> <<set $lastUpgradeText = "材料不足:" + _duMissing.join(",")>> <<else>> /* 扣除材料 */ <<for _dci = 0; _dci < _duCostKeys.length; _dci++>> <<set _dcId = _duCostKeys[_dci]>> <<set _dcReq = _duCost[_dcId]>> <<set _dcType = ($items[_dcId] ? $items[_dcId].type : "")>> <<set _dcLeft = _dcReq>> <<if _dcType && $store[_dcType]>> <<for _dci2 = 0; _dci2 < $store[_dcType].length; _dci2++>> <<if $store[_dcType][_dci2].id === _dcId && _dcLeft > 0>> <<set _dcTake = Math.min($store[_dcType][_dci2].quantity, _dcLeft)>> <<set $store[_dcType][_dci2].quantity -= _dcTake>> <<set _dcLeft -= _dcTake>> <</if>> <</for>> <</if>> <<if _dcLeft > 0 && _dcType && $backpack[_dcType]>> <<for _dci2 = 0; _dci2 < $backpack[_dcType].length; _dci2++>> <<if $backpack[_dcType][_dci2].id === _dcId && _dcLeft > 0>> <<set _dcTake = Math.min($backpack[_dcType][_dci2].quantity, _dcLeft)>> <<set $backpack[_dcType][_dci2].quantity -= _dcTake>> <<set _dcLeft -= _dcTake>> <</if>> <</for>> <</if>> <</for>> /* 升级 */ <<set $upgrades[_duId] = _duNext>> /* 立即应用效果 */ <<applyUpgradeEffects _duId>> <<set $lastUpgradeText = _duDef.name + " 升至 Lv." + _duNext + "「" + _duLvlDef.label + "」">> <</if>> <</if>> <</if>> <</widget>> /* 应用升级效果到游戏变量 */ <<widget "applyUpgradeEffects">> <<set _aueId = $args[0]>> /* 推进器 → spdmax */ <<if _aueId === "thruster">> <<set _aueSpdTable = [100, 200, 350, 500]>> <<set $spdmax = _aueSpdTable[Number($upgrades.thruster)||0]>> <</if>> /* 燃料槽 → fuelMax */ <<if _aueId === "fuel_tank">> <<set _aueFuelTable = [300, 500, 800, 1400]>> <<set $fuelMax = _aueFuelTable[Number($upgrades.fuel_tank)||0]>> <</if>> /* 氧气 → diveOxygen上限(存入 $diveOxygenMax,diveInit时使用)*/ <<if _aueId === "oxygen_sys">> <<set _aueO2Table = [100, 160, 250, 400]>> <<set $diveOxygenMax = _aueO2Table[Number($upgrades.oxygen_sys)||0]>> <</if>> /* kitchen / alchemy: 无需更新数值变量,UI 直接读 $upgrades.kitchen/alchemy */ <</widget>> <</nobr>>
<<nobr>> <<upgradeDefs>> <<if !$lastUpgradeText>><<set $lastUpgradeText = "">><</if>> <div style="font-size:0.9rem;color:var(--amber-bright);margin-bottom:0.25rem;">🔧 机械室</div> <div style="font-size:0.77rem;color:var(--bone-dim);margin-bottom:0.4rem;line-height:1.65;"> 满是工具和零件的舱室,各种管道和电路在隔板上交错延伸。操作台旁边贴着几张手绘的改装图纸。 </div> /* ── 升级结果提示 ── */ <<if $lastUpgradeText>> <div style="border-left:2px solid var(--teal-bright);padding:0.1rem 0.4rem;font-size:0.75rem;color:var(--teal-bright);margin-bottom:0.3rem;"> <<print $lastUpgradeText>> </div> <<set $lastUpgradeText = "">> <</if>> /* ── 升级项列表 ── */ <<set _mechKeys = ["hull","pressure","thruster","arm","oxygen_sys","fuel_tank","kitchen","alchemy"]>> <<for _mki = 0; _mki < _mechKeys.length; _mki++>> <<set _mkId = _mechKeys[_mki]>> <<set _mkDef = $upgradeDefs[_mkId]>> <<set _mkCur = Number($upgrades[_mkId]) || 0>> <<set _mkMax = _mkDef.maxLevel>> <<set _mkCurLvl = _mkDef.levels[_mkCur]>> <<capture _mkId, _mkDef, _mkCur, _mkMax, _mkCurLvl>> <div style="border:1px solid var(--border-dim);border-radius:3px;padding:0.25rem 0.4rem;margin-bottom:0.2rem;"> /* 名称 + 等级点 */ <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:0.05rem;"> <span style="font-size:0.8rem;color:var(--bone);"><<print _mkDef.name>></span> <span style="font-size:0.68rem;color:var(--bone-dim);"> <<for _lpi = 0; _lpi <= _mkMax; _lpi++>><<if _lpi <= _mkCur>><span style="color:var(--amber);">●</span><<else>><span style="opacity:0.3;">○</span><</if>><</for>> </span> </div> /* 当前等级描述 */ <div style="font-size:0.72rem;color:var(--bone-dim);margin-bottom:0.08rem;"> <<print _mkCurLvl.label>> <span style="opacity:0.6;margin-left:0.3rem;">— <<print _mkCurLvl.effect>></span> </div> /* 升级按钮 */ <<if _mkCur < _mkMax>> <<set _mkNextLvl = _mkDef.levels[_mkCur + 1]>> <<set _mkCostStr = "">> <<set _mkCostKeys = Object.keys(_mkNextLvl.cost)>> <<for _mci = 0; _mci < _mkCostKeys.length; _mci++>> <<set _mcId = _mkCostKeys[_mci]>> <<if _mci > 0>><<set _mkCostStr += " + ">><</if>> <<set _mkCostStr += ($items[_mcId] ? $items[_mcId].name : _mcId) + "×" + _mkNextLvl.cost[_mcId]>> <</for>> <div style="font-size:0.71rem;color:var(--amber-dim);margin-bottom:0.06rem;"> → <<print _mkNextLvl.label>>:<<print _mkCostStr>> </div> <<set _mkUpLabel = "⬆ 升级(" + _mkNextLvl.label + ")">> <<link _mkUpLabel>><<doUpgrade _mkId>><<goto "机械室">><</link>> <<else>> <div style="font-size:0.71rem;color:var(--teal-bright);opacity:0.7;">✓ 已达最高等级</div> <</if>> </div> <</capture>> <</for>> <div style="margin-top:0.4rem;font-size:0.75rem;">[[← 返回走廊|走廊]]</div> <</nobr>>
<<nobr>> <<if !$activeCombat>><<goto ($combatReturn || "仓外探索")>><</if>> <<if $activeCombat.result>><<goto "战斗结算">><</if>> <<set _p = $activeCombat.player>> <<set _e = $activeCombat.enemy>> /* 敌方状态描述 key */ <<set _eStateKey = (_e.alertness >= 50 ? "high" : "low")+"_"+(_e.morale >= 40 ? "high" : "low")>> <<set _eStateText = _e.stateDesc[_eStateKey] || "">> /* 体力阶段文本 */ <<set _eHpPct = _e.hpMax > 0 ? Math.floor(_e.hp / _e.hpMax * 100) : 0>> <<set _eHpDesc = "">> <<if _eHpPct <= 25>> <<set _eHpDesc = _e.hpDesc[25] || _e.hpDesc[50] || "">> <<elseif _eHpPct <= 50>> <<set _eHpDesc = _e.hpDesc[50] || "">> <</if>> /* 伤势阶段文本 */ <<set _eInjPct = _e.injuryMax > 0 ? Math.floor(_e.injury / _e.injuryMax * 100) : 0>> <<set _eInjDesc = "">> <<if _eInjPct >= 70>> <<set _eInjDesc = _e.injuryDesc[70] || _e.injuryDesc[40] || "">> <<elseif _eInjPct >= 40>> <<set _eInjDesc = _e.injuryDesc[40] || "">> <</if>> <<set _hpCrisis = _p.hp <= 0>> <div style="max-width:520px;margin:0 auto;padding:0.5rem 0.4rem;font-size:0.82rem;"> <!-- ══ 敌方信息 ══ --> <div style="border:1px solid var(--teal-dim,#2a5a5a);border-radius:4px;padding:0.5rem 0.75rem;margin-bottom:0.35rem;"> <div style="display:flex;justify-content:space-between;align-items:baseline;margin-bottom:0.2rem;"> <span style="color:var(--teal-bright,#4ecdc4);font-size:0.9rem;font-weight:bold;"><<print _e.name>></span> <span style="color:var(--muted,#8a8070);font-size:0.74rem;">回合 <<print $activeCombat.round>></span> </div> <div style="color:var(--bone,#d4c9a8);font-size:0.8rem;line-height:1.65;margin-bottom:0.2rem;"><<print _eStateText>></div> <<if _eHpDesc || _eInjDesc>> <div style="color:var(--muted,#8a8070);font-size:0.76rem;font-style:italic;margin-bottom:0.2rem;"> <<if _eHpDesc>><<print _eHpDesc>><<if _eInjDesc>> <</if>><</if>><<if _eInjDesc>><<print _eInjDesc>><</if>> </div> <</if>> <div style="display:grid;grid-template-columns:repeat(5,1fr);gap:0.1rem;font-size:0.73rem;color:var(--muted,#8a8070);text-align:center;"> <div>伤势<br><span style="color:var(--danger-bright,#e74c3c);"><<print _e.injury>>/<<print _e.injuryMax>></span></div> <div>体力<br><span style="color:var(--teal-bright,#4ecdc4);"><<print _e.hp>></span></div> <div>警觉<br><span style="color:var(--bone,#d4c9a8);"><<print _e.alertness>></span></div> <div>士气<br><span style="color:var(--bone,#d4c9a8);"><<print _e.morale>></span></div> <div>破绽<br><span style="color:var(--accent,#f39c12);"><<print "◆".repeat(_e.flaws)>><<print "◇".repeat(3-_e.flaws)>></span></div> </div> </div> <!-- ══ 玩家状态 ══ --> <div style="border:1px solid var(--bone-dim,#3a3025);border-radius:4px;padding:0.35rem 0.75rem;margin-bottom:0.35rem;"> <div style="display:grid;grid-template-columns:repeat(5,1fr);gap:0.1rem;font-size:0.73rem;color:var(--muted,#8a8070);text-align:center;"> <div>体力<br><span style="color:<<print _p.hp <= 0 ? 'var(--danger-bright,#e74c3c)' : 'var(--teal-bright,#4ecdc4)'>>;font-size:0.76rem;"><<print _p.hp>>/<<print _p.hpMax>></span></div> <div>伤势<br><span style="color:<<print _p.injury >= 70 ? 'var(--danger-bright,#e74c3c)' : 'var(--bone,#d4c9a8)'>>;"><<print _p.injury>>/100</span></div> <div>警觉<br><span style="color:var(--bone,#d4c9a8);"><<print _p.alertness>></span></div> <div>士气<br><span style="color:<<print _p.morale <= 20 ? 'var(--danger-bright,#e74c3c)' : 'var(--bone,#d4c9a8)'>>;"><<print _p.morale>></span></div> <div>破绽<br><span style="color:<<print _p.flaws > 0 ? 'var(--danger-bright,#e74c3c)' : 'var(--muted,#8a8070)'>>;"><<print "◆".repeat(_p.flaws)>><<print "◇".repeat(3-_p.flaws)>></span></div> </div> </div> <!-- ══ 回合日志 ══ --> <<if $activeCombat.log>> <div style="border-left:2px solid var(--teal-dim,#2a5a5a);padding:0.2rem 0.5rem;margin-bottom:0.35rem;font-size:0.78rem;color:var(--bone,#d4c9a8);line-height:1.75;"><<print $activeCombat.log>></div> <</if>> <!-- ══ 行动宫格 ══ --> <<set _btnBase = "border-radius:3px;padding:0.55rem 0.3rem;text-align:center;cursor:pointer;">> <<set _btnTeal = "border:1px solid var(--teal-dim,#2a5a5a);">> <<set _btnBone = "border:1px solid var(--bone-dim,#3a3025);">> <<set _btnDim = "border:1px solid var(--bone-dim,#3a3025);opacity:0.38;color:var(--muted,#8a8070);">> <<if _hpCrisis>> <!-- 体力危机面板 --> <div style="color:var(--danger-bright,#e74c3c);font-size:0.77rem;text-align:center;margin-bottom:0.3rem;">⚠ 体力耗尽,行动受限</div> <div style="display:grid;grid-template-columns:1fr 1fr;gap:0.35rem;"> <div style="<<print _btnBase>><<print _btnBone>>"><<link "休息">><<combatExecRound "休息">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<goto "战斗">><</if>><</link>></div> <div style="<<print _btnBase>><<print _btnBone>>"><<link "道具">><<set $activeCombat.phase = "item">><<goto "战斗">><</link>></div> <div style="<<print _btnBase>><<print _btnBone>>"><<link "逃跑">><<combatExecRound "逃跑">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<goto "战斗">><</if>><</link>></div> <div style="<<print _btnBase>><<print _btnDim>>">行动不可用</div> </div> <<elseif $activeCombat.phase === "main">> <div style="display:grid;grid-template-columns:1fr 1fr;gap:0.35rem;"> <div style="<<print _btnBase>><<print _btnTeal>>"><<link "行动">><<set $activeCombat.phase = "action">><<goto "战斗">><</link>></div> <div style="<<print _btnBase>><<print _btnTeal>>"><<link "道具">><<set $activeCombat.phase = "item">><<goto "战斗">><</link>></div> <div style="<<print _btnBase>><<print _btnBone>>"><<link "休息">><<combatExecRound "休息">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<goto "战斗">><</if>><</link>></div> <div style="<<print _btnBase>><<print _btnBone>>"><<link "逃跑">><<combatExecRound "逃跑">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<goto "战斗">><</if>><</link>></div> </div> <<elseif $activeCombat.phase === "action">> <div style="text-align:right;margin-bottom:0.2rem;font-size:0.75rem;"><<link "← 返回">><<set $activeCombat.phase = "main">><<goto "战斗">><</link>></div> <div style="display:grid;grid-template-columns:1fr 1fr;gap:0.35rem;"> <div style="<<print _btnBase>><<print _btnTeal>>"><<link "进攻">><<combatExecRound "进攻">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<set $activeCombat.phase = "main">><<goto "战斗">><</if>><</link>></div> <div style="<<print _btnBase>><<print _btnTeal>>"><<link "警戒">><<combatExecRound "警戒">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<set $activeCombat.phase = "main">><<goto "战斗">><</if>><</link>></div> <div style="<<print _btnBase>><<print _btnBone>>"><<link "防御">><<combatExecRound "防御">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<set $activeCombat.phase = "main">><<goto "战斗">><</if>><</link>></div> <div style="<<print _btnBase>><<print _btnBone>>"><<link "观察">><<combatExecRound "观察">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<set $activeCombat.phase = "main">><<goto "战斗">><</if>><</link>></div> </div> <<elseif $activeCombat.phase === "item">> <div style="text-align:right;margin-bottom:0.2rem;font-size:0.75rem;"><<link "← 返回">><<set $activeCombat.phase = "main">><<goto "战斗">><</link>></div> <div style="display:grid;grid-template-columns:1fr 1fr;gap:0.35rem;"> <!-- 攻势:暴露破绽 --> <div style="<<print _btnBase>><<print _btnTeal>>"> <<link "诱饵[测]">><<combatExecRound "item_add_flaw">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<set $activeCombat.phase = "main">><<goto "战斗">><</if>><</link>> <div style="font-size:0.68rem;color:var(--muted,#8a8070);margin-top:0.1rem;">敌方破绽+2</div> </div> <!-- 恢复:体力 --> <div style="<<print _btnBase>><<print _btnBone>>"> <<link "恢复剂[测]">><<combatExecRound "item_restore_hp">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<set $activeCombat.phase = "main">><<goto "战斗">><</if>><</link>> <div style="font-size:0.68rem;color:var(--muted,#8a8070);margin-top:0.1rem;">体力+30</div> </div> <!-- 辅助1:必中 --> <div style="<<print _btnBase>><<print _btnBone>>"> <<link "瞄准镜[测]">><<combatExecRound "item_must_hit">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<set $activeCombat.phase = "main">><<goto "战斗">><</if>><</link>> <div style="font-size:0.68rem;color:var(--muted,#8a8070);margin-top:0.1rem;">下击必中</div> </div> <!-- 辅助2:锁定逃跑 --> <div style="<<print _btnBase>><<print _btnBone>>"> <<link "声爆弹[测]">><<combatExecRound "item_lock_escape">><<if $activeCombat.result>><<goto "战斗结算">><<else>><<set $activeCombat.phase = "main">><<goto "战斗">><</if>><</link>> <div style="font-size:0.68rem;color:var(--muted,#8a8070);margin-top:0.1rem;">锁定逃跑</div> </div> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set _npcN = ($npcState && $npcState.npcName) ? $npcState.npcName : "陌生商人">> <<set _npcRet = $npcReturn || "航行">> <div style="max-width:520px;margin:0 auto;padding:0.6rem;"> <div style="border:1px solid var(--amber-bright);border-radius:4px;padding:0.5rem 0.8rem;"> <div style="color:var(--amber-bright);font-size:0.8rem;margin-bottom:0.2rem;">🏪 <<print _npcN>> 的商店</div> <div style="background:rgba(180,140,60,0.08);border:1px dashed #876;border-radius:3px;padding:0.25rem 0.5rem;font-size:0.72rem;color:#a98;margin-bottom:0.25rem;">🔧 施工中 — NPC 商店 v0(占位)<br>NPC ID:<<print ($npcState && $npcState.npcId) ? $npcState.npcId : "unknown">></div> <div style="font-size:0.82rem;color:var(--bone);line-height:1.8;margin-bottom:0.25rem;"><<print _npcN>>向你展示了一些货物。购买系统尚在建设中。</div> <<link "离开商店">> <<set $lastSmallEventText = "和" + _npcN + "打了个招呼,暂时没有交易。">> <<set $npcState = null>><<goto _npcRet>> <</link>> </div></div> <</nobr>>
<<nobr>> <<set _npcN = ($npcState && $npcState.npcName) ? $npcState.npcName : "陌生人">> <<set _npcRet = $npcReturn || "航行">> <div style="max-width:520px;margin:0 auto;padding:0.6rem;"> <div style="border:1px solid var(--teal-bright);border-radius:4px;padding:0.5rem 0.8rem;"> <div style="color:var(--teal-bright);font-size:0.8rem;margin-bottom:0.2rem;">💬 与 <<print _npcN>> 对话</div> <div style="background:rgba(0,180,150,0.05);border:1px dashed #466;border-radius:3px;padding:0.25rem 0.5rem;font-size:0.72rem;color:#8aa;margin-bottom:0.25rem;">🔧 施工中 — NPC 对话 v0(占位)<br>NPC ID:<<print ($npcState && $npcState.npcId) ? $npcState.npcId : "unknown">></div> <div style="font-size:0.82rem;color:var(--bone);line-height:1.8;margin-bottom:0.25rem;"><<print _npcN>>打量了你一会儿,若有所思。对话系统尚在建设中。</div> <<link "结束对话">> <<set $lastSmallEventText = "和" + _npcN + "简短地交谈了几句。">> <<set $npcState = null>><<goto _npcRet>> <</link>> </div></div> <</nobr>>
<<nobr>> <div style="max-width:520px;margin:0 auto;padding:0.6rem;"> <div style="border:1px solid #88f;border-radius:4px;padding:0.5rem 0.8rem;"> <div style="color:#aaf;font-size:0.8rem;margin-bottom:0.2rem;">✦ 主线触发点</div> <div style="background:rgba(100,100,255,0.06);border:1px dashed #558;border-radius:3px;padding:0.25rem 0.5rem;font-size:0.72rem;color:#99c;margin-bottom:0.25rem;">🔧 施工中 — 主线系统 v0(占位)<br>questFlags:<<print JSON.stringify($questFlags)>></div> <div style="font-size:0.82rem;color:var(--bone);line-height:1.8;margin-bottom:0.25rem;">某种更深的力量在此处留下了印记。主线系统尚在建设中,你记录下了这个地点的坐标。</div> <<set _mqRet = $npcReturn || $combatReturn || "航行">> <<link "离开">> <<set $lastSmallEventText = "在此处感受到了某种异常,记录了坐标。">> <<set $npcReturn = null>><<set $combatReturn = null>><<goto _mqRet>> <</link>> </div></div> <</nobr>>
<<nobr>> <<widget "questDefs">> /* ══════════════════════════════════ 主线任务链 $questChain 每个节点字段: id 唯一标识 title 日记标题 logEntry 触发时写入日记的文字(第一人称日记体) completedLog 完成后追加的文字 trigger 触发条件:{type, ...} type:"auto" — 满足 condition 后自动触发 type:"item" — 拾取指定物品 type:"wsChild" — 完成指定 wsChild type:"flag" — questFlags 中某个旗标为 true type:"npcMet" — 首次与指定 NPC 相遇 condition 前置条件检查字符串(JS 表达式,可用 $questProgress) worldHook 挂载到某个 worldScene/largeScene 作为触发点 {wsId:"wreck_site", childId:"mq_q01_wsChild"} reward 完成奖励 [{id,qty:[min,max]}] ══════════════════════════════════ */ <<set $questChain = [ /* ── 第0节:序章(自动触发,游戏开始时)── */ { id: "mq_00_prologue", title: "第1段主线", logEntry: "【占位】第1段主线日记文本。触发条件:auto(每次下水自动推进)。", completedLog: "【占位】第1段主线完成后追加文字。", trigger: { type: "auto" }, condition: "always", worldHook: null, reward: [] }, /* ── 第1节:漂流瓶(中型事件触发,需出仓)── */ { id: "mq_01_drift_bottle", title: "第2段主线", logEntry: "【占位】第2段主线日记文本。触发条件:wsChild(完成特定中型事件子节点 mq_q00_complete)。", completedLog: "【占位】第2段主线完成后追加文字。", trigger: { type: "wsChild", childId: "mq_q00_complete" }, condition: "$questProgress === 0", worldHook: null, reward: [] }, /* ── 第2节:占位节点 C(支线触发可以用同样结构)── */ { id: "mq_02_placeholder", title: "第3段主线", logEntry: "【占位】第3段主线日记文本。触发条件:flag(mq_01_found_ruin旗标)。", completedLog: "【占位】第3段主线完成后追加文字。", trigger: { type: "flag", flag: "mq_01_found_ruin" }, condition: "$questProgress === 1", worldHook: null, reward: [] } ]>> /* ══════════════════════════════════ 支线任务定义 $sideQuestDefs 每条支线绑定一个 NPC(或地点) nodes 数组结构与主线节点相同 ══════════════════════════════════ */ <<set $sideQuestDefs = { "sq_placeholder_npc": { npcId: "placeholder_npc", title: "【占位·支线·陌生商人】", nodes: [ { id: "sq_pnpc_00", title: "初次相遇", logEntry: "(施工中)支线第一节日记占位。第一次遇到了这个人,他说了些让我在意的话。", completedLog: "(施工中)支线第一节完成。", trigger: { type: "npcMet", npcId: "placeholder_npc" }, condition: "always", reward: [] }, { id: "sq_pnpc_01", title: "委托", logEntry: "(施工中)支线第二节日记占位。他托付给我一件事。", completedLog: "(施工中)支线第二节完成。", trigger: { type: "flag", flag: "sq_pnpc_met_twice" }, condition: "always", reward: [] } ] } }>> <</widget>> <</nobr>>
<<nobr>> <<widget "questCheck">> /* 调用:<> type: "wsChild" — 完成 wsChild,id 为 childId "flag" — 设置旗标后检查,id 为 flag key "item" — 拾取物品,id 为 itemId "npcMet" — 遇见 NPC,id 为 npcId "auto" — 每次进入新场景时自动检查 结果:命中则写日记、推进进度、设 $questNotify */ <<if !$questChain>><<questDefs>><</if>> <<set _qcType = ($args && $args[0]) ? String($args[0]) : "auto">> <<set _qcId = ($args && $args[1]) ? String($args[1]) : "">> /* ── 主线检查 ── */ <<if $questProgress < $questChain.length>> <<set _qcNode = $questChain[$questProgress]>> <<set _qcMatch = false>> <<if _qcNode.trigger.type === _qcType>> <<if _qcType === "auto">><<set _qcMatch = true>> <<elseif _qcType === "wsChild" && _qcId === _qcNode.trigger.childId>><<set _qcMatch = true>> <<elseif _qcType === "flag" && _qcId === _qcNode.trigger.flag>><<set _qcMatch = true>> <<elseif _qcType === "item" && _qcId === _qcNode.trigger.itemId>><<set _qcMatch = true>> <<elseif _qcType === "npcMet" && _qcId === _qcNode.trigger.npcId>><<set _qcMatch = true>> <</if>> <</if>> <<if _qcMatch>> /* 追加日记条目 */ <<run $questLog.push({ id: _qcNode.id, title: _qcNode.title, text: _qcNode.logEntry, day: $day || 0, type: "main" })>> <<set $questNotify = "✦ 日记已更新:" + _qcNode.title>> <<set $questProgress = $questProgress + 1>> /* 主线触发中型事件通知(优先级低:不覆盖已有事件)*/ <<if !$activeEvent>> <<set $activeEvent = {id:"quest_"+_qcNode.id, name:"✦ "+_qcNode.title, desc:"主线日记已更新,前往书桌查看。", type:"event", actions:["查看日志","稍后再看"]}>> <<set $sailspd = 0>> <</if>> <</if>> <</if>> /* ── 支线检查 ── */ <<if $sideQuestDefs>> <<set _sqKeys = Object.keys($sideQuestDefs)>> <<for _sqi = 0; _sqi < _sqKeys.length; _sqi++>> <<set _sqId = _sqKeys[_sqi]>> <<set _sqDef = $sideQuestDefs[_sqId]>> <<set _sqProg = (typeof $sideQuestProgress[_sqId] === "number") ? $sideQuestProgress[_sqId] : 0>> <<if _sqProg < _sqDef.nodes.length>> <<set _sqNode = _sqDef.nodes[_sqProg]>> <<set _sqMatch = false>> <<if _sqNode.trigger.type === _qcType>> <<if _qcType === "auto">><<set _sqMatch = false>>/* auto不触发支线,由npcMet/flag触发 */ <<elseif _qcType === "wsChild" && _qcId === _sqNode.trigger.childId>><<set _sqMatch = true>> <<elseif _qcType === "flag" && _qcId === _sqNode.trigger.flag>><<set _sqMatch = true>> <<elseif _qcType === "item" && _qcId === _sqNode.trigger.itemId>><<set _sqMatch = true>> <<elseif _qcType === "npcMet" && _qcId === _sqNode.trigger.npcId>><<set _sqMatch = true>> <</if>> <</if>> <<if _sqMatch>> <<if typeof $sideQuestLog[_sqId] !== "object">><<set $sideQuestLog[_sqId] = []>><</if>> <<run $sideQuestLog[_sqId].push({ id: _sqNode.id, title: _sqNode.title, text: _sqNode.logEntry, day: $day || 0 })>> <<set $sideQuestProgress[_sqId] = _sqProg + 1>> <<set $questNotify = ($questNotify || "") + " ✧ 支线更新:" + _sqDef.title>> <</if>> <</if>> <</for>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "npcDefs">> /* ══════════════════════════════════ NPC 定义表 $npcDefTable 字段说明: id 唯一标识 name 显示名 type "trader" / "drifter" / "salvager" spawnCtx 出现上下文 ["sailing","anchored"] condition 出现条件(JS 字符串,返回 bool) cooldownDays 同一 NPC 再次出现的冷却天数 weight 出现权重 greeting 初次见面台词池 reGreeting 再次见面台词池 chat 闲聊台词池(随机取1) tradeComment 进入商店时台词池 buyComment 购买后台词池 shop 商品列表 [{id, name, price, qty}] price 单位:珍珠数量 sideQuestId 绑定的支线 ID(可选,触发 questCheck "npcMet") ══════════════════════════════════ */ <<set $npcDefTable = { /* ── 水面补给船:靠近水面时出现的小型贸易船 ── */ "supply_drifter": { id: "supply_drifter", name: "漂泊补给船", type: "trader", spawnCtx: ["sailing", "anchored"], condition: "$depth <= 100", cooldownDays: 3, weight: 20, greeting: ["嘿,独自出海?真有胆量。我有些物资,看你需不需要。", "哟,这片海域不常见到你这样的船。有兴趣交易吗?"], reGreeting: ["又见面了。东西还够不够用?", "老朋友!我这次进了些新货。"], chat: ["这片海最近不太平,听说南边有什么大家伙出没。", "珍珠越来越值钱了,有人在大量收购,也不知道干什么用。", "我在海上漂了二十年,什么稀奇古怪的东西都见过。"], tradeComment: ["都是实用的东西,价格公道。", "挑吧,不合适的我不勉强。"], buyComment: ["好眼光。", "这东西值。", "拿好,用得上的。"], shop: [ { id: "fish_oil", name: "鱼油", price: 2, qty: 6 }, { id: "wreck_wood", name: "沉船木材", price: 1, qty: 5 }, { id: "rubber_seal", name: "橡胶密封件",price: 3, qty: 3 }, { id: "metal", name: "金属材料", price: 1, qty: 8 } ], sideQuestId: null }, /* ── 深海废品商:只在深水区出现 ── */ "deep_salvager": { id: "deep_salvager", name: "深渊废品商", type: "salvager", spawnCtx: ["anchored"], condition: "$depth >= 150", cooldownDays: 5, weight: 10, greeting: ["你也来这深处淘东西?我收购残骸零件,也卖些稀罕货。", "黑暗里什么都有,就看你敢不敢捡。"], reGreeting: ["又下来了。深水让人上瘾,不是吗?", "嘿,还活着。那就做生意吧。"], chat: ["越深的地方,东西越好。也越危险。", "我在这里见过没有名字的东西。它没伤我,我也没惹它。", "据说最深处有一片发光的平原。没人能证实,但也没人否认。"], tradeComment: ["残骸出来的东西,各有各的故事。", "不要问这些东西从哪来的。"], buyComment: ["明智的选择。", "这东西在深处很难找的。"], shop: [ { id: "wreck_steel", name: "沉船钢材", price: 3, qty: 4 }, { id: "iron", name: "铁块", price: 2, qty: 6 }, { id: "glass", name: "玻璃", price: 2, qty: 4 }, { id: "relic_log", name: "古旧航行日志",price: 8, qty: 2 } ], sideQuestId: null }, /* ── 维奥娜:肉铺 ── */ "viona_butcher": { id: "viona_butcher", name: "维奥娜", type: "trader", spawnCtx: ["sailing", "anchored"], condition: "always", cooldownDays: 4, weight: 15, greeting: ["总之……请随便看。", "今天不会给你优惠的。", "我有闻到你身上的海腥味……抱歉,对我来说很恶心。", "是不是有几天没来了?好好吃饭对每个人都很重要。", "是不是来得太频繁了?没法做出好吃的东西的话,多多反思自己吧。"], reGreeting: ["总之……请随便看。", "今天不会给你优惠的。", "是不是有几天没来了?好好吃饭对每个人都很重要。", "是不是来得太频繁了?没法做出好吃的东西的话,多多反思自己吧。"], chat: ["越新鲜的东西,越考验厨师的手艺。刚好我很勤劳,而你很优秀。", "这些东西对你的资产来说,贵了吧?", "我有段时间非常、非常地饥饿,甚至连在吃肉之前去烹饪的耐心都没有……因此,我保证本店所售的肉,绝对地适合生食。", "你饿吗?饿了才来买食材,是不会规划时间的表现。"], tradeComment: ["越新鲜的东西,越考验厨师的手艺。刚好我很勤劳,而你很优秀。", "这些东西对你的资产来说,贵了吧?", "我有段时间非常、非常地饥饿,甚至连在吃肉之前去烹饪的耐心都没有……因此,我保证本店所售的肉,绝对地适合生食。", "你饿吗?饿了才来买食材,是不会规划时间的表现。"], buyComment: ["其实我很想尝尝你会做出什么样的食物……如果有机会的话。", "总得来说……就是这些。", "总感觉味道很香呢……它们会变成美味的食物的。", "你很需要的话……也不能给你赠品。我不是慈善家。", "再见。请规律且健康地来购物。"], shop: [ { id: "pork", name: "猪肉", price: 2, qty: 5 }, { id: "lamb", name: "羊肉", price: 3, qty: 4 }, { id: "beef", name: "牛肉", price: 4, qty: 3 }, { id: "fish_bone", name: "鱼骨",price: 1, qty: 6 } ], sideQuestId: null } }>> <</widget>> <</nobr>>
<<nobr>> <<widget "spawnNpc">> /* 调用:<> ctx = "sailing" / "anchored" 结果:命中则写入 $activeNpc,否则为 null */ <<if !$npcDefTable>><<npcDefs>><</if>> <<set _snCtx = ($args && $args[0]) ? String($args[0]) : "sailing">> /* 冷却检查(tick冷却优先)*/ <<if ($npcCooldownTicks || 0) > 0>><<return>><</if>> <<if ($npcSpawnCooldown || 0) > ($day || 0)>><<return>><</if>> /* 已有 NPC 则不再生成 */ <<if $activeNpc>><<return>><</if>> /* 构建候选池 */ <<set _snPool = []>> <<set _snKeys = Object.keys($npcDefTable)>> <<for _sni = 0; _sni < _snKeys.length; _sni++>> <<set _snDef = $npcDefTable[_snKeys[_sni]]>> <<if _snDef.spawnCtx.includes(_snCtx)>> /* 条件检查(字符串 eval 包裹在 try) */ <<set _snOk = false>> <<if _snDef.condition === "always">> <<set _snOk = true>> <<elseif _snDef.condition === "\$depth <= 100">> <<set _snOk = ($depth <= 100)>> <<elseif _snDef.condition === "\$depth >= 150">> <<set _snOk = ($depth >= 150)>> <</if>> <<if _snOk>> <<for _snW = 0; _snW < _snDef.weight; _snW++>> <<run _snPool.push(_snKeys[_sni])>> <</for>> <</if>> <</if>> <</for>> <<if _snPool.length === 0>><<return>><</if>> /* 基础触发概率:每次 sail tick 约 0.1% */ <<set _snRoll = Math.random()>> <<if _snRoll > 0.001>><<return>><</if>> /* 抽取 NPC */ <<set _snId = _snPool[Math.floor(Math.random() * _snPool.length)]>> <<set _snDef = $npcDefTable[_snId]>> <<set $activeNpc = _snDef>> /* 航速归零,强制玩家处理遭遇 */ <<set $sailspd = 0>> /* 触发支线(首次相遇)*/ <<if _snDef.sideQuestId>> <<questCheck "npcMet" _snId>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<if !$npcDefTable>><<npcDefs>><</if>> <<if !$activeNpc>><<goto ($npcReturn || "航行")>><</if>> <<set _ntDef = $activeNpc>> <<set _ntRet = $npcReturn || "航行">> /* 判断是否首次见面 */ <<set _ntMet = $metNpcs[_ntDef.id]>> <<set _ntIsFirst = !_ntMet>> /* 更新见面记录 */ <<if _ntIsFirst>> <<set $metNpcs[_ntDef.id] = { firstDay: ($day||0), meetCount: 1 }>> <<else>> <<set $metNpcs[_ntDef.id].meetCount += 1>> <</if>> /* 随机台词 */ <<set _ntGreetPool = _ntIsFirst ? _ntDef.greeting : _ntDef.reGreeting>> <<set _ntGreet = _ntGreetPool[Math.floor(Math.random() * _ntGreetPool.length)]>> <<set _ntChatLine = _ntDef.chat[Math.floor(Math.random() * _ntDef.chat.length)]>> <div style="max-width:520px;margin:0 auto;padding:0.5rem 0.6rem;"> <div style="border:1px solid var(--teal-bright);border-radius:4px;padding:0.5rem 0.8rem;margin-bottom:0.4rem;"> <div style="color:var(--teal-bright);font-size:0.8rem;margin-bottom:0.3rem;">💬 <<print _ntDef.name>></div> <div style="font-size:0.85rem;color:var(--bone);line-height:1.9;margin-bottom:0.35rem;font-style:italic;">「<<print _ntGreet>>」</div> /* 闲聊选项 */ <<link "闲聊一句">> <<set $npcState = {npcId: _ntDef.id, npcName: _ntDef.name, chatLine: _ntChatLine}>> <<goto "NPC_闲聊">> <</link>><br> /* 商店选项 */ <<if _ntDef.shop && _ntDef.shop.length > 0>> <<link "查看货物">> <<set $npcState = {npcId: _ntDef.id, npcName: _ntDef.name}>> <<set $npcReturn = _ntRet>> <<goto "NPC_商店">> <</link>><br> <</if>> /* 离开 */ <<link "道别离开">> <<set $lastSmallEventText = "和" + _ntDef.name + "道了别。">> <<set $activeNpc = null>> <<set $npcCooldownTicks = _ntDef.cooldownDays * 600>> <<set $npcSpawnCooldown = ($day||0) + _ntDef.cooldownDays>> <<goto _ntRet>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$npcState>><<goto ($npcReturn || "航行")>><</if>> <<set _ncRet = $npcReturn || "航行">> <<set _ncName = $npcState.npcName || "陌生人">> <<set _ncLine = $npcState.chatLine || "……">> <div style="max-width:520px;margin:0 auto;padding:0.5rem 0.6rem;"> <div style="border:1px solid var(--teal-bright);border-radius:4px;padding:0.5rem 0.8rem;margin-bottom:0.4rem;"> <div style="color:var(--teal-bright);font-size:0.8rem;margin-bottom:0.3rem;">💬 <<print _ncName>></div> <div style="font-size:0.85rem;color:var(--bone);line-height:1.9;margin-bottom:0.35rem;font-style:italic;">「<<print _ncLine>>」</div> <div style="font-size:0.78rem;color:var(--bone-dim);margin-bottom:0.3rem;">你点了点头,没有多说什么。</div> <<link "回到对话">><<goto "NPC_对话">><</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$npcDefTable>><<npcDefs>><</if>> <<if !$npcState || !$npcState.npcId>><<goto ($npcReturn || "航行")>><</if>> <<set _nsId = $npcState.npcId>> <<set _nsDef = $npcDefTable[_nsId]>> <<set _nsRet = $npcReturn || "航行">> <<if !_nsDef>><<goto _nsRet>><</if>> /* 进入商店台词 */ <<set _nsEntryLine = _nsDef.tradeComment[Math.floor(Math.random()*_nsDef.tradeComment.length)]>> /* 珍珠数量(store里) */ <<set _nsPearl = 0>> <<if $store && $store["基础材料"]>> <<for _nsPi = 0; _nsPi < $store["基础材料"].length; _nsPi++>> <<if $store["基础材料"][_nsPi].id === "pearl">> <<set _nsPearl = $store["基础材料"][_nsPi].quantity || 0>> <</if>> <</for>> <</if>> <div style="max-width:520px;margin:0 auto;padding:0.5rem 0.6rem;"> <div style="border:1px solid var(--amber-bright);border-radius:4px;padding:0.5rem 0.8rem;margin-bottom:0.4rem;"> <div style="color:var(--amber-bright);font-size:0.8rem;margin-bottom:0.2rem;">🏪 <<print _nsDef.name>> 的货物</div> <div style="font-size:0.78rem;color:var(--bone-dim);font-style:italic;margin-bottom:0.3rem;">「<<print _nsEntryLine>>」</div> <div style="font-size:0.74rem;color:var(--bone-dim);margin-bottom:0.3rem;">💠 持有珍珠:<<print _nsPearl>> 颗</div> /* 商品列表 */ <<for _nsGi = 0; _nsGi < _nsDef.shop.length; _nsGi++>> <<set _nsGoods = _nsDef.shop[_nsGi]>> <<set _nsCanBuy = (_nsPearl >= _nsGoods.price)>> <<capture _nsGoods, _nsCanBuy, _nsPearl>> <div style="display:flex;justify-content:space-between;align-items:center;padding:0.18rem 0;border-bottom:1px solid var(--border-dim);"> <span style="font-size:0.82rem;color:var(--bone);"><<print _nsGoods.name>></span> <span> <span style="font-size:0.76rem;color:var(--amber-bright);margin-right:0.5rem;">💠×<<print _nsGoods.price>></span> <<if _nsCanBuy>> <<link "购买">> <<removeitem "pearl" _nsGoods.price>> <<additem _nsGoods.id 1>> <<set _nsBuyLine = _nsDef.buyComment[Math.floor(Math.random()*_nsDef.buyComment.length)]>> <<set $lastSmallEventText = _nsDef.name + ":「" + _nsBuyLine + "」">> <<goto "NPC_商店">> <</link>> <<else>> <span style="font-size:0.75rem;opacity:0.35;">珍珠不足</span> <</if>> </span> </div> <</capture>> <</for>> <div style="margin-top:0.35rem;"> <<link "结束交易">> <<set $lastSmallEventText = _nsDef.name + "收起了货物,道了声再见。">> <<set $activeNpc = null>> <<set $npcCooldownTicks = _nsDef.cooldownDays * 600>> <<set $npcSpawnCooldown = ($day||0) + _nsDef.cooldownDays>> <<goto _nsRet>> <</link>> <<link "回到对话">><<goto "NPC_对话">><</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<widget "spawnCombat">> /* 调用:<<spawnCombat [forceid]>> 无参数=随机,有forceid=强制 */ <<if !$combatEnemyTable>><<combatEnemyDefs>><</if>> <<set _scForce = ($args && $args[0]) ? String($args[0]) : "">> <<set _scDef = _scForce ? $combatEnemyTable[_scForce] : null>> <<set _scId = _scForce ? _scForce : "">> <<if !_scDef>> /* 深度分层随机池 */ <<set _scPool = []>> <<if $depth <= 80>> <<run _scPool.push("jellyfish_swarm", "jellyfish_swarm", "armored_crab")>> <<elseif $depth <= 200>> <<run _scPool.push("armored_crab", "armored_crab", "deep_eel", "patrol_shark")>> <<else>> <<run _scPool.push("patrol_shark", "deep_eel", "angler_lurker", "angler_lurker")>> <</if>> <<set _scId = _scPool[Math.floor(Math.random() * _scPool.length)]>> <<set _scDef = $combatEnemyTable[_scId]>> <</if>> <<if !_scDef>><<return>><</if>> <<combatInit _scId "仓外探索">> <<goto "战斗">> <</widget>> <</nobr>>
<<nobr>> <<widget "smallEventPanel">> /* 渲染当前 $activeSmallEvent 的描述+选项 $args[0] = "sailing" | "anchored"(决定跳转目标,默认 anchored) 在 <<repeat>> 环境中必须通过 widget 间接调用,不能内联 <<for>> */ <<if !$smallEventDefs>><<smallEventTable>><</if>> <<if $activeSmallEvent>> <<set _spId = String($activeSmallEvent.id)>> <<set _spDef = $smallEventDefs[_spId]>> <<if _spDef>> <<set _spCtxSail = ($args && $args[0] === "sailing")>> <div style="border:1px solid var(--teal-bright);border-radius:3px;padding:0.3rem 0.5rem;margin-bottom:0.25rem;background:rgba(0,180,150,0.04);"> <div style="font-size:0.74rem;color:var(--teal-bright);margin-bottom:0.08rem;">⚑ <<print _spDef.name>></div> <div style="font-size:0.8rem;color:var(--bone);line-height:1.75;margin-bottom:0.12rem;"><<print $activeSmallEvent.stageDesc>></div> <div style="font-size:0.76rem;"> <<for _spai = 0; _spai < $activeSmallEvent.actions.length; _spai++>> <<set _spaAct = $activeSmallEvent.actions[_spai]>> <<capture _spaAct, _spCtxSail>> <<if _spCtxSail>> <<link _spaAct>><<resolveSmallEvent _spaAct>><</link>> · <<else>> <div style="margin-bottom:0.05rem;"><<link _spaAct>><<resolveSmallEvent _spaAct>><</link>></div> <</if>> <</capture>> <</for>> </div> </div> <<if $lastSmallEventText>> <div style="border-left:2px solid var(--teal-bright);padding:0.15rem 0.4rem;margin-bottom:0.15rem;font-size:0.78rem;color:var(--bone);"><<print $lastSmallEventText>></div> <<set $lastSmallEventText = "">> <</if>> <<else>> <<set $activeSmallEvent = null>> <</if>> <<else>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "checkEnvEffects">> /* ────────────────────────────────────────── checkEnvEffects — 第四批 调用时机:每次 sail tick(checkEvent 前) 每次 exploreSearch 每次 diveStep 功能: ① envEffects 条目逐一推进生长周期 ② ecoBonds 条目记录最后访问日并控制冷却 ────────────────────────────────────────── */ /* ── envEffects:遍历所有持久环境效果 ── */ <<for _ceI = 0; _ceI < $envEffects.length; _ceI++>> <<set _ceEff = $envEffects[_ceI]>> /* 只处理当前地形+深度匹配的条目 */ <<set _ceTMatch = (_ceEff.terrain === $maptype)>> <<set _ceDMatch = ($depth >= _ceEff.depthMin && $depth <= _ceEff.depthMax)>> <<if !_ceTMatch || !_ceDMatch>><<continue>><</if>> /* kelp_farm:海带农场生长周期 */ <<if _ceEff.type === "kelp_farm">> <<set _ceAge = ($day || 0) - (_ceEff.plantedDay || 0)>> <<if _ceEff.state === "growing" && _ceAge >= 10>> <<set $envEffects[_ceI].state = "ready">> <</if>> /* ready 状态下提示玩家可收获(UI 在 smallEventTable 的影响类事件里处理) */ <</if>> /* 占位:其他影响类型后续扩展 */ <</for>> /* ── ecoBonds:冷却检查(不修改 bond 值,只做访问时间记录) ── */ <<set _ceBKeys = Object.keys($ecoBonds)>> <<for _ceBI = 0; _ceBI < _ceBKeys.length; _ceBI++>> <<set _ceBK = _ceBKeys[_ceBI]>> <<set _ceBnd = $ecoBonds[_ceBK]>> <<if !_ceBnd.active>><<continue>><</if>> /* 地形+深度匹配才处理 */ <<set _ceBTM = (_ceBnd.terrain === $maptype)>> <<set _ceBDM = ($depth >= _ceBnd.depthMin && $depth <= _ceBnd.depthMax)>> <<if !_ceBTM || !_ceBDM>><<continue>><</if>> /* 写入最后访问日(供好感类事件读取,不在此处修改 bond) */ <<set $ecoBonds[_ceBK].lastVisit = $day || 0>> <</for>> <</widget>> <</nobr>>
<<nobr>> <<widget "spawnSmallEvent">> /* ────────────────────────────────────────── spawnSmallEvent — 第二批实装 调用:<<spawnSmallEvent ctx [mult]>> ctx = "sailing" / "anchored" / "outside" mult = 概率倍数(可选,默认 1) 结果:命中则写入 $pendingEvent,否则置 null ────────────────────────────────────────── */ /* 参数读取(安全访问 $args,修复启动期 Warning) */ <<set _spCtx = ($args && $args.length > 0) ? String($args[0]) : $currentContext>> <<set _spMult = ($args && $args.length > 1) ? Number($args[1]) : 1>> /* 上下文校验 */ <<if _spCtx !== "sailing" && _spCtx !== "anchored" && _spCtx !== "outside">> <<set _spCtx = $currentContext>> <</if>> /* 初始化事件池定义 */ <<if !$smallEventDefs>><<smallEventTable>><</if>> /* ── 优先:就近 kelp_farm 成熟检查 ── */ <<set _spKelpReady = false>> <<for _spKI = 0; _spKI < $envEffects.length; _spKI++>> <<set _spKEff = $envEffects[_spKI]>> <<if _spKEff.type === "kelp_farm" && _spKEff.state === "ready" && _spKEff.terrain === $maptype && $depth >= _spKEff.depthMin && $depth <= _spKEff.depthMax>> <<set _spKelpReady = true>> <<break>> <</if>> <</for>> <<if _spKelpReady && !$activeSmallEvent>> <<set _spKD = $smallEventDefs["kelp_harvest"]>> <<if _spKD>> <<set $pendingEvent = {id:"kelp_harvest", name:_spKD.name, stageIdx:0, stageDesc:_spKD.stages[0].desc, actions:_spKD.stages[0].actions, lootLog:""}>> <<return>> <</if>> <</if>> /* ── 过滤候选池 ── */ <<set _spCands = []>> <<set _spKeys = Object.keys($smallEventDefs)>> <<for _spI = 0; _spI < _spKeys.length; _spI++>> <<set _spId = _spKeys[_spI]>> <<set _spDef = $smallEventDefs[_spId]>> /* 上下文过滤 */ <<set _spCtxOK = false>> <<if _spDef.context>> <<for _spCI = 0; _spCI < _spDef.context.length; _spCI++>> <<if _spDef.context[_spCI] === _spCtx>> <<set _spCtxOK = true>> <<break>> <</if>> <</for>> <<else>> <<set _spCtxOK = true>> <</if>> <<if !_spCtxOK>><<continue>><</if>> /* 地形过滤 */ <<set _spTOK = false>> <<if _spDef.terrain>> <<for _spTI = 0; _spTI < _spDef.terrain.length; _spTI++>> <<if _spDef.terrain[_spTI] === $maptype>> <<set _spTOK = true>> <<break>> <</if>> <</for>> <<else>> <<set _spTOK = true>> <</if>> <<if !_spTOK>><<continue>><</if>> /* 深度过滤 */ <<set _spDOK = true>> <<if _spDef.depthRange>> <<if $depth < _spDef.depthRange[0] || $depth > _spDef.depthRange[1]>> <<set _spDOK = false>> <</if>> <</if>> <<if !_spDOK>><<continue>><</if>> <<set _spCands[_spCands.length] = _spId>> <</for>> /* Fisher-Yates 乱序 */ <<for _spI = _spCands.length - 1; _spI > 0; _spI-->> <<set _spJ = Math.floor(Math.random() * (_spI + 1))>> <<set _spTmp = _spCands[_spI]>> <<set _spCands[_spI] = _spCands[_spJ]>> <<set _spCands[_spJ] = _spTmp>> <</for>> /* 逐一掷骰,首中写入 $pendingEvent */ <<set $pendingEvent = null>> <<for _spI = 0; _spI < _spCands.length; _spI++>> <<set _spD2 = $smallEventDefs[_spCands[_spI]]>> <<if _spD2 && Math.random() < _spD2.baseChance * _spMult>> <<set $pendingEvent = {id:_spCands[_spI], name:_spD2.name, stageIdx:0, stageDesc:_spD2.stages[0].desc, actions:_spD2.stages[0].actions, lootLog:""}>> <<break>> <</if>> <</for>> <</widget>> <</nobr>>
此片段不会被游戏调用,纯作内置开发笔记。 ══════════════════════════════════════════ 六维 · 角色状态 ══════════════════════════════════════════ $hunger 饱腹度 0-100;每小时自然下降 $water 饮水度 0-100;每小时下降更快 $power 体力 0-100;睡眠/进食恢复 $life 生命 0-100;掉到0=死亡 $san 安定值 0-100;低=触发异常事件 $tre 压力 0-100;高=恐惧/减效 $magic 魔力 0-100;炼金消耗 $tem 体感温度(℃);影响六维消耗 $wet 潮湿度;影响温度散失 ══════════════════════════════════════════ 时间 · 世界 ══════════════════════════════════════════ $minute/$hour/$day/$season 游戏内时间 $timepass 每帧累计分钟数,<<time>>消费 $weather 0-9 天气索引;$showweather[]对应名称 $worldtem 环境温度(℃) $seasontem 季节基础温度 $weatem[] 各天气对温度的修正 ══════════════════════════════════════════ 航行 · 地图 ══════════════════════════════════════════ $depth 当前深度(m) $depthdeep 当前地区最大深度(m) $map 当前位置坐标(原始单位,1单位=1m) $maplim 当前地区总跨度(原始单位) $mapspan 显示用坐标=floor($map/50) $maplimspan 显示用跨度=floor($maplim/50) $maptype 当前地形 sand/flat/cliff/grass/reef/forest $sailspd 当前速度(每秒移动量) $spdmax 最高速度上限(受推进器升级影响) $sailtime 航行计划总时间 $sailMode "travel"=航行中 / "explore"=锚定 $fuel 燃料量(当前) $fuelMax 燃料槽上限(受fuel_tank升级影响) $driftMode true=燃料耗尽漂流,禁止下潜 $shell 船体完整度 0-100 $sys 系统完整度 0-100 ══════════════════════════════════════════ 地区切换预生成 ══════════════════════════════════════════ $nextAreas[] 预生成的3个下一区域选项 [{type,depth,maplim,label}] $nextAreasReady 0/1 是否已预生成 $selectedNextArea 玩家选择的区域索引(0/1/2) $prevArea 上一个区域快照 {type,depth,maplim} ══════════════════════════════════════════ 场景系统 ══════════════════════════════════════════ $worldScene 当前活动的中型场景对象 .id 场景类型 ID(wreck_site等) .name 显示名 .approachDesc 接近时的描述 .state "pending"/"approaching"/"inside"/"done" .mapStart/mapEnd 场景坐标范围(原始单位) .approachAt 开始显示提示的坐标 .children[] 子事件 ID 列表 .doneCids[] 已完成的子事件 ID $worldSceneQueue[] 本地形预生成的全部场景数组 $worldSceneQueueIdx 当前激活的场景索引 $largeScene 大型场景对象(0=无) .state "approaching"/"active"/"leaving"/"done" .approachEnd 进入active的坐标 .activeEnd 进入leaving的坐标 .leaveEnd 进入done的坐标 .zones[] [{name,zoneAt,wsType,st:"pending"/"done"}] .activeZone 当前激活zone索引(-1=无) $wsChild 当前交互中的子事件对象 .id 子事件类型 ID .stageIdx 当前阶段编号 .actions[] 当前可用操作 .lootLog 累计战利品文本 .actionText 上次操作结果文本 $activeEvent 当前活动中的随机事件对象(0=无) $activeSmallEvent 小型事件(null=无) $activeMicroEvent 微型事件(null=无) $temporalEvent 时间性事件(0=无) ══════════════════════════════════════════ 仓外探索 ══════════════════════════════════════════ $divingMode true=当前在舱外 $diveOxygen 当前氧气量(0-diveOxygenMax) $diveOxygenMax 氧气上限(受oxygen_sys升级影响) $diveCold 冷压积累(0-100) $diveStepsOut 已深入步数(用于返程消耗计算) $diveStepCostO2 每步氧气消耗(按深度在diveInit设定) $diveStepTime 每步游戏时间(分钟) $diveO2Dead true=氧气耗尽,强制显示返回 $diveChain[] 预生成的探索路线 [i].type "frag"=碎片/"scene"=场景/"end"=终点 [i].id 节点唯一ID [i].desc 场景合成描述文本 [i].elements[] 可交互元素名称列表 [i].blocked[] 被障碍物阻塞的元素(需机械臂清除) [i].visited 是否已访问 $diveIdx 当前路线位置索引 $diveChainTerrain 生成路线时的地形键 $diveArmBlocked {sceneId:[elem,...]} 记录被障碍阻塞的元素 $diveArmCleared {sceneId:[elem,...]} 已被机械臂从仓内清除的障碍 $diveShowIntro true=当前帧显示出仓简介横幅 $diveIntro 出仓简介文本(diveInit时生成) $diveChainSub[] 分叉子路线(备用) $diveLog 上次行动的文本日志 $diveInteractResult 交互结果(持续显示,需手动确认) ══════════════════════════════════════════ 升级系统 $upgrades ══════════════════════════════════════════ $upgrades.hull 船体隔热层 0-3;降低深海燃料系数/减损耗 $upgrades.pressure 加压舱改造 0-3;提升安全深度 300/600/1500/5000m $upgrades.thruster 推进器 0-3;提升spdmax 100/200/350/500 $upgrades.arm 机械臂 0-2;仓内操作权限+清除仓外障碍物 0=无臂(操作需臂按钮灰显) 1=基础臂(撬开/拆卸/清除障碍) 2=精密臂(精密/精细操作) $upgrades.oxygen_sys 氧气循环系统 0-3;提升diveOxygenMax 100/160/250/400 $upgrades.fuel_tank 燃料槽扩容 0-3;提升fuelMax 300/500/800/1400 $upgrades.kitchen 厨房设备 0-3;解锁烹饪方式 0=明火烤+生食 1=+铜锅炖 2=+清蒸+煎炒 3=+油炸 $upgrades.alchemy 炼金台 0-3;解锁炼金仪器 0=精炼台 1=+溶解皿(黑化) 2=+蒸馏器(白化)+凝结炉(黄化) 3=+赤化炉(赤化) $upgradeDefs 运行时由 <<upgradeDefs>> widget 注入的配置对象 $lastUpgradeText 升级操作结果提示文本 ══════════════════════════════════════════ 燃料系统 ══════════════════════════════════════════ $fuelDefs {id:热值} 燃料物品热值表(由<<fuelDefs>>注入) $lastFuelText 补燃料操作结果文本 $driftMode true=燃料耗尽漂流(禁止下潜,速度锁0) ══════════════════════════════════════════ 物品/仓储 ══════════════════════════════════════════ $items 物品定义表(ItemDefs注入) {id:{name,type,size,fuelVal?,element?,form?,...}} $store 货舱存储 {type:[{id,quantity,addedDay},...]} $backpack 背包存储 同上结构 $fridge[] 冰箱槽位 长度8,null=空 $selectitem 当前选中的物品ID(物品详情页用) ══════════════════════════════════════════ 烹饪系统 ══════════════════════════════════════════ $cookMethod 当前选择的烹饪方式 $cookIngredients[] 选定的食材ID列表 $cookTimer 当前烹饪计时器(秒) $cookDuration 本次烹饪总时长 $cookFinalTime 玩家按停时的计时值 $cookQuality "失败"/"成功"/"完美" $cookRecipeName 匹配到的菜谱名称 $cookResultId 结果食物ID $cookSuccessMin/Max 成功区间 $cookPerfectMin/Max 完美区间 ══════════════════════════════════════════ 炼金系统 ══════════════════════════════════════════ $alchemyInstrument 当前选择的仪器名称 $alchemyMaterials[] 选定的炼金材料ID列表 $alchemyTimer 计时器(秒) $alchemyInstrumentDefs 仪器配置(AlchemyDefs注入) $refineRules 精炼规则表(AlchemyDefs注入) ══════════════════════════════════════════ 开发标志 ══════════════════════════════════════════ $devMode true=显示DEV调试按钮;发布前改为false ══════════════════════════════════════════ 特殊片段列表(不显示返回按钮) ══════════════════════════════════════════ $specialPassages[] ["backpack","背包物品页面","ship"] 等
<<nobr>> <<widget "cpTick">> <<set _ctNow = ($day || 1) * 1440 + ($hour || 7) * 60 + ($minute || 0)>> <<for _ctI = 0; _ctI < $activeCpIds.length; _ctI++>> <<set _ctId = $activeCpIds[_ctI]>> <<set _ctCp = $cps[_ctId]>> <<if !_ctCp>><<continue>><</if>> /* ── 经过时间 ── */ <<set _ctElapsed = Math.max(0, _ctNow - (_ctCp.lastTickTime || _ctNow))>> <<set $cps[_ctId].lastTickTime = _ctNow>> <<if _ctElapsed <= 0>><<continue>><</if>> /* ── 精力速率 ── */ <<if _ctCp.action === "sleep">> <<set _ctERate = _ctCp.energyRates.sleep>> <<elseif _ctCp.action === "nap">> <<set _ctERate = _ctCp.energyRates.rest>> <<elseif _ctCp.action === "outside" || _ctCp.action === "exercise">> <<set _ctERate = _ctCp.energyRates.heavy>> <<else>> <<set _ctERate = _ctCp.energyRates.normal>> <</if>> /* ── 数值衰减 ── */ <<set $cps[_ctId].hunger = Math.max(0, Math.min(100, _ctCp.hunger + (-0.050 * _ctCp.hungerRate) * _ctElapsed))>> <<set $cps[_ctId].water = Math.max(0, Math.min(100, _ctCp.water + (-0.083 * _ctCp.waterRate) * _ctElapsed))>> <<set $cps[_ctId].energy = Math.max(0, Math.min(100, _ctCp.energy + _ctERate * _ctElapsed))>> /* ── eat 行动正向回复 ── */ <<if _ctCp.action === "eat">> <<set $cps[_ctId].hunger = Math.min(100, _ctCp.hunger + 1.5 * _ctElapsed)>> <<set $cps[_ctId].water = Math.min(100, _ctCp.water + 2.6 * _ctElapsed)>> <</if>> /* ── 短期记忆过期 ── */ <<if _ctCp.recentMemory && _ctCp.recentMemory.tag && $day >= _ctCp.recentMemory.expire>> <<set $cps[_ctId].recentMemory = { tag: "", day: 0, expire: -1 }>> <</if>> /* ── 通知过期 ── */ <<if _ctCp.pendingNotify && _ctCp.pendingNotify.expire >= 0 && $day > _ctCp.pendingNotify.expire>> <<set $cps[_ctId].pendingNotify = { text: "", expire: -1 }>> <</if>> /* ── 行动到期 → 结算上一行动 → 重算意图 ── */ <<if _ctNow >= _ctCp.actionEndTime>> <<cpActionResult _ctId>> <<cpIntent _ctId>> <</if>> /* ── 心情计算(重新读取,intent 可能已修改数值) ── */ <<set _ctCp2 = $cps[_ctId]>> <<if _ctCp2.hunger < 20 || _ctCp2.water < 20 || _ctCp2.energy < 15>> <<set $cps[_ctId].mood = 0>> <<elseif _ctCp2.hunger > 65 && _ctCp2.water > 65 && _ctCp2.energy > 50>> <<set $cps[_ctId].mood = (_ctCp2.bond >= 65) ? 2 : 1>> <<else>> <<set $cps[_ctId].mood = 1>> <</if>> /* ── 安定计算 ── */ <<set _ctCp2 = $cps[_ctId]>> <<if _ctCp2.mood === 0>> <<set $cps[_ctId].calm = 0>> <<elseif _ctCp2.mood === 2 && _ctCp2.bond >= 60>> <<set $cps[_ctId].calm = 2>> <<else>> <<set $cps[_ctId].calm = 1>> <</if>> /* ── 主动行动检测 ── */ <<cpProactiveCheck _ctId>> <</for>> <</widget>> <</nobr>>
<<nobr>> <<widget "cpSceneRender">> /* 调用:<<cpSceneRender "cp_id">> 从 CP 模板的 sceneTexts 读取当前行动对应文本 支持字符串或数组(数组随机取一条) actionDetail 非空时附加在描述后面 */ <<set _csr = $cps[$args[0]]>> <<set _csrId = $args[0]>> <<if _csr>> /* ── 从 sceneTexts 取文本 ── */ <<set _csrPool = _csr.sceneTexts ? _csr.sceneTexts[_csr.action] : null>> <<set _csrHint = "">> <<if !_csrPool>> /* 没有定义该行动的文本,兜底显示 */ <<set _csrHint = _csr.name + "在这里。">> <<elseif Array.isArray(_csrPool)>> <<set _csrHint = _csrPool[Math.floor(Math.random() * _csrPool.length)]>> <<else>> <<set _csrHint = _csrPool>> <</if>> /* actionDetail 非空时附加 */ <<if _csr.actionDetail>> <<set _csrHint = _csrHint + "(" + _csr.actionDetail + ")">> <</if>> <<set _csrLinkText = "查看" + _csr.name>> <div class="cp-scene-hint"> <<print _csrHint>> @@.cp-scene-link;<<link _csrLinkText>> <<set $detailCpId = _csrId>> <<navigate "go" "cp详情">> <</link>>@@ </div> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "cpIntent">> /* 调用:<<cpIntent "cp_id">> */ <<set _ciId = $args[0]>> <<set _ciCp = $cps[_ciId]>> <<if !_ciCp>><<return>><</if>> <<set _ciNow = ($day || 1) * 1440 + ($hour || 7) * 60 + ($minute || 0)>> <<set _ciTh = _ciCp.intentThresholds>> /* ══ 生存优先级 ══ */ <<if _ciCp.energy <= _ciTh.sleepAt>> <<set $cps[_ciId].action = "sleep">> <<set $cps[_ciId].location = "休息室">> <<set $cps[_ciId].actionEndTime = _ciNow + 480>> <<set $cps[_ciId].actionDetail = "">> <<elseif _ciCp.hunger <= _ciTh.eatAt>> <<set $cps[_ciId].action = "eat">> <<set $cps[_ciId].location = "厨房">> <<set $cps[_ciId].actionEndTime = _ciNow + 35>> <<set $cps[_ciId].actionDetail = "">> <<elseif _ciCp.water <= _ciTh.drinkAt>> <<set $cps[_ciId].action = "eat">> <<set $cps[_ciId].location = "厨房">> <<set $cps[_ciId].actionEndTime = _ciNow + 20>> <<set $cps[_ciId].actionDetail = "倒了杯水">> <<else>> /* ══ 自由活动加权随机 只从该角色 activityWeights 里定义的行动里选 没有列出的行动永远不会触发 ══ */ <<set _ciW = clone(_ciCp.activityWeights)>> <<if _ciCp.energy <= _ciTh.napAt && _ciW.nap !== undefined>> <<set _ciW.nap = _ciW.nap * 3>> <</if>> <<set _ciTotal = 0>> <<set _ciKeys = Object.keys(_ciW)>> <<for _ciK = 0; _ciK < _ciKeys.length; _ciK++>> <<set _ciTotal += _ciW[_ciKeys[_ciK]]>> <</for>> <<set _ciRoll = Math.random() * _ciTotal>> <<set _ciChosen = _ciKeys[_ciKeys.length - 1]>> <<set _ciAcc = 0>> <<for _ciK = 0; _ciK < _ciKeys.length; _ciK++>> <<set _ciAcc += _ciW[_ciKeys[_ciK]]>> <<if _ciRoll < _ciAcc>> <<set _ciChosen = _ciKeys[_ciK]>> <<break>> <</if>> <</for>> /* ── 世界行动:库存检查 + 降级 ── */ <<if _ciChosen === "disassemble">> <<set _ciHasFish = false>> <<for _ciFI = 0; _ciFI < _ciCp.fishIds.length; _ciFI++>> <<finditem $store _ciCp.fishIds[_ciFI]>> <<if _foundItem && _foundItem.quantity > 0>> <<set _ciHasFish = true>><<break>> <</if>> <</for>> <<if _ciHasFish>> <<set $cps[_ciId].action = "disassemble">> <<set $cps[_ciId].location = "仓库">> <<set $cps[_ciId].actionEndTime = _ciNow + 40 + Math.floor(Math.random()*20)>> <<else>> <<set $cps[_ciId].action = "tidy">> <<set $cps[_ciId].location = "仓库">> <<set $cps[_ciId].actionEndTime = _ciNow + 30 + Math.floor(Math.random()*20)>> <</if>> <<set $cps[_ciId].actionDetail = "">> <<elseif _ciChosen === "cook">> <<set _ciHasIngredient = false>> <<set _ciStoreKeys = Object.keys($store)>> <<for _ciSKI = 0; _ciSKI < _ciStoreKeys.length; _ciSKI++>> <<set _ciCat = _ciStoreKeys[_ciSKI]>> <<if !Array.isArray($store[_ciCat])>><<continue>><</if>> <<for _ciSII = 0; _ciSII < $store[_ciCat].length; _ciSII++>> <<set _ciEntry = $store[_ciCat][_ciSII]>> <<set _ciEntryDef = State.variables.items[_ciEntry.id]>> <<if _ciEntry.quantity > 0 && _ciEntryDef && _ciEntryDef.foodtags && _ciEntryDef.foodtags.length > 0>> <<set _ciHasIngredient = true>><<break>> <</if>> <</for>> <<if _ciHasIngredient>><<break>><</if>> <</for>> <<if _ciHasIngredient>> <<set $cps[_ciId].action = "cook">> <<set $cps[_ciId].location = "厨房">> <<set $cps[_ciId].actionEndTime = _ciNow + 60 + Math.floor(Math.random()*30)>> <<else>> <<if $day >= _ciCp.notifyCooldown>> <<set $cps[_ciId].pendingNotify = { text : _ciCp.name + ":仓库里没有食材了,我去弄点东西回来。", expire : $day }>> <<set $cps[_ciId].notifyCooldown = $day + 2>> <</if>> <<set $cps[_ciId].action = "outside">> <<set $cps[_ciId].location = "舱外">> <<set $cps[_ciId].actionEndTime = _ciNow + 90 + Math.floor(Math.random()*60)>> <<set $cps[_ciId].wet = true>> <</if>> <<set $cps[_ciId].actionDetail = "">> <<elseif _ciChosen === "outside">> <<set $cps[_ciId].action = "outside">> <<set $cps[_ciId].location = "舱外">> <<set $cps[_ciId].actionEndTime = _ciNow + 90 + Math.floor(Math.random()*60)>> <<set $cps[_ciId].actionDetail = "">> <<set $cps[_ciId].wet = true>> <<elseif _ciChosen === "watch">> <<set $cps[_ciId].action = "watch">> <<set $cps[_ciId].location = "驾驶舱">> <<set $cps[_ciId].actionEndTime = _ciNow + 45 + Math.floor(Math.random()*30)>> <<set $cps[_ciId].actionDetail = "">> <<elseif _ciChosen === "exercise">> <<set $cps[_ciId].action = "exercise">> <<set $cps[_ciId].location = "主舱">> <<set $cps[_ciId].actionEndTime = _ciNow + 50 + Math.floor(Math.random()*20)>> <<set $cps[_ciId].actionDetail = "">> <<elseif _ciChosen === "nap">> <<set $cps[_ciId].action = "nap">> <<set $cps[_ciId].location = "休息室">> <<set $cps[_ciId].actionEndTime = _ciNow + 60 + Math.floor(Math.random()*60)>> <<set $cps[_ciId].actionDetail = "">> <<else>> /* tidy 及其他兜底 */ <<set $cps[_ciId].action = "tidy">> <<set $cps[_ciId].location = "仓库">> <<set $cps[_ciId].actionEndTime = _ciNow + 30 + Math.floor(Math.random()*20)>> <<set $cps[_ciId].actionDetail = "">> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "cpMemoryTag">> /* 调用:<<cpMemoryTag "cp_id" "tag" [expire天数,默认1]>> 统一入口写入短期记忆 同一时间只保留一条记忆,新写入覆盖旧记忆 */ <<set _cmtId = $args[0]>> <<set _cmtTag = $args[1]>> <<set _cmtExpire = ($args[2] !== undefined) ? Number($args[2]) : 1>> <<set _cmtCp = $cps[_cmtId]>> <<if _cmtCp>> <<set $cps[_cmtId].recentMemory = { tag : _cmtTag, day : $day, expire : $day + _cmtExpire }>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "cpActionResult">> /* 调用:<<cpActionResult "cp_id">> 在 cpTick 检测到行动到期、调用 cpIntent 之前自动执行 只处理世界行动的库存结算,生存行动(sleep/eat/nap)不触碰库存 */ <<set _carId = $args[0]>> <<set _carCp = $cps[_carId]>> <<if _carCp>> <<set _carPrev = _carCp.action>> /* ══ outside:外出返回,随机带回 1-3 件渔获 ══ */ <<if _carPrev === "outside">> <<set _carFishList = _carCp.fishIds>> <<set _carCatch = Math.floor(Math.random() * 3) + 1>> <<set _carLootLog = []>> <<for _carCI = 0; _carCI < _carCatch; _carCI++>> <<set _carFishId = _carFishList[Math.floor(Math.random() * _carFishList.length)]>> <<additem _carFishId 1>> <<set _carFishDef = State.variables.items[_carFishId]>> <<if _carFishDef>><<run _carLootLog.push(_carFishDef.name)>><</if>> <</for>> /* 写入返回记忆 */ <<cpMemoryTag _carId "went_outside" 1>> <<if $day >= _carCp.notifyCooldown && _carLootLog.length > 0>> <<set $cps[_carId].pendingNotify = { text : _carCp.name + " 带回来了:" + _carLootLog.join("、") + "。", expire : $day }>> <<set $cps[_carId].notifyCooldown = $day + 1>> <</if>> <</if>> /* ══ disassemble:复用现有 widget,NPC 模式跳过玩家数值影响 ══ */ <<if _carPrev === "disassemble">> <<set _carFoundFish = "">> <<for _carFI = 0; _carFI < _carCp.fishIds.length; _carFI++>> <<finditem $store _carCp.fishIds[_carFI]>> <<if _foundItem && _foundItem.quantity > 0>> <<set _carFoundFish = _carCp.fishIds[_carFI]>> <<break>> <</if>> <</for>> <<if _carFoundFish>> /* 第二参数 true = NPC 模式,跳过时间/体力/划伤 */ <<disassemble _carFoundFish true>> <<if $day >= _carCp.notifyCooldown>> <<set $cps[_carId].pendingNotify = { text : _carCp.name + " 处理了渔获:" + $lastDisassembleText, expire : $day }>> <<set $cps[_carId].notifyCooldown = $day + 1>> <</if>> <</if>> <</if>> /* ══ cook:两轮筛选选食材,复用 matchRecipe + assembleDish ══ */ <<if _carPrev === "cook">> /* ── 收集候选食材:foodPrefs 优先,再补充其他有 foodtags 的仓库食材 ── */ <<set _carCands = []>> <<for _carPI = 0; _carPI < _carCp.foodPrefs.length; _carPI++>> <<finditem $store _carCp.foodPrefs[_carPI]>> <<if _foundItem && _foundItem.quantity > 0>> <<run _carCands.push({ id: _carCp.foodPrefs[_carPI], pref: true })>> <</if>> <</for>> <<set _carStoreKeys = Object.keys($store)>> <<for _carSKI = 0; _carSKI < _carStoreKeys.length; _carSKI++>> <<set _carCat = _carStoreKeys[_carSKI]>> <<if !Array.isArray($store[_carCat])>><<continue>><</if>> <<for _carSII = 0; _carSII < $store[_carCat].length; _carSII++>> <<set _carEntry = $store[_carCat][_carSII]>> <<set _carEntryDef = State.variables.items[_carEntry.id]>> <<if _carEntry.quantity <= 0>><<continue>><</if>> <<if !_carEntryDef || !_carEntryDef.foodtags || _carEntryDef.foodtags.length === 0>><<continue>><</if>> <<set _carAlready = false>> <<for _carCI2 = 0; _carCI2 < _carCands.length; _carCI2++>> <<if _carCands[_carCI2].id === _carEntry.id>><<set _carAlready = true>><<break>><</if>> <</for>> <<if !_carAlready>><<run _carCands.push({ id: _carEntry.id, pref: false })>><</if>> <</for>> <</for>> <<if _carCands.length > 0>> /* 随机烹饪方式:从该 CP 的 cookMethods 里取 */ <<set _carMethods = _carCp.cookMethods || ["明火烤","铜锅炖","煎炒"]>> <<set _carMethod = _carMethods[Math.floor(Math.random() * _carMethods.length)]>> /* ── 第一轮:只试 foodPrefs 食材 ── */ <<set _carPrefCands = []>> <<for _carCI = 0; _carCI < _carCands.length; _carCI++>> <<if _carCands[_carCI].pref>><<run _carPrefCands.push(_carCands[_carCI].id)>><</if>> <</for>> /* Fisher-Yates 乱序 */ <<for _carSI = _carPrefCands.length - 1; _carSI > 0; _carSI-->> <<set _carSJ = Math.floor(Math.random() * (_carSI + 1))>> <<set _carSTmp = _carPrefCands[_carSI]>> <<set _carPrefCands[_carSI] = _carPrefCands[_carSJ]>> <<set _carPrefCands[_carSJ] = _carSTmp>> <</for>> <<set _carChosenId = "">> <<for _carTI = 0; _carTI < _carPrefCands.length; _carTI++>> <<set $cookIngredients = [_carPrefCands[_carTI]]>> <<set $cookMethod = _carMethod>> <<matchRecipe>> <<if $cookTemplate && $cookTemplate.id && !$cookTemplate.id.includes("fallback")>> <<set _carChosenId = _carPrefCands[_carTI]>> <<break>> <</if>> <</for>> /* ── 第二轮:全部候选乱序试 ── */ <<if !_carChosenId>> <<for _carSI2 = _carCands.length - 1; _carSI2 > 0; _carSI2-->> <<set _carSJ2 = Math.floor(Math.random() * (_carSI2 + 1))>> <<set _carSTmp2 = _carCands[_carSI2]>> <<set _carCands[_carSI2] = _carCands[_carSJ2]>> <<set _carCands[_carSJ2] = _carSTmp2>> <</for>> <<for _carTI2 = 0; _carTI2 < _carCands.length; _carTI2++>> <<set $cookIngredients = [_carCands[_carTI2].id]>> <<set $cookMethod = _carMethod>> <<matchRecipe>> <<if $cookTemplate && $cookTemplate.id && !$cookTemplate.id.includes("fallback")>> <<set _carChosenId = _carCands[_carTI2].id>> <<break>> <</if>> <</for>> <</if>> /* ── 兜底:单品保底 ── */ <<if !_carChosenId>> <<set _carChosenId = (_carPrefCands.length > 0) ? _carPrefCands[0] : _carCands[0].id>> <<set $cookIngredients = [_carChosenId]>> <<set $cookMethod = _carMethod>> <<matchRecipe>> <</if>> /* ── 消耗食材,生成菜品 ── */ <<removeitem _carChosenId 1>> <<if _carCp.bond >= 70 && Math.random() < 0.3>> <<set $cookQuality = "完美">> <<else>> <<set $cookQuality = "成功">> <</if>> <<assembleDish>> /* 冰箱满了放仓库 */ <<if $assembleResult === "full">> <<if $cookTemplate>><<additem $cookTemplate.id 1>><</if>> <</if>> /* 写入记忆 + 重要通知 */ <<cpMemoryTag _carId "cooked_for_player" 2>> <<set _carDishName = $cookTemplate ? $cookTemplate.name : "一道菜">> <<set $cps[_carId].pendingNotify = { text : _carCp.name + " 做了" + _carDishName + ",放进冰箱了。", expire : $day + 1, important: true }>> <</if>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "cpProactiveDefs">> /* Viona 主动事件定义表 字段说明: type : "chat" / "gift" passage : 跳转目标 passage 名 baseChance : 每次 tick 检测的触发概率 weight : 同批候选时的权重 cooldown : 触发后冷却天数 minBond : 最低好感要求(可选) minMood : 最低心情档位(可选) requireMemory : 触发所需记忆 tag(可选) */ <<set $cpProactiveDefs = {}>> <<set $cpProactiveDefs["viona"] = [ { type : "chat", passage : "viona主动闲聊", baseChance : 0.12, weight : 20, cooldown : 2, minBond : 30, minMood : 1 }, { type : "chat", passage : "viona心情好搭话", baseChance : 0.18, weight : 15, cooldown : 3, minBond : 50, minMood : 2 }, { type : "chat", passage : "viona记仇质问", baseChance : 0.35, weight : 30, cooldown : 1, requireMemory : "was_teased" }, { type : "gift", passage : "viona送礼物", baseChance : 0.10, weight : 10, cooldown : 5, minBond : 60, requireMemory : "cooked_for_player" } ]>> <</widget>> <</nobr>>
<<nobr>> <<widget "cpGiftFood">> /* 调用:<<cpGiftFood "cp_id" "item_id">> 玩家将仓库里的物品赠给 CP 输出一行反馈文字,调用处可直接显示 */ <<set _cgfId = $args[0]>> <<set _cgfItemId = $args[1]>> <<set _cgfCp = $cps[_cgfId]>> <<set _cgfDef = State.variables.items[_cgfItemId]>> <<if !_cgfCp>> <<print "错误:找不到 CP " + _cgfId>> <<elseif !_cgfDef>> <<print "错误:找不到物品 " + _cgfItemId>> <<else>> <<finditem $store _cgfItemId>> <<if !_foundItem || _foundItem.quantity <= 0>> <<print _cgfDef.name + " 数量不足,无法赠送。">> <<else>> <<removeitem _cgfItemId 1>> /* 数值回复:读物品定义的 nutrition / hydration,无则用默认值 */ <<set _cgfNutr = (_cgfDef.nutrition !== undefined) ? _cgfDef.nutrition : 20>> <<set _cgfHydr = (_cgfDef.hydration !== undefined) ? _cgfDef.hydration : 0>> <<set $cps[_cgfId].hunger = Math.min(100, _cgfCp.hunger + _cgfNutr)>> <<set $cps[_cgfId].water = Math.min(100, _cgfCp.water + _cgfHydr)>> /* 偏好检查 */ <<set _cgfPref = false>> <<for _cgfPI = 0; _cgfPI < _cgfCp.foodPrefs.length; _cgfPI++>> <<if _cgfCp.foodPrefs[_cgfPI] === _cgfItemId>> <<set _cgfPref = true>><<break>> <</if>> <</for>> <<if _cgfPref>> <<set $cps[_cgfId].mood = Math.min(2, _cgfCp.mood + 1)>> <<set $cps[_cgfId].bond = Math.min(100, _cgfCp.bond + 3)>> <<set _cgfReply = _cgfCp.name + " 的眼睛亮了一下——这是她喜欢的。">> <<else>> <<set $cps[_cgfId].bond = Math.min(100, _cgfCp.bond + 1)>> <<set _cgfReply = _cgfCp.name + " 接过去,道了声谢。">> <</if>> <<cpMemoryTag _cgfId "received_gift" 1>> <<print _cgfReply>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "cpNotifyDisplay">> /* 在 StoryCaption 的 <div id="sc-status"> 之后加:<<cpNotifyDisplay>> important=true 用金色醒目样式,普通通知用次要样式 */ <<if $activeCpIds && $activeCpIds.length > 0>> <<for _cndI = 0; _cndI < $activeCpIds.length; _cndI++>> <<set _cndId = $activeCpIds[_cndI]>> <<set _cndCp = $cps[_cndId]>> <<if !_cndCp>><<continue>><</if>> <<if !_cndCp.pendingNotify || !_cndCp.pendingNotify.text>><<continue>><</if>> <<if _cndCp.pendingNotify.expire >= 0 && $day > _cndCp.pendingNotify.expire>><<continue>><</if>> <<if _cndCp.pendingNotify.important === true>> <div class="cp-notify cp-notify-important"> <span class="cp-notify-icon">★</span><<print _cndCp.pendingNotify.text>> </div> <<else>> <div class="cp-notify"><<print _cndCp.pendingNotify.text>></div> <</if>> <</for>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "cpRoomCheck">> <<set _crcRoom = $args[0]>> <<set _crcTriggered = false>> <<if $activeCpIds && $activeCpIds.length > 0>> <<for _crcI = 0; _crcI < $activeCpIds.length && !_crcTriggered; _crcI++>> <<set _crcId = $activeCpIds[_crcI]>> <<set _crcCp = $cps[_crcId]>> <<if !_crcCp>><<continue>><</if>> <<if _crcCp.location !== _crcRoom>><<continue>><</if>> <<if !_crcCp.pendingImportantEvent || !_crcCp.pendingImportantEvent.passage>><<continue>><</if>> <<set _crcEvt = _crcCp.pendingImportantEvent>> <<if _crcEvt.expire >= 0 && $day > _crcEvt.expire>> <<set $cps[_crcId].pendingImportantEvent = null>> <<continue>> <</if>> <<set $cpEventReturn = _crcRoom>> <<set $cpEventCpId = _crcId>> <<set $cps[_crcId].pendingImportantEvent = null>> <<set _crcTriggered = true>> <<navigate "go" _crcEvt.passage>> <</for>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "cpProactiveCheck">> <<set _cpcId = $args[0]>> <<set _cpcCp = $cps[_cpcId]>> <<if _cpcCp && $day >= _cpcCp.proactiveCooldown && _cpcCp.action !== "sleep" && _cpcCp.action !== "outside" && _cpcCp.action !== "exercise" && _cpcCp.mood !== 0 && (!_cpcCp.pendingImportantEvent || !_cpcCp.pendingImportantEvent.passage)>> <<if !$cpProactiveDefs>><<cpProactiveDefs>><</if>> <<set _cpcDefs = $cpProactiveDefs[_cpcId]>> <<if _cpcDefs && _cpcDefs.length > 0>> /* ── 过滤候选事件 ── */ <<set _cpcCands = []>> <<for _cpcI = 0; _cpcI < _cpcDefs.length; _cpcI++>> <<set _cpcDef = _cpcDefs[_cpcI]>> <<set _cpcOk = true>> <<if _cpcDef.minBond !== undefined && _cpcCp.bond < _cpcDef.minBond>> <<set _cpcOk = false>> <</if>> <<if _cpcOk && _cpcDef.minMood !== undefined && _cpcCp.mood < _cpcDef.minMood>> <<set _cpcOk = false>> <</if>> <<if _cpcOk && _cpcDef.type === "chat" && $day <= _cpcCp.lastChatDay>> <<set _cpcOk = false>> <</if>> <<if _cpcOk && _cpcDef.requireMemory>> <<if !_cpcCp.recentMemory || _cpcCp.recentMemory.tag !== _cpcDef.requireMemory || $day >= _cpcCp.recentMemory.expire>> <<set _cpcOk = false>> <</if>> <</if>> <<if _cpcOk>><<run _cpcCands.push(_cpcDef)>><</if>> <</for>> <<if _cpcCands.length > 0>> /* ── 加权随机 ── */ <<set _cpcTotal = 0>> <<for _cpcWI = 0; _cpcWI < _cpcCands.length; _cpcWI++>> <<set _cpcTotal += (_cpcCands[_cpcWI].weight || 10)>> <</for>> <<set _cpcRoll = Math.random() * _cpcTotal>> <<set _cpcChosen = _cpcCands[_cpcCands.length - 1]>> <<set _cpcAcc = 0>> <<for _cpcWI = 0; _cpcWI < _cpcCands.length; _cpcWI++>> <<set _cpcAcc += (_cpcCands[_cpcWI].weight || 10)>> <<if _cpcRoll < _cpcAcc>> <<set _cpcChosen = _cpcCands[_cpcWI]>> <<break>> <</if>> <</for>> /* ── 概率掷骰,命中则写入事件和冷却 ── */ <<if Math.random() < (_cpcChosen.baseChance || 0.15)>> <<set $cps[_cpcId].pendingImportantEvent = { passage : _cpcChosen.passage, type : _cpcChosen.type, expire : $day + 2 }>> <<set $cps[_cpcId].proactiveCooldown = $day + (_cpcChosen.cooldown || 2)>> <</if>> <</if>> <</if>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<cpRoomCheck $passage>> <<set _cd = $cps[$detailCpId]>> <<if !_cd>> <p>找不到对应的角色数据。</p> <<link "返回">><<navigate "back">><</link>> <<else>> <<set _cdNow = ($day || 1) * 1440 + ($hour || 7) * 60 + ($minute || 0)>> <<set _cdRemain = Math.max(0, _cd.actionEndTime - _cdNow)>> <<set _cdRemH = Math.floor(_cdRemain / 60)>> <<set _cdRemM = _cdRemain % 60>> /* ── 从 detailTexts 取完整描述 ── */ <<set _cdPool = _cd.detailTexts ? _cd.detailTexts[_cd.action] : null>> <<set _cdDesc = "">> <<if !_cdPool>> <<set _cdDesc = _cd.name + "在这里,没做什么特别的事。">> <<elseif Array.isArray(_cdPool)>> <<set _cdDesc = _cdPool[Math.floor(Math.random() * _cdPool.length)]>> <<else>> <<set _cdDesc = _cdPool>> <</if>> /* actionDetail 非空时附加 */ <<if _cd.actionDetail>> <<set _cdDesc = _cdDesc + "(" + _cd.actionDetail + ")">> <</if>> /* ── 状态 tag ── */ <<set _cdTags = []>> <<if _cd.wet>><<run _cdTags.push("潮湿")>><</if>> <<if _cd.sick>><<run _cdTags.push("生病")>><</if>> <<if _cd.injured === 1>><<run _cdTags.push("轻伤")>> <<elseif _cd.injured === 2>><<run _cdTags.push("重伤")>><</if>> /* ── 心情 / 安定文字 ── */ <<set _cdMoodText = ["低落","平常","愉快"][_cd.mood]>> <<set _cdCalmText = ["不安","平静","安心"][_cd.calm]>> /* ── 数值条警告色 ── */ <<set _cdHColor = (_cd.hunger < 20) ? "var(--danger-bright,#e55)" : "var(--teal-bright,#4ecdc4)">> <<set _cdWColor = (_cd.water < 20) ? "var(--danger-bright,#e55)" : "var(--teal-bright,#4ecdc4)">> <<set _cdEColor = (_cd.energy < 20) ? "var(--danger-bright,#e55)" : "var(--teal-bright,#4ecdc4)">> <div id="cp-detail"> <div class="cp-detail-name"><<print _cd.name>></div> <div class="cp-detail-desc"><<print _cdDesc>></div> <div class="cp-detail-timer"> 当前行动还有 <<if _cdRemH > 0>><<print _cdRemH>> 小时 <</if>><<print _cdRemM>> 分钟结束 </div> <div class="cp-detail-stats"> <div class="stat-row"> <span class="stat-label">饥饿</span> <span class="stat-bar"> <span class="stat-fill" style="width:<<print Math.floor(_cd.hunger)>>%;background:<<print _cdHColor>>;"></span> </span> <span class="stat-num"><<print Math.floor(_cd.hunger)>></span> </div> <div class="stat-row"> <span class="stat-label">饮水</span> <span class="stat-bar"> <span class="stat-fill" style="width:<<print Math.floor(_cd.water)>>%;background:<<print _cdWColor>>;"></span> </span> <span class="stat-num"><<print Math.floor(_cd.water)>></span> </div> <div class="stat-row"> <span class="stat-label">精力</span> <span class="stat-bar"> <span class="stat-fill" style="width:<<print Math.floor(_cd.energy)>>%;background:<<print _cdEColor>>;"></span> </span> <span class="stat-num"><<print Math.floor(_cd.energy)>></span> </div> <div class="stat-row"> <span class="stat-label">心情</span> <span class="stat-num-text"><<print _cdMoodText>></span> </div> <div class="stat-row"> <span class="stat-label">安定</span> <span class="stat-num-text"><<print _cdCalmText>></span> </div> <div class="stat-row"> <span class="stat-label">好感</span> <span class="stat-bar"> <span class="stat-fill" style="width:<<print _cd.bond>>%;"></span> </span> <span class="stat-num"><<print _cd.bond>></span> </div> </div> <<if _cdTags.length > 0>> <div class="cp-detail-tags"> <<for _cdTI = 0; _cdTI < _cdTags.length; _cdTI++>> <span class="cp-tag"><<print _cdTags[_cdTI]>></span> <</for>> </div> <</if>> <div class="cp-detail-return"> <<link "返回">><<navigate "back">><</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set _vChat = $cps["viona"]>> <div id="cp-event"> <div class="cp-event-name"><<print _vChat.name>></div> <<if _vChat.mood === 2>> <div class="cp-event-desc">「心情愉快时的闲聊开场」</div> <<else>> <div class="cp-event-desc">「普通心情时的闲聊开场」</div> <</if>> <div class="cp-event-options"> <<link "随便聊聊">> <<set $cps.viona.bond = Math.min(100, $cps.viona.bond + 1)>> <<set $cps.viona.lastChatDay = $day>> <<cpMemoryTag "viona" "had_chat" 1>> <div class="cp-event-reply">「玩家搭话后 Viona 的回应」</div> <<link "好的">><<navigate "go" $cpEventReturn>><</link>> <</link>> <<link "现在没空">> <<set $cps.viona.lastChatDay = $day>> <<navigate "go" $cpEventReturn>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _vGood = $cps["viona"]>> <div id="cp-event"> <div class="cp-event-name"><<print _vGood.name>></div> <div class="cp-event-desc">「心情愉快时主动找玩家说话,语气可以比普通闲聊更活泼」</div> <div class="cp-event-options"> <<link "陪她说一会儿">> <<set $cps.viona.bond = Math.min(100, $cps.viona.bond + 2)>> <<set $cps.viona.lastChatDay = $day>> <<cpMemoryTag "viona" "had_chat" 1>> <div class="cp-event-reply">「玩家陪聊后 Viona 的反应」</div> <<link "好的">><<navigate "go" $cpEventReturn>><</link>> <</link>> <<link "让她自己玩">> <<set $cps.viona.lastChatDay = $day>> <div class="cp-event-reply">「被拒绝后 Viona 的反应,可以有点委屈但不扣好感」</div> <<link "好的">><<navigate "go" $cpEventReturn>><</link>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _vMad = $cps["viona"]>> <div id="cp-event"> <div class="cp-event-name"><<print _vMad.name>></div> <div class="cp-event-desc">「被捉弄后来找玩家算账,语气不善」</div> <div class="cp-event-options"> <<link "道歉">> <<set $cps.viona.recentMemory = { tag: "", day: 0, expire: -1 }>> <<set $cps.viona.bond = Math.min(100, $cps.viona.bond + 1)>> <div class="cp-event-reply">「道歉后 Viona 勉强接受的反应」</div> <<link "好的">><<navigate "go" $cpEventReturn>><</link>> <</link>> <<link "死不承认">> <<set $cps.viona.recentMemory.expire = $day + 2>> <<set $cps.viona.mood = Math.max(0, $cps.viona.mood - 1)>> <div class="cp-event-reply">「死不承认后 Viona 更生气的反应,记仇延长一天」</div> <<link "行吧">><<navigate "go" $cpEventReturn>><</link>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _vGift = $cps["viona"]>> /* 礼物 id:替换为实际物品 id */ <<set _vGiftId = "fish_bone">> <<set _vGiftDef = State.variables.items[_vGiftId]>> <div id="cp-event"> <div class="cp-event-name"><<print _vGift.name>></div> <div class="cp-event-desc">「Viona 拿出礼物时的场景描述」</div> <<if _vGiftDef>> <div class="cp-event-item"> <span class="cp-event-item-name"><<print _vGiftDef.name>></span> <<if _vGiftDef.desc>> <span class="cp-event-item-desc"><<print _vGiftDef.desc>></span> <</if>> </div> <</if>> <div class="cp-event-options"> <<link "收下">> <<if _vGiftDef>><<additem _vGiftId 1>><</if>> <<set $cps.viona.bond = Math.min(100, $cps.viona.bond + 2)>> <<cpMemoryTag "viona" "received_gift_from_cp" 2>> <div class="cp-event-reply">「收下礼物后 Viona 的反应」</div> <<link "好的">><<navigate "go" $cpEventReturn>><</link>> <</link>> <<link "婉拒">> <<set $cps.viona.bond = Math.max(0, $cps.viona.bond - 1)>> <div class="cp-event-reply">「拒绝礼物后 Viona 有点尴尬的反应」</div> <<link "行吧">><<navigate "go" $cpEventReturn>><</link>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<widget "combatInit">> /* 调用方式:<<combatInit "enemy_id" "return_passage">> */ <<if !$combatEnemyTable>><<combatEnemyDefs>><</if>> <<set _ciId = String($args[0])>> <<set _ciDef = $combatEnemyTable[_ciId] || $combatEnemyTable["jellyfish_swarm"]>> /* 士气随机 */ <<set _ciMorale = Array.isArray(_ciDef.morale) ? _ciDef.morale[0] + Math.floor(Math.random() * (_ciDef.morale[1] - _ciDef.morale[0] + 1)) : _ciDef.morale>> <<set $activeCombat = { enemy: { id: _ciId, name: _ciDef.name, alertness: _ciDef.alertness, morale: _ciMorale, hp: _ciDef.hp, hpMax: _ciDef.hp, injury: 0, flaws: 0, injuryMax: _ciDef.injuryMax, loot: _ciDef.loot || [], stateDesc: _ciDef.stateDesc, hpDesc: _ciDef.hpDesc, injuryDesc: _ciDef.injuryDesc, lockedEscape: false, nextDefend: false }, player: { alertness: 50, morale: 75, hp: $power * 2, hpMax: $power * 2, injury: 0, flaws: 0, nextDefend: false, mustHit: false, dmgHalf: false }, round: 0, phase: "main", log: "", result: null }>> <<set $combatReturn = ($args[1] ? String($args[1]) : "仓外探索")>> <</widget>> <</nobr>>
<<nobr>> <<widget "combatExecRound">> /* 调用:<<combatExecRound "action">> 行动值:进攻 / 警戒 / 防御 / 观察 / 休息 / 逃跑 item_add_flaw / item_restore_hp / item_must_hit / item_lock_escape 结果写入:$activeCombat.result, $activeCombat.log */ <<set _act = String($args[0])>> <<set _p = $activeCombat.player>> <<set _e = $activeCombat.enemy>> <<set _log = "">> <<set _wm = ($weaponMult || 1)>> /* ══════════════════════════════════════ 玩家行动 ══════════════════════════════════════ */ <<if _act === "进攻">> /* 进攻消耗体力 */ <<set _p.alertness = Math.max(0, _p.alertness - 10)>> <<set _p.hp = Math.max(0, _p.hp - 10)>> /* miss 判定:无破绽20%,1层10%,2层以上必中;mustHit强制命中 */ <<set _missRate = _e.flaws >= 2 ? 0 : (_e.flaws === 1 ? 0.10 : 0.20)>> <<if _p.mustHit>><<set _missRate = 0>><</if>> <<set _p.mustHit = false>> <<if Math.random() < _missRate>> <<set _p.morale = Math.max(0, _p.morale - 5)>> <<set _e.morale = Math.min(100, _e.morale + 5)>> <<set _log += "你发动攻击,但落了空。">> <<else>> <<set _dmg = Math.floor((10 + Math.floor(Math.random() * 11)) * _wm * (1 + _e.flaws * 0.3))>> <<set _e.injury = Math.min(999, _e.injury + _dmg)>> <<set _e.hp = Math.max(0, _e.hp - _dmg)>> <<set _e.morale = Math.max(0, _e.morale - 8)>> <<set _p.morale = Math.min(100, _p.morale + 5)>> <<set _log += "你发起攻击,造成 "+_dmg+" 点伤势"+(_e.flaws > 0 ? "(破绽×"+_e.flaws+")" : "")+"。">> <</if>> <<elseif _act === "警戒">> <<set _p.alertness = Math.min(100, _p.alertness + 30)>> <<if Math.random() < _p.alertness / 100>> <<set _e.flaws = Math.min(3, _e.flaws + 1)>> <<set _p.flaws = Math.max(0, _p.flaws - 1)>> <<set _log += "你保持高度警觉,察觉敌方破绽(共 "+_e.flaws+" 层)。">> <<else>> <<set _log += "你提高警觉,暂未发现破绽。">> <</if>> <<elseif _act === "防御">> <<set _p.alertness = Math.max(0, _p.alertness - 5)>> <<set _p.nextDefend = true>> <<set _log += "你摆好防御姿态,准备格挡下一击。">> <<elseif _act === "观察">> <<set _p.alertness = Math.min(100, _p.alertness + 15)>> <<if _p.alertness > 50 && Math.random() < 0.4>> <<set _e.flaws = Math.min(3, _e.flaws + 1)>> <<set _log += "你仔细观察,发现敌方破绽(共 "+_e.flaws+" 层)。">> <<else>> <<set _log += "你审视敌人的动向,尚未找到可乘之机。">> <</if>> <<elseif _act === "休息">> <<set _p.hp = Math.min(_p.hpMax, _p.hp + 20)>> <<set _p.alertness = Math.max(0, _p.alertness - 25)>> <<set _p.morale = Math.min(100, _p.morale + 10)>> <<set _log += "你短暂休整,恢复体力(+20)。">> <<elseif _act === "逃跑">> /* 敌方警觉显著高于我方时有50%阻拦概率 */ <<set _fleeBlock = (_e.alertness > _p.alertness + 20) ? 0.5 : 0>> <<if Math.random() < _fleeBlock>> <<set _p.morale = Math.max(0, _p.morale - 10)>> <<set _log += "你试图撤退,被对方拦截!">> /* 继续走敌方回合 */ <<else>> <<set $activeCombat.result = "player_flee">> <<set $activeCombat.log = _log + "你趁隙脱身,撤出了战斗。">> <<set $power = Math.max(0, $power - Math.floor((_p.hpMax - _p.hp) / 2))>> <<return>> <</if>> /* ── 道具(测试用,占用一个回合,无数量消耗)── */ <<elseif _act === "item_add_flaw">> <<set _e.flaws = Math.min(3, _e.flaws + 2)>> <<set _log += "投出诱饵,强制暴露敌方破绽(+2层,共 "+_e.flaws+" 层)。">> <<elseif _act === "item_restore_hp">> <<set _p.hp = Math.min(_p.hpMax, _p.hp + 30)>> <<set _log += "使用恢复剂,体力恢复 +30。">> <<elseif _act === "item_must_hit">> <<set _p.mustHit = true>> <<set _log += "使用瞄准装置,下次攻击必定命中。">> <<elseif _act === "item_lock_escape">> <<set _e.lockedEscape = true>> <<set _log += "投出声爆弹,敌方本回合无法逃跑。">> <</if>> /* ══════════════════════════════════════ 敌方回合(仅在战斗未结束时执行) ══════════════════════════════════════ */ <<if !$activeCombat.result>> /* ── 敌方 AI 行动选择(2×2 状态矩阵)── */ <<set _aHigh = _e.alertness >= 50>> <<set _mHigh = _e.morale >= 40>> <<set _r = Math.random()>> <<set _eAct = "进攻">> <<if _aHigh && _mHigh>> /* 战术型:有破绽再打,否则蓄积 */ <<if _p.flaws >= 2>> <<set _eAct = _r < 0.70 ? "进攻" : "警戒">> <<else>> <<set _eAct = _r < 0.50 ? "警戒" : (_r < 0.80 ? "观察" : "防御")>> <</if>> <<elseif _aHigh && !_mHigh>> /* 保守型:防御/观察为主 */ <<set _eAct = _r < 0.40 ? "防御" : (_r < 0.70 ? "观察" : "休息")>> <<elseif !_aHigh && _mHigh>> /* 莽撞型:大量进攻 */ <<set _eAct = _r < 0.70 ? "进攻" : (_r < 0.90 ? "防御" : "警戒")>> <<else>> /* 慌乱型 */ <<set _eAct = _r < 0.40 ? "进攻" : (_r < 0.70 ? "休息" : "警戒")>> <</if>> /* ── 执行敌方行动 ── */ <<if _eAct === "进攻">> <<set _e.alertness = Math.max(0, _e.alertness - 10)>> <<set _e.hp = Math.max(0, _e.hp - 10)>> <<set _eMiss = _p.flaws >= 2 ? 0 : (_p.flaws === 1 ? 0.10 : 0.20)>> <<if Math.random() < _eMiss>> <<set _e.morale = Math.max(0, _e.morale - 5)>> <<set _p.morale = Math.min(100, _p.morale + 5)>> <<set _log += _e.name+"的攻击偏离了目标。">> <<else>> <<set _eDmg = Math.floor((8 + Math.floor(Math.random() * 8)) * (1 + _p.flaws * 0.3))>> <<if _p.nextDefend || _p.dmgHalf>><<set _eDmg = Math.floor(_eDmg / 2)>><</if>> <<set _p.injury = Math.min(100, _p.injury + _eDmg)>> <<set _p.morale = Math.max(0, _p.morale - 8)>> <<set _e.morale = Math.min(100, _e.morale + 5)>> <<set _log += _e.name+"发起攻击,你受到 "+_eDmg+" 点伤势"+(_p.flaws > 0 ? "(破绽×"+_p.flaws+")" : "")+"。">> <</if>> <<elseif _eAct === "警戒">> <<set _e.alertness = Math.min(100, _e.alertness + 30)>> <<if Math.random() < _e.alertness / 100>> <<set _p.flaws = Math.min(3, _p.flaws + 1)>> <<set _e.flaws = Math.max(0, _e.flaws - 1)>> <<set _log += _e.name+"警觉地观察,察觉了你的破绽("+_p.flaws+"层)。">> <<else>> <<set _log += _e.name+"提高了警觉。">> <</if>> <<elseif _eAct === "观察">> <<set _e.alertness = Math.min(100, _e.alertness + 15)>> <<if _e.alertness > 50 && Math.random() < 0.4>> <<set _p.flaws = Math.min(3, _p.flaws + 1)>> <<set _log += _e.name+"审视你的动作,发现你的破绽("+_p.flaws+"层)。">> <<else>> <<set _log += _e.name+"打量着你。">> <</if>> <<elseif _eAct === "防御">> <<set _e.alertness = Math.max(0, _e.alertness - 5)>> <<set _e.nextDefend = true>> <<set _log += _e.name+"摆好防御姿态。">> <<elseif _eAct === "休息">> <<set _e.hp = Math.min(_e.hpMax, _e.hp + 10)>> <<set _e.alertness = Math.max(0, _e.alertness - 15)>> <<set _log += _e.name+"暂时后退,恢复体力。">> <</if>> /* ── 回合末:破绽更新(警觉差值驱动)── */ <<set _alertDiff = _p.alertness - _e.alertness>> <<if _alertDiff > 20>> <<set _e.flaws = Math.min(3, _e.flaws + 1)>> <<set _log += " (你的警觉压制对方,敌方破绽+1)">> <<elseif _alertDiff < -20>> <<set _p.flaws = Math.min(3, _p.flaws + 1)>> <<set _log += " (你的警觉不足,己方破绽+1)">> <</if>> /* ── 敌方逃跑检定 ── */ <<if !_e.lockedEscape && _e.morale < 30>> <<set _escProb = (30 - _e.morale) / 40>> <<if Math.random() < _escProb>> <<set $activeCombat.result = "enemy_flee">> <<set _log += " "+_e.name+"丧失战意,仓皇逃去。">> <<else>> <<set _e.morale = Math.max(0, _e.morale - 15)>> <<set _p.morale = Math.min(100, _p.morale + 10)>> <<set _log += " "+_e.name+"试图逃跑,被你挡住了!">> <</if>> <</if>> /* ── 重置单回合标志 ── */ <<set _p.nextDefend = false>> <<set _e.nextDefend = false>> <<set _p.dmgHalf = false>> <<set _e.lockedEscape = false>> /* ── 终止条件 ── */ <<if !$activeCombat.result>> <<if _e.injury >= _e.injuryMax>> <<set $activeCombat.result = "kill">> <<set _log += " 【"+_e.name+"被击倒!】">> <<elseif _p.injury >= 100>> <<set $activeCombat.result = "player_hurt">> <<set _log += " 【你伤势过重,被迫撤退!】">> <<set $life = Math.max(0, $life - Math.floor(_p.injury / 2))>> <<elseif _p.morale <= 0>> <<set $activeCombat.result = "player_flee">> <<set _log += " 【士气崩溃,你本能地撤退!】">> <<set $san = Math.max(0, $san - 10)>> <<set $tre = Math.min(100, $tre + 10)>> <<elseif _e.morale <= 0>> <<set $activeCombat.result = "enemy_flee">> <<set _log += " "+_e.name+"斗志全无,转身逃去。">> <</if>> <</if>> <</if>> /* ── 写回 ── */ <<set $activeCombat.round += 1>> <<set $activeCombat.log = _log>> /* 战斗结束折算体力损耗(逃跑<<return>>路径已在上方处理,不会重复) */ <<if $activeCombat.result>> <<set $power = Math.max(0, $power - Math.floor((_p.hpMax - _p.hp) / 2))>> <</if>> <</widget>> <</nobr>>
<<nobr>> <<widget "combatEnemyDefs">> <<set $combatEnemyTable = {}>> <<set $combatEnemyTable["jellyfish_swarm"] = { name:"水母群", alertness:30, morale:[40,60], hp:40, injuryMax:50, loot:[{id:"jellyfish",qty:[1,2]}], stateDesc:{ high_high:"水母群密密麻麻地环绕着你,触手微微颤动", high_low: "水母群开始向外扩散,似乎在寻找退路", low_high: "水母群毫无章法地涌来,刺针乱舞", low_low: "水母群已经溃散,漫无目的地漂流" }, hpDesc:{ 50:"水母群数量明显减少", 25:"残余的水母萎靡漂散" }, injuryDesc:{ 40:"部分水母已经破碎", 70:"水母群几近瓦解" } }>> <<set $combatEnemyTable["armored_crab"] = { name:"岩甲蟹", alertness:55, morale:[60,80], hp:60, injuryMax:70, loot:[{id:"kingcrab",qty:[1,1]},{id:"fish_bone",qty:[0,1]}], stateDesc:{ high_high:"岩甲蟹横举双钳,步步为营地逼近", high_low: "岩甲蟹缩入壳中,双眼警惕地盯着你", low_high: "岩甲蟹横冲直撞,钳子横扫而来", low_low: "岩甲蟹踉踉跄跄,夹钳无力地垂着" }, hpDesc:{ 50:"它的动作开始迟缓", 25:"它气喘吁吁,步伐沉重" }, injuryDesc:{ 40:"它的外壳出现了裂缝", 70:"血从甲缝中渗出" } }>> <<set $combatEnemyTable["patrol_shark"] = { name:"巡游鲨", alertness:65, morale:[65,85], hp:100, injuryMax:80, loot:[{id:"fish_scale",qty:[1,2]},{id:"fish_meat",qty:[1,3]}], stateDesc:{ high_high:"它警惕地环绕你游动,伺机而动", high_low: "它保持距离,似乎在犹豫是否撤退", low_high: "它毫无顾忌地直扑过来", low_low: "它慌乱地冲撞,动作越来越混乱" }, hpDesc:{ 50:"它的动作开始迟缓", 25:"它气喘吁吁,游动愈发沉重" }, injuryDesc:{ 40:"它身上渗出淡淡的血色", 70:"血流不止,伤口在水中晕开大片红雾" } }>> <<set $combatEnemyTable["deep_eel"] = { name:"狼鳗", alertness:70, morale:[50,70], hp:50, injuryMax:60, loot:[{id:"eel",qty:[1,2]}], stateDesc:{ high_high:"狼鳗缠绕成螺旋,在暗处窥视你的破绽", high_low: "它收缩身体,慢慢向后退去", low_high: "狼鳗猛地弹射而来,獠牙大张", low_low: "它扭动着受伤的身躯,本能地乱咬" }, hpDesc:{ 50:"它的扭动变得迟钝", 25:"它颤抖着,几乎无法保持姿态" }, injuryDesc:{ 40:"它皮肤上出现了撕裂伤", 70:"它血迹斑斑,奄奄一息" } }>> <<set $combatEnemyTable["angler_lurker"] = { name:"深渊灯笼鱼", alertness:75, morale:[55,75], hp:80, injuryMax:85, loot:[{id:"anglerfish",qty:[1,1]},{id:"fish_meat",qty:[1,2]}], stateDesc:{ high_high:"它的诱饵灯摇曳着,耐心等待你靠近", high_low: "诱饵灯光芒黯淡,它缓缓向深处沉去", low_high: "它张开血盆大口直扑而来,诱饵乱晃", low_low: "它慌乱地闪烁着微弱的光,四处乱窜" }, hpDesc:{ 50:"它的发光器官开始闪烁不稳", 25:"它几乎无法维持平衡" }, injuryDesc:{ 40:"它的鳞片破碎脱落", 70:"它的伤口在黑暗中发着惨淡的光" } }>> <</widget>> <</nobr>>
<<nobr>> <<if !$activeCombat>><<goto ($combatReturn || "仓外探索")>><</if>> <<set _p = $activeCombat.player>> <<set _e = $activeCombat.enemy>> <<set _res = $activeCombat.result>> <<set _hpLost = _p.hpMax - _p.hp>> <<set _pwrDeduct = Math.floor(_hpLost / 2)>> <div style="max-width:520px;margin:0 auto;padding:0.6rem 0.4rem;font-size:0.82rem;"> <<if _res === "kill">> <div style="border:1px solid var(--teal-bright,#4ecdc4);border-radius:4px;padding:0.6rem 0.85rem;margin-bottom:0.5rem;"> <div style="color:var(--teal-bright,#4ecdc4);font-size:0.9rem;margin-bottom:0.3rem;">✓ 战斗胜利</div> <div style="color:var(--bone,#d4c9a8);line-height:1.8;"> 你击倒了<<print _e.name>>,历经 <<print $activeCombat.round>> 回合。 /* TODO: 战利品结算 — 遍历 _e.loot,调用 addItem widget */ </div> </div> <<elseif _res === "enemy_flee">> <div style="border:1px solid var(--teal-dim,#2a5a5a);border-radius:4px;padding:0.6rem 0.85rem;margin-bottom:0.5rem;"> <div style="color:var(--bone,#d4c9a8);font-size:0.9rem;margin-bottom:0.3rem;">— 敌人逃跑</div> <div style="color:var(--bone,#d4c9a8);line-height:1.8;"><<print _e.name>>丧失了战斗意志,消失在黑暗中。</div> </div> <<elseif _res === "player_flee">> <div style="border:1px solid var(--bone-dim,#3a3025);border-radius:4px;padding:0.6rem 0.85rem;margin-bottom:0.5rem;"> <div style="color:var(--muted,#8a8070);font-size:0.9rem;margin-bottom:0.3rem;">↩ 撤退</div> <div style="color:var(--bone,#d4c9a8);line-height:1.8;"><<print $activeCombat.log>></div> </div> <<elseif _res === "player_hurt">> <div style="border:1px solid var(--danger-bright,#e74c3c);border-radius:4px;padding:0.6rem 0.85rem;margin-bottom:0.5rem;"> <div style="color:var(--danger-bright,#e74c3c);font-size:0.9rem;margin-bottom:0.3rem;">✗ 重伤撤退</div> <div style="color:var(--bone,#d4c9a8);line-height:1.8;"> 你伤势过重,勉强撤出战斗。 生命值已损失 <span style="color:var(--danger-bright,#e74c3c);">−<<print Math.floor(_p.injury / 2)>></span>。 </div> </div> <</if>> <!-- 体力损耗小结 --> <<if _hpLost > 0>> <div style="color:var(--muted,#8a8070);font-size:0.76rem;margin-bottom:0.6rem;padding:0.2rem 0;"> 体力消耗 <<print _hpLost>>,主体体力 −<<print _pwrDeduct>> </div> <</if>> <<link "离开">> <<set $activeCombat = null>> <<goto $combatReturn>> <</link>> </div> <</nobr>>
<<nobr>> <<set _dv = $cps["viona"]>> <div id="dev-panel"> <div class="dev-title">DEV — 维奥娜</div> /* ── 快速数值调整 ── */ <div class="dev-section">数值</div> <<link "饥饿 +30">><<set $cps.viona.hunger = Math.min(100,$cps.viona.hunger+30)>><<navigate "go" "dev面板">><</link>> · <<link "饥饿 -30">><<set $cps.viona.hunger = Math.max(0,$cps.viona.hunger-30)>><<navigate "go" "dev面板">><</link>><br><<link "饮水 +30">><<set $cps.viona.water = Math.min(100,$cps.viona.water+30)>><<navigate "go" "dev面板">><</link>> · <<link "饮水 -30">><<set $cps.viona.water = Math.max(0,$cps.viona.water-30)>><<navigate "go" "dev面板">><</link>><br> <<link "精力 +30">><<set $cps.viona.energy = Math.min(100,$cps.viona.energy+30)>><<navigate "go" "dev面板">><</link>> · <<link "精力 -30">><<set $cps.viona.energy = Math.max(0,$cps.viona.energy-30)>><<navigate "go" "dev面板">><</link>><br> <<link "好感 +10">><<set $cps.viona.bond = Math.min(100,$cps.viona.bond+10)>><<navigate "go" "dev面板">><</link>> · <<link "好感 -10">><<set $cps.viona.bond = Math.max(0,$cps.viona.bond-10)>><<navigate "go" "dev面板">><</link>> /* ── 记忆 tag ── */ <div class="dev-section">记忆 tag</div> <<link "was_teased">> <<cpMemoryTag "viona" "was_teased" 1>> <<navigate "go" "dev面板">><</link>> ·<<link "received_gift">><<cpMemoryTag "viona" "received_gift" 1>><<navigate "go" "dev面板">><</link>> · <<link "had_chat">> <<cpMemoryTag "viona" "had_chat" 1>> <<navigate "go" "dev面板">><</link>> · <<link "清除记忆">><<set $cps.viona.recentMemory = {tag:"",day:0,expire:-1}>><<navigate "go" "dev面板">><</link>> /* ── 状态 tag ── */ <div class="dev-section">状态</div> <<link "潮湿 切换">><<set $cps.viona.wet = !$cps.viona.wet>> <<navigate "go" "dev面板">><</link>> · <<link "生病 切换">><<set $cps.viona.sick = !$cps.viona.sick>><<navigate "go" "dev面板">><</link>><br> <<link "无伤">><<set $cps.viona.injured=0>><<navigate "go" "dev面板">><</link>> · <<link "轻伤">><<set $cps.viona.injured=1>><<navigate "go" "dev面板">><</link>> · <<link "重伤">><<set $cps.viona.injured=2>><<navigate "go" "dev面板">><</link>> /* ── 强制意图 ── */ <div class="dev-section">强制行动</div> <<link "强制重算意图">><<cpIntent "viona">><<navigate "go" "dev面板">><</link>> · <<link "强制外出">> <<set $cps.viona.action="outside">> <<set $cps.viona.location="舱外">> <<set $cps.viona.actionEndTime=$day*1440+$hour*60+$minute+10>> <<navigate "go" "dev面板">> <</link>> /* ── 当前状态显示 ── */ <div class="dev-section">当前状态</div> <div class="dev-status"> 饥饿:<<print Math.floor(_dv.hunger)>> 饮水:<<print Math.floor(_dv.water)>> 精力:<<print Math.floor(_dv.energy)>><br> 好感:<<print _dv.bond>> 心情:<<print ["低落","平常","愉快"][_dv.mood]>> 安定:<<print ["不安","平静","安心"][_dv.calm]>><br> 位置:<<print _dv.location>> 行动:<<print _dv.action>><br> 潮湿:<<print _dv.wet>> 受伤:<<print _dv.injured>> 生病:<<print _dv.sick>><br> 记忆:<<print _dv.recentMemory.tag || "无">> (到期日<<print _dv.recentMemory.expire>>) </div> <div class="dev-return"><<link "关闭">><<goto 走廊>><</link>></div> </div> <</nobr>>