JavaScript must be enabled to play.
Browser lacks capabilities required to play.
Upgrade or switch to another browser.
Loading…
<div class="dashboard-layout fade-in-down"> <div class="dash-center-art"> <canvas id="particle-canvas"></canvas> <<if $meta.todayVisitor>> <div class="sprite-container" @data-visitor="$meta.todayVisitor"></div> <</if>> </div> <div class="dash-bottom-left"> <div class="doll-id-card"> <div class="doll-avatar"></div> <div class="doll-info"> <div class="doll-name"><<print $management.doll.name>></div> <div class="doll-status">核心 Lv.<<print $management.doll.level>> | 待机中</div> </div> </div> <div class="quick-status-box" style="margin-top: 1rem;"> <h4 class="qs-title">WORKSHOP INFO</h4> <<set _activeProcs = Object.keys($management.workshop.processes).filter(k => $management.workshop.processes[k] > 0).map(k => window.ProcessDatabase[k] ? window.ProcessDatabase[k].name : k)>> <div class="qs-item" style="color: var(--color-accent-gold); font-size: 0.85rem; white-space: normal; line-height: 1.4;"> 工序: <<print _activeProcs.length > 0 ? _activeProcs.join(" / ") : "无">> </div> <div class="qs-item">已录入原型: <span class="highlight-gold"><<print Object.keys($management.workshop.prototypes).length>></span></div> <div style="display: flex; gap: 0.5rem; margin-top: 0.8rem;"> <button class="sys-btn menu-item" data-target="工坊_管理面板" style="flex:1; padding: 0.4rem; font-size: 0.85rem;">设施管理</button> <button class="sys-btn menu-item" data-target="工坊仓库_主界面" style="flex:1; padding: 0.4rem; font-size: 0.85rem;">工坊仓库</button> </div> </div> <!-- 核心调度按钮:纯净 HTML,动态显示文本 --> <div style="margin-top: 0.5rem;"> <button class="sys-btn btn-primary menu-item" data-target="工坊_调度面板" style="width:100%; padding: 0.8rem; font-size: 1rem; letter-spacing: 2px;"> >日间调度 (1 AP) </button> </div> </div> <div class="dash-right-matrix"> <div class="dash-btn size-large menu-item" data-target="研习_主界面"> <div class="btn-bg"></div> <div class="btn-content"><span class="en">STUDY</span><span class="zh">研习密契</span></div> </div> <!-- 私人库房移至右侧 --> <div class="dash-btn size-medium menu-item" data-target="私人库房_主界面"> <div class="btn-bg"></div> <div class="btn-content"><span class="en">INVENTORY</span><span class="zh">私人库房</span></div> </div> <div class="dash-btn size-medium menu-item" data-target="开发_主界面"> <div class="btn-bg"></div> <div class="btn-content"><span class="en">ALCHEMY</span><span class="zh">私人炼金</span></div> </div> <div class="dash-btn size-medium menu-item" data-target="探索_主界面"> <div class="btn-bg"></div> <div class="btn-content"><span class="en">EXPLORE</span><span class="zh">探索影界</span></div> </div> <div class="dash-btn size-medium menu-item" data-target="接待_主界面"> <div class="btn-bg"></div> <div class="btn-content"><span class="en">GUEST</span><span class="zh">接待访客</span></div> </div> <div class="dash-btn size-small menu-item" data-target="宅邸日常_小憩"> <div class="btn-bg"></div> <div class="btn-content"><span class="en">REST</span><span class="zh">小憩片刻</span></div> </div> <div class="dash-btn size-small menu-item" data-target="宅邸日常_进餐"> <div class="btn-bg"></div> <div class="btn-content"><span class="en">DINE</span><span class="zh">享用茶点</span></div> </div> <div class="dash-btn size-small btn-danger menu-item" data-action="end_day" style="grid-column: span 2;"> <div class="btn-bg"></div> <div class="btn-content"> <span class="en">SLEEP</span><span class="zh">结束本日</span> </div> </div> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">WORKSHOP INFO</h1> <div class="zh">工坊设施与原型总览</div> </div> <div class="sys-back-btn menu-item" data-target="工坊_主界面"> < RETURN </div> </div> <div class="cc-content-area" style="max-width: 1000px; margin: 0 auto;"> <!-- 1. 设施状态区 --> <h3 class="cc-subtitle">核心设施状态 <span class="en">FACILITIES</span></h3> <div style="display: flex; gap: 1rem; margin-bottom: 2.5rem;"> <!-- 助理协议 --> <div style="flex: 1; background: var(--color-overlay-dark); border: 1px solid var(--color-border-subtle); padding: 1.2rem;"> <div style="color: var(--color-text-secondary); font-size: 0.85rem; margin-bottom: 0.5rem;">自动化协议等级</div> <div style="font-size: 1.5rem; color: var(--color-accent-gold); font-family: var(--font-en);">Lv.<<print $management.doll.level>></div> <div style="font-size: 0.85rem; color: var(--color-text-muted); margin-top: 0.8rem; border-top: 1px dashed var(--color-border-subtle); padding-top: 0.5rem;"> 当前支持:基础队列执行 </div> </div> <!-- 搭载工序 --> <div style="flex: 2; background: var(--color-overlay-dark); border: 1px solid var(--color-border-subtle); padding: 1.2rem;"> <div style="color: var(--color-text-secondary); font-size: 0.85rem; margin-bottom: 0.5rem;">已搭载加工工序</div> <div style="color: var(--color-accent-gold); font-size: 1.1rem; letter-spacing: 2px; margin-top: 0.5rem;"> <<set _activeProcs = Object.keys($management.workshop.processes).filter(k => $management.workshop.processes[k] > 0).map(k => window.ProcessDatabase[k] ? window.ProcessDatabase[k].name : k)>> [ <<print _activeProcs.length > 0 ? _activeProcs.join(" / ") : "无可用工序">> ] </div> </div> </div> <!-- 2. 原型数据区 --> <div style="display: flex; justify-content: space-between; align-items: flex-end; border-bottom: 1px solid var(--color-border-subtle); padding-bottom: 0.5rem; margin-bottom: 1.5rem;"> <h3 class="cc-subtitle" style="margin-bottom: 0; border-bottom: none; padding-bottom: 0;">已录入原型数据 <span class="en">PROTOTYPES</span></h3> <button class="sys-btn menu-item" data-target="工坊_录入原型" style="padding: 0.4rem 1rem; font-size: 0.85rem; border-color: var(--color-accent-purple); color: var(--color-accent-purple);"> + 录入新原型 </button> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem;"> <<set _protoKeys to Object.keys($management.workshop.prototypes)>> <<if _protoKeys.length === 0>> <div class="empty-text" style="grid-column: span 2; padding: 3rem; border: 1px dashed var(--color-border-subtle);"> 尚未向工坊录入任何配方原型。 </div> <<else>> <<for _i, _rcpId range _protoKeys>> <<set _rcp to window.RecipeDatabase[_rcpId]>> <div class="ws-order-card" style="cursor: default; padding: 1.2rem;"> <!-- 头部:名称与所需工序标签 --> <div class="ws-card-header" style="display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--color-border-subtle); padding-bottom: 0.8rem; margin-bottom: 0.8rem;"> <span><<print _rcp.name>></span> <span style="font-size: 0.8rem; color: var(--color-accent-purple); border: 1px solid var(--color-accent-purple); padding: 0.2rem 0.5rem;"> <<print window.ProcessDatabase[_rcp.final_process] ? window.ProcessDatabase[_rcp.final_process].name : _rcp.final_process>> </span> </div> <!-- 效率数据 --> <div style="font-size:0.85rem; color:var(--color-text-muted); margin-bottom:1rem; display: flex; justify-content: space-between; font-family: var(--font-en);"> <span>COST: <span class="highlight-gold"><<print _rcp.time_cost>> Time</span></span> <span>YIELD: <span class="highlight-gold"><<print _rcp.output_amount>><<print window.ItemDatabase[_rcp.output_item].unit>></span></span> </div> <!-- 材料需求明细 --> <div style="background: var(--color-bg-base); padding: 0.8rem; border: 1px solid var(--color-border-subtle);"> <div style="font-size:0.8rem; color:var(--color-text-secondary); margin-bottom:0.5rem; border-bottom: 1px dashed var(--color-border-subtle); padding-bottom: 0.3rem;"> [ 流水线基础材料需求 ] </div> <<for _matId, _req range _rcp.prototype_cost>> <<set _matDef to window.ItemDatabase[_matId]>> <div style="display:flex; justify-content:space-between; font-size:0.85rem; color:var(--color-text-primary); padding:0.3rem 0;"> <span><<print _matDef.name>> <span style="font-size:0.75rem; color:var(--color-text-muted);">({_req.form})</span></span> <span style="font-family: var(--font-en);"><<print _req.amount>> <<print _matDef.unit>></span> </div> <</for>> </div> </div> <</for>> <</if>> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">REGISTER PROTOTYPE</h1> <div class="zh">录入生产原型</div> </div> <div class="sys-back-btn menu-item" data-target="工坊_管理面板"> < RETURN </div> </div> <div class="cc-content-area" style="max-width: 900px; margin: 0 auto;"> <div style="margin-bottom: 2rem; color: var(--color-text-secondary); font-size: 0.95rem; line-height: 1.6; background: var(--color-overlay-dark); padding: 1rem; border-left: 2px solid var(--color-accent-purple);"> 请从行囊中选择一件成品交给炼金人偶进行解析。<br> <span style="color: var(--color-accent-gold);">注意:录入过程需要消耗 1 份成品,且你必须已经掌握了该物品的配方蓝图。</span> </div> <!-- 改为 2 列网格展示物品 --> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.5rem;"> <<set _hasAvailable to false>> /* 1. 获取玩家当前私人库房和背包里的所有物品 */ <<set _availableMats to setup.Alchemy.getAvailableMaterials($inventory)>> /* 2. 按 baseId 聚合数量,方便展示总数 */ <<set _groupedItems to {}>> <<for _i to 0; _i lt _availableMats.length; _i++>> <<set _mat to _availableMats[_i]>> <<if !_groupedItems[_mat.baseId]>> /* 保存一个 sampleTraits 用于渲染名字和作为扣除时的参考 */ <<set _groupedItems[_mat.baseId] to { amount: 0, sampleTraits: _mat.traits }>> <</if>> <<set _groupedItems[_mat.baseId].amount += _mat.amount>> <</for>> /* 3. 遍历聚合后的库存物品 */ <<for _baseId, _data range _groupedItems>> <<set _itemDef to window.ItemDatabase[_baseId]>> /* 筛选条件 A:必须是产品 */ <<if _itemDef and _itemDef.is_product>> /* 反向查找该产品对应的配方 ID */ <<set _rcpId to Object.keys(window.RecipeDatabase).find(id => window.RecipeDatabase[id].output_item === _baseId)>> /* 筛选条件 B:有对应配方 + 工坊尚未录入 + 玩家已掌握该配方 */ <<if _rcpId and !$management.workshop.prototypes[_rcpId] and $recipes[_rcpId] !== undefined>> <<set _hasAvailable to true>> <<set _rcp to window.RecipeDatabase[_rcpId]>> <<capture _baseId, _rcpId, _rcp, _data>> <div class="ws-order-card" style="padding: 1.2rem; display: flex; flex-direction: column; justify-content: space-between;"> <!-- 物品信息区 --> <div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 1.5rem;"> <div> <div style="font-size: 1.2rem; color: var(--color-text-primary); margin-bottom: 0.3rem;"> <<print _itemDef.icon>> <<print setup.Material.formatName(_baseId, _data.sampleTraits)>> </div> <div style="font-size: 0.85rem; color: var(--color-text-muted);"> 对应配方: <<print _rcp.name>> </div> </div> <div style="font-size: 1.2rem; font-family: var(--font-en); color: var(--color-accent-gold);"> 持有: <<print _data.amount>> </div> </div> <!-- 操作区 --> <div style="text-align: right; border-top: 1px dashed var(--color-border-subtle); padding-top: 1rem;"> <<button "提交样本录入 (1 AP)">> <<if $player.derived.currentAp >= 1>> /* 1. 扣除 AP */ <<set $player.derived.currentAp -= 1>> /* 2. 扣除 1 个成品样本 (底层会自动处理 Hash 匹配或暴力扣除) */ <<run setup.Alchemy.deductMaterial(_baseId, _data.sampleTraits, 1)>> /* 3. 录入系统 */ <<set $management.workshop.prototypes[_rcpId] to true>> <<run GameUI.Toast.show("原型录入成功!已消耗 1 份样本。", "success")>> <<run $(document).trigger(":refreshHUD")>> /* 刷新当前页面,让已录入的物品消失 */ <<goto "工坊_录入原型">> <<else>> <<run GameUI.Toast.show("精力不足,无法录入原型。", "error")>> <</if>> <</button>> </div> </div> <</capture>> <</if>> <</if>> <</for>> <<if !_hasAvailable>> <div class="empty-text" style="grid-column: 1 / -1; padding: 4rem; border: 1px dashed var(--color-border-subtle); text-align: center;"> <div style="font-size: 3rem; opacity: 0.3; margin-bottom: 1rem;">📦</div> 行囊中没有可录入的成品。<br> <span style="font-size: 0.85rem; margin-top: 0.5rem; display: inline-block; color: var(--color-text-muted);"> 请先在【私人炼金】中制作出成品,且确保你已掌握其配方。 </span> </div> <</if>> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">WORKSHOP: SCHEDULE</h1> <div class="zh">日间工坊调度</div> </div> </div> <div class="cc-layout" style="min-height: 70vh;"> <div class="cc-sidebar"> <h3 class="cc-sidebar-title">日间调度</h3> <div class="cc-nav-links"> <<link "【 订单调度 】">><<replace "#ws-content">><<ws_orders>><</replace>><</link>> <<link "【 物资采购 】">><<replace "#ws-content">><<ws_market>><</replace>><</link>> </div> <div class="cc-confirm-btn" style="display: flex; flex-direction: column; gap: 0.8rem;"> <<button "确认 (1 AP)">> <<if $player.derived.currentAp >= 1>> <<set $player.derived.currentAp -= 1>> <<goto "工坊_主界面">> <<else>> <<run GameUI.Toast.show("精力不足,无法确认安排。", "error")>> <</if>> <</button>> <<button "取消">><<run Engine.backward()>><</button>> </div> </div> <div class="cc-content-area" style="display: flex; flex-direction: column;"> <div style="display:flex; justify-content:space-between; border-bottom:1px solid var(--color-border-subtle); padding-bottom:1rem; margin-bottom:1rem;"> <span style="color:var(--color-text-secondary);">负责人: <span style="color:var(--color-text-primary);"><<print $management.doll.name>></span></span> <div style="font-family:var(--font-en); font-size:0.9rem;"> AP: <span class="highlight-gold"><<print $player.derived.currentAp>></span> | 资金: <span id="ws-ui-coin" class="highlight-gold"><<print $management.workshop.coin>></span> </div> </div> <div id="ws-doll-msg" style="border-left: 2px solid var(--color-accent-purple); padding: 0.8rem 1rem; margin-bottom: 1.5rem; font-size: 0.95rem; background: var(--color-overlay-dark); color: var(--color-text-muted);"> 【 <<print $management.doll.name>> 】:日间调整生产队列或采购物资,将在确认时消耗 1 点 AP。若取消则不消耗。 </div> <!-- 动态渲染容器,默认加载订单组件 --> <div id="ws-content" style="flex: 1; overflow-y: auto; padding-right: 10px;"> <<ws_orders>> </div> </div> </div>
<!-- 1. 后台静默生成今日的订单和采购数据 --> <<run window.WorkshopSystem.generateDailyContent()>> <!-- 2. 预留剧情判定:这里可以根据天数或特定变量,跳转到不同的剧情段落 --> <<if $time.sleepDay === 2>> <!-- 比如第二天早上,可以触发一个特殊剧情 --> <!-- <<goto "剧情_第二天晨间">> --> <</if>> <!-- 3. 如果没有特殊剧情,显示常规的苏醒文本 --> <div class="static-scene fade-in-down"> <div class="static-text" style="text-align: center;"> <p style="font-size: 1.5rem; color: var(--color-text-primary); letter-spacing: 4px; margin-bottom: 2rem;"> 第 <<print $time.sleepDay>> 日,晨光微熹。 </p> <p style="color: var(--color-text-secondary);"> 你从沉睡中苏醒,精力已完全恢复。<br> <<print $management.doll.name>> 已经为你整理好了今日的树影相会派发清单,以及黑市游商的到货情报。 </p> </div> <div class="controls-box" style="margin-top: 3rem;"> <!-- 点击后,锁定侧边栏,进入晨间规划面板 --> <<button "开始晨间规划""晨间_工坊规划">><</button>> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">WORKSHOP: MORNING</h1> <div class="zh">晨间工坊规划</div> </div> </div> <div class="cc-layout" style="min-height: 70vh;"> <div class="cc-sidebar"> <h3 class="cc-sidebar-title">晨间规划</h3> <div class="cc-nav-links"> <!-- 利用 replace 局部刷新右侧内容区 --> <<link "【 订单调度 】">><<replace "#ws-content">><<ws_orders>><</replace>><</link>> <<link "【 物资采购 】">><<replace "#ws-content">><<ws_market>><</replace>><</link>> <<link "【 工坊总览 】">><<replace "#ws-content">><<ws_overview>><</replace>><</link>> </div> <div class="cc-confirm-btn"> <button class="sys-btn btn-primary menu-item" data-target="工坊_主界面" style="width: 100%;">确认安排</button> </div> </div> <div class="cc-content-area" style="display: flex; flex-direction: column;"> <div style="display:flex; justify-content:space-between; border-bottom:1px solid var(--color-border-subtle); padding-bottom:1rem; margin-bottom:1rem;"> <span style="color:var(--color-text-secondary);">负责人: <span style="color:var(--color-text-primary);"><<print $management.doll.name>></span></span> <div style="font-family:var(--font-en); font-size:0.9rem;"> 资金: <span id="ws-ui-coin" class="highlight-gold"><<print $management.workshop.coin>></span> </div> </div> <div id="ws-doll-msg" style="border-left: 2px solid var(--color-accent-purple); padding: 0.8rem 1rem; margin-bottom: 1.5rem; font-size: 0.95rem; background: var(--color-overlay-dark); color: var(--color-text-muted);"> 【 <<print $management.doll.name>> 】:早安。请先查阅工坊状态,再进行订单调度。 </div> <!-- 动态渲染容器,默认加载订单组件 --> <div id="ws-content" style="flex: 1; overflow-y: auto; padding-right: 10px;"> <<ws_orders>> </div> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">NIGHT LOGISTICS</h1> <div class="zh">夜间物流打包</div> </div> </div> <<run window.WorkshopSystem.simulateDaytimeProduction()>> <div class="fade-in-down" style="max-width: 800px; margin: 2rem auto;"> <div style="color: var(--color-text-secondary); margin-bottom: 2rem; font-size: 1.05rem; line-height: 1.8;"> <p>工坊的白日运作已结束。在休息之前,请清点今日的订单。</p> <p>将需要明早让信使带走的货物<span style="color:var(--color-accent-gold); font-weight:bold;">【打包发货】</span>。未打包的订单将扣除 1 日期限。</p> </div> <!-- 调用我们之前写好的打包宏 --> <div id="night-delivery-mount"> <<night_delivery_panel>> </div> <div style="margin-top: 3rem; text-align: center;"> <<button "确认打包,准备休息" "夜间结算_确认">><<addclass ".macro-button" "btn-primary">><</button>> </div> </div>
<div class="sleep-wrapper fade-in-down"> <!-- 核心动效:影界夜空画框 --> <div class="night-window"> <div class="window-frame"></div> <!-- 漫幽星云层 (缓慢流动的底色) --> <div class="nebula-layer"></div> <!-- 远景粒子 (小而暗,移动极慢) --> <div class="star-particles far"> <div class="star s1"></div> <div class="star s2"></div> <div class="star s3"></div> <div class="star s4"></div> <div class="star s5"></div> <div class="star s6"></div> <div class="star s7"></div> <div class="star s8"></div> </div> <!-- 近景粒子 (大而亮,移动较快,模拟漫幽生物的孢子或光屑) --> <div class="star-particles near"> <div class="star n1"></div> <div class="star n2"></div> <div class="star n3"></div> <div class="star n4"></div> <div class="star n5"></div> </div> </div> <!-- 文字排版区 --> <div class="sleep-text-area fade-in-down" style="animation-delay: 0.2s;"> <!-- 标题组:中英双语 + 装饰线 --> <div class="sleep-title-group"> <div class="sleep-title-en">NIGHTFALL APPROACHES</div> <div class="sleep-title-zh">夜色已深,工坊的炉火渐渐平息。</div> <div class="sleep-divider"></div> </div> <!-- 提示框:系统日志风格 --> <div class="sleep-notice-box"> <div class="notice-header"> <span class="notice-icon">✦</span> <span class="notice-label">SYS.NOTICE</span> </div> <div class="notice-body"> <p>现在闭上眼睛,助理 <span style="color:var(--color-text-primary); font-weight:bold;">[ <<print $management.doll.name>> ]</span> 将根据你白天的安排,在夜间自动执行生产与交付。</p> <p>未完成的订单期限将减少,同时会扣除每日的基础维护费用。</p> </div> </div> </div> <div class="controls-box" style="margin-top: 3rem; flex-direction: row; justify-content: center; gap: 3rem;"> <<button "闭上眼睛" "夜间结算_报告">><<addclass ".macro-button" "btn-sleep">><</button>> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">REPORT</h1> <div class="zh">结算报告</div> </div> </div> <<night_report>>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">WORKSHOP WAREHOUSE</h1> <div class="zh">工坊流水线仓库</div> </div> <div class="sys-back-btn menu-item" data-target="工坊_主界面"> < RETURN </div> </div> <div class="warehouse-container"> <!-- 1. 顶部容量监控条 --> <<set _currentVol = window.WorkshopSystem ? window.WorkshopSystem.getInventoryVolume() : 0>> <<set _maxVol = $management.warehouse.maxCapacity>> <<set _volPercent = Math.min((_currentVol / _maxVol) * 100, 100)>> <div class="wh-capacity-box"> <div class="wh-cap-text"> <span class="zh">工坊总负载</span><span class="en">CAPACITY</span> <span @class="_currentVol > _maxVol ? 'val highlight-red' : 'val highlight-gold'"> <<print _currentVol>> / <<print _maxVol>> </span> </div> <div class="wh-cap-bar-bg"> <div class="wh-cap-bar-fill" @style="'width: ' + _volPercent + '%; background-color: ' + (_currentVol > _maxVol ? 'var(--color-error)' : 'var(--color-accent-gold)') + ';'"></div> </div> <<if _currentVol > _maxVol>> <div style="color:var(--color-error); font-size:0.85rem; margin-top:0.5rem; text-align:right;"> [ 警告:负载已溢出,夜间结算时将强制销毁部分物资 ] </div> <</if>> </div> <!-- 2. 原材料区域 --> <div class="wh-section"> <h3 class="wh-section-title">原材料 <span class="en">MATERIALS</span></h3> <div class="wh-grid"> <<set _matKeys = Object.keys($management.warehouse.materials)>> <<if _matKeys.length === 0>> <div class="empty-text">仓库中暂无原材料。</div> <<else>> /* 遍历第一层:基础 ID */ <<for _i to 0; _i lt _matKeys.length; _i++>> <<set _baseId = _matKeys[_i]>> <<set _itemDef = window.ItemDatabase[_baseId]>> <<set _hashGroup = $management.warehouse.materials[_baseId]>> /* 遍历第二层:Hash Key (具体属性组合) */ <<for _hashKey, _itemData range _hashGroup>> <<if _itemData.amount > 0>> <div class="wh-item-card"> <!-- 调用智能命名器 --> <div class="wh-item-name"><<print setup.Material.formatName(_baseId, _itemData)>></div> <div class="wh-item-amount"><<print _itemData.amount>> <span class="unit"><<print _itemDef.unit>></span></div> </div> <</if>> <</for>> <</for>> <</if>> </div> </div> <!-- 3. 制成品区域 --> <div class="wh-section"> <h3 class="wh-section-title">制成品 <span class="en">PRODUCTS</span></h3> <div class="wh-grid"> <<set _prodKeys = Object.keys($management.warehouse.products)>> <<if _prodKeys.length === 0>> <div class="empty-text">仓库中暂无制成品。</div> <<else>> /* 遍历第一层:基础 ID */ <<for _i to 0; _i lt _prodKeys.length; _i++>> <<set _baseId = _prodKeys[_i]>> <<set _itemDef = window.ItemDatabase[_baseId]>> <<set _hashGroup = $management.warehouse.products[_baseId]>> /* 遍历第二层:Hash Key */ <<for _hashKey, _itemData range _hashGroup>> <<if _itemData.amount > 0>> <div class="wh-item-card"> <!-- 调用智能命名器 --> <div class="wh-item-name"><<print setup.Material.formatName(_baseId, _itemData)>></div> <div class="wh-item-amount"><<print _itemData.amount>> <span class="unit"><<print _itemDef.unit>></span></div> </div> <</if>> <</for>> <</for>> <</if>> </div> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">PRIVATE STORAGE</h1> <div class="zh">私人库房与行囊整理</div> </div> <div class="sys-back-btn menu-item" data-target="工坊_主界面"> < RETURN </div> </div> <<private_warehouse>>
<<set $management.visitors to $management.visitors || []>> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">PARLOR</h1> <div class="zh">会客室</div> </div> <div class="sys-back-btn menu-item" data-target="工坊_主界面"> < RETURN </div> </div> <div class="parlor-layout fade-in-down" style="padding: 20px; max-width: 1000px; margin: 0 auto;"> <<if $management.visitors.length === 0>> <div class="guest-placeholder"> <div class="guest-icon">🪑</div> <h2 class="guest-title">静谧的会客室</h2> <p class="guest-desc">这里是接待访客、进行洽谈与交易的地方。<br>目前没有访客在等待。</p> <div style="margin-top: 40px;"> <<button "【DEBUG】模拟 完构物质 登门拜访">> /* 现在不需要瞎编 desc 了,直接推入 ID 即可 */ <<run $management.visitors.push({ id: "physical_done" })>> <<set $npcs.physical_done.isMet to true>> <<run Engine.play("接待_主界面")>> <</button>> </div> </div> <<else>> <div class="visitors-list"> <h3 style="color: var(--color-text-primary); font-family: var(--font-title); border-bottom: 1px solid var(--color-border-subtle); padding-bottom: 10px; margin-bottom: 20px;"> 等候中的访客 <span class="en" style="font-size: 0.8rem; color: var(--color-text-muted);">WAITING GUESTS</span> </h3> <<for _i, _visitor range $management.visitors>> <<capture _i, _visitor>> <<set _npcStatic to setup.NPCs[_visitor.id]>> <<set _npcDynamic to $npcs[_visitor.id]>> <div class="visitor-card"> <div class="v-avatar"> <span class="text-muted">IMAGE</span> </div> <div class="v-info"> <!-- 1. 来访者名字与绝美英文 --> <div class="v-header" style="border-bottom: none; padding-bottom: 0; margin-bottom: 15px; display: flex; flex-direction: column;"> <div> <span style="color: var(--color-text-secondary); font-size: 1.1rem; font-family: var(--font-zh);">来访者是 </span> <span class="v-name" style="color: var(--color-accent-gold); font-family: var(--font-zh); font-size: 1.8rem; font-weight: bold;"><<print _npcStatic.name>></span> </div> <!-- 英文名排版:等宽/无衬线,增加字间距,极具高级感 --> <div style="font-family: var(--font-en); font-size: 1rem; color: var(--color-text-muted); letter-spacing: 2px; margin-top: 5px; text-transform: uppercase;"> <<print _npcStatic.en_name>> </div> </div> <!-- 2. 拜访描述 (直接读取你写的 reception 文本!) --> <div class="v-desc" style="font-size: 0.95rem; color: var(--color-text-primary); margin-bottom: 20px; border-left: 2px solid var(--color-accent-purple); padding-left: 15px; line-height: 1.8; font-family: var(--font-zh); text-align: justify;"> <<set _stageKey to "stage_" + (_npcDynamic.loreStage || 1)>> <<print _npcStatic.reception[_stageKey]>> </div> <!-- 3. 概念与势力 --> <div class="v-faction" style="font-family: var(--font-zh); font-size: 0.9rem; color: var(--color-accent-purple); margin-bottom: 20px; background: var(--color-bg-base); padding: 8px 15px; display: inline-block; border: 1px solid var(--color-border-subtle);"> [ <<print _npcStatic.concept_tag>> | <<print _npcStatic.faction || "未知势力">> ] </div> <!-- 4. 接待按钮 --> <div class="v-actions" style="margin-top: auto;"> <<button "迎客并洽谈 (消耗 AP)">> <<if setup.Contacts.initSession(_visitor.id, "physical_done_event_1")>> <<run $management.visitors.splice(_i, 1)>> <<goto "洽谈_主界面">> <<else>> <<run GameUI.Toast.show("初始化洽谈失败:未找到对应的剧本数据。", "error")>> <</if>> <</button>> <<button "婉拒不见">> <<run $management.visitors.splice(_i, 1)>> <<run GameUI.Toast.show("你让炼金人偶婉拒了访客。", "warn")>> <<run Engine.play("接待_主界面")>> <</button>> </div> </div> </div> <</capture>> <</for>> </div> <</if>> </div>
<<if ndef setup.ContactSession>> <<goto "接待_主界面">> <<else>> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">NEGOTIATION</h1> <div class="zh">洽谈中:<<print setup.NPCs[setup.ContactSession.npcId].name>></div> </div> </div> <<negotiation_board>> <</if>>
<!-- 安全校验:读取 setup 上的持久化数据 --> <<if ndef setup.NegoFinalData>> <<goto "接待_主界面">> <</if>> <<set _finalData to setup.NegoFinalData>> <<set _reason to setup.NegoResult>> <<set _npcStatic to setup.NPCs[_finalData.npcId]>> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">AFTERMATH</h1> <div class="zh">会客结束</div> </div> </div> <div class="aftermath-layout fade-in-down"> <div class="aftermath-grid-bg"></div> <!-- 左侧:人偶的日常叙事 --> <div class="aftermath-left"> <div class="aftermath-narrative"> <p>随着沉重的大门缓缓闭合,会客室重新归于寂静。</p> <p><<print $management.doll.name>> 端着一杯刚泡好的红茶走到你身边,轻轻放在了桌案上。茶香稍微驱散了刚才交涉时残留的压抑感。</p> <p class="aftermath-doll-quote">“主人,辛苦了。关于刚才那位客人的谈话内容,我已经整理完毕并归档。”</p> </div> <!-- 动态剧情分支结算 --> <<if _reason === "accept">> <div class="aftermath-result-box accept"> <div class="result-title">[ 契约达成 ]</div> <div class="result-desc">你接下了<<print _npcStatic.name>>的专属订单。这份来自旧时代的图纸已经被录入工坊系统。</div> <!-- 预留:执行接单的底层代码 --> </div> <<elseif _reason === "reject">> <div class="aftermath-result-box reject"> <div class="result-title">[ 关系断裂 ]</div> <div class="result-desc">你拒绝了委托。<<print _npcStatic.name>>的事件串已永久中断,他不会再踏入这间工坊。</div> <!-- 预留:执行中断事件串的底层代码 --> <<set $npcs[_finalData.npcId].storyline_aborted to true>> </div> <<else>> <div class="aftermath-result-box neutral"> <div class="result-title">[ 常规会面 ]</div> <div class="result-desc">一次普通的交涉。对方似乎还在观望。</div> </div> <</if>> </div> <!-- 右侧:硬核的档案结算报告 --> <div class="aftermath-right"> <div class="dossier-header"> <span class="dossier-title-badge">DOSSIER UPDATED</span> <span class="dossier-target">TARGET: <<print _npcStatic.en_name.toUpperCase()>></span> </div> <!-- 1. 图鉴记录提示 --> <<if _finalData.metaRecorded>> <h3 class="cc-subtitle" style="color: var(--color-accent-gold); border-color: var(--color-accent-gold);">情报已归档</h3> <div class="dossier-card"> <div class="dossier-card-title"><<print _finalData.metaRecorded.title>></div> <div style="font-size: 0.85rem; color: var(--color-text-muted); margin-bottom: 10px;">主题: <<print _finalData.metaRecorded.theme>></div> <div style="display: flex; gap: 8px; margin-bottom: 10px;"> <<for _i, _kw range _finalData.metaRecorded.keywords>> <span class="dossier-keyword-tag"><<print _kw>></span> <</for>> </div> <div style="font-size: 0.9rem; color: var(--color-text-secondary); line-height: 1.6; text-align: justify;"> <<print _finalData.metaRecorded.summary>> </div> </div> <</if>> <!-- 2. 态度变化总结 (如果有检定节点的话) --> <<if _finalData.totalNodes > 0>> <h3 class="cc-subtitle">博弈复盘</h3> <div class="dossier-stat-grid"> <div class="dossier-stat-box"> <div style="font-size: 0.8rem; color: var(--color-text-muted); margin-bottom: 5px;">节点成功率</div> <div style="font-family: var(--font-en); font-size: 2rem; font-weight: bold; color: var(--color-accent-gold);"><<print _finalData.rate>>%</div> </div> <div class="dossier-stat-box"> <div style="font-size: 0.8rem; color: var(--color-text-muted); margin-bottom: 5px;">综合评价</div> <div @style="'font-family: var(--font-zh); font-size: 1.5rem; font-weight: bold; margin-top: 5px; color: ' + (_finalData.result === '完美成功' ? 'var(--color-accent-gold)' : (_finalData.result === '成功' ? 'var(--color-text-primary)' : 'var(--color-error)'))"> <<print _finalData.result>> </div> </div> </div> <</if>> <!-- 离开按钮 --> <div style="margin-top: 40px;"> <<button "整理完毕,返回接待室" "接待_主界面">> <<run delete setup.NegoResult>> <<run delete setup.NegoFinalData>> <</button>> </div> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">REST & RECOVER</h1> <div class="zh">小憩片刻</div> </div> <div class="sys-back-btn menu-item" data-target="工坊_主界面"> < RETURN </div> </div> <div class="building-interior-layout"> <div class="interior-content"> <div class="detail-desc fade-in-down"> <p>你在工坊角落的躺椅上躺下,闭上眼睛。虽然影界的空气总是带着一丝挥之不去的阴冷,但短暂的放空依然能有效缓解精神的紧绷。</p> <p class="text-muted">(休息会消耗宝贵的时间,请注意日程安排。)</p> </div> <div class="interaction-board fade-in-down"> <div class="board-section"> <h3 class="section-title">执行动作</h3> <div class="action-list"> <div class="action-btn"> <div class="act-info"> <span class="act-icon">🛋️</span> <span class="act-name">闭目养神</span> </div> <div class="act-cost">恢复: 2 AP | 降压: 5 | Time: 15</div> <<button "执行">> <<if $time.timeValue + 15 > 100>> <<run GameUI.Toast.show("时间太晚了,不如直接结束本日休息吧。", "warn")>> <<else>> <<set $time.timeValue += 15>> <<set $player.derived.currentAp = Math.min($player.derived.apMax, $player.derived.currentAp + 2)>> <<set $player.mental.stress = Math.max(0, $player.mental.stress - 5)>> <<run $(document).trigger(":refreshHUD")>> <<run GameUI.Toast.show("稍微恢复了一些精力。", "normal")>> <<run Engine.play("工坊_主界面")>> <</if>> <</button>> </div> </div> </div> </div> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">TEA TIME</h1> <div class="zh">享用茶点</div> </div> <div class="sys-back-btn menu-item" data-target="工坊_主界面"> < RETURN </div> </div> <div class="building-interior-layout"> <div class="interior-content"> <div class="detail-desc fade-in-down"> <p>你让炼金人偶为你准备了一份简单的茶点。虽然影界的食材大多透着古怪的色泽,但经过人偶的精心处理,味道还算可以接受,能有效补充体力。</p> </div> <div class="interaction-board fade-in-down"> <div class="board-section"> <h3 class="section-title">执行动作</h3> <div class="action-list"> <div class="action-btn"> <div class="act-info"> <span class="act-icon">🫖</span> <span class="act-name">享用茶点</span> </div> <div class="act-cost">花费: 15 银币 | 恢复: 4 AP | Time: 10</div> <<button "执行">> <<if $time.timeValue + 10 > 100>> <<run GameUI.Toast.show("时间太晚了,不宜进食。", "warn")>> <<elseif $management.workshop.coin < 15>> <<run GameUI.Toast.show("银币不足,连最劣质的茶点都买不起了。", "error")>> <<else>> <<set $time.timeValue += 10>> <<set $management.workshop.coin -= 15>> <<set $player.derived.currentAp = Math.min($player.derived.apMax, $player.derived.currentAp + 4)>> <<run $(document).trigger(":refreshHUD")>> <<run GameUI.Toast.show("享用了茶点,精力充沛。", "success")>> <<run Engine.play("工坊_主界面")>> <</if>> <</button>> </div> </div> </div> </div> </div> </div>
<<set _pinnedRecipe to null>> <<set _currentMethod to null>> <<set _activeSlots to []>> <<set _selectedSkill to null>> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">ALCHEMY WORKSPACE</h1> <div class="zh">私人炼金台</div> </div> <div class="sys-back-btn menu-item" data-target="工坊_主界面"> < RETURN </div> </div> <div class="alchemy-layout fade-in-down"> <!-- 左侧:图纸与工序 (紧凑排版) --> <div class="al-left-panel"> <!-- 上半部:图纸 --> <div class="panel-title-soft">案头图纸 <span class="en">BLUEPRINT</span></div> <div class="blueprint-board compact" id="blueprint-board"> <<include "开发_图纸渲染">> </div> <div class="recipe-book-btn"> <<button "打开配方簿">><<run GameUI.Popup.open("配方簿 | RECIPES", "开发_配方簿弹窗")>><</button>> </div> <!-- 下半部:工序网格 --> <div class="panel-title-soft" style="margin-top: 1.5rem;">执行工序 <span class="en">METHOD</span></div> <div class="method-selector" id="method-selector"> <<include "开发_工序选择渲染">> </div> </div> <!-- 中间:核心操作台 (纯粹的槽位与执行) --> <div class="al-center-panel"> <div class="magic-circle-bg"></div> <div class="slots-arena" id="slots-area"> <<include "开发_槽位渲染">> </div> <div class="execution-console" id="execution-console"> <<include "开发_执行控制台渲染">> </div> </div> <!-- 右侧:私人库房 --> <div class="al-right-panel"> <div class="panel-title-soft" style="text-align: right;"><span class="en">PRIVATE STORAGE</span> 私人素材库</div> <div class="inventory-list" id="inventory-list"> <<include "开发_库存渲染">> </div> </div> </div>
<<if _pinnedRecipe === null>> <div class="empty-blueprint"> <div class="icon">📜</div> <p>案头空空如也。</p> </div> <<else>> <<set _rcp to window.RecipeDatabase[_pinnedRecipe]>> <div class="active-blueprint"> <h3 class="bp-title">《<<print _rcp.name>>》</h3> <div class="bp-meta"> <span>工序:<b class="highlight-gold"><<print window.ProcessDatabase[_rcp.final_process].name>></b></span> <span>难度:<<print _rcp.difficulty>></span> </div> <div class="bp-ingredients"> <<for _i, _ing range _rcp.ingredients>> <div class="bp-ing-item"> <div class="ing-req"><b class="highlight-purple">[<<print _ing.tags.join("] [")>>]</b></div> <div class="ing-amount">需: <<print _ing.amount>><<print _ing.unit>> <span class="status-check pending">[未满]</span></div> </div> <</for>> </div> <div class="bp-unpin"> <<button "取下">><<set _pinnedRecipe to null>><<replace "#blueprint-board">><<include "开发_图纸渲染">><</replace>><</button>> </div> </div> <</if>>
<!-- 基础工序:3列紧凑网格 --> <div class="method-grid basic-methods"> <<set _allProcs to Object.keys(window.ProcessDatabase)>> <<for _i, _pId range _allProcs>> <<set _pDef to window.ProcessDatabase[_pId]>> <<capture _pId, _pDef>> <div @class="'method-btn ' + (_currentMethod === _pId ? 'active' : '')"> <<link _pDef.name>> <<set _currentMethod to _pId>> <<set _activeSlots to []>> <<for _j to 0; _j lt _pDef.slots.length; _j++>> <<set _activeSlots.push({ id: _pDef.slots[_j].id, name: _pDef.slots[_j].name, item: null, amount: 10, optional: _pDef.slots[_j].optional || false })>> <</for>> <<replace "#method-selector">><<include "开发_工序选择渲染">><</replace>> <<replace "#slots-area">><<include "开发_槽位渲染">><</replace>> <<replace "#execution-console">><<include "开发_执行控制台渲染">><</replace>> <</link>> </div> <</capture>> <</for>> </div> <!-- 炼金序列:单列宽按钮 --> <div class="method-group-title">高级序列</div> <div class="method-grid sequence-methods"> <<set _allSeqs to Object.keys(window.SequenceDatabase)>> <<for _i, _sId range _allSeqs>> <<set _sDef to window.SequenceDatabase[_sId]>> <<capture _sId, _sDef>> <div @class="'method-btn ' + (_currentMethod === _sId ? 'active' : '')"> <<link _sDef.name>> <<set _currentMethod to _sId>> /* 序列的槽位生成逻辑与基础工序完全一致 */ <<set _activeSlots to []>> <<for _j to 0; _j lt _sDef.slots.length; _j++>> <<set _activeSlots.push({ id: _sDef.slots[_j].id, name: _sDef.slots[_j].name, item: null, amount: 10, optional: _sDef.slots[_j].optional || false })>> <</for>> <<replace "#method-selector">><<include "开发_工序选择渲染">><</replace>> <<replace "#slots-area">><<include "开发_槽位渲染">><</replace>> <<replace "#execution-console">><<include "开发_执行控制台渲染">><</replace>> <</link>> </div> <</capture>> <</for>> </div>
<<if _currentMethod === null>> <div class="empty-slots-msg">请先在左侧选择执行工序。</div> <<else>> <div class="slots-container"> <<for _i, _slot range _activeSlots>> <<capture _i, _slot>> <div @class="'alchemy-slot ' + (_slot.item ? 'filled' : 'empty')"> <div class="slot-ring"></div> <<if _slot.item>> <div class="slot-content"> <div class="s-name"><<print setup.Material.formatName(_slot.item.baseId, _slot.item.traits)>></div> <!-- 数量调整控制区 --> <div class="s-amount-control" style="display: flex; justify-content: center; align-items: center; gap: 5px; margin-bottom: 8px;"> <<button "-">> <<set _activeSlots[_i].amount -= 10>> <<if _activeSlots[_i].amount < 1>><<set _activeSlots[_i].amount to 1>><</if>> <<replace "#slots-area">><<include "开发_槽位渲染">><</replace>> <<replace "#execution-console">><<include "开发_执行控制台渲染">><</replace>> <</button>> <span class="s-amount" style="margin: 0; min-width: 40px;"><<print _slot.amount>></span> <<button "+">> /* 不能超过玩家实际持有的数量 */ <<set _max to _slot.item.amount>> <<set _activeSlots[_i].amount += 10>> <<if _activeSlots[_i].amount > _max>><<set _activeSlots[_i].amount to _max>><</if>> <<replace "#slots-area">><<include "开发_槽位渲染">><</replace>> <<replace "#execution-console">><<include "开发_执行控制台渲染">><</replace>> <</button>> </div> <<button "移除">> <<set _activeSlots[_i].item to null>> <<replace "#slots-area">><<include "开发_槽位渲染">><</replace>> <<replace "#execution-console">><<include "开发_执行控制台渲染">><</replace>> <</button>> </div> <<else>> <div class="slot-content"> <div class="s-placeholder"><<print _slot.name>></div> <div class="s-hint">点击右侧素材填入</div> </div> <</if>> </div> <</capture>> <</for>> </div> <</if>>
<<if _currentMethod !== null>> <div class="console-box"> <div class="skill-injection"> <span class="text-muted">注入个人技能 (消耗 1 AP):</span> <div class="skill-options"> <<link "无">><<set _selectedSkill to null>><<replace "#execution-console">><<include "开发_执行控制台渲染">><</replace>><</link>> <<link "巫术">><<set _selectedSkill to "witchcraft">><<replace "#execution-console">><<include "开发_执行控制台渲染">><</replace>><</link>> <<link "博弈">><<set _selectedSkill to "game">><<replace "#execution-console">><<include "开发_执行控制台渲染">><</replace>><</link>> </div> </div> <div class="execute-action"> <div class="cost-info"> <span>AP: <b class="highlight-gold">-2</b></span> <span>Time: <b class="highlight-gold">+20</b></span> </div> <<button "开始炼成">> <<executeAlchemy>> <</button>> </div> </div> <</if>>
/* 调用 JS 聚合器,获取合并后的材料列表 */ <<set _availableMats to setup.Alchemy.getAvailableMaterials($inventory)>> <<if _availableMats.length === 0>> <div class="empty-inventory"> <div style="font-size: 2rem; opacity: 0.3; margin-bottom: 10px;">🗄️</div> 私人库房与背包空空如也。 </div> <<else>> <<for _i, _mat range _availableMats>> <<capture _i, _mat>> <div class="inv-item"> <div class="inv-info"> <div class="i-name"><<print setup.Material.formatName(_mat.baseId, _mat.traits)>></div> <div class="i-stock">持有: <b class="highlight-gold"><<print _mat.amount>></b></div> </div> <div class="inv-action"> <<button "填入">> /* 1. 检查是否已经选择了工序 (是否有槽位) */ <<if _activeSlots.length === 0>> <<run GameUI.Toast.show("请先在左侧选择执行工序!", "warn")>> <<else>> /* 2. 寻找第一个空槽位 */ <<set _emptyIdx to _activeSlots.findIndex(s => s.item === null)>> <<if _emptyIdx !== -1>> /* 3. 填入数据,默认数量为 10 或最大持有量 */ <<set _activeSlots[_emptyIdx].item to clone(_mat)>> <<set _activeSlots[_emptyIdx].amount to Math.min(10, _mat.amount)>> /* 4. 局部刷新槽位区和控制台区 */ <<replace "#slots-area">><<include "开发_槽位渲染">><</replace>> <<replace "#execution-console">><<include "开发_执行控制台渲染">><</replace>> <<else>> <<run GameUI.Toast.show("操作台槽位已满!", "error")>> <</if>> <</if>> <</button>> </div> </div> <</capture>> <</for>> <</if>>
/* 初始化弹窗内选中的配方 */ <<set _selectedRecipe to null>> <div class="recipe-book-layout" id="recipe-book-layout"> <<include "开发_配方簿内容">> </div>
<div style="display: flex; gap: 20px; height: 60vh; min-height: 400px; overflow: hidden;"> <!-- 左侧:已解锁的配方列表 --> <!-- 使用 flex: 0 0 220px 严格锁死宽度,防止被右侧挤压 --> <div style="flex: 0 0 220px; border-right: 1px solid var(--color-border-subtle); overflow-y: auto; padding-right: 10px;"> <<set _knownRecipes to Object.keys($recipes)>> <<if _knownRecipes.length === 0>> <div class="text-muted" style="font-size: 0.9rem; text-align: center; margin-top: 20px;">暂无任何配方记录。</div> <<else>> <<for _i, _rId range _knownRecipes>> <<set _rcpDef to window.RecipeDatabase[_rId]>> <<if _rcpDef>> <<capture _rId>> <div style="margin-bottom: 8px;"> <<button _rcpDef.name>> <<set _selectedRecipe to _rId>> <<replace "#recipe-book-layout">><<include "开发_配方簿内容">><</replace>> <</button>> </div> <</capture>> <</if>> <</for>> <</if>> </div> <!-- 右侧:配方详情与悬挂操作 --> <!-- 使用 flex: 1 确保占据剩余空间,并允许内部独立滚动 --> <div style="flex: 1; overflow-y: auto; padding-left: 10px; padding-right: 10px; display: flex; flex-direction: column;"> <<if _selectedRecipe === null>> <div class="text-muted" style="text-align:center; margin-top: 100px;"> <div style="font-size: 3rem; opacity: 0.3; margin-bottom: 10px;">📖</div> 请在左侧选择配方查看详情。 </div> <<else>> <<set _rcp to window.RecipeDatabase[_selectedRecipe]>> <<set _status to $recipes[_selectedRecipe]>> <h2 style="color: var(--color-accent-gold); margin-top: 0; margin-bottom: 10px; font-family: var(--font-title); letter-spacing: 2px;"><<print _rcp.name>></h2> <div style="margin-bottom: 20px;"> <<if _status === 0>> <span class="state-badge" style="color: var(--color-text-muted); border: 1px solid var(--color-text-muted); padding: 2px 8px; font-size: 0.85rem;">蓝图期 (未实践)</span> <<else>> <span class="state-badge" style="color: var(--color-accent-purple); border: 1px solid var(--color-accent-purple); padding: 2px 8px; font-size: 0.85rem;">已掌握 (可量产)</span> <</if>> </div> <div style="background: var(--color-overlay-dark); padding: 15px; border-left: 2px solid var(--color-accent-purple); margin-bottom: 20px;"> <p style="color: var(--color-text-primary); line-height: 1.6; margin: 0;"><<print _rcp.desc>></p> </div> <h4 style="color: var(--color-text-secondary); border-bottom: 1px dashed var(--color-border-subtle); padding-bottom: 5px; margin-bottom: 10px;">调配需求</h4> <ul style="color: var(--color-text-muted); font-size: 0.9rem; padding-left: 20px; margin-bottom: 20px;"> <li>最终工序:<b style="color: var(--color-text-primary);"><<print window.ProcessDatabase[_rcp.final_process].name>></b></li> <<if _rcp.required_sequence>> <li>指定序列:<b style="color: var(--color-accent-gold);"><<print window.SequenceDatabase[_rcp.required_sequence].name>></b></li> <</if>> <<if _rcp.required_skill>> <li>注入技能:<b style="color: var(--color-accent-purple);"><<print _rcp.required_skill>></b></li> <</if>> </ul> <h4 style="color: var(--color-text-secondary); border-bottom: 1px dashed var(--color-border-subtle); padding-bottom: 5px; margin-bottom: 10px;">物质构成</h4> <div style="display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px;"> <<for _i, _ing range _rcp.ingredients>> <div style="background: var(--color-bg-surface); padding: 10px; border: 1px solid var(--color-border-subtle); display: flex; justify-content: space-between; align-items: center;"> <div> <span style="color: var(--color-text-primary);">[<<print _ing.tags.join("] [")>>]</span> <<if _ing.traits>> <<set _traitStrs to []>> <<for _k, _v range _ing.traits>><<run _traitStrs.push(_v)>><</for>> <span style="color: var(--color-accent-gold); font-size: 0.85rem; margin-left: 5px;">(<<print _traitStrs.join(", ")>>)</span> <</if>> </div> <span style="color: var(--color-text-muted); font-family: var(--font-en);"><<print _ing.amount>><<print _ing.unit>></span> </div> <</for>> </div> <!-- 将悬挂按钮推到最底部 --> <div style="margin-top: auto; text-align: right; border-top: 1px solid var(--color-border-subtle); padding-top: 15px;"> <<button "悬挂此图纸于案头">> <<set _pinnedRecipe to _selectedRecipe>> <<run GameUI.Popup.close()>> <<replace "#blueprint-board">><<include "开发_图纸渲染">><</replace>> <</button>> </div> <</if>> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">SANCTUM OF KNOWLEDGE</h1> <div class="zh">宅邸学库</div> </div> <div class="sys-back-btn menu-item" data-target="工坊_主界面"> < RETURN </div> </div> <div class="soft-bookshelf-layout fade-in-down"> /* --- 1. 研读 (左上横条 2x1) --- */ <div class="soft-block block-study menu-item" data-target="研习_研读"> <div class="s-content"> <div class="s-en">STUDY & FOCUS</div> <h2 class="s-title">研读卷宗</h2> <p class="s-desc">布置环境,沉浸于旧纸堆中汲取经验。</p> </div> </div> /* --- 2. 概念解构 (中上横条 2x1) --- */ <div class="soft-block block-decoding menu-item" data-target="研习_概念解构"> <div class="s-content"> <div class="s-en">CONCEPT DECODING</div> <h2 class="s-title">概念解析</h2> <p class="s-desc">扭曲灵态,从乱码中锚定真理的坐标。</p> </div> </div> /* --- 3. 炼金笔记 (右上宽块 2x1) --- */ <div class="soft-block block-notes menu-item" data-target="研习_炼金笔记"> <div class="s-content"> <div class="s-en">ALCHEMY NOTES</div> <h2 class="s-title">炼金笔记</h2> <p class="s-desc">配方、物质溯源与实验记录。</p> </div> </div> /* --- 4. 学科校验 (中右竖块 1x2) --- */ <div class="soft-block block-exam menu-item" data-target="研习_学科校验"> <div class="s-content"> <div class="s-en">OCCULT EXAM</div> <h2 class="s-title">学科校验</h2> <p class="s-desc">测试学识,突破秘氛评级。</p> </div> </div> /* --- 5. 智识殿堂 (极右高块 1x3) --- */ <div class="soft-block block-lore menu-item" data-target="研习_智识殿堂"> <div class="s-content"> <div class="s-en">LORE</div> <h2 class="s-title">智识殿堂</h2> <p class="s-desc">世界观与影界法则。</p> </div> </div> /* --- 6. 角色档案 (中左横条 2x1) --- */ <div class="soft-block block-contacts menu-item" data-target="研习_人际档案"> <div class="s-content"> <div class="s-en">ARCHIVES</div> <h2 class="s-title">角色档案</h2> <p class="s-desc">已知实体的深度情报与态度观测。</p> </div> </div> /* --- 7. 典藏展览 (左下横条 2x1) --- */ <div class="soft-block block-relics menu-item" data-target="研习_典藏展览"> <div class="s-content"> <div class="s-en">RELICS</div> <h2 class="s-title">典藏展览</h2> <p class="s-desc">非棺物品的静默陈列。</p> </div> </div> /* --- 8. 冥想 (右下小方块 1x1) --- */ <div class="soft-block block-meditation menu-item" data-target="研习_冥想"> <div class="s-content"> <div class="s-en">MEDITATION</div> <h2 class="s-title">冥想</h2> <p class="s-desc">平息理智,触碰预言的边缘。</p> </div> </div> /* --- 9. 沼泽学 (底部条带) --- */ <<if $meta.events and $meta.events.swamp_unlocked>> <div class="soft-block block-swamp menu-item" data-target="研习_沼泽学"> <div class="s-content"> <div class="s-en">SWAMP</div> <h2 class="s-title">沼泽学</h2> </div> </div> <<else>> <div class="soft-block block-swamp locked" onclick="GameUI.Toast.show('你对如何成为魔女还没有任何头绪...', 'warn')"> <div class="s-content"> <div class="s-en">???</div> <h2 class="s-title">未知领域</h2> </div> </div> <</if>> </div>
<<set _selItemType to _selItemType || null>> <<set _selItemId to _selItemId || null>> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">STUDY & FOCUS</h1> <div class="zh">研读卷宗</div> </div> <div class="sys-back-btn menu-item" data-target="研习_主界面"> < RETURN </div> </div> <div class="cc-layout" style="min-height: 75vh; padding: 20px;"> /* 核心修复:必须用 do 宏包裹动态渲染区! */ <<do>> <div style="display: flex; gap: 2rem; width: 100%; height: 100%;"> /* ================= 左侧:已破译的物品列表 ================= */ <div style="flex: 1; display: flex; flex-direction: column; border-right: 1px solid var(--color-border-subtle); padding-right: 20px;"> <h3 class="cc-subtitle">研读目标 <span class="en">TARGETS</span></h3> <div style="font-size: 0.85rem; color: var(--color-text-muted); margin-bottom: 15px;"> 仅显示已在【概念解构台】中成功破译的密契与非棺。 </div> <div style="display: flex; flex-direction: column; overflow-y: auto; padding-right: 5px;"> <<set _hasValidItems to false>> /* 1. 渲染密契 (Pacts) */ <<for _pactId, _pactData range $inventory.pacts>> <<if _pactData.isDecoded>> <<set _hasValidItems to true>> <<capture _pactId>> <<set _pactDef to setup.Pacts[_pactId]>> <<set _targetDef to setup.Database.StudyTargets[_pactId]>> <<set _maxTimes to _targetDef.maxStudyTimes || 3>> <<set _currentTimes to _pactData.studiedCount || 0>> <<set _isExhausted to _currentTimes >= _maxTimes>> /* 拼装按钮内部的 HTML 字符串 */ <<set _statusHtml to _isExhausted ? '<span class="status-exhausted">[ EXHAUSTED ]</span>' : '<span class="status-ready">[ READY ]</span>'>> <<set _btnLabel to '<div class="btn-inner-flex"><span class="item-title">📜 ' + _pactDef.name + '</span>' + _statusHtml + '</div>'>> <div @class="'study-target-btn ' + (_selItemId === _pactId ? 'active' : '')"> <<if _isExhausted>> <button disabled><<print _btnLabel>></button> <<else>> <<button _btnLabel>> <<set _selItemType to "pacts">> <<set _selItemId to _pactId>> <<redo>> <</button>> <</if>> </div> <</capture>> <</if>> <</for>> /* 2. 渲染非棺 (Relics) */ <<for _relicId, _relicData range $inventory.relics>> <<if _relicData.isDecoded>> <<set _hasValidItems to true>> <<capture _relicId>> <<set _relicDef to setup.Relics[_relicId]>> <<set _targetDef to setup.Database.StudyTargets[_relicId]>> <<set _maxTimes to _targetDef.maxStudyTimes || 3>> <<set _currentTimes to _relicData.studiedCount || 0>> <<set _isExhausted to _currentTimes >= _maxTimes>> /* 拼装按钮内部的 HTML 字符串 */ <<set _statusHtml to _isExhausted ? '<span class="status-exhausted">[ EXHAUSTED ]</span>' : '<span class="status-ready">[ READY ]</span>'>> <<set _btnLabel to '<div class="btn-inner-flex"><span class="item-title">' + _relicDef.icon + ' ' + _relicDef.name + '</span>' + _statusHtml + '</div>'>> <div @class="'study-target-btn ' + (_selItemId === _relicId ? 'active' : '')"> <<if _isExhausted>> <button disabled><<print _btnLabel>></button> <<else>> <<button _btnLabel>> <<set _selItemType to "relics">> <<set _selItemId to _relicId>> <<redo>> <</button>> <</if>> </div> <</capture>> <</if>> <</for>> <<if !_hasValidItems>> <div class="empty-text" style="margin-top: 20px; text-align: center;">没有已破译的物品可供研读。</div> <</if>> </div> </div> /* ================= 右侧:研读详情与执行 ================= */ <div style="flex: 1; display: flex; flex-direction: column; padding-left: 10px;"> <h3 class="cc-subtitle">研读详情 <span class="en">DETAILS</span></h3> <<if _selItemId>> <<set _itemDef to (_selItemType === "pacts" ? setup.Pacts[_selItemId] : setup.Relics[_selItemId])>> <<set _targetDef to setup.Database.StudyTargets[_selItemId]>> <<set _invData to $inventory[_selItemType][_selItemId]>> <<set _maxTimes to _targetDef.maxStudyTimes || 3>> <<set _currentTimes to _invData.studiedCount || 0>> <<set _apCost to _targetDef.studyApCost || 2>> <<set _timeCost to _targetDef.studyTimeCost || 30>> /* 翻译奖励文本 */ <<set _rewardText to "未知">> <<if _targetDef.expReward>> <<set _cat to _targetDef.expReward.category>> <<set _id to _targetDef.expReward.id>> <<if _cat === "occult">> <<set _rewardText to (_id === "nomantia" ? "巫疍学" : (_id === "deillogy" ? "诅咒学" : "图腾学")) + " 经验">> <<else>> <<set _skillDict to { linguistics: "语言学", eavesdrop: "窃听", detective: "侦探学", rhetoric: "话术", foresight: "预知", witchcraft: "巫术", combat: "格斗", game: "博弈", locate: "定位" }>> <<set _rewardText to (_skillDict[_id] || _id) + " 经验">> <</if>> <</if>> <div style="background: var(--color-bg-glass); border: 1px solid var(--color-border-subtle); padding: 20px; margin-bottom: 20px;"> <div style="font-size: 1.2rem; color: var(--color-accent-gold); margin-bottom: 10px; font-family: var(--font-title);"> <<print _itemDef.name>> </div> <div style="font-size: 0.9rem; color: var(--color-text-secondary); line-height: 1.6; margin-bottom: 20px; border-bottom: 1px dashed var(--color-border-subtle); padding-bottom: 15px;"> 你正准备深入剖析这份知识。每次研读都会榨取它内部蕴含的真理,直到它彻底变成凡物。 </div> <div style="display: flex; justify-content: space-between; margin-bottom: 10px; font-size: 0.95rem;"> <span style="color: var(--color-text-muted);">研读进度:</span> <span style="font-family: var(--font-en); color: var(--color-text-primary);"> <span class="highlight-gold"><<print _currentTimes>></span> / <<print _maxTimes>> </span> </div> <div style="display: flex; justify-content: space-between; margin-bottom: 10px; font-size: 0.95rem;"> <span style="color: var(--color-text-muted);">预计收获:</span> <span style="color: var(--color-accent-purple);"><<print _rewardText>></span> </div> </div> <div style="margin-top: auto; background: var(--color-bg-surface); border: 1px solid var(--color-border-subtle); padding: 20px;"> <div style="display: flex; justify-content: space-between; margin-bottom: 20px; font-family: var(--font-en); font-size: 1.1rem;"> <span>AP COST: <span class="highlight-gold"><<print _apCost>></span></span> <span>TIME COST: <span class="highlight-gold"><<print _timeCost>></span></span> </div> <<button "开始研读">> <<set _res to setup.Study.executeReadingItem(_selItemType, _selItemId)>> <<if _res.success>> <<run GameUI.Toast.show(_res.msg, "success")>> <<if $inventory[_selItemType][_selItemId].studiedCount >= _maxTimes>> <<set _selItemId to null>> /* 读满了自动取消选中 */ <</if>> <<redo>> <<else>> <<run GameUI.Toast.show(_res.msg, "error")>> <</if>> <</button>> </div> <<else>> <div class="empty-text" style="text-align: center; margin-top: 50px;"> <div style="font-size: 3rem; opacity: 0.3; margin-bottom: 15px;">📖</div> 请先在左侧选择要研读的物品。 </div> <</if>> </div> </div> <</do>> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">CONCEPT DECODING</h1> <div class="zh">概念解构台</div> </div> <div class="sys-back-btn menu-item" data-target="研习_主界面"> < RETURN </div> </div> <<concept_decoding_board>>
<<set _noteTab to _noteTab || "recipes">> <<set _selectedEntry to _selectedEntry || null>> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">ALCHEMY NOTES</h1> <div class="zh">炼金笔记与物质溯源</div> </div> <div class="sys-back-btn menu-item" data-target="研习_主界面"> < RETURN </div> </div> <div class="notes-layout fade-in-down"> <<do>> <div class="notes-inner-wrap"> <div class="notes-sidebar"> <div class="notes-tabs"> <<button "配方蓝图">><<set _noteTab to "recipes">><<set _selectedEntry to null>><<redo>><</button>> <<button "物质图鉴">><<set _noteTab to "materials">><<set _selectedEntry to null>><<redo>><</button>> </div> <div class="notes-list"> <<if _noteTab === "recipes">> <<set _allRecipes to Object.keys(window.RecipeDatabase)>> <<for _i, _rId range _allRecipes>> <<capture _rId>> <<set _rcp to window.RecipeDatabase[_rId]>> <<set _isKnown to ($recipes[_rId] !== undefined)>> <<set _linkName to _isKnown ? _rcp.name : "未知配方">> <div @class="'list-item ' + (_selectedEntry === _rId ? 'active' : '') + (_isKnown ? '' : ' unknown')"> <<link _linkName>><<set _selectedEntry to _rId>><<redo>><</link>> </div> <</capture>> <</for>> <<else>> <<set _knownItems to setup.getKnownItemIds($inventory)>> <<if _knownItems.length === 0>> <div class="text-muted" style="padding: 20px; text-align: center; font-size: 0.85rem;">行囊空空,无物可考。</div> <<else>> <<for _i, _itemId range _knownItems>> <<capture _itemId>> <<set _item to window.ItemDatabase[_itemId]>> <div @class="'list-item ' + (_selectedEntry === _itemId ? 'active' : '')"> <<link _item.name>><<set _selectedEntry to _itemId>><<redo>><</link>> </div> <</capture>> <</for>> <</if>> <</if>> </div> </div> <div class="notes-detail"> <<if _selectedEntry === null>> <div class="empty-state"> <div class="e-icon">🗂️</div> <div class="e-text">请在左侧选择卷宗进行查阅。</div> </div> <<else>> <<if _noteTab === "recipes">> <<set _rcp to window.RecipeDatabase[_selectedEntry]>> <<set _isKnown to ($recipes[_selectedEntry] !== undefined)>> <<if _isKnown>> <div class="detail-header"> <h2 class="d-title"><<print _rcp.name>></h2> <div class="d-meta"> <span>难度: <<print _rcp.difficulty>></span> <span>最终工序: <<print window.ProcessDatabase[_rcp.final_process].name>></span> </div> </div> <div class="detail-body"> <div class="d-section"> <h4 class="s-title">卷宗描述</h4> <p class="s-text"><<print _rcp.desc>></p> </div> <div class="d-section"> <h4 class="s-title">物质构成法则</h4> <ul class="s-list"> <<for _i, _ing range _rcp.ingredients>> <li> <span class="highlight-purple">[<<print _ing.tags.join("] [")>>]</span> <<if _ing.traits>> <<set _tList to []>><<for _k, _v range _ing.traits>><<run _tList.push(_v)>><</for>> <span class="text-muted">(<<print _tList.join(", ")>>)</span> <</if>> <span style="float:right;"><<print _ing.amount>><<print _ing.unit>></span> </li> <</for>> </ul> </div> </div> <<else>> <div class="detail-header"><h2 class="d-title text-muted">未知配方</h2></div> <div class="detail-body"> <p class="text-muted">你尚未在实践中掌握此配方的结构,或未获得相关图纸。</p> <p class="text-muted" style="font-size: 0.85rem; margin-top: 10px;">/* 提示:部分高级配方需要通过【概念解构台】破译残篇后方可解锁。 */</p> </div> <</if>> <<else>> <<set _item to window.ItemDatabase[_selectedEntry]>> <<if $notes.items[_selectedEntry] === undefined>><<set $notes.items[_selectedEntry] to []>><</if>> <<set _noteList to $notes.items[_selectedEntry]>> <<set _newNoteText to "">> <div class="detail-header"> <h2 class="d-title"><<print _item.name>></h2> <div class="d-meta"> <span>基础形态: <<print _item.default_form>></span> <span>类型: <<print _item.type === "material" ? "素材" : "消耗品">></span> </div> </div> <div class="detail-body"> <div class="d-section"> <h4 class="s-title">神秘学标签 (Tags)</h4> <div class="tag-cloud"> <<for _i, _tag range _item.tags>><span class="tag-item"><<print _tag>></span><</for>> </div> </div> <div class="d-section"> <h4 class="s-title">观测记录</h4> <p class="s-text"><<print setup.Material.getDesc(_selectedEntry, {form: _item.default_form})>></p> </div> <div class="d-section"> <h4 class="s-title">私人笔记</h4> <div class="note-entries-list"> <<if _noteList.length === 0>> <div class="text-muted" style="font-style: italic; font-size: 0.85rem; margin-bottom: 15px;">暂无任何笔记记录。</div> <<else>> <<for _idx, _note range _noteList>> <<capture _idx>> <div class="note-entry-item"> <div class="n-text"><<print _note>></div> <div class="n-action"> <<button "×">><<run $notes.items[_selectedEntry].deleteAt(_idx)>><<redo>><</button>> </div> </div> <</capture>> <</for>> <</if>> </div> <div class="personal-note-area"> <<textarea "_newNoteText" "">> <div class="note-actions"> <<button "新增笔记">> <<if _newNoteText.trim() !== "">> <<run $notes.items[_selectedEntry].push(_newNoteText.trim())>> <<set _newNoteText to "">> <<redo>> <<else>> <<run GameUI.Toast.show("笔记内容不能为空。", "warn")>> <</if>> <</button>> </div> </div> </div> </div> <</if>> <</if>> </div> </div> <</do>> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">OCCULT EXAM</h1> <div class="zh">学科校验</div> </div> <div class="sys-back-btn menu-item" data-target="研习_主界面"> < RETURN </div> </div> <div class="study-layout fade-in-down" style="padding: 20px;"> <h2 style="color: var(--color-text-primary); font-family: var(--font-title);">秘氛评级突破</h2> <p class="text-muted">消耗盈余点数,将学科等级从 B 提升至 E。</p> <!-- TODO: 学科校验 UI 待开发 --> </div>
<<set _selectedLore to _selectedLore || "alchemy_elements">> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">LORE & ARCHIVES</h1> <div class="zh">智识殿堂</div> </div> <div class="sys-back-btn menu-item" data-target="研习_主界面"> < RETURN </div> </div> <div class="notes-layout fade-in-down"> <<do>> <div class="notes-inner-wrap"> <div class="notes-sidebar"> <div class="notes-tabs"> <button style="cursor: default; color: var(--color-text-primary);">世界观档案</button> </div> <div class="notes-list"> <<set _allLores to Object.keys(setup.Lore)>> <<for _i, _loreId range _allLores>> <<capture _loreId>> <<set _lore to setup.Lore[_loreId]>> <div @class="'list-item ' + (_selectedLore === _loreId ? 'active' : '')"> <<link _lore.title>><<set _selectedLore to _loreId>><<redo>><</link>> </div> <</capture>> <</for>> </div> </div> <div class="notes-detail"> <<if _selectedLore === null>> <div class="empty-state"> <div class="e-icon">📜</div> <div class="e-text">请在左侧选择档案进行查阅。</div> </div> <<else>> <<set _activeLore to setup.Lore[_selectedLore]>> <div class="detail-header"> <h2 class="d-title"><<print _activeLore.title>></h2> <div class="d-meta"> <span>分类: <<print _activeLore.category>></span> </div> </div> <div class="detail-body lore-content"> <<print _activeLore.content.replace(/[\r\n]\s*/g, "")>> </div> <</if>> </div> </div> <</do>> </div>
<<set _selectedRelic to _selectedRelic || "mishi_heart">> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">FALSE & RELICS</h1> <div class="zh">非棺典藏</div> </div> <div class="sys-back-btn menu-item" data-target="研习_主界面"> < RETURN </div> </div> <div class="relics-layout fade-in-down"> <<do>> <div class="relics-inner-wrap"> <div class="relics-cabinet"> <div class="cabinet-header"> <span class="en">EXHIBITION</span> <span class="zh">陈列柜</span> </div> <div class="cabinet-grid"> <<set _allRelics to Object.keys(setup.Relics)>> <<for _i to 0; _i lt 9; _i++>> <<if _i < _allRelics.length>> <<set _rId to _allRelics[_i]>> /* 修复:必须 capture _rId,否则 link 永远指向最后一个 */ <<capture _rId>> <<set _relicDef to setup.Relics[_rId]>> <<set _invRelic to $inventory.relics[_rId]>> <<set _isOwned to (_invRelic !== undefined)>> <<set _isDecoded to (_isOwned && _invRelic.isDecoded)>> <div @class="'relic-slot ' + (_isOwned ? (_isDecoded ? 'owned' : 'corrupted') : 'locked') + (_selectedRelic === _rId ? ' active' : '')"> <<if _isOwned>> <<link "">><<set _selectedRelic to _rId>><<redo>><</link>> <<if _isDecoded>> <div class="r-icon"><<print _relicDef.icon>></div> <div class="r-name"><<print _relicDef.name>></div> <<else>> <div class="r-icon text-muted" style="filter: blur(3px); opacity: 0.5;">?</div> <div class="r-name text-muted" style="color: var(--color-error);">未知的非棺</div> <</if>> <<else>> <div class="r-icon text-muted" style="opacity: 0.2;">?</div> <div class="r-name text-muted" style="opacity: 0.2;">空置</div> <</if>> </div> <</capture>> <<else>> <div class="relic-slot empty"></div> <</if>> <</for>> </div> </div> <div class="relics-detail"> <div class="concept-quote"> <div class="q-mark">“</div> <p>“丰”为碑,“非”为棺。<span class="en">Fullen & False.</span></p> <p>丰在中间切开后便是非的字形。无法成为丰碑的物品,即被称为非棺。</p> </div> <<if _selectedRelic>> <<set _activeRelic to setup.Relics[_selectedRelic]>> <<set _invRelic to $inventory.relics[_selectedRelic]>> <<set _isOwned to (_invRelic !== undefined)>> <<set _isDecoded to (_isOwned && _invRelic.isDecoded)>> <<if _isOwned>> <<if _isDecoded>> <div class="detail-content fade-in"> <div class="d-icon-large"><<print _activeRelic.icon>></div> <h2 class="d-title"><<print _activeRelic.name>></h2> /* 已移除 title 渲染 */ <div class="d-divider"></div> <div class="d-desc"><<print _activeRelic.desc>></div> </div> <<else>> <div class="detail-content empty-state"> <div class="e-icon" style="filter: blur(5px); opacity: 0.5;">🪦</div> <div class="e-text" style="color: var(--color-error); letter-spacing: 4px;">CONCEPT_CORRUPTED</div> <div style="margin-top: 15px; font-size: 0.9rem; color: var(--color-text-muted);">这件非棺的概念尚未锚定。<br>请前往【概念解构台】进行破译。</div> </div> <</if>> <<else>> <div class="detail-content empty-state"> <div class="e-icon" style="opacity: 0.2;">🪦</div> <div class="e-text">此展台空置。你尚未获得该非棺。</div> </div> <</if>> <<else>> <div class="detail-content empty-state"> <div class="e-icon" style="opacity: 0.2;">🪦</div> <div class="e-text">凝视展柜,选择一件非棺。</div> </div> <</if>> </div> </div> <</do>> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">MEDITATION</h1> <div class="zh">冥想</div> </div> <div class="sys-back-btn menu-item" data-target="研习_主界面"> < RETURN </div> </div> <div class="study-layout fade-in-down" style="padding: 20px;"> <h2 style="color: var(--color-text-primary); font-family: var(--font-title);">平息理智</h2> <p class="text-muted">消耗时间降低压力,并微量提升预言技能经验。</p> <!-- TODO: 冥想 UI 待开发 --> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">SWAMPOLOGY</h1> <div class="zh">沼泽学</div> </div> <div class="sys-back-btn menu-item" data-target="研习_主界面"> < RETURN </div> </div> <div class="study-layout fade-in-down" style="padding: 20px;"> <h2 style="color: var(--color-accent-purple); font-family: var(--font-title);">禁忌的深渊</h2> <p class="text-muted">你已经触碰到了成为魔女的边缘……</p> <!-- TODO: 沼泽学 UI 待开发 --> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">KNOWN ENTITIES</h1> <div class="zh">已知实体名录</div> </div> <div class="sys-back-btn menu-item" data-target="研习_主界面"> < RETURN </div> </div> <div class="npc-roster-layout fade-in-down"> <div class="npc-card-grid"> <<set _hasMetAnyone to false>> <<for _npcId, _npcData range $npcs>> <<if _npcData.isMet>> <<set _hasMetAnyone to true>> <<capture _npcId>> <<set _npcStatic to setup.NPCs[_npcId]>> <div class="npc-card"> <<link "">> <<set $tempSelectedNpc to _npcId>> <<run Engine.play("角色档案_详情")>> <</link>> <div class="npc-card-portrait"> <div class="portrait-bg-pattern"></div> <div class="portrait-placeholder">PORTRAIT</div> </div> <div class="npc-card-info"> <div class="c-faction"><<print _npcStatic.faction || "未知势力">></div> <div class="c-name"><<print _npcStatic.name>></div> <div class="c-en"><<print _npcStatic.en_name>></div> <div class="c-concept"><<print _npcStatic.concept_tag>></div> </div> </div> <</capture>> <</if>> <</for>> <<if !_hasMetAnyone>> <div class="empty-state" style="grid-column: 1 / -1; height: 50vh;"> <div class="e-icon">📇</div> <div class="e-text">联络簿中暂无记录。</div> </div> <</if>> </div> </div>
<<set _npcId to $tempSelectedNpc>> <<set _npcStatic to setup.NPCs[_npcId]>> <<set _npcDynamic to $npcs[_npcId]>> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">CONFIDENTIAL FILE</h1> <div class="zh">机密观测档案</div> </div> <div class="sys-back-btn menu-item" data-target="研习_人际档案"> < RETURN </div> </div> <div class="npc-detail-layout fade-in-down"> <div class="detail-paper"> <div class="detail-header" style="text-align: center; border-bottom: 1px solid var(--color-border-subtle); padding-bottom: 30px; margin-bottom: 40px;"> <div class="d-en-title" style="font-family: var(--font-en); font-size: 1.5rem; color: var(--color-text-muted); letter-spacing: 4px; margin-bottom: 10px; text-transform: uppercase;"> <<print _npcStatic.en_name>> </div> <h2 class="d-title" style="margin: 0 0 15px 0; font-family: var(--font-title); font-size: 3rem; color: var(--color-text-primary); letter-spacing: 4px;"> <<print _npcStatic.name>> </h2> <div class="d-meta" style="display: flex; justify-content: center; gap: 30px; font-size: 0.95rem; color: var(--color-accent-purple); font-family: var(--font-zh);"> <span>[ 真名: <<print _npcStatic.real_name || "未知">> ]</span> <span>[ 概念: <<print _npcStatic.concept_tag>> ]</span> </div> </div> <div class="detail-body"> <div class="d-section"> <h4 class="s-title">态度观测 <span class="en" style="font-size:0.8rem; color:var(--color-text-muted);">ATTITUDE OBSERVATION</span></h4> <<set _eyeRelic to $inventory.relics["eye_of_shemit"]>> <<set _hasEye to (_eyeRelic !== undefined && _eyeRelic.isDecoded === true)>> <div class="npc-stats-panel"> <<if _hasEye>> <div class="stat-notice success">[ 视界已展开 ] 歇密特之眼看穿了表象,目标的心理维度已完全解析。</div> <<set _attMap to [ { key: "inf", name: "情报倾向", desc: "独享 ↔ 共享" }, { key: "thr", name: "威胁评估", desc: "无害 ↔ 高危" }, { key: "val", name: "价值评估", desc: "负担 ↔ 瑰宝" }, { key: "res", name: "理念共振", desc: "相悖 ↔ 共鸣" }, { key: "cos", name: "交互成本", desc: "麻烦 ↔ 便利" } ]>> <div class="stat-bars"> <<for _i, _att range _attMap>> <<set _val to _npcDynamic.attitudes[_att.key]>> <<set _percent to Math.abs(_val) * 10>> <<set _isPositive to _val >= 0>> <div class="stat-row"> <div class="s-label"><span class="zh"><<print _att.name>></span><span class="en"><<print _att.key.toUpperCase()>></span></div> <div class="s-bar-container"> <div class="s-bar-center-line"></div> <div @class="'s-bar-fill ' + (_isPositive ? 'positive' : 'negative')" @style="'width: ' + _percent + '%; ' + (_isPositive ? 'left: 50%;' : 'right: 50%;')"></div> </div> <div class="s-value"><<print _val > 0 ? "+" + _val : _val>></div> </div> <</for>> </div> <div class="stat-weights"> <span style="color:var(--color-text-secondary);">行为权重序列:</span> <span class="highlight-gold"><<print _npcStatic.weights.map(w => w.toUpperCase()).join(" ➔ ")>></span> </div> <<else>> <div class="stat-obfuscated"><div class="glitch-text">INF: ??? | THR: ??? | VAL: ??? | RES: ??? | COS: ???</div></div> <</if>> </div> </div> <div class="d-section"> <h4 class="s-title">接触记录</h4> <div class="npc-reception-text"> <<set _stageKey to "stage_" + (_npcDynamic.loreStage || 1)>> <<print _npcStatic.reception[_stageKey]>> </div> </div> <div class="d-section"> <h4 class="s-title">已知概念 <span class="en" style="font-size:0.8rem; color:var(--color-text-muted);">KNOWN CONCEPTS</span></h4> <div class="tag-cloud"> <<for _i, _kw range _npcStatic.keywords>> <<if _npcDynamic.unlockedKeywords.includes(_kw)>> <span class="tag-item" style="border-color: var(--color-accent-gold); color: var(--color-accent-gold);"><<print _kw>></span> <<else>> <span class="tag-item" style="opacity: 0.3; border-style: dashed;">???</span> <</if>> <</for>> </div> </div> <div class="d-section"> <h4 class="s-title">深度档案 <span class="en" style="font-size:0.8rem; color:var(--color-text-muted);">INTEL FRAGMENTS</span></h4> <div class="npc-archives"> <<set _arcKeys to Object.keys(_npcStatic.archives)>> <<for _i, _key range _arcKeys>> <<set _arcData to _npcStatic.archives[_key]>> <<set _isUnlocked to _npcDynamic.unlockedArchives.includes(_key)>> <div @class="'arc-block ' + (_isUnlocked ? '' : 'locked')"> <<if _isUnlocked>> <div class="arc-title">■ <<print _arcData.title>></div> <div class="arc-content"><<print _arcData.text>></div> <<else>> <div class="arc-title text-muted">■ [ 档案加密 ]</div> <div class="arc-content text-muted" style="opacity: 0.5; font-family: var(--font-en); letter-spacing: 2px;">DATA_CORRUPTED_OR_UNAVAILABLE...</div> <</if>> </div> <</for>> </div> </div> </div> </div> </div>
<div id="start-screen" class="fade-in-text"> <!-- 左侧:标题与档案信息 (已剥离迭代记录,增加大量留白) --> <div class="start-left-col"> <div class="series-badge">PROJECT [ VOLONGOTO - 02 ]</div> <div class="title-block"> <h1 class="title-en">NOMANTIA<br><span class="title-en-sub">MAJYOSIS</span></h1> <h2 class="title-zh">巫疍学:魔女的密契</h2> </div> <div class="intro-block"> <p>魔女,即便是在影界,这个称呼也仅用于指代那些最为离经叛道的女士。</p> <p>而你,是一个想成为魔女的恶魔。</p> <div class="warning-box"> <span class="warning-label">[ WARNING ]</span> 本游戏包含成人要素、暗黑奇幻、认知污染及道德争议内容。未成年人请勿游玩。 </div> </div> </div> <!-- 右侧:交互菜单 (全部改为 data-target 全屏跳转) --> <div class="start-right-col"> <div class="menu-list"> <div class="menu-item" data-target="创建角色_开场剧情"> <span class="menu-zh">签订新约</span><span class="menu-en">NEW PACT</span> </div> <div class="menu-item" data-target="Debug_快速测试通道"> <span class="menu-zh">幕后通道</span><span class="menu-en">QUICK START</span> </div> <div class="menu-item" data-target="读取存档"> <span class="menu-zh">履行旧约</span><span class="menu-en">LOAD PACT</span> </div> <div class="menu-item" data-target="答案之书"> <span class="menu-zh">答案之书</span><span class="menu-en">ENDINGS</span> </div> <div class="menu-item" data-target="游戏图鉴"> <span class="menu-zh">乐园宣传单</span><span class="menu-en">GALLERY</span> </div> <div class="menu-item" data-target="游戏设置"> <span class="menu-zh">校准纺车</span><span class="menu-en">SETTINGS</span> </div> <div class="menu-item" data-target="开发日记"> <span class="menu-zh">迭代记录</span><span class="menu-en">SYS.LOG</span> </div> <div class="menu-item" data-target="制作组"> <span class="menu-zh">斯克茵的线轴</span><span class="menu-en">CREDITS</span> </div> </div> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">LOAD PACT</h1> <div class="zh">履行旧约</div> </div> <div class="sys-back-btn menu-item" data-target="标题界面"> < RETURN </div> </div> <!-- 传入 loadOnly 参数,隐藏存档按钮 --> <<savesgrid "loadOnly">>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">SETTINGS</h1> <div class="zh">校准纺车</div> </div> <div class="sys-back-btn menu-item" data-target="标题界面"> < RETURN </div> </div> <div class="sys-settings-container" style="max-width: 600px;"> <div class="setting-row"> <div class="setting-label"> <span class="zh">纺车轰鸣</span><span class="en">VOLUME</span> </div> <div class="setting-control"> <input type="range" id="set-volume" min="0" max="1" step="0.1" value="1"> <span id="val-volume" class="val-display">100%</span> </div> </div> <div class="setting-row"> <div class="setting-label"> <span class="zh">墨迹流速</span><span class="en">TEXT SPEED</span> </div> <div class="setting-control"> <input type="range" id="set-speed" min="10" max="100" step="10" value="50"> <span id="val-speed" class="val-display">50ms</span> </div> </div> <div class="setting-row"> <div class="setting-label"> <span class="zh">视界焦距</span><span class="en">TEXT SIZE</span> </div> <div class="setting-control btn-group"> <button class="sys-btn size-btn" data-size="small">微缩</button> <button class="sys-btn size-btn active" data-size="normal">寻常</button> <button class="sys-btn size-btn" data-size="large">宏大</button> </div> </div> <div class="setting-row"> <div class="setting-label"> <span class="zh">环境光照</span><span class="en">MODE</span> </div> <div class="setting-control btn-group" style="display: flex; gap: 0.5rem; flex-wrap: wrap; justify-content: flex-end;"> <button class="sys-btn mode-btn" data-mode="dark">深邃</button> <button class="sys-btn mode-btn" data-mode="light">白昼</button> </div> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">SYS.LOG</h1> <div class="zh">迭代记录</div> </div> <div class="sys-back-btn menu-item" data-target="标题界面"> < RETURN </div> </div> <div class="dev-notes-block" style="font-size: 1rem; line-height: 2; padding: 20px;"> <ul class="dev-list"> <li><span class="highlight-yellow" style="color: var(--color-accent-gold); font-weight: bold;">目前更新:</span> <ul style="margin-top: 5px; margin-bottom: 15px; color: var(--color-text-secondary);"> <li><b>学究闭环实装:</b>彻底打通了“获取残篇 ➔ 概念解构(调频) ➔ 图鉴归档 ➔ 研读吸收”的暗黑学术体验链路。</li> <li><b>数据架构重构:</b>实现“机制与文本分离”,解构台坐标与图鉴文本解耦,彻底消灭数据冗余与 window 污染。</li> <li><b>工坊自动化升级:</b>新增【录入原型】功能,玩家可消耗 AP 将私人炼金配方授权给人偶进行流水线量产。</li> <li><b>研习系统补全:</b>实装【冥想】降压功能与【学科校验】秘氛评级突破功能。</li> </ul> </li> <li><span class="highlight-yellow" style="color: var(--color-accent-gold); font-weight: bold;">后续开发计划:</span> <ul style="margin-top: 5px; color: var(--color-text-secondary);"> <li>推进大地图探索系统 (Explore) 的事件分发与明雷节点渲染。</li> <li>实装 NPC 洽谈系统 (Contacts) 的 12 种策略博弈矩阵。</li> <li>将 NPC 线索板 (Node Map) 的智能引力布局算法接入 UI 渲染。</li> </ul> </li> </ul> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">ENDINGS</h1> <div class="zh">答案之书</div> </div> <div class="sys-back-btn menu-item" data-target="标题界面"> < RETURN </div> </div> <p style="color: var(--color-text-secondary);">[ 数据缺失:尚未解锁任何结局 ]</p>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">GALLERY</h1> <div class="zh">乐园宣传单</div> </div> <div class="sys-back-btn menu-item" data-target="标题界面"> < RETURN </div> </div> <p style="color: var(--color-text-secondary);">[ 数据缺失:画廊模块构建中 ]</p>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">CREDITS</h1> <div class="zh">斯克茵的线轴</div> </div> <div class="sys-back-btn menu-item" data-target="标题界面"> < RETURN </div> </div> <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 50vh; text-align: center;"> <div style="font-family: var(--font-en); color: var(--color-text-secondary); letter-spacing: 4px; margin-bottom: 4rem; font-size: 0.9rem;"> PROJECT [ VOLONGOTO - 02 ] </div> <div style="margin-bottom: 3rem;"> <div style="font-family: var(--font-en); color: var(--color-accent-purple); font-size: 0.85rem; letter-spacing: 3px; margin-bottom: 0.8rem;"> DIRECTOR / LEAD DEVELOPER </div> <div style="font-size: 1.8rem; color: var(--color-accent-gold); letter-spacing: 6px; font-weight: 300; text-shadow: var(--shadow-glow-gold);"> 水母菲士 JELLY[FISH] </div> </div> <!-- 预留位置:后续如果有美术、音乐或其他协助者,可以继续往下加 --> <div style="margin-bottom: 3rem;"> <div style="font-family: var(--font-en); color: var(--color-text-muted); font-size: 0.85rem; letter-spacing: 3px; margin-bottom: 0.8rem;"> SYSTEM ARCHITECTURE & UI </div> <div style="font-size: 1.2rem; color: var(--color-text-secondary); letter-spacing: 4px; font-weight: 300;"> AI Assistant </div> </div> </div>
<<scene>> <<line>>没想到,经历过那样的事情,你还能保持自我啊。 <<line>>即便询问你还记不记得自己的名字,恐怕也没有什么意义。 <<line>>毕竟知晓你真名的人已经全部都不存在了吧? <<line>>不过,姑且还是问一下。 <<controls>> <<button "继续">><<goto "创建角色_输入名字">><</button>> <</scene>>
<<scene>> <<line>>你还记得自己的真名吗? <<controls>> <<textbox "$player.name" $player.name autofocus>> <<button "确认名字">> <<set $player.name to $player.name.trim()>> <<if $player.name is "">> <<goto "创建角色_忘记名字">> <<else>> <<goto "创建角色_路线剧情">> <</if>> <</button>> <</scene>>
<<scene>> <<line>>忘记了?现在为自己起一个名字吧。 <<controls>> <<button "返回修改">><<goto "创建角色_输入名字">><</button>> <</scene>>
<<scene>> <<line>>你是真的记得自己的名字,还是重新起了一个? <<line>>都无所谓,只要你能明确自我的存在就好。 <<line>>名字、代号、外貌,都并非亘古不变之物。 <<line>>想必这一点你早就了然了。 <<controls>> <<button "继续">><<goto "创建角色_路线选择">><</button>> <</scene>>
<<scene>> <<line>>现在的你,姑且能看清面前的自己吗? <<controls>> <div style="display: flex; gap: 1rem;"> <<button "失却的人像">> <<set $meta.ccStep to "quick">> <<goto "创建角色_过渡_初诞">> <</button>> <<button "形形绰绰">> <<set $meta.ccStep to "tag">> <<goto "创建角色_过渡_标签">> <</button>> <<button "诚实的倒影">> <<set $meta.ccStep to "custom">> <<goto "创建角色_过渡_密契">> <</button>> </div> <<button "返回修改名字">><<goto "创建角色_输入名字">><</button>> <</scene>>
<<scene>> <<line>>别担心,这也只是无伤大雅的小事而已。 <<line>>在宏观上,大象和蚂蚁的差别其实并不大。 <<controls>> <<button "接受此形" "创建角色_捏人面板_初诞">><<addclass ".macro-button" "btn-primary">><</button>> <<button "返回重新选择" "创建角色_路线选择">><</button>> <</scene>>
<<scene>> <<line>>至少你还有回去的地方,就不用担心迷失道路。 <<line>>姑且依照你的渴望来塑造自我吧。 <<controls>> <!-- 标签选择网格 --> <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1.5rem;"> <<button "魔鬼">><<set $meta.selectedTag to "魔鬼">><<goto "创建角色_捏人面板_标签">><</button>> <<button "兽">><<set $meta.selectedTag to "兽">><<goto "创建角色_捏人面板_标签">><</button>> <<button "海妖">><<set $meta.selectedTag to "海妖">><<goto "创建角色_捏人面板_标签">><</button>> <<button "类天使">><<set $meta.selectedTag to "类天使">><<goto "创建角色_捏人面板_标签">><</button>> <<button "树化人">><<set $meta.selectedTag to "树化人">><<goto "创建角色_捏人面板_标签">><</button>> <<button "牲">><<set $meta.selectedTag to "牲">><<goto "创建角色_捏人面板_标签">><</button>> <<button "冠奴">><<set $meta.selectedTag to "冠奴">><<goto "创建角色_捏人面板_标签">><</button>> <<button "铸物">><<set $meta.selectedTag to "铸物">><<goto "创建角色_捏人面板_标签">><</button>> </div> <<button "返回重新选择" "创建角色_路线选择">><</button>> <</scene>>
<<scene>> <<line>>看来你还记得自己曾经的这幅摸样啊。 <<line>>恐怕影界的魔族们,会认为你依然是原本的自己吧。 <<controls>> <<button "审视倒影" "创建角色_捏人面板_密契">><<addclass ".macro-button" "btn-primary">><</button>> <<button "返回重新选择" "创建角色_路线选择">><</button>> <</scene>>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">APPEARANCE: QUICK</h1> <div class="zh">初诞之形</div> </div> </div> <<cc_panel "quick" "">>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">APPEARANCE: TAGS</h1> <div class="zh">尘世标签</div> </div> </div> <!-- 动态读取玩家刚才选择的标签 --> <<cc_panel "tag" $meta.selectedTag>>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">APPEARANCE: CUSTOM</h1> <div class="zh">密契匠造</div> </div> </div> <<cc_panel "custom" "">>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">SOUL SCALE</h1> <div class="zh">灵魂刻度</div> </div> <!-- 返回按钮 --> <div class="sys-back-btn menu-item" data-target="创建角色_路线选择"> < RETURN </div> </div> <<stats_panel>> <div style="text-align:center; margin-top: 2rem; display: flex; gap: 1rem; justify-content: center;"> <<button "返回重塑肉体" "创建角色_路线选择">><</button>> <<button "确认灵魂刻度" "创建角色_终局苏醒">><<addclass ".macro-button" "btn-primary">><</button>> </div>
<<scene>> <<line>>恭喜,$player.name,看来你已经彻底找回了自己。 <<line>>也许下一次,你就没有这么幸运了。 <<line>>在抵达终局之前,我们还会再见面的…… <<controls>> <<button "苏醒" "导入_工坊创建">><<addclass ".macro-button" "btn-primary">><</button>> <</scene>>
<div class="static-scene fade-in-down"> <div class="static-text"> <p>醒来时,你感到一阵剧烈的头痛,看来睡得太死并不是一个好习惯。</p> <p>即便如此你仍然必须尽快离开那张老旧的小床。树影相会的信使会在一个睡眠日的早晨将协约文件递送到你的工坊来。</p> <p>父母双亡使得你拥有一间独立的小民宅,对于一个人来说显得有些空旷,不过所幸你为自己制作了一个炼金人偶来替你管理生活起居和工坊的通常运作。</p> <p>当递送文件的信使抵达你的家门时,你看到他带着一个小巧的飞羽帽,帽檐正好能遮住大半张脸,但哪怕他不将帽檐压得那么低、你也无法看清他的长相。</p> <p>他飞快的撇向大门前的楼号:“这份文件需要本人签收,女士,请在这里写下您的称号和收件工坊的名字。”</p> </div> <div class="controls-box"> <div style="display:flex; flex-direction:column; gap:1rem; align-items:flex-end;"> <div><span style="color:var(--color-text-secondary); margin-right:1rem; letter-spacing:2px;">对外称号</span><<textbox "$player.title" $player.title autofocus>></div> <!-- 修正变量路径 --> <div><span style="color:var(--color-text-secondary); margin-right:1rem; letter-spacing:2px;">工坊名称</span><<textbox "$management.workshop.name" $management.workshop.name>></div> </div> <div id="warning-msg" class="warning-msg-box"></div> <<button "确认签名">> <<set $player.title to $player.title.trim()>> <!-- 修正变量路径 --> <<set $management.workshop.name to $management.workshop.name.trim()>> <<if $player.title is "" or $management.workshop.name is "">> <<replace "#warning-msg">> <div class="fade-in-down" style="color: var(--color-error);"> “女士,我不能将一份没有签名的文件交出去,这会让我丢掉工作。”<br> <span style="font-size:0.9rem; color:var(--color-text-secondary);">信使警惕地看着你,他的下肢并非寻常魔族的模样,如果他跑走,恐怕你追不上他。</span> </div> <</replace>> <<else>> <<goto "导入_工坊创建_完成">> <</if>> <</button>> </div> </div>
<div class="static-scene fade-in-down"> <div class="static-text"> <p>“当然。”看见你准确签下自己的称号,他松一口气,将手中的文书重新卷好交给你,“您需要收好这份文件,如有损坏或者丢失,请在三个睡眠日内亲往当地的树影相会进行补办,逾期不候。”</p> <p>这些内容,他说起来有些磕磕绊绊、不甚熟练。本地树影相会已经很久没有收到过工坊的申请,魔药学、炼金术,在你上学时就已经是几乎无人问津的学科——难道说现在的魔族们更喜欢魔像或者人偶?</p> <p>可对于当下的你来说,制作炼金人偶仍是相当耗神的技术,哪怕再有一份材料和机会,你恐怕也更倾向于给自己再制作一个助手,而不是售卖。</p> <p>你收好那份重要的协约文件,关上了小院的大门,返回你位于住宅地下的工坊之中。</p> </div> <div class="controls-box" style="margin-top: 2rem;"> <<button "进入地下工坊">><<goto "导入_人偶创建">><</button>> </div> </div>
<div class="static-scene fade-in-down"> <div class="static-text"> <p>当你走入地下的工坊,炼金人偶已经清理好炼金台和桌案,一边供你学习和研发新的炼金物品、一边则是用以处理工坊的安排等文书事务。</p> <p>炼金人偶和你有着七八分相似的长相,因为关节的制作问题,她比你略高一些,因此在你身边时肢体稍显怪异和不协调,她对此显然毫不介意。</p> <p>不过现在的问题是,你并不打算所有事务都亲力亲为,不仅是生产线的管理,采购和售卖等对外的活动你也需要交给她完成。</p> <p>曾经在这个家只有你们两人时,无论你怎么称呼她,她都可以精准知道名称指代的对象,但今时不同往日,如果炼金人偶需要出门活动,她就必须得有一个名字,或者说、代号。</p> <p>她微笑着等待你为她取名。你打算称呼她为:</p> </div> <div class="controls-box"> <div style="margin-bottom: 0.5rem;"> <span style="color:var(--color-text-secondary); margin-right:1rem; letter-spacing:2px;">人偶代号</span> <<textbox "$management.doll.name" $management.doll.name autofocus>> </div> <div id="warning-msg" class="warning-msg-box"></div> <<button "确认命名">> <<set $management.doll.name to $management.doll.name.trim()>> <<if $management.doll.name is "">> <<replace "#warning-msg">> <div class="fade-in-down" style="color: var(--color-accent-purple);"> “主人。”她说,“对于其他魔族而言,自我以外的客体显然需要一个可称呼的方式。”<br> <span style="font-size:0.9rem; color:var(--color-text-secondary);">看来你还是得给她起一个名字。</span> </div> <</replace>> <<else>> <<goto "导入_教学_工坊安排">> <</if>> <</button>> </div> </div>
<div class="static-scene fade-in-down"> <div class="static-text"> <p style="color: var(--color-accent-gold);">“我很喜欢这个名字,主人。”</p> <p>这是一句预先决定好的话,你当然很清楚:炼金人偶的声带无法完整模拟自然生物的发声习惯,这有可能是你技艺不精的缺陷,无论如何,她的话语中没有感情,或者是她本来就没有这样的自我意识。</p> <p>但这样的设置让她可以更好地协助你经营你的工坊,现在,你需要在她的帮忙下开始了解如何安排所有的工作。</p> <hr style="border: 0; border-bottom: 1px dashed var(--color-border-subtle); margin: 2rem 0;"> <p style="color: var(--color-text-secondary);"><strong>[ <<print $management.doll.name>> ]</strong></p> <p>我无意怀疑您的智慧与学识,不过考虑到这时您第一次经营工坊,我的主人。</p> <p>您需要复习一下我们经营工坊的方式与开发产品的流程吗?</p> <p>我已经为您整理出两个合适的订单作为基础入门,您可以尝试选择接取并排序,这些订单在取消时并不会扣取您的信用与保证金。</p> <p>请您来尝试一下安排工坊的工作吧。</p> </div> <div class="controls-box" style="margin-top: 2rem; display: flex; gap: 20px; justify-content: center;"> <<button "尝试安排工坊工作 (进入新手引导)">> /* 1. 仅注入教学订单,材料已在 StoryInit 中配置 */ <<run $management.workshop.orders.available = [ { id: "tut_1", recipeId: "rcp_snelling_salt", name: "灵感嗅盐", amount: 50, unit: "g", days: 3, reward: 150, deposit: 30, client: "下城黑市商人", readyToDeliver: false }, { id: "tut_0", recipeId: "rcp_organ_bag_crude", name: "粗制器官保鲜袋", amount: 1, unit: "件", days: 5, reward: 800, deposit: 400, client: "匿名买家", readyToDeliver: false }, ]; $management.workshop.orders.active = []; >> <<set $meta.tutorialStep to 1>> <<goto "晨间_工坊规划">> <</button>> <<button "不了,我很清楚 (跳过教学)">> <<set $meta.isStarted to true>> <<run window.WorkshopSystem.generateDailyContent()>> <<goto "晨间_苏醒">> <</button>> </div> </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">WORKSHOP: TUTORIAL</h1> <div class="zh">工坊安排教学</div> </div> </div> <!-- 强行注入教学数据 --> <<run $management.workshop.orders.available = [ { id: "tut_0", recipeId: "rcp_organ_bag_crude", name: "粗制器官保鲜袋", amount: 1, unit: "件", days: 5, reward: 800, deposit: 400, client: "匿名买家", readyToDeliver: false }, { id: "tut_1", recipeId: "rcp_snelling_salt", name: "灵感嗅盐", amount: 50, unit: "g", days: 3, reward: 150, deposit: 30, client: "下城黑市商人", readyToDeliver: false }, { id: "tut_2", recipeId: "rcp_sulfur_cleaner", name: "硫磺清洁剂", amount: 2, unit: "瓶", days: 2, reward: 200, deposit: 50, client: "树影相会", readyToDeliver: false }, { id: "tut_3", recipeId: "rcp_snelling_salt", name: "灵感嗅盐", amount: 30, unit: "g", days: 4, reward: 100, deposit: 20, client: "散客", readyToDeliver: false }, { id: "tut_4", recipeId: "rcp_sulfur_cleaner", name: "硫磺清洁剂", amount: 5, unit: "瓶", days: 5, reward: 450, deposit: 100, client: "上城清洁所", readyToDeliver: false } ]; >> <!-- 调用你真实的 UI 渲染宏 --> <<workshop_panel>>
<!-- ========================================== --> <!-- 1. 强制跳过捏人,设置游戏已开始 --> <!-- ========================================== --> <<set $meta.isStarted = true>> <<set $meta.progress = "init">> <<set $meta.currentRegion = "reg_capital">> <<set $meta.currentZone = "z_lower">> <<set $meta.currentBuilding = "b_home">> <!-- ========================================== --> <!-- 2. 注入测试角色数据 (高属性方便测试) --> <!-- ========================================== --> <<set $player.name = "测试学究">> <<set $player.title = "灰烬观测者">> <<set $player.race = "demon">> <<set $player.stats = { str: 12, con: 14, siz: 13, int: 18, pow: 16, dex: 14, app: 16, luk: 15 }>> <<set $player.derived.apMax = Math.floor(($player.stats.con + $player.stats.siz + $player.stats.pow) / 3)>> <<set $player.derived.currentAp = $player.derived.apMax>> <<set $player.derived.error = Math.max(2, Math.min(5, Math.ceil(Math.abs($player.stats.pow - $player.stats.int) / 2)))>> <<set $player.derived.res = Math.floor(($player.stats.con + $player.stats.pow) / 2)>> <<set $player.skills.general.eavesdrop.level = 50>> <<set $player.skills.general.rhetoric.level = 50>> <<set $player.occult.nomantia.level = 12>> <<set $player.occult.nomantia.courses = { alchemy: "E", herbology: "E", incantation: "E", phantom: "E" }>> <!-- ========================================== --> <!-- 3. 注入初始资产与工坊数据 --> <!-- ========================================== --> <<set $management.workshop.name = "DEBUG 异常工坊">> <<set $management.workshop.coin = 5000>> <<set $management.workshop.credit = 500>> <<set $management.workshop.debt = 0>> <!-- 【修复】塞入测试材料,使用新版嵌套结构 --> <<set $inventory.warehouse.materials = { "sea_salt": { "标准|晶体|无": { amount: 500, prefix: "标准", form: "晶体", error: "无" } }, "lead": { "标准|块状|无": { amount: 50, prefix: "标准", form: "块状", error: "无" } }, "raw_hide": { "标准|生皮|无": { amount: 20, prefix: "标准", form: "生皮", error: "无" } }, "sulfur": { "标准|块状|无": { amount: 100, prefix: "标准", form: "块状", error: "无" } } }>> <!-- ========================================== --> <!-- 4. 视觉过渡与跳转 --> <!-- ========================================== --> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">SYSTEM OVERRIDE</h1> <div class="zh" style="color: var(--color-error);">测试通道已激活</div> </div> </div> <div class="static-scene fade-in-down"> <div class="static-text" style="text-align: center;"> <span style="color: var(--color-accent-gold); font-size: 1.5rem;">[ 数据注入完毕 ]</span> <br><br> 玩家实体:<<print $player.name>> (AP: <<print $player.derived.apMax>> | Error: <<print $player.derived.error>>)<br> 初始资金:<<print $management.workshop.coin>> 银币<br> 当前位置:<<print setup.MapDatabase[$meta.currentRegion].zones[$meta.currentZone].buildings[$meta.currentBuilding].name>> </div> <div class="controls-box" style="margin-top: 3rem;"> <<button "进入游戏 (工坊)" "工坊_主界面">><</button>> <<button "进入游戏 (探索)" "探索_主界面">><</button>> </div> </div>
<<explore_main_panel>>
<<if setup.ExploreSession == null>><<initExploreSession>><</if>> <<set _region to setup.MapDatabase[$meta.currentRegion]>> <<set _zone to _region.zones[$meta.currentZone]>> <<set _b to _zone.buildings[$meta.currentBuilding]>> <<set _gameData to setup.ExploreSession[_b.id]>> <<set _stateDesc to _b.stateDesc ? _b.stateDesc[_gameData.state] : "当前无法进入该区域。">> <!-- 统一题头:右上角返回大地图 --> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">LOCATION</h1> <div class="zh"><<print _b.name>> <span style="font-size:0.8rem; color:var(--color-text-muted);">(门前)</span></div> </div> </div> <div class="building-interior-layout"> <div class="interior-content"> <div class="detail-desc fade-in-down"> <p class="b-desc" style="margin-bottom: 15px;"><<print _b.desc>></p> <div class="b-status-box" style="padding-top: 15px; border-top: 1px dashed var(--color-border-subtle);"> <span class="state-badge" style="margin-bottom: 10px; display: inline-block;"><<print _gameData.state>></span> <p><<print _stateDesc>></p> </div> </div> <div class="arrival-actions fade-in-down" style="display: flex; gap: 15px; justify-content: center; margin-top: 30px;"> <<if _gameData.state === "开放" or _gameData.state === "封锁">> <<button "推门进入">> <<goto "探索_建筑内部">> <</button>> <<else>> <button disabled style="opacity: 0.5; cursor: not-allowed;">无法进入</button> <</if>> <<button "去别处看看">> <<set $meta.currentBuilding to null>> <<goto "探索_主界面">> <</button>> <<if _b.id === "b_home">> <<button "进入宅邸 (回家)">> <<set $meta.currentBuilding to null>> <<goto "工坊_主界面">> <</button>> <<else>> <<set _homeCost to setup.Explore.calculateTravelCost(_region.x, _region.y, setup.MapDatabase["reg_capital"].x, setup.MapDatabase["reg_capital"].y)>> <<button `"返回工坊 (耗时: " + _homeCost.time + " | AP: " + _homeCost.ap + ")"`>> <<if $player.derived.currentAp < _homeCost.ap>> <<run GameUI.Toast.show("精力不足!", "error")>> <<else>> <<set $player.derived.currentAp -= _homeCost.ap>> <<set $time.timeValue += _homeCost.time>> <<set $meta.currentRegion to "reg_capital">> <<set $meta.currentBuilding to null>> <<run $(document).trigger(":refreshHUD")>> <<goto "工坊_主界面">> <</if>> <</button>> <</if>> </div> </div> </div>
<<if setup.ExploreSession == null>><<initExploreSession>><</if>> <<set _region to setup.MapDatabase[$meta.currentRegion]>> <<set _zone to _region.zones[$meta.currentZone]>> <<set _b to _zone.buildings[$meta.currentBuilding]>> <<set _gameData to setup.ExploreSession[_b.id]>> <<set _targetPassage to _b.name + "_" + _gameData.state>> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">INSIDE</h1> <div class="zh"><<print _b.name>></div> </div> <div class="sys-back-btn menu-item" data-target="探索_建筑状态"> < RETURN </div> </div> <div class="cc-layout" style="min-height: 75vh; padding: 20px;"> <div style="display: flex; gap: 2rem; width: 100%; height: 100%;"> <!-- 左侧:叙事与事件 (占大头) --> <div style="flex: 3; display: flex; flex-direction: column; overflow-y: auto; padding-right: 10px;"> <!-- ① 状态描述文案 --> <div style="font-size: 1.05rem; line-height: 1.8; background: var(--color-bg-glass); padding: 20px; border-left: 2px solid var(--color-accent-purple); margin-bottom: 2rem;"> <<if Story.has(_targetPassage)>> <<include _targetPassage>> <<else>> <p class="text-muted">(你进入了建筑内部。这里似乎没有什么特别值得注意的景象。)</p> <</if>> </div> <!-- ④ 异状与事件串 --> <h3 class="cc-subtitle">异状与事件 <span class="en">EVENTS</span></h3> <div style="display: flex; flex-direction: column; gap: 1rem;"> <<if _gameData.events.length > 0>> <<for _i, _eventId range _gameData.events>> <!-- 预留的事件卡片样式 --> <div class="ws-order-card" style="border-color: var(--color-accent-purple);"> <div class="ws-card-header" style="color: var(--color-accent-purple);"> ✦ [主线] 迷失的信使 </div> <div class="ws-card-details"> <span style="color: var(--color-text-secondary);">角落里坐着一个戴飞羽帽的信使,他看起来非常焦躁。</span> </div> <div class="ws-card-action"> <<button "介入事件">><</button>> </div> </div> <</for>> <<else>> <div class="empty-text" style="padding: 2rem; border: 1px dashed var(--color-border-subtle);">(一切如常,没有特殊事件发生)</div> <</if>> </div> </div> <!-- 右侧:交互与人物 (占小头) --> <div style="flex: 2; display: flex; flex-direction: column; gap: 2rem; overflow-y: auto; padding-right: 10px;"> <!-- ② 常规行动 --> <div> <h3 class="cc-subtitle">常规行动 <span class="en">ACTIONS</span></h3> <div style="display: flex; flex-direction: column; gap: 1rem;"> <<set _availableActions to _b.actions[_gameData.state] || []>> <<if _availableActions.length > 0>> <<for _i, _actId range _availableActions>> <<set _act to setup.ActionDB[_actId]>> <<capture _actId, _act, _b>> <!-- 复用工坊的卡片样式,保持 UI 极度统一 --> <div class="ws-order-card"> <div class="ws-card-header"> <span style="margin-right: 10px;"><<print _act.icon>></span><<print _act.name>> </div> <div class="ws-card-details" style="font-family: var(--font-en);"> <span>AP: <span class="highlight-gold"><<print _act.ap>></span></span> <span>Time: <span class="highlight-gold"><<print _act.time>></span></span> </div> <div class="ws-card-action"> <<button "执行">><<exploreAction _actId _b.id>><</button>> </div> </div> <</capture>> <</for>> <<else>> <div class="empty-text">(当前状态下无可用行动)</div> <</if>> </div> </div> <!-- ③ 在场人物 --> <div> <h3 class="cc-subtitle">在场人物 <span class="en">CONTACTS</span></h3> <div style="display: flex; flex-direction: column; gap: 1rem;"> <<if _gameData.npcs.length > 0>> <<for _i, _npcId range _gameData.npcs>> <!-- 预留的 NPC 卡片样式 --> <div class="ws-order-card"> <div class="ws-card-header">完构物质</div> <div class="ws-card-details"> <span style="color: var(--color-text-secondary);">态度: 冷漠</span> </div> <div class="ws-card-action"> <<button "发起洽谈">><</button>> <<button "快速对话">><</button>> </div> </div> <</for>> <<else>> <div class="empty-text" style="padding: 2rem; border: 1px dashed var(--color-border-subtle);">(暂未发现值得注意的人)</div> <</if>> </div> </div> </div> </div> </div>
<<do>> <<set _shopTab to _shopTab || "buy">> <<set _activeCategory to _activeCategory || "全部">> <<set _bId to $meta.currentBuilding>> <<set _shopDef to setup.Database.Shops[_bId]>> <<set _regionDef to setup.MapDatabase[$meta.currentRegion]>> <div class="sys-header"> <div class="sys-header-title"> <h1 class="en">MARKETPLACE</h1> <div class="zh"><<print _shopDef ? _shopDef.name : "未知集市">></div> </div> <div class="sys-back-btn menu-item" data-target="探索_建筑内部"> < RETURN </div> </div> <<if !_shopDef>> <div class="empty-text" style="text-align:center; padding: 4rem;"> <div style="font-size: 3rem; opacity: 0.3; margin-bottom: 1rem;">🛒</div> 这里似乎没有什么可以交易的物资。 </div> <<else>> <<set _shopData to setup.Explore.getShopInventory(_bId)>> <<set _dailyItems to _shopData.items>> <<set _fameBonus to (_shopDef.type === "official") ? Math.min(0.30, Math.floor($management.workshop.credit / 100) * 0.02) : 0>> <<set _fameDisplay to Math.round(_fameBonus * 100)>> <div class="shop-full-layout fade-in-down"> <!-- 左侧:商人立绘与对话 --> <div class="shop-merchant-panel"> <div class="merchant-sprite"> <div class="merchant-placeholder">PORTRAIT</div> </div> <div class="merchant-dialogue"> <div class="md-name">商人</div> <div class="md-text" id="shop-dialogue-text"> <<if _shopDialogueMsg>> <span @style="_shopDialogueIsError ? 'color: var(--color-error);' : 'color: var(--color-text-primary);'"> <<print _shopDialogueMsg>> </span> <<else>> <<set _welcomePool to _shopDef.dialogues["welcome"]>> <<set _shopDialogueMsg to _welcomePool[Math.floor(Math.random() * _welcomePool.length)]>> <<print _shopDialogueMsg>> <</if>> </div> </div> </div> <!-- 右侧:交易区 --> <div class="shop-trading-panel"> <!-- 顶部导航与状态栏 --> <div class="shop-header-bar"> <div class="shop-tabs"> <span @class="'shop-tab-wrapper ' + (_shopTab === 'buy' ? 'active' : '')"> <<button "购买物资">> <<set _shopTab to "buy">> <<set _activeCategory to "全部">> <<redo>> <</button>> </span> <span @class="'shop-tab-wrapper ' + (_shopTab === 'sell' ? 'active' : '')"> <<button "出售行囊">> <<set _shopTab to "sell">> <<set _activeCategory to "全部">> <<redo>> <</button>> </span> </div> <div class="shop-status"> <div class="shop-status-coin"> 持有资金: <span class="highlight-gold"><<print $management.workshop.coin>></span> 🪙 </div> <div class="shop-status-meta"> <<if _fameDisplay > 0>> <span style="color: var(--color-accent-purple);">[ 知名度加成: <<print _fameDisplay>>% ]</span> <</if>> <span>交易耗时: <<print _shopDef.timeCost>> Time | 汇率: <<print _regionDef.exchangeRate>></span> <<if _shopData.haggleAttempted>> <<if _shopData.haggleBonus > 0>> <span class="haggle-badge success">议价成功</span> <<elseif _shopData.haggleBonus < 0>> <span class="haggle-badge error">激怒商人</span> <<else>> <span class="haggle-badge fail">议价失败</span> <</if>> <<else>> <span class="shop-haggle-wrapper"> <button class="sys-btn" style="padding: 2px 10px; font-size: 0.85rem; border-color: var(--color-accent-purple); color: var(--color-accent-purple);" onclick="setup.Explore.haggle($meta.currentBuilding)"> 议价 (1 AP) </button> </span> <</if>> </div> </div> </div> <!-- 动态分类标签 --> <<set _categories to ["全部"]>> <<if _shopTab === "buy">> <<for _hash, _data range _dailyItems>> <<set _tag to window.ItemDatabase[_data.baseId].tags[0]>> <<if !_categories.includes(_tag)>><<run _categories.push(_tag)>><</if>> <</for>> <<else>> <<for _idx, _slot range $inventory.backpack.slots>> <<if _slot !== null>> <<set _itemDef to window.ItemDatabase[_slot.id]>> <<if _itemDef.tags.some(t => _shopDef.sellTags.includes(t))>> <<set _tag to _itemDef.tags[0]>> <<if !_categories.includes(_tag)>><<run _categories.push(_tag)>><</if>> <</if>> <</if>> <</for>> <</if>> <div class="shop-category-tabs"> <<for _i, _cat range _categories>> <<capture _cat>> <span @class="'shop-category-wrapper ' + (_activeCategory === _cat ? 'active' : '')"> <<button _cat>> <<set _activeCategory to _cat>> <<redo>> <</button>> </span> <</capture>> <</for>> </div> <!-- 商品网格区 --> <div style="flex: 1; overflow-y: auto;"> <<if _shopTab === "buy">> /* ================= 购买列表 ================= */ <div class="shop-grid"> <<for _hashKey, _itemData range _dailyItems>> <<set _itemDef to window.ItemDatabase[_itemData.baseId]>> <<if _activeCategory !== "全部" && _itemDef.tags[0] !== _activeCategory>><<continue>><</if>> <<capture _hashKey, _itemData, _itemDef>> <<set _batchPrice to setup.Explore.getShopPrice(_itemData.baseId, _itemData.traits, _bId, true)>> <<set _fullName to setup.Material.formatName(_itemData.baseId, _itemData.traits)>> <<set _purityPrefix to (_itemData.traits.purity !== "标准" ? _itemData.traits.purity : "")>> <<set _clarityPrefix to (_itemData.traits.clarity !== "合格" ? _itemData.traits.clarity : "")>> <div class="shop-item-card"> <div> <div class="shop-item-header"> <span class="shop-item-name"> <<print _itemDef.icon>> <<if _purityPrefix !== "">><span style="color: var(--color-accent-gold); font-size: 0.9rem; margin-right: 2px;"><<print _purityPrefix>>的</span><</if>> <<if _clarityPrefix !== "">><span style="color: var(--color-accent-gold); font-size: 0.9rem; margin-right: 2px;"><<print _clarityPrefix>>的</span><</if>> <<print _fullName>> <<if _itemData.isSpecialty>><span class="shop-tag specialty">特产</span><</if>> <<if _itemData.isDiscount>><span class="shop-tag discount">今日特价</span><</if>> </span> <span class="shop-item-price"><<print _batchPrice>> 🪙 <span style="font-size:0.8rem; color:var(--color-text-muted);">/ <<print _itemDef.price_unit || 1>><<print _itemDef.unit>></span></span> </div> <div class="shop-item-desc"><<print setup.Material.getDesc(_itemData.baseId, _itemData.traits)>></div> </div> <div class="shop-item-footer"> <div class="shop-item-stock"> 库存: <span @class="_itemData.stock > 0 ? 'val highlight-gold' : 'val highlight-red'"><<print _itemData.stock>></span> 份 </div> <div class="shop-item-actions"> <<if _itemData.stock >= 1>> <span class="shop-action-wrapper"> <<button "买 1 份">> <<set _res to setup.Explore.buyItem(_hashKey, _bId, 1)>> <<if _res.success>><<run GameUI.Toast.show(_res.msg, "success")>><<redo>><<else>><<run GameUI.Toast.show(_res.msg, "error")>><</if>> <</button>> </span> <</if>> <<if _itemData.stock >= 10>> <span class="shop-action-wrapper"> <<button "买 10 份">> <<set _res to setup.Explore.buyItem(_hashKey, _bId, 10)>> <<if _res.success>><<run GameUI.Toast.show(_res.msg, "success")>><<redo>><<else>><<run GameUI.Toast.show(_res.msg, "error")>><</if>> <</button>> </span> <</if>> <<if _itemData.stock === 0>> <span class="sold-out">售罄</span> <</if>> </div> </div> </div> <</capture>> <</for>> </div> <<else>> /* ================= 出售列表 (读取背包) ================= */ <<set _hasItems to false>> <div class="shop-grid"> <<for _idx, _slot range $inventory.backpack.slots>> <<if _slot !== null>> <<set _itemDef to window.ItemDatabase[_slot.id]>> <<if _itemDef.tags.some(t => _shopDef.sellTags.includes(t))>> <<if _activeCategory !== "全部" && _itemDef.tags[0] !== _activeCategory>><<continue>><</if>> <<set _hasItems to true>> <<capture _idx, _slot, _itemDef>> <<set _batchPrice to setup.Explore.getShopPrice(_slot.id, _slot, _bId, false)>> <<set _fullName to setup.Material.formatName(_slot.id, _slot)>> <<set _isHighDemand to (_dailyItems[_slot.id] && _dailyItems[_slot.id].isHighDemand)>> <<set _purityPrefix to (_slot.purity !== "标准" ? _slot.purity : "")>> <<set _clarityPrefix to (_slot.clarity !== "合格" ? _slot.clarity : "")>> <div class="shop-item-card"> <div> <div class="shop-item-header"> <span class="shop-item-name"> <<print _itemDef.icon>> <<if _purityPrefix !== "">><span style="color: var(--color-accent-gold); font-size: 0.9rem; margin-right: 2px;"><<print _purityPrefix>>的</span><</if>> <<if _clarityPrefix !== "">><span style="color: var(--color-accent-gold); font-size: 0.9rem; margin-right: 2px;"><<print _clarityPrefix>>的</span><</if>> <<print _fullName>> <<if _isHighDemand>><span class="shop-tag demand">高价急收</span><</if>> </span> <span class="shop-item-price" style="color: var(--color-text-secondary);">回收: <<print _batchPrice>> 🪙 <span style="font-size:0.8rem;">/ <<print _itemDef.price_unit || 1>><<print _itemDef.unit>></span></span> </div> <div class="shop-item-desc" style="font-family: var(--font-en);"> 持有数量: <span style="color: var(--color-text-primary); font-weight: bold;"><<print _slot.amount>></span> <<print _itemDef.unit>> </div> </div> <div class="shop-item-footer"> <div style="flex: 1;"></div> <div class="shop-item-actions"> <<if _batchPrice <= 0>> <span class="sold-out" style="border-color: transparent; background: transparent;">商人拒收此物</span> <<else>> <<set _batchSize to _itemDef.price_unit || 1>> <<if _slot.amount >= _batchSize>> <span class="shop-action-wrapper"> <<button "卖 1 份">> <<set _res to setup.Explore.sellItem(_idx, _bId, _batchSize)>> <<if _res.success>><<run GameUI.Toast.show(_res.msg, "success")>><<redo>><<else>><<run GameUI.Toast.show(_res.msg, "error")>><</if>> <</button>> </span> <</if>> <span class="shop-action-wrapper"> <<button "卖全部">> <<set _res to setup.Explore.sellItem(_idx, _bId, _slot.amount)>> <<if _res.success>><<run GameUI.Toast.show(_res.msg, "success")>><<redo>><<else>><<run GameUI.Toast.show(_res.msg, "error")>><</if>> <</button>> </span> <</if>> </div> </div> </div> <</capture>> <</if>> <</if>> <</for>> </div> <<if !_hasItems>> <div class="empty-text" style="text-align:center; padding: 4rem; grid-column: 1 / -1;"> 行囊中没有符合该分类或这家店愿意收购的物品。 </div> <</if>> <</if>> </div> </div> </div> <</if>> <</do>>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">GATHER INTEL</h1> <div class="zh">打听情报</div> </div> <div class="sys-back-btn menu-item" data-target="探索_建筑内部"> < RETURN </div> </div> <div class="empty-text" style="text-align:center; padding: 4rem;"> <div style="font-size: 3rem; opacity: 0.3; margin-bottom: 1rem;">👁️</div> 情报系统建设中... </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">LOAN & CONTRACT</h1> <div class="zh">盲眼合约</div> </div> <div class="sys-back-btn menu-item" data-target="探索_建筑内部"> < RETURN </div> </div> <div class="empty-text" style="text-align:center; padding: 4rem;"> <div style="font-size: 3rem; opacity: 0.3; margin-bottom: 1rem;">⚖️</div> 借贷系统建设中... </div>
<div class="sys-header"> <div class="sys-header-title"> <h1 class="en">INVESTIGATE</h1> <div class="zh">调查现场</div> </div> <div class="sys-back-btn menu-item" data-target="探索_建筑内部"> < RETURN </div> </div> <div class="empty-text" style="text-align:center; padding: 4rem;"> <div style="font-size: 3rem; opacity: 0.3; margin-bottom: 1rem;">🔍</div> 现场调查系统建设中... </div>
<div class="detail-desc"> <p>[文本留空:请在此处填写王座厅正常开放时的场景描述。]</p> </div> <div class="action-list"> <!-- 王座厅正常开放时没有常规动作,你可以根据主线在这里手写特殊按钮 --> </div>
<div class="detail-desc"> <p>[文本留空:请在此处填写王座厅被封锁时的场景描述,例如满地血迹、大门紧锁等。]</p> </div> <div class="action-list"> <div class="action-btn"> <div class="act-info"> <span class="act-icon">🔍</span><span class="act-name">调查现场</span> </div> <div class="act-cost">AP: 1 | Time: 10</div> <<button "执行">><<exploreAction "investigate" "b_throne">><</button>> </div> </div>
<div class="detail-desc"> <p>[文本留空:请在此处填写高庭学会正常开放时的场景描述,例如学者们匆匆走过、空气中弥漫着羊皮纸的味道。]</p> </div> <div class="action-list"> <div class="action-btn"> <div class="act-info"> <span class="act-icon">👁️</span><span class="act-name">打听情报</span> </div> <div class="act-cost">AP: 1 | Time: 5</div> <<button "执行">><<exploreAction "intel" "b_academy">><</button>> </div> </div>
<div class="detail-desc"> <p>[文本留空:请在此处填写高庭学会被封锁时的场景描述。]</p> </div> <div class="action-list"> <div class="action-btn"> <div class="act-info"> <span class="act-icon">🔍</span><span class="act-name">调查现场</span> </div> <div class="act-cost">AP: 1 | Time: 10</div> <<button "执行">><<exploreAction "investigate" "b_academy">><</button>> </div> </div> /* ---------------------------------------------------------------------------- 【上城区】 ---------------------------------------------------------------------------- */
<div class="detail-desc"> <p>[文本留空:请在此处填写树影相会总会正常开放时的场景描述,例如繁忙的交易大厅、精密的机械天平。]</p> </div> <div class="action-list"> <div class="action-btn"> <div class="act-info"><span class="act-icon">👁️</span><span class="act-name">打听情报</span></div> <div class="act-cost">AP: 1 | Time: 5</div> <<button "执行">><<exploreAction "intel" "b_shadow_hq">><</button>> </div> <div class="action-btn"> <div class="act-info"><span class="act-icon">🛒</span><span class="act-name">浏览商品</span></div> <div class="act-cost">AP: 0 | Time: 5</div> <<button "执行">><<exploreAction "shop" "b_shadow_hq">><</button>> </div> </div>
<div class="detail-desc"> <p>[文本留空:请在此处填写歌剧院正常开放时的场景描述,例如纸醉金迷的贵族、悠扬的咏叹调。]</p> </div> <div class="action-list"> <div class="action-btn"> <div class="act-info"><span class="act-icon">☕</span><span class="act-name">小憩片刻 (降压)</span></div> <div class="act-cost">AP: 0 | Time: 20</div> <<button "执行">><<exploreAction "rest" "b_opera">><</button>> </div> </div>
<div class="detail-desc"> <p>[文本留空:请在此处填写因为魅力(APP)不足被侍者拦在门外的屈辱/冷漠场景。]</p> </div> <!-- 门槛不足时,不提供任何动作按钮,玩家只能点击左上角返回 -->
<div class="detail-desc"> <p>[文本留空:请在此处填写赛马场正常开放时的场景描述,例如赌徒的狂热呼喊、刺鼻的汗水味。]</p> </div> <div class="action-list"> <div class="action-btn"> <div class="act-info"><span class="act-icon">☕</span><span class="act-name">小憩片刻 (观赛)</span></div> <div class="act-cost">AP: 0 | Time: 20</div> <<button "执行">><<exploreAction "rest" "b_racecourse">><</button>> </div> </div> /* ---------------------------------------------------------------------------- 【下城区】 ---------------------------------------------------------------------------- */
<div class="detail-desc"> <p>[文本留空:请在此处填写下城市场正常开放时的场景描述,例如鱼龙混杂的摊位、讨价还价的喧闹。]</p> </div> <div class="action-list"> <div class="action-btn"> <div class="act-info"><span class="act-icon">👁️</span><span class="act-name">打听情报</span></div> <div class="act-cost">AP: 1 | Time: 5</div> <<button "执行">><<exploreAction "intel" "b_market">><</button>> </div> <div class="action-btn"> <div class="act-info"><span class="act-icon">🛒</span><span class="act-name">浏览商品</span></div> <div class="act-cost">AP: 0 | Time: 5</div> <<button "执行">><<exploreAction "shop" "b_market">><</button>> </div> </div>
<div class="detail-desc"> <p>[文本留空:请在此处填写盲眼当铺正常开放时的场景描述,例如阴暗的角落、诡异的契约羊皮纸。]</p> </div> <div class="action-list"> <div class="action-btn"> <div class="act-info"><span class="act-icon">👁️</span><span class="act-name">打听情报</span></div> <div class="act-cost">AP: 1 | Time: 5</div> <<button "执行">><<exploreAction "intel" "b_pawnshop">><</button>> </div> <div class="action-btn"> <div class="act-info"><span class="act-icon">⚖️</span><span class="act-name">办理业务 (借贷)</span></div> <div class="act-cost">AP: 0 | Time: 5</div> <<button "执行">><<exploreAction "loan" "b_pawnshop">><</button>> </div> </div> /* ---------------------------------------------------------------------------- 【特殊:宅邸与工坊】 ---------------------------------------------------------------------------- */
<<goto "工坊_主界面">>
<!-- 游戏的绝对底层 HTML 结构 --> <div id="game-app"> <!-- 核心内容渲染区 --> <div id="passages"></div> <!-- 全局底边栏 --> <div id="global-bottom-bar"></div> <!-- 全局自定义弹窗系统 --> <div id="custom-overlay" class="hidden"> <div id="custom-dialog"> <div class="dialog-header"> <div class="dialog-title" id="custom-modal-title">SYS.REQ</div> <div class="dialog-close" data-action="close-popup"><span class="close-icon">×</span></div> </div> <div class="dialog-content" id="custom-modal-body"></div> </div> </div> </div>
/* ========================================== */ /* ① 游戏全局与元数据 ($meta) */ /* ========================================== */ <<set $meta = { isStarted: false, progress: "init", ccStep: 1, decisionCount: 0, saveTime: null, playTime: 0, /* --- 探索系统相关 --- */ currentRegion: "reg_capital", location: "宅邸工坊", buildingOverrides: {} }>> /* ========================================== */ /* ② 系统设置变量 ($sys) */ /* ========================================== */ <<set $sys = { version: "0.1.0", volume: 1.0, theme: "dark", textSize: "normal", textSpeed: 50 }>> /* ========================================== */ /* ③ 时间与循环系统 ($time) */ /* ========================================== */ <<set $time = { sleepDay: 1, season: "patrol", timeValue: 0, timeChaos: 0 }>> /* ========================================== */ /* ④ 玩家核心实体 ($player) */ /* ========================================== */ <<set $player = { name: "", title: "", race: "demon", mental: { stress: 0, anxiety: 0, trance: 0, dissociation: 0 }, stats: { str: 10, con: 10, siz: 10, int: 10, pow: 10, dex: 10, app: 10, luk: 10 }, derived: { apMax: 0, currentAp: 0, error: 0, res: 0 }, skills: { general: { linguistics: { level: 1, exp: 0 }, eavesdrop: { level: 2, exp: 0 }, detective: { level: 3, exp: 0 }, rhetoric: { level: 2, exp: 0 } }, personal: { foresight: { level: 1, exp: 0, isPassive: true }, witchcraft: { level: 1, exp: 0 }, combat: { level: 1, exp: 0 }, game: { level: 1, exp: 0 }, locate: { level: 1, exp: 0 } } }, occult: { deillogy: { level: 0, exp: 0, surplusPoints: 0, courses: { tracking: "B", imaging: "B", ritual: "B", halo: "B" } }, nomantia: { level: 0, exp: 0, surplusPoints: 0, courses: { alchemy: "B", herbology: "B", incantation: "B", phantom: "B" } }, totem: { level: 0, exp: 0, surplusPoints: 0, courses: { anatomy: "B", meridian: "B", colossus: "B", livestock: "B" } } }, appearance: { skin: { type: "常规", mainColor: "灼红", subColor: "无", texture: "无", scar: "无" }, body: { weight: "正常", muscle: "中等", fat: "适中", shape: "均匀型" }, gender: { social: "女性", identity: "女性", visibility: "寻常" }, face: { eyeCount: 2, eyeAlternative: "无", eyes: [ { shape: "圆眼", whiteColor: "雾白", pupilColor: "渊黑", pupilShape: "圆形", position: "常规", special: "无" }, { shape: "圆眼", whiteColor: "雾白", pupilColor: "渊黑", pupilShape: "圆形", position: "常规", special: "无" } ], ears: { type: "常规", material: "默认", color: "同肤色", special: "无" }, nose: { type: "小巧", alternative: "无" }, mouth: { lipShape: "常规", naturalColor: "苍白色", coating: "无", upperThickness: "中等", lowerThickness: "中等", teeth: "常规", special: "无", tongueShape: "常规", tongueColor: "肉粉" } }, hair: { front: { length: "中长", style: "无" }, side: { length: "中长", style: "自然" }, back: { length: "中长", style: "自然" }, overall: { style: "蓬乱", texture: "直发", gloss: "哑光", colorMode: "纯色" } }, genitals: { type: "常规雌性", size: "中", cover: "无", status: "光滑", texture: "柔软" }, breasts: { size: "适中", count: "一对", texture: "柔软", nippleShape: "凸起", areolaSize: "中", cover: "无" }, throat: { adamsApple: "无" }, limbs: { hands: { shape: "人形", digitCount: "五", joint: "常规", cover: "无", special: "无" }, feet: { shape: "人形", stance: "跖行", special: "无" }, overall: { symmetry: "是", proportion: "符合身材", jointFeature: "平滑连接", prosthetic: "否" } }, headAttachments: [], headGrowths: [], bodyGrowths: [] } }>> /* ========================================== */ /* ⑤ 玩家私人资产与知识库 ($inventory) */ /* ========================================== */ <<set $inventory = { warehouse: { materials: { "rock_salt": { "无|标准|合格|死寂|晶体|无|0": { amount: 1000, bundle: "无", purity: "标准", clarity: "合格", greyness: "死寂", form: "晶体", error: "无", age: 0 } }, "sea_salt": { "无|标准|合格|死寂|晶体|无|0": { amount: 400, bundle: "无", purity: "标准", clarity: "合格", greyness: "死寂", form: "晶体", error: "无", age: 0 } }, "sulfur": { "无|标准|合格|死寂|块状|无|0": { amount: 500, bundle: "无", purity: "标准", clarity: "合格", greyness: "死寂", form: "块状", error: "无", age: 0 } }, "qi_liquid": { "无|高纯|合格|死寂|溶剂|无|0": { amount: 200, bundle: "无", purity: "高纯", clarity: "合格", greyness: "死寂", form: "溶剂", error: "无", age: 0 } }, "lead": { "无|标准|合格|死寂|块状|无|0": { amount: 20, bundle: "无", purity: "标准", clarity: "合格", greyness: "死寂", form: "块状", error: "无", age: 0 } }, "secret_gold": { "无|极纯|无瑕|死寂|块状|无|0": { amount: 5, bundle: "无", purity: "极纯", clarity: "无瑕", greyness: "死寂", form: "块状", error: "无", age: 0 } }, "raw_hide": { "腐败|浑浊|粗劣|鲜活|生皮|无|0": { amount: 10, bundle: "腐败", purity: "浑浊", clarity: "粗劣", greyness: "鲜活", form: "生皮", error: "无", age: 0 } }, "pod_peel": { "无|标准|合格|死寂|块状|无|0": { amount: 300, bundle: "无", purity: "标准", clarity: "合格", greyness: "死寂", form: "块状", error: "无", age: 0 } } }, usables: {} }, backpack: { baseSlots: 16, extraSlots: 0, slots: [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null] }, /* 1. 密契与残篇 (Pacts & Scrolls) - 核心研习对象 */ /* 流程:获取 -> 概念解构(isDecoded:true) -> 研读卷宗(isStudied:true) -> 转化为技能经验/盈余点数 */ pacts: { "scroll_volongoto": { amount: 1, isDecoded: false, isStudied: false }, "recipe_blood_solvent": { amount: 1, isDecoded: false, isStudied: false } }, /* 2. 非棺与遗物 (Relics) - 展览与被动增益 */ /* 流程:获取 -> 概念解构(isDecoded:true) -> 典藏展览(解锁图鉴与全局被动) */ relics: { "mishi_heart": { amount: 1, isDecoded: true, isStudied: true }, /* 初始自带,已完全解析 */ "eye_of_shemit": { amount: 1, isDecoded: false, isStudied: false } }, /* 3. 常规关键道具 (Key Items) - 信件、凭证、任务物品 */ /* 流程:获取 -> 直接查看/使用 (不需要解构) */ keyItems: { "letter_from_tree": { amount: 1, isRead: false }, "workshop_license": { amount: 1, isRead: true } } }>> <<set $recipes = { rcp_snelling_salt: 1, rcp_sulfur_cleaner: 1, rcp_organ_bag_crude: 0 }>> /* 玩家笔记 */ <<set $notes = { items: { "rock_salt": [ "我喜欢把岩盐晶称为第一物质,虽然图腾学的同窗们总是在纠正我影界的第一物质应该是海洋,我只能说去他的,影界的海都不知道死了多久了,谁知道他们说的是真是假。" ], "sea_salt": [ "找遍了所有港口只有这里出售海盐,老东西居然敢要我四十银币一千克,真是疯了,这东西值个鸟钱。" ], "sulfur": [ "买回来之后记得先放在院子里散散味,这些东西刚从火山里被挖出来就送到了市场卖,臭气浓得很,放炭粒都去不掉。" ] }, npcs: {}, }>> /* ========================================== */ /* ⑥ 社交与 NPC 关系档案 ($npcs) */ /* ========================================== */ <<set $npcs = { "physical_done": { isMet: true, loreStage: 1, attitudes: { inf: -5, thr: 1, val: 3, res: 0, cos: 4 }, currentMode: "中立", isResistant: false, unlockedKeywords: ["暂停", "宿疾"], unlockedArchives: ["family"] }, "hana_parade": { isMet: true, loreStage: 1, attitudes: { inf: 4, thr: 2, val: 1, res: -2, cos: -4 }, currentMode: "中立", isResistant: false, unlockedKeywords: ["蕃神"], // 初始解锁一个词 unlockedArchives: ["observer"] // 初始解锁一条档案 }, "npc_yushi": { isMet: false, loreStage: 1, attitudes: { inf: 0, thr: 0, val: 0, res: 0, cos: 0 }, currentMode: "中立", isResistant: false, unlockedKeywords: [], unlockedArchives: [] } }>> /* ========================================== */ /* ⑦ 经营与后勤系统 ($management) */ /* ========================================== */ <<set $management = { doll: { name: "", level: 0, maintenanceDays: 0, status: "normal", yieldMultiplier: 1.0, queue: [] }, warehouse: { maxCapacity: 10000, materials: { "rock_salt": { "标准|晶体|无": { amount: 5000, prefix: "标准", form: "晶体", error: "无" } }, "sulfur": { "标准|块状|无": { amount: 2000, prefix: "标准", form: "块状", error: "无" } }, "pod_peel": { "标准|块状|无": { amount: 1000, prefix: "标准", form: "块状", error: "无" } } }, products: {} }, workshop: { name: "", credit: 0, coin: 500, debt: 0, prototypes: { "rcp_snelling_salt": true, "rcp_sulfur_cleaner": true }, processes: { grinding: 1.0, mixing: 1.0, compressing: 1.0, cutting: 1.0, sewing: 1.0, extracting: 0.0, fusing: 0.0, purifying: 0.0, tanning: 0.0, corrupting: 0.0, fermenting: 0.0, infusing: 0.0, cleansing: 0.0 }, orders: { available: [], active: [], history: 0 } } }>> /* ========================================== */ /* ⑧ 研究与主线进度 ($research) */ /* ========================================== */ <<set $research = { swampUnlocked: { colorShift: false, deathWall: false, witchsPact: false, angel: false, astral: false, shadowBehind: false } }>>
<<do>> <div class="bottom-bar-content"> <!-- 左侧:工坊与人偶信息 --> <div class="bottom-info"> <span class="ws-name"><<print $management.workshop.name>></span> <span class="ws-doll">助理: <<print $management.doll.name>></span> </div> <!-- 中间:核心状态 HUD --> <div class="bottom-hud"> <div class="hud-item" title="当前时节"> <span class="icon">🌙</span> <span class="val"><<if $time.season is "patrol">>巡游期<<elseif $time.season is "predation">>捕食期<<else>>繁殖期<</if>></span> </div> <div class="hud-item" title="精力"> <span class="icon">⚡</span> <span class="val"><<print $player.derived.currentAp>> / <<print $player.derived.apMax>></span> </div> <div class="hud-item" title="资金"> <span class="icon">🪙</span> <span class="val highlight-gold"><<print $management.workshop.coin>></span> </div> </div> <!-- 中右侧:玩家随身功能 (点击弹窗) --> <div class="bottom-player-nav"> <div class="sys-btn" data-action="inventory" title="随身背包 (Backpack)">INV</div> <div class="sys-btn" data-action="contacts" title="联络簿 (Contacts)">CON</div> <div class="sys-btn" data-action="player_stats" title="灵魂刻度 (Stats)">STA</div> </div> <!-- 右侧:系统功能 --> <div class="bottom-sys"> <div class="sys-btn" id="btn-sys-saves" title="履行旧约">DOC</div> <div class="sys-btn" id="btn-sys-settings" title="校准纺车">SET</div> <div class="sys-btn" id="btn-sys-title" title="返回标题">ESC</div> </div> </div> <</do>>
<<savesgrid>>
<div class="sys-settings-container" style="padding: 1rem;"> <div class="setting-row"> <div class="setting-label"> <span class="zh">纺车轰鸣</span><span class="en">VOLUME</span> </div> <div class="setting-control"> <input type="range" id="set-volume" min="0" max="1" step="0.1" value="1"> <span id="val-volume" class="val-display">100%</span> </div> </div> <div class="setting-row"> <div class="setting-label"> <span class="zh">墨迹流速</span><span class="en">TEXT SPEED</span> </div> <div class="setting-control"> <input type="range" id="set-speed" min="10" max="100" step="10" value="50"> <span id="val-speed" class="val-display">50ms</span> </div> </div> <div class="setting-row"> <div class="setting-label"> <span class="zh">视界焦距</span><span class="en">TEXT SIZE</span> </div> <div class="setting-control btn-group"> <button class="sys-btn size-btn" data-size="small">微缩</button> <button class="sys-btn size-btn active" data-size="normal">寻常</button> <button class="sys-btn size-btn" data-size="large">宏大</button> </div> </div> <div class="setting-row"> <div class="setting-label"> <span class="zh">视觉界域</span><span class="en">THEME</span> </div> <div class="setting-control btn-group" style="display: flex; gap: 0.5rem; flex-wrap: wrap; justify-content: flex-end;"> <button class="sys-btn theme-btn" data-theme="dark">深邃</button> <button class="sys-btn theme-btn" data-theme="light">白昼</button> <button class="sys-btn theme-btn" data-theme="crimson">猩红</button> <button class="sys-btn theme-btn" data-theme="abyss">深渊</button> <button class="sys-btn theme-btn" data-theme="prism">棱镜</button> </div> </div> </div>
<div style="text-align: center; padding: 2rem 1rem;"> <p style="color: var(--color-text-primary); font-size: 1.2rem; margin-bottom: 1rem; letter-spacing: 2px;"> 确定要放弃当前进度,返回标题界面吗? </p> <p style="color: var(--color-error); font-size: 0.9rem; margin-bottom: 3rem;"> [ 警告 ] 未铭刻的记忆(未保存的进度)将会永久消散。 </p> <div style="display: flex; justify-content: center; gap: 2rem;"> <!-- 取消按钮:关闭弹窗 --> <<button "取消">><<run GameUI.Popup.close()>><</button>> <!-- 确认按钮:调用引擎重启,并加上危险按钮的红色样式 --> <<button "确认返回">> <<run Engine.restart()>> <</button>> </div> </div>
<!-- 个人背包界面 --> <<backpack_popup>>
/* 统计已认识的 NPC 数量 */ <<set _metCount to 0>> <<for _npcId, _npcData range $npcs>> <<if _npcData.isMet>><<set _metCount++>><</if>> <</for>> <<if _metCount === 0>> <!-- 空状态:保持你原本的绝佳设计 --> <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 40vh; text-align: center;"> <div style="font-size: 3rem; opacity: 0.5; filter: grayscale(100%); margin-bottom: 1rem;">📇</div> <div style="color: var(--color-text-primary); font-size: 1.2rem; letter-spacing: 2px; margin-bottom: 0.5rem; font-family: var(--font-zh);"> [ 联络簿中暂无记录 ] </div> <div style="color: var(--color-text-muted); font-size: 0.9rem; font-family: var(--font-zh);"> 随着探索的深入,你结识的实体与他们的态度倾向将记录于此。 </div> </div> <<else>> <!-- 列表状态:迷你名片 --> <div class="contacts-mini-list" style="max-height: 50vh; overflow-y: auto; padding-right: 10px; display: flex; flex-direction: column; gap: 10px;"> <<for _npcId, _npcData range $npcs>> <<if _npcData.isMet>> <<set _npcStatic to setup.NPCs[_npcId]>> <div class="contact-mini-card" style="background: var(--color-bg-surface); border: 1px solid var(--color-border-subtle); padding: 15px; display: flex; justify-content: space-between; align-items: center; transition: border-color var(--transition-fast);"> <div style="display: flex; flex-direction: column; gap: 5px;"> <div style="color: var(--color-text-primary); font-size: 1.1rem; font-family: var(--font-zh); letter-spacing: 1px;"> <<print _npcStatic.name>> </div> <div style="color: var(--color-text-muted); font-size: 0.85rem; font-family: var(--font-zh);"> <<print _npcStatic.concept_tag>> </div> </div> <div style="text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 10px;"> <div style="color: var(--color-accent-gold); font-size: 0.85rem; font-family: var(--font-zh);"> 当前态度: [ <<print _npcData.currentMode>> ] </div> </div> </div> <</if>> <</for>> </div> <!-- 底部全局跳转按钮 --> <div style="margin-top: 20px; text-align: center; border-top: 1px dashed var(--color-border-subtle); padding-top: 15px;"> <<button "进入完整联络档案库">> <<run GameUI.Popup.close()>> <<run Engine.play("角色档案")>> <</button>> </div> <</if>>
<div class="sta-layout"> <!-- 1. 档案头部:身份与精神状态 --> <div class="sta-header-card"> <div class="sta-profile"> <div class="sta-avatar"></div> <div class="sta-info"> <div class="sta-name"> <<if $player.name is "">>未命名<<else>><<print $player.name>><</if>> <span class="sta-title">「 <<if $player.title is "">>无称号<<else>><<print $player.title>><</if>> 」</span> </div> <div class="sta-race">种族判定: <span class="highlight-gold"><<print $player.race>></span></div> </div> </div> <div class="sta-mental"> <div class="mental-item">压力 <span><<print $player.mental.stress>></span></div> <div class="mental-item">不安 <span><<print $player.mental.anxiety>></span></div> <div class="mental-item">恍惚 <span><<print $player.mental.trance>></span></div> <div class="mental-item">解离 <span><<print $player.mental.dissociation>></span></div> </div> </div> <!-- 2. 基础与衍生属性 --> <div class="sta-section"> <h3 class="sta-sec-title">躯体机能 <span class="en">ATTRIBUTES</span></h3> <div class="sta-stats-grid"> <div class="sta-stat-box"><span class="label">力量 <span class="en">STR</span></span><span class="val"><<print $player.stats.str>></span></div> <div class="sta-stat-box"><span class="label">体质 <span class="en">CON</span></span><span class="val"><<print $player.stats.con>></span></div> <div class="sta-stat-box"><span class="label">体型 <span class="en">SIZ</span></span><span class="val"><<print $player.stats.siz>></span></div> <div class="sta-stat-box"><span class="label">智力 <span class="en">INT</span></span><span class="val"><<print $player.stats.int>></span></div> <div class="sta-stat-box"><span class="label">意志 <span class="en">POW</span></span><span class="val"><<print $player.stats.pow>></span></div> <div class="sta-stat-box"><span class="label">敏捷 <span class="en">DEX</span></span><span class="val"><<print $player.stats.dex>></span></div> <div class="sta-stat-box"><span class="label">魅力 <span class="en">APP</span></span><span class="val"><<print $player.stats.app>></span></div> <div class="sta-stat-box"><span class="label">幸运 <span class="en">LUK</span></span><span class="val"><<print $player.stats.luk>></span></div> </div> <div class="sta-derived-grid"> <div class="sta-stat-box derived"><span class="label">行动点 <span class="en">AP</span></span><span class="val highlight-gold"><<print $player.derived.apMax>></span></div> <div class="sta-stat-box derived"><span class="label">失误值 <span class="en">ERROR</span></span><span class="val highlight-red"><<print $player.derived.error>></span></div> <div class="sta-stat-box derived"><span class="label">抵抗值 <span class="en">RES</span></span><span class="val highlight-gold"><<print $player.derived.res>></span></div> </div> </div> <!-- 3. 常规技能 --> <div class="sta-section"> <h3 class="sta-sec-title">常规技艺 <span class="en">SKILLS</span></h3> <div class="sta-skills-grid"> <div class="sta-skill-item"><div class="skill-name">语言学</div><div class="skill-level">Lv.<<print $player.skills.general.linguistics.level>></div></div> <div class="sta-skill-item"><div class="skill-name">窃听</div><div class="skill-level">Lv.<<print $player.skills.general.eavesdrop.level>></div></div> <div class="sta-skill-item"><div class="skill-name">侦探学</div><div class="skill-level">Lv.<<print $player.skills.general.detective.level>></div></div> <div class="sta-skill-item"><div class="skill-name">话术</div><div class="skill-level">Lv.<<print $player.skills.general.rhetoric.level>></div></div> <div class="sta-skill-item"><div class="skill-name">预知 <span class="passive-tag">[被动]</span></div><div class="skill-level">Lv.<<print $player.skills.personal.foresight.level>></div></div> <div class="sta-skill-item"><div class="skill-name">巫术</div><div class="skill-level">Lv.<<print $player.skills.personal.witchcraft.level>></div></div> <div class="sta-skill-item"><div class="skill-name">格斗</div><div class="skill-level">Lv.<<print $player.skills.personal.combat.level>></div></div> <div class="sta-skill-item"><div class="skill-name">博弈</div><div class="skill-level">Lv.<<print $player.skills.personal.game.level>></div></div> <div class="sta-skill-item"><div class="skill-name">定位</div><div class="skill-level">Lv.<<print $player.skills.personal.locate.level>></div></div> </div> </div> <!-- 4. 秘氛学科 --> <div class="sta-section"> <h3 class="sta-sec-title">秘氛学科 <span class="en">OCCULT</span></h3> <div class="sta-occult-grid"> <!-- 巫疍学 --> <div class="sta-occult-card"> <div class="occ-header"> <span class="occ-name">巫疍学</span> <span class="occ-level">大类等级: <<print $player.occult.nomantia.level>></span> </div> <div class="occ-surplus">盈余点数: <span class="highlight-gold"><<print $player.occult.nomantia.surplusPoints>></span></div> <div class="occ-courses"> <div class="occ-course-row"><span>炼金术</span><span @class="'grade-' + $player.occult.nomantia.courses.alchemy.toLowerCase()"><<print $player.occult.nomantia.courses.alchemy>></span></div> <div class="occ-course-row"><span>草药学</span><span @class="'grade-' + $player.occult.nomantia.courses.herbology.toLowerCase()"><<print $player.occult.nomantia.courses.herbology>></span></div> <div class="occ-course-row"><span>咒文学</span><span @class="'grade-' + $player.occult.nomantia.courses.incantation.toLowerCase()"><<print $player.occult.nomantia.courses.incantation>></span></div> <div class="occ-course-row"><span>漫幽相学</span><span @class="'grade-' + $player.occult.nomantia.courses.phantom.toLowerCase()"><<print $player.occult.nomantia.courses.phantom>></span></div> </div> </div> <!-- 诅咒学 --> <div class="sta-occult-card"> <div class="occ-header"> <span class="occ-name">诅咒学</span> <span class="occ-level">大类等级: <<print $player.occult.deillogy.level>></span> </div> <div class="occ-surplus">盈余点数: <span class="highlight-gold"><<print $player.occult.deillogy.surplusPoints>></span></div> <div class="occ-courses"> <div class="occ-course-row"><span>追迹术</span><span @class="'grade-' + $player.occult.deillogy.courses.tracking.toLowerCase()"><<print $player.occult.deillogy.courses.tracking>></span></div> <div class="occ-course-row"><span>成像学</span><span @class="'grade-' + $player.occult.deillogy.courses.imaging.toLowerCase()"><<print $player.occult.deillogy.courses.imaging>></span></div> <div class="occ-course-row"><span>典仪</span><span @class="'grade-' + $player.occult.deillogy.courses.ritual.toLowerCase()"><<print $player.occult.deillogy.courses.ritual>></span></div> <div class="occ-course-row"><span>色晕学</span><span @class="'grade-' + $player.occult.deillogy.courses.halo.toLowerCase()"><<print $player.occult.deillogy.courses.halo>></span></div> </div> </div> <!-- 图腾学 --> <div class="sta-occult-card"> <div class="occ-header"> <span class="occ-name">图腾学</span> <span class="occ-level">大类等级: <<print $player.occult.totem.level>></span> </div> <div class="occ-surplus">盈余点数: <span class="highlight-gold"><<print $player.occult.totem.surplusPoints>></span></div> <div class="occ-courses"> <div class="occ-course-row"><span>生体解剖</span><span @class="'grade-' + $player.occult.totem.courses.anatomy.toLowerCase()"><<print $player.occult.totem.courses.anatomy>></span></div> <div class="occ-course-row"><span>脉络学</span><span @class="'grade-' + $player.occult.totem.courses.meridian.toLowerCase()"><<print $player.occult.totem.courses.meridian>></span></div> <div class="occ-course-row"><span>巨像术</span><span @class="'grade-' + $player.occult.totem.courses.colossus.toLowerCase()"><<print $player.occult.totem.courses.colossus>></span></div> <div class="occ-course-row"><span>畜柱学</span><span @class="'grade-' + $player.occult.totem.courses.livestock.toLowerCase()"><<print $player.occult.totem.courses.livestock>></span></div> </div> </div> </div> </div> </div>
<div style="text-align: center; padding: 2rem 1rem;"> <p style="color: var(--color-text-primary); font-size: 1.2rem; margin-bottom: 1rem; letter-spacing: 2px;"> 确定要结束白日的运作吗? </p> <p style="color: var(--color-error); font-size: 0.9rem; margin-bottom: 3rem; line-height: 1.6;"> [ 警告 ] 结束本日后,你将无法再进行炼金、探索或研习。<br> 系统将结算炼金人偶白天的生产进度,并进入夜间物流打包阶段。 </p> <div style="display: flex; justify-content: center; gap: 2rem;"> <!-- 取消按钮:调用 JS 关闭弹窗 --> <<button "再等一下">> <<run GameUI.Popup.close()>> <</button>> <!-- 确认按钮:关闭弹窗并跳转到打包界面 --> <<button "确认结束">> <<run GameUI.Popup.close()>> <<goto "夜间_打包发货">> <</button>> </div> </div>