diff --git a/design/dev/architecture/architecture.md b/design/dev/architecture/architecture.md index 9fd9de0f..ef3018e1 100644 --- a/design/dev/architecture/architecture.md +++ b/design/dev/architecture/architecture.md @@ -110,7 +110,7 @@ | 模块 | Owns | Exposes | Consumes | 引擎 API | |---|---|---|---|---| -| **battle_orchestrator**(B1) | 段序骨架(七段结构冻结)、轮 facts 缓冲、可回放步骤流、[明细行协议](../../design/gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)(15 类行 + 字段分层)、条款③⑤闭合对账、**战斗域全部跨系统调用权** | `begin_battle(encounter)`;窗口/刷新意图提交面(扮演 D1);`level_clear()`;步骤流(输出契约) | B2/B3/B4 全调用面(**唯一调用方**);A3 request_refresh 代理 + 回发;A2 install/retire + 三事件订阅;A1 generate(attempt 非 scope 事件);D2 SettlementTable + set_reload_gate | 无(零随机、禁 await——切片 88 冒烟实证可回放) | +| **battle_orchestrator**(B1) | 段序骨架(七段结构冻结)、轮 facts 缓冲、可回放步骤流、[明细行协议](../../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)(15 类行 + 字段分层)、条款③⑤闭合对账、**战斗域全部跨系统调用权** | `begin_battle(encounter)`;窗口/刷新意图提交面(扮演 D1);`level_clear()`;步骤流(输出契约) | B2/B3/B4 全调用面(**唯一调用方**);A3 request_refresh 代理 + 回发;A2 install/retire + 三事件订阅;A1 generate(attempt 非 scope 事件);D2 SettlementTable + set_reload_gate | 无(零随机、禁 await——切片 88 冒烟实证可回放) | | **level_runner**(C1-lite,切片已建) | 关卡域生命周期(节点链推进、共享 B4 + HP 携带、关卡末 level_clear) | 节点推进接口;LevelTable(`level.tres`——节点 enum {battle,reward,rest,boss}、末节点必须 Boss、ConfigDB 跨表校验⑧) | B1 begin_battle、B4 grant_node_active、ConfigDB LevelTable | 无 | | **run_structure**(C2) | 冒险/关卡序列、失败重开、**master_seed 唯一接线方** | (未设计) | RngService.set_master_seed、C3/D2 | 无 | | **difficulty**(C3) | DifficultyTable 回填、全部曲线数值调参所有权、战斗期望表(切片 monte_carlo 为工具原型) | 调参输出(经 D2 R1 解析/编排器传递,禁反向调用生成) | ConfigDB、B1 对账输出(调参约束清单)、A1 报告 C | 无 | @@ -193,7 +193,7 @@ D1 ◀──呈现数据源:A2 事件流 / B1 步骤流 / A3 ap-rap / ConfigDB | A1 → A2 | Board 产物 class_name 数据契约 | install 四不变式校验(violation = 拒绝 + 五类诊断枚举) | 生成期合法性闸(R₀≠S / clearable / min_safe) | | A1 ↔ B1 | attempt 边界非 scope 事件;actuals p10 为对账输入(非 target 参数) | 编排不把重试当取号 | 生成期指标集输出(实测可推理率 / 实际雷数与安全格数 / 重试次数 / 降级与非法产物标记) | | B4 → B3 | buff 类经 B1 调 apply_effect(B4 零跨系统读、零直接接口) | 满层拒绝 = 零兑付 + 明细行(无折算) | 授予时数值快照(抗热重载) | -| B1 → D1 | [步骤流行协议](../../design/gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)(15 类封闭枚举 + 公共字段 type/source_class/origin_cell/round_index/display_name/value/highlight? + 特有字段 target/effect_id/pool_value) | 无来源行 = 断言失败;呈现侧禁按行序重演 B2 状态机 | 可回放步骤流(同种子逐行相同) | +| B1 → D1 | [步骤流行协议](../../gdd/systems/战斗循环/战斗结算.md#明细流水每一行都能指回你刚才的哪一步棋)(15 类封闭枚举 + 公共字段 type/source_class/origin_cell/round_index/display_name/value/highlight? + 特有字段 target/effect_id/pool_value) | 无来源行 = 断言失败;呈现侧禁按行序重演 B2 状态机 | 可回放步骤流(同种子逐行相同) | **引擎类型核验注记**:接口使用的引擎类型 = Resource / .tres(D2 全表)、RefCounted(容器类)、Signal/Callable(事件载体,ADR-0001)、Control/CanvasLayer/Drawing(D1)、SceneTree headless 协议(测试)——均属 4.x 基线稳定面;4.7 Control 域增量(offset_transform_* 等)已在 breaking-changes.md 登记,D1 采纳前对照核实。 diff --git a/design/gdd/07-体验验证清单.md b/design/gdd/07-体验验证清单.md index 2729cb6f..5aa7513e 100644 --- a/design/gdd/07-体验验证清单.md +++ b/design/gdd/07-体验验证清单.md @@ -144,6 +144,11 @@ - **红灯信号**:解锁行反复弹(闩失效);toast 带数值/权重(池不公开纪律破);满血即解锁(门谓词错)。 - **结论回流**:体感 → 本条目记录;技能强度体感归 T7 节奏重测读数(跑批待用户批准,过涝越带 S2 回调呈报禁自动调)。 +### ⑮ 秘宝词族换词全 UI 面目检 + 渲染像素闸补跑(2026-10-05 秘宝代码词族对齐批随批登记——迭代15③号卡) + +- **实机目检(「秘宝」字样全 UI 面,约 3 分钟)**:①C 区槽位标题应显示「秘宝」(原「魔法道具」,hero_info_panel_view 槽位组);②空槽悬停提示应显示「秘宝槽(空)」;③战斗总结三选一叙述行应显示「秘宝 / …」或「秘宝 / 随机获得一件」(原「魔法道具」开头);④换关 toast 应显示「上关剩余 N 件秘宝已随关卡结束清空」。**红灯信号**:任何界面残留「魔法道具」字样。 +- **渲染像素类闸补跑挂账**:本批屏蔽五件(golden_compare / shot_probe / fx_probe / ui_layout_probe / board_shot——组 A 文案变更使像素断言合法失效,按 goal 令弃断);**补跑时点=迭代 14 全落籍后的表现批周期闸一次性补跑**,与本批无独立补跑义务;届时若 golden 基线因文案换代失效,按换代流程重锚而非当缺陷修。 + ## 验收读数重测义务(履行留痕 + 现行义务) **已履行**(按序换代,旧读数各随其批作废留痕不入本单):①验收读数重测批(2026-09-19——Boss 单独出列/承伤带/通关率基线全量重测,硬化翻倍期·乏力死效果期·充能期旧读数作废);②迭代 5 基线重测(统一随机流后 MC+verifier 双窗);③**数值修复批新尺重测(2026-10-01)**——模拟档位重构后全量重测,新锚 `sim-data/runsum_numfix_final_n200_20261001.jsonl`,全旧带作废只测不判([numfix 报告](../qa/numfix-newruler-readings-2026-10-01.md));④**迭代 10 奖励重构批重锚(2026-10-01)**——四代锚 77000/78000/79000/80000(改前/重构后/共享池后/掷定前置后,各 400 局),普通 L1 41.8%/L2 10.2% 带内([读数报告](../qa/m3-iter10-clear-rate-readings-2026-10-01.md));⑤**T19 真人标定局收口(2026-10-03 用户裁)**——有效局 2(1 通关 1 死于 L3 首战,[读数报告](../qa/t19-real-playtest-readings-2026-10-02.md)),用户裁定**佐证级收口不再补局**;k 预期带同日立(**正常 >0.5、预警 <0.3**),字段随 81000 重锚入库后补算终值。 diff --git a/design/gdd/systems/冒险循环/奇物.md b/design/gdd/systems/冒险循环/奇物.md index 85717557..61e6e397 100644 --- a/design/gdd/systems/冒险循环/奇物.md +++ b/design/gdd/systems/冒险循环/奇物.md @@ -19,7 +19,7 @@ 一次冒险要走三关,如果走完时角色和开局毫无区别,中途的每一次取舍就都不算数了。奇物就是那个把"这一局玩成了什么样"落下来的东西:让玩家在冒险过程中不断变强,且每一局变强的方向不同。 -它同时要和跨冒险的成长隔开:永久保留的东西是[魔法道具](../排雷循环/魔法道具.md)(带在身上的物品)与[元进度](../跨局循环/元进度.md)(账号级的树),奇物只在当局存在,冒险收束即清零——它不是"你的存档变强了",而是"这一次下矿的你变强了"。 +它同时要和跨冒险的成长隔开:永久保留的东西是[魔法道具](../排雷循环/秘宝.md)(带在身上的物品)与[元进度](../跨局循环/元进度.md)(账号级的树),奇物只在当局存在,冒险收束即清零——它不是"你的存档变强了",而是"这一次下矿的你变强了"。 **边界判据(一句话)**:**一次冒险内获得、冒险收束即清零的,是奇物;跨冒险跟着你走的,是魔法道具。** @@ -270,7 +270,7 @@ | 相邻概念 | 关系(只写关系,不写对方的规则) | |---|---| -| [魔法道具](../排雷循环/魔法道具.md) | 最需要分清的一对,判据是生命周期:**奇物当局清零,魔法道具跨冒险保留**。两者互不相通——奇物永不进同调位,魔法道具永不进当局随机渠道。 | +| [魔法道具](../排雷循环/秘宝.md) | 最需要分清的一对,判据是生命周期:**奇物当局清零,魔法道具跨冒险保留**。两者互不相通——奇物永不进同调位,魔法道具永不进当局随机渠道。 | | [元进度](../跨局循环/元进度.md)(树) | 树管账号永久的规则与容量,奇物管当局构筑,两层互不代替。 | | [战斗结算](../战斗循环/战斗结算.md) | 专长的挂点位于结算管线的各段;挂点清单与语义归结算文档。 | | [行动经济](../排雷循环/行动经济.md)、[地形变异](../排雷循环/地形变异.md) | 部分挂点落在行动点结转与地形处理上,语义归各自文档。 | diff --git a/design/qa/iter15-3-mibao-exit-report-2026-10-05.md b/design/qa/iter15-3-mibao-exit-report-2026-10-05.md new file mode 100644 index 00000000..c817e6bd --- /dev/null +++ b/design/qa/iter15-3-mibao-exit-report-2026-10-05.md @@ -0,0 +1,88 @@ +# 出口报告:迭代 15 卡③ 秘宝代码词族对齐批(2026-10-05) + +> 任务书 = `design/research/任务书-秘宝代码词族对齐批-2026-10-05.md` v1.2(§1.2 基线已回填)。 +> 设计事实源 = `design/gdd/systems/排雷循环/秘宝.md` v0.9。worktree = `g-plan2-m4iter15-mibao`,分支 `m4iter15-mibao-20261005`。 + +## 一、提交链(worktree 八笔) + +| # | 提交 | 内容 | +|---|---|---| +| 1 | b4b8bb3 | T1 组A+D:玩家可见文案 5 处 + 注释层「魔法道具」→「秘宝」全清(敌方语汇/道具工坊分色保全) | +| 2 | dfd5fdd | T2 组C:architecture.md 两处既有断链清偿 | +| 3 | 5294b12 | T3 组F:`"aux_item"` 域串 16 处 → `"treasure_item"` + `TREASURE_ITEM_TYPE` 常量族 + `reward_dangling_treasure` 诊断码 | +| 4 | 2532c8f | T4 组B-1:四文件改名(treasure_items.gd / treasure_item_table.gd / treasure_items.tres / treasure_interact_controller.gd)+ 类名 + .uid 稳定 + .tres ext_resource 同步 + --import 重刷 | +| 5 | 7e5b6d9 | T5 组B-2:ConfigDB 注册键/持有变量/五访问器 + 调用方 + 单测桩表 + loaded 取键 | +| 6 | f8c6db4 | T6 组E-1:三测试文件改名 + run_all 登记 + test_kit 注释同步 | +| 7 | cd73e62 | T7 组E-2:内部标识符全族换词(60+ token)+ 存档键零触碰专项核 + 任务书 §1.2 基线回填 | +| 8 | 8c27213 | T8:tests 文档两处清零 + 奇物.md 换名断链补修 + 批末闸认证 | + +主区合并提交与全量复跑读数见台账(active.md 快照行)。 + +## 二、批末读数(批末树态 8c27213 实跑) + +| 闸 | 基线(3c4291d 实跑) | 批末 | 判定 | +|---|---|---|---| +| 冒烟 smoke_all | 755 项 / 0 失败 | **755 项 / 0 失败** | ✅ 零漂移 | +| run_all 15 套件 | 14/15(唯一红 reward_overlay_test = **②批遗留基线红**,主区 3c4291d 同样红,非本批引入) | **14/15,唯一红同款** | ✅ 对照零新增 | +| 行为探针 ui_probe / ui_click / ui_input / ui_tune | 全绿 | **全绿**(click done=true 问题=0 / input 十六断言 / tune 全链) | ✅ | +| doc 三闸(lint/term/link) | lint 8 文件 2 不通过(既有)/ term 218 命中 3 疑似 / link 死链 0(主区带脏件口径) | 同基线 | ✅ 零新增 | +| 熵增闸 repo_structure_audit | PASS | PASS | ✅ | +| MC 逐位对拍 | —— | **未跑(goal 令:纯改名零数值面禁跑 MC,静态零漂移证明代之,见 §四-12)** | ✅ 按令豁免 | + +**渲染像素类闸本批屏蔽**(golden_compare / shot_probe / fx_probe / ui_layout_probe / board_shot)——组 A 文案变更使像素断言合法失效,按 goal 令弃断;**补跑挂账 07 清单**(迭代 14 全落籍后表现批周期闸一次性补跑)。 + +## 三、批末验收断言(12 条) + +1. **词族换尽**:`aux_`/`AuxItem*`/`AUX_ITEM*` 批末全仓 game/ 残留 43 处,**逐处归例外**(§五清单),零在族欠改。 +2. **玩家可见清零**:`grep 魔法道具 game/` = 1 处(`game/README.md:538`,§4.4 禁改项·历史 changelog 留痕,非玩家可见面)——代码与 UI 面零命中。tests/README.md 与 critical-paths.md 两处已随批清零。 +3. **重闸全绿**:冒烟 755/0(§二);run_all 零新增;四探针全绿;doc 三闸+熵增闸零新增。 +4. **存档兼容零破坏(R1)**:本批 diff 全部 37 文件、六存档键(`bonus_aux_carry`/`aux_items`/`aux_detail`/`aux_cleared`/`aux_cleared_last`/`attunement_charges`)引号字面量 HEAD↔批末**逐键普查零差异**;点号访问形式全仓代码行**零存在**(仅注释提及);`_node_bonus_pending` 持久化嵌套键全部引号形态未动。 +5. **数值零漂移(R2)**:静态证明——批 diff `game/data/tables/` 数值行零改动(断言空);`magnitude`/`weight`/`power`/`charge_n` 零触碰;reward.tres 零改动。 +6. **schema 契约面零变更(R3)**:`CELL_TYPES.size()==10` 保持(改字面量不改项数);`smoke_all.gd:3932` 断言同步为 `has("treasure_item")` 后全绿;校验行为不变,错误消息文案可变(`reward_dangling_treasure` 诊断码随族改,测试双端同步)。 +7. **零字段更名(R4)**:`item_id`/`effect_kinds`/`form`/`slot_cost` 原样;treasure_items.tres 仅改 `script_class` 与 `ext_resource` 路径。 +8. **零 await(R5)**:批 diff core/ 新增 await 行数 = 0。 +9. **冒烟夹具零触碰**:smoke_all.gd 断点夹具区(:4473/:4495 `"aux_items"`/`"aux_scout"`)diff 零改动。 +10. **敌方语汇保全**:`魔法矢`/`魔法反噬`/`魔法族`/`魔法护甲` 12 处未动;`道具工坊` 8 处未动;`arch_names["magic"]` 未动。 +11. **.uid/.tscn 纪律**:四个改名 .gd 的 .uid 随文件改名且内容零变(git R100);全仓 .tscn 对改名目标零引用(改前已核);--import 批内重刷两次(T0 基线 + T4 改名后),类名解析实证=冒烟加载 TreasureItemTable 零报错。 +12. **registry 条目键不动**:`design/registry/entities.yaml` 零改动(条目键 `aux_items` 数据契约键沿用)。 + +## 四、缺陷与自修记录(全 L1 级,均当轮闭环) + +1. **T3**:任务书 §4.3 的 16 处清单漏计 `AUX_ITEM_TYPE` 常量消费方 4 处(cross_validator×2 / reward_economy / smoke:2578)——冒烟 SCRIPT ERROR 抓到,自查补齐,一次重试绿。 +2. **T4→T5**:`treasure_items.gd:117` 桩回退行 `_db.aux_items.` 漏随族改 → run_all `treasure_items_test` 红 → 补修转绿。 +3. **T8**:`grep 魔法道具 game/` 在 .gd/.tres 口径外余 3 处文档件——tests/ 两处随批清零;README.md 一处按 §4.4 保留(见 §五-4)。 + +## 五、例外清单(批末仍在族字面量穷举,共 43+2 处) + +| 类 | 量 | 明细 | +|---|---|---| +| 存档键引号字面量 | 43 | `aux_detail`×30 · `aux_items`×11(断点快照键+冒烟夹具键)· `aux_cleared`×10·`aux_cleared_last`×1(含信号文档注释提及)· `bonus_aux_carry`×3 · `attunement_charges`×2 | +| 冒烟夹具数据值 | 2 | smoke_all.gd `:4473/:4496` `"aux_scout"`(断点快照夹具 item_id,整块零触碰) | +| game/README.md §4.4 禁改项 | 1 | `:538` 历史 changelog 行文(§1.2 判定 2 唯一余量,非玩家可见) | +| registry 条目键 | 库外 | `design/registry/entities.yaml` `aux_items` 条目键沿用(数据契约) | +| 裸词 `aux`/`attunement_*` | 库外 | 裸 `aux` 局部变量与注释词(无 `aux_` 族 token 形态,出口 grep 族外);`attunement_*` 系同调位 DND 机制名(秘宝.md v0.9 明令保留) | + +## 六、代拍板追认单(白名单内 5 项,请追认) + +1. **词根选型 `treasure_*` 全族**:`treasure_item`(域串)/`treasure_items`(表+注册键+变量)/`TreasureItemTable`/`TreasureItems`/`treasure_items.tres`/`treasure_item_table.gd`/`treasure_items.gd`/`treasure_interact_controller.gd`。依据:任务书组 B 预设建议词根 + 全仓 `treasure` 零冲突(局内奇物 `curio_*`/`feat_*` 无碰撞)。 +2. **诊断码 `reward_dangling_aux` → `reward_dangling_treasure`**(config_db_cross_validator + 测试双端)。依据:§4.0 判据(指向秘宝概念)、R3 文案可变行为不变。 +3. **`aux_unlocked` params 键族改 `treasure_unlocked`**(main/adventure_runner/smoke/breakpoint_resume_test 四端同步)。依据:已核实该键=main.gd 现场构造的进程内 params 键,**不入任何存档**(§4.1 判据只锁跨局持久化键)。 +4. **呈现与结算 token 全族**:`aux_inventory→treasure_inventory`、`aux_mark→treasure_mark`、`_aux_reveal/_aux_preview→_treasure_*`、`aux_slot_clicked→treasure_slot_clicked`、`set_aux_inventory/set_aux_overlays→set_treasure_*`、`use_aux→use_treasure`、`aux_replace_presented→treasure_replace_presented`、`aux_replace`(autoplay 事件日志键)→`treasure_replace`、`_aux→_treasure_ui`、`AuxInteractController→TreasureInteractController` 等。依据:§4.0 判据+白名单词形自由。 +5. **三处注释/错误文案换词**:meta_table.gd:88 校验错误消息(「出域秘宝六件词表」)、treasure_items.gd/treasure_item_table.gd 头注 registry 键提及换「秘宝条目(键 aux_items 沿用)」、treasure_interact_controller:11 注释类名引用同步。依据:R3 文案可变。 + +**非代拍、按硬边界执行**:`game/README.md:538` 未改(§4.4 明令 + 换名先例「历史留痕原样保留」)——若你要它也清零,一句话即补。 + +## 七、挂账与移交 + +1. **渲染像素类闸补跑**(已挂 07⑮):迭代 14 全落籍后表现批周期闸一次性补跑五件。 +2. **实机目检**(已挂 07⑮):「秘宝」字样全 UI 面——C 区槽位标题+悬停 tooltip+战斗总结叙述行+上关清空 toast。 +3. **reward_overlay_test 基线红**:②批遗留(选择态三卡 btns=0),本批未触碰其域,**归属 ②批收口方处置**;读数已录本报告 §二。 +4. **存档键正式迁移**(②批待裁点):本批未动任何键名,②批若启动迁移与本批无冲突(键字面量=本批保护面)。 + +## 八、并行协调与合并实录 + +1. **合并前停机点(goal 令履行)**:batch 末查得 master 已推进 85dc9af(迭代14①收窄批落籍)且新在飞 worktree m4iter14-skillpool(④技能池批)——四文件重叠(battle_orchestrator/adventure_runner/level_runner/main.gd),按 goal 令停机提问三选一;**用户裁「我先合,对方 rebase」**。 +2. **第一轮 master 并入**(85dc9af):07 清单⑬双登冲突(收窄批⑬保留,本批目检项改⑭);smoke_all.gd/roadmap auto-merge;合并后全查零旧词带入。 +3. **局面变化**:技能池批未等本批,先自落籍 master(d3fa887,冒烟 772/0);用户令继续并提示防冲突。 +4. **第二轮 master 并入**(d3fa887):07 清单⑭双登冲突(技能池⑭保留,本批目检项改⑮);四重叠文件 auto-merge **零旧词带入**(全查仅存档键合法例外——技能池批新增行不在 aux 词族区);认证电池复跑(--import+冒烟+run_all+四探针)。 +5. **经验注记**:并行双批各自在旧词族/新词族上开发时,auto-merge 静默带入旧词的风险真实存在;本批合并后全仓 token 级 grep 复查是必要闸,不能只看 git 冲突标记。 diff --git a/design/research/任务书-秘宝代码词族对齐批-2026-10-05.md b/design/research/任务书-秘宝代码词族对齐批-2026-10-05.md index bb4b8a31..8ee98aa4 100644 --- a/design/research/任务书-秘宝代码词族对齐批-2026-10-05.md +++ b/design/research/任务书-秘宝代码词族对齐批-2026-10-05.md @@ -28,6 +28,8 @@ | 5 | 收口五步 | active.md 快照 / 台账条目 / roadmap 里程碑行 / stage.txt(如变)/ 闸序列留痕 | > ⚠️ **基线纪律**:迭代 15 调试整合批已把冒烟推进到 **747 项**。本批开工前必须重测基线取实际值(本任务书不写死数字,T0 复核后回填),**禁止用本文档的历史数字当闸门**。 +> +> ✅ **T0 回填(2026-10-05 实测,主区 3c4291d 实跑)**:冒烟基线 = **755 项 / 0 失败**(§1.2 的 747 与判式批出口 750 均系②批前旧数,作废);run_all = 15 套件 14 绿,唯一红 = `reward_overlay_test.gd`(**② 奇物批遗留基线红**,与本批无关,对照口径=零新增);词族实数 = **364 处 / 36 文件**(§2 F1 的 358 处系②批前口径);`treasure_*` 词根全仓零冲突;§4.1 六存档键引用普查 HEAD↔批末逐键零差异。 ## 2. 现状事实(代码级,T0 须自行复核) diff --git a/game/core/action_economy.gd b/game/core/action_economy.gd index a88ad4aa..684d3da5 100644 --- a/game/core/action_economy.gd +++ b/game/core/action_economy.gd @@ -177,7 +177,7 @@ func notify_settlement_done(next_round_mode: String) -> bool: # 下轮行动点修正排队(格面资源八型批 2026-09-20):action 型正负行结算期调用,同轮多次授予累加; # 相位无关(授予发生在结算段,此时本类可能处于 ACTIVE/WAITING 任一相位) -# 第 9 API(registry 行动经济×① 接口漂移预授权——迭代 7 T2 魔法道具内容批落位):ap_grant 道具的 +# 第 9 API(registry 行动经济×① 接口漂移预授权——迭代 7 T2 秘宝内容批落位):ap_grant 道具的 # 当轮行动点加量(GDD「加行动点效果给当轮」——区别于 queue_ap_delta 的下轮排队语义)。Active 受理、 # 无上限域、零随机;使用道具本身零扣费(成本在获取时已付——捡道具格不出战斗奖励)。 func grant_ap(amount: int) -> bool: diff --git a/game/core/adventure_runner.gd b/game/core/adventure_runner.gd index fe300572..561a5795 100644 --- a/game/core/adventure_runner.gd +++ b/game/core/adventure_runner.gd @@ -43,7 +43,7 @@ extends RefCounted signal level_started(level_index: int, display_name: String) # 每关开始(含冒险首关)——呈现层重取 runner()、刷新图条与层名行 signal bonus_choice_presented(payload: Dictionary) # 提升三选一停点(非末关通关恰一次;迭代 10 大奖励重构——big_reward_paid 退役)——{level_index, candidates, heal_gained, hp_before, hp_after, keystone_gained, keystone_total, gp, aux_cleared} signal bonus_resolved(result: Dictionary) # 三选一兑付完成(pick_bonus/替换受理后恰一次)——{picked, value, hp_before, hp_after, level_index} -signal aux_replace_presented(items: Array, incoming: Dictionary) # 同调位满位替换子交互(pick_bonus 道具件满位时)——items=现有持有件记录、incoming=新件记录 +signal treasure_replace_presented(items: Array, incoming: Dictionary) # 同调位满位替换子交互(pick_bonus 道具件满位时)——items=现有持有件记录、incoming=新件记录 signal adventure_finished(summary: Dictionary) # 冒险结算(completed/failed/abandoned)——summary 五件事:打穿没有/通关几关/止步第几关/钥石合计/主种子(+additive keystone_drops 迭代 10) # ---- 转发族(签名与 LevelRunner 同款——呈现层对接透明;ADR-0001 S6 经 _forward_* 方法)---- signal node_entered(node: Dictionary, info: Dictionary) @@ -70,12 +70,12 @@ var _last_level_payload := {} # 最近一次关卡结束载荷(失 var _override := [0, 0] # 调试浮窗百分比通道 [atk_pct, hp_pct](每关新 runner 都要应用) var _base_override := {"atk": 0, "max_hp": 0, "armor_class": 0} var _first_script := false # 首次脚本模式(关卡节点图生成 v0.4——true = 全关零抽签取池内模板 0;测量夹具恒 false) # 永久强化 flat 注入(元进度实现批——冒险开始参数面 params.hero_override 存入,共享给 LevelRunner;全零 = 白板) -var _last_aux_cleared := 0 # additive(迭代 7 T4——最近一次关卡末清空计数,summary 取数面) -var _aux_unlocked := {} # aux 解锁门控集(迭代 7 T5——params.aux_unlocked 接收面) +var _last_treasure_cleared := 0 # additive(迭代 7 T4——最近一次关卡末清空计数,summary 取数面) +var _treasure_unlocked := {} # aux 解锁门控集(迭代 7 T5——params.treasure_unlocked 接收面) var _attunement: Array = [] # 同调装配集(迭代 11 第①批 T5——params.attunement 接收面,start_level 外下传 LevelRunner) var _attune_refresh_x := 0 # 刷新件余量(迭代 11 第①批 T5b P1 甲——每碰三选一重置=X 表值;优先消耗、不结转) var _attune_refresh_y := 0 # Y 冒险周期池(开局参数面注入,用完即无——营地升级行表值) -var attune_charges := {} # 同调主动件冒险充能账本(迭代 11 第①批 T6——跨关卡共享 dict;settlement use_aux 扣减直改同引用;断点随 attunement_charges 键入档) +var attune_charges := {} # 同调主动件冒险充能账本(迭代 11 第①批 T6——跨关卡共享 dict;settlement use_treasure 扣减直改同引用;断点随 attunement_charges 键入档) var _save_manager = null # 断点承载注入(迭代 8 卡①——null = 不写断点;模拟/冒烟缺省) var _resume_bp := {} # 续玩快照暂存(resume_adventure → _start_current_level 单跳传递) # ---- 三选一停点态(迭代 10 奖励重构批)---- @@ -85,9 +85,9 @@ var _relics: Array[String] = [] # 特性持有集(迭代 12 T1—— var _tree_rules: Array = [] # 树 rule 键集(迭代 12 T10——Fork 激活侧 effects 透传;下传 enc.tree_rules 消费面) var _bonus_pending := {} # 停点态:{"candidates": Array, "payload": Dictionary, "chosen"/"incoming": 替换在途}——空 = 无停点 var _bonus_result := {} # 已兑付待推进态(bonus_resolved 载荷副本——中断续玩不重兑付) -var _bonus_aux_carry: Array[String] = [] # 道具件跨关携带(兑付后注入下一关库存——清库后授予的体验窗) +var _bonus_treasure_carry: Array[String] = [] # 道具件跨关携带(兑付后注入下一关库存——清库后授予的体验窗) var _keystone_drops: Array = [] # Boss 逐杀掉落明细(additive 摘要键 keystone_drops——结算明细/复盘归因数据源) -var _last_draw_aux: Array[String] = [] # 最近一次抽签掷定的道具件(掷定前置——卡片直显具体道具;追加批二) +var _last_draw_treasure: Array[String] = [] # 最近一次抽签掷定的道具件(掷定前置——卡片直显具体道具;追加批二) var _node_bonus_pending := {} # 奖励节点三选一停点态(迭代 10 追加批——共享池;断点不载:续玩重建到选路停点重走,恢复的计数器保证同候选重抽) var _shop_mode := "legacy" # 商店模式(迭代 11 第②批 T3——"legacy"=固定三件加定价〔off 对照承载,缺省零扰动〕/"pool"=共享池抽 3 买 1 重抽;真实入口 main.gd 显式投 pool) @@ -121,7 +121,7 @@ func start_adventure(seed_val: int, params: Dictionary = {}) -> bool: _base_override = _normalize_override(params.get("hero_override", {})) _first_script = bool(params.get("first_script", false)) # 缺省 = 非首次(抽签路径;真实侧由呈现层读存档布尔位传入) _shop_mode = "pool" if String(params.get("shop_mode", "legacy")) == "pool" else "legacy" # 迭代 11 第②批 T3——缺省 legacy(off 对照零扰动) - _aux_unlocked = params.get("aux_unlocked", {}) if params.get("aux_unlocked", {}) is Dictionary else {} + _treasure_unlocked = params.get("treasure_unlocked", {}) if params.get("treasure_unlocked", {}) is Dictionary else {} _attunement = params.get("attunement", []) if params.get("attunement", []) is Array else [] # additive(迭代 11 第①批 T5) _attune_refresh_y = maxi(0, int(params.get("attune_refresh_y", 0))) # additive(迭代 11 第①批 T5b——Y 冒险周期池) _seed_attune_charges() # 迭代 11 第①批 T6——冒险开始充能账本按装备主动件重置(每冒险充能语义) # additive(迭代 7 T5) @@ -195,7 +195,7 @@ func resume_adventure(bp: Dictionary, params: Dictionary = {}) -> bool: for r in (bp.get("relics", []) as Array): _relics.append(String(r)) for v in (bp.get("bonus_aux_carry", []) as Array): - _bonus_aux_carry.append(String(v)) + _bonus_treasure_carry.append(String(v)) _keystone_drops = (bp.get("keystone_drops", []) as Array).duplicate(true) _base_override = _normalize_override(params.get("hero_override", {})) # 生命账本越界钳制(T17——spawn 守卫 EC16 免疫):断点可能由旧口径版本写出(如调试上限 @@ -207,7 +207,7 @@ func resume_adventure(bp: Dictionary, params: Dictionary = {}) -> bool: int(round(float(int(db.hero.max_hp) + int(_base_override.get("max_hp", 0))) * (100.0 + float(_override[1])) / 100.0)))) _first_script = false # 续玩模板已随快照强制(已抽模板零重抽)——脚本模式不重放 _shop_mode = "pool" if String(params.get("shop_mode", "legacy")) == "pool" else "legacy" # 迭代 11 第②批 T3——续玩参数面同 start_adventure(缺省 legacy) - _aux_unlocked = params.get("aux_unlocked", {}) if params.get("aux_unlocked", {}) is Dictionary else {} + _treasure_unlocked = params.get("treasure_unlocked", {}) if params.get("treasure_unlocked", {}) is Dictionary else {} _attunement = params.get("attunement", []) if params.get("attunement", []) is Array else [] # additive(迭代 11 第①批 T5) _attune_refresh_y = maxi(0, int(params.get("attune_refresh_y", 0))) # additive(迭代 11 第①批 T5b——Y 冒险周期池) _seed_attune_charges() # 迭代 11 第①批 T6——冒险开始充能账本按装备主动件重置(每冒险充能语义) @@ -228,13 +228,13 @@ func resume_adventure(bp: Dictionary, params: Dictionary = {}) -> bool: _bonus_pending["aux_detail"] = (bp_pending.get("aux_detail", []) as Array).duplicate(true) # 掷定前置随停点快照续接 var payload: Dictionary = (bp_pending.get("payload", {}) as Dictionary).duplicate(true) if bp_pending.has("incoming"): - _bonus_pending["chosen"] = "aux_item" + _bonus_pending["chosen"] = "treasure_item" var incoming: Array = (bp_pending.get("incoming", []) as Array).duplicate(true) _bonus_pending["incoming"] = incoming state = "running" bonus_choice_presented.emit(payload) # 替换在途续发(呈现层直落替换子态——持有件记录按恢复后 carry 重建) - aux_replace_presented.emit(_carry_records(), + treasure_replace_presented.emit(_carry_records(), {"index": -1, "item_id": String(incoming[0]) if not incoming.is_empty() else "", "count": incoming.size()}) return true state = "running" @@ -262,7 +262,7 @@ func _reset_bonus_state() -> void: _relics = [] _bonus_pending = {} _bonus_result = {} - _bonus_aux_carry = [] + _bonus_treasure_carry = [] _keystone_drops = [] _node_bonus_pending = {} @@ -363,8 +363,8 @@ func pick_bonus(kind: String, tier: String = "", relic_id: String = "") -> bool: return false var value: int = int(db.adventure.feature_value(kind, tier)) var hp_before := int(ledger.get("hero_hp", 0)) - if kind == "aux_item": - return _pick_aux_item(value) # 道具件分派通关渠道(持有容器 = 跨关携带——与节点渠道分轨;池种退役后不可达) + if kind == "treasure_item": + return _pick_treasure_item(value) # 道具件分派通关渠道(持有容器 = 跨关携带——与节点渠道分轨;池种退役后不可达) if not _apply_bonus_pick(kind, tier, value, relic_id): push_error("[冒险结构] pick_bonus 拒绝——未知件: %s|%s|%s" % [kind, tier, relic_id]) return false @@ -473,41 +473,41 @@ func _pool_stock_snapshot() -> Dictionary: return out -# 道具件兑付(同调位约束):有位直接入跨关携带;满位转替换子交互(incoming 暂存、等 resolve_aux_replace)。 -# 掷定前置(追加批二):具体道具随候选抽定(_last_draw_aux / _bonus_pending.aux_detail)——本函数消费预掷值, +# 道具件兑付(同调位约束):有位直接入跨关携带;满位转替换子交互(incoming 暂存、等 resolve_treasure_replace)。 +# 掷定前置(追加批二):具体道具随候选抽定(_last_draw_treasure / _bonus_pending.aux_detail)——本函数消费预掷值, # 断点续玩/无预掷值时回退当场掷定(流序不同但消费数不变,确定性由调用序保证)。 -# 持有容器 = 跨关携带 _bonus_aux_carry(与节点渠道的关卡域库存分轨——容器差异保守不合,注记在案)。 -func _pick_aux_item(count: int) -> bool: - var picked: Array = _draw_pending_aux(_bonus_pending, count, true) +# 持有容器 = 跨关携带 _bonus_treasure_carry(与节点渠道的关卡域库存分轨——容器差异保守不合,注记在案)。 +func _pick_treasure_item(count: int) -> bool: + var picked: Array = _draw_pending_treasure(_bonus_pending, count, true) if picked.is_empty(): - push_error("[冒险结构] pick_bonus(aux_item) 拒绝——解锁道具池空集(白板/门控态不入牌库的防御兜底)") + push_error("[冒险结构] pick_bonus(treasure_item) 拒绝——解锁道具池空集(白板/门控态不入牌库的防御兜底)") return false var hp_before := int(ledger.get("hero_hp", 0)) # 迭代 11 第①批 T7——同调位守卫随过渡键退役拆除(aux 卡出池后本路径不可达;能力件容量闸 # 正主 = 营地装配面 Attunement.slots 满位禁选) for iid in picked: - _bonus_aux_carry.append(String(iid)) - _finish_bonus_pick("aux_item", picked.size(), hp_before) + _bonus_treasure_carry.append(String(iid)) + _finish_bonus_pick("treasure_item", picked.size(), hp_before) return true # 替换子交互受理(discard_index = -1 放弃新件不获取;否则丢该件腾位收新)——终态恒 ≤ 同调位 # 持有容器 = 跨关携带(序号寻址);与节点渠道(库存句柄寻址)的丢弃/授予/收尾三步保守不合。 -func resolve_aux_replace(discard_index: int) -> bool: +func resolve_treasure_replace(discard_index: int) -> bool: if not _replace_in_transit(_bonus_pending): - push_error("[冒险结构] resolve_aux_replace 拒绝——无替换在途") + push_error("[冒险结构] resolve_treasure_replace 拒绝——无替换在途") return false var incoming: Array = _bonus_pending.get("incoming", []) as Array var hp_before := int(ledger.get("hero_hp", 0)) if discard_index >= 0: - if discard_index >= _bonus_aux_carry.size(): - push_error("[冒险结构] resolve_aux_replace 拒绝——序号不在持有集: %d" % discard_index) + if discard_index >= _bonus_treasure_carry.size(): + push_error("[冒险结构] resolve_treasure_replace 拒绝——序号不在持有集: %d" % discard_index) return false - _bonus_aux_carry.remove_at(discard_index) + _bonus_treasure_carry.remove_at(discard_index) for iid in incoming: - _bonus_aux_carry.append(String(iid)) + _bonus_treasure_carry.append(String(iid)) # 放弃新件(discard_index < 0)= 原持有集不动、新件不获取 - _finish_bonus_pick("aux_item", incoming.size(), hp_before) + _finish_bonus_pick("treasure_item", incoming.size(), hp_before) return true @@ -535,12 +535,12 @@ func _finish_bonus_pick(picked: String, value: int, hp_before: int, tier: String # 掷定前置(追加批二):返回 dict 带 aux_detail(道具件具体道具)供卡片直显。 func node_bonus_candidates() -> Dictionary: var cands: Array = _draw_bonus_candidates() - return {"candidates": cands, "aux_detail": _last_draw_aux.duplicate()} + return {"candidates": cands, "aux_detail": _last_draw_treasure.duplicate()} -func present_node_bonus(candidates: Array, aux_detail: Array = []) -> void: +func present_node_bonus(candidates: Array, treasure_detail: Array = []) -> void: _reset_refresh_x() # 迭代 11 第①批 T5b——碰三选一重置 X 余量(不结转) - _node_bonus_pending = {"candidates": candidates.duplicate(true), "aux_detail": aux_detail.duplicate(true)} + _node_bonus_pending = {"candidates": candidates.duplicate(true), "aux_detail": treasure_detail.duplicate(true)} # 点选兑付(节点域——无部分回血无钥石;令牌消费与牌库摘牌与通关三选一同库;relic 同权入持有集) @@ -553,8 +553,8 @@ func apply_node_bonus(kind: String, tier: String = "", relic_id: String = "") -> push_error("[冒险结构] apply_node_bonus 拒绝——令牌不在候选: %s|%s|%s" % [kind, tier, relic_id]) return false var value: int = int(db.adventure.feature_value(kind, tier)) - if kind == "aux_item": - return _apply_node_aux(value) # 道具件分派节点渠道(持有容器 = 关卡域库存——与通关渠道分轨;池种退役后不可达) + if kind == "treasure_item": + return _apply_node_treasure(value) # 道具件分派节点渠道(持有容器 = 关卡域库存——与通关渠道分轨;池种退役后不可达) if not _apply_bonus_pick(kind, tier, value, relic_id): push_error("[冒险结构] apply_node_bonus 拒绝——未知件: %s|%s|%s" % [kind, tier, relic_id]) return false @@ -565,22 +565,22 @@ func apply_node_bonus(kind: String, tier: String = "", relic_id: String = "") -> # 节点渠道道具件(同调位约束):持有=关卡域库存+跨关携带,有位直接入本关库存(当关可用); # 满位转替换子交互(丢弃目标=库存件 handle——与通关渠道的 carry 序号分轨,容器语义保守不合)。 # 掷定前置:消费 _node_bonus_pending.aux_detail 预掷值(缺省回退当场掷定)。 -func _apply_node_aux(count: int) -> bool: - var picked: Array = _draw_pending_aux(_node_bonus_pending, count, false) +func _apply_node_treasure(count: int) -> bool: + var picked: Array = _draw_pending_treasure(_node_bonus_pending, count, false) if picked.is_empty(): - push_error("[冒险结构] apply_node_bonus(aux_item) 拒绝——解锁道具池空集(白板/门控态不入牌库的防御兜底)") + push_error("[冒险结构] apply_node_bonus(treasure_item) 拒绝——解锁道具池空集(白板/门控态不入牌库的防御兜底)") return false var records: Array = [] - if _runner != null and _runner.aux_inventory != null: - records = _runner.aux_inventory.holding_records() - # 迭代 11 第①批 T7——守卫随过渡键退役拆除(FEATURE_KINDS 已除名 aux_item,本分支不可达; + if _runner != null and _runner.treasure_inventory != null: + records = _runner.treasure_inventory.holding_records() + # 迭代 11 第①批 T7——守卫随过渡键退役拆除(FEATURE_KINDS 已除名 treasure_item,本分支不可达; # 替换子交互路由随容量闸一并退役——能力件容量闸正主 = 营地装配面满位禁选) if _runner != null: for iid in picked: - var rec: Dictionary = _runner.grant_aux_item(String(iid), "reward_node") + var rec: Dictionary = _runner.grant_treasure_item(String(iid), "reward_node") if rec.is_empty(): push_warning("[冒险结构] 奖励节点道具授予被拒(防御兜底留痕): %s" % String(iid)) - _finish_node_bonus("aux_item", picked.size()) + _finish_node_bonus("treasure_item", picked.size()) return true @@ -590,15 +590,15 @@ func _resolve_node_replace(discard_handle: int) -> bool: return false var incoming: Array = _node_bonus_pending.get("incoming", []) as Array if discard_handle >= 0: - if _runner == null or _runner.aux_inventory == null or not _runner.aux_inventory.discard_item(discard_handle): + if _runner == null or _runner.treasure_inventory == null or not _runner.treasure_inventory.discard_item(discard_handle): push_error("[冒险结构] resolve_node_replace 拒绝——句柄不在持有集: %d" % discard_handle) return false for iid in incoming: - var rec: Dictionary = _runner.grant_aux_item(String(iid), "reward_node") + var rec: Dictionary = _runner.grant_treasure_item(String(iid), "reward_node") if rec.is_empty(): push_warning("[冒险结构] 替换子道具授予被拒(防御兜底留痕): %s" % String(iid)) # 放弃新件(discard_handle < 0)= 原持有集不动、新件不获取 - _finish_node_bonus("aux_item", incoming.size()) + _finish_node_bonus("treasure_item", incoming.size()) return true @@ -606,7 +606,7 @@ func _resolve_node_replace(discard_handle: int) -> bool: func _seed_attune_charges() -> void: attune_charges = {} for iid in _attunement: - var arow: Dictionary = db.aux_item_row(String(iid)) + var arow: Dictionary = db.treasure_item_row(String(iid)) if String(arow.get("form", "")) == "active_charged": attune_charges[String(iid)] = maxi(0, int(arow.get("charges_per_adventure", 0))) @@ -616,7 +616,7 @@ func _seed_attune_charges() -> void: # 达上限剔牌/掷定前置直显;停点可中断)---- func _attune_refresh_x_total() -> int: - return int(db.aux_item_row("pick_refresh").get("magnitude", 0)) if _attunement.has("pick_refresh") else 0 + return int(db.treasure_item_row("pick_refresh").get("magnitude", 0)) if _attunement.has("pick_refresh") else 0 func _reset_refresh_x() -> void: @@ -648,10 +648,10 @@ func refresh_bonus() -> bool: _attune_refresh_y -= 1 var cands: Array = _draw_bonus_candidates() _bonus_pending["candidates"] = cands.duplicate(true) - _bonus_pending["aux_detail"] = _last_draw_aux.duplicate() + _bonus_pending["aux_detail"] = _last_draw_treasure.duplicate() var payload: Dictionary = (_bonus_pending.get("payload", {}) as Dictionary).duplicate(true) payload["candidates"] = cands - payload["aux_detail"] = _last_draw_aux.duplicate() + payload["aux_detail"] = _last_draw_treasure.duplicate() bonus_choice_presented.emit(payload) # 同信号重 present(零自动推进契约不破——停点仍在途) _snapshot_breakpoint() return true @@ -662,34 +662,34 @@ func refresh_bonus() -> bool: _attune_refresh_y -= 1 var cands2: Array = _draw_bonus_candidates() _node_bonus_pending["candidates"] = cands2.duplicate(true) - _node_bonus_pending["aux_detail"] = _last_draw_aux.duplicate() + _node_bonus_pending["aux_detail"] = _last_draw_treasure.duplicate() return true return false -# 替换在途守卫(2026-10-02 修复批——双渠道替换受理的共用前置谓词:停点态非空且 chosen=aux_item) +# 替换在途守卫(2026-10-02 修复批——双渠道替换受理的共用前置谓词:停点态非空且 chosen=treasure_item) func _replace_in_transit(pending: Dictionary) -> bool: - return not pending.is_empty() and String(pending.get("chosen", "")) == "aux_item" + return not pending.is_empty() and String(pending.get("chosen", "")) == "treasure_item" -# 双渠道道具件掷定共享体(2026-10-02 修复批——_pick_aux_item/_apply_node_aux 复制债收口一步): +# 双渠道道具件掷定共享体(2026-10-02 修复批——_pick_treasure_item/_apply_node_treasure 复制债收口一步): # 解锁道具池空集守卫 + N 件掷定(先消费停点预掷 aux_detail,不足部分当场经 reward_pick 封闭流补掷—— # 取数序与拆分前逐位一致)。返回空数组 = 池空集(调用方按渠道名报错)。 -# 保守不合处:通关渠道允许回退 _last_draw_aux(allow_detail_fallback)、节点渠道不回退——掷定回退 +# 保守不合处:通关渠道允许回退 _last_draw_treasure(allow_detail_fallback)、节点渠道不回退——掷定回退 # 语义渠道各异,参数化保留差异;持有容器与兑付收尾仍归调用方渠道。 -func _draw_pending_aux(pending: Dictionary, count: int, allow_detail_fallback: bool) -> Array: - var pool: Array = _bonus_aux_pool() +func _draw_pending_treasure(pending: Dictionary, count: int, allow_detail_fallback: bool) -> Array: + var pool: Array = _bonus_treasure_pool() if pool.is_empty(): return [] var picked: Array = [] var detail: Array = (pending.get("aux_detail", []) as Array).duplicate() if detail.is_empty() and allow_detail_fallback: - detail = _last_draw_aux.duplicate() + detail = _last_draw_treasure.duplicate() for i in maxi(1, count): if i < detail.size(): picked.append(String(detail[i])) else: - picked.append(_roll_bonus_aux_item(pool)) + picked.append(_roll_bonus_treasure_item(pool)) return picked @@ -697,7 +697,7 @@ func _draw_pending_aux(pending: Dictionary, count: int, allow_detail_fallback: b func resolve_bonus_replace(discard: int) -> bool: if not _node_bonus_pending.is_empty() and _node_bonus_pending.has("incoming"): return _resolve_node_replace(discard) - return resolve_aux_replace(discard) + return resolve_treasure_replace(discard) func _finish_node_bonus(picked: String, value: int, tier: String = "", relic_id: String = "") -> void: @@ -718,9 +718,9 @@ func _finish_node_bonus(picked: String, value: int, tier: String = "", relic_id: # kind 出现率∝剩余令牌数〔档位配额即分布——无独立权重 knob〕;抽签不摘牌、兑付才摘牌=未选 # 自动回池;池耗即枯竭——余库不足 N kind 时出齐剩余,空库 = 零候选合法态)。候选 = 令牌字典 # {"kind","tier"}。消费 reward_pick 封闭流——一次停点恰一 scope,同种子同候选;道具件掷定前置 -# 随池种退役拆除(_last_draw_aux 恒空集,机械惰性承载)。 +# 随池种退役拆除(_last_draw_treasure 恒空集,机械惰性承载)。 func _draw_bonus_candidates() -> Array: - _last_draw_aux = [] + _last_draw_treasure = [] var pool := _bonus_deck.duplicate() var rg: RandomNumberGenerator = rng.open_stream("reward_pick") for i in pool.size(): @@ -745,29 +745,29 @@ func _draw_bonus_candidates() -> Array: func _roll_from(rg: RandomNumberGenerator) -> String: - var pool: Array = _bonus_aux_pool() + var pool: Array = _bonus_treasure_pool() return String(pool[rg.randi_range(0, pool.size() - 1)]) # 三选一道具件随机池(与投放门控同源:aux 活行 ∩ 解锁门控集——空集 = 道具件不入牌库) -func _bonus_aux_pool() -> Array: +func _bonus_treasure_pool() -> Array: var out: Array = [] - var live: Dictionary = db.aux_live_ids() + var live: Dictionary = db.treasure_live_ids() for iid in live.keys(): - if _aux_unlocked.has(String(iid)): + if _treasure_unlocked.has(String(iid)): out.append(String(iid)) return out -func _roll_bonus_aux_item(pool: Array) -> String: +func _roll_bonus_treasure_item(pool: Array) -> String: var rg: RandomNumberGenerator = rng.open_stream("reward_pick") return String(pool[rg.randi_range(0, pool.size() - 1)]) func _carry_records() -> Array: var out: Array = [] - for i in _bonus_aux_carry.size(): - out.append({"index": i, "item_id": _bonus_aux_carry[i]}) + for i in _bonus_treasure_carry.size(): + out.append({"index": i, "item_id": _bonus_treasure_carry[i]}) return out @@ -837,11 +837,11 @@ func _start_current_level() -> bool: # 注入面随停点渠道退役拆除(容器字段保留=替换子交互机械惰性承载,零投放零行为) level_started.emit(level_index, String(_runner.level_row.get("display_name", ""))) # 入口停点断点(node_id=-1)与 defer_entry 同态(node_index=-1+单候选)——走入口呈现; - # 中途停点(node_id>=0)走停点呈现(restore_aux_items 先于呈现=C 区库存就位)。 + # 中途停点(node_id>=0)走停点呈现(restore_treasure_items 先于呈现=C 区库存就位)。 if resume_state.is_empty() or int(resume_state.get("node_id", -1)) < 0: _runner.present_entry_choice() else: - _runner.restore_aux_items(_resume_bp.get("aux_items", []) as Array) + _runner.restore_treasure_items(_resume_bp.get("aux_items", []) as Array) _runner.present_resumed_choice() _resume_bp = {} return ok @@ -861,7 +861,7 @@ func _on_level_finished(payload: Dictionary) -> void: if result != "victory": push_error("[冒险结构] 关卡结束结果出域: %s" % result) return - _last_aux_cleared = int(payload.get("aux_cleared", 0)) # additive(迭代 7 T4——末关 summary 取数面) + _last_treasure_cleared = int(payload.get("aux_cleared", 0)) # additive(迭代 7 T4——末关 summary 取数面) # Boss 钥石逐杀掉落(迭代 10——渠道改击杀掉落,末关照常入账;首杀/复杀读 meta.tres boss_keystone) _boss_keystone_drop(level_index) if level_index < levels_total: @@ -877,7 +877,7 @@ func _on_level_finished(payload: Dictionary) -> void: var pick_payload: Dictionary = { "level_index": level_index, "candidates": _draw_bonus_candidates(), - "aux_detail": _last_draw_aux.duplicate(), # 掷定前置(追加批二——道具件具体道具随候选抽定,卡片直显) + "aux_detail": _last_draw_treasure.duplicate(), # 掷定前置(追加批二——道具件具体道具随候选抽定,卡片直显) "heal_gained": heal, "hp_before": hp_before, "hp_after": int(ledger.get("hero_hp", 0)), @@ -887,7 +887,7 @@ func _on_level_finished(payload: Dictionary) -> void: "aux_cleared": int(payload.get("aux_cleared", 0)), # additive 扩签(迭代 7 T4——关卡末清空反馈取数) } _bonus_pending = {"candidates": (pick_payload["candidates"] as Array).duplicate(true), - "aux_detail": _last_draw_aux.duplicate(), + "aux_detail": _last_draw_treasure.duplicate(), "payload": pick_payload.duplicate(true)} bonus_choice_presented.emit(pick_payload) _snapshot_breakpoint() # 选择停点可中断(契约 5——续玩不重抽不静默丢失) @@ -905,7 +905,7 @@ func _settle(result: String) -> void: "stopped_at": 0 if result == "completed" else level_index, "keystone_total": keystone, "master_seed": master_seed, - "aux_cleared_last": _last_aux_cleared, # additive 扩签(迭代 7 T4——末关清空反馈;非末关走 bonus 载荷) + "aux_cleared_last": _last_treasure_cleared, # additive 扩签(迭代 7 T4——末关清空反馈;非末关走 bonus 载荷) "keystone_drops": _keystone_drops.duplicate(true), # additive 扩签(迭代 10——逐杀掉落明细;settle 入账明细/复盘归因数据源) "pool_stock": _pool_stock_snapshot(), # additive 扩签(迭代 11 第②批 T5——终局池读数:清账前快照,商店买走 vs 奖励领走 vs 枯竭的终局面) "relics": _relics.duplicate(), # additive 扩签(迭代 12 T1——特性终局持有集:清账前快照,成型判读取数面) @@ -948,9 +948,9 @@ func _forward_choices_presented(candidates: Array) -> void: func _snapshot_breakpoint() -> void: if _save_manager == null or state != "running": return - var aux_items: Array = [] - if _runner != null and _runner.aux_inventory != null: - aux_items = _runner.aux_inventory.snapshot_inventory() + var treasure_snapshot: Array = [] + if _runner != null and _runner.treasure_inventory != null: + treasure_snapshot = _runner.treasure_inventory.snapshot_inventory() # 三选一停点续玩分支 _runner 为 null(关卡已收束、下一关未开)——节点域字段按缺省落档, # 该两态的续玩只消费 bonus_* 附随件(选择停点/已兑付停点快照,迭代 10) var bp: Dictionary = { @@ -973,13 +973,13 @@ func _snapshot_breakpoint() -> void: "rng_counter": rng.counter(), "keystone": keystone, "visited_ids": _runner.visited_ids() if _runner != null else [], - "aux_items": aux_items, + "aux_items": treasure_snapshot, "bonus_taken": _bonus_taken.duplicate(true), # 三选一件获取次数(kind 维度派生账本——断点附随件与读数承载) "bonus_deck": _bonus_deck.duplicate(true), # 令牌池余库(TP0 v2.2——池消耗即上限,续玩余库逐枚还原) "relics": _relics.duplicate(), # 特性持有集(迭代 12 T1——局内随机渠道获得态续玩防丢失) "bonus_pending": _bonus_pending.duplicate(true), # 三选一停点态(空 = 无停点——选择停点可中断契约) "bonus_result": _bonus_result.duplicate(true), # 已兑付待推进态(空 = 无——中断续玩不重兑付) - "bonus_aux_carry": _bonus_aux_carry.duplicate(true), # 道具件跨关携带(注入前中断防静默丢失) + "bonus_aux_carry": _bonus_treasure_carry.duplicate(true), # 道具件跨关携带(注入前中断防静默丢失) "keystone_drops": _keystone_drops.duplicate(true), # 逐杀掉落明细(摘要归因续接——迭代 10) } _save_manager.set_breakpoint(bp) diff --git a/game/core/attunement.gd b/game/core/attunement.gd index 28685dca..5312b2c8 100644 --- a/game/core/attunement.gd +++ b/game/core/attunement.gd @@ -1,10 +1,10 @@ # VERTICAL SLICE - NOT FOR PRODUCTION # Validation Question: 同调位读数是否由「通关次数 + Boss 击杀数」经 attunement_growth.tres 谓词表 # 实时求值(Σ达成 grant clamp slot_cap),迭代 10 过渡键 transitional_sync_slots 得以退役(P0) -# Date: 2026-10-03(迭代 11 第①批 魔法道具同调实施批 T3——任务书 v1.1 §六 T3;设计权威底稿 proposal §2) +# Date: 2026-10-03(迭代 11 第①批 秘宝同调实施批 T3——任务书 v1.1 §六 T3;设计权威底稿 proposal §2) # 同调位求值服务:计数源组装(save 账本 → 计数字典)与实时求值,纯函数零副作用。 # 读数源切换(迭代 10 欠账③):装配面消费方(营地装配覆盖层 T4/冒险开始装配注入 T6)一律经本服务取 -# Slots;过渡键 adventure.transitional_sync_slots 的在途读取面(aux_items 持有上限 gate/战斗内沉没/ +# Slots;过渡键 adventure.transitional_sync_slots 的在途读取面(treasure_items 持有上限 gate/战斗内沉没/ # 停点替换交互/main 同调位呈现)系过渡渠道承载——T7 退役面切换时随渠道一并消亡(该批读数源切换的 # 正主落点,06 欠账③销账注记随 T7/T9)。过渡期切早 = off 态 MC 对 81000 锚添新扰动(fresh 档计数全零 # → Slots=0 ≠ 过渡键 1),违「attune=off 逐位一致」🔴 契约——故本服务先立、在途面 T7 切。 diff --git a/game/core/battle_orchestrator.gd b/game/core/battle_orchestrator.gd index 3eaf42d6..85da5281 100644 --- a/game/core/battle_orchestrator.gd +++ b/game/core/battle_orchestrator.gd @@ -50,7 +50,7 @@ var action_economy: ActionEconomy var _enemy_system: UnitContainer var _status_effects: StatusContainer var _reward_economy: RewardEconomy -var aux_inventory: AuxItems # 迭代 7 T3——LevelRunner 注入的关卡域库存引用; +var treasure_inventory: TreasureItems # 迭代 7 T3——LevelRunner 注入的关卡域库存引用; # 每战新建本类,库存不归本类所有——注入面 var _damage: DamageController # 伤害控制器(伤害管线单据化批 2026-09-24——单据唯一兑付管线) @@ -69,7 +69,7 @@ var _board_from_midround_refresh := false # 装板 provenance:轮内刷新换 var _flag_consumed := {} # 兑付资格以雷格实例为键(板级;换图重置) # 同调装配运行态(迭代 11 第①批 T5——begin_battle 经 enc.attunement 注入;off=空集全部效果零扰动) var attunement: Array = [] # 装备中同调件 item_id 集 -var _attune_charges_ref: Dictionary = {} # 充能账本共享引用(迭代 11 第①批 T6——use_aux 消费直改) +var _attune_charges_ref: Dictionary = {} # 充能账本共享引用(迭代 11 第①批 T6——use_treasure 消费直改) var _attune_bank := 0 # 掘进蓄能积点(battle 域——每 charge_n 安全格 +1 点) var _attune_safe_seen := 0 # 掘进蓄能 battle 域安全开格计数 # 特性运行态(迭代 12 T2——relic 持有集经 enc.relics 注入;求值旗注 damage_controller.relic_flags; @@ -85,9 +85,9 @@ func _attune_has(item_id: String) -> bool: return attunement.has(item_id) -# 装备件表值读取(magnitude/effective_rounds 等——AuxItemTable 行;未装配不读表) +# 装备件表值读取(magnitude/effective_rounds 等——TreasureItemTable 行;未装配不读表) func _attune_row(item_id: String) -> Dictionary: - return db.aux_item_row(item_id) if _attune_has(item_id) else {} + return db.treasure_item_row(item_id) if _attune_has(item_id) else {} func _attune_mag(item_id: String) -> int: @@ -242,7 +242,7 @@ func begin_battle(enc: Dictionary) -> bool: # 同调装配运行态注入(迭代 11 第①批 T5——enc.attunement 携带;off=空集零扰动。淬毒 N 注入 # 伤害控制器、偏运 N 注入地图战斗资源——均须先于首板 install) attunement = (enc.get("attunement", []) as Array).duplicate() - _attune_charges_ref = enc.get("attune_charges", {}) # 共享 dict 引用(level/adventure 同账本——use_aux 扣减直改) + _attune_charges_ref = enc.get("attune_charges", {}) # 共享 dict 引用(level/adventure 同账本——use_treasure 扣减直改) _attune_bank = 0 _attune_safe_seen = 0 _damage.attune_venom = _attune_mag("venom_edge") if _attune_has("venom_edge") else 0 @@ -318,8 +318,8 @@ func _install_new_board(during_round := false) -> bool: _board_from_midround_refresh = during_round # 轮内刷新装板 = 刷新图(清图奖励不发);常规换图/开战装板 = false _board_seq += 1 board_changed.emit() - if aux_inventory != null: - aux_inventory.retire_overlays() # 迭代 7 T3——叠加层随图消亡(换图/刷新图装板点;已花道具不返还) + if treasure_inventory != null: + treasure_inventory.retire_overlays() # 迭代 7 T3——叠加层随图消亡(换图/刷新图装板点;已花道具不返还) return true @@ -493,7 +493,7 @@ func _settle() -> void: # 掘进蓄能计数(迭代 11 同调批 T6——battle 域安全开格计数,每 charge_n 格积 1 点) if _attune_has("dig_charge"): _attune_safe_seen += 1 - var cn_b: int = int(db.aux_item_row("dig_charge").get("charge_n", 999)) + var cn_b: int = int(db.treasure_item_row("dig_charge").get("charge_n", 999)) if cn_b > 0 and _attune_safe_seen % cn_b == 0: _attune_bank += 1 elif evt.kind == "mine": @@ -619,22 +619,22 @@ func _relic_yield_adjust(snap: Dictionary, positive: bool) -> Dictionary: # 「动作 × 格型」矩阵的执行面:snap = 缓冲期冻结身份快照(cell_type = 该格装板期摇定的类型身份), # polarity 由动作决定(开安全格/标中旗 = positive,开雷格/标错旗 = negative), # 兑付行 = 奖励字典(类型, 极性)行。返回 true = percent 行实际生效(flat 行恒 false——兑付结果由行协议承载)。 -# ---- 魔法道具(use_aux 四步受理编排保留给同调主动件复用——迭代 11 第①批 T7:过渡授予路由 -# _grant_aux 随掉落/停点渠道退役拆除;能力件注入归 LevelRunner.set_attune_charges 骑库存面)---- +# ---- 秘宝(use_treasure 四步受理编排保留给同调主动件复用——迭代 11 第①批 T7:过渡授予路由 +# _grant_treasure 随掉落/停点渠道退役拆除;能力件注入归 LevelRunner.set_attune_charges 骑库存面)---- -# use_aux 四步受理(registry use_orchestration 规范序——唯一调用权归本类;序即原子: +# use_treasure 四步受理(registry use_orchestration 规范序——唯一调用权归本类;序即原子: # ① 相位 gate(Active——行动经济 phase getter)→ ② validate_use(目标校验读 排雷玩法 只读面,零消耗)→ # ③ 逐 kind 应用(顺序钉死:空间先、ap_grant 后——effect_kinds 列表序非运行时语义)→ ④ consume。 # 拒绝全部发生在 ①②(后两步合法输入下无失败路径);使用零 AP 成本(不经 try_spend)。 # 结算明细无道具行(GDD——效果即时可见:overlay 呈现+AP 条刷新;AP 过账本 grant_ap 走 _reject 面)。 -func use_aux(handle: int, target: Vector2i) -> Dictionary: - if aux_inventory == null: +func use_treasure(handle: int, target: Vector2i) -> Dictionary: + if treasure_inventory == null: return {"ok": false, "reason": "库存未接线"} if action_economy.phase != action_economy.PHASE_ACTIVE: return {"ok": false, "reason": "非挖掘期(使用窗口=Active)"} - var board: MinesweeperRules = minesweeper # 恒等包装退役(2026-10-02 修复批——use_aux 直引公有成员) - var v: Dictionary = aux_inventory.validate_use(handle, target, + var board: MinesweeperRules = minesweeper # 恒等包装退役(2026-10-02 修复批——use_treasure 直引公有成员) + var v: Dictionary = treasure_inventory.validate_use(handle, target, Vector2(board.width, board.height), func(c: Vector2i): return not board.is_revealed(c)) if not bool(v.ok): @@ -642,14 +642,14 @@ func use_aux(handle: int, target: Vector2i) -> Dictionary: # 掘进蓄能受理闸(迭代 11 同调批 T6——bank>0 才可发起,一行一点;积点不足拒绝零消耗) if String(v.item_id) == "dig_charge" and _attune_has("dig_charge"): if _attune_bank <= 0: - var cn_info: int = int(db.aux_item_row("dig_charge").get("charge_n", 0)) + var cn_info: int = int(db.treasure_item_row("dig_charge").get("charge_n", 0)) return {"ok": false, "reason": "掘进蓄能:安全格积点未达(%d/%d)" % [_attune_safe_seen % cn_info if cn_info > 0 else 0, cn_info]} _attune_bank -= 1 var kinds: Array = v.kinds if kinds.has("mine_reveal"): - aux_inventory.apply_overlay("mine_reveal", v.resolved) + treasure_inventory.apply_overlay("mine_reveal", v.resolved) if kinds.has("reward_preview"): - aux_inventory.apply_overlay("reward_preview", v.resolved) + treasure_inventory.apply_overlay("reward_preview", v.resolved) if kinds.has("ap_grant"): if not action_economy.grant_ap(int(v.magnitude)): return {"ok": false, "reason": "行动点加量被拒(相位防御)"} @@ -664,7 +664,7 @@ func use_aux(handle: int, target: Vector2i) -> Dictionary: var blasted: Array = board.remove_mines_in(v.resolved) if blasted.is_empty(): return {"ok": false, "reason": "爆破工兵包:3×3 区域内无可移除雷格(须未揭示且未插旗)"} - var rec: Dictionary = aux_inventory.consume(handle) + var rec: Dictionary = treasure_inventory.consume(handle) # 同调主动件充能扣减(迭代 11 第①批 T6——共享账本直改:adventure/level/settlement 同一字典引用) if not rec.is_empty() and String(rec.get("source_class", "")) == "attunement": var used_iid: String = String(rec.get("item_id", "")) @@ -674,12 +674,12 @@ func use_aux(handle: int, target: Vector2i) -> Dictionary: # aux 解锁门控转发(迭代 7 T5——LevelRunner 注入;E1/E3 封装:外部经公有面,禁直读 _reward_economy) -func set_aux_unlocked(ids: Dictionary) -> void: - _reward_economy.set_aux_unlocked(ids) +func set_treasure_unlocked(ids: Dictionary) -> void: + _reward_economy.set_treasure_unlocked(ids) func _grant_routed(snap: Dictionary, polarity: String, source_class: String, cell: Vector2i, ri: int, highlight: String = "", label_suffix: String = "") -> bool: - # 迭代 11 第①批 T7——aux 授予分支随掉落/停点渠道退役拆除(reward 词表第十型 aux_item 保留但零投放: + # 迭代 11 第①批 T7——aux 授予分支随掉落/停点渠道退役拆除(reward 词表第十型 treasure_item 保留但零投放: # 无 aux 行入池、FEATURE_KINDS 词表已除名);剩余类型走极性字典路由。 var row: Dictionary = _reward_economy.polarity_row(String(snap.get("cell_type", "")), polarity) if row.is_empty(): @@ -1095,7 +1095,7 @@ func _exit_distribution() -> void: _fatal("换图编排失败") return # 工兵晨令续队(迭代 11 同调批 T5——upcoming 轮号 = round_index+1 ≤ effective_rounds 才续,P4 甲表值化) - if _attune_has("dawn_order") and round_index + 1 <= int(db.aux_item_row("dawn_order").get("effective_rounds", 0)): + if _attune_has("dawn_order") and round_index + 1 <= int(db.treasure_item_row("dawn_order").get("effective_rounds", 0)): action_economy.queue_ap_delta(_attune_mag("dawn_order")) action_economy.notify_settlement_done(mode) action_economy.notify_round_start() @@ -1136,8 +1136,8 @@ func _battle_over(result: String) -> void: _reward_economy.retire_mapping() _enemy_system.despawn_all() _status_effects.notify_battle_end() - if aux_inventory != null: - aux_inventory.retire_overlays() # 迭代 7 T3——叠加层随战斗结束清空(库存不动——关卡域跨战斗) + if treasure_inventory != null: + treasure_inventory.retire_overlays() # 迭代 7 T3——叠加层随战斗结束清空(库存不动——关卡域跨战斗) action_economy.notify_combat_end() # → Idle,RAP 清零(2026-10-02 修复批:原被 tab 事故并进上一行行尾注释从不执行——每战新建实例掩盖了症状;P0-3) db.set_reload_gate(false) _reset_round_facts() diff --git a/game/core/config_db.gd b/game/core/config_db.gd index 7e1ff3ee..45a6c13a 100644 --- a/game/core/config_db.gd +++ b/game/core/config_db.gd @@ -24,10 +24,10 @@ const TABLE_MANIFEST := { "shop": "shop.tres", # GP+商店房实施批 2026-09-21(表与 schema 落籍归并行数据面——本批只接线加载与消费) "meta": "meta.tres", # 元进度实现批 2026-09-21(MetaTable 四行族——schema 与表同批落籍) "meta_tree": "meta_tree.tres", # 迭代 12 T8 双层 BD 天赋树(MetaTreeTable 定义表 Rule 4 豁免——R1 甲融合案 33 节点) - "aux_items": "aux_items.tres", # 迭代 7 T1 魔法道具内容批(AuxItemTable 六行——定义表 Rule 4 豁免;罗盘 retired/失义件 deferred 标记见 schema 头注) + "treasure_items": "treasure_items.tres", # 迭代 7 T1 秘宝内容批(TreasureItemTable 六行——定义表 Rule 4 豁免;罗盘 retired/失义件 deferred 标记见 schema 头注) "adventure": "adventure.tres", # 冒险结构实现批 2026-09-21(AdventureTable 建表——大奖励与钥石行值单点) "attunement_growth": "attunement_growth.tres", # 迭代 11 第①批 同调实施批 T1(AttunementGrowthTable 单行全局——同调位里程碑谓词表;单行先例 Rule 4 豁免) - "relics": "relics.tres", # 迭代 12 T1 双层 BD 规则改写型特性基建(RelicTable 定义表 Rule 4 豁免——AuxItemTable 先例;空表合法态=主时间线零扰动) + "relics": "relics.tres", # 迭代 12 T1 双层 BD 规则改写型特性基建(RelicTable 定义表 Rule 4 豁免——TreasureItemTable 先例;空表合法态=主时间线零扰动) } var action_economy: ActionEconomyTable @@ -47,7 +47,7 @@ var shop: ShopTable = null # 元进度实现批(2026-09-21):MetaTable 类型化持用(schema 与表同批落籍,无 shop 先例的落籍间隙问题) var meta: MetaTable var meta_tree: MetaTreeTable # 迭代 12 T8 类型化持用(消费面走 tree_node 访问器) -var aux_items: AuxItemTable # 迭代 7 T1 类型化持用(消费面走 aux_* 访问器) +var treasure_items: TreasureItemTable # 迭代 7 T1 类型化持用(消费面走 treasure_* 访问器) var adventure: AdventureTable var attunement_growth: AttunementGrowthTable # 迭代 11 第①批 T1 类型化持用(消费面走 attunement_* 访问器) var relics: RelicTable # 迭代 12 T1 类型化持用(消费面走 relic_* 访问器) @@ -139,7 +139,7 @@ func load_tables(root: String, collect_only: bool) -> bool: difficulty = loaded.get("difficulty") shop = loaded.get("shop") meta = loaded.get("meta") - aux_items = loaded.get("aux_items") + treasure_items = loaded.get("treasure_items") adventure = loaded.get("adventure") attunement_growth = loaded.get("attunement_growth") relics = loaded.get("relics") @@ -248,31 +248,31 @@ func level_count() -> int: # ---- GP+商店房实施批(2026-09-21):ShopTable 消费面(行集解析单点——runner/战斗编排禁自扫表)---- -# ── 魔法道具访问器(迭代 7 T1——消费面一律走访问器,禁直读行集)── +# ── 秘宝访问器(迭代 7 T1——消费面一律走访问器,禁直读行集)── # 活行集(非 retired 非 deferred)——投放校验/奖励节点池/呈现可用性的唯一取数口径 -func aux_active_rows() -> Array: - return aux_items.active_rows() if aux_items != null else [] +func treasure_active_rows() -> Array: + return treasure_items.active_rows() if treasure_items != null else [] -func aux_item_row(item_id: String) -> Dictionary: - return aux_items.row_by_id(item_id) if aux_items != null else {} +func treasure_item_row(item_id: String) -> Dictionary: + return treasure_items.row_by_id(item_id) if treasure_items != null else {} # 过渡渠道活行(form 空 = 切片期过渡形态)——掉落投放/停点池/工坊解锁取数口径;同调行(form 非空) # 永不入过渡渠道(迭代 11 第①批 T1;T7 退役面切换后本口径随渠道消亡) -func aux_transitional_rows() -> Array: - return aux_items.transitional_rows() if aux_items != null else [] +func treasure_transitional_rows() -> Array: + return treasure_items.transitional_rows() if treasure_items != null else [] # 同调行集(form 非空——装配覆盖层/效果接线的取数口径,迭代 11 第①批 T1/T4) -func aux_attunement_rows() -> Array: - return aux_items.attunement_rows() if aux_items != null else [] +func treasure_attunement_rows() -> Array: + return treasure_items.attunement_rows() if treasure_items != null else [] # 活行词表(掉落投放 effect_id 白名单——过渡渠道口径) -func aux_live_ids() -> Dictionary: +func treasure_live_ids() -> Dictionary: var out := {} - for row in aux_transitional_rows(): + for row in treasure_transitional_rows(): out[String(row.get("item_id", ""))] = true return out diff --git a/game/core/config_db_cross_validator.gd b/game/core/config_db_cross_validator.gd index d784a86c..0efe416c 100644 --- a/game/core/config_db_cross_validator.gd +++ b/game/core/config_db_cross_validator.gd @@ -25,30 +25,30 @@ func cross_validate(loaded: Dictionary, push_diag: Callable) -> void: # GP+商店房实施批(2026-09-21)例外:gp_gain/gp_loss = GP 战斗内缓冲(escrow)通道的路由键 # (战斗结算 _apply_gp_row 兑付——不入增益状态容器),词表封闭按字面豁免悬空引用校验。 for row in rt.rows: - if String(row.get("cell_type", "")) == RewardTable.AUX_ITEM_TYPE: - continue # aux 行 effect_id=item_id——归 ①b 双表校验(reward_dangling_aux),不入增益词表面 + if String(row.get("cell_type", "")) == RewardTable.TREASURE_ITEM_TYPE: + continue # aux 行 effect_id=item_id——归 ①b 双表校验(reward_dangling_treasure),不入增益词表面 var eff: String = row.get("effect_id", "") if eff != "" and eff != "gp_gain" and eff != "gp_loss" and not effect_ids.has(eff): push_diag.call("error", "dangling_effect", "RewardTable %s 引用不存在的 effect_id: %s" % [row.get("reward_id"), eff]) - # ①b RewardTable aux 投放行双表校验(迭代 7 T1——reward_dangling_aux):aux 行 effect_id = item_id, - # 须命中 AuxItemTable 活行(非 retired 非 deferred——罗盘退役/失义件不投放)。retired 行被引用=退役 + # ①b RewardTable aux 投放行双表校验(迭代 7 T1——reward_dangling_treasure):aux 行 effect_id = item_id, + # 须命中 TreasureItemTable 活行(非 retired 非 deferred——罗盘退役/失义件不投放)。retired 行被引用=退役 # 后仍投放(连带错误),同拦。 - var aux_live := {} - var aux_tab = loaded.get("aux_items") - if aux_tab != null: - for arow in aux_tab.active_rows(): - aux_live[String(arow.get("item_id", ""))] = true + var treasure_live := {} + var treasure_tab = loaded.get("treasure_items") + if treasure_tab != null: + for arow in treasure_tab.active_rows(): + treasure_live[String(arow.get("item_id", ""))] = true for row in rt.rows: - if String(row.get("cell_type", "")) != RewardTable.AUX_ITEM_TYPE: + if String(row.get("cell_type", "")) != RewardTable.TREASURE_ITEM_TYPE: continue - var aux_eff: String = String(row.get("effect_id", "")) - if aux_eff == "": # 负占位行(雷格极性字典兜底,零兑付)——不入投放词表校验 + var treasure_eff: String = String(row.get("effect_id", "")) + if treasure_eff == "": # 负占位行(雷格极性字典兜底,零兑付)——不入投放词表校验 continue - if not aux_live.has(aux_eff): - push_diag.call("error", "reward_dangling_aux", "RewardTable %s aux 行引用无效道具 %s(retired/deferred/不存在): %s" % [row.get("reward_id"), aux_eff, "双表校验"]) - # ①c F2 投放维度覆盖(魔法道具 GDD——五维度各 ≥1 掉落权重为正的活行):豁免面 {plan, info, counter} + if not treasure_live.has(treasure_eff): + push_diag.call("error", "reward_dangling_treasure", "RewardTable %s aux 行引用无效道具 %s(retired/deferred/不存在): %s" % [row.get("reward_id"), treasure_eff, "双表校验"]) + # ①c F2 投放维度覆盖(秘宝 GDD——五维度各 ≥1 掉落权重为正的活行):豁免面 {plan, info, counter} # = 罗盘退役(plan,2026-09-29 拍板①乙)+显影件 Alpha 重定(info/counter 悬置)——豁免随 Alpha 重定批消减 - # ①c F2 投放维度覆盖校验随战斗掉落渠道退役(2026-10-01 用户拍板甲——挖格不掉道具,魔法道具 + # ①c F2 投放维度覆盖校验随战斗掉落渠道退役(2026-10-01 用户拍板甲——挖格不掉道具,秘宝 # 唯一来路=三选一共享池〔节点/通关〕):旧校验=「掉落池五维度各 ≥1 正权重活行」,载体已随 # reward.tres aux 投放四行删除而消失;共享池为「抽到道具位再动态掷定具体道具」,维度覆盖不可 # 静态校验。静态覆盖保证的重立(如按维度钉共享池抽签面)归同调实施批/渠道设计批。 diff --git a/game/core/level_runner.gd b/game/core/level_runner.gd index 186e4c6f..0d5f745a 100644 --- a/game/core/level_runner.gd +++ b/game/core/level_runner.gd @@ -62,10 +62,10 @@ var base_override := {"atk": 0, "max_hp": 0, "armor_class": 0} # 永久强化 var _shop_purchased := {} # product_id → 已购档数(现价重算输入;冒险开始清零) # 协作对象私有(E1/E3 封装收口 2026-09-13):settlement 读取经 current_battle() 成文出口 var _settlement: BattleOrchestrator = null # 当前战斗编排器(关卡结束置 null) -var aux_inventory: AuxItems = null # 魔法道具 关卡域库存(迭代 7 T3——AuxItems;跨战斗延续, -var _aux_unlocked := {} # aux 解锁门控集(迭代 7 T5——拍板③甲;空集=零投放) +var treasure_inventory: TreasureItems = null # 秘宝 关卡域库存(迭代 7 T3——TreasureItems;跨战斗延续, +var _treasure_unlocked := {} # aux 解锁门控集(迭代 7 T5——拍板③甲;空集=零投放) var _attunement: Array = [] # 同调装配集(迭代 11 第①批 T5——adventure params.attunement 下传,begin_battle enc 携带进战斗结算;空集=off 零扰动) -var _attune_charges: Dictionary = {} # 同调主动件充能账本(迭代 11 第①批 T6——adventure 共享 dict 引用;settlement use_aux 扣减直改同引用) +var _attune_charges: Dictionary = {} # 同调主动件充能账本(迭代 11 第①批 T6——adventure 共享 dict 引用;settlement use_treasure 扣减直改同引用) # 关卡末清空+快照计数入 level_finished 载荷) # ---- 商店共享池模式态(迭代 11 第②批 T3——缺省 legacy=固定三件加定价 off 对照承载,零 RNG 零池消费;TP0 令牌池换代)---- var _shop_pool_mode := false # pool 模式旗(set_shop_pool 注入时置位——AdventureRunner 按 params.shop_mode 下传) @@ -295,11 +295,11 @@ func present_resumed_choice() -> bool: # 断点道具库存回填(迭代 8 卡①——奖励节点已选道具随停点快照回局;幂等,先清后入受理序重排) -func restore_aux_items(items: Array) -> void: - if aux_inventory == null: - aux_inventory = AuxItems.new(db) - aux_inventory.reset() - aux_inventory.restore_inventory(items) +func restore_treasure_items(items: Array) -> void: + if treasure_inventory == null: + treasure_inventory = TreasureItems.new(db) + treasure_inventory.reset() + treasure_inventory.restore_inventory(items) func _find_level_row(level_index: int) -> Dictionary: @@ -460,11 +460,11 @@ func _enter_node(node: Dictionary) -> bool: func _start_battle(node: Dictionary) -> bool: _settlement = BattleOrchestrator.new(db, rng) - if aux_inventory == null: - aux_inventory = AuxItems.new(db) # 惰性建——关卡域单实例(跨战斗延续) - _settlement.aux_inventory = aux_inventory # 迭代 7 T3——库存注入(授予路由+use_aux 编排消费面) + if treasure_inventory == null: + treasure_inventory = TreasureItems.new(db) # 惰性建——关卡域单实例(跨战斗延续) + _settlement.treasure_inventory = treasure_inventory # 迭代 7 T3——库存注入(授予路由+use_treasure 编排消费面) if _settlement != null: - _settlement.set_aux_unlocked(_aux_unlocked) # 迭代 7 T5——解锁门控下传(装板摇号前) + _settlement.set_treasure_unlocked(_treasure_unlocked) # 迭代 7 T5——解锁门控下传(装板摇号前) # core↔core 接线只许方法 Callable(ADR-0001 静态规则 S6——lambda 捕获 self 会延长 # RefCounted 生命周期乃至成环:settlement 的信号持捕获 runner 的 lambda,runner 又持 settlement) _settlement.step_row.connect(_forward_step_row) @@ -514,13 +514,13 @@ func _on_battle_finished(payload: Dictionary) -> void: close_wallet() # 单关模式:关卡收束即冒险收束(GP 清零);冒险模式归 AdventureRunner._settle _phase = Phase.ENDED _settlement = null - var aux_cleared := 0 - if aux_inventory != null: - aux_cleared = aux_inventory.inventory_count() # 快照计数(清空前——「剩余道具随关卡结束清空」可见反馈取数) - aux_inventory.reset() # 迭代 7 T3——关卡末库存清空(无论输赢,幂等) + var treasure_cleared := 0 + if treasure_inventory != null: + treasure_cleared = treasure_inventory.inventory_count() # 快照计数(清空前——「剩余道具随关卡结束清空」可见反馈取数) + treasure_inventory.reset() # 迭代 7 T3——关卡末库存清空(无论输赢,幂等) level_finished.emit({"result": level_result, "hp": hp_left, "node_index": node_index, "node_id": _node_id(node), "node_type": String(node.get("type", "")), - "aux_cleared": aux_cleared}) # additive 扩签(不参与派生——node_map 扩签先例) + "aux_cleared": treasure_cleared}) # additive 扩签(不参与派生——node_map 扩签先例) return # 接口漂移清偿(关卡节点地图 v1.0 ⑦):战斗胜利不再自动推进——确认后进选路口 _settlement = null @@ -579,10 +579,10 @@ func current_battle(): return _settlement # aux 解锁门控集注入(迭代 7 T5——AdventureRunner 自 params 传递) -func set_aux_unlocked(ids: Dictionary) -> void: - _aux_unlocked = ids +func set_treasure_unlocked(ids: Dictionary) -> void: + _treasure_unlocked = ids if _settlement != null: - _settlement.set_aux_unlocked(ids) + _settlement.set_treasure_unlocked(ids) # 同调装配集注入(迭代 11 第①批 T5——冒险开始参数面;AdventureRunner 唯一调用方) @@ -617,23 +617,23 @@ func set_tree_rules(rules: Array) -> void: # 差额注入防续玩双份——resume 路径 restore_inventory 已含断点内 attune 记录) func set_attune_charges(charges: Dictionary) -> void: _attune_charges = charges - if aux_inventory == null: - aux_inventory = AuxItems.new(db) + if treasure_inventory == null: + treasure_inventory = TreasureItems.new(db) for iid in charges: var existing := 0 - for r in aux_inventory.snapshot_inventory(): + for r in treasure_inventory.snapshot_inventory(): if String(r.item_id) == String(iid) and String(r.source_class) == "attunement" and not bool(r.used): existing += 1 for i in range(maxi(0, int(charges[iid]) - existing)): - aux_inventory.add_item(String(iid), "attunement", Vector2i(-1, -1), 0) + treasure_inventory.add_item(String(iid), "attunement", Vector2i(-1, -1), 0) # 奖励节点兑付透传(迭代 7 T5——呈现层三选一 → 关卡域库存;来源归因 reward_node)。 # 迭代 11 第①批 T7——同调位持有闸随过渡键退役拆除(aux 卡出池后仅剩防御面;能力件容量闸 # 正主 = 营地装配面 Attunement.slots 满位禁选)。 -func grant_aux_item(item_id: String, source: String) -> Dictionary: - if aux_inventory == null: - aux_inventory = AuxItems.new(db) - return aux_inventory.add_item(item_id, source, Vector2i(-1, -1), 0) +func grant_treasure_item(item_id: String, source: String) -> Dictionary: + if treasure_inventory == null: + treasure_inventory = TreasureItems.new(db) + return treasure_inventory.add_item(item_id, source, Vector2i(-1, -1), 0) # 三选一 GP 袋件入账(迭代 10——钱包收口扩「奖励入账」入口;复用战斗完成同一入账原语, diff --git a/game/core/meta_progression.gd b/game/core/meta_progression.gd index a89ade6e..775705c9 100644 --- a/game/core/meta_progression.gd +++ b/game/core/meta_progression.gd @@ -6,7 +6,7 @@ # 职责三件:① 属性锻造定价与购买(几何递增——tier 级价格 = 迭代 floor(p × ratio/100),tier 0 = # base_price,floor 单一取整对齐 round_direction 纪律);② 道具工坊解锁(渠道由 meta.tres channel # 字段声明、判定量换算单点 _workshop_progress——2026-09-21 用户拍板可替换轴;首版 = 总通关次数, -# 钥石直购价随定价批后补最终双渠道;六件局内效果归 Alpha 魔法道具重设计批,本类只有解锁状态); +# 钥石直购价随定价批后补最终双渠道;六件局内效果归 Alpha 秘宝重设计批,本类只有解锁状态); # ③ 冒险收束入账(Boss 两档 = 表值 first_kill/repeat_kill,首杀标记读存档判first;调 SaveManager # apply_adventure_summary 入账并附 boss_drops 副本——复盘可归因,验收 5)。 # 注入面:hero_override() = 三档 forge flat(全零 = 白板合法态;override 不写表——表运行期只读, @@ -91,7 +91,7 @@ func workshop_status() -> Array: var out: Array[Dictionary] = [] for row in db.meta_workshop_items(): var iid := String(row.get("item_id", "")) - var arow: Dictionary = db.aux_item_row(iid) # 迭代 7 T5——失义/退役状态面(呈现「能力封存/已退役」) + var arow: Dictionary = db.treasure_item_row(iid) # 迭代 7 T5——失义/退役状态面(呈现「能力封存/已退役」) out.append({ "item_id": iid, "display_name": String(row.get("display_name", "")), @@ -326,12 +326,12 @@ func migrate_tree() -> Dictionary: save.set_tree_level(String(pair[0]), lvl) migrated["forge"] += 1 var any_unlock := false - for iid in db.aux_live_ids().keys(): + for iid in db.treasure_live_ids().keys(): if save.item_unlocked(String(iid)): any_unlock = true break if not any_unlock: - for row in db.aux_attunement_rows(): + for row in db.treasure_attunement_rows(): if save.item_unlocked(String(row.get("item_id", ""))): any_unlock = true break @@ -354,7 +354,7 @@ func migrate_tree() -> Dictionary: func toggle_attunement(item_id: String) -> bool: var equipped: Array = save.attunement_equipped() if not equipped.has(item_id): - var arow: Dictionary = db.aux_item_row(item_id) + var arow: Dictionary = db.treasure_item_row(item_id) if arow.is_empty() or String(arow.get("form", "")) == "": return false # 非同调行(过渡/退役行)禁装配 if equipped.size() >= Attunement.slots(db, save): @@ -370,7 +370,7 @@ func toggle_attunement(item_id: String) -> bool: func attune_camp_status() -> Dictionary: var equipped: Array = save.attunement_equipped() var items: Array[Dictionary] = [] - for row in db.aux_attunement_rows(): + for row in db.treasure_attunement_rows(): var iid := String(row.get("item_id", "")) items.append({ "item_id": iid, diff --git a/game/core/reward_economy.gd b/game/core/reward_economy.gd index 09d9de60..57943374 100644 --- a/game/core/reward_economy.gd +++ b/game/core/reward_economy.gd @@ -81,7 +81,7 @@ func roll_board(eligible: Array) -> bool: return true -# ---- 查询面(Ready 只读;未开格恒可查——魔法道具 桥接结构前提)---- +# ---- 查询面(Ready 只读;未开格恒可查——秘宝 桥接结构前提)---- # 相位只读出口(诊断观测面——unrolled/ready/retired;消费方禁直读 _phase 下划线字段) func phase() -> String: @@ -296,20 +296,20 @@ func weighted_pick(rows: Array, r: int) -> String: # aux 解锁门控集(迭代 7 T5——拍板③甲「解锁→进投放池」:未解锁 aux 行不入摇号池。 # 空集默认 = 全部 aux 不投放(白板/夹具态零投放——模拟读数零扰动;真实侧 main 组装工坊解锁集传入) -var _aux_unlocked := {} +var _treasure_unlocked := {} -func set_aux_unlocked(ids: Dictionary) -> void: - _aux_unlocked = ids +func set_treasure_unlocked(ids: Dictionary) -> void: + _treasure_unlocked = ids func _rollable_rows() -> Array: # 摇号池 = cell 池正向行 weight>0(负向行纯字典不消费权重;封锁格不在本函数职责域——清单由调用方裁剪) var out: Array[Dictionary] = [] for row in db.reward.rows: - if String(row.get("cell_type", "")) == RewardTable.AUX_ITEM_TYPE: + if String(row.get("cell_type", "")) == RewardTable.TREASURE_ITEM_TYPE: var iid := String(row.get("effect_id", "")) - if iid == "" or not _aux_unlocked.has(iid): + if iid == "" or not _treasure_unlocked.has(iid): continue if String(row.get("pool_tag", "")) == "cell" and String(row.get("polarity", "")) == "positive" and int(row.weight) > 0: out.append(row) diff --git a/game/core/save_manager.gd b/game/core/save_manager.gd index 363a525e..d57b7fd6 100644 --- a/game/core/save_manager.gd +++ b/game/core/save_manager.gd @@ -11,7 +11,7 @@ # keystone_balance / forge_levels / item_unlocks / level_clear_counts / boss_first_kill # —— 内容 owner = 元进度.md(营地三柜台:钥石余额/属性锻造/道具工坊/通关次数/首杀标记) # boss_kill_count / attunement_equipped / attune_refresh_level -# —— 内容 owner = 魔法道具.md(同调位账本,M-4 迭代 11 第①批 T2):Boss 击杀总数〔含重复〕= +# —— 内容 owner = 秘宝.md(同调位账本,M-4 迭代 11 第①批 T2):Boss 击杀总数〔含重复〕= # attunement_growth 谓词表计数源;装配关系 = 局外进度事实(元进度域同族——非契约 2 反面清单的 # 「局内道具库存」,后者=冒险进行中瞬态);attune_refresh_level = Y 刷新升级购买等级 # breakpoint.attunement_charges(主动件充能余量)——每冒险重置语义的断点瞬态附随件,内容装配归 diff --git a/game/core/aux_items.gd b/game/core/treasure_items.gd similarity index 91% rename from game/core/aux_items.gd rename to game/core/treasure_items.gd index da8454ba..a8fb1625 100644 --- a/game/core/aux_items.gd +++ b/game/core/treasure_items.gd @@ -1,8 +1,8 @@ # VERTICAL SLICE - NOT FOR PRODUCTION # Validation Question: 道具从掉落到使用的全程零随机零特判——同操作序列重放两遍,库存与叠加层投影逐位相同(P0) -# Date: 2026-09-29(迭代 7 T2 core 骨架——魔法道具内容批;设计权威 design/gdd/systems/排雷循环/魔法道具.md -# + registry aux_items api 8 入口/load_bearing_rules/use_orchestration) -# 魔法道具 关卡域库存 + 板级叠加层(自持派生信息层)。 +# Date: 2026-09-29(迭代 7 T2 core 骨架——秘宝内容批;设计权威 design/gdd/systems/排雷循环/秘宝.md +# + registry 秘宝条目(键 aux_items 沿用)api 8 入口/load_bearing_rules/use_orchestration) +# 秘宝 关卡域库存 + 板级叠加层(自持派生信息层)。 # 结构冻结照抄(违反即返工): # 零随机(零 RNG 流消费——信息只来自 排雷玩法 恒真数字/地图战斗资源 Ready 映射/行动经济 账本三既有事实源); # 库存关卡域(跨轮跨图跨战斗延续、关卡末清空——清空编排归 战斗结算/关卡层,本类只供 clear/reset); @@ -11,10 +11,10 @@ # 真视恒可用(零雷窗口=「这 9 格没雷」信息非空);点击级零信息不消耗(拒绝零消耗——预读窗口全已开); # 零特判(排雷玩法 代码零本系统分支——本类不写任何其他系统状态)。 # 负空间:无自动使用入口/无重掷/无事件订阅/无 RNG 直连/无 排雷玩法/地图战斗资源 写入口; -# 相位检查归 战斗结算 use_aux 编排第一步(本类不管相位——validate_use 是纯谓词+投影)。 +# 相位检查归 战斗结算 use_treasure 编排第一步(本类不管相位——validate_use 是纯谓词+投影)。 # 呈现取数面:query_inventory(C 区槽位)/query_overlays(棋盘叠加层标记)——只读投影,零数据复制 # (预读徽章数据源=战斗结算 query_reward_identity 既有读面,本类只记「哪些格要额外显示」)。 -class_name AuxItems +class_name TreasureItems extends RefCounted var _items: Array = [] # [{handle, item_id, used}]——受理序;Used 保留只读 @@ -112,11 +112,11 @@ func _usable_now(item_id: String, board_has_preview_info: Callable) -> bool: func _item_row(item_id: String) -> Dictionary: if _db == null: return {} - if _db.has_method("aux_item_row"): - return _db.aux_item_row(item_id) # 表访问收口(2026-10-02——正式面走 ConfigDB 访问器) - return _db.aux_items.row_by_id(item_id) # 桩表面(单测 StubDB 无访问器——直读保留,随测试面演进退役) + if _db.has_method("treasure_item_row"): + return _db.treasure_item_row(item_id) # 表访问收口(2026-10-02——正式面走 ConfigDB 访问器) + return _db.treasure_items.row_by_id(item_id) # 桩表面(单测 StubDB 无访问器——直读保留,随测试面演进退役) -# 不标具体类型原因:单元测试注入 StubDB 桩表(aux_items_test.gd)——typed 赋值会运行期拒收,保守保持 null 注 +# 不标具体类型原因:单元测试注入 StubDB 桩表(treasure_items_test.gd)——typed 赋值会运行期拒收,保守保持 null 注 var _db = null # ConfigDB(行定义读取——_init 注入;测试可注入桩表) @@ -124,7 +124,7 @@ func _init(db_ref = null) -> void: _db = db_ref -# ---- 使用校验(战斗结算 use_aux 编排第二步——纯谓词+投影,零消耗零副作用)---- +# ---- 使用校验(战斗结算 use_treasure 编排第二步——纯谓词+投影,零消耗零副作用)---- # target = 目标格(空间行=3×3 窗口中心;ap 行忽略)。board_size = 板维度; # cell_unrevealed_cb = Callable(Vector2i) -> bool(排雷玩法 只读面——预读窗口信息判据)。 diff --git a/game/core/aux_items.gd.uid b/game/core/treasure_items.gd.uid similarity index 100% rename from game/core/aux_items.gd.uid rename to game/core/treasure_items.gd.uid diff --git a/game/data/schemas/adventure_table.gd b/game/data/schemas/adventure_table.gd index 54d8e4b0..8b55a98f 100644 --- a/game/data/schemas/adventure_table.gd +++ b/game/data/schemas/adventure_table.gd @@ -7,7 +7,7 @@ # TP0 令牌池换代(2026-10-03 用户全裁 b——node-reward v2.2):三选一池改固定配额令牌池——普通 70/稀有 25/ # 罕见 5=100 张;洗牌不放回抽 3、选中踢池未选回池、池耗即枯竭;种类次数上限退役(池消耗即上限)。 # 档位构成:普通〔小GP 18/小增伤 18/小护甲 17/小生命 17〕+稀有〔大GP/大增伤/大护甲/大生命/恢复 各 5〕 -# +罕见〔AP 3〕——罕见档原列「道具件 2」随 aux_item 池种退役(迭代 11 第①批 T7)不投放,配额缺省收窄。 +# +罕见〔AP 3〕——罕见档原列「道具件 2」随 treasure_item 池种退役(迭代 11 第①批 T7)不投放,配额缺省收窄。 # 恢复件=新入池种类(当即回血)。旧权重/次数上限字段整代退役。 # 全部 knob provisional-pending-曲线调参批(数值所有权归 难度曲线与Boss,上调须重扫通关率带)。 class_name AdventureTable @@ -23,7 +23,7 @@ extends Resource ## 刷新次数 / 金币 / 回复,命名待定〕——本表两类混编;刷新次数与专长获取两项尚未入表。 ## 类内异质性:金币与回复是即时兑付,不进持有集、不持续生效。) ## 三选一提升池 kind 词表(封闭——断点附随件与牌库剔除态依赖它;扩件走本表+registry 修订)。 -## aux_item 池种退役(迭代 11 第①批 T7——同调批出池);heal 恢复件新入池(v2.2 令牌池追认 b)。 +## treasure_item 池种退役(迭代 11 第①批 T7——同调批出池);heal 恢复件新入池(v2.2 令牌池追认 b)。 const FEATURE_KINDS: Array[String] = ["attack", "max_hp", "armor", "gp", "ap", "heal"] ## 令牌档位词表(v2.2 三档位——稀有度命名对齐 MC 策略判读序 316-f:1 级最稀有=rarest 优先) const TIERS: Array[String] = ["common", "rare", "rarest"] @@ -31,7 +31,7 @@ const TIER_COMMON := "common" const TIER_RARE := "rare" const TIER_RAREST := "rarest" ## 档位配额结构锚(v2.2 追认 b 定稿——validate() 硬断言;改总量=重裁非调参)。 -## 罕见档 5→3:原「道具件 2」席位随 aux_item 池种退役(迭代 11 第①批 T7,落地晚于追认 b)收窄, +## 罕见档 5→3:原「道具件 2」席位随 treasure_item 池种退役(迭代 11 第①批 T7,落地晚于追认 b)收窄, ## 池总量 100→98——TP0 台账自决+人工清单披露项。 const TIER_QUOTAS := {"common": 70, "rare": 25, "rarest": 3} diff --git a/game/data/schemas/attunement_growth_table.gd b/game/data/schemas/attunement_growth_table.gd index dd7b7203..a09066c0 100644 --- a/game/data/schemas/attunement_growth_table.gd +++ b/game/data/schemas/attunement_growth_table.gd @@ -1,8 +1,8 @@ # VERTICAL SLICE - NOT FOR PRODUCTION # Validation Question: 同调位增长是否由「通关次数 + Boss 击杀数」经数据驱动的里程碑谓词表实时求值, # 试玩后调增长曲线 = 改表不动码(proposal-magic-item-attunement-2026-09-22 §2.1 用户点名要求) -# Date: 2026-10-03(迭代 11 第①批 魔法道具同调实施批 T1——任务书 v1.1 §六 T1;设计权威底稿 proposal §2) -# 数据配置 AttunementGrowthTable schema(魔法道具 回填 owner)。 +# Date: 2026-10-03(迭代 11 第①批 秘宝同调实施批 T1——任务书 v1.1 §六 T1;设计权威底稿 proposal §2) +# 数据配置 AttunementGrowthTable schema(秘宝 回填 owner)。 # 单行全局常量表(slot_cap + milestones 行族——AdventureTable 单行全局先例,Rule 4 豁免)。 # 行 = Dictionary:{id: String 唯一, grant: int, requires: [{key: String, threshold: int}]}—— # requires 为 (计数键, 阈值) 对的 AND 列表,全部满足即授予 grant 槽; diff --git a/game/data/schemas/meta_table.gd b/game/data/schemas/meta_table.gd index a1c44d52..fd57bf3d 100644 --- a/game/data/schemas/meta_table.gd +++ b/game/data/schemas/meta_table.gd @@ -8,8 +8,8 @@ # 投值语言锁定 flat 整数;几何定价 tier 级价格 = 迭代 p = floor(p × price_ratio_pct/100),tier 0 = base_price)。 # boss_keystone = Boss 钥石两档行(level_index 连续从 1;first_kill ≥ repeat_kill——首杀全量、 # 重复杀固定小额恒定不递减,两档数值归元进度设计批配读数)。 -# workshop_items = 道具工坊行(item_id = registry aux_items 六件词表封闭恰全;首版解锁渠道 = 总通关次数 -# 达标 clear_threshold——2026-09-20 排期裁决;局内效果整体归 Alpha 魔法道具重设计批,本表只有解锁状态面)。 +# workshop_items = 道具工坊行(item_id = 秘宝六件词表封闭恰全;首版解锁渠道 = 总通关次数 +# 达标 clear_threshold——2026-09-20 排期裁决;局内效果整体归 Alpha 秘宝重设计批,本表只有解锁状态面)。 # conversion = 区间平移换算率行(attr 与 forge 词表一致恰三;per_level_shift_pct ∈ [0,100]—— # registry 键 meta_progression_conversion_table;护甲行强条目:验收读数必须按解锁后参数重测)。 # attune_refresh_upgrade = Y 刷新升级行族(迭代 11 第①批 T4——P1 甲:每冒险开局给 Y 次、冒险周期池、 @@ -80,12 +80,12 @@ func validate() -> Array: if li_at != i + 1: errs.append({"category": "structural", "message": "boss_keystone level_index 不连续(须从 1 连续递增): 位 %d = %d" % [i + 1, li_at]}) break - # workshop_items:item_id 词表封闭 + 唯一 + 覆盖恰六(registry aux_items 词表)+ 阈值域 [1,99] + # workshop_items:item_id 词表封闭 + 唯一 + 覆盖恰六(秘宝词表)+ 阈值域 [1,99] var seen_item := {} for row in workshop_items: var iid: String = row.get("item_id", "") if not WORKSHOP_ITEM_IDS.has(iid): - errs.append({"category": "enum", "message": "workshop_items item_id 出域 aux_items 六件词表: %s" % iid}) + errs.append({"category": "enum", "message": "workshop_items item_id 出域秘宝六件词表: %s" % iid}) if seen_item.has(iid): errs.append({"category": "dup_key", "message": "workshop_items item_id 重复: %s" % iid}) seen_item[iid] = true diff --git a/game/data/schemas/relic_table.gd b/game/data/schemas/relic_table.gd index 6f9a3c65..67205374 100644 --- a/game/data/schemas/relic_table.gd +++ b/game/data/schemas/relic_table.gd @@ -9,7 +9,7 @@ # 表名与 relic_id 沿用历史命名,与统一词族对齐归后续批次——见 06-待办清单「命名统一」条目。 # 目标渠道:专长走关底 Boss 击败后专属三选一(不新增节点类型),见奇物文档 2.1 节。) # 数据配置 RelicTable schema(奇物·专长定义表;行 = Dictionary 键 relic_id,Rule 4 豁免 -# 定义表——AuxItemTable 先例)。 +# 定义表——TreasureItemTable 先例)。 # 行字段:relic_id 主键 / display_name / rarity ∈ {common, rare, rarest}(对齐令牌池三档命名—— # 投放档映射:common/rare→稀有令牌档、rarest→罕见令牌档;relic 令牌永不入普通档=「挂稀有/罕见档」 # 追认 b 接线口径)/ archetype ∈ ARCHETYPES 七流派标签 / hook ∈ HOOKS 挂点枚举(结算段槽——整合定稿 @@ -19,7 +19,7 @@ # 档位激活(整合定稿 设计工具 1——以撒套装/小骨铭文):同标签计数 ≥2→档一(流派核心规则)/≥4→档二 # (完全体);散件单体保底=每件效果独立生效,档位只做质变(反例 B-2)——引擎纯函数 RelicsEngine。 # 🔴 层级纪律(任务书红线 2):专长只走局内随机渠道(三选一/商店/格面)——本表行永不入同调位 -# (aux_items 表)/局外树(T8 节点表);扫雷触发点铁律:每流派 ≥1 行 hook ∈ MINE_HOOKS(加载校验, +# (treasure_items 表)/局外树(T8 节点表);扫雷触发点铁律:每流派 ≥1 行 hook ∈ MINE_HOOKS(加载校验, # 违反=红线①触碰面)。 class_name RelicTable extends Resource diff --git a/game/data/schemas/reward_table.gd b/game/data/schemas/reward_table.gd index f8ff8f76..e5b57bd9 100644 --- a/game/data/schemas/reward_table.gd +++ b/game/data/schemas/reward_table.gd @@ -12,8 +12,8 @@ extends Resource @export var rows: Array[Dictionary] = [] # Array[Dictionary] -const CELL_TYPES := ["attack", "defense", "heal", "blast", "weaken", "pierce", "magic", "action", "gp", "aux_item"] # 十型(迭代 7 T1 魔法道具内容批扩值——registry aux_items 词表;aux 行 effect_id = item_id 双表校验键) -const AUX_ITEM_TYPE := "aux_item" # aux 行标识(掉落投放行:挖开→战斗结算 grant 路由关卡域库存,不入增益容器) +const CELL_TYPES := ["attack", "defense", "heal", "blast", "weaken", "pierce", "magic", "action", "gp", "treasure_item"] # 十型(迭代 7 T1 秘宝内容批扩值——registry 秘宝词表;aux 行 effect_id = item_id 双表校验键) +const TREASURE_ITEM_TYPE := "treasure_item" # aux 行标识(掉落投放行:挖开→战斗结算 grant 路由关卡域库存,不入增益容器) const POLARITIES := ["positive", "negative"] const POOL_TAGS := ["cell", "clear_default"] # cell = 格面资源单一池;clear_ 命名空间预留拒绝 const CELL_TYPE_KEYS := ["attack", "defense", "heal", "blast", "weaken", "pierce", "magic", "action", "gp"] # 字典完整性校验轴(类型 × 极性 = 十八格) @@ -46,8 +46,8 @@ func validate() -> Array: if atk_type != "" and not ["normal", "pierce", "magic"].has(atk_type): errs.append({"category": "enum", "message": "%s attack_type 出域 {normal, pierce, magic}: %s" % [rid, atk_type]}) # aux 投放行专属校验(迭代 7 T1):极性恒正/加权入池/effect_id=item_id 非空(悬空在 config_db 跨表层 - # 对 aux_items 词表校验——reward_dangling_aux)/无 power 无区间(数值语义不复用,道具效果读 AuxItemTable) - if ctype == AUX_ITEM_TYPE: + # 对秘宝词表校验——reward_dangling_treasure)/无 power 无区间(数值语义不复用,道具效果读 TreasureItemTable) + if ctype == TREASURE_ITEM_TYPE: # 负向行 = 雷格极性字典占位(雷安同池摇号下雷格可摇中 aux 身份——负路由零兑付兜底, # effect_id 空/power 0/weight 0 不入池;2026-09-29 T1) if pol == "negative": @@ -57,7 +57,7 @@ func validate() -> Array: if String(row.get("effect_id", "")) == "": errs.append({"category": "domain", "message": "%s aux 正行 effect_id 空(应=item_id)" % rid}) if int(row.get("power", 0)) != 0 or row.has("power_min"): - errs.append({"category": "cross_field", "message": "%s aux 正行禁 power/区间数值(道具数值读 AuxItemTable)" % rid}) + errs.append({"category": "cross_field", "message": "%s aux 正行禁 power/区间数值(道具数值读 TreasureItemTable)" % rid}) var pool: String = row.get("pool_tag", "") var pool_reserved: bool = pool.begins_with("clear_") and pool != "clear_default" if not POOL_TAGS.has(pool) and not pool_reserved: diff --git a/game/data/schemas/aux_item_table.gd b/game/data/schemas/treasure_item_table.gd similarity index 93% rename from game/data/schemas/aux_item_table.gd rename to game/data/schemas/treasure_item_table.gd index 70112d7b..58d5f8fd 100644 --- a/game/data/schemas/aux_item_table.gd +++ b/game/data/schemas/treasure_item_table.gd @@ -1,10 +1,10 @@ # VERTICAL SLICE - NOT FOR PRODUCTION -# Validation Question: 挖掘期撞上推理断头时,玩家能否从掉落池捡到魔法道具、在关键时刻花掉买回情报或行动点(P0) -# Date: 2026-09-29(迭代 7 T1 数据面——魔法道具内容批;设计权威 design/gdd/systems/排雷循环/魔法道具.md v0.4+ -# + registry aux_items 六行 mvp_content;2026-09-29 用户拍板:①乙 探宝罗盘退役留痕 ④甲 显影尘/地穴全图卷失义件 +# Validation Question: 挖掘期撞上推理断头时,玩家能否从掉落池捡到秘宝、在关键时刻花掉买回情报或行动点(P0) +# Date: 2026-09-29(迭代 7 T1 数据面——秘宝内容批;设计权威 design/gdd/systems/排雷循环/秘宝.md v0.4+ +# + registry 秘宝条目六行 mvp_content;2026-09-29 用户拍板:①乙 探宝罗盘退役留痕 ④甲 显影尘/地穴全图卷失义件 # 六行全建零投放「已解锁·能力封存中」) -# 数据配置 AuxItemTable schema(魔法道具 回填 owner)。 -# 行 = Dictionary,键 item_id(Rule 4 豁免:定义表——registry aux_items Rule 4 豁免先例)。 +# 数据配置 TreasureItemTable schema(秘宝 回填 owner)。 +# 行 = Dictionary,键 item_id(Rule 4 豁免:定义表——registry 秘宝条目 Rule 4 豁免先例)。 # 七字段(registry fields 全量):item_id 主键 / display_name / dimension_tags ⊆ 五维 非空 / # effect_kinds ⊆ {mine_reveal, reward_preview, ap_grant}(活性校验见下)/ target ∈ {none, area_3x3, board_wide} / # magnitude [0,999](仅 ap_grant 行消费,加载校验 ≥1)/ use_phase ∈ {active_dig}。 @@ -13,8 +13,8 @@ # 行名保留=meta.tres workshop_items 六件词表恰全校验兼容,存档 item_unlocks 旧键无害; # 免活性校验、不入投放校验、不入 F2 覆盖面、奖励节点/掉落池排除) # deferred = 效果失义待重定行(probe_dust/catacomb_scroll——原显影半边随雾格移除失义,效果与目标 -# 随魔法道具整体重设计归 Alpha(2026-09-20 用户拍板);免 effect_kinds 非空校验、不入投放与 F2) -# 承重护栏(魔法道具 GDD §结构冻结,schema 校验强制不靠运行时拦截): +# 随秘宝整体重设计归 Alpha(2026-09-20 用户拍板);免 effect_kinds 非空校验、不入投放与 F2) +# 承重护栏(秘宝 GDD §结构冻结,schema 校验强制不靠运行时拦截): # 真视窄域——effect_kinds 含 mine_reveal 的活行 target 必须 area_3x3(真视一次最多 3×3,禁全图看雷); # board_wide 仅恢复推理原料类——target=board_wide 的活行 effect_kinds 不得含 mine_reveal(现行无此类活行, # 显影载体待 Alpha 重定后落位)。 @@ -29,7 +29,7 @@ # 🔴 零裸 flat 结构护栏(任务书 §三 1——机制轴禁无条件属性加项):行键白名单封闭(KEY_WHITELIST 外键 = # 加载致命)+ effect_kinds 封闭枚举只收条件触发/机制修正类 kind——任何「无条件属性加项」类效果不得以 # 新 kind 或新键入表(返工红线)。 -class_name AuxItemTable +class_name TreasureItemTable extends Resource @export var rows: Array = [] # Array[Dictionary] 键 item_id @@ -109,7 +109,7 @@ func validate() -> Array: kind_seen[kind] = true # 承重护栏①真视窄域:mine_reveal 活行 target 必须 area_3x3(一次最多 3×3,禁全图看雷) if kind_seen.has("mine_reveal") and target != "area_3x3": - errs.append({"category": "load_bearing", "message": "%s 真视窄域护栏:mine_reveal 行 target 必须 area_3x3,实得 %s(魔法道具 GDD 结构冻结)" % [iid, target]}) + errs.append({"category": "load_bearing", "message": "%s 真视窄域护栏:mine_reveal 行 target 必须 area_3x3,实得 %s(秘宝 GDD 结构冻结)" % [iid, target]}) # 承重护栏②board_wide 仅恢复推理类:全图域行禁替推理效果 if target == "board_wide" and kind_seen.has("mine_reveal"): errs.append({"category": "load_bearing", "message": "%s board_wide 行 effect_kinds 不得含 mine_reveal(全图域仅恢复推理原料类——Alpha 重定后落位)" % iid}) diff --git a/game/data/schemas/aux_item_table.gd.uid b/game/data/schemas/treasure_item_table.gd.uid similarity index 100% rename from game/data/schemas/aux_item_table.gd.uid rename to game/data/schemas/treasure_item_table.gd.uid diff --git a/game/data/tables/adventure.tres b/game/data/tables/adventure.tres index e1ce4c3a..e64cd4d8 100644 --- a/game/data/tables/adventure.tres +++ b/game/data/tables/adventure.tres @@ -28,11 +28,11 @@ feature_value_heal_rare = 6 feature_value_ap_rarest = 1 ; TP0 令牌池换代(2026-10-03,node-reward v2.2 追认 b 落地):三选一池 = 固定配额令牌池—— -; 普通 70/稀有 25/罕见 3 = 98 张(罕见档原列「道具件 2」随 aux_item 池种退役收窄——台账自决披露项); +; 普通 70/稀有 25/罕见 3 = 98 张(罕见档原列「道具件 2」随 treasure_item 池种退役收窄——台账自决披露项); ; 洗牌不放回抽 3、选中踢池未选回池、池耗即枯竭; ; 种类次数上限退役(池消耗即上限;货架库存同账本=牌库剩余令牌数)。 ; 档位构成:普通〔小GP 18/小增伤 18/小护甲 17/小生命 17〕+ 稀有〔大GP/大增伤/大护甲/大生命/恢复 各 5〕 -; + 罕见〔AP 3〕——罕见档原列「道具件 2」随 aux_item 池种退役(迭代 11 第①批 T7)不投放。 +; + 罕见〔AP 3〕——罕见档原列「道具件 2」随 treasure_item 池种退役(迭代 11 第①批 T7)不投放。 ; 数值对:小GP 20/大GP 50、小增伤 +1/大 +2、小护甲 +1/大 +2、小生命 +5/大 +10、恢复 +6(当即回血)、AP +1。 ; 恢复件 = 新入池种类(rare 档)。 ; 退役字段:bonus_weight_*(E-S 权重族)/ bonus_cap_*(种类次数上限族)/ BONUS_CAP_UNLIMITED 哨兵—— diff --git a/game/data/tables/relics.tres b/game/data/tables/relics.tres index 4dfbeb1d..560f2719 100644 --- a/game/data/tables/relics.tres +++ b/game/data/tables/relics.tres @@ -269,6 +269,6 @@ rows = [{ ; dig 4/charge 3/devour 4——整合定稿 §2.3 七流派的件面)。 ; 稀有度→投放档映射:common/rare → 稀有令牌档、rarest → 罕见令牌档(relic 永不入普通令牌档 ; ——「规则改写型特性带挂稀有/罕见档」追认 b 接线口径,普通档 70 张纯数值维持)。 -; 🔴 层级纪律:本表行永不入同调位(aux_items)/局外树(T8 节点表)——规则改写型特性只走局内随机渠道。 +; 🔴 层级纪律:本表行永不入同调位(treasure_items)/局外树(T8 节点表)——规则改写型特性只走局内随机渠道。 ; 数值全 provisional 归 M-4 数值批;effects 键白名单封闭(零裸 flat 同族护栏)。 diff --git a/game/data/tables/aux_items.tres b/game/data/tables/treasure_items.tres similarity index 95% rename from game/data/tables/aux_items.tres rename to game/data/tables/treasure_items.tres index db17404f..3da8a3f6 100644 --- a/game/data/tables/aux_items.tres +++ b/game/data/tables/treasure_items.tres @@ -1,6 +1,6 @@ -[gd_resource type="Resource" script_class="AuxItemTable" load_steps=2 format=3] +[gd_resource type="Resource" script_class="TreasureItemTable" load_steps=2 format=3] -[ext_resource type="Script" path="res://data/schemas/aux_item_table.gd" id="1"] +[ext_resource type="Script" path="res://data/schemas/treasure_item_table.gd" id="1"] [resource] script = ExtResource("1") diff --git a/game/presentation/battle_narrator.gd b/game/presentation/battle_narrator.gd index db5b90be..323cd6f7 100644 --- a/game/presentation/battle_narrator.gd +++ b/game/presentation/battle_narrator.gd @@ -94,8 +94,8 @@ static func bonus_pick_header(payload: Dictionary) -> String: # 三选一选项卡文案(件名 + 档位 + 效果读数;值 = 冒险表行值,组合根喂入;TP0 令牌池——档位词 # 对齐 v2.2 追认 b 口径:小/大前缀(小GP/大GP 族)、恢复/AP 不带档位词;道具件掷定前置时 -# aux_line = 具体道具「名 · 效果摘要」行——池种退役后恒空走通用分支,机械惰性保留) -static func bonus_card_text(id: String, tier: String, value: int, aux_line: String = "") -> String: +# treasure_line = 具体道具「名 · 效果摘要」行——池种退役后恒空走通用分支,机械惰性保留) +static func bonus_card_text(id: String, tier: String, value: int, treasure_line: String = "") -> String: var ts := "" if tier == "common": ts = " · 小" @@ -112,10 +112,10 @@ static func bonus_card_text(id: String, tier: String, value: int, aux_line: Stri return "金币袋%s\n金币 +%d" % [ts, value] "heal": return "恢复药剂\n生命 +%d(当即回复)" % value - "aux_item": - if aux_line != "": - return "魔法道具\n%s" % aux_line - return "魔法道具\n随机获得一件" + "treasure_item": + if treasure_line != "": + return "秘宝\n%s" % treasure_line + return "秘宝\n随机获得一件" "ap": return "行动点提升\n每战首轮 AP +%d" % value return id diff --git a/game/presentation/bonus_interact_controller.gd b/game/presentation/bonus_interact_controller.gd index d6930cbc..ac1621b5 100644 --- a/game/presentation/bonus_interact_controller.gd +++ b/game/presentation/bonus_interact_controller.gd @@ -2,7 +2,7 @@ # 提升三选一与替换子交互控制器(迭代 13 T4/D4——二期家族① 自 main.gd 迁出;规范 1.1 单一职责): # 三选一停点编排(presented→pick→confirm/refresh→resolved→continue)+ 同调位替换子态 #(presented→chosen)+ TP0 令牌池卡片文案装配("kind|tier|relic_id" 复合键)+ 工坊显示名投影。 -# 装配纪律(ADR-0001,仿 aux_interact_controller 先例):信号连接不在此发生——bonus_overlay +# 装配纪律(ADR-0001,仿 treasure_interact_controller 先例):信号连接不在此发生——bonus_overlay # 四信号与 adventure 两信号由组合根接至本类 on_* 入口;模态栈/演播后排窗/呈现刷新/终局面/ # 推进失败 fatal 经组合根回调注入;adventure/runner 随局更替——现值回调注入;兑付写调用唯一 # 经 adventure.pick_bonus/apply_node_bonus/resolve_bonus_replace(core 侧单口,本类零直写)。 @@ -29,7 +29,7 @@ var _gp_summary: Callable # () → 战斗总结 GP 行文案(组 var _pending_bonus := {} # 三选一停点载荷暂存(迭代 10——战斗总结结算确认后开三选一面;续玩停点复用) var _bonus_context := "level_clear" # 三选一面上下文(level_clear=通关停点→推进下一关 / reward_node=奖励节点→回图选路) -var _last_replace_items: Array = [] # 替换子态续玩重建缓存(aux_replace_presented 载荷) +var _last_replace_items: Array = [] # 替换子态续玩重建缓存(treasure_replace_presented 载荷) var _last_replace_incoming := {} # 同上——incoming 记录 @@ -73,7 +73,7 @@ func resume_if_pending() -> bool: # 增量行在其上),确认后进三选一面(level-clear.md v2);续玩停点恢复同入口(零自动推进契约) func on_presented(payload: Dictionary) -> void: if int(payload.get("aux_cleared", 0)) > 0: - toast.show_toast("上关剩余 %d 件魔法道具已随关卡结束清空" % int(payload.get("aux_cleared", 0)), "info") # 迭代 7 T4 清空反馈 + toast.show_toast("上关剩余 %d 件秘宝已随关卡结束清空" % int(payload.get("aux_cleared", 0)), "info") # 迭代 7 T4 清空反馈 _pending_bonus = payload.duplicate(true) _bonus_context = "level_clear" if bool(payload.get("replace_pending", false)): @@ -87,9 +87,9 @@ func on_presented(payload: Dictionary) -> void: _refresh_presentations.call() -# 三选一面开出(战斗总结结算确认 / 续玩停点恢复;替换在途由 aux_replace_presented 续发直落子态) +# 三选一面开出(战斗总结结算确认 / 续玩停点恢复;替换在途由 treasure_replace_presented 续发直落子态) # 奖励节点三选一(迭代 10 追加批——与通关三选一共享同池同权重同上限;BonusPickOverlay 共用面, -# 道具件满位替换子交互同构)。原「魔法道具投放渠道」三选一(迭代 7 过渡形态)随批退役。 +# 道具件满位替换子交互同构)。原「秘宝投放渠道」三选一(迭代 7 过渡形态)随批退役。 func present_node_bonus() -> void: var adventure = _adventure_get.call() _bonus_context = "reward_node" @@ -101,7 +101,7 @@ func present_node_bonus() -> void: bonus_overlay.set_refresh_info(adventure.attune_refresh_left()) # 迭代 11 第①批 T5b——刷新余量投喂 -# 三选一面开出(战斗总结结算确认 / 续玩停点恢复;替换在途由 aux_replace_presented 续发直落子态) +# 三选一面开出(战斗总结结算确认 / 续玩停点恢复;替换在途由 treasure_replace_presented 续发直落子态) func show_pick() -> void: var payload: Dictionary = _pending_bonus _open_modal.call(bonus_overlay) @@ -111,11 +111,11 @@ func show_pick() -> void: _refresh_presentations.call() -func _bonus_card_texts(candidates: Array, aux_detail: Array = []) -> Array: +func _bonus_card_texts(candidates: Array, treasure_detail: Array = []) -> Array: # TP0 令牌池——候选 = {"kind","tier"} 令牌字典;卡片 id = "kind|tier|relic_id" 复合键(同 kind # 大小两档/同档多 relic 可同屏,kind 单键不构成唯一身份),确认回程拆键(on_pick_confirmed) var out: Array = [] - var aux_i := 0 + var treasure_i := 0 for tok in candidates: var kind := String((tok as Dictionary).get("kind", "")) var tier := String((tok as Dictionary).get("tier", "")) @@ -124,10 +124,10 @@ func _bonus_card_texts(candidates: Array, aux_detail: Array = []) -> Array: var text := "" if kind == "relic": text = Narrator.relic_card_text(db.relic_row(rid)) - elif kind == "aux_item": - var iid := String(aux_detail[aux_i]) if aux_i < aux_detail.size() else "" - aux_i += 1 - text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier)), _aux_card_line(iid)) + elif kind == "treasure_item": + var iid := String(treasure_detail[treasure_i]) if treasure_i < treasure_detail.size() else "" + treasure_i += 1 + text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier)), _treasure_card_line(iid)) else: text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier))) out.append({"id": cid, "text": text}) @@ -135,10 +135,10 @@ func _bonus_card_texts(candidates: Array, aux_detail: Array = []) -> Array: # 道具件卡片行(掷定前置——具体道具名 + 效果摘要;空 iid = 无预掷回退态显示通用文案) -func _aux_card_line(iid: String) -> String: +func _treasure_card_line(iid: String) -> String: if iid == "": return "" - var row: Dictionary = db.aux_item_row(iid) + var row: Dictionary = db.treasure_item_row(iid) if row.is_empty(): return "" var parts: Array[String] = [] @@ -185,7 +185,7 @@ func on_pick_confirmed(item_id: String) -> void: push_error("[bonus_interact] 三选一兑付被拒——见输出日志") -func on_aux_replace_presented(items: Array, incoming: Dictionary) -> void: +func on_treasure_replace_presented(items: Array, incoming: Dictionary) -> void: _last_replace_items = items.duplicate(true) _last_replace_incoming = incoming.duplicate(true) if not bonus_overlay.visible: diff --git a/game/presentation/camp_shop_presenter.gd b/game/presentation/camp_shop_presenter.gd index da7e89ad..cf799bec 100644 --- a/game/presentation/camp_shop_presenter.gd +++ b/game/presentation/camp_shop_presenter.gd @@ -1,7 +1,7 @@ # VERTICAL SLICE - NOT FOR PRODUCTION # 营地/商店投影控制器(迭代 13 T4/D4——二期家族③ 自 main.gd 迁出;规范 1.1 单一职责): # 营地面开合/快照投影/锻造·同调·天赋树·Fork 购买与切换 + 商店房购买/离开(pool 与 product 双面)。 -# 装配纪律(ADR-0001,仿 aux_interact_controller 先例):信号连接不在此发生——campbtn/ +# 装配纪律(ADR-0001,仿 treasure_interact_controller 先例):信号连接不在此发生——campbtn/ # camp_overlay 四信号/shop_overlay 两信号由组合根接至本类 on_* 入口;模态栈/呈现刷新/续玩按钮 # 刷新经组合根回调注入;runner 随局更替——现值回调注入;写调用唯一经 MetaProgression 购买原语 # 与 LevelRunner.buy_*(core 侧单口,本类零直写——拒绝可见 pattern 1 兜底 toast 保留原地)。 diff --git a/game/presentation/main.gd b/game/presentation/main.gd index feba9646..f4b44fd9 100644 --- a/game/presentation/main.gd +++ b/game/presentation/main.gd @@ -19,15 +19,15 @@ # ui_assembler.gd,模态层级归 modal_stack.gd,批量模拟编排归 tune_sim_controller.gd,调试模式编排归 # debug_session.gd——本类不拼呈现字符串。 # T3 拆件批(2026-10-02,规范 1.1 单一职责):结算行排播泵迁 row_pacer.gd(本类只入队/排空/读队列, -# 探针/测试委托面 _row_queue/pace_delay_for/_flush_row_queue 原位保留);魔法道具两步交互迁 -# aux_interact_controller.gd(本类只接线与转发意图,无目标使用显式化——哨兵坐标不出控制器); +# 探针/测试委托面 _row_queue/pace_delay_for/_flush_row_queue 原位保留);秘宝两步交互迁 +# treasure_interact_controller.gd(本类只接线与转发意图,无目标使用显式化——哨兵坐标不出控制器); # GP 冒险钱包影子账迁 gp_shadow_ledger.gd(本类留探针同名读写委托面)。模态开合全量走 # _open_modal/_close_modal 单口,输入锁=modal_stack.has_open() 开态查询+三例外;battle 收尾反馈与 # 结算视觉 setter 收敛 hud_presenter 单通道(时序敏感演出触发留本类并注释);settlement 相位读取改经 # presentation_snapshot 成文面、变异表读取直读本根 db(settlement.db 即同一实例)——禁 # settlement.action_economy / settlement.db 链式穿透。 # ADR-0001 纪律:呈现层永不直接订阅 排雷玩法/行动经济——只订 战斗结算/runner 转发信号;相位读取仅用于 -# 驱动视图状态;信号连接只在组合根(row_pacer/aux_interact_controller 零连接,只收注入)。 +# 驱动视图状态;信号连接只在组合根(row_pacer/treasure_interact_controller 零连接,只收注入)。 extends Control const UiAssembler := preload("res://presentation/ui_assembler.gd") @@ -36,7 +36,7 @@ const ModalStack := preload("res://presentation/modal_stack.gd") const TuneSimController := preload("res://presentation/tune_sim_controller.gd") const DebugSessionScript := preload("res://presentation/debug_session.gd") const RowPacer := preload("res://presentation/row_pacer.gd") # 结算行排播泵(T3 拆件批) -const AuxInteractController := preload("res://presentation/aux_interact_controller.gd") # 魔法道具两步交互(T3 拆件批) +const TreasureInteractController := preload("res://presentation/treasure_interact_controller.gd") # 秘宝两步交互(T3 拆件批) const GpShadowLedgerScript := preload("res://presentation/gp_shadow_ledger.gd") # GP 影子账本(T3 拆件批) const BonusInteractController := preload("res://presentation/bonus_interact_controller.gd") # 三选一与替换子交互(T4/D4 拆件批) const CampShopPresenter := preload("res://presentation/camp_shop_presenter.gd") # 营地/商店投影(T4/D4 拆件批) @@ -90,7 +90,7 @@ var settlement_fx: SettlementFxView # 结算演出覆盖层(跨区弹道 # T3 拆件批(2026-10-02)——三件迁出后的组合根持有面(职责见各类头注;装配见 _build_ui) var _row_pacer = null # 结算行排播泵(row_pacer.gd——本类只入队/排空/读队列) -var _aux = null # 魔法道具两步交互(aux_interact_controller.gd——本类只接线与转发意图) +var _treasure_ui = null # 秘宝两步交互(treasure_interact_controller.gd——本类只接线与转发意图) var _bonus = null # 三选一与替换子交互(bonus_interact_controller.gd——本类只接线与回调注入) var _camp_pres = null # 营地/商店投影(camp_shop_presenter.gd——本类只接线、探针缝保缝转发) var _gp_ledger := GpShadowLedgerScript.new() # GP 冒险钱包影子账(gp_shadow_ledger.gd——wallet 事件投喂) @@ -217,13 +217,13 @@ func _build_ui() -> void: _row_pacer.refresh_request = _refresh_presentations _row_pacer.pump_ended = _on_pump_ended # T17 v3.1+演播后排窗——边沿统一派发(挂起 modal 优先,其次锁期点击重放) # T17 v3.1——演播完边沿重放锁期点击(合并批接线) add_child(_row_pacer) - # 魔法道具两步交互(T3 拆件批——迁 aux_interact_controller.gd;settlement/runner 随关卡更替, + # 秘宝两步交互(T3 拆件批——迁 treasure_interact_controller.gd;settlement/runner 随关卡更替, # 经现值回调注入——仿 identity_resolver 只读回调先例) - _aux = AuxInteractController.new(db, meta, info_panel, board_zone.toast, board_view, + _treasure_ui = TreasureInteractController.new(db, meta, info_panel, board_zone.toast, board_view, func() -> Variant: return settlement, func() -> Variant: return runner) board_zone.action_requested.connect(_on_board_action) - info_panel.aux_slot_clicked.connect(_aux.on_slot_clicked) # 迭代 7 T4——两步交互第一步 + info_panel.treasure_slot_clicked.connect(_treasure_ui.on_slot_clicked) # 迭代 7 T4——两步交互第一步 board_zone.stop_pressed.connect(_on_stop_pressed) board_zone.refresh_confirmed.connect(_on_refresh_confirmed) board_zone.legend_toggled.connect(_on_legend_toggled) @@ -434,7 +434,7 @@ func _resume_from_menu() -> void: log_view.clear() logger.start_session(int(bp.get("master_seed", 0))) adventure.set_hero_override(debug_overlay.atk_pct(), debug_overlay.hp_pct()) - if not adventure.resume_adventure(bp, {"hero_override": meta.hero_override() if meta != null else {}, "aux_unlocked": _aux.unlocked_set()}): + if not adventure.resume_adventure(bp, {"hero_override": meta.hero_override() if meta != null else {}, "treasure_unlocked": _treasure_ui.unlocked_set()}): _fatal_screen("续玩恢复失败——见输出日志") return @@ -452,7 +452,7 @@ func _wire_adventure() -> void: # 迭代 10 奖励重构批——big_reward_paid 退役,三选一信号族接线 adventure.bonus_choice_presented.connect(_bonus.on_presented) adventure.bonus_resolved.connect(_bonus.on_resolved) - adventure.aux_replace_presented.connect(_bonus.on_aux_replace_presented) + adventure.treasure_replace_presented.connect(_bonus.on_treasure_replace_presented) adventure.adventure_finished.connect(_on_adventure_finished) adventure.level_started.connect(_on_adventure_level_started) adventure.set_save_manager(save_manager) # 断点承载注入(迭代 8 卡①——停点快照写盘;调试/模拟不经过此路径) @@ -472,7 +472,7 @@ func _start_adventure() -> void: # 永久强化注入(元进度实现批):冒险开始参数面——meta 现算 override 显式传参(全零 = 白板) # 首次冒险脚本(关卡节点图生成 v0.4):存档布尔位 false = 全关固定模板 0(教学重放);置位后逐关抽签 var first_script: bool = not save_manager.is_first_adventure_done() - if not adventure.start_adventure(seed_val, {"hero_override": meta.hero_override() if meta != null else {}, "first_script": first_script, "aux_unlocked": _aux.unlocked_set(), "shop_mode": "pool"}): + if not adventure.start_adventure(seed_val, {"hero_override": meta.hero_override() if meta != null else {}, "first_script": first_script, "treasure_unlocked": _treasure_ui.unlocked_set(), "shop_mode": "pool"}): _fatal_screen("冒险启动失败——见输出日志") return @@ -954,17 +954,17 @@ func _on_board_action(cell: Vector2i, kind: String) -> void: if not _row_queue.is_empty(): _locked_click = {"cell": cell, "kind": kind} return - # 魔法道具选中态劫持(迭代 7 T4——两步交互第二步):点格=使用目标拾取,不落挖格; + # 秘宝选中态劫持(迭代 7 T4——两步交互第二步):点格=使用目标拾取,不落挖格; # 只劫持挖掘点击(move/flag 语义不冲突——选中期玩家仍可移动/插旗) - var aux_sel: int = _aux.active_selection() - if aux_sel != 0 and kind == "dig": - _aux.attempt_use(aux_sel, cell) + var treasure_sel: int = _treasure_ui.active_selection() + if treasure_sel != 0 and kind == "dig": + _treasure_ui.attempt_use(treasure_sel, cell) return var outcomes: Array = settlement.minesweeper.settle_batch([{"action": kind, "cell": cell}]) var accepted: bool = not outcomes.is_empty() and bool(outcomes[0].accepted) logger.log_action(kind, cell, accepted) - if runner != null and runner.aux_inventory != null: - _aux.refresh_slots() # 迭代 7 T4——授予发生在 settle_batch 结算段内(同步走完,行尾重查) + if runner != null and runner.treasure_inventory != null: + _treasure_ui.refresh_slots() # 迭代 7 T4——授予发生在 settle_batch 结算段内(同步走完,行尾重查) _handle_outcome_feedback(outcomes[0] if not outcomes.is_empty() else {}) # settle_batch 内部同步走完 结算→战斗结束→关卡推进(事件同步发射)——关卡终局时 settlement 已被 # runner 置空,清图演出判定须先判 settlement(基线既有重入隐患,2026-09-13 加固) diff --git a/game/presentation/aux_interact_controller.gd b/game/presentation/treasure_interact_controller.gd similarity index 75% rename from game/presentation/aux_interact_controller.gd rename to game/presentation/treasure_interact_controller.gd index dcff5fd8..51613b21 100644 --- a/game/presentation/aux_interact_controller.gd +++ b/game/presentation/treasure_interact_controller.gd @@ -1,17 +1,17 @@ # VERTICAL SLICE - NOT FOR PRODUCTION -# 魔法道具两步交互控制器(迭代 7 T4;T3 拆件批 2026-10-02 自 main.gd 迁出——规范 1.1 单一职责): +# 秘宝两步交互控制器(迭代 7 T4;T3 拆件批 2026-10-02 自 main.gd 迁出——规范 1.1 单一职责): # C 区槽位选中/取消(toggle)→ 棋盘点格使用目标拾取的两步交互状态机 + 库存/叠加层只读投影装配。 # 数据源 = runner 级库存只读面(query_inventory/query_overlays)+ 表行投影(display_name/target/effect_kinds); -# 写调用唯一经 战斗结算.use_aux(core 侧四步编排——拒绝零消耗 toast 可辨认)。 +# 写调用唯一经 战斗结算.use_treasure(core 侧四步编排——拒绝零消耗 toast 可辨认)。 # 装配纪律:settlement/runner 随关卡逐关更替——经组合根现值回调注入(仿 identity_resolver 只读回调 # 先例);呈现句柄(信息面板/toast/棋盘叠加层)由组合根注入;ADR-0001——信号连接不在此发生, -# info_panel.aux_slot_clicked 由组合根接至 on_slot_clicked。 +# info_panel.treasure_slot_clicked 由组合根接至 on_slot_clicked。 # 无目标使用显式化(T3 收口):AP 类(target=none)本无坐标可给——原调用面伪造 Vector2i(-9,-9) # 哨兵坐标;现调用面一律 attempt_use(handle)(cell 缺省=null=显式「无目标」),core 契约的 -# Vector2i 形参收口于本类常量(aux_items.validate_use 对 ap 行忽略目标值,哨兵不出本类)。 +# Vector2i 形参收口于本类常量(treasure_items.validate_use 对 ap 行忽略目标值,哨兵不出本类)。 extends RefCounted -const NO_TARGET := Vector2i(-9, -9) # core use_aux 形参占位(仅 target=none 行到达——validate_use 忽略该值) +const NO_TARGET := Vector2i(-9, -9) # core use_treasure 形参占位(仅 target=none 行到达——validate_use 忽略该值) var db var meta # 解锁门控数据源(工坊解锁×活行交集——冒险开始组装;组合根 _ready 建立后注入) @@ -35,12 +35,12 @@ func _init(db_ref, meta_ref, info_panel_ref: HeroInfoPanelView, toast_ref: Toast # aux 解锁门控集组装(迭代 7 T5——拍板③甲:工坊解锁 ∩ 过渡活行词表;罗盘退役/失义件/同调行不入集 -# ——迭代 11 第①批 T1 切 aux_transitional_rows 口径,同调行永不入过渡渠道) +# ——迭代 11 第①批 T1 切 treasure_transitional_rows 口径,同调行永不入过渡渠道) func unlocked_set() -> Dictionary: var out := {} if meta == null: return out - for row in db.aux_transitional_rows(): + for row in db.treasure_transitional_rows(): var iid := String(row.get("item_id", "")) if meta.is_item_unlocked(iid): out[iid] = true @@ -56,7 +56,7 @@ func active_selection() -> int: func on_slot_clicked(slot_handle: int) -> void: var settlement = _settlement_get.call() var runner = _runner_get.call() - if settlement == null or runner == null or runner.aux_inventory == null: + if settlement == null or runner == null or runner.treasure_inventory == null: return if slot_handle == 0: _use_selection = 0 @@ -69,7 +69,7 @@ func on_slot_clicked(slot_handle: int) -> void: break if rec.is_empty() or bool(rec.get("used", false)): return - var arow: Dictionary = db.aux_item_row(String(rec.get("item_id", ""))) + var arow: Dictionary = db.treasure_item_row(String(rec.get("item_id", ""))) if String(arow.get("target", "none")) == "none": attempt_use(slot_handle) # AP 类:显式无目标即用(不再伪造哨兵坐标) return @@ -82,13 +82,13 @@ func on_slot_clicked(slot_handle: int) -> void: toast.show_toast("%s:点击目标格使用(9 宫窗口),再点道具取消" % String(rec.get("name", "")), "info") -# 使用受理(第二步;cell=空间类目标格,null=无目标;core 侧 use_aux 四步编排——拒绝零消耗 toast 可辨认) +# 使用受理(第二步;cell=空间类目标格,null=无目标;core 侧 use_treasure 四步编排——拒绝零消耗 toast 可辨认) func attempt_use(handle: int, cell: Variant = null) -> void: var settlement = _settlement_get.call() if settlement == null: return var target: Vector2i = cell if cell != null else NO_TARGET - var v: Dictionary = settlement.use_aux(handle, target) + var v: Dictionary = settlement.use_treasure(handle, target) if not bool(v.ok): toast.show_toast(String(v.get("reason", "无法使用")), "warn") return @@ -96,14 +96,14 @@ func attempt_use(handle: int, cell: Variant = null) -> void: refresh_slots() refresh_overlays() board_view.refresh() # 迭代 13 T8/D6——移除格即时落图(无移除态的件 diff 零变化幂等) - var arow: Dictionary = db.aux_item_row(String(v.get("item_id", ""))) + var arow: Dictionary = db.treasure_item_row(String(v.get("item_id", ""))) toast.show_toast("已使用 %s" % String(arow.get("display_name", "")), "info") # 库存投影(C 区四槽取数面——字形=名首字;usable=板级零信息预判回调接排雷玩法只读面) func inventory_projection() -> Array: var runner = _runner_get.call() - if runner == null or runner.aux_inventory == null: + if runner == null or runner.treasure_inventory == null: return [] var settlement = _settlement_get.call() var ms = settlement.minesweeper if settlement != null else null @@ -112,8 +112,8 @@ func inventory_projection() -> Array: cb = func(_c: Vector2i) -> bool: return ms.has_unrevealed() # 只读查询面(排雷玩法 has_unrevealed——手搓全板双循环收口) var out: Array = [] - for rec in runner.aux_inventory.query_inventory(cb): - var arow: Dictionary = db.aux_item_row(String(rec.get("item_id", ""))) + for rec in runner.treasure_inventory.query_inventory(cb): + var arow: Dictionary = db.treasure_item_row(String(rec.get("item_id", ""))) var dn := String(arow.get("display_name", "")) out.append({ "handle": int(rec.get("handle", 0)), @@ -127,13 +127,13 @@ func inventory_projection() -> Array: func refresh_slots() -> void: - info_panel.set_aux_inventory(inventory_projection(), _use_selection) + info_panel.set_treasure_inventory(inventory_projection(), _use_selection) # 叠加层投影注入(use 成功/三清后——棋盘标记与预读徽章重算) func refresh_overlays() -> void: var runner = _runner_get.call() - if runner == null or runner.aux_inventory == null or board_view == null: + if runner == null or runner.treasure_inventory == null or board_view == null: return - var ov: Dictionary = runner.aux_inventory.query_overlays() - board_view.set_aux_overlays(ov.get("mine_reveal", []), ov.get("reward_preview", [])) + var ov: Dictionary = runner.treasure_inventory.query_overlays() + board_view.set_treasure_overlays(ov.get("mine_reveal", []), ov.get("reward_preview", [])) diff --git a/game/presentation/aux_interact_controller.gd.uid b/game/presentation/treasure_interact_controller.gd.uid similarity index 100% rename from game/presentation/aux_interact_controller.gd.uid rename to game/presentation/treasure_interact_controller.gd.uid diff --git a/game/presentation/views/board_cell_unit.gd b/game/presentation/views/board_cell_unit.gd index d98f3995..6fb8e04e 100644 --- a/game/presentation/views/board_cell_unit.gd +++ b/game/presentation/views/board_cell_unit.gd @@ -82,7 +82,7 @@ var tex_base: Texture2D = null # ① 砖面底 var tex_mutation: Texture2D = null # ② 变异纹带 var tex_glyph: Texture2D = null # ③ 数字 var tex_badge: Texture2D = null # ③' 徽章 -var tex_flag: Texture2D = null: # ④ 旗(T17 修复:槽位可运行时换装〔插旗〕——同族 facade/aux_mark +var tex_flag: Texture2D = null: # ④ 旗(T17 修复:槽位可运行时换装〔插旗〕——同族 facade/treasure_mark set(v): # 均 setter 触发重绘;旧普通 var 赋值不重绘=旗插上不显示) if tex_flag != v: tex_flag = v @@ -95,13 +95,13 @@ var facade_strip := false: # E 格开关(BoardView paint 按「已开 # 变异角标(迭代 6 T6——程序化,tex_mutation 纹带槽留给变异纹带六型自产批): # "flat_damage" = 未开格伤害型变异,左下角危险红三角(开格有代价的策略纹理标记) -# 叠加层标记(迭代 7 T4——魔法道具板级叠加层的格面呈现;派生信息层零回写): +# 叠加层标记(迭代 7 T4——秘宝板级叠加层的格面呈现;派生信息层零回写): # "mine_reveal" = 真视格(危险红内缩框——「这格是雷」的确定决策标记,插旗照常计费); # "reward_preview" 格不复用本字段——预读徽章走 badge_glyph 注入(board_view refresh 注入 REWARD_BADGE 字形) -var aux_mark := "": +var treasure_mark := "": set(v): - if aux_mark != v: - aux_mark = v + if treasure_mark != v: + treasure_mark = v queue_redraw() var mutation_mark := "": set(v): @@ -212,8 +212,8 @@ func _draw() -> void: draw_texture_rect(tex_mutation, rect, false) # ②' 变异角标(迭代 6 T6):左下角危险红三角(危险红=「开此格有代价」语义位,与雷族同源; # 尺寸随格边比例——灰色可辨辅助=红对砖面明度差,禁喧宾) - # ②" 魔法道具叠加层(迭代 7 T4):真视格=危险红内缩框(策略纹理——确定决策输入不喧宾) - if aux_mark == "mine_reveal": + # ②" 秘宝叠加层(迭代 7 T4):真视格=危险红内缩框(策略纹理——确定决策输入不喧宾) + if treasure_mark == "mine_reveal": var inset := edge * 0.14 draw_rect(Rect2(inset, inset, edge - inset * 2.0, edge - inset * 2.0), Color(UiKit.RED_MINE, 0.9), false, 2.0) diff --git a/game/presentation/views/board_view.gd b/game/presentation/views/board_view.gd index 5c540ba8..f3d6a41c 100644 --- a/game/presentation/views/board_view.gd +++ b/game/presentation/views/board_view.gd @@ -98,8 +98,8 @@ var _minesweeper = null # 排雷玩法 只读查询引用(refresh var _identity_cb := Callable() # 地图战斗资源 身份解析回调(组合根注入只读面)——Vector2i → Dictionary/null var _mask_cb := Callable() # 地形变异 数字遮蔽回调(组合根注入只读面)——Vector2i → bool(true = 该格数字不显示) var _vmark_cb := Callable() # 地形变异 角标回调(迭代 6 T6 只读面)——Vector2i → String("flat_damage"=伤害型变异未开格;""=无) -var _aux_reveal := {} # 魔法道具 真视集(迭代 7 T4——Vector2i → true;组合根 set_aux_overlays 注入投影) -var _aux_preview := {} # 魔法道具 预读集(同上——未开格徽章呈现挂点) +var _treasure_reveal := {} # 秘宝 真视集(迭代 7 T4——Vector2i → true;组合根 set_treasure_overlays 注入投影) +var _treasure_preview := {} # 秘宝 预读集(同上——未开格徽章呈现挂点) var _diggable := {} # 可挖域(8 向相邻未开格)——呼吸微光作用集 var _breath_t := 0.0 var _contact_unit: Node2D = null # 接触带承载单元(=英雄格 CellUnit;rebuild 随清场复位) @@ -220,14 +220,14 @@ func set_variant_mask_resolver(cb: Callable) -> void: func set_variant_mark_resolver(cb: Callable) -> void: _vmark_cb = cb -# 魔法道具叠加层投影注入(迭代 7 T4——组合根在 use 成功/三清后调;refresh 消费) -func set_aux_overlays(reveal_cells: Array, preview_cells: Array) -> void: - _aux_reveal.clear() - _aux_preview.clear() +# 秘宝叠加层投影注入(迭代 7 T4——组合根在 use 成功/三清后调;refresh 消费) +func set_treasure_overlays(reveal_cells: Array, preview_cells: Array) -> void: + _treasure_reveal.clear() + _treasure_preview.clear() for c in reveal_cells: - _aux_reveal[Vector2i(c)] = true + _treasure_reveal[Vector2i(c)] = true for c in preview_cells: - _aux_preview[Vector2i(c)] = true + _treasure_preview[Vector2i(c)] = true refresh() @@ -795,11 +795,11 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void: if south_in and not _minesweeper.is_revealed(south_n) and _tiles_ok: u.facade_strip = true u.tex_facade = _tiles.get("wall_center") - # ②( 魔法道具叠加层(迭代 7 T4):真视格=红内缩框;预读格=奖励身份徽章(identity_resolver 既有 + # ②( 秘宝叠加层(迭代 7 T4):真视格=红内缩框;预读格=奖励身份徽章(identity_resolver 既有 # 只读面取字形——零数据复制,badge 位复用);已开格标记自然退位(refresh 逐拍重算) if not revealed: - u.aux_mark = "mine_reveal" if _aux_reveal.has(c) else "" - if _aux_preview.has(c) and glyph == "": + u.treasure_mark = "mine_reveal" if _treasure_reveal.has(c) else "" + if _treasure_preview.has(c) and glyph == "": var pid = _identity_cb.call(c) if _identity_cb.is_valid() else null if pid != null and REWARD_BADGE.has(String(pid.get("cell_type", ""))): glyph = String(REWARD_BADGE[String(pid.get("cell_type", ""))]) diff --git a/game/presentation/views/bonus_pick_overlay.gd b/game/presentation/views/bonus_pick_overlay.gd index 1001ebe2..1056142c 100644 --- a/game/presentation/views/bonus_pick_overlay.gd +++ b/game/presentation/views/bonus_pick_overlay.gd @@ -172,7 +172,7 @@ func show_result(text: String) -> void: visible = true -# 同调位替换子态(aux_replace_presented 到达):items = [{index, item_id, display_name}](组合根 +# 同调位替换子态(treasure_replace_presented 到达):items = [{index, item_id, display_name}](组合根 # 喂显示名)。两路出口:丢旧收新(逐件钮)/ 放弃新件——终态恒 ≤ 同调位由核心受理面保证。 func open_replace(items: Array, incoming_name: String, holding: int, slots: int) -> void: _label.text = "同调位已满(%d/%d)——收下「%s」需丢弃一件已有道具,或放弃新件" % [holding, slots, incoming_name] diff --git a/game/presentation/views/hero_info_panel_view.gd b/game/presentation/views/hero_info_panel_view.gd index 3add280e..0326a0c4 100644 --- a/game/presentation/views/hero_info_panel_view.gd +++ b/game/presentation/views/hero_info_panel_view.gd @@ -1,6 +1,6 @@ # VERTICAL SLICE - NOT FOR PRODUCTION # 实现 GDD:design/ux/battle.md(C 区角色信息 240×548——2026-09-26 信息归属拍板精简: -# 攻击(+修正来源角标)/护甲 AC 数据框 + 魔法道具槽(预留)+ 特性列表(预留)。 +# 攻击(+修正来源角标)/护甲 AC 数据框 + 秘宝槽(预留)+ 特性列表(预留)。 # HP 条/立绘占位/状态效果槽/RAP 池/GP/钥石退役——HP 与状态唯一展示面 = B 区站桩(同一数据 # hud_presenter 双投喂 B/C 两区的重复展示);RAP 迁 D 区 AP 条(贴弃图刷新消费口); # GP(中循环)/钥石(大循环)迁出战斗屏)。 @@ -14,11 +14,11 @@ const COL_INK := UiKit.INK var _atk_label: Label var _armor_label: Label -signal aux_slot_clicked(handle: int) # 迭代 7 T4——槽点击(组合根消费:AP 类即用/空间类进选中态) -var item_slots: HBoxContainer # 魔法道具槽(迭代 7 T4 接线——库存条常读+两步交互第一步) +signal treasure_slot_clicked(handle: int) # 迭代 7 T4——槽点击(组合根消费:AP 类即用/空间类进选中态) +var item_slots: HBoxContainer # 秘宝槽(迭代 7 T4 接线——库存条常读+两步交互第一步) var _slot_panels: Array = [] # 槽 PanelContainer 引用(选中高亮/置灰重刷) var _selected_handle := 0 # 选中态(0=无;组合根回写维持单源) -var _slot_handles: Array = [] # 槽位→handle 映射(set_aux_inventory 刷新) +var _slot_handles: Array = [] # 槽位→handle 映射(set_treasure_inventory 刷新) var _bonus_section: VBoxContainer # 特性(预留——空态隐藏,接线归大奖励/锻造呈现批) var _bonus_list: VBoxContainer var _relic_section: VBoxContainer # 特性持有段(迭代 12 呈现补齐——空态隐藏) @@ -51,9 +51,9 @@ func _init() -> void: _armor_label = _data_line() data_col.add_child(_armor_label) - # 魔法道具槽(预留):随身战斗用道具的唯一展示面——空槽占位承诺格子在此, - # 不预设交互(挖掘期指向交互归 E 区既有裁决);终稿样式/槽位数归魔法道具批 - col.add_child(UiKit.label("魔法道具", 16, true)) + # 秘宝槽(预留):随身战斗用道具的唯一展示面——空槽占位承诺格子在此, + # 不预设交互(挖掘期指向交互归 E 区既有裁决);终稿样式/槽位数归秘宝批 + col.add_child(UiKit.label("秘宝", 16, true)) item_slots = HBoxContainer.new() item_slots.add_theme_constant_override("separation", 10) col.add_child(item_slots) @@ -66,7 +66,7 @@ func _init() -> void: slot.gui_input.connect(func(ev: InputEvent): if ev is InputEventMouseButton and ev.pressed and ev.button_index == MOUSE_BUTTON_LEFT: # 空槽/越界槽点击=取消选中(handle 0);有效槽发其 handle(组合根判 AP 即用/进选中态) - aux_slot_clicked.emit(_slot_handles[idx] if idx < _slot_handles.size() else 0)) + treasure_slot_clicked.emit(_slot_handles[idx] if idx < _slot_handles.size() else 0)) item_slots.add_child(slot) _slot_panels.append(slot) @@ -162,11 +162,11 @@ func _data_line() -> Label: l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS return l -# ---- 魔法道具库存条(迭代 7 T4——C 区四槽常读+两步交互第一步)---- +# ---- 秘宝库存条(迭代 7 T4——C 区四槽常读+两步交互第一步)---- # 投影行 = {handle, glyph, name, used, usable}(组合根组装:字形=道具名首字;数据源 runner 级库存只读面)。 # 空槽=虚位;used=暗态「已用」保留占位(Used 不可逆——受理序展示语义);不可用=置灰(板级零信息); # selected=金框高亮(两步交互第一步的可见态)。tooltip=全名+维度语义。 -func set_aux_inventory(items: Array, selected_handle: int) -> void: +func set_treasure_inventory(items: Array, selected_handle: int) -> void: _selected_handle = selected_handle _slot_handles.clear() for i in 4: @@ -175,7 +175,7 @@ func set_aux_inventory(items: Array, selected_handle: int) -> void: c.queue_free() if i >= items.size(): _slot_handles.append(0) - slot.tooltip_text = "魔法道具槽(空)" + slot.tooltip_text = "秘宝槽(空)" slot.add_theme_stylebox_override("panel", UiKit.panel_flat(UiKit.PANEL_DATA, UiKit.PANEL_BORDER, 0, 1, Vector4(4, 4, 4, 4))) continue diff --git a/game/presentation/views/ui_kit.gd b/game/presentation/views/ui_kit.gd index 9ddf47ac..3dff1792 100644 --- a/game/presentation/views/ui_kit.gd +++ b/game/presentation/views/ui_kit.gd @@ -161,7 +161,7 @@ const TEX_ICON_HEART := "res://assets/art/ui/icon_heart.png" # const TEX_ICON_SHOVEL := "res://assets/art/ui/icon_shovel.png" # 图标·铲(挖掘系商品/锻造) const TEX_ICON_MEDKIT := "res://assets/art/ui/icon_medkit.png" # 图标·医疗包 const TEX_ICON_POUCH := "res://assets/art/ui/icon_pouch.png" # 图标·弹药袋/行动点 -const TEX_ICON_BLAST := "res://assets/art/ui/icon_blast.png" # 图标·工兵爆破(魔法道具) +const TEX_ICON_BLAST := "res://assets/art/ui/icon_blast.png" # 图标·工兵爆破(秘宝) const TEX_ICON_COINBAG := "res://assets/art/ui/icon_coinbag.png" # 图标·金币袋 const TEX_ICON_KEYSHARD := "res://assets/art/ui/icon_keyshard.png" # 图标·钥石残片 const TEX_ICON_REFRESH := "res://assets/art/ui/icon_refresh.png" # 图标·刷新(货架/候选) diff --git a/game/smoke/adventure_monte_carlo.gd b/game/smoke/adventure_monte_carlo.gd index c21fe5ea..0936e43a 100644 --- a/game/smoke/adventure_monte_carlo.gd +++ b/game/smoke/adventure_monte_carlo.gd @@ -72,7 +72,7 @@ func _initialize() -> void: var slots: int = db.attunement_growth.slots({"clear_count": 3, "boss_kill_count": 6}) var passives: Array = [] var actives: Array = [] - for r in db.aux_attunement_rows(): + for r in db.treasure_attunement_rows(): if String(r.get("form", "")) == "passive": passives.append(String(r.get("item_id", ""))) elif String(r.get("form", "")) == "active_charged": diff --git a/game/smoke/level_autoplay.gd b/game/smoke/level_autoplay.gd index fce5a090..8ccb32cd 100644 --- a/game/smoke/level_autoplay.gd +++ b/game/smoke/level_autoplay.gd @@ -153,7 +153,7 @@ static func run_adventure(db, seed_val: int, atk_pct: int, hp_pct: int, collect_ # 道具件满位替换放弃新件、兑付后推进下一关——零随机流自开,同种子逐位可复放) adr.bonus_choice_presented.connect(_on_adventure_bonus.bind(st, adr)) adr.bonus_resolved.connect(_on_adventure_bonus_resolved.bind(st, adr)) - adr.aux_replace_presented.connect(_on_adventure_aux_replace.bind(st, adr)) + adr.treasure_replace_presented.connect(_on_adventure_treasure_replace.bind(st, adr)) adr.adventure_finished.connect(_on_adventure_finished.bind(st, logger)) adr.set_hero_override(atk_pct, hp_pct) # 同调分层注入(迭代 11 第①批 T8——缺省 {} 与既有调用方逐位一致零行为变更) @@ -302,8 +302,8 @@ static func _pick_token(candidates: Array, relic_mode: String = "off") -> Dictio # 同调位满位替换子交互(确定性策略:放弃新件不获取——分发面按停点上下文裁决节点/通关渠道) -static func _on_adventure_aux_replace(items: Array, incoming: Dictionary, st: Dictionary, adr) -> void: - st.reward_events.append({"aux_replace": incoming.duplicate(true)}) +static func _on_adventure_treasure_replace(items: Array, incoming: Dictionary, st: Dictionary, adr) -> void: + st.reward_events.append({"treasure_replace": incoming.duplicate(true)}) if not adr.resolve_bonus_replace(-1): st.result = "advance_failed" diff --git a/game/smoke/smoke_all.gd b/game/smoke/smoke_all.gd index a389b650..836d9492 100644 --- a/game/smoke/smoke_all.gd +++ b/game/smoke/smoke_all.gd @@ -543,7 +543,7 @@ func _smoke_adventure() -> void: # ⑪ 池耗即枯竭 + 池收缩 + 满血回 0(TP0——white-box:耗尽 attack/ap 令牌后候选零出现; # 种类次数上限退役,「达上限剔除」语义由牌库耗尽承载) var a11 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(11)) - check(a11.start_adventure(11, {"first_script": true, "aux_unlocked": {"blast_kit": true}}), + check(a11.start_adventure(11, {"first_script": true, "treasure_unlocked": {"blast_kit": true}}), "剔牌库/替换场景:冒险启动(seed 11——道具解锁集只含 blast_kit)") for di in range(a11._bonus_deck.size() - 1, -1, -1): var dk := String((a11._bonus_deck[di] as Dictionary).get("kind", "")) @@ -558,13 +558,13 @@ func _smoke_adventure() -> void: check((draw as Array).size() >= 2, "池耗后候选恒 ≥2(稀有/罕见档余量——防「三选项全不可选」死角)") # 池收缩(迭代 11 同调批 T7——aux 卡退役出三选一牌库:重复抽样零 aux 候选;同调位替换两路 # white-box 测试随停点渠道退役拆除——机械惰性承载,零投放零行为) - var aux_seen := false + var treasure_seen := false for i in 40: for t in a11._draw_bonus_candidates(): - if String((t as Dictionary).get("kind", "")) == "aux_item": - aux_seen = true + if String((t as Dictionary).get("kind", "")) == "treasure_item": + treasure_seen = true break - check(not aux_seen, "池收缩——40 次重抽零 aux 候选(停点渠道 aux 卡退役,迭代 11 第①批 T7)") + check(not treasure_seen, "池收缩——40 次重抽零 aux 候选(停点渠道 aux 卡退役,迭代 11 第①批 T7)") # 满血回 0 合法(通关回血封顶口径) var a12 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(12)) a12.start_adventure(12, {"first_script": true}) @@ -577,7 +577,7 @@ func _smoke_adventure() -> void: "满血通关回血 0 合法(封顶口径——heal_gained=0 非负溢出)") # ⑬ 奖励节点共享池(迭代 10 追加批——同库同池同摘牌;TP0:attack 令牌耗尽后节点域同样零出现) var a13 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(13)) - check(a13.start_adventure(13, {"first_script": true, "aux_unlocked": {"blast_kit": true}}), + check(a13.start_adventure(13, {"first_script": true, "treasure_unlocked": {"blast_kit": true}}), "节点共享池场景:冒险启动(seed 13)") for di13 in range(a13._bonus_deck.size() - 1, -1, -1): if String((a13._bonus_deck[di13] as Dictionary).get("kind", "")) == "attack": @@ -2602,9 +2602,9 @@ func _smoke_negative_dictionary() -> void: if r0.has(c) or by_type.size() == 5: continue var ident = settlement.query_reward_identity(c) - # aux 身份不入五型轴(魔法道具内容批 2026-09-29——五型齐备=格面资源历史断言轴, + # aux 身份不入五型轴(秘宝内容批 2026-09-29——五型齐备=格面资源历史断言轴, # aux 供给挤占不改变本断言语义;扫描排除 aux 身份格) - if ident != null and String(ident.cell_type) != RewardTable.AUX_ITEM_TYPE and not by_type.has(String(ident.cell_type)): + if ident != null and String(ident.cell_type) != RewardTable.TREASURE_ITEM_TYPE and not by_type.has(String(ident.cell_type)): by_type[String(ident.cell_type)] = c # break 条件=percent_map 三型齐备(迭代 7 T1——aux 供给挤占下 weaken/defense 收集时机漂移, # 直验可达性优先;五型多样性 check 保留不动) @@ -2679,7 +2679,7 @@ func _smoke_resource_surface() -> void: check(digchain_bad == 0, "chain/dig 揭示事件 resource 恒 true(雷安同池——违例 %d)" % digchain_bad) check(initial_bad == 0 and initial_count >= 1, "initial 揭示事件(封锁格)resource 恒 false(×%d 事件)" % initial_count) check(mine_with_resource >= 1, "雷格揭示携带资源(mine ×resource=true %d——雷格不再恒无)" % mine_with_resource) - # 封锁格无身份 / 雷格未开恒可查(未开格恒可查——魔法道具 桥接结构前提) + # 封锁格无身份 / 雷格未开恒可查(未开格恒可查——秘宝 桥接结构前提) var rng3 = load("res://core/rng_service.gd").new() rng3.set_master_seed(20260920) var settlement = load("res://core/battle_orchestrator.gd").new(_db, rng3) @@ -2696,7 +2696,7 @@ func _smoke_resource_surface() -> void: break check(settlement.query_reward_identity(r0_first) == null, "封锁格(R₀)身份查询 = null(不入摇号清单)") check(mine_unrevealed != null and settlement.query_reward_identity(mine_unrevealed) != null, - "未开雷格身份恒可查({reward_id, cell_type, tier}——魔法道具 桥接前提)") + "未开雷格身份恒可查({reward_id, cell_type, tier}——秘宝 桥接前提)") # 五段全序断言(战斗结算 验收"五段全序"+ 行型封闭 10 类):逐轮行相位序 = 授予 → 增益/减益 → 战斗 → 衰减 → 判定。 @@ -3895,7 +3895,7 @@ func _smoke_shop_pool() -> void: for i in 40: r8._shop_draw_shelf() for c in r8.shop_shelf(): - if String(c.get("kind_id", "")) == "gp" or String(c.get("kind_id", "")) == "aux_item": + if String(c.get("kind_id", "")) == "gp" or String(c.get("kind_id", "")) == "treasure_item": cut_seen = true check(not cut_seen, "切边件零入店(40 次重抽零 gp/aux——负交易切边+三轴 doctrine)") # ⑤ 池空硬闸(库存尽剔出牌库——TP0:white-box 耗尽 attack 令牌后货架零 attack + 消费口拒绝) @@ -3980,8 +3980,8 @@ func _all_entry_boss_paths(nodes: Array) -> Array: func _smoke_nine_types_gp_stream() -> void: print("--- 格面资源九型 + gp_drop 流(奖励字典 18 格 + 黄金向量)---") - check(RewardTable.CELL_TYPES.size() == 10 and RewardTable.CELL_TYPES.has("gp") and RewardTable.CELL_TYPES.has("aux_item"), - "格面资源十型封闭(第九型 gp 九型批 2026-09-20 / 第十型 aux_item 魔法道具内容批 2026-09-29——词表 v1.2)") + check(RewardTable.CELL_TYPES.size() == 10 and RewardTable.CELL_TYPES.has("gp") and RewardTable.CELL_TYPES.has("treasure_item"), + "格面资源十型封闭(第九型 gp 九型批 2026-09-20 / 第十型 treasure_item 秘宝内容批 2026-09-29——词表 v1.2)") var cell_rows := 0 var pos_weight := 0 var gp_pos := -1 @@ -3995,7 +3995,7 @@ func _smoke_nine_types_gp_stream() -> void: gp_pos = int(row.weight) if String(row.get("reward_id", "")) == "gp_lose": gp_neg = int(row.weight) - check(cell_rows == 18, "奖励字典 18 行(九型×正负 18 格——aux 挖格投放四行已退役 2026-10-01 用户拍板甲:战斗/挖格不掉道具,魔法道具唯一来路=三选一共享池〔节点/通关〕;清图槽独立批尾不计)") + check(cell_rows == 18, "奖励字典 18 行(九型×正负 18 格——aux 挖格投放四行已退役 2026-10-01 用户拍板甲:战斗/挖格不掉道具,秘宝唯一来路=三选一共享池〔节点/通关〕;清图槽独立批尾不计)") # 雷格负向直伤当量(迭代 8 卡⑧——真人反馈「三雷 3/4 血无后果感」投值:三行各抬 +3 档,负向≈正向 2 倍定价) var mine_power := {"heal_backlash": 6, "pierce_snare": 8, "magic_recoil": 8} # 数值修复批 2026-10-01 再抬档(旧 4/5/5,见 numfix 报告) for row in _db.reward.rows: @@ -4543,8 +4543,8 @@ func _smoke_save() -> void: var bp_visited: Array = bp.get("visited_ids", []) check(bp_visited.size() == 3 and int(bp_visited[0]) == 0 and int(bp_visited[2]) == 5, "断点附随件往返:已到节点序") - var bp_aux: Array = bp.get("aux_items", []) - check(bp_aux.size() == 1 and String(bp_aux[0].get("item_id", "")) == "aux_scout", + var bp_treasure: Array = bp.get("aux_items", []) + check(bp_treasure.size() == 1 and String(bp_treasure[0].get("item_id", "")) == "aux_scout", "断点附随件往返:道具库存") bp["hero_hp"] = 999 check(int((rb.breakpoint_snapshot() as Dictionary).get("hero_hp", -1)) == 13, diff --git a/game/smoke/ui_probe.gd b/game/smoke/ui_probe.gd index 95b54e49..f09dab87 100644 --- a/game/smoke/ui_probe.gd +++ b/game/smoke/ui_probe.gd @@ -104,7 +104,7 @@ func _ready() -> void: if main.board_zone.toast == null: problems.append("D 区 toast 槽缺失") if main.info_panel.item_slots == null or main.info_panel.item_slots.get_child_count() != 4: - problems.append("C 区魔法道具槽(预留)缺失") + problems.append("C 区秘宝槽(预留)缺失") if main.stage.hero_standee.slot_row == null: problems.append("B 区站桩状态行缺失(状态效果唯一展示面——2026-09-26 C 区精简批)") # B 区明细带挖掘期收起断言(T17 视觉扩展批适配):结算演播期 settling 视觉延伸=mode=settle diff --git a/game/tests/README.md b/game/tests/README.md index c019bdd2..ed9a53b2 100644 --- a/game/tests/README.md +++ b/game/tests/README.md @@ -32,7 +32,7 @@ godot --headless --path . res://smoke/.tscn timeout 120s godot --headless --script tests/run_all.gd ``` -> 单元/契约套件状态(单元测试与契约层批 2026-09-28 立基,后随迭代 7/8 增补):`_suites()` manifest 已登记实跑十五套件——data_config(ConfigDB 加载/进度坐标 ceil 解析/fatal 退出码/统一随机流)、core(魔法道具结构冻结/断点续玩)、battle_settlement(DamageMath 纯函数/DamageController 伤害单据五配方)、contracts(系统间接口契约断言)、presentation(节奏队列/奖励浮层/字体资产/地形瓦片集);致命类独立进程 `expect=1`。期望值一律由表读值推导(零玩法数值字面量)、随机只经 RngService 统一流。 +> 单元/契约套件状态(单元测试与契约层批 2026-09-28 立基,后随迭代 7/8 增补):`_suites()` manifest 已登记实跑十五套件——data_config(ConfigDB 加载/进度坐标 ceil 解析/fatal 退出码/统一随机流)、core(秘宝结构冻结/断点续玩)、battle_settlement(DamageMath 纯函数/DamageController 伤害单据五配方)、contracts(系统间接口契约断言)、presentation(节奏队列/奖励浮层/字体资产/地形瓦片集);致命类独立进程 `expect=1`。期望值一律由表读值推导(零玩法数值字面量)、随机只经 RngService 统一流。 **协议要点**(D2 冒烟协议 + ADR-0004): - 冒烟脚本 `extends SceneTree` 以获得 `quit(code)`;成功 `quit(0)`、失败 `quit(1)` diff --git a/game/tests/run_all.gd b/game/tests/run_all.gd index 9b129d2f..388d5345 100644 --- a/game/tests/run_all.gd +++ b/game/tests/run_all.gd @@ -29,10 +29,10 @@ func _suites() -> Array: {"path": "res://tests/unit/example_test.gd", "expect": 0}, {"path": "res://tests/unit/data_config/config_db_test.gd", "expect": 0}, {"path": "res://tests/unit/data_config/config_db_fatal_oob_test.gd", "expect": 1}, - {"path": "res://tests/unit/data_config/aux_target_violation_test.gd", "expect": 1}, # 迭代 7 T1——真视窄域护栏 - {"path": "res://tests/unit/data_config/reward_dangling_aux_test.gd", "expect": 1}, # 迭代 7 T1——aux 双表校验 + {"path": "res://tests/unit/data_config/treasure_target_violation_test.gd", "expect": 1}, # 迭代 7 T1——真视窄域护栏 + {"path": "res://tests/unit/data_config/reward_dangling_treasure_test.gd", "expect": 1}, # 迭代 7 T1——秘宝双表校验 {"path": "res://tests/unit/data_config/rng_service_test.gd", "expect": 0}, - {"path": "res://tests/unit/core/aux_items_test.gd", "expect": 0}, # 迭代 7 T7——魔法道具结构冻结断言面 + {"path": "res://tests/unit/core/treasure_items_test.gd", "expect": 0}, # 迭代 7 T7——秘宝结构冻结断言面 {"path": "res://tests/unit/core/breakpoint_resume_test.gd", "expect": 0}, # 迭代 8 卡①/T9——断点往返/续玩确定性/幂等/退出清断点 {"path": "res://tests/unit/presentation/pacing_queue_test.gd", "expect": 0}, # 迭代 8 卡⑦ AC⑤/T9——排空零分叉/零丢行/延迟双态 {"path": "res://tests/unit/presentation/reward_overlay_test.gd", "expect": 0}, # 迭代 7 hotfix——奖励节点 UI 直验(盲区补漏) diff --git a/game/tests/smoke/critical-paths.md b/game/tests/smoke/critical-paths.md index c1e5e361..8cfadbb3 100644 --- a/game/tests/smoke/critical-paths.md +++ b/game/tests/smoke/critical-paths.md @@ -23,7 +23,7 @@ ## Battle & Level 10. 战斗段:主角先手攻击行(hero_attack 来源)、敌方行为环读怪(姿态↔下一拍)、死亡即不动手 -11. 胜负判定与 battle_over 清理全序;aux 魔法道具关内跨战斗延续(三选一 BonusPickOverlay 入包、C 区槽位两步交互施用)、关卡末"剩余道具 ×N 清空"反馈(aux_cleared) +11. 胜负判定与 battle_over 清理全序;aux 秘宝关内跨战斗延续(三选一 BonusPickOverlay 入包、C 区槽位两步交互施用)、关卡末"剩余道具 ×N 清空"反馈(aux_cleared) 12. 关卡推进:节点链兑付(奖励点/恢复点)、Boss 房(Dmax 行)、层间 HP 携带 ## Data & Perf diff --git a/game/tests/unit/battle_settlement/skill_unlock_test.gd.uid b/game/tests/unit/battle_settlement/skill_unlock_test.gd.uid new file mode 100644 index 00000000..052825af --- /dev/null +++ b/game/tests/unit/battle_settlement/skill_unlock_test.gd.uid @@ -0,0 +1 @@ +uid://csqehh43v2dn2 diff --git a/game/tests/unit/core/breakpoint_resume_test.gd b/game/tests/unit/core/breakpoint_resume_test.gd index 5e814f0e..0d30d15b 100644 --- a/game/tests/unit/core/breakpoint_resume_test.gd +++ b/game/tests/unit/core/breakpoint_resume_test.gd @@ -26,7 +26,7 @@ func _init() -> void: var sm_a = SaveManagerScript.new(_bp_path) var adr_a = AdventureRunnerScript.new(db, rng_a) adr_a.set_save_manager(sm_a) - var params := {"hero_override": {}, "aux_unlocked": {}} + var params := {"hero_override": {}, "treasure_unlocked": {}} Kit.check_quiet(adr_a.start_adventure(1234, params), "冒险启动(入口停点)") Kit.check_quiet(sm_a.has_breakpoint(), "入口停点断点在档") Kit.check_quiet(int((sm_a.breakpoint_snapshot() as Dictionary).get("level_index", -1)) == 1, "断点关卡序号 = 1") @@ -91,7 +91,7 @@ func _init() -> void: var sm_e = SaveManagerScript.new(_bp_path) var adr_e = AdventureRunnerScript.new(db, rng_e) adr_e.set_save_manager(sm_e) - var params_e := {"hero_override": {}, "aux_unlocked": {"blast_kit": true}} + var params_e := {"hero_override": {}, "treasure_unlocked": {"blast_kit": true}} Kit.check_quiet(adr_e.start_adventure(4321, params_e), "P5 冒险启动(seed 4321)") adr_e._bonus_taken["attack"] = 1 # 白盒预置计数(断点附随件往返的判据面——计数不可由加算区反推) adr_e._on_level_finished({"result": "victory", "hp": 30, "node_index": 1, "node_id": 1, "node_type": "shop"}) diff --git a/game/tests/unit/core/aux_items_test.gd b/game/tests/unit/core/treasure_items_test.gd similarity index 91% rename from game/tests/unit/core/aux_items_test.gd rename to game/tests/unit/core/treasure_items_test.gd index f78c1626..dc49d73e 100644 --- a/game/tests/unit/core/aux_items_test.gd +++ b/game/tests/unit/core/treasure_items_test.gd @@ -1,11 +1,11 @@ # VERTICAL SLICE - NOT FOR PRODUCTION -# 魔法道具 AuxItems 类单测(迭代 7 T7——结构冻结断言面;设计权威 魔法道具.md + registry aux_items)。 +# 秘宝 TreasureItems 类单测(迭代 7 T7——结构冻结断言面;设计权威 秘宝.md + registry treasure_items)。 # 覆盖:授予归因 / Used 不可逆 / 真视恒可用 / 预读点击级零信息拒绝 / 3×3 边缘窗口∩板 / # 叠加层三清(retire_overlays 不动库存)/ 关卡末 reset / 零随机(同操作序列重放两遍投影逐位)。 -# 运行:godot --headless --path game --script res://tests/unit/core/aux_items_test.gd(expect 0) +# 运行:godot --headless --path game --script res://tests/unit/core/treasure_items_test.gd(expect 0) extends SceneTree -const AuxItemsScript := preload("res://core/aux_items.gd") +const TreasureItemsScript := preload("res://core/treasure_items.gd") const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:check/汇总退出样板单点(静默收集通道) @@ -18,7 +18,7 @@ class StubTable: class StubDB: - var aux_items: StubTable + var treasure_items: StubTable func _stub_db() -> StubDB: @@ -32,12 +32,12 @@ func _stub_db() -> StubDB: "effect_kinds": ["reward_preview"], "target": "area_3x3", "magnitude": 0, "use_phase": "active_dig"}, } var db := StubDB.new() - db.aux_items = t + db.treasure_items = t return db func _new_inv() -> Object: - return AuxItemsScript.new(_stub_db()) + return TreasureItemsScript.new(_stub_db()) func _unrevealed(_c: Vector2i) -> bool: @@ -103,4 +103,4 @@ func _init() -> void: Kit.check_quiet(str(replay_a) == str(replay_b), "零随机重放:库存+叠加层+探针投影逐位相同") # ---- 汇总 ---- - quit(Kit.finish("aux_items_test", "PASS — 授予归因/Used 不可逆/真视恒可用/零信息拒绝/边缘窗口/三清/零随机重放 全过")) + quit(Kit.finish("treasure_items_test", "PASS — 授予归因/Used 不可逆/真视恒可用/零信息拒绝/边缘窗口/三清/零随机重放 全过")) diff --git a/game/tests/unit/core/aux_items_test.gd.uid b/game/tests/unit/core/treasure_items_test.gd.uid similarity index 100% rename from game/tests/unit/core/aux_items_test.gd.uid rename to game/tests/unit/core/treasure_items_test.gd.uid diff --git a/game/tests/unit/data_config/reward_dangling_aux_test.gd b/game/tests/unit/data_config/reward_dangling_treasure_test.gd similarity index 61% rename from game/tests/unit/data_config/reward_dangling_aux_test.gd rename to game/tests/unit/data_config/reward_dangling_treasure_test.gd index 7d110512..1d539e6d 100644 --- a/game/tests/unit/data_config/reward_dangling_aux_test.gd +++ b/game/tests/unit/data_config/reward_dangling_treasure_test.gd @@ -1,8 +1,8 @@ # 致命类用例(独立进程,期望退出码 1) -# reward_dangling_aux——RewardTable aux 投放行双表校验(迭代 7 T1):aux 行 effect_id 引用 retired -# 道具(loot_compass——2026-09-29 拍板①乙退役)时,config_db 跨表校验必须报 reward_dangling_aux、 +# reward_dangling_treasure——RewardTable aux 投放行双表校验(迭代 7 T1):aux 行 effect_id 引用 retired +# 道具(loot_compass——2026-09-29 拍板①乙退役)时,config_db 跨表校验必须报 reward_dangling_treasure、 # load_tables 整体拒绝(退役件/失义件不得出现在掉落投放面)。 -# 运行:godot --headless --path game --script res://tests/unit/data_config/reward_dangling_aux_test.gd +# 运行:godot --headless --path game --script res://tests/unit/data_config/reward_dangling_treasure_test.gd # 退出码协议:1 = 校验正确拒绝(预期);2 = 违规表被放行(回归信号)。 extends SceneTree @@ -10,7 +10,7 @@ const ConfigDBScript := preload("res://core/config_db.gd") const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:BAD 表目录夹具共享(copy_tables) const SRC_DIR := "res://data/tables" -const BAD_DIR := "user://aux_fixture_dangling_aux" +const BAD_DIR := "user://treasure_fixture_dangling" func _inject_violation() -> bool: @@ -22,7 +22,7 @@ func _inject_violation() -> bool: f.close() # 追加式注入(2026-10-01 战斗掉落渠道退役随批——现行表已无 aux 行可作锚):向 rows 尾追加 # 一块引用已退役 loot_compass 的 aux 投放行,双表校验须拦(retired 不入投放面)。 - var inject := ', {\n\n"reward_id": "aux_dangling_probe",\n"cell_type": "aux_item",\n"polarity": "positive",\n"effect_id": "loot_compass",\n"display_name": "悬空探针",\n"power": 0,\n"weight": 1,\n"pool_tag": "cell",\n"tier": 1\n}' + var inject := ', {\n\n"reward_id": "treasure_dangling_probe",\n"cell_type": "treasure_item",\n"polarity": "positive",\n"effect_id": "loot_compass",\n"display_name": "悬空探针",\n"power": 0,\n"weight": 1,\n"pool_tag": "cell",\n"tier": 1\n}' var idx := s.rfind("\n}]") if idx < 0: return false @@ -37,18 +37,18 @@ func _inject_violation() -> bool: func _init() -> void: if not Kit.copy_tables(SRC_DIR, BAD_DIR) or not _inject_violation(): - push_error("[reward_dangling_aux_test] 夹具目录准备失败") + push_error("[reward_dangling_treasure_test] 夹具目录准备失败") quit(2) return var db = ConfigDBScript.new() var ok: bool = db.load_tables(BAD_DIR, false) if ok: - push_error("[reward_dangling_aux_test] 违规表被放行——aux 双表校验失守(回归)") + push_error("[reward_dangling_treasure_test] 违规表被放行——aux 双表校验失守(回归)") quit(2) return if db.diagnostics_count("error") >= 1: - print("[reward_dangling_aux_test] 双表校验触发(reward_dangling_aux 诊断在案,加载被拒)") + print("[reward_dangling_treasure_test] 双表校验触发(reward_dangling_treasure 诊断在案,加载被拒)") quit(1) return - push_error("[reward_dangling_aux_test] 加载被拒但无 reward_dangling_aux 诊断——校验通道静默化(回归)") + push_error("[reward_dangling_treasure_test] 加载被拒但无 reward_dangling_treasure 诊断——校验通道静默化(回归)") quit(2) diff --git a/game/tests/unit/data_config/reward_dangling_aux_test.gd.uid b/game/tests/unit/data_config/reward_dangling_treasure_test.gd.uid similarity index 100% rename from game/tests/unit/data_config/reward_dangling_aux_test.gd.uid rename to game/tests/unit/data_config/reward_dangling_treasure_test.gd.uid diff --git a/game/tests/unit/data_config/aux_target_violation_test.gd b/game/tests/unit/data_config/treasure_target_violation_test.gd similarity index 71% rename from game/tests/unit/data_config/aux_target_violation_test.gd rename to game/tests/unit/data_config/treasure_target_violation_test.gd index 4f4fa08d..35fcd536 100644 --- a/game/tests/unit/data_config/aux_target_violation_test.gd +++ b/game/tests/unit/data_config/treasure_target_violation_test.gd @@ -1,7 +1,7 @@ # 致命类用例(独立进程,期望退出码 1) -# aux_target_violation——真视窄域护栏(魔法道具 GDD 结构冻结,迭代 7 T1):mine_reveal 行 target -# 越域至 board_wide 时,AuxItemTable.validate 必须报 load_bearing 错、load_tables 整体拒绝。 -# 运行:godot --headless --path game --script res://tests/unit/data_config/aux_target_violation_test.gd +# treasure_target_violation——真视窄域护栏(秘宝 GDD 结构冻结,迭代 7 T1):mine_reveal 行 target +# 越域至 board_wide 时,TreasureItemTable.validate 必须报 load_bearing 错、load_tables 整体拒绝。 +# 运行:godot --headless --path game --script res://tests/unit/data_config/treasure_target_violation_test.gd # 退出码协议:1 = 校验正确拒绝(预期);2 = 违规表被放行(回归信号)。 # 时序注:纯加载期校验——不触运行期 fatal 通道,断言 load_tables 返回 false + 诊断在案即 quit(1)。 extends SceneTree @@ -10,11 +10,11 @@ const ConfigDBScript := preload("res://core/config_db.gd") const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:BAD 表目录夹具共享(copy_tables) const SRC_DIR := "res://data/tables" -const BAD_DIR := "user://aux_fixture_target_violation" +const BAD_DIR := "user://treasure_fixture_target_violation" func _inject_violation() -> bool: - var path := BAD_DIR + "/aux_items.tres" + var path := BAD_DIR + "/treasure_items.tres" var f := FileAccess.open(path, FileAccess.READ) if f == null: return false @@ -44,18 +44,18 @@ func _inject_violation() -> bool: func _init() -> void: if not Kit.copy_tables(SRC_DIR, BAD_DIR) or not _inject_violation(): - push_error("[aux_target_violation_test] 夹具目录准备失败") + push_error("[treasure_target_violation_test] 夹具目录准备失败") quit(2) return var db = ConfigDBScript.new() var ok: bool = db.load_tables(BAD_DIR, false) if ok: - push_error("[aux_target_violation_test] 违规表被放行——真视窄域护栏失守(回归)") + push_error("[treasure_target_violation_test] 违规表被放行——真视窄域护栏失守(回归)") quit(2) return if db.diagnostics_count("error") >= 1: - print("[aux_target_violation_test] 护栏触发(load_bearing 诊断在案,加载被拒)") + print("[treasure_target_violation_test] 护栏触发(load_bearing 诊断在案,加载被拒)") quit(1) return - push_error("[aux_target_violation_test] 加载被拒但无 load_bearing 诊断——护栏通道静默化(回归)") + push_error("[treasure_target_violation_test] 加载被拒但无 load_bearing 诊断——护栏通道静默化(回归)") quit(2) diff --git a/game/tests/unit/data_config/aux_target_violation_test.gd.uid b/game/tests/unit/data_config/treasure_target_violation_test.gd.uid similarity index 100% rename from game/tests/unit/data_config/aux_target_violation_test.gd.uid rename to game/tests/unit/data_config/treasure_target_violation_test.gd.uid diff --git a/game/tests/unit/test_kit.gd b/game/tests/unit/test_kit.gd index e8b81bb8..80ae2ece 100644 --- a/game/tests/unit/test_kit.gd +++ b/game/tests/unit/test_kit.gd @@ -1,6 +1,6 @@ # tests/unit/test_kit.gd — 单元测试协议样板单点(T6 样板收口批 2026-10-02) # 收口范围:11 份套件的 _check/_problems 样板(计数器 + PASS/FAIL 行 + 汇总退出)+ -# reward_dangling_aux/aux_target_violation 两致命类用例各自复制的 BAD 表目录夹具。 +# reward_dangling_treasure/treasure_target_violation 两致命类用例各自复制的 BAD 表目录夹具。 # 用法(--script 模式无 autoload/全局标识符——禁 class_name 裸引用,使用方 preload): # const Kit := preload("res://tests/unit/test_kit.gd") # Kit.check("断言描述", cond) # 计数 + 即时 PASS/FAIL 行 @@ -27,7 +27,7 @@ static func check(desc: String, ok: bool) -> void: # 静默收集通道:失败只记入 problems(即时零刷屏),finish 统一汇总。 -# 参序沿原函数式套件 aux_items/breakpoint_resume 的 check(cond, msg)——条件在前,与主通道相反。 +# 参序沿原函数式套件 treasure_items/breakpoint_resume 的 check(cond, msg)——条件在前,与主通道相反。 static func check_quiet(ok: bool, desc: String) -> void: checks += 1 if not ok: @@ -49,7 +49,7 @@ static func finish(suite: String, pass_line: String = "") -> int: return 0 -# BAD 表夹具共享(原 reward_dangling_aux/aux_target_violation 各自复制的 _copy_tables): +# BAD 表夹具共享(原 reward_dangling_treasure/treasure_target_violation 各自复制的 _copy_tables): # 整目录拷贝 src_dir → bad_dir(目录已建)。BAD_DIR 常量仍由各用例自持(名字互异——独立进程并行不互踩)。 static func copy_tables(src_dir: String, bad_dir: String) -> bool: DirAccess.make_dir_recursive_absolute(bad_dir) diff --git a/roadmap.md b/roadmap.md index e1698fa1..14489d74 100644 --- a/roadmap.md +++ b/roadmap.md @@ -62,7 +62,7 @@ | 迭代 14 | **初始展开收窄批(2026-10-04 用户拍板甲乙混合立项)**:甲=先布后删剃雷域收窄至出生 3×3∪外扩 r 环(参数化半径,现值 r=1——开阔地均值从板面 66.5% 根因性降至约三成)+乙=生成重掷闸 R₀≤cap(合法性门序列、cap=板面 30% 锚〔10×10=30/12×12=43/13×13=51〕、重试耗尽走既有三分出口);**玩法侧零改动路线**(排雷玩法「初始展开恰等」验收原样为真,minesweeper_rules.gd 零 diff);裸数字截断路否决退役(可见 0 格+未开邻居=扫雷不可能态)。可行性报告=`design/research/研究-初始展开收窄可行性-2026-10-04.md`,任务书=`design/research/任务书-初始展开收窄批-2026-10-04.md`(T0-T8≈5.25d,读数批 T5-T6 可切独立后批;拍板点 P1-P3 全读数后置;停机点 S1 相变警戒/S2 带越界回调)。**✅ 实施批落地(2026-10-05,worktree m4iter14-narrow-20261005 台账 357;S1 停机呈报已裁=用户方案A)**:T0-T4+T7+T8 全落(T5 结构读数随批出讫;T6 MC 四带复算读数批按切分预案后置,跑批待用户批准挂 07 现行义务)——甲=剃雷域收窄(shave_ring_radius 参数化,r=1→出生 5×5,全域 flood 剃雷退役,零 RNG 消费变化)+乙=R₀≤cap 重掷闸(合法性闸序列+同流重试+耗尽三分出口诚实降级+r0_cap_rejected 指标)+参数面两列(schema 域校验加载期致命+19 行投值)+断言面 +12(R₀≤cap/ring_removed 量级/cap 压线诚实降级/确定性逐位)+夹具复核 3 处(relic 候选身份按 TP0 v2.2=kind|tier|relic_id、商店购买笔数推导防 GP 流漂移、极性探针种子自愈);**S1 停机实录**=r=1 自然 R₀ 均值 39>cap30 锚结构性倒挂(94% 拒绝/inf 0.976→0.719/常态非法板)→用户裁方案A「10×10 cap 30→45」〔P1 上调预案字面〕,12×12/13×13 健康侧维持;改后结构读数=R₀ 均值 39.7/37.9/42.8/46.6(收窄自 68.6/83.2——10×10 −42%、12×12 −54%)/尾部闸精确截断/雷密度 19.2-21.6%<25% 相变线/inf 全行达标;玩法侧零改动(minesweeper_rules.gd 零 diff、「初始展开恰等」验收原样为真);闸=冒烟 767/0(+12);registry initial_expansion_narrowing 条+棋盘生成.md v0.5+07⑬ 四信号组;06 视野条目已于 745b92ea 清账批退役(收窄立项即正主)。**②挖掘风险不等式判式换代批(2026-10-04 用户裁编入本迭代,作为迭代内需求)**:判式三层换代(条款2 标中旗锚/条款3 聚合健康式「(1−ρ̂)E_dig−ρ̂V_mine≥0」/旗边际引理+条件二旗溢价)+β 比值带判读 [1.2,2.5](u=3 登记态)+标中兑付溢价 δ=1.25(形态 a 兑付公式一处·雷安同池冻结不动)+runsum 旗行为五字段+audit 工具常量刷新(池 77/直伤 6-8-8/AP 8);裁决全落零新拍板点(方案报告 §九(已退役,git 1da9a41)),任务书=`.zcode/plans/mine-inequality-revision-miniloop-plan-2026-10-04.md`(T0-T5≈2.5d;条件二 T3 落文按登记已知破·T4 机制转绿;契约红线=DamageController 零改/直伤雷 6-8-8 与 p_perfect 不动——iter8 缺口四选一解绑独立在案;开工门=U0)。**✅ 实施批落地(2026-10-05,worktree m4iter14-mineq-20261005 台账 356)**:T0-T5 全落——audit 工具常量刷新(改前静态锚与方案报告 §四 逐位吻合)+runsum 五字段(行侧判据考证=授予行专带 highlight,87行==87插旗1:1)+F1 条款3 重立三层口径(v0.8)+战斗结算 v0.25+难度联动表+6 行+registry clause3_inequality 重立条(改前锚+P7 修正注记)+06 破线条收口+**T4 标中兑付溢价机制**(settlement.flag_hit_premium=125 provisional,grant 单点只挂 flag_hit 正向·percent 幅度贯穿应用与呈现,标空/挖格不乘,DamageController 零改/同池冻结)+smoke 750/0(+3 断言;max 路径种子 42→43 重采);判读三件=β 带 u=1/2 带内 u=3 登记态/δ 敏感度行为无感(η 位移 <1.4pp<5pp,保留+登记)/条件二判式口径等号压线转绿(整数量级实现 u=1/2 绿·u=3 微欠 −1.1% 登记面);改后锚换代 runsum_m4iter14mineq_post_n200_20261005(perfect 冒险通关 65.3%→72.0% 增强向位移,四带判读归 M-4);出口报告=design/qa/m4iter14-mineq-exit-report-2026-10-05.md(provisional 追认单 8 项+07⑫ 人工项);damage_probe A1 红灯=改前既有非本批新增(在册)。**③全局作用域变异首发批(2026-10-04 用户拍板立项——调研报告 P1-P8+盘问 Q1-Q4 全按推荐案落,批内序位待排)**:L2/L3 Boss 图恒定一型 scope=global 变异,首发型=**案A 资源面·微贫向偏斜**(正向格面池合计不变、进攻族 attack/blast/pierce/magic 权重上浮/生存族 heal/defense 明显下调、EV 微降 3-5% provisional、gp/action 白名单不动;v1.0「沃土+雷密对冲」形勘误作废——雷数为生成器事实、布置段不可加,改生成端=踩结构面否决理由);**替换制**(Boss 图不再布 region 片——L2 完美 Boss 承伤 55.8% 已越带不叠加;迭代 12 四件地形应对件在 Boss 图失效=知情代价,registry/调参日志随批登记);L1 Boss 免疫(带B [50,85] 教学保护);三层预告(开战横幅+HUD 常驻角标+帮助手册行);带A 判读后置 M-4(落地 off/on 对拍只测不判;off 基线=替换制后零变异 Boss 图,与现行带 region 片 Boss 图语义不同须注明);偏运硬币合成序=图级先件级后(代拍随批锚登记)。调研报告(事实源,v1.1 裁决落盘)=`design/research/调研-全局作用域变异设计空间-2026-10-04.md`,任务书已退役(git 01bfc15 批;裁决全录另见调研报告 §7)(T0-T8≈5.75d,读数批 T7 可切独立后批→主体≈5.25d;零新拍板点·provisional 追认单随批;停机点 S1 普通图逐位漂移/S2 读数越带只呈报/S3 互锁误伤;开工门=U0;**⑥A4 批开工门含本批出口——本批落地图级偏斜投影点为⑥合成链中段**〔2026-10-05 注:⑥已移出迭代 14 挂起,此依赖句冻结待其重启〕)。与①②互不撞(收窄=普通图初始展开轴/判式=不等式判读口径/全局变异=Boss 图资源面轴),出口读数各自分开归因。**✅ 实施批落地(2026-10-04,worktree m4iter14-gvar-20261004 台账 345)**:T1-T8 实施批全落(T7b MC 读数批按切分预案切独立后批,跑批待用户批准)——skewed_veins 贫矿脉行+互锁三条+effect_value [0,50]/门控第三维节点身份/替换制+兜底回落/装板序全局决议前置(数据依赖调和,出口报告在册)/资源面偏斜投影(整数最大余数守恒 77+合成序图级先件级后)/三层预告三层全接/七正主落文+06 收口;闸=冒烟 747/0(+29)+run_all 15+golden 普通图逐位 12/12 全等+六探针+三闸熵增终录见批报告 design/qa/m4iter14-gvar-exit-report-2026-10-04.md(Q3 四件应对件知情代价登记+静态推演+provisional 追认单+人闸目检清单);**③出口成立——⑥A4 开工门解一半**(另半=②出口);off/on 双档读数待 T7b(带 A 判读归 M-4 只测不判)。**④技能池执行批(2026-10-04 用户点名入列——调研+四裁+任务书全齐,06 Alpha 验证条目随之收口)**:文档五件(敌人系统.md 池构成表补 L2/L3 五敌种行/护甲列改读表口径/Boss 三代错峰句/意图呈现节补解锁弹出规格/版本 v0.13+EV 锚整数口径重登记+enemy.tres 批注消歧)+**新机制一件=Boss 半血解锁新独占伤害技**(三 Boss 血量 ≤50%〔用户口径定死〕解锁:酋长「震地怒击」类 ×2.5/CD4·卓尔遏毒类 ×2.0/CD3·石君王「岩崩」类 ×2.5/CD4——参考档即工作值,命名 T5 定稿、倍率冷却 provisional 归调参;enemy.tres 池条目扩 unlock_hp_pct 键〔int [1,99] 缺省无=无门槛〕;未解锁条目双面过滤不进摇号与保底集合;解锁出一次归因明细行「XX 解锁了 YY」);首拍加权取消(杂鱼纹理注销——巨蜘蛛 52% 读数已被 Package B 抬血自愈、地精两行终裁不加工);呈现=明细行+既有类型级预告+解锁时技能名一次性弹出(零动画资产、不改演出);裁决 D1-D8 零待裁;任务书=`design/research/任务书-技能池执行批-2026-10-04.md`(T0-T7≈4.25d,切分预案在册)——开工=用户发令升计划书。**✅ 实施批落地(2026-10-05,worktree m4iter14-skillpool-20261005 台账 358;goal 开工令 U0)**:T0-T6+⑤ 全落(T7 读数批后置挂 07 现行义务,跑批待用户批准)——T0 表盘点零漂移;T1 敌人系统.md v0.13 五件全落;T2 skills.tres 有效倍率表批注〔D4 整数基线半点矩阵〕+enemy.tres EV 锚整数口径重登记+巨蜘蛛 1.11 消歧〔=atk1 口径非混用〕+registry enemy/skill 条目换代;T3-T4 机制件=unlock_hp_pct〔1,99] 可选键(schema 域校验,缺省无=无门槛)+容器闩 check_skill_unlocks(单向闩零随机)+双面过滤(保底不逼锁定)+编排归因行「XX 解锁了 YY」〔type=highlight 高光键 skill_unlock 零行型新增〕+呈现一次性技能名 toast〔排除 perfect_sweep 误触〕;T5 三 Boss 解锁技落表(震地怒击 ×2.5/CD4·遏毒 ×2.0/CD3·岩崩 ×2.5/CD4 案甲 provisional+池尾 weight2/unlock50)+断言基线换代 3 处〔技能表 12 行/池模板+门控条目/酋长 EV 锚重锚 1.10-1.30 实测 1.1948〕;T6 单测 skill_unlock_test 22 断言(run_all 15 套)+smoke +5 集成(半血→次轮解锁行恰一次/文本/行型零新增);闸=冒烟 772/0+run_all 15+探针绿+doc 三闸零新增(reward_overlay_test 红=master 既有在册)。**⑤✅ 提灯 +2 接线落地(同批顺路)**:board_view.set_fog_lantern 公共接线面(半径算式迷雾批已在位;载体道具仍归 Alpha 信息件重定批=接缝就绪态)+ui_input_probe case⑮ 接线断言+HUD框架 注记**⑤魔法提灯 +2 效果接线(小卡)**:零调研直入——2026-09-30 拍板④已裁(灯甲视野外扩 +2 格、类型微光不随视野扩),迷雾批已留常量 LIGHT_RADIUS_LANTERN_BONUS,纯接线+断言估 0.5d 内。原候选卡注记终态(2026-10-04):敌人系统内容批=已具化为④;教学引导定稿批=用户裁改排 Beta(06 教学节头注记在案),移出本迭代候选。**⑥冒险前资源配比预设批——已移出本迭代(2026-10-05 用户令挂起:暂不做;条目保留 06-待办清单「冒险前资源配比预设(构筑提案)」〔已裁待实施→挂起〕,八项裁决全数有效、任务书冻结保留=design/research/任务书-冒险前资源配比预设批-2026-10-04.md;重启须用户另行发令,届时开工门仍=②③号卡出口〔若②③已落籍 master 则自动解——合成序与包络数值锚依赖②判式换代与③变异投影,三者共用摇号投影点〕)**。 | 迭代 13 出口(**迭代 13 已落籍 2026-10-04 eff8cb8**,台账 342) | 初始展开批 T0-T8(可两段切分)+判式换代批 T0-T5≈2.5d(独立 worktree 合并)+全局变异首发批 T0-T8≈5.75d(读数批可切,独立 worktree 合并)+技能池执行批 T0-T7≈4.25d(独立 worktree 合并)+提灯接线小卡 0.5d(可并入任一批顺路)〔⑥配比预设批 A4 已移出本迭代挂起,2026-10-05 用户令〕 |**③全局作用域变异首发批(2026-10-04 用户拍板立项——调研报告 P1-P8+盘问 Q1-Q4 全按推荐案落,批内序位待排)**:L2/L3 Boss 图恒定一型 scope=global 变异,首发型=**案A 资源面·微贫向偏斜**(正向格面池合计不变、进攻族 attack/blast/pierce/magic 权重上浮/生存族 heal/defense 明显下调、EV 微降 3-5% provisional、gp/action 白名单不动;v1.0「沃土+雷密对冲」形勘误作废——雷数为生成器事实、布置段不可加,改生成端=踩结构面否决理由);**替换制**(Boss 图不再布 region 片——L2 完美 Boss 承伤 55.8% 已越带不叠加;迭代 12 四件地形应对件在 Boss 图失效=知情代价,registry/调参日志随批登记);L1 Boss 免疫(带B [50,85] 教学保护);三层预告(开战横幅+HUD 常驻角标+帮助手册行);带A 判读后置 M-4(落地 off/on 对拍只测不判;off 基线=替换制后零变异 Boss 图,与现行带 region 片 Boss 图语义不同须注明);偏运硬币合成序=图级先件级后(代拍随批锚登记)。调研报告(事实源,v1.1 裁决落盘)=`design/research/调研-全局作用域变异设计空间-2026-10-04.md`,任务书已退役(git 01bfc15 批;裁决全录另见调研报告 §7)(T0-T8≈5.75d,读数批 T7 可切独立后批→主体≈5.25d;零新拍板点·provisional 追认单随批;停机点 S1 普通图逐位漂移/S2 读数越带只呈报/S3 互锁误伤;开工门=U0;**⑥A4 批开工门含本批出口——本批落地图级偏斜投影点为⑥合成链中段**〔2026-10-05 注:⑥已移出迭代 14 挂起,此依赖句冻结待其重启〕)。与①②互不撞(收窄=普通图初始展开轴/判式=不等式判读口径/全局变异=Boss 图资源面轴),出口读数各自分开归因。**✅ 实施批落地(2026-10-04,worktree m4iter14-gvar-20261004 台账 345)**:T1-T8 实施批全落(T7b MC 读数批按切分预案切独立后批,跑批待用户批准)——skewed_veins 贫矿脉行+互锁三条+effect_value [0,50]/门控第三维节点身份/替换制+兜底回落/装板序全局决议前置(数据依赖调和,出口报告在册)/资源面偏斜投影(整数最大余数守恒 77+合成序图级先件级后)/三层预告三层全接/七正主落文+06 收口;闸=冒烟 747/0(+29)+run_all 15+golden 普通图逐位 12/12 全等+六探针+三闸熵增终录见批报告 design/qa/m4iter14-gvar-exit-report-2026-10-04.md(Q3 四件应对件知情代价登记+静态推演+provisional 追认单+人闸目检清单);**③出口成立——⑥A4 开工门解一半**(另半=②出口);off/on 双档读数待 T7b(带 A 判读归 M-4 只测不判)。**④技能池执行批(2026-10-04 用户点名入列——调研+四裁+任务书全齐,06 Alpha 验证条目随之收口)**:文档五件(敌人系统.md 池构成表补 L2/L3 五敌种行/护甲列改读表口径/Boss 三代错峰句/意图呈现节补解锁弹出规格/版本 v0.13+EV 锚整数口径重登记+enemy.tres 批注消歧)+**新机制一件=Boss 半血解锁新独占伤害技**(三 Boss 血量 ≤50%〔用户口径定死〕解锁:酋长「震地怒击」类 ×2.5/CD4·卓尔遏毒类 ×2.0/CD3·石君王「岩崩」类 ×2.5/CD4——参考档即工作值,命名 T5 定稿、倍率冷却 provisional 归调参;enemy.tres 池条目扩 unlock_hp_pct 键〔int [1,99] 缺省无=无门槛〕;未解锁条目双面过滤不进摇号与保底集合;解锁出一次归因明细行「XX 解锁了 YY」);首拍加权取消(杂鱼纹理注销——巨蜘蛛 52% 读数已被 Package B 抬血自愈、地精两行终裁不加工);呈现=明细行+既有类型级预告+解锁时技能名一次性弹出(零动画资产、不改演出);裁决 D1-D8 零待裁;任务书=`design/research/任务书-技能池执行批-2026-10-04.md`(T0-T7≈4.25d,切分预案在册)——开工=用户发令升计划书。**⑤魔法提灯 +2 效果接线(小卡)**:零调研直入——2026-09-30 拍板④已裁(灯甲视野外扩 +2 格、类型微光不随视野扩),迷雾批已留常量 LIGHT_RADIUS_LANTERN_BONUS,纯接线+断言估 0.5d 内。原候选卡注记终态(2026-10-04):敌人系统内容批=已具化为④;教学引导定稿批=用户裁改排 Beta(06 教学节头注记在案),移出本迭代候选。**⑥冒险前资源配比预设批——已移出本迭代(2026-10-05 用户令挂起:暂不做;条目保留 06-待办清单「冒险前资源配比预设(构筑提案)」〔已裁待实施→挂起〕,八项裁决全数有效、任务书冻结保留=design/research/任务书-冒险前资源配比预设批-2026-10-04.md;重启须用户另行发令,届时开工门仍=②③号卡出口〔若②③已落籍 master 则自动解——合成序与包络数值锚依赖②判式换代与③变异投影,三者共用摇号投影点〕)**。 | 迭代 13 出口(**迭代 13 已落籍 2026-10-04 eff8cb8**,台账 342) | 初始展开批 T0-T8(可两段切分)+判式换代批 T0-T5≈2.5d(独立 worktree 合并)+全局变异首发批 T0-T8≈5.75d(读数批可切,独立 worktree 合并)+技能池执行批 T0-T7≈4.25d(独立 worktree 合并)+提灯接线小卡 0.5d(可并入任一批顺路)〔⑥配比预设批 A4 已移出本迭代挂起,2026-10-05 用户令〕 | | 迭代 15 | **①调试功能整合批(2026-10-05 用户令自「14.5」临时卡改编入册——原周期外 0.5 卡,落地事实与验证读数零变化,只改编号归属)**:主菜单三调试散件(随机种子输入框/角色数值调整板/两层调试入口)收一张调试浮窗 DebugOverlay——入口=开始覆盖层右下角「调试」角标(与主按钮组非平级,DS_DEBUG=1 环境变量门控沿用迭代 8 卡④口径);浮窗=悬浮菜单之上 Dialog(不隐藏开始层,同确认弹窗形态;旧 TunePanel「与开始层互斥」形态与类整体吸收退役含 .uid);可扩展滚动列表页四区块(随机种子/数值调整/批量模拟/两层调试入口——后续调试项往下追加滚轮下探)。四拍板全落(2026-10-04 用户裁)=P1 甲 DS_DEBUG 门控/P2 乙全摊平/P3 仅开始菜单可开·对局不可达(_show_debug_overlay 门禁护栏+对局发起随开随收)/P4 可扩展列表。**✅ 已全批落籍(2026-10-05,worktree iter145-debug-hub 两提交 48c0b34/46dadbb,主区 merge --no-ff d0a3c6b/10c301b,台账 352)**:闸=冒烟 747/0+探针 ui_tune/ui_click/ui 三绿(worktree+主区双跑,主区跑前 --import 重刷类名缓存在册坑);遗留=实机目检归用户(DS_DEBUG=1 启动→右下角角标→浮窗四区块→两层调试入口) | 卡①门:迭代 14 出口(注:本卡先于迭代 14 出口落籍——编入时点迭代 14 ③已闭/①②④⑤在飞/⑥挂起,门列仅记编入时点状态,不构成追溯闸) | 单批已落地(原估 0.5d,实际一次会话);后续扩调试项=debug_overlay.gd _build() 列表区追加区块(P4 扩展口径) | | 迭代 15 | **②奇物概念收口与词族对齐批(2026-10-05 用户令编入本迭代)**:概念层已由用户逐轮裁定定稿(《奇物》v1.0→v2.7,7 轮),本批只做**落地对齐**、不做二次设计。三批内容:**①三套旧词族全面对齐**(顶层已改名「奇物」而代码仍叫旧名=用户最初抱怨的"文档与代码分开"):`feature_*`→`curio_*`(103 处/7 文件)、`relic_*`→`feat_*`(162 处/12 文件)、运行层 `bonus_*`→`curio_*`(160 处/8 文件)。**硬约束:`reward_*` 已被 `reward_pick`/`reward_node`/`reward_preview` 占用,统一词族不得使用**;`relic_table.gd` 与两个控制器类改名须同步 Godot `.uid`/`.tscn`(非文本层无法自证)。**②三条渠道按分类分离**(现行三渠道共用同一个 98 张池、三类混编):关底 Boss 击败=通过这一关→只出专长;奖励节点/商店→属性值提升+资源、专长在此**只以门票形式**出现。**兑付频率红线**:奇物不是打一场战斗给一份,关内普通战斗节点打完不给任何奇物,一关之内只兑付一次(用户 2026-10-05 纠错)。**③两个新种类入池**=刷新次数(须先与"商店独立刷新机制"划清边界)+ 专长获取门票(拿到即开不可囤积/罕见只在概率/一局限购一次/计步保底:连续 5 次三选一展示未出→第 6 次必出,刷新重展计入、奖励节点与商店共享计数);附带 `shop.tres` 补回复(默认原则要求分类内成员都在该出现的渠道池里)与 charge 标签补至 ≥4 件(现仅 3 件,档二永远达不到——数据缺陷)。设计事实源=`design/gdd/systems/冒险循环/奇物.md` v2.7,任务书=`design/research/任务书-奇物词族对齐与渠道分离批-2026-10-05.md`(T0-T8≈4.5d,两段切分预案在册〔段一词族 T0-T3≈2d/段二渠道+入表 T4-T8≈2.5d〕,切分点=T3 出口;11 条设计契约含 6 条 🔴 停机级;12 条批末验收断言;代拍板白名单 5 项;待用户裁点 4 项〔玩家可见面违规/第四关档二复裁/门票四参数终值/存档键正式迁移〕)。**开工门**:与在途 M-4 各批(判式换代/全局变异/配比预设)撞同一批文件(`adventure_table.gd`/`level_runner.gd`/`adventure.tres`),须确认不并行或用户明示插队 | 卡②门:迭代 14 出口 | 卡①已落籍(原估 0.5d);卡②T0-T8≈4.5d(可两段切分:词族对齐段 + 渠道入表段) | -| 迭代 15 | **③秘宝代码词族对齐批(2026-10-05 用户令编入本迭代)**:设计侧已完成(消歧更名批 `430419c`+`06e94b7`,26 个设计文档「魔法道具」→「**秘宝**」,同调位机制名保留不变),本批只做**代码侧对齐**、不做二次设计。内容:`aux_*`/`AuxItem*` 词族全族换词 **358 处 / 36 文件**(重灾 `adventure_runner.gd`79 / `level_runner.gd`27 / `bonus_interact_controller.gd`19 / `battle_orchestrator.gd`18 / `config_db.gd`14 / `main.gd`13),分五组落:**A 玩家可见文案(P0,5 处)**=`battle_narrator.gd:117-118` + `bonus_interact_controller.gd:76` + `hero_info_panel_view.gd:56`(槽位标题 `UiKit.label`)+ `:178`(tooltip)· B schema 与数据表(`aux_item_table.gd`/`aux_items.tres`/`aux_items.gd` 文件名+类名+`ConfigDB` 持有变量与访问器全链跟改,**须同步 Godot `.uid`/`.tscn` + `--import` 重刷类名缓存**——迭代 14.5 实证在册坑)· C 文档链接修复(含 `architecture.md` 两处既有断债顺带清偿)· D 中文注释层(**须分色**:`魔法矢`/`魔法反噬`/`魔法族`/`魔法护甲` 属敌方伤害护甲语汇🔴不动)· E 测试文件名+内部变量。**用户三项拍板**:全族彻底改(含数据表)· **断点存档键一律保留**(`bonus_aux_carry`/`aux_detail`/`aux_cleared`/`aux_cleared_last`/`aux_items` 断点数组/`attunement_charges` 共 34 处引用一字不改,破档即进度丢失)· registry 条目键 `aux_items` 不改(数据契约键)。设计事实源=`design/gdd/systems/排雷循环/秘宝.md` v0.9,任务书=`design/research/任务书-秘宝代码词族对齐批-2026-10-05.md`(T0-T9≈5.0d,**超软盒 3 日上限·知情预挂**:T7 段末闸后 L3 呈报切点不擅切;**三档降级面 G1/G2/G3 在册**〔G3 下限=仅组 A 完成〕;5 条设计契约含 5 条 🔴 停机级〔存档兼容零破坏/数值零漂移/schema 契约面零变更/零字段更名/核心层零 await〕;代拍板白名单 5 项;**C1/C2 已裁关闭·全改保一致·待裁点 0 项**)。**撞批已消解**:② 奇物批 2026-10-05 收口落库(合并 `c571af2`),并行风险解除,本批为迭代 15 唯一在途需求;**T0 须重取基线**(判式换代批 T5 读数 750/0、② 又动数据层,§1.2 的 747 为②前旧数禁沿用)并复核事实表。**✅ 裁决(用户 2026-10-05「全改保一致」)**:C1 `"aux_item"` 域串**照改**(实测连锁面收窄——`reward.tres` 已零 aux_item 数据行,池种随迭代 11 T7 退役;16 处字面量全在代码内闭合无存档依赖;唯一连锁项=`smoke_all.gd:3932` 断言须同步)· C2 `aux_items` 一名两义**拆分**(ConfigDB 持有变量+表注册键✅改 / 断点存档键+冒烟夹具🔴禁改——**「键名禁改」与「变量名禁改」是两回事**,禁改的只是落盘字面量)。新增**组 F**(分派语汇与域串 16 处),任务卡扩为 T0-T10≈5.5d。**开工门**:✅ 已无待裁点,可直接发 T0 | 卡③门:迭代 14 出口(**裁点已全决·可开工**) | 卡①已落籍(原估 0.5d);卡②已落籍(`c571af2`);**卡③可开工**(无待裁点;T0 取基线后回填估时) | +| 迭代 15 | **③秘宝代码词族对齐批(2026-10-05 用户令编入本迭代)**:设计侧已完成(消歧更名批 `430419c`+`06e94b7`,26 个设计文档「魔法道具」→「**秘宝**」,同调位机制名保留不变),本批只做**代码侧对齐**、不做二次设计。内容:`aux_*`/`AuxItem*` 词族全族换词 **358 处 / 36 文件**(重灾 `adventure_runner.gd`79 / `level_runner.gd`27 / `bonus_interact_controller.gd`19 / `battle_orchestrator.gd`18 / `config_db.gd`14 / `main.gd`13),分五组落:**A 玩家可见文案(P0,5 处)**=`battle_narrator.gd:117-118` + `bonus_interact_controller.gd:76` + `hero_info_panel_view.gd:56`(槽位标题 `UiKit.label`)+ `:178`(tooltip)· B schema 与数据表(`aux_item_table.gd`/`aux_items.tres`/`aux_items.gd` 文件名+类名+`ConfigDB` 持有变量与访问器全链跟改,**须同步 Godot `.uid`/`.tscn` + `--import` 重刷类名缓存**——迭代 14.5 实证在册坑)· C 文档链接修复(含 `architecture.md` 两处既有断债顺带清偿)· D 中文注释层(**须分色**:`魔法矢`/`魔法反噬`/`魔法族`/`魔法护甲` 属敌方伤害护甲语汇🔴不动)· E 测试文件名+内部变量。**用户三项拍板**:全族彻底改(含数据表)· **断点存档键一律保留**(`bonus_aux_carry`/`aux_detail`/`aux_cleared`/`aux_cleared_last`/`aux_items` 断点数组/`attunement_charges` 共 34 处引用一字不改,破档即进度丢失)· registry 条目键 `aux_items` 不改(数据契约键)。设计事实源=`design/gdd/systems/排雷循环/秘宝.md` v0.9,任务书=`design/research/任务书-秘宝代码词族对齐批-2026-10-05.md`(T0-T9≈5.0d,**超软盒 3 日上限·知情预挂**:T7 段末闸后 L3 呈报切点不擅切;**三档降级面 G1/G2/G3 在册**〔G3 下限=仅组 A 完成〕;5 条设计契约含 5 条 🔴 停机级〔存档兼容零破坏/数值零漂移/schema 契约面零变更/零字段更名/核心层零 await〕;代拍板白名单 5 项;**C1/C2 已裁关闭·全改保一致·待裁点 0 项**)。**撞批已消解**:② 奇物批 2026-10-05 收口落库(合并 `c571af2`),并行风险解除,本批为迭代 15 唯一在途需求;**T0 须重取基线**(判式换代批 T5 读数 750/0、② 又动数据层,§1.2 的 747 为②前旧数禁沿用)并复核事实表。**✅ 裁决(用户 2026-10-05「全改保一致」)**:C1 `"aux_item"` 域串**照改**(实测连锁面收窄——`reward.tres` 已零 aux_item 数据行,池种随迭代 11 T7 退役;16 处字面量全在代码内闭合无存档依赖;唯一连锁项=`smoke_all.gd:3932` 断言须同步)· C2 `aux_items` 一名两义**拆分**(ConfigDB 持有变量+表注册键✅改 / 断点存档键+冒烟夹具🔴禁改——**「键名禁改」与「变量名禁改」是两回事**,禁改的只是落盘字面量)。新增**组 F**(分派语汇与域串 16 处),任务卡扩为 T0-T10≈5.5d。**开工门**:✅ 已无待裁点,可直接发 T0 | 卡③门:迭代 14 出口(**裁点已全决·可开工**) | 卡①已落籍(原估 0.5d);卡②已落籍(`c571af2`);**卡③ ✅ 已全批落籍(2026-10-05,worktree m4iter15-mibao 九提交 b4b8bb3..收口笔,主区 merge --no-ff 哈希见台账/active.md 快照行;出口报告=[iter15-3-mibao-exit-report](design/qa/iter15-3-mibao-exit-report-2026-10-05.md))**:词族实数 364 处/36 文件全换尽(例外 43+2 处=存档键引号字面量+夹具,穷举在报告 §五);闸=冒烟 755/0+run_all 14/15(唯一红=②批遗留基线红 reward_overlay,对照零新增)+行为探针四件全绿+doc 三闸/熵增闸零新增+存档键六键普查零差异+MC 按 goal 令豁免(静态零漂移证明代);渲染像素五闸屏蔽挂账 07⑮;遗留=实机目检归用户(07⑮)+reward_overlay 基线红归②批处置 | ## 执行纪律(2026-09-27 用户立规)