merge: 秘宝代码词族对齐批T0-T10全落(迭代15③号卡;冒烟772/0+run_all 15套唯reward_overlay既有红+探针绿+存档键六键普查零差异+doc三闸零新增)
This commit is contained in:
commit
8944dca0d3
55 files changed
+465
-369
No files matched your search
@@ -110,7 +110,7 @@
|
|||||||
|
|
||||||
| 模块 | Owns | Exposes | Consumes | 引擎 API |
|
| 模块 | 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 | 无 |
|
| **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 | 无 |
|
| **run_structure**(C2) | 冒险/关卡序列、失败重开、**master_seed 唯一接线方** | (未设计) | RngService.set_master_seed、C3/D2 | 无 |
|
||||||
| **difficulty**(C3) | DifficultyTable 回填、全部曲线数值调参所有权、战斗期望表(切片 monte_carlo 为工具原型) | 调参输出(经 D2 R1 解析/编排器传递,禁反向调用生成) | ConfigDB、B1 对账输出(调参约束清单)、A1 报告 C | 无 |
|
| **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 → A2 | Board 产物 class_name 数据契约 | install 四不变式校验(violation = 拒绝 + 五类诊断枚举) | 生成期合法性闸(R₀≠S / clearable / min_safe) |
|
||||||
| A1 ↔ B1 | attempt 边界非 scope 事件;actuals p10 为对账输入(非 target 参数) | 编排不把重试当取号 | 生成期指标集输出(实测可推理率 / 实际雷数与安全格数 / 重试次数 / 降级与非法产物标记) |
|
| A1 ↔ B1 | attempt 边界非 scope 事件;actuals p10 为对账输入(非 target 参数) | 编排不把重试当取号 | 生成期指标集输出(实测可推理率 / 实际雷数与安全格数 / 重试次数 / 降级与非法产物标记) |
|
||||||
| B4 → B3 | buff 类经 B1 调 apply_effect(B4 零跨系统读、零直接接口) | 满层拒绝 = 零兑付 + 明细行(无折算) | 授予时数值快照(抗热重载) |
|
| 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 采纳前对照核实。
|
**引擎类型核验注记**:接口使用的引擎类型 = 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 采纳前对照核实。
|
||||||
|
|
||||||
|
|||||||
@@ -144,6 +144,11 @@
|
|||||||
- **红灯信号**:解锁行反复弹(闩失效);toast 带数值/权重(池不公开纪律破);满血即解锁(门谓词错)。
|
- **红灯信号**:解锁行反复弹(闩失效);toast 带数值/权重(池不公开纪律破);满血即解锁(门谓词错)。
|
||||||
- **结论回流**:体感 → 本条目记录;技能强度体感归 T7 节奏重测读数(跑批待用户批准,过涝越带 S2 回调呈报禁自动调)。
|
- **结论回流**:体感 → 本条目记录;技能强度体感归 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 重锚入库后补算终值。
|
**已履行**(按序换代,旧读数各随其批作废留痕不入本单):①验收读数重测批(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 重锚入库后补算终值。
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
一次冒险要走三关,如果走完时角色和开局毫无区别,中途的每一次取舍就都不算数了。奇物就是那个把"这一局玩成了什么样"落下来的东西:让玩家在冒险过程中不断变强,且每一局变强的方向不同。
|
一次冒险要走三关,如果走完时角色和开局毫无区别,中途的每一次取舍就都不算数了。奇物就是那个把"这一局玩成了什么样"落下来的东西:让玩家在冒险过程中不断变强,且每一局变强的方向不同。
|
||||||
|
|
||||||
它同时要和跨冒险的成长隔开:永久保留的东西是[魔法道具](../排雷循环/魔法道具.md)(带在身上的物品)与[元进度](../跨局循环/元进度.md)(账号级的树),奇物只在当局存在,冒险收束即清零——它不是"你的存档变强了",而是"这一次下矿的你变强了"。
|
它同时要和跨冒险的成长隔开:永久保留的东西是[魔法道具](../排雷循环/秘宝.md)(带在身上的物品)与[元进度](../跨局循环/元进度.md)(账号级的树),奇物只在当局存在,冒险收束即清零——它不是"你的存档变强了",而是"这一次下矿的你变强了"。
|
||||||
|
|
||||||
**边界判据(一句话)**:**一次冒险内获得、冒险收束即清零的,是奇物;跨冒险跟着你走的,是魔法道具。**
|
**边界判据(一句话)**:**一次冒险内获得、冒险收束即清零的,是奇物;跨冒险跟着你走的,是魔法道具。**
|
||||||
|
|
||||||
@@ -270,7 +270,7 @@
|
|||||||
|
|
||||||
| 相邻概念 | 关系(只写关系,不写对方的规则) |
|
| 相邻概念 | 关系(只写关系,不写对方的规则) |
|
||||||
|---|---|
|
|---|---|
|
||||||
| [魔法道具](../排雷循环/魔法道具.md) | 最需要分清的一对,判据是生命周期:**奇物当局清零,魔法道具跨冒险保留**。两者互不相通——奇物永不进同调位,魔法道具永不进当局随机渠道。 |
|
| [魔法道具](../排雷循环/秘宝.md) | 最需要分清的一对,判据是生命周期:**奇物当局清零,魔法道具跨冒险保留**。两者互不相通——奇物永不进同调位,魔法道具永不进当局随机渠道。 |
|
||||||
| [元进度](../跨局循环/元进度.md)(树) | 树管账号永久的规则与容量,奇物管当局构筑,两层互不代替。 |
|
| [元进度](../跨局循环/元进度.md)(树) | 树管账号永久的规则与容量,奇物管当局构筑,两层互不代替。 |
|
||||||
| [战斗结算](../战斗循环/战斗结算.md) | 专长的挂点位于结算管线的各段;挂点清单与语义归结算文档。 |
|
| [战斗结算](../战斗循环/战斗结算.md) | 专长的挂点位于结算管线的各段;挂点清单与语义归结算文档。 |
|
||||||
| [行动经济](../排雷循环/行动经济.md)、[地形变异](../排雷循环/地形变异.md) | 部分挂点落在行动点结转与地形处理上,语义归各自文档。 |
|
| [行动经济](../排雷循环/行动经济.md)、[地形变异](../排雷循环/地形变异.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 冲突标记。
|
||||||
@@ -28,6 +28,8 @@
|
|||||||
| 5 | 收口五步 | active.md 快照 / 台账条目 / roadmap 里程碑行 / stage.txt(如变)/ 闸序列留痕 |
|
| 5 | 收口五步 | active.md 快照 / 台账条目 / roadmap 里程碑行 / stage.txt(如变)/ 闸序列留痕 |
|
||||||
|
|
||||||
> ⚠️ **基线纪律**:迭代 15 调试整合批已把冒烟推进到 **747 项**。本批开工前必须重测基线取实际值(本任务书不写死数字,T0 复核后回填),**禁止用本文档的历史数字当闸门**。
|
> ⚠️ **基线纪律**:迭代 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 须自行复核)
|
## 2. 现状事实(代码级,T0 须自行复核)
|
||||||
|
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ func notify_settlement_done(next_round_mode: String) -> bool:
|
|||||||
|
|
||||||
# 下轮行动点修正排队(格面资源八型批 2026-09-20):action 型正负行结算期调用,同轮多次授予累加;
|
# 下轮行动点修正排队(格面资源八型批 2026-09-20):action 型正负行结算期调用,同轮多次授予累加;
|
||||||
# 相位无关(授予发生在结算段,此时本类可能处于 ACTIVE/WAITING 任一相位)
|
# 相位无关(授予发生在结算段,此时本类可能处于 ACTIVE/WAITING 任一相位)
|
||||||
# 第 9 API(registry 行动经济×① 接口漂移预授权——迭代 7 T2 魔法道具内容批落位):ap_grant 道具的
|
# 第 9 API(registry 行动经济×① 接口漂移预授权——迭代 7 T2 秘宝内容批落位):ap_grant 道具的
|
||||||
# 当轮行动点加量(GDD「加行动点效果给当轮」——区别于 queue_ap_delta 的下轮排队语义)。Active 受理、
|
# 当轮行动点加量(GDD「加行动点效果给当轮」——区别于 queue_ap_delta 的下轮排队语义)。Active 受理、
|
||||||
# 无上限域、零随机;使用道具本身零扣费(成本在获取时已付——捡道具格不出战斗奖励)。
|
# 无上限域、零随机;使用道具本身零扣费(成本在获取时已付——捡道具格不出战斗奖励)。
|
||||||
func grant_ap(amount: int) -> bool:
|
func grant_ap(amount: int) -> bool:
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ extends RefCounted
|
|||||||
signal level_started(level_index: int, display_name: String) # 每关开始(含冒险首关)——呈现层重取 runner()、刷新图条与层名行
|
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_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 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)
|
signal adventure_finished(summary: Dictionary) # 冒险结算(completed/failed/abandoned)——summary 五件事:打穿没有/通关几关/止步第几关/钥石合计/主种子(+additive keystone_drops 迭代 10)
|
||||||
# ---- 转发族(签名与 LevelRunner 同款——呈现层对接透明;ADR-0001 S6 经 _forward_* 方法)----
|
# ---- 转发族(签名与 LevelRunner 同款——呈现层对接透明;ADR-0001 S6 经 _forward_* 方法)----
|
||||||
signal node_entered(node: Dictionary, info: Dictionary)
|
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 _override := [0, 0] # 调试浮窗百分比通道 [atk_pct, hp_pct](每关新 runner 都要应用)
|
||||||
var _base_override := {"atk": 0, "max_hp": 0, "armor_class": 0}
|
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 _first_script := false # 首次脚本模式(关卡节点图生成 v0.4——true = 全关零抽签取池内模板 0;测量夹具恒 false) # 永久强化 flat 注入(元进度实现批——冒险开始参数面 params.hero_override 存入,共享给 LevelRunner;全零 = 白板)
|
||||||
var _last_aux_cleared := 0 # additive(迭代 7 T4——最近一次关卡末清空计数,summary 取数面)
|
var _last_treasure_cleared := 0 # additive(迭代 7 T4——最近一次关卡末清空计数,summary 取数面)
|
||||||
var _aux_unlocked := {} # aux 解锁门控集(迭代 7 T5——params.aux_unlocked 接收面)
|
var _treasure_unlocked := {} # aux 解锁门控集(迭代 7 T5——params.treasure_unlocked 接收面)
|
||||||
var _attunement: Array = [] # 同调装配集(迭代 11 第①批 T5——params.attunement 接收面,start_level 外下传 LevelRunner)
|
var _attunement: Array = [] # 同调装配集(迭代 11 第①批 T5——params.attunement 接收面,start_level 外下传 LevelRunner)
|
||||||
var _attune_refresh_x := 0 # 刷新件余量(迭代 11 第①批 T5b P1 甲——每碰三选一重置=X 表值;优先消耗、不结转)
|
var _attune_refresh_x := 0 # 刷新件余量(迭代 11 第①批 T5b P1 甲——每碰三选一重置=X 表值;优先消耗、不结转)
|
||||||
var _attune_refresh_y := 0 # Y 冒险周期池(开局参数面注入,用完即无——营地升级行表值)
|
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 _save_manager = null # 断点承载注入(迭代 8 卡①——null = 不写断点;模拟/冒烟缺省)
|
||||||
var _resume_bp := {} # 续玩快照暂存(resume_adventure → _start_current_level 单跳传递)
|
var _resume_bp := {} # 续玩快照暂存(resume_adventure → _start_current_level 单跳传递)
|
||||||
# ---- 三选一停点态(迭代 10 奖励重构批)----
|
# ---- 三选一停点态(迭代 10 奖励重构批)----
|
||||||
@@ -85,9 +85,9 @@ var _relics: Array[String] = [] # 特性持有集(迭代 12 T1——
|
|||||||
var _tree_rules: Array = [] # 树 rule 键集(迭代 12 T10——Fork 激活侧 effects 透传;下传 enc.tree_rules 消费面)
|
var _tree_rules: Array = [] # 树 rule 键集(迭代 12 T10——Fork 激活侧 effects 透传;下传 enc.tree_rules 消费面)
|
||||||
var _bonus_pending := {} # 停点态:{"candidates": Array, "payload": Dictionary, "chosen"/"incoming": 替换在途}——空 = 无停点
|
var _bonus_pending := {} # 停点态:{"candidates": Array, "payload": Dictionary, "chosen"/"incoming": 替换在途}——空 = 无停点
|
||||||
var _bonus_result := {} # 已兑付待推进态(bonus_resolved 载荷副本——中断续玩不重兑付)
|
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 _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 _node_bonus_pending := {} # 奖励节点三选一停点态(迭代 10 追加批——共享池;断点不载:续玩重建到选路停点重走,恢复的计数器保证同候选重抽)
|
||||||
var _shop_mode := "legacy" # 商店模式(迭代 11 第②批 T3——"legacy"=固定三件加定价〔off 对照承载,缺省零扰动〕/"pool"=共享池抽 3 买 1 重抽;真实入口 main.gd 显式投 pool)
|
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", {}))
|
_base_override = _normalize_override(params.get("hero_override", {}))
|
||||||
_first_script = bool(params.get("first_script", false)) # 缺省 = 非首次(抽签路径;真实侧由呈现层读存档布尔位传入)
|
_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 对照零扰动)
|
_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)
|
_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 冒险周期池)
|
_attune_refresh_y = maxi(0, int(params.get("attune_refresh_y", 0))) # additive(迭代 11 第①批 T5b——Y 冒险周期池)
|
||||||
_seed_attune_charges() # 迭代 11 第①批 T6——冒险开始充能账本按装备主动件重置(每冒险充能语义) # additive(迭代 7 T5)
|
_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):
|
for r in (bp.get("relics", []) as Array):
|
||||||
_relics.append(String(r))
|
_relics.append(String(r))
|
||||||
for v in (bp.get("bonus_aux_carry", []) as Array):
|
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)
|
_keystone_drops = (bp.get("keystone_drops", []) as Array).duplicate(true)
|
||||||
_base_override = _normalize_override(params.get("hero_override", {}))
|
_base_override = _normalize_override(params.get("hero_override", {}))
|
||||||
# 生命账本越界钳制(T17——spawn 守卫 EC16 免疫):断点可能由旧口径版本写出(如调试上限
|
# 生命账本越界钳制(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))))
|
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 # 续玩模板已随快照强制(已抽模板零重抽)——脚本模式不重放
|
_first_script = false # 续玩模板已随快照强制(已抽模板零重抽)——脚本模式不重放
|
||||||
_shop_mode = "pool" if String(params.get("shop_mode", "legacy")) == "pool" else "legacy" # 迭代 11 第②批 T3——续玩参数面同 start_adventure(缺省 legacy)
|
_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)
|
_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 冒险周期池)
|
_attune_refresh_y = maxi(0, int(params.get("attune_refresh_y", 0))) # additive(迭代 11 第①批 T5b——Y 冒险周期池)
|
||||||
_seed_attune_charges() # 迭代 11 第①批 T6——冒险开始充能账本按装备主动件重置(每冒险充能语义)
|
_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) # 掷定前置随停点快照续接
|
_bonus_pending["aux_detail"] = (bp_pending.get("aux_detail", []) as Array).duplicate(true) # 掷定前置随停点快照续接
|
||||||
var payload: Dictionary = (bp_pending.get("payload", {}) as Dictionary).duplicate(true)
|
var payload: Dictionary = (bp_pending.get("payload", {}) as Dictionary).duplicate(true)
|
||||||
if bp_pending.has("incoming"):
|
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)
|
var incoming: Array = (bp_pending.get("incoming", []) as Array).duplicate(true)
|
||||||
_bonus_pending["incoming"] = incoming
|
_bonus_pending["incoming"] = incoming
|
||||||
state = "running"
|
state = "running"
|
||||||
bonus_choice_presented.emit(payload)
|
bonus_choice_presented.emit(payload)
|
||||||
# 替换在途续发(呈现层直落替换子态——持有件记录按恢复后 carry 重建)
|
# 替换在途续发(呈现层直落替换子态——持有件记录按恢复后 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()})
|
{"index": -1, "item_id": String(incoming[0]) if not incoming.is_empty() else "", "count": incoming.size()})
|
||||||
return true
|
return true
|
||||||
state = "running"
|
state = "running"
|
||||||
@@ -262,7 +262,7 @@ func _reset_bonus_state() -> void:
|
|||||||
_relics = []
|
_relics = []
|
||||||
_bonus_pending = {}
|
_bonus_pending = {}
|
||||||
_bonus_result = {}
|
_bonus_result = {}
|
||||||
_bonus_aux_carry = []
|
_bonus_treasure_carry = []
|
||||||
_keystone_drops = []
|
_keystone_drops = []
|
||||||
_node_bonus_pending = {}
|
_node_bonus_pending = {}
|
||||||
|
|
||||||
@@ -363,8 +363,8 @@ func pick_bonus(kind: String, tier: String = "", relic_id: String = "") -> bool:
|
|||||||
return false
|
return false
|
||||||
var value: int = int(db.adventure.feature_value(kind, tier))
|
var value: int = int(db.adventure.feature_value(kind, tier))
|
||||||
var hp_before := int(ledger.get("hero_hp", 0))
|
var hp_before := int(ledger.get("hero_hp", 0))
|
||||||
if kind == "aux_item":
|
if kind == "treasure_item":
|
||||||
return _pick_aux_item(value) # 道具件分派通关渠道(持有容器 = 跨关携带——与节点渠道分轨;池种退役后不可达)
|
return _pick_treasure_item(value) # 道具件分派通关渠道(持有容器 = 跨关携带——与节点渠道分轨;池种退役后不可达)
|
||||||
if not _apply_bonus_pick(kind, tier, value, relic_id):
|
if not _apply_bonus_pick(kind, tier, value, relic_id):
|
||||||
push_error("[冒险结构] pick_bonus 拒绝——未知件: %s|%s|%s" % [kind, tier, relic_id])
|
push_error("[冒险结构] pick_bonus 拒绝——未知件: %s|%s|%s" % [kind, tier, relic_id])
|
||||||
return false
|
return false
|
||||||
@@ -473,41 +473,41 @@ func _pool_stock_snapshot() -> Dictionary:
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
# 道具件兑付(同调位约束):有位直接入跨关携带;满位转替换子交互(incoming 暂存、等 resolve_aux_replace)。
|
# 道具件兑付(同调位约束):有位直接入跨关携带;满位转替换子交互(incoming 暂存、等 resolve_treasure_replace)。
|
||||||
# 掷定前置(追加批二):具体道具随候选抽定(_last_draw_aux / _bonus_pending.aux_detail)——本函数消费预掷值,
|
# 掷定前置(追加批二):具体道具随候选抽定(_last_draw_treasure / _bonus_pending.aux_detail)——本函数消费预掷值,
|
||||||
# 断点续玩/无预掷值时回退当场掷定(流序不同但消费数不变,确定性由调用序保证)。
|
# 断点续玩/无预掷值时回退当场掷定(流序不同但消费数不变,确定性由调用序保证)。
|
||||||
# 持有容器 = 跨关携带 _bonus_aux_carry(与节点渠道的关卡域库存分轨——容器差异保守不合,注记在案)。
|
# 持有容器 = 跨关携带 _bonus_treasure_carry(与节点渠道的关卡域库存分轨——容器差异保守不合,注记在案)。
|
||||||
func _pick_aux_item(count: int) -> bool:
|
func _pick_treasure_item(count: int) -> bool:
|
||||||
var picked: Array = _draw_pending_aux(_bonus_pending, count, true)
|
var picked: Array = _draw_pending_treasure(_bonus_pending, count, true)
|
||||||
if picked.is_empty():
|
if picked.is_empty():
|
||||||
push_error("[冒险结构] pick_bonus(aux_item) 拒绝——解锁道具池空集(白板/门控态不入牌库的防御兜底)")
|
push_error("[冒险结构] pick_bonus(treasure_item) 拒绝——解锁道具池空集(白板/门控态不入牌库的防御兜底)")
|
||||||
return false
|
return false
|
||||||
var hp_before := int(ledger.get("hero_hp", 0))
|
var hp_before := int(ledger.get("hero_hp", 0))
|
||||||
# 迭代 11 第①批 T7——同调位守卫随过渡键退役拆除(aux 卡出池后本路径不可达;能力件容量闸
|
# 迭代 11 第①批 T7——同调位守卫随过渡键退役拆除(aux 卡出池后本路径不可达;能力件容量闸
|
||||||
# 正主 = 营地装配面 Attunement.slots 满位禁选)
|
# 正主 = 营地装配面 Attunement.slots 满位禁选)
|
||||||
for iid in picked:
|
for iid in picked:
|
||||||
_bonus_aux_carry.append(String(iid))
|
_bonus_treasure_carry.append(String(iid))
|
||||||
_finish_bonus_pick("aux_item", picked.size(), hp_before)
|
_finish_bonus_pick("treasure_item", picked.size(), hp_before)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
# 替换子交互受理(discard_index = -1 放弃新件不获取;否则丢该件腾位收新)——终态恒 ≤ 同调位
|
# 替换子交互受理(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):
|
if not _replace_in_transit(_bonus_pending):
|
||||||
push_error("[冒险结构] resolve_aux_replace 拒绝——无替换在途")
|
push_error("[冒险结构] resolve_treasure_replace 拒绝——无替换在途")
|
||||||
return false
|
return false
|
||||||
var incoming: Array = _bonus_pending.get("incoming", []) as Array
|
var incoming: Array = _bonus_pending.get("incoming", []) as Array
|
||||||
var hp_before := int(ledger.get("hero_hp", 0))
|
var hp_before := int(ledger.get("hero_hp", 0))
|
||||||
if discard_index >= 0:
|
if discard_index >= 0:
|
||||||
if discard_index >= _bonus_aux_carry.size():
|
if discard_index >= _bonus_treasure_carry.size():
|
||||||
push_error("[冒险结构] resolve_aux_replace 拒绝——序号不在持有集: %d" % discard_index)
|
push_error("[冒险结构] resolve_treasure_replace 拒绝——序号不在持有集: %d" % discard_index)
|
||||||
return false
|
return false
|
||||||
_bonus_aux_carry.remove_at(discard_index)
|
_bonus_treasure_carry.remove_at(discard_index)
|
||||||
for iid in incoming:
|
for iid in incoming:
|
||||||
_bonus_aux_carry.append(String(iid))
|
_bonus_treasure_carry.append(String(iid))
|
||||||
# 放弃新件(discard_index < 0)= 原持有集不动、新件不获取
|
# 放弃新件(discard_index < 0)= 原持有集不动、新件不获取
|
||||||
_finish_bonus_pick("aux_item", incoming.size(), hp_before)
|
_finish_bonus_pick("treasure_item", incoming.size(), hp_before)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
@@ -535,12 +535,12 @@ func _finish_bonus_pick(picked: String, value: int, hp_before: int, tier: String
|
|||||||
# 掷定前置(追加批二):返回 dict 带 aux_detail(道具件具体道具)供卡片直显。
|
# 掷定前置(追加批二):返回 dict 带 aux_detail(道具件具体道具)供卡片直显。
|
||||||
func node_bonus_candidates() -> Dictionary:
|
func node_bonus_candidates() -> Dictionary:
|
||||||
var cands: Array = _draw_bonus_candidates()
|
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 余量(不结转)
|
_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 同权入持有集)
|
# 点选兑付(节点域——无部分回血无钥石;令牌消费与牌库摘牌与通关三选一同库;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])
|
push_error("[冒险结构] apply_node_bonus 拒绝——令牌不在候选: %s|%s|%s" % [kind, tier, relic_id])
|
||||||
return false
|
return false
|
||||||
var value: int = int(db.adventure.feature_value(kind, tier))
|
var value: int = int(db.adventure.feature_value(kind, tier))
|
||||||
if kind == "aux_item":
|
if kind == "treasure_item":
|
||||||
return _apply_node_aux(value) # 道具件分派节点渠道(持有容器 = 关卡域库存——与通关渠道分轨;池种退役后不可达)
|
return _apply_node_treasure(value) # 道具件分派节点渠道(持有容器 = 关卡域库存——与通关渠道分轨;池种退役后不可达)
|
||||||
if not _apply_bonus_pick(kind, tier, value, relic_id):
|
if not _apply_bonus_pick(kind, tier, value, relic_id):
|
||||||
push_error("[冒险结构] apply_node_bonus 拒绝——未知件: %s|%s|%s" % [kind, tier, relic_id])
|
push_error("[冒险结构] apply_node_bonus 拒绝——未知件: %s|%s|%s" % [kind, tier, relic_id])
|
||||||
return false
|
return false
|
||||||
@@ -565,22 +565,22 @@ func apply_node_bonus(kind: String, tier: String = "", relic_id: String = "") ->
|
|||||||
# 节点渠道道具件(同调位约束):持有=关卡域库存+跨关携带,有位直接入本关库存(当关可用);
|
# 节点渠道道具件(同调位约束):持有=关卡域库存+跨关携带,有位直接入本关库存(当关可用);
|
||||||
# 满位转替换子交互(丢弃目标=库存件 handle——与通关渠道的 carry 序号分轨,容器语义保守不合)。
|
# 满位转替换子交互(丢弃目标=库存件 handle——与通关渠道的 carry 序号分轨,容器语义保守不合)。
|
||||||
# 掷定前置:消费 _node_bonus_pending.aux_detail 预掷值(缺省回退当场掷定)。
|
# 掷定前置:消费 _node_bonus_pending.aux_detail 预掷值(缺省回退当场掷定)。
|
||||||
func _apply_node_aux(count: int) -> bool:
|
func _apply_node_treasure(count: int) -> bool:
|
||||||
var picked: Array = _draw_pending_aux(_node_bonus_pending, count, false)
|
var picked: Array = _draw_pending_treasure(_node_bonus_pending, count, false)
|
||||||
if picked.is_empty():
|
if picked.is_empty():
|
||||||
push_error("[冒险结构] apply_node_bonus(aux_item) 拒绝——解锁道具池空集(白板/门控态不入牌库的防御兜底)")
|
push_error("[冒险结构] apply_node_bonus(treasure_item) 拒绝——解锁道具池空集(白板/门控态不入牌库的防御兜底)")
|
||||||
return false
|
return false
|
||||||
var records: Array = []
|
var records: Array = []
|
||||||
if _runner != null and _runner.aux_inventory != null:
|
if _runner != null and _runner.treasure_inventory != null:
|
||||||
records = _runner.aux_inventory.holding_records()
|
records = _runner.treasure_inventory.holding_records()
|
||||||
# 迭代 11 第①批 T7——守卫随过渡键退役拆除(FEATURE_KINDS 已除名 aux_item,本分支不可达;
|
# 迭代 11 第①批 T7——守卫随过渡键退役拆除(FEATURE_KINDS 已除名 treasure_item,本分支不可达;
|
||||||
# 替换子交互路由随容量闸一并退役——能力件容量闸正主 = 营地装配面满位禁选)
|
# 替换子交互路由随容量闸一并退役——能力件容量闸正主 = 营地装配面满位禁选)
|
||||||
if _runner != null:
|
if _runner != null:
|
||||||
for iid in picked:
|
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():
|
if rec.is_empty():
|
||||||
push_warning("[冒险结构] 奖励节点道具授予被拒(防御兜底留痕): %s" % String(iid))
|
push_warning("[冒险结构] 奖励节点道具授予被拒(防御兜底留痕): %s" % String(iid))
|
||||||
_finish_node_bonus("aux_item", picked.size())
|
_finish_node_bonus("treasure_item", picked.size())
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
@@ -590,15 +590,15 @@ func _resolve_node_replace(discard_handle: int) -> bool:
|
|||||||
return false
|
return false
|
||||||
var incoming: Array = _node_bonus_pending.get("incoming", []) as Array
|
var incoming: Array = _node_bonus_pending.get("incoming", []) as Array
|
||||||
if discard_handle >= 0:
|
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)
|
push_error("[冒险结构] resolve_node_replace 拒绝——句柄不在持有集: %d" % discard_handle)
|
||||||
return false
|
return false
|
||||||
for iid in incoming:
|
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():
|
if rec.is_empty():
|
||||||
push_warning("[冒险结构] 替换子道具授予被拒(防御兜底留痕): %s" % String(iid))
|
push_warning("[冒险结构] 替换子道具授予被拒(防御兜底留痕): %s" % String(iid))
|
||||||
# 放弃新件(discard_handle < 0)= 原持有集不动、新件不获取
|
# 放弃新件(discard_handle < 0)= 原持有集不动、新件不获取
|
||||||
_finish_node_bonus("aux_item", incoming.size())
|
_finish_node_bonus("treasure_item", incoming.size())
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
@@ -606,7 +606,7 @@ func _resolve_node_replace(discard_handle: int) -> bool:
|
|||||||
func _seed_attune_charges() -> void:
|
func _seed_attune_charges() -> void:
|
||||||
attune_charges = {}
|
attune_charges = {}
|
||||||
for iid in _attunement:
|
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":
|
if String(arow.get("form", "")) == "active_charged":
|
||||||
attune_charges[String(iid)] = maxi(0, int(arow.get("charges_per_adventure", 0)))
|
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:
|
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:
|
func _reset_refresh_x() -> void:
|
||||||
@@ -648,10 +648,10 @@ func refresh_bonus() -> bool:
|
|||||||
_attune_refresh_y -= 1
|
_attune_refresh_y -= 1
|
||||||
var cands: Array = _draw_bonus_candidates()
|
var cands: Array = _draw_bonus_candidates()
|
||||||
_bonus_pending["candidates"] = cands.duplicate(true)
|
_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)
|
var payload: Dictionary = (_bonus_pending.get("payload", {}) as Dictionary).duplicate(true)
|
||||||
payload["candidates"] = cands
|
payload["candidates"] = cands
|
||||||
payload["aux_detail"] = _last_draw_aux.duplicate()
|
payload["aux_detail"] = _last_draw_treasure.duplicate()
|
||||||
bonus_choice_presented.emit(payload) # 同信号重 present(零自动推进契约不破——停点仍在途)
|
bonus_choice_presented.emit(payload) # 同信号重 present(零自动推进契约不破——停点仍在途)
|
||||||
_snapshot_breakpoint()
|
_snapshot_breakpoint()
|
||||||
return true
|
return true
|
||||||
@@ -662,34 +662,34 @@ func refresh_bonus() -> bool:
|
|||||||
_attune_refresh_y -= 1
|
_attune_refresh_y -= 1
|
||||||
var cands2: Array = _draw_bonus_candidates()
|
var cands2: Array = _draw_bonus_candidates()
|
||||||
_node_bonus_pending["candidates"] = cands2.duplicate(true)
|
_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 true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
||||||
# 替换在途守卫(2026-10-02 修复批——双渠道替换受理的共用前置谓词:停点态非空且 chosen=aux_item)
|
# 替换在途守卫(2026-10-02 修复批——双渠道替换受理的共用前置谓词:停点态非空且 chosen=treasure_item)
|
||||||
func _replace_in_transit(pending: Dictionary) -> bool:
|
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 封闭流补掷——
|
# 解锁道具池空集守卫 + 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:
|
func _draw_pending_treasure(pending: Dictionary, count: int, allow_detail_fallback: bool) -> Array:
|
||||||
var pool: Array = _bonus_aux_pool()
|
var pool: Array = _bonus_treasure_pool()
|
||||||
if pool.is_empty():
|
if pool.is_empty():
|
||||||
return []
|
return []
|
||||||
var picked: Array = []
|
var picked: Array = []
|
||||||
var detail: Array = (pending.get("aux_detail", []) as Array).duplicate()
|
var detail: Array = (pending.get("aux_detail", []) as Array).duplicate()
|
||||||
if detail.is_empty() and allow_detail_fallback:
|
if detail.is_empty() and allow_detail_fallback:
|
||||||
detail = _last_draw_aux.duplicate()
|
detail = _last_draw_treasure.duplicate()
|
||||||
for i in maxi(1, count):
|
for i in maxi(1, count):
|
||||||
if i < detail.size():
|
if i < detail.size():
|
||||||
picked.append(String(detail[i]))
|
picked.append(String(detail[i]))
|
||||||
else:
|
else:
|
||||||
picked.append(_roll_bonus_aux_item(pool))
|
picked.append(_roll_bonus_treasure_item(pool))
|
||||||
return picked
|
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:
|
func resolve_bonus_replace(discard: int) -> bool:
|
||||||
if not _node_bonus_pending.is_empty() and _node_bonus_pending.has("incoming"):
|
if not _node_bonus_pending.is_empty() and _node_bonus_pending.has("incoming"):
|
||||||
return _resolve_node_replace(discard)
|
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:
|
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〕;抽签不摘牌、兑付才摘牌=未选
|
# kind 出现率∝剩余令牌数〔档位配额即分布——无独立权重 knob〕;抽签不摘牌、兑付才摘牌=未选
|
||||||
# 自动回池;池耗即枯竭——余库不足 N kind 时出齐剩余,空库 = 零候选合法态)。候选 = 令牌字典
|
# 自动回池;池耗即枯竭——余库不足 N kind 时出齐剩余,空库 = 零候选合法态)。候选 = 令牌字典
|
||||||
# {"kind","tier"}。消费 reward_pick 封闭流——一次停点恰一 scope,同种子同候选;道具件掷定前置
|
# {"kind","tier"}。消费 reward_pick 封闭流——一次停点恰一 scope,同种子同候选;道具件掷定前置
|
||||||
# 随池种退役拆除(_last_draw_aux 恒空集,机械惰性承载)。
|
# 随池种退役拆除(_last_draw_treasure 恒空集,机械惰性承载)。
|
||||||
func _draw_bonus_candidates() -> Array:
|
func _draw_bonus_candidates() -> Array:
|
||||||
_last_draw_aux = []
|
_last_draw_treasure = []
|
||||||
var pool := _bonus_deck.duplicate()
|
var pool := _bonus_deck.duplicate()
|
||||||
var rg: RandomNumberGenerator = rng.open_stream("reward_pick")
|
var rg: RandomNumberGenerator = rng.open_stream("reward_pick")
|
||||||
for i in pool.size():
|
for i in pool.size():
|
||||||
@@ -745,29 +745,29 @@ func _draw_bonus_candidates() -> Array:
|
|||||||
|
|
||||||
|
|
||||||
func _roll_from(rg: RandomNumberGenerator) -> String:
|
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)])
|
return String(pool[rg.randi_range(0, pool.size() - 1)])
|
||||||
|
|
||||||
|
|
||||||
# 三选一道具件随机池(与投放门控同源:aux 活行 ∩ 解锁门控集——空集 = 道具件不入牌库)
|
# 三选一道具件随机池(与投放门控同源:aux 活行 ∩ 解锁门控集——空集 = 道具件不入牌库)
|
||||||
func _bonus_aux_pool() -> Array:
|
func _bonus_treasure_pool() -> Array:
|
||||||
var out: Array = []
|
var out: Array = []
|
||||||
var live: Dictionary = db.aux_live_ids()
|
var live: Dictionary = db.treasure_live_ids()
|
||||||
for iid in live.keys():
|
for iid in live.keys():
|
||||||
if _aux_unlocked.has(String(iid)):
|
if _treasure_unlocked.has(String(iid)):
|
||||||
out.append(String(iid))
|
out.append(String(iid))
|
||||||
return out
|
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")
|
var rg: RandomNumberGenerator = rng.open_stream("reward_pick")
|
||||||
return String(pool[rg.randi_range(0, pool.size() - 1)])
|
return String(pool[rg.randi_range(0, pool.size() - 1)])
|
||||||
|
|
||||||
|
|
||||||
func _carry_records() -> Array:
|
func _carry_records() -> Array:
|
||||||
var out: Array = []
|
var out: Array = []
|
||||||
for i in _bonus_aux_carry.size():
|
for i in _bonus_treasure_carry.size():
|
||||||
out.append({"index": i, "item_id": _bonus_aux_carry[i]})
|
out.append({"index": i, "item_id": _bonus_treasure_carry[i]})
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
@@ -837,11 +837,11 @@ func _start_current_level() -> bool:
|
|||||||
# 注入面随停点渠道退役拆除(容器字段保留=替换子交互机械惰性承载,零投放零行为)
|
# 注入面随停点渠道退役拆除(容器字段保留=替换子交互机械惰性承载,零投放零行为)
|
||||||
level_started.emit(level_index, String(_runner.level_row.get("display_name", "")))
|
level_started.emit(level_index, String(_runner.level_row.get("display_name", "")))
|
||||||
# 入口停点断点(node_id=-1)与 defer_entry 同态(node_index=-1+单候选)——走入口呈现;
|
# 入口停点断点(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:
|
if resume_state.is_empty() or int(resume_state.get("node_id", -1)) < 0:
|
||||||
_runner.present_entry_choice()
|
_runner.present_entry_choice()
|
||||||
else:
|
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()
|
_runner.present_resumed_choice()
|
||||||
_resume_bp = {}
|
_resume_bp = {}
|
||||||
return ok
|
return ok
|
||||||
@@ -861,7 +861,7 @@ func _on_level_finished(payload: Dictionary) -> void:
|
|||||||
if result != "victory":
|
if result != "victory":
|
||||||
push_error("[冒险结构] 关卡结束结果出域: %s" % result)
|
push_error("[冒险结构] 关卡结束结果出域: %s" % result)
|
||||||
return
|
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 钥石逐杀掉落(迭代 10——渠道改击杀掉落,末关照常入账;首杀/复杀读 meta.tres boss_keystone)
|
||||||
_boss_keystone_drop(level_index)
|
_boss_keystone_drop(level_index)
|
||||||
if level_index < levels_total:
|
if level_index < levels_total:
|
||||||
@@ -877,7 +877,7 @@ func _on_level_finished(payload: Dictionary) -> void:
|
|||||||
var pick_payload: Dictionary = {
|
var pick_payload: Dictionary = {
|
||||||
"level_index": level_index,
|
"level_index": level_index,
|
||||||
"candidates": _draw_bonus_candidates(),
|
"candidates": _draw_bonus_candidates(),
|
||||||
"aux_detail": _last_draw_aux.duplicate(), # 掷定前置(追加批二——道具件具体道具随候选抽定,卡片直显)
|
"aux_detail": _last_draw_treasure.duplicate(), # 掷定前置(追加批二——道具件具体道具随候选抽定,卡片直显)
|
||||||
"heal_gained": heal,
|
"heal_gained": heal,
|
||||||
"hp_before": hp_before,
|
"hp_before": hp_before,
|
||||||
"hp_after": int(ledger.get("hero_hp", 0)),
|
"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——关卡末清空反馈取数)
|
"aux_cleared": int(payload.get("aux_cleared", 0)), # additive 扩签(迭代 7 T4——关卡末清空反馈取数)
|
||||||
}
|
}
|
||||||
_bonus_pending = {"candidates": (pick_payload["candidates"] as Array).duplicate(true),
|
_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)}
|
"payload": pick_payload.duplicate(true)}
|
||||||
bonus_choice_presented.emit(pick_payload)
|
bonus_choice_presented.emit(pick_payload)
|
||||||
_snapshot_breakpoint() # 选择停点可中断(契约 5——续玩不重抽不静默丢失)
|
_snapshot_breakpoint() # 选择停点可中断(契约 5——续玩不重抽不静默丢失)
|
||||||
@@ -905,7 +905,7 @@ func _settle(result: String) -> void:
|
|||||||
"stopped_at": 0 if result == "completed" else level_index,
|
"stopped_at": 0 if result == "completed" else level_index,
|
||||||
"keystone_total": keystone,
|
"keystone_total": keystone,
|
||||||
"master_seed": master_seed,
|
"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 入账明细/复盘归因数据源)
|
"keystone_drops": _keystone_drops.duplicate(true), # additive 扩签(迭代 10——逐杀掉落明细;settle 入账明细/复盘归因数据源)
|
||||||
"pool_stock": _pool_stock_snapshot(), # additive 扩签(迭代 11 第②批 T5——终局池读数:清账前快照,商店买走 vs 奖励领走 vs 枯竭的终局面)
|
"pool_stock": _pool_stock_snapshot(), # additive 扩签(迭代 11 第②批 T5——终局池读数:清账前快照,商店买走 vs 奖励领走 vs 枯竭的终局面)
|
||||||
"relics": _relics.duplicate(), # additive 扩签(迭代 12 T1——特性终局持有集:清账前快照,成型判读取数面)
|
"relics": _relics.duplicate(), # additive 扩签(迭代 12 T1——特性终局持有集:清账前快照,成型判读取数面)
|
||||||
@@ -948,9 +948,9 @@ func _forward_choices_presented(candidates: Array) -> void:
|
|||||||
func _snapshot_breakpoint() -> void:
|
func _snapshot_breakpoint() -> void:
|
||||||
if _save_manager == null or state != "running":
|
if _save_manager == null or state != "running":
|
||||||
return
|
return
|
||||||
var aux_items: Array = []
|
var treasure_snapshot: Array = []
|
||||||
if _runner != null and _runner.aux_inventory != null:
|
if _runner != null and _runner.treasure_inventory != null:
|
||||||
aux_items = _runner.aux_inventory.snapshot_inventory()
|
treasure_snapshot = _runner.treasure_inventory.snapshot_inventory()
|
||||||
# 三选一停点续玩分支 _runner 为 null(关卡已收束、下一关未开)——节点域字段按缺省落档,
|
# 三选一停点续玩分支 _runner 为 null(关卡已收束、下一关未开)——节点域字段按缺省落档,
|
||||||
# 该两态的续玩只消费 bonus_* 附随件(选择停点/已兑付停点快照,迭代 10)
|
# 该两态的续玩只消费 bonus_* 附随件(选择停点/已兑付停点快照,迭代 10)
|
||||||
var bp: Dictionary = {
|
var bp: Dictionary = {
|
||||||
@@ -973,13 +973,13 @@ func _snapshot_breakpoint() -> void:
|
|||||||
"rng_counter": rng.counter(),
|
"rng_counter": rng.counter(),
|
||||||
"keystone": keystone,
|
"keystone": keystone,
|
||||||
"visited_ids": _runner.visited_ids() if _runner != null else [],
|
"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_taken": _bonus_taken.duplicate(true), # 三选一件获取次数(kind 维度派生账本——断点附随件与读数承载)
|
||||||
"bonus_deck": _bonus_deck.duplicate(true), # 令牌池余库(TP0 v2.2——池消耗即上限,续玩余库逐枚还原)
|
"bonus_deck": _bonus_deck.duplicate(true), # 令牌池余库(TP0 v2.2——池消耗即上限,续玩余库逐枚还原)
|
||||||
"relics": _relics.duplicate(), # 特性持有集(迭代 12 T1——局内随机渠道获得态续玩防丢失)
|
"relics": _relics.duplicate(), # 特性持有集(迭代 12 T1——局内随机渠道获得态续玩防丢失)
|
||||||
"bonus_pending": _bonus_pending.duplicate(true), # 三选一停点态(空 = 无停点——选择停点可中断契约)
|
"bonus_pending": _bonus_pending.duplicate(true), # 三选一停点态(空 = 无停点——选择停点可中断契约)
|
||||||
"bonus_result": _bonus_result.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)
|
"keystone_drops": _keystone_drops.duplicate(true), # 逐杀掉落明细(摘要归因续接——迭代 10)
|
||||||
}
|
}
|
||||||
_save_manager.set_breakpoint(bp)
|
_save_manager.set_breakpoint(bp)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||||
# Validation Question: 同调位读数是否由「通关次数 + Boss 击杀数」经 attunement_growth.tres 谓词表
|
# Validation Question: 同调位读数是否由「通关次数 + Boss 击杀数」经 attunement_growth.tres 谓词表
|
||||||
# 实时求值(Σ达成 grant clamp slot_cap),迭代 10 过渡键 transitional_sync_slots 得以退役(P0)
|
# 实时求值(Σ达成 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 账本 → 计数字典)与实时求值,纯函数零副作用。
|
# 同调位求值服务:计数源组装(save 账本 → 计数字典)与实时求值,纯函数零副作用。
|
||||||
# 读数源切换(迭代 10 欠账③):装配面消费方(营地装配覆盖层 T4/冒险开始装配注入 T6)一律经本服务取
|
# 读数源切换(迭代 10 欠账③):装配面消费方(营地装配覆盖层 T4/冒险开始装配注入 T6)一律经本服务取
|
||||||
# Slots;过渡键 adventure.transitional_sync_slots 的在途读取面(aux_items 持有上限 gate/战斗内沉没/
|
# Slots;过渡键 adventure.transitional_sync_slots 的在途读取面(treasure_items 持有上限 gate/战斗内沉没/
|
||||||
# 停点替换交互/main 同调位呈现)系过渡渠道承载——T7 退役面切换时随渠道一并消亡(该批读数源切换的
|
# 停点替换交互/main 同调位呈现)系过渡渠道承载——T7 退役面切换时随渠道一并消亡(该批读数源切换的
|
||||||
# 正主落点,06 欠账③销账注记随 T7/T9)。过渡期切早 = off 态 MC 对 81000 锚添新扰动(fresh 档计数全零
|
# 正主落点,06 欠账③销账注记随 T7/T9)。过渡期切早 = off 态 MC 对 81000 锚添新扰动(fresh 档计数全零
|
||||||
# → Slots=0 ≠ 过渡键 1),违「attune=off 逐位一致」🔴 契约——故本服务先立、在途面 T7 切。
|
# → Slots=0 ≠ 过渡键 1),违「attune=off 逐位一致」🔴 契约——故本服务先立、在途面 T7 切。
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ var action_economy: ActionEconomy
|
|||||||
var _enemy_system: UnitContainer
|
var _enemy_system: UnitContainer
|
||||||
var _status_effects: StatusContainer
|
var _status_effects: StatusContainer
|
||||||
var _reward_economy: RewardEconomy
|
var _reward_economy: RewardEconomy
|
||||||
var aux_inventory: AuxItems # 迭代 7 T3——LevelRunner 注入的关卡域库存引用;
|
var treasure_inventory: TreasureItems # 迭代 7 T3——LevelRunner 注入的关卡域库存引用;
|
||||||
# 每战新建本类,库存不归本类所有——注入面
|
# 每战新建本类,库存不归本类所有——注入面
|
||||||
var _damage: DamageController # 伤害控制器(伤害管线单据化批 2026-09-24——单据唯一兑付管线)
|
var _damage: DamageController # 伤害控制器(伤害管线单据化批 2026-09-24——单据唯一兑付管线)
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ var _board_from_midround_refresh := false # 装板 provenance:轮内刷新换
|
|||||||
var _flag_consumed := {} # 兑付资格以雷格实例为键(板级;换图重置)
|
var _flag_consumed := {} # 兑付资格以雷格实例为键(板级;换图重置)
|
||||||
# 同调装配运行态(迭代 11 第①批 T5——begin_battle 经 enc.attunement 注入;off=空集全部效果零扰动)
|
# 同调装配运行态(迭代 11 第①批 T5——begin_battle 经 enc.attunement 注入;off=空集全部效果零扰动)
|
||||||
var attunement: Array = [] # 装备中同调件 item_id 集
|
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_bank := 0 # 掘进蓄能积点(battle 域——每 charge_n 安全格 +1 点)
|
||||||
var _attune_safe_seen := 0 # 掘进蓄能 battle 域安全开格计数
|
var _attune_safe_seen := 0 # 掘进蓄能 battle 域安全开格计数
|
||||||
# 特性运行态(迭代 12 T2——relic 持有集经 enc.relics 注入;求值旗注 damage_controller.relic_flags;
|
# 特性运行态(迭代 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)
|
return attunement.has(item_id)
|
||||||
|
|
||||||
|
|
||||||
# 装备件表值读取(magnitude/effective_rounds 等——AuxItemTable 行;未装配不读表)
|
# 装备件表值读取(magnitude/effective_rounds 等——TreasureItemTable 行;未装配不读表)
|
||||||
func _attune_row(item_id: String) -> Dictionary:
|
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:
|
func _attune_mag(item_id: String) -> int:
|
||||||
@@ -242,7 +242,7 @@ func begin_battle(enc: Dictionary) -> bool:
|
|||||||
# 同调装配运行态注入(迭代 11 第①批 T5——enc.attunement 携带;off=空集零扰动。淬毒 N 注入
|
# 同调装配运行态注入(迭代 11 第①批 T5——enc.attunement 携带;off=空集零扰动。淬毒 N 注入
|
||||||
# 伤害控制器、偏运 N 注入地图战斗资源——均须先于首板 install)
|
# 伤害控制器、偏运 N 注入地图战斗资源——均须先于首板 install)
|
||||||
attunement = (enc.get("attunement", []) as Array).duplicate()
|
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_bank = 0
|
||||||
_attune_safe_seen = 0
|
_attune_safe_seen = 0
|
||||||
_damage.attune_venom = _attune_mag("venom_edge") if _attune_has("venom_edge") else 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_from_midround_refresh = during_round # 轮内刷新装板 = 刷新图(清图奖励不发);常规换图/开战装板 = false
|
||||||
_board_seq += 1
|
_board_seq += 1
|
||||||
board_changed.emit()
|
board_changed.emit()
|
||||||
if aux_inventory != null:
|
if treasure_inventory != null:
|
||||||
aux_inventory.retire_overlays() # 迭代 7 T3——叠加层随图消亡(换图/刷新图装板点;已花道具不返还)
|
treasure_inventory.retire_overlays() # 迭代 7 T3——叠加层随图消亡(换图/刷新图装板点;已花道具不返还)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
@@ -493,7 +493,7 @@ func _settle() -> void:
|
|||||||
# 掘进蓄能计数(迭代 11 同调批 T6——battle 域安全开格计数,每 charge_n 格积 1 点)
|
# 掘进蓄能计数(迭代 11 同调批 T6——battle 域安全开格计数,每 charge_n 格积 1 点)
|
||||||
if _attune_has("dig_charge"):
|
if _attune_has("dig_charge"):
|
||||||
_attune_safe_seen += 1
|
_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:
|
if cn_b > 0 and _attune_safe_seen % cn_b == 0:
|
||||||
_attune_bank += 1
|
_attune_bank += 1
|
||||||
elif evt.kind == "mine":
|
elif evt.kind == "mine":
|
||||||
@@ -619,22 +619,22 @@ func _relic_yield_adjust(snap: Dictionary, positive: bool) -> Dictionary:
|
|||||||
# 「动作 × 格型」矩阵的执行面:snap = 缓冲期冻结身份快照(cell_type = 该格装板期摇定的类型身份),
|
# 「动作 × 格型」矩阵的执行面:snap = 缓冲期冻结身份快照(cell_type = 该格装板期摇定的类型身份),
|
||||||
# polarity 由动作决定(开安全格/标中旗 = positive,开雷格/标错旗 = negative),
|
# polarity 由动作决定(开安全格/标中旗 = positive,开雷格/标错旗 = negative),
|
||||||
# 兑付行 = 奖励字典(类型, 极性)行。返回 true = percent 行实际生效(flat 行恒 false——兑付结果由行协议承载)。
|
# 兑付行 = 奖励字典(类型, 极性)行。返回 true = percent 行实际生效(flat 行恒 false——兑付结果由行协议承载)。
|
||||||
# ---- 魔法道具(use_aux 四步受理编排保留给同调主动件复用——迭代 11 第①批 T7:过渡授予路由
|
# ---- 秘宝(use_treasure 四步受理编排保留给同调主动件复用——迭代 11 第①批 T7:过渡授予路由
|
||||||
# _grant_aux 随掉落/停点渠道退役拆除;能力件注入归 LevelRunner.set_attune_charges 骑库存面)----
|
# _grant_treasure 随掉落/停点渠道退役拆除;能力件注入归 LevelRunner.set_attune_charges 骑库存面)----
|
||||||
|
|
||||||
|
|
||||||
# use_aux 四步受理(registry use_orchestration 规范序——唯一调用权归本类;序即原子:
|
# use_treasure 四步受理(registry use_orchestration 规范序——唯一调用权归本类;序即原子:
|
||||||
# ① 相位 gate(Active——行动经济 phase getter)→ ② validate_use(目标校验读 排雷玩法 只读面,零消耗)→
|
# ① 相位 gate(Active——行动经济 phase getter)→ ② validate_use(目标校验读 排雷玩法 只读面,零消耗)→
|
||||||
# ③ 逐 kind 应用(顺序钉死:空间先、ap_grant 后——effect_kinds 列表序非运行时语义)→ ④ consume。
|
# ③ 逐 kind 应用(顺序钉死:空间先、ap_grant 后——effect_kinds 列表序非运行时语义)→ ④ consume。
|
||||||
# 拒绝全部发生在 ①②(后两步合法输入下无失败路径);使用零 AP 成本(不经 try_spend)。
|
# 拒绝全部发生在 ①②(后两步合法输入下无失败路径);使用零 AP 成本(不经 try_spend)。
|
||||||
# 结算明细无道具行(GDD——效果即时可见:overlay 呈现+AP 条刷新;AP 过账本 grant_ap 走 _reject 面)。
|
# 结算明细无道具行(GDD——效果即时可见:overlay 呈现+AP 条刷新;AP 过账本 grant_ap 走 _reject 面)。
|
||||||
func use_aux(handle: int, target: Vector2i) -> Dictionary:
|
func use_treasure(handle: int, target: Vector2i) -> Dictionary:
|
||||||
if aux_inventory == null:
|
if treasure_inventory == null:
|
||||||
return {"ok": false, "reason": "库存未接线"}
|
return {"ok": false, "reason": "库存未接线"}
|
||||||
if action_economy.phase != action_economy.PHASE_ACTIVE:
|
if action_economy.phase != action_economy.PHASE_ACTIVE:
|
||||||
return {"ok": false, "reason": "非挖掘期(使用窗口=Active)"}
|
return {"ok": false, "reason": "非挖掘期(使用窗口=Active)"}
|
||||||
var board: MinesweeperRules = minesweeper # 恒等包装退役(2026-10-02 修复批——use_aux 直引公有成员)
|
var board: MinesweeperRules = minesweeper # 恒等包装退役(2026-10-02 修复批——use_treasure 直引公有成员)
|
||||||
var v: Dictionary = aux_inventory.validate_use(handle, target,
|
var v: Dictionary = treasure_inventory.validate_use(handle, target,
|
||||||
Vector2(board.width, board.height),
|
Vector2(board.width, board.height),
|
||||||
func(c: Vector2i): return not board.is_revealed(c))
|
func(c: Vector2i): return not board.is_revealed(c))
|
||||||
if not bool(v.ok):
|
if not bool(v.ok):
|
||||||
@@ -642,14 +642,14 @@ func use_aux(handle: int, target: Vector2i) -> Dictionary:
|
|||||||
# 掘进蓄能受理闸(迭代 11 同调批 T6——bank>0 才可发起,一行一点;积点不足拒绝零消耗)
|
# 掘进蓄能受理闸(迭代 11 同调批 T6——bank>0 才可发起,一行一点;积点不足拒绝零消耗)
|
||||||
if String(v.item_id) == "dig_charge" and _attune_has("dig_charge"):
|
if String(v.item_id) == "dig_charge" and _attune_has("dig_charge"):
|
||||||
if _attune_bank <= 0:
|
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]}
|
return {"ok": false, "reason": "掘进蓄能:安全格积点未达(%d/%d)" % [_attune_safe_seen % cn_info if cn_info > 0 else 0, cn_info]}
|
||||||
_attune_bank -= 1
|
_attune_bank -= 1
|
||||||
var kinds: Array = v.kinds
|
var kinds: Array = v.kinds
|
||||||
if kinds.has("mine_reveal"):
|
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"):
|
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 kinds.has("ap_grant"):
|
||||||
if not action_economy.grant_ap(int(v.magnitude)):
|
if not action_economy.grant_ap(int(v.magnitude)):
|
||||||
return {"ok": false, "reason": "行动点加量被拒(相位防御)"}
|
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)
|
var blasted: Array = board.remove_mines_in(v.resolved)
|
||||||
if blasted.is_empty():
|
if blasted.is_empty():
|
||||||
return {"ok": false, "reason": "爆破工兵包:3×3 区域内无可移除雷格(须未揭示且未插旗)"}
|
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 同一字典引用)
|
# 同调主动件充能扣减(迭代 11 第①批 T6——共享账本直改:adventure/level/settlement 同一字典引用)
|
||||||
if not rec.is_empty() and String(rec.get("source_class", "")) == "attunement":
|
if not rec.is_empty() and String(rec.get("source_class", "")) == "attunement":
|
||||||
var used_iid: String = String(rec.get("item_id", ""))
|
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)
|
# aux 解锁门控转发(迭代 7 T5——LevelRunner 注入;E1/E3 封装:外部经公有面,禁直读 _reward_economy)
|
||||||
func set_aux_unlocked(ids: Dictionary) -> void:
|
func set_treasure_unlocked(ids: Dictionary) -> void:
|
||||||
_reward_economy.set_aux_unlocked(ids)
|
_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:
|
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 词表已除名);剩余类型走极性字典路由。
|
# 无 aux 行入池、FEATURE_KINDS 词表已除名);剩余类型走极性字典路由。
|
||||||
var row: Dictionary = _reward_economy.polarity_row(String(snap.get("cell_type", "")), polarity)
|
var row: Dictionary = _reward_economy.polarity_row(String(snap.get("cell_type", "")), polarity)
|
||||||
if row.is_empty():
|
if row.is_empty():
|
||||||
@@ -1095,7 +1095,7 @@ func _exit_distribution() -> void:
|
|||||||
_fatal("换图编排失败")
|
_fatal("换图编排失败")
|
||||||
return
|
return
|
||||||
# 工兵晨令续队(迭代 11 同调批 T5——upcoming 轮号 = round_index+1 ≤ effective_rounds 才续,P4 甲表值化)
|
# 工兵晨令续队(迭代 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.queue_ap_delta(_attune_mag("dawn_order"))
|
||||||
action_economy.notify_settlement_done(mode)
|
action_economy.notify_settlement_done(mode)
|
||||||
action_economy.notify_round_start()
|
action_economy.notify_round_start()
|
||||||
@@ -1136,8 +1136,8 @@ func _battle_over(result: String) -> void:
|
|||||||
_reward_economy.retire_mapping()
|
_reward_economy.retire_mapping()
|
||||||
_enemy_system.despawn_all()
|
_enemy_system.despawn_all()
|
||||||
_status_effects.notify_battle_end()
|
_status_effects.notify_battle_end()
|
||||||
if aux_inventory != null:
|
if treasure_inventory != null:
|
||||||
aux_inventory.retire_overlays() # 迭代 7 T3——叠加层随战斗结束清空(库存不动——关卡域跨战斗)
|
treasure_inventory.retire_overlays() # 迭代 7 T3——叠加层随战斗结束清空(库存不动——关卡域跨战斗)
|
||||||
action_economy.notify_combat_end() # → Idle,RAP 清零(2026-10-02 修复批:原被 tab 事故并进上一行行尾注释从不执行——每战新建实例掩盖了症状;P0-3)
|
action_economy.notify_combat_end() # → Idle,RAP 清零(2026-10-02 修复批:原被 tab 事故并进上一行行尾注释从不执行——每战新建实例掩盖了症状;P0-3)
|
||||||
db.set_reload_gate(false)
|
db.set_reload_gate(false)
|
||||||
_reset_round_facts()
|
_reset_round_facts()
|
||||||
|
|||||||
+15
-15
@@ -24,10 +24,10 @@ const TABLE_MANIFEST := {
|
|||||||
"shop": "shop.tres", # GP+商店房实施批 2026-09-21(表与 schema 落籍归并行数据面——本批只接线加载与消费)
|
"shop": "shop.tres", # GP+商店房实施批 2026-09-21(表与 schema 落籍归并行数据面——本批只接线加载与消费)
|
||||||
"meta": "meta.tres", # 元进度实现批 2026-09-21(MetaTable 四行族——schema 与表同批落籍)
|
"meta": "meta.tres", # 元进度实现批 2026-09-21(MetaTable 四行族——schema 与表同批落籍)
|
||||||
"meta_tree": "meta_tree.tres", # 迭代 12 T8 双层 BD 天赋树(MetaTreeTable 定义表 Rule 4 豁免——R1 甲融合案 33 节点)
|
"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 建表——大奖励与钥石行值单点)
|
"adventure": "adventure.tres", # 冒险结构实现批 2026-09-21(AdventureTable 建表——大奖励与钥石行值单点)
|
||||||
"attunement_growth": "attunement_growth.tres", # 迭代 11 第①批 同调实施批 T1(AttunementGrowthTable 单行全局——同调位里程碑谓词表;单行先例 Rule 4 豁免)
|
"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
|
var action_economy: ActionEconomyTable
|
||||||
@@ -47,7 +47,7 @@ var shop: ShopTable = null
|
|||||||
# 元进度实现批(2026-09-21):MetaTable 类型化持用(schema 与表同批落籍,无 shop 先例的落籍间隙问题)
|
# 元进度实现批(2026-09-21):MetaTable 类型化持用(schema 与表同批落籍,无 shop 先例的落籍间隙问题)
|
||||||
var meta: MetaTable
|
var meta: MetaTable
|
||||||
var meta_tree: MetaTreeTable # 迭代 12 T8 类型化持用(消费面走 tree_node 访问器)
|
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 adventure: AdventureTable
|
||||||
var attunement_growth: AttunementGrowthTable # 迭代 11 第①批 T1 类型化持用(消费面走 attunement_* 访问器)
|
var attunement_growth: AttunementGrowthTable # 迭代 11 第①批 T1 类型化持用(消费面走 attunement_* 访问器)
|
||||||
var relics: RelicTable # 迭代 12 T1 类型化持用(消费面走 relic_* 访问器)
|
var relics: RelicTable # 迭代 12 T1 类型化持用(消费面走 relic_* 访问器)
|
||||||
@@ -139,7 +139,7 @@ func load_tables(root: String, collect_only: bool) -> bool:
|
|||||||
difficulty = loaded.get("difficulty")
|
difficulty = loaded.get("difficulty")
|
||||||
shop = loaded.get("shop")
|
shop = loaded.get("shop")
|
||||||
meta = loaded.get("meta")
|
meta = loaded.get("meta")
|
||||||
aux_items = loaded.get("aux_items")
|
treasure_items = loaded.get("treasure_items")
|
||||||
adventure = loaded.get("adventure")
|
adventure = loaded.get("adventure")
|
||||||
attunement_growth = loaded.get("attunement_growth")
|
attunement_growth = loaded.get("attunement_growth")
|
||||||
relics = loaded.get("relics")
|
relics = loaded.get("relics")
|
||||||
@@ -248,31 +248,31 @@ func level_count() -> int:
|
|||||||
|
|
||||||
|
|
||||||
# ---- GP+商店房实施批(2026-09-21):ShopTable 消费面(行集解析单点——runner/战斗编排禁自扫表)----
|
# ---- GP+商店房实施批(2026-09-21):ShopTable 消费面(行集解析单点——runner/战斗编排禁自扫表)----
|
||||||
# ── 魔法道具访问器(迭代 7 T1——消费面一律走访问器,禁直读行集)──
|
# ── 秘宝访问器(迭代 7 T1——消费面一律走访问器,禁直读行集)──
|
||||||
# 活行集(非 retired 非 deferred)——投放校验/奖励节点池/呈现可用性的唯一取数口径
|
# 活行集(非 retired 非 deferred)——投放校验/奖励节点池/呈现可用性的唯一取数口径
|
||||||
func aux_active_rows() -> Array:
|
func treasure_active_rows() -> Array:
|
||||||
return aux_items.active_rows() if aux_items != null else []
|
return treasure_items.active_rows() if treasure_items != null else []
|
||||||
|
|
||||||
|
|
||||||
func aux_item_row(item_id: String) -> Dictionary:
|
func treasure_item_row(item_id: String) -> Dictionary:
|
||||||
return aux_items.row_by_id(item_id) if aux_items != null else {}
|
return treasure_items.row_by_id(item_id) if treasure_items != null else {}
|
||||||
|
|
||||||
|
|
||||||
# 过渡渠道活行(form 空 = 切片期过渡形态)——掉落投放/停点池/工坊解锁取数口径;同调行(form 非空)
|
# 过渡渠道活行(form 空 = 切片期过渡形态)——掉落投放/停点池/工坊解锁取数口径;同调行(form 非空)
|
||||||
# 永不入过渡渠道(迭代 11 第①批 T1;T7 退役面切换后本口径随渠道消亡)
|
# 永不入过渡渠道(迭代 11 第①批 T1;T7 退役面切换后本口径随渠道消亡)
|
||||||
func aux_transitional_rows() -> Array:
|
func treasure_transitional_rows() -> Array:
|
||||||
return aux_items.transitional_rows() if aux_items != null else []
|
return treasure_items.transitional_rows() if treasure_items != null else []
|
||||||
|
|
||||||
|
|
||||||
# 同调行集(form 非空——装配覆盖层/效果接线的取数口径,迭代 11 第①批 T1/T4)
|
# 同调行集(form 非空——装配覆盖层/效果接线的取数口径,迭代 11 第①批 T1/T4)
|
||||||
func aux_attunement_rows() -> Array:
|
func treasure_attunement_rows() -> Array:
|
||||||
return aux_items.attunement_rows() if aux_items != null else []
|
return treasure_items.attunement_rows() if treasure_items != null else []
|
||||||
|
|
||||||
|
|
||||||
# 活行词表(掉落投放 effect_id 白名单——过渡渠道口径)
|
# 活行词表(掉落投放 effect_id 白名单——过渡渠道口径)
|
||||||
func aux_live_ids() -> Dictionary:
|
func treasure_live_ids() -> Dictionary:
|
||||||
var out := {}
|
var out := {}
|
||||||
for row in aux_transitional_rows():
|
for row in treasure_transitional_rows():
|
||||||
out[String(row.get("item_id", ""))] = true
|
out[String(row.get("item_id", ""))] = true
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|||||||
@@ -25,30 +25,30 @@ func cross_validate(loaded: Dictionary, push_diag: Callable) -> void:
|
|||||||
# GP+商店房实施批(2026-09-21)例外:gp_gain/gp_loss = GP 战斗内缓冲(escrow)通道的路由键
|
# GP+商店房实施批(2026-09-21)例外:gp_gain/gp_loss = GP 战斗内缓冲(escrow)通道的路由键
|
||||||
# (战斗结算 _apply_gp_row 兑付——不入增益状态容器),词表封闭按字面豁免悬空引用校验。
|
# (战斗结算 _apply_gp_row 兑付——不入增益状态容器),词表封闭按字面豁免悬空引用校验。
|
||||||
for row in rt.rows:
|
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 # aux 行 effect_id=item_id——归 ①b 双表校验(reward_dangling_aux),不入增益词表面
|
continue # aux 行 effect_id=item_id——归 ①b 双表校验(reward_dangling_treasure),不入增益词表面
|
||||||
var eff: String = row.get("effect_id", "")
|
var eff: String = row.get("effect_id", "")
|
||||||
if eff != "" and eff != "gp_gain" and eff != "gp_loss" and not effect_ids.has(eff):
|
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])
|
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,
|
# ①b RewardTable aux 投放行双表校验(迭代 7 T1——reward_dangling_treasure):aux 行 effect_id = item_id,
|
||||||
# 须命中 AuxItemTable 活行(非 retired 非 deferred——罗盘退役/失义件不投放)。retired 行被引用=退役
|
# 须命中 TreasureItemTable 活行(非 retired 非 deferred——罗盘退役/失义件不投放)。retired 行被引用=退役
|
||||||
# 后仍投放(连带错误),同拦。
|
# 后仍投放(连带错误),同拦。
|
||||||
var aux_live := {}
|
var treasure_live := {}
|
||||||
var aux_tab = loaded.get("aux_items")
|
var treasure_tab = loaded.get("treasure_items")
|
||||||
if aux_tab != null:
|
if treasure_tab != null:
|
||||||
for arow in aux_tab.active_rows():
|
for arow in treasure_tab.active_rows():
|
||||||
aux_live[String(arow.get("item_id", ""))] = true
|
treasure_live[String(arow.get("item_id", ""))] = true
|
||||||
for row in rt.rows:
|
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
|
continue
|
||||||
var aux_eff: String = String(row.get("effect_id", ""))
|
var treasure_eff: String = String(row.get("effect_id", ""))
|
||||||
if aux_eff == "": # 负占位行(雷格极性字典兜底,零兑付)——不入投放词表校验
|
if treasure_eff == "": # 负占位行(雷格极性字典兜底,零兑付)——不入投放词表校验
|
||||||
continue
|
continue
|
||||||
if not aux_live.has(aux_eff):
|
if not treasure_live.has(treasure_eff):
|
||||||
push_diag.call("error", "reward_dangling_aux", "RewardTable %s aux 行引用无效道具 %s(retired/deferred/不存在): %s" % [row.get("reward_id"), aux_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}
|
# ①c F2 投放维度覆盖(秘宝 GDD——五维度各 ≥1 掉落权重为正的活行):豁免面 {plan, info, counter}
|
||||||
# = 罗盘退役(plan,2026-09-29 拍板①乙)+显影件 Alpha 重定(info/counter 悬置)——豁免随 Alpha 重定批消减
|
# = 罗盘退役(plan,2026-09-29 拍板①乙)+显影件 Alpha 重定(info/counter 悬置)——豁免随 Alpha 重定批消减
|
||||||
# ①c F2 投放维度覆盖校验随战斗掉落渠道退役(2026-10-01 用户拍板甲——挖格不掉道具,魔法道具
|
# ①c F2 投放维度覆盖校验随战斗掉落渠道退役(2026-10-01 用户拍板甲——挖格不掉道具,秘宝
|
||||||
# 唯一来路=三选一共享池〔节点/通关〕):旧校验=「掉落池五维度各 ≥1 正权重活行」,载体已随
|
# 唯一来路=三选一共享池〔节点/通关〕):旧校验=「掉落池五维度各 ≥1 正权重活行」,载体已随
|
||||||
# reward.tres aux 投放四行删除而消失;共享池为「抽到道具位再动态掷定具体道具」,维度覆盖不可
|
# reward.tres aux 投放四行删除而消失;共享池为「抽到道具位再动态掷定具体道具」,维度覆盖不可
|
||||||
# 静态校验。静态覆盖保证的重立(如按维度钉共享池抽签面)归同调实施批/渠道设计批。
|
# 静态校验。静态覆盖保证的重立(如按维度钉共享池抽签面)归同调实施批/渠道设计批。
|
||||||
|
|||||||
+28
-28
@@ -62,10 +62,10 @@ var base_override := {"atk": 0, "max_hp": 0, "armor_class": 0} # 永久强化
|
|||||||
var _shop_purchased := {} # product_id → 已购档数(现价重算输入;冒险开始清零)
|
var _shop_purchased := {} # product_id → 已购档数(现价重算输入;冒险开始清零)
|
||||||
# 协作对象私有(E1/E3 封装收口 2026-09-13):settlement 读取经 current_battle() 成文出口
|
# 协作对象私有(E1/E3 封装收口 2026-09-13):settlement 读取经 current_battle() 成文出口
|
||||||
var _settlement: BattleOrchestrator = null # 当前战斗编排器(关卡结束置 null)
|
var _settlement: BattleOrchestrator = null # 当前战斗编排器(关卡结束置 null)
|
||||||
var aux_inventory: AuxItems = null # 魔法道具 关卡域库存(迭代 7 T3——AuxItems;跨战斗延续,
|
var treasure_inventory: TreasureItems = null # 秘宝 关卡域库存(迭代 7 T3——TreasureItems;跨战斗延续,
|
||||||
var _aux_unlocked := {} # aux 解锁门控集(迭代 7 T5——拍板③甲;空集=零投放)
|
var _treasure_unlocked := {} # aux 解锁门控集(迭代 7 T5——拍板③甲;空集=零投放)
|
||||||
var _attunement: Array = [] # 同调装配集(迭代 11 第①批 T5——adventure params.attunement 下传,begin_battle enc 携带进战斗结算;空集=off 零扰动)
|
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 载荷)
|
# 关卡末清空+快照计数入 level_finished 载荷)
|
||||||
# ---- 商店共享池模式态(迭代 11 第②批 T3——缺省 legacy=固定三件加定价 off 对照承载,零 RNG 零池消费;TP0 令牌池换代)----
|
# ---- 商店共享池模式态(迭代 11 第②批 T3——缺省 legacy=固定三件加定价 off 对照承载,零 RNG 零池消费;TP0 令牌池换代)----
|
||||||
var _shop_pool_mode := false # pool 模式旗(set_shop_pool 注入时置位——AdventureRunner 按 params.shop_mode 下传)
|
var _shop_pool_mode := false # pool 模式旗(set_shop_pool 注入时置位——AdventureRunner 按 params.shop_mode 下传)
|
||||||
@@ -295,11 +295,11 @@ func present_resumed_choice() -> bool:
|
|||||||
|
|
||||||
|
|
||||||
# 断点道具库存回填(迭代 8 卡①——奖励节点已选道具随停点快照回局;幂等,先清后入受理序重排)
|
# 断点道具库存回填(迭代 8 卡①——奖励节点已选道具随停点快照回局;幂等,先清后入受理序重排)
|
||||||
func restore_aux_items(items: Array) -> void:
|
func restore_treasure_items(items: Array) -> void:
|
||||||
if aux_inventory == null:
|
if treasure_inventory == null:
|
||||||
aux_inventory = AuxItems.new(db)
|
treasure_inventory = TreasureItems.new(db)
|
||||||
aux_inventory.reset()
|
treasure_inventory.reset()
|
||||||
aux_inventory.restore_inventory(items)
|
treasure_inventory.restore_inventory(items)
|
||||||
|
|
||||||
|
|
||||||
func _find_level_row(level_index: int) -> Dictionary:
|
func _find_level_row(level_index: int) -> Dictionary:
|
||||||
@@ -460,11 +460,11 @@ func _enter_node(node: Dictionary) -> bool:
|
|||||||
|
|
||||||
func _start_battle(node: Dictionary) -> bool:
|
func _start_battle(node: Dictionary) -> bool:
|
||||||
_settlement = BattleOrchestrator.new(db, rng)
|
_settlement = BattleOrchestrator.new(db, rng)
|
||||||
if aux_inventory == null:
|
if treasure_inventory == null:
|
||||||
aux_inventory = AuxItems.new(db) # 惰性建——关卡域单实例(跨战斗延续)
|
treasure_inventory = TreasureItems.new(db) # 惰性建——关卡域单实例(跨战斗延续)
|
||||||
_settlement.aux_inventory = aux_inventory # 迭代 7 T3——库存注入(授予路由+use_aux 编排消费面)
|
_settlement.treasure_inventory = treasure_inventory # 迭代 7 T3——库存注入(授予路由+use_treasure 编排消费面)
|
||||||
if _settlement != null:
|
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 会延长
|
# core↔core 接线只许方法 Callable(ADR-0001 静态规则 S6——lambda 捕获 self 会延长
|
||||||
# RefCounted 生命周期乃至成环:settlement 的信号持捕获 runner 的 lambda,runner 又持 settlement)
|
# RefCounted 生命周期乃至成环:settlement 的信号持捕获 runner 的 lambda,runner 又持 settlement)
|
||||||
_settlement.step_row.connect(_forward_step_row)
|
_settlement.step_row.connect(_forward_step_row)
|
||||||
@@ -514,13 +514,13 @@ func _on_battle_finished(payload: Dictionary) -> void:
|
|||||||
close_wallet() # 单关模式:关卡收束即冒险收束(GP 清零);冒险模式归 AdventureRunner._settle
|
close_wallet() # 单关模式:关卡收束即冒险收束(GP 清零);冒险模式归 AdventureRunner._settle
|
||||||
_phase = Phase.ENDED
|
_phase = Phase.ENDED
|
||||||
_settlement = null
|
_settlement = null
|
||||||
var aux_cleared := 0
|
var treasure_cleared := 0
|
||||||
if aux_inventory != null:
|
if treasure_inventory != null:
|
||||||
aux_cleared = aux_inventory.inventory_count() # 快照计数(清空前——「剩余道具随关卡结束清空」可见反馈取数)
|
treasure_cleared = treasure_inventory.inventory_count() # 快照计数(清空前——「剩余道具随关卡结束清空」可见反馈取数)
|
||||||
aux_inventory.reset() # 迭代 7 T3——关卡末库存清空(无论输赢,幂等)
|
treasure_inventory.reset() # 迭代 7 T3——关卡末库存清空(无论输赢,幂等)
|
||||||
level_finished.emit({"result": level_result, "hp": hp_left, "node_index": node_index,
|
level_finished.emit({"result": level_result, "hp": hp_left, "node_index": node_index,
|
||||||
"node_id": _node_id(node), "node_type": String(node.get("type", "")),
|
"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
|
return
|
||||||
# 接口漂移清偿(关卡节点地图 v1.0 ⑦):战斗胜利不再自动推进——确认后进选路口
|
# 接口漂移清偿(关卡节点地图 v1.0 ⑦):战斗胜利不再自动推进——确认后进选路口
|
||||||
_settlement = null
|
_settlement = null
|
||||||
@@ -579,10 +579,10 @@ func current_battle():
|
|||||||
return _settlement
|
return _settlement
|
||||||
|
|
||||||
# aux 解锁门控集注入(迭代 7 T5——AdventureRunner 自 params 传递)
|
# aux 解锁门控集注入(迭代 7 T5——AdventureRunner 自 params 传递)
|
||||||
func set_aux_unlocked(ids: Dictionary) -> void:
|
func set_treasure_unlocked(ids: Dictionary) -> void:
|
||||||
_aux_unlocked = ids
|
_treasure_unlocked = ids
|
||||||
if _settlement != null:
|
if _settlement != null:
|
||||||
_settlement.set_aux_unlocked(ids)
|
_settlement.set_treasure_unlocked(ids)
|
||||||
|
|
||||||
|
|
||||||
# 同调装配集注入(迭代 11 第①批 T5——冒险开始参数面;AdventureRunner 唯一调用方)
|
# 同调装配集注入(迭代 11 第①批 T5——冒险开始参数面;AdventureRunner 唯一调用方)
|
||||||
@@ -617,23 +617,23 @@ func set_tree_rules(rules: Array) -> void:
|
|||||||
# 差额注入防续玩双份——resume 路径 restore_inventory 已含断点内 attune 记录)
|
# 差额注入防续玩双份——resume 路径 restore_inventory 已含断点内 attune 记录)
|
||||||
func set_attune_charges(charges: Dictionary) -> void:
|
func set_attune_charges(charges: Dictionary) -> void:
|
||||||
_attune_charges = charges
|
_attune_charges = charges
|
||||||
if aux_inventory == null:
|
if treasure_inventory == null:
|
||||||
aux_inventory = AuxItems.new(db)
|
treasure_inventory = TreasureItems.new(db)
|
||||||
for iid in charges:
|
for iid in charges:
|
||||||
var existing := 0
|
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):
|
if String(r.item_id) == String(iid) and String(r.source_class) == "attunement" and not bool(r.used):
|
||||||
existing += 1
|
existing += 1
|
||||||
for i in range(maxi(0, int(charges[iid]) - existing)):
|
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)。
|
# 奖励节点兑付透传(迭代 7 T5——呈现层三选一 → 关卡域库存;来源归因 reward_node)。
|
||||||
# 迭代 11 第①批 T7——同调位持有闸随过渡键退役拆除(aux 卡出池后仅剩防御面;能力件容量闸
|
# 迭代 11 第①批 T7——同调位持有闸随过渡键退役拆除(aux 卡出池后仅剩防御面;能力件容量闸
|
||||||
# 正主 = 营地装配面 Attunement.slots 满位禁选)。
|
# 正主 = 营地装配面 Attunement.slots 满位禁选)。
|
||||||
func grant_aux_item(item_id: String, source: String) -> Dictionary:
|
func grant_treasure_item(item_id: String, source: String) -> Dictionary:
|
||||||
if aux_inventory == null:
|
if treasure_inventory == null:
|
||||||
aux_inventory = AuxItems.new(db)
|
treasure_inventory = TreasureItems.new(db)
|
||||||
return aux_inventory.add_item(item_id, source, Vector2i(-1, -1), 0)
|
return treasure_inventory.add_item(item_id, source, Vector2i(-1, -1), 0)
|
||||||
|
|
||||||
|
|
||||||
# 三选一 GP 袋件入账(迭代 10——钱包收口扩「奖励入账」入口;复用战斗完成同一入账原语,
|
# 三选一 GP 袋件入账(迭代 10——钱包收口扩「奖励入账」入口;复用战斗完成同一入账原语,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
# 职责三件:① 属性锻造定价与购买(几何递增——tier 级价格 = 迭代 floor(p × ratio/100),tier 0 =
|
# 职责三件:① 属性锻造定价与购买(几何递增——tier 级价格 = 迭代 floor(p × ratio/100),tier 0 =
|
||||||
# base_price,floor 单一取整对齐 round_direction 纪律);② 道具工坊解锁(渠道由 meta.tres channel
|
# base_price,floor 单一取整对齐 round_direction 纪律);② 道具工坊解锁(渠道由 meta.tres channel
|
||||||
# 字段声明、判定量换算单点 _workshop_progress——2026-09-21 用户拍板可替换轴;首版 = 总通关次数,
|
# 字段声明、判定量换算单点 _workshop_progress——2026-09-21 用户拍板可替换轴;首版 = 总通关次数,
|
||||||
# 钥石直购价随定价批后补最终双渠道;六件局内效果归 Alpha 魔法道具重设计批,本类只有解锁状态);
|
# 钥石直购价随定价批后补最终双渠道;六件局内效果归 Alpha 秘宝重设计批,本类只有解锁状态);
|
||||||
# ③ 冒险收束入账(Boss 两档 = 表值 first_kill/repeat_kill,首杀标记读存档判first;调 SaveManager
|
# ③ 冒险收束入账(Boss 两档 = 表值 first_kill/repeat_kill,首杀标记读存档判first;调 SaveManager
|
||||||
# apply_adventure_summary 入账并附 boss_drops 副本——复盘可归因,验收 5)。
|
# apply_adventure_summary 入账并附 boss_drops 副本——复盘可归因,验收 5)。
|
||||||
# 注入面:hero_override() = 三档 forge flat(全零 = 白板合法态;override 不写表——表运行期只读,
|
# 注入面:hero_override() = 三档 forge flat(全零 = 白板合法态;override 不写表——表运行期只读,
|
||||||
@@ -91,7 +91,7 @@ func workshop_status() -> Array:
|
|||||||
var out: Array[Dictionary] = []
|
var out: Array[Dictionary] = []
|
||||||
for row in db.meta_workshop_items():
|
for row in db.meta_workshop_items():
|
||||||
var iid := String(row.get("item_id", ""))
|
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({
|
out.append({
|
||||||
"item_id": iid,
|
"item_id": iid,
|
||||||
"display_name": String(row.get("display_name", "")),
|
"display_name": String(row.get("display_name", "")),
|
||||||
@@ -326,12 +326,12 @@ func migrate_tree() -> Dictionary:
|
|||||||
save.set_tree_level(String(pair[0]), lvl)
|
save.set_tree_level(String(pair[0]), lvl)
|
||||||
migrated["forge"] += 1
|
migrated["forge"] += 1
|
||||||
var any_unlock := false
|
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)):
|
if save.item_unlocked(String(iid)):
|
||||||
any_unlock = true
|
any_unlock = true
|
||||||
break
|
break
|
||||||
if not any_unlock:
|
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", ""))):
|
if save.item_unlocked(String(row.get("item_id", ""))):
|
||||||
any_unlock = true
|
any_unlock = true
|
||||||
break
|
break
|
||||||
@@ -354,7 +354,7 @@ func migrate_tree() -> Dictionary:
|
|||||||
func toggle_attunement(item_id: String) -> bool:
|
func toggle_attunement(item_id: String) -> bool:
|
||||||
var equipped: Array = save.attunement_equipped()
|
var equipped: Array = save.attunement_equipped()
|
||||||
if not equipped.has(item_id):
|
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", "")) == "":
|
if arow.is_empty() or String(arow.get("form", "")) == "":
|
||||||
return false # 非同调行(过渡/退役行)禁装配
|
return false # 非同调行(过渡/退役行)禁装配
|
||||||
if equipped.size() >= Attunement.slots(db, save):
|
if equipped.size() >= Attunement.slots(db, save):
|
||||||
@@ -370,7 +370,7 @@ func toggle_attunement(item_id: String) -> bool:
|
|||||||
func attune_camp_status() -> Dictionary:
|
func attune_camp_status() -> Dictionary:
|
||||||
var equipped: Array = save.attunement_equipped()
|
var equipped: Array = save.attunement_equipped()
|
||||||
var items: Array[Dictionary] = []
|
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", ""))
|
var iid := String(row.get("item_id", ""))
|
||||||
items.append({
|
items.append({
|
||||||
"item_id": iid,
|
"item_id": iid,
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ func roll_board(eligible: Array) -> bool:
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
# ---- 查询面(Ready 只读;未开格恒可查——魔法道具 桥接结构前提)----
|
# ---- 查询面(Ready 只读;未开格恒可查——秘宝 桥接结构前提)----
|
||||||
|
|
||||||
# 相位只读出口(诊断观测面——unrolled/ready/retired;消费方禁直读 _phase 下划线字段)
|
# 相位只读出口(诊断观测面——unrolled/ready/retired;消费方禁直读 _phase 下划线字段)
|
||||||
func phase() -> String:
|
func phase() -> String:
|
||||||
@@ -296,20 +296,20 @@ func weighted_pick(rows: Array, r: int) -> String:
|
|||||||
|
|
||||||
# aux 解锁门控集(迭代 7 T5——拍板③甲「解锁→进投放池」:未解锁 aux 行不入摇号池。
|
# aux 解锁门控集(迭代 7 T5——拍板③甲「解锁→进投放池」:未解锁 aux 行不入摇号池。
|
||||||
# 空集默认 = 全部 aux 不投放(白板/夹具态零投放——模拟读数零扰动;真实侧 main 组装工坊解锁集传入)
|
# 空集默认 = 全部 aux 不投放(白板/夹具态零投放——模拟读数零扰动;真实侧 main 组装工坊解锁集传入)
|
||||||
var _aux_unlocked := {}
|
var _treasure_unlocked := {}
|
||||||
|
|
||||||
|
|
||||||
func set_aux_unlocked(ids: Dictionary) -> void:
|
func set_treasure_unlocked(ids: Dictionary) -> void:
|
||||||
_aux_unlocked = ids
|
_treasure_unlocked = ids
|
||||||
|
|
||||||
|
|
||||||
func _rollable_rows() -> Array:
|
func _rollable_rows() -> Array:
|
||||||
# 摇号池 = cell 池正向行 weight>0(负向行纯字典不消费权重;封锁格不在本函数职责域——清单由调用方裁剪)
|
# 摇号池 = cell 池正向行 weight>0(负向行纯字典不消费权重;封锁格不在本函数职责域——清单由调用方裁剪)
|
||||||
var out: Array[Dictionary] = []
|
var out: Array[Dictionary] = []
|
||||||
for row in db.reward.rows:
|
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", ""))
|
var iid := String(row.get("effect_id", ""))
|
||||||
if iid == "" or not _aux_unlocked.has(iid):
|
if iid == "" or not _treasure_unlocked.has(iid):
|
||||||
continue
|
continue
|
||||||
if String(row.get("pool_tag", "")) == "cell" and String(row.get("polarity", "")) == "positive" and int(row.weight) > 0:
|
if String(row.get("pool_tag", "")) == "cell" and String(row.get("polarity", "")) == "positive" and int(row.weight) > 0:
|
||||||
out.append(row)
|
out.append(row)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
# keystone_balance / forge_levels / item_unlocks / level_clear_counts / boss_first_kill
|
# keystone_balance / forge_levels / item_unlocks / level_clear_counts / boss_first_kill
|
||||||
# —— 内容 owner = 元进度.md(营地三柜台:钥石余额/属性锻造/道具工坊/通关次数/首杀标记)
|
# —— 内容 owner = 元进度.md(营地三柜台:钥石余额/属性锻造/道具工坊/通关次数/首杀标记)
|
||||||
# boss_kill_count / attunement_equipped / attune_refresh_level
|
# 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 反面清单的
|
# attunement_growth 谓词表计数源;装配关系 = 局外进度事实(元进度域同族——非契约 2 反面清单的
|
||||||
# 「局内道具库存」,后者=冒险进行中瞬态);attune_refresh_level = Y 刷新升级购买等级
|
# 「局内道具库存」,后者=冒险进行中瞬态);attune_refresh_level = Y 刷新升级购买等级
|
||||||
# breakpoint.attunement_charges(主动件充能余量)——每冒险重置语义的断点瞬态附随件,内容装配归
|
# breakpoint.attunement_charges(主动件充能余量)——每冒险重置语义的断点瞬态附随件,内容装配归
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||||
# Validation Question: 道具从掉落到使用的全程零随机零特判——同操作序列重放两遍,库存与叠加层投影逐位相同(P0)
|
# Validation Question: 道具从掉落到使用的全程零随机零特判——同操作序列重放两遍,库存与叠加层投影逐位相同(P0)
|
||||||
# Date: 2026-09-29(迭代 7 T2 core 骨架——魔法道具内容批;设计权威 design/gdd/systems/排雷循环/魔法道具.md
|
# Date: 2026-09-29(迭代 7 T2 core 骨架——秘宝内容批;设计权威 design/gdd/systems/排雷循环/秘宝.md
|
||||||
# + registry aux_items api 8 入口/load_bearing_rules/use_orchestration)
|
# + registry 秘宝条目(键 aux_items 沿用)api 8 入口/load_bearing_rules/use_orchestration)
|
||||||
# 魔法道具 关卡域库存 + 板级叠加层(自持派生信息层)。
|
# 秘宝 关卡域库存 + 板级叠加层(自持派生信息层)。
|
||||||
# 结构冻结照抄(违反即返工):
|
# 结构冻结照抄(违反即返工):
|
||||||
# 零随机(零 RNG 流消费——信息只来自 排雷玩法 恒真数字/地图战斗资源 Ready 映射/行动经济 账本三既有事实源);
|
# 零随机(零 RNG 流消费——信息只来自 排雷玩法 恒真数字/地图战斗资源 Ready 映射/行动经济 账本三既有事实源);
|
||||||
# 库存关卡域(跨轮跨图跨战斗延续、关卡末清空——清空编排归 战斗结算/关卡层,本类只供 clear/reset);
|
# 库存关卡域(跨轮跨图跨战斗延续、关卡末清空——清空编排归 战斗结算/关卡层,本类只供 clear/reset);
|
||||||
@@ -11,10 +11,10 @@
|
|||||||
# 真视恒可用(零雷窗口=「这 9 格没雷」信息非空);点击级零信息不消耗(拒绝零消耗——预读窗口全已开);
|
# 真视恒可用(零雷窗口=「这 9 格没雷」信息非空);点击级零信息不消耗(拒绝零消耗——预读窗口全已开);
|
||||||
# 零特判(排雷玩法 代码零本系统分支——本类不写任何其他系统状态)。
|
# 零特判(排雷玩法 代码零本系统分支——本类不写任何其他系统状态)。
|
||||||
# 负空间:无自动使用入口/无重掷/无事件订阅/无 RNG 直连/无 排雷玩法/地图战斗资源 写入口;
|
# 负空间:无自动使用入口/无重掷/无事件订阅/无 RNG 直连/无 排雷玩法/地图战斗资源 写入口;
|
||||||
# 相位检查归 战斗结算 use_aux 编排第一步(本类不管相位——validate_use 是纯谓词+投影)。
|
# 相位检查归 战斗结算 use_treasure 编排第一步(本类不管相位——validate_use 是纯谓词+投影)。
|
||||||
# 呈现取数面:query_inventory(C 区槽位)/query_overlays(棋盘叠加层标记)——只读投影,零数据复制
|
# 呈现取数面:query_inventory(C 区槽位)/query_overlays(棋盘叠加层标记)——只读投影,零数据复制
|
||||||
# (预读徽章数据源=战斗结算 query_reward_identity 既有读面,本类只记「哪些格要额外显示」)。
|
# (预读徽章数据源=战斗结算 query_reward_identity 既有读面,本类只记「哪些格要额外显示」)。
|
||||||
class_name AuxItems
|
class_name TreasureItems
|
||||||
extends RefCounted
|
extends RefCounted
|
||||||
|
|
||||||
var _items: Array = [] # [{handle, item_id, used}]——受理序;Used 保留只读
|
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:
|
func _item_row(item_id: String) -> Dictionary:
|
||||||
if _db == null:
|
if _db == null:
|
||||||
return {}
|
return {}
|
||||||
if _db.has_method("aux_item_row"):
|
if _db.has_method("treasure_item_row"):
|
||||||
return _db.aux_item_row(item_id) # 表访问收口(2026-10-02——正式面走 ConfigDB 访问器)
|
return _db.treasure_item_row(item_id) # 表访问收口(2026-10-02——正式面走 ConfigDB 访问器)
|
||||||
return _db.aux_items.row_by_id(item_id) # 桩表面(单测 StubDB 无访问器——直读保留,随测试面演进退役)
|
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 注入;测试可注入桩表)
|
var _db = null # ConfigDB(行定义读取——_init 注入;测试可注入桩表)
|
||||||
|
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ func _init(db_ref = null) -> void:
|
|||||||
_db = db_ref
|
_db = db_ref
|
||||||
|
|
||||||
|
|
||||||
# ---- 使用校验(战斗结算 use_aux 编排第二步——纯谓词+投影,零消耗零副作用)----
|
# ---- 使用校验(战斗结算 use_treasure 编排第二步——纯谓词+投影,零消耗零副作用)----
|
||||||
|
|
||||||
# target = 目标格(空间行=3×3 窗口中心;ap 行忽略)。board_size = 板维度;
|
# target = 目标格(空间行=3×3 窗口中心;ap 行忽略)。board_size = 板维度;
|
||||||
# cell_unrevealed_cb = Callable(Vector2i) -> bool(排雷玩法 只读面——预读窗口信息判据)。
|
# cell_unrevealed_cb = Callable(Vector2i) -> bool(排雷玩法 只读面——预读窗口信息判据)。
|
||||||
File renamed without changes.
@@ -7,7 +7,7 @@
|
|||||||
# TP0 令牌池换代(2026-10-03 用户全裁 b——node-reward v2.2):三选一池改固定配额令牌池——普通 70/稀有 25/
|
# TP0 令牌池换代(2026-10-03 用户全裁 b——node-reward v2.2):三选一池改固定配额令牌池——普通 70/稀有 25/
|
||||||
# 罕见 5=100 张;洗牌不放回抽 3、选中踢池未选回池、池耗即枯竭;种类次数上限退役(池消耗即上限)。
|
# 罕见 5=100 张;洗牌不放回抽 3、选中踢池未选回池、池耗即枯竭;种类次数上限退役(池消耗即上限)。
|
||||||
# 档位构成:普通〔小GP 18/小增伤 18/小护甲 17/小生命 17〕+稀有〔大GP/大增伤/大护甲/大生命/恢复 各 5〕
|
# 档位构成:普通〔小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,上调须重扫通关率带)。
|
# 全部 knob provisional-pending-曲线调参批(数值所有权归 难度曲线与Boss,上调须重扫通关率带)。
|
||||||
class_name AdventureTable
|
class_name AdventureTable
|
||||||
@@ -23,7 +23,7 @@ extends Resource
|
|||||||
## 刷新次数 / 金币 / 回复,命名待定〕——本表两类混编;刷新次数与专长获取两项尚未入表。
|
## 刷新次数 / 金币 / 回复,命名待定〕——本表两类混编;刷新次数与专长获取两项尚未入表。
|
||||||
## 类内异质性:金币与回复是即时兑付,不进持有集、不持续生效。)
|
## 类内异质性:金币与回复是即时兑付,不进持有集、不持续生效。)
|
||||||
## 三选一提升池 kind 词表(封闭——断点附随件与牌库剔除态依赖它;扩件走本表+registry 修订)。
|
## 三选一提升池 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"]
|
const FEATURE_KINDS: Array[String] = ["attack", "max_hp", "armor", "gp", "ap", "heal"]
|
||||||
## 令牌档位词表(v2.2 三档位——稀有度命名对齐 MC 策略判读序 316-f:1 级最稀有=rarest 优先)
|
## 令牌档位词表(v2.2 三档位——稀有度命名对齐 MC 策略判读序 316-f:1 级最稀有=rarest 优先)
|
||||||
const TIERS: Array[String] = ["common", "rare", "rarest"]
|
const TIERS: Array[String] = ["common", "rare", "rarest"]
|
||||||
@@ -31,7 +31,7 @@ const TIER_COMMON := "common"
|
|||||||
const TIER_RARE := "rare"
|
const TIER_RARE := "rare"
|
||||||
const TIER_RAREST := "rarest"
|
const TIER_RAREST := "rarest"
|
||||||
## 档位配额结构锚(v2.2 追认 b 定稿——validate() 硬断言;改总量=重裁非调参)。
|
## 档位配额结构锚(v2.2 追认 b 定稿——validate() 硬断言;改总量=重裁非调参)。
|
||||||
## 罕见档 5→3:原「道具件 2」席位随 aux_item 池种退役(迭代 11 第①批 T7,落地晚于追认 b)收窄,
|
## 罕见档 5→3:原「道具件 2」席位随 treasure_item 池种退役(迭代 11 第①批 T7,落地晚于追认 b)收窄,
|
||||||
## 池总量 100→98——TP0 台账自决+人工清单披露项。
|
## 池总量 100→98——TP0 台账自决+人工清单披露项。
|
||||||
const TIER_QUOTAS := {"common": 70, "rare": 25, "rarest": 3}
|
const TIER_QUOTAS := {"common": 70, "rare": 25, "rarest": 3}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||||
# Validation Question: 同调位增长是否由「通关次数 + Boss 击杀数」经数据驱动的里程碑谓词表实时求值,
|
# Validation Question: 同调位增长是否由「通关次数 + Boss 击杀数」经数据驱动的里程碑谓词表实时求值,
|
||||||
# 试玩后调增长曲线 = 改表不动码(proposal-magic-item-attunement-2026-09-22 §2.1 用户点名要求)
|
# 试玩后调增长曲线 = 改表不动码(proposal-magic-item-attunement-2026-09-22 §2.1 用户点名要求)
|
||||||
# Date: 2026-10-03(迭代 11 第①批 魔法道具同调实施批 T1——任务书 v1.1 §六 T1;设计权威底稿 proposal §2)
|
# Date: 2026-10-03(迭代 11 第①批 秘宝同调实施批 T1——任务书 v1.1 §六 T1;设计权威底稿 proposal §2)
|
||||||
# 数据配置 AttunementGrowthTable schema(魔法道具 回填 owner)。
|
# 数据配置 AttunementGrowthTable schema(秘宝 回填 owner)。
|
||||||
# 单行全局常量表(slot_cap + milestones 行族——AdventureTable 单行全局先例,Rule 4 豁免)。
|
# 单行全局常量表(slot_cap + milestones 行族——AdventureTable 单行全局先例,Rule 4 豁免)。
|
||||||
# 行 = Dictionary:{id: String 唯一, grant: int, requires: [{key: String, threshold: int}]}——
|
# 行 = Dictionary:{id: String 唯一, grant: int, requires: [{key: String, threshold: int}]}——
|
||||||
# requires 为 (计数键, 阈值) 对的 AND 列表,全部满足即授予 grant 槽;
|
# requires 为 (计数键, 阈值) 对的 AND 列表,全部满足即授予 grant 槽;
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
# 投值语言锁定 flat 整数;几何定价 tier 级价格 = 迭代 p = floor(p × price_ratio_pct/100),tier 0 = base_price)。
|
# 投值语言锁定 flat 整数;几何定价 tier 级价格 = 迭代 p = floor(p × price_ratio_pct/100),tier 0 = base_price)。
|
||||||
# boss_keystone = Boss 钥石两档行(level_index 连续从 1;first_kill ≥ repeat_kill——首杀全量、
|
# boss_keystone = Boss 钥石两档行(level_index 连续从 1;first_kill ≥ repeat_kill——首杀全量、
|
||||||
# 重复杀固定小额恒定不递减,两档数值归元进度设计批配读数)。
|
# 重复杀固定小额恒定不递减,两档数值归元进度设计批配读数)。
|
||||||
# workshop_items = 道具工坊行(item_id = registry aux_items 六件词表封闭恰全;首版解锁渠道 = 总通关次数
|
# workshop_items = 道具工坊行(item_id = 秘宝六件词表封闭恰全;首版解锁渠道 = 总通关次数
|
||||||
# 达标 clear_threshold——2026-09-20 排期裁决;局内效果整体归 Alpha 魔法道具重设计批,本表只有解锁状态面)。
|
# 达标 clear_threshold——2026-09-20 排期裁决;局内效果整体归 Alpha 秘宝重设计批,本表只有解锁状态面)。
|
||||||
# conversion = 区间平移换算率行(attr 与 forge 词表一致恰三;per_level_shift_pct ∈ [0,100]——
|
# conversion = 区间平移换算率行(attr 与 forge 词表一致恰三;per_level_shift_pct ∈ [0,100]——
|
||||||
# registry 键 meta_progression_conversion_table;护甲行强条目:验收读数必须按解锁后参数重测)。
|
# registry 键 meta_progression_conversion_table;护甲行强条目:验收读数必须按解锁后参数重测)。
|
||||||
# attune_refresh_upgrade = Y 刷新升级行族(迭代 11 第①批 T4——P1 甲:每冒险开局给 Y 次、冒险周期池、
|
# attune_refresh_upgrade = Y 刷新升级行族(迭代 11 第①批 T4——P1 甲:每冒险开局给 Y 次、冒险周期池、
|
||||||
@@ -80,12 +80,12 @@ func validate() -> Array:
|
|||||||
if li_at != i + 1:
|
if li_at != i + 1:
|
||||||
errs.append({"category": "structural", "message": "boss_keystone level_index 不连续(须从 1 连续递增): 位 %d = %d" % [i + 1, li_at]})
|
errs.append({"category": "structural", "message": "boss_keystone level_index 不连续(须从 1 连续递增): 位 %d = %d" % [i + 1, li_at]})
|
||||||
break
|
break
|
||||||
# workshop_items:item_id 词表封闭 + 唯一 + 覆盖恰六(registry aux_items 词表)+ 阈值域 [1,99]
|
# workshop_items:item_id 词表封闭 + 唯一 + 覆盖恰六(秘宝词表)+ 阈值域 [1,99]
|
||||||
var seen_item := {}
|
var seen_item := {}
|
||||||
for row in workshop_items:
|
for row in workshop_items:
|
||||||
var iid: String = row.get("item_id", "")
|
var iid: String = row.get("item_id", "")
|
||||||
if not WORKSHOP_ITEM_IDS.has(iid):
|
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):
|
if seen_item.has(iid):
|
||||||
errs.append({"category": "dup_key", "message": "workshop_items item_id 重复: %s" % iid})
|
errs.append({"category": "dup_key", "message": "workshop_items item_id 重复: %s" % iid})
|
||||||
seen_item[iid] = true
|
seen_item[iid] = true
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# 表名与 relic_id 沿用历史命名,与统一词族对齐归后续批次——见 06-待办清单「命名统一」条目。
|
# 表名与 relic_id 沿用历史命名,与统一词族对齐归后续批次——见 06-待办清单「命名统一」条目。
|
||||||
# 目标渠道:专长走关底 Boss 击败后专属三选一(不新增节点类型),见奇物文档 2.1 节。)
|
# 目标渠道:专长走关底 Boss 击败后专属三选一(不新增节点类型),见奇物文档 2.1 节。)
|
||||||
# 数据配置 RelicTable schema(奇物·专长定义表;行 = Dictionary 键 relic_id,Rule 4 豁免
|
# 数据配置 RelicTable schema(奇物·专长定义表;行 = Dictionary 键 relic_id,Rule 4 豁免
|
||||||
# 定义表——AuxItemTable 先例)。
|
# 定义表——TreasureItemTable 先例)。
|
||||||
# 行字段:relic_id 主键 / display_name / rarity ∈ {common, rare, rarest}(对齐令牌池三档命名——
|
# 行字段:relic_id 主键 / display_name / rarity ∈ {common, rare, rarest}(对齐令牌池三档命名——
|
||||||
# 投放档映射:common/rare→稀有令牌档、rarest→罕见令牌档;relic 令牌永不入普通档=「挂稀有/罕见档」
|
# 投放档映射:common/rare→稀有令牌档、rarest→罕见令牌档;relic 令牌永不入普通档=「挂稀有/罕见档」
|
||||||
# 追认 b 接线口径)/ archetype ∈ ARCHETYPES 七流派标签 / hook ∈ HOOKS 挂点枚举(结算段槽——整合定稿
|
# 追认 b 接线口径)/ archetype ∈ ARCHETYPES 七流派标签 / hook ∈ HOOKS 挂点枚举(结算段槽——整合定稿
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
# 档位激活(整合定稿 设计工具 1——以撒套装/小骨铭文):同标签计数 ≥2→档一(流派核心规则)/≥4→档二
|
# 档位激活(整合定稿 设计工具 1——以撒套装/小骨铭文):同标签计数 ≥2→档一(流派核心规则)/≥4→档二
|
||||||
# (完全体);散件单体保底=每件效果独立生效,档位只做质变(反例 B-2)——引擎纯函数 RelicsEngine。
|
# (完全体);散件单体保底=每件效果独立生效,档位只做质变(反例 B-2)——引擎纯函数 RelicsEngine。
|
||||||
# 🔴 层级纪律(任务书红线 2):专长只走局内随机渠道(三选一/商店/格面)——本表行永不入同调位
|
# 🔴 层级纪律(任务书红线 2):专长只走局内随机渠道(三选一/商店/格面)——本表行永不入同调位
|
||||||
# (aux_items 表)/局外树(T8 节点表);扫雷触发点铁律:每流派 ≥1 行 hook ∈ MINE_HOOKS(加载校验,
|
# (treasure_items 表)/局外树(T8 节点表);扫雷触发点铁律:每流派 ≥1 行 hook ∈ MINE_HOOKS(加载校验,
|
||||||
# 违反=红线①触碰面)。
|
# 违反=红线①触碰面)。
|
||||||
class_name RelicTable
|
class_name RelicTable
|
||||||
extends Resource
|
extends Resource
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ extends Resource
|
|||||||
|
|
||||||
@export var rows: Array[Dictionary] = [] # Array[Dictionary]
|
@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 CELL_TYPES := ["attack", "defense", "heal", "blast", "weaken", "pierce", "magic", "action", "gp", "treasure_item"] # 十型(迭代 7 T1 秘宝内容批扩值——registry 秘宝词表;aux 行 effect_id = item_id 双表校验键)
|
||||||
const AUX_ITEM_TYPE := "aux_item" # aux 行标识(掉落投放行:挖开→战斗结算 grant 路由关卡域库存,不入增益容器)
|
const TREASURE_ITEM_TYPE := "treasure_item" # aux 行标识(掉落投放行:挖开→战斗结算 grant 路由关卡域库存,不入增益容器)
|
||||||
const POLARITIES := ["positive", "negative"]
|
const POLARITIES := ["positive", "negative"]
|
||||||
const POOL_TAGS := ["cell", "clear_default"] # cell = 格面资源单一池;clear_<biome> 命名空间预留拒绝
|
const POOL_TAGS := ["cell", "clear_default"] # cell = 格面资源单一池;clear_<biome> 命名空间预留拒绝
|
||||||
const CELL_TYPE_KEYS := ["attack", "defense", "heal", "blast", "weaken", "pierce", "magic", "action", "gp"] # 字典完整性校验轴(类型 × 极性 = 十八格)
|
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):
|
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]})
|
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 投放行专属校验(迭代 7 T1):极性恒正/加权入池/effect_id=item_id 非空(悬空在 config_db 跨表层
|
||||||
# 对 aux_items 词表校验——reward_dangling_aux)/无 power 无区间(数值语义不复用,道具效果读 AuxItemTable)
|
# 对秘宝词表校验——reward_dangling_treasure)/无 power 无区间(数值语义不复用,道具效果读 TreasureItemTable)
|
||||||
if ctype == AUX_ITEM_TYPE:
|
if ctype == TREASURE_ITEM_TYPE:
|
||||||
# 负向行 = 雷格极性字典占位(雷安同池摇号下雷格可摇中 aux 身份——负路由零兑付兜底,
|
# 负向行 = 雷格极性字典占位(雷安同池摇号下雷格可摇中 aux 身份——负路由零兑付兜底,
|
||||||
# effect_id 空/power 0/weight 0 不入池;2026-09-29 T1)
|
# effect_id 空/power 0/weight 0 不入池;2026-09-29 T1)
|
||||||
if pol == "negative":
|
if pol == "negative":
|
||||||
@@ -57,7 +57,7 @@ func validate() -> Array:
|
|||||||
if String(row.get("effect_id", "")) == "":
|
if String(row.get("effect_id", "")) == "":
|
||||||
errs.append({"category": "domain", "message": "%s aux 正行 effect_id 空(应=item_id)" % rid})
|
errs.append({"category": "domain", "message": "%s aux 正行 effect_id 空(应=item_id)" % rid})
|
||||||
if int(row.get("power", 0)) != 0 or row.has("power_min"):
|
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: String = row.get("pool_tag", "")
|
||||||
var pool_reserved: bool = pool.begins_with("clear_") and pool != "clear_default"
|
var pool_reserved: bool = pool.begins_with("clear_") and pool != "clear_default"
|
||||||
if not POOL_TAGS.has(pool) and not pool_reserved:
|
if not POOL_TAGS.has(pool) and not pool_reserved:
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||||
# Validation Question: 挖掘期撞上推理断头时,玩家能否从掉落池捡到魔法道具、在关键时刻花掉买回情报或行动点(P0)
|
# Validation Question: 挖掘期撞上推理断头时,玩家能否从掉落池捡到秘宝、在关键时刻花掉买回情报或行动点(P0)
|
||||||
# Date: 2026-09-29(迭代 7 T1 数据面——魔法道具内容批;设计权威 design/gdd/systems/排雷循环/魔法道具.md v0.4+
|
# Date: 2026-09-29(迭代 7 T1 数据面——秘宝内容批;设计权威 design/gdd/systems/排雷循环/秘宝.md v0.4+
|
||||||
# + registry aux_items 六行 mvp_content;2026-09-29 用户拍板:①乙 探宝罗盘退役留痕 ④甲 显影尘/地穴全图卷失义件
|
# + registry 秘宝条目六行 mvp_content;2026-09-29 用户拍板:①乙 探宝罗盘退役留痕 ④甲 显影尘/地穴全图卷失义件
|
||||||
# 六行全建零投放「已解锁·能力封存中」)
|
# 六行全建零投放「已解锁·能力封存中」)
|
||||||
# 数据配置 AuxItemTable schema(魔法道具 回填 owner)。
|
# 数据配置 TreasureItemTable schema(秘宝 回填 owner)。
|
||||||
# 行 = Dictionary,键 item_id(Rule 4 豁免:定义表——registry aux_items Rule 4 豁免先例)。
|
# 行 = Dictionary,键 item_id(Rule 4 豁免:定义表——registry 秘宝条目 Rule 4 豁免先例)。
|
||||||
# 七字段(registry fields 全量):item_id 主键 / display_name / dimension_tags ⊆ 五维 非空 /
|
# 七字段(registry fields 全量):item_id 主键 / display_name / dimension_tags ⊆ 五维 非空 /
|
||||||
# effect_kinds ⊆ {mine_reveal, reward_preview, ap_grant}(活性校验见下)/ target ∈ {none, area_3x3, board_wide} /
|
# effect_kinds ⊆ {mine_reveal, reward_preview, ap_grant}(活性校验见下)/ target ∈ {none, area_3x3, board_wide} /
|
||||||
# magnitude [0,999](仅 ap_grant 行消费,加载校验 ≥1)/ use_phase ∈ {active_dig}。
|
# magnitude [0,999](仅 ap_grant 行消费,加载校验 ≥1)/ use_phase ∈ {active_dig}。
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
# 行名保留=meta.tres workshop_items 六件词表恰全校验兼容,存档 item_unlocks 旧键无害;
|
# 行名保留=meta.tres workshop_items 六件词表恰全校验兼容,存档 item_unlocks 旧键无害;
|
||||||
# 免活性校验、不入投放校验、不入 F2 覆盖面、奖励节点/掉落池排除)
|
# 免活性校验、不入投放校验、不入 F2 覆盖面、奖励节点/掉落池排除)
|
||||||
# deferred = 效果失义待重定行(probe_dust/catacomb_scroll——原显影半边随雾格移除失义,效果与目标
|
# deferred = 效果失义待重定行(probe_dust/catacomb_scroll——原显影半边随雾格移除失义,效果与目标
|
||||||
# 随魔法道具整体重设计归 Alpha(2026-09-20 用户拍板);免 effect_kinds 非空校验、不入投放与 F2)
|
# 随秘宝整体重设计归 Alpha(2026-09-20 用户拍板);免 effect_kinds 非空校验、不入投放与 F2)
|
||||||
# 承重护栏(魔法道具 GDD §结构冻结,schema 校验强制不靠运行时拦截):
|
# 承重护栏(秘宝 GDD §结构冻结,schema 校验强制不靠运行时拦截):
|
||||||
# 真视窄域——effect_kinds 含 mine_reveal 的活行 target 必须 area_3x3(真视一次最多 3×3,禁全图看雷);
|
# 真视窄域——effect_kinds 含 mine_reveal 的活行 target 必须 area_3x3(真视一次最多 3×3,禁全图看雷);
|
||||||
# board_wide 仅恢复推理原料类——target=board_wide 的活行 effect_kinds 不得含 mine_reveal(现行无此类活行,
|
# board_wide 仅恢复推理原料类——target=board_wide 的活行 effect_kinds 不得含 mine_reveal(现行无此类活行,
|
||||||
# 显影载体待 Alpha 重定后落位)。
|
# 显影载体待 Alpha 重定后落位)。
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
# 🔴 零裸 flat 结构护栏(任务书 §三 1——机制轴禁无条件属性加项):行键白名单封闭(KEY_WHITELIST 外键 =
|
# 🔴 零裸 flat 结构护栏(任务书 §三 1——机制轴禁无条件属性加项):行键白名单封闭(KEY_WHITELIST 外键 =
|
||||||
# 加载致命)+ effect_kinds 封闭枚举只收条件触发/机制修正类 kind——任何「无条件属性加项」类效果不得以
|
# 加载致命)+ effect_kinds 封闭枚举只收条件触发/机制修正类 kind——任何「无条件属性加项」类效果不得以
|
||||||
# 新 kind 或新键入表(返工红线)。
|
# 新 kind 或新键入表(返工红线)。
|
||||||
class_name AuxItemTable
|
class_name TreasureItemTable
|
||||||
extends Resource
|
extends Resource
|
||||||
|
|
||||||
@export var rows: Array = [] # Array[Dictionary] 键 item_id
|
@export var rows: Array = [] # Array[Dictionary] 键 item_id
|
||||||
@@ -109,7 +109,7 @@ func validate() -> Array:
|
|||||||
kind_seen[kind] = true
|
kind_seen[kind] = true
|
||||||
# 承重护栏①真视窄域:mine_reveal 活行 target 必须 area_3x3(一次最多 3×3,禁全图看雷)
|
# 承重护栏①真视窄域:mine_reveal 活行 target 必须 area_3x3(一次最多 3×3,禁全图看雷)
|
||||||
if kind_seen.has("mine_reveal") and target != "area_3x3":
|
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 仅恢复推理类:全图域行禁替推理效果
|
# 承重护栏②board_wide 仅恢复推理类:全图域行禁替推理效果
|
||||||
if target == "board_wide" and kind_seen.has("mine_reveal"):
|
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})
|
errs.append({"category": "load_bearing", "message": "%s board_wide 行 effect_kinds 不得含 mine_reveal(全图域仅恢复推理原料类——Alpha 重定后落位)" % iid})
|
||||||
File renamed without changes.
@@ -28,11 +28,11 @@ feature_value_heal_rare = 6
|
|||||||
feature_value_ap_rarest = 1
|
feature_value_ap_rarest = 1
|
||||||
|
|
||||||
; TP0 令牌池换代(2026-10-03,node-reward v2.2 追认 b 落地):三选一池 = 固定配额令牌池——
|
; TP0 令牌池换代(2026-10-03,node-reward v2.2 追认 b 落地):三选一池 = 固定配额令牌池——
|
||||||
; 普通 70/稀有 25/罕见 3 = 98 张(罕见档原列「道具件 2」随 aux_item 池种退役收窄——台账自决披露项);
|
; 普通 70/稀有 25/罕见 3 = 98 张(罕见档原列「道具件 2」随 treasure_item 池种退役收窄——台账自决披露项);
|
||||||
; 洗牌不放回抽 3、选中踢池未选回池、池耗即枯竭;
|
; 洗牌不放回抽 3、选中踢池未选回池、池耗即枯竭;
|
||||||
; 种类次数上限退役(池消耗即上限;货架库存同账本=牌库剩余令牌数)。
|
; 种类次数上限退役(池消耗即上限;货架库存同账本=牌库剩余令牌数)。
|
||||||
; 档位构成:普通〔小GP 18/小增伤 18/小护甲 17/小生命 17〕+ 稀有〔大GP/大增伤/大护甲/大生命/恢复 各 5〕
|
; 档位构成:普通〔小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。
|
; 数值对:小GP 20/大GP 50、小增伤 +1/大 +2、小护甲 +1/大 +2、小生命 +5/大 +10、恢复 +6(当即回血)、AP +1。
|
||||||
; 恢复件 = 新入池种类(rare 档)。
|
; 恢复件 = 新入池种类(rare 档)。
|
||||||
; 退役字段:bonus_weight_*(E-S 权重族)/ bonus_cap_*(种类次数上限族)/ BONUS_CAP_UNLIMITED 哨兵——
|
; 退役字段:bonus_weight_*(E-S 权重族)/ bonus_cap_*(种类次数上限族)/ BONUS_CAP_UNLIMITED 哨兵——
|
||||||
|
|||||||
@@ -269,6 +269,6 @@ rows = [{
|
|||||||
; dig 4/charge 3/devour 4——整合定稿 §2.3 七流派的件面)。
|
; dig 4/charge 3/devour 4——整合定稿 §2.3 七流派的件面)。
|
||||||
; 稀有度→投放档映射:common/rare → 稀有令牌档、rarest → 罕见令牌档(relic 永不入普通令牌档
|
; 稀有度→投放档映射:common/rare → 稀有令牌档、rarest → 罕见令牌档(relic 永不入普通令牌档
|
||||||
; ——「规则改写型特性带挂稀有/罕见档」追认 b 接线口径,普通档 70 张纯数值维持)。
|
; ——「规则改写型特性带挂稀有/罕见档」追认 b 接线口径,普通档 70 张纯数值维持)。
|
||||||
; 🔴 层级纪律:本表行永不入同调位(aux_items)/局外树(T8 节点表)——规则改写型特性只走局内随机渠道。
|
; 🔴 层级纪律:本表行永不入同调位(treasure_items)/局外树(T8 节点表)——规则改写型特性只走局内随机渠道。
|
||||||
; 数值全 provisional 归 M-4 数值批;effects 键白名单封闭(零裸 flat 同族护栏)。
|
; 数值全 provisional 归 M-4 数值批;effects 键白名单封闭(零裸 flat 同族护栏)。
|
||||||
|
|
||||||
@@ -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]
|
[resource]
|
||||||
script = ExtResource("1")
|
script = ExtResource("1")
|
||||||
@@ -94,8 +94,8 @@ static func bonus_pick_header(payload: Dictionary) -> String:
|
|||||||
|
|
||||||
# 三选一选项卡文案(件名 + 档位 + 效果读数;值 = 冒险表行值,组合根喂入;TP0 令牌池——档位词
|
# 三选一选项卡文案(件名 + 档位 + 效果读数;值 = 冒险表行值,组合根喂入;TP0 令牌池——档位词
|
||||||
# 对齐 v2.2 追认 b 口径:小/大前缀(小GP/大GP 族)、恢复/AP 不带档位词;道具件掷定前置时
|
# 对齐 v2.2 追认 b 口径:小/大前缀(小GP/大GP 族)、恢复/AP 不带档位词;道具件掷定前置时
|
||||||
# aux_line = 具体道具「名 · 效果摘要」行——池种退役后恒空走通用分支,机械惰性保留)
|
# treasure_line = 具体道具「名 · 效果摘要」行——池种退役后恒空走通用分支,机械惰性保留)
|
||||||
static func bonus_card_text(id: String, tier: String, value: int, aux_line: String = "") -> String:
|
static func bonus_card_text(id: String, tier: String, value: int, treasure_line: String = "") -> String:
|
||||||
var ts := ""
|
var ts := ""
|
||||||
if tier == "common":
|
if tier == "common":
|
||||||
ts = " · 小"
|
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]
|
return "金币袋%s\n金币 +%d" % [ts, value]
|
||||||
"heal":
|
"heal":
|
||||||
return "恢复药剂\n生命 +%d(当即回复)" % value
|
return "恢复药剂\n生命 +%d(当即回复)" % value
|
||||||
"aux_item":
|
"treasure_item":
|
||||||
if aux_line != "":
|
if treasure_line != "":
|
||||||
return "魔法道具\n%s" % aux_line
|
return "秘宝\n%s" % treasure_line
|
||||||
return "魔法道具\n随机获得一件"
|
return "秘宝\n随机获得一件"
|
||||||
"ap":
|
"ap":
|
||||||
return "行动点提升\n每战首轮 AP +%d" % value
|
return "行动点提升\n每战首轮 AP +%d" % value
|
||||||
return id
|
return id
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# 提升三选一与替换子交互控制器(迭代 13 T4/D4——二期家族① 自 main.gd 迁出;规范 1.1 单一职责):
|
# 提升三选一与替换子交互控制器(迭代 13 T4/D4——二期家族① 自 main.gd 迁出;规范 1.1 单一职责):
|
||||||
# 三选一停点编排(presented→pick→confirm/refresh→resolved→continue)+ 同调位替换子态
|
# 三选一停点编排(presented→pick→confirm/refresh→resolved→continue)+ 同调位替换子态
|
||||||
#(presented→chosen)+ TP0 令牌池卡片文案装配("kind|tier|relic_id" 复合键)+ 工坊显示名投影。
|
#(presented→chosen)+ TP0 令牌池卡片文案装配("kind|tier|relic_id" 复合键)+ 工坊显示名投影。
|
||||||
# 装配纪律(ADR-0001,仿 aux_interact_controller 先例):信号连接不在此发生——bonus_overlay
|
# 装配纪律(ADR-0001,仿 treasure_interact_controller 先例):信号连接不在此发生——bonus_overlay
|
||||||
# 四信号与 adventure 两信号由组合根接至本类 on_* 入口;模态栈/演播后排窗/呈现刷新/终局面/
|
# 四信号与 adventure 两信号由组合根接至本类 on_* 入口;模态栈/演播后排窗/呈现刷新/终局面/
|
||||||
# 推进失败 fatal 经组合根回调注入;adventure/runner 随局更替——现值回调注入;兑付写调用唯一
|
# 推进失败 fatal 经组合根回调注入;adventure/runner 随局更替——现值回调注入;兑付写调用唯一
|
||||||
# 经 adventure.pick_bonus/apply_node_bonus/resolve_bonus_replace(core 侧单口,本类零直写)。
|
# 经 adventure.pick_bonus/apply_node_bonus/resolve_bonus_replace(core 侧单口,本类零直写)。
|
||||||
@@ -29,7 +29,7 @@ var _gp_summary: Callable # () → 战斗总结 GP 行文案(组
|
|||||||
|
|
||||||
var _pending_bonus := {} # 三选一停点载荷暂存(迭代 10——战斗总结结算确认后开三选一面;续玩停点复用)
|
var _pending_bonus := {} # 三选一停点载荷暂存(迭代 10——战斗总结结算确认后开三选一面;续玩停点复用)
|
||||||
var _bonus_context := "level_clear" # 三选一面上下文(level_clear=通关停点→推进下一关 / reward_node=奖励节点→回图选路)
|
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 记录
|
var _last_replace_incoming := {} # 同上——incoming 记录
|
||||||
|
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ func resume_if_pending() -> bool:
|
|||||||
# 增量行在其上),确认后进三选一面(level-clear.md v2);续玩停点恢复同入口(零自动推进契约)
|
# 增量行在其上),确认后进三选一面(level-clear.md v2);续玩停点恢复同入口(零自动推进契约)
|
||||||
func on_presented(payload: Dictionary) -> void:
|
func on_presented(payload: Dictionary) -> void:
|
||||||
if int(payload.get("aux_cleared", 0)) > 0:
|
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)
|
_pending_bonus = payload.duplicate(true)
|
||||||
_bonus_context = "level_clear"
|
_bonus_context = "level_clear"
|
||||||
if bool(payload.get("replace_pending", false)):
|
if bool(payload.get("replace_pending", false)):
|
||||||
@@ -87,9 +87,9 @@ func on_presented(payload: Dictionary) -> void:
|
|||||||
_refresh_presentations.call()
|
_refresh_presentations.call()
|
||||||
|
|
||||||
|
|
||||||
# 三选一面开出(战斗总结结算确认 / 续玩停点恢复;替换在途由 aux_replace_presented 续发直落子态)
|
# 三选一面开出(战斗总结结算确认 / 续玩停点恢复;替换在途由 treasure_replace_presented 续发直落子态)
|
||||||
# 奖励节点三选一(迭代 10 追加批——与通关三选一共享同池同权重同上限;BonusPickOverlay 共用面,
|
# 奖励节点三选一(迭代 10 追加批——与通关三选一共享同池同权重同上限;BonusPickOverlay 共用面,
|
||||||
# 道具件满位替换子交互同构)。原「魔法道具投放渠道」三选一(迭代 7 过渡形态)随批退役。
|
# 道具件满位替换子交互同构)。原「秘宝投放渠道」三选一(迭代 7 过渡形态)随批退役。
|
||||||
func present_node_bonus() -> void:
|
func present_node_bonus() -> void:
|
||||||
var adventure = _adventure_get.call()
|
var adventure = _adventure_get.call()
|
||||||
_bonus_context = "reward_node"
|
_bonus_context = "reward_node"
|
||||||
@@ -101,7 +101,7 @@ func present_node_bonus() -> void:
|
|||||||
bonus_overlay.set_refresh_info(adventure.attune_refresh_left()) # 迭代 11 第①批 T5b——刷新余量投喂
|
bonus_overlay.set_refresh_info(adventure.attune_refresh_left()) # 迭代 11 第①批 T5b——刷新余量投喂
|
||||||
|
|
||||||
|
|
||||||
# 三选一面开出(战斗总结结算确认 / 续玩停点恢复;替换在途由 aux_replace_presented 续发直落子态)
|
# 三选一面开出(战斗总结结算确认 / 续玩停点恢复;替换在途由 treasure_replace_presented 续发直落子态)
|
||||||
func show_pick() -> void:
|
func show_pick() -> void:
|
||||||
var payload: Dictionary = _pending_bonus
|
var payload: Dictionary = _pending_bonus
|
||||||
_open_modal.call(bonus_overlay)
|
_open_modal.call(bonus_overlay)
|
||||||
@@ -111,11 +111,11 @@ func show_pick() -> void:
|
|||||||
_refresh_presentations.call()
|
_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
|
# TP0 令牌池——候选 = {"kind","tier"} 令牌字典;卡片 id = "kind|tier|relic_id" 复合键(同 kind
|
||||||
# 大小两档/同档多 relic 可同屏,kind 单键不构成唯一身份),确认回程拆键(on_pick_confirmed)
|
# 大小两档/同档多 relic 可同屏,kind 单键不构成唯一身份),确认回程拆键(on_pick_confirmed)
|
||||||
var out: Array = []
|
var out: Array = []
|
||||||
var aux_i := 0
|
var treasure_i := 0
|
||||||
for tok in candidates:
|
for tok in candidates:
|
||||||
var kind := String((tok as Dictionary).get("kind", ""))
|
var kind := String((tok as Dictionary).get("kind", ""))
|
||||||
var tier := String((tok as Dictionary).get("tier", ""))
|
var tier := String((tok as Dictionary).get("tier", ""))
|
||||||
@@ -124,10 +124,10 @@ func _bonus_card_texts(candidates: Array, aux_detail: Array = []) -> Array:
|
|||||||
var text := ""
|
var text := ""
|
||||||
if kind == "relic":
|
if kind == "relic":
|
||||||
text = Narrator.relic_card_text(db.relic_row(rid))
|
text = Narrator.relic_card_text(db.relic_row(rid))
|
||||||
elif kind == "aux_item":
|
elif kind == "treasure_item":
|
||||||
var iid := String(aux_detail[aux_i]) if aux_i < aux_detail.size() else ""
|
var iid := String(treasure_detail[treasure_i]) if treasure_i < treasure_detail.size() else ""
|
||||||
aux_i += 1
|
treasure_i += 1
|
||||||
text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier)), _aux_card_line(iid))
|
text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier)), _treasure_card_line(iid))
|
||||||
else:
|
else:
|
||||||
text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier)))
|
text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier)))
|
||||||
out.append({"id": cid, "text": text})
|
out.append({"id": cid, "text": text})
|
||||||
@@ -135,10 +135,10 @@ func _bonus_card_texts(candidates: Array, aux_detail: Array = []) -> Array:
|
|||||||
|
|
||||||
|
|
||||||
# 道具件卡片行(掷定前置——具体道具名 + 效果摘要;空 iid = 无预掷回退态显示通用文案)
|
# 道具件卡片行(掷定前置——具体道具名 + 效果摘要;空 iid = 无预掷回退态显示通用文案)
|
||||||
func _aux_card_line(iid: String) -> String:
|
func _treasure_card_line(iid: String) -> String:
|
||||||
if iid == "":
|
if iid == "":
|
||||||
return ""
|
return ""
|
||||||
var row: Dictionary = db.aux_item_row(iid)
|
var row: Dictionary = db.treasure_item_row(iid)
|
||||||
if row.is_empty():
|
if row.is_empty():
|
||||||
return ""
|
return ""
|
||||||
var parts: Array[String] = []
|
var parts: Array[String] = []
|
||||||
@@ -185,7 +185,7 @@ func on_pick_confirmed(item_id: String) -> void:
|
|||||||
push_error("[bonus_interact] 三选一兑付被拒——见输出日志")
|
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_items = items.duplicate(true)
|
||||||
_last_replace_incoming = incoming.duplicate(true)
|
_last_replace_incoming = incoming.duplicate(true)
|
||||||
if not bonus_overlay.visible:
|
if not bonus_overlay.visible:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||||
# 营地/商店投影控制器(迭代 13 T4/D4——二期家族③ 自 main.gd 迁出;规范 1.1 单一职责):
|
# 营地/商店投影控制器(迭代 13 T4/D4——二期家族③ 自 main.gd 迁出;规范 1.1 单一职责):
|
||||||
# 营地面开合/快照投影/锻造·同调·天赋树·Fork 购买与切换 + 商店房购买/离开(pool 与 product 双面)。
|
# 营地面开合/快照投影/锻造·同调·天赋树·Fork 购买与切换 + 商店房购买/离开(pool 与 product 双面)。
|
||||||
# 装配纪律(ADR-0001,仿 aux_interact_controller 先例):信号连接不在此发生——campbtn/
|
# 装配纪律(ADR-0001,仿 treasure_interact_controller 先例):信号连接不在此发生——campbtn/
|
||||||
# camp_overlay 四信号/shop_overlay 两信号由组合根接至本类 on_* 入口;模态栈/呈现刷新/续玩按钮
|
# camp_overlay 四信号/shop_overlay 两信号由组合根接至本类 on_* 入口;模态栈/呈现刷新/续玩按钮
|
||||||
# 刷新经组合根回调注入;runner 随局更替——现值回调注入;写调用唯一经 MetaProgression 购买原语
|
# 刷新经组合根回调注入;runner 随局更替——现值回调注入;写调用唯一经 MetaProgression 购买原语
|
||||||
# 与 LevelRunner.buy_*(core 侧单口,本类零直写——拒绝可见 pattern 1 兜底 toast 保留原地)。
|
# 与 LevelRunner.buy_*(core 侧单口,本类零直写——拒绝可见 pattern 1 兜底 toast 保留原地)。
|
||||||
|
|||||||
+17
-17
@@ -19,15 +19,15 @@
|
|||||||
# ui_assembler.gd,模态层级归 modal_stack.gd,批量模拟编排归 tune_sim_controller.gd,调试模式编排归
|
# ui_assembler.gd,模态层级归 modal_stack.gd,批量模拟编排归 tune_sim_controller.gd,调试模式编排归
|
||||||
# debug_session.gd——本类不拼呈现字符串。
|
# debug_session.gd——本类不拼呈现字符串。
|
||||||
# T3 拆件批(2026-10-02,规范 1.1 单一职责):结算行排播泵迁 row_pacer.gd(本类只入队/排空/读队列,
|
# T3 拆件批(2026-10-02,规范 1.1 单一职责):结算行排播泵迁 row_pacer.gd(本类只入队/排空/读队列,
|
||||||
# 探针/测试委托面 _row_queue/pace_delay_for/_flush_row_queue 原位保留);魔法道具两步交互迁
|
# 探针/测试委托面 _row_queue/pace_delay_for/_flush_row_queue 原位保留);秘宝两步交互迁
|
||||||
# aux_interact_controller.gd(本类只接线与转发意图,无目标使用显式化——哨兵坐标不出控制器);
|
# treasure_interact_controller.gd(本类只接线与转发意图,无目标使用显式化——哨兵坐标不出控制器);
|
||||||
# GP 冒险钱包影子账迁 gp_shadow_ledger.gd(本类留探针同名读写委托面)。模态开合全量走
|
# GP 冒险钱包影子账迁 gp_shadow_ledger.gd(本类留探针同名读写委托面)。模态开合全量走
|
||||||
# _open_modal/_close_modal 单口,输入锁=modal_stack.has_open() 开态查询+三例外;battle 收尾反馈与
|
# _open_modal/_close_modal 单口,输入锁=modal_stack.has_open() 开态查询+三例外;battle 收尾反馈与
|
||||||
# 结算视觉 setter 收敛 hud_presenter 单通道(时序敏感演出触发留本类并注释);settlement 相位读取改经
|
# 结算视觉 setter 收敛 hud_presenter 单通道(时序敏感演出触发留本类并注释);settlement 相位读取改经
|
||||||
# presentation_snapshot 成文面、变异表读取直读本根 db(settlement.db 即同一实例)——禁
|
# presentation_snapshot 成文面、变异表读取直读本根 db(settlement.db 即同一实例)——禁
|
||||||
# settlement.action_economy / settlement.db 链式穿透。
|
# settlement.action_economy / settlement.db 链式穿透。
|
||||||
# ADR-0001 纪律:呈现层永不直接订阅 排雷玩法/行动经济——只订 战斗结算/runner 转发信号;相位读取仅用于
|
# ADR-0001 纪律:呈现层永不直接订阅 排雷玩法/行动经济——只订 战斗结算/runner 转发信号;相位读取仅用于
|
||||||
# 驱动视图状态;信号连接只在组合根(row_pacer/aux_interact_controller 零连接,只收注入)。
|
# 驱动视图状态;信号连接只在组合根(row_pacer/treasure_interact_controller 零连接,只收注入)。
|
||||||
extends Control
|
extends Control
|
||||||
|
|
||||||
const UiAssembler := preload("res://presentation/ui_assembler.gd")
|
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 TuneSimController := preload("res://presentation/tune_sim_controller.gd")
|
||||||
const DebugSessionScript := preload("res://presentation/debug_session.gd")
|
const DebugSessionScript := preload("res://presentation/debug_session.gd")
|
||||||
const RowPacer := preload("res://presentation/row_pacer.gd") # 结算行排播泵(T3 拆件批)
|
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 GpShadowLedgerScript := preload("res://presentation/gp_shadow_ledger.gd") # GP 影子账本(T3 拆件批)
|
||||||
const BonusInteractController := preload("res://presentation/bonus_interact_controller.gd") # 三选一与替换子交互(T4/D4 拆件批)
|
const BonusInteractController := preload("res://presentation/bonus_interact_controller.gd") # 三选一与替换子交互(T4/D4 拆件批)
|
||||||
const CampShopPresenter := preload("res://presentation/camp_shop_presenter.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)
|
# T3 拆件批(2026-10-02)——三件迁出后的组合根持有面(职责见各类头注;装配见 _build_ui)
|
||||||
var _row_pacer = null # 结算行排播泵(row_pacer.gd——本类只入队/排空/读队列)
|
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 _bonus = null # 三选一与替换子交互(bonus_interact_controller.gd——本类只接线与回调注入)
|
||||||
var _camp_pres = null # 营地/商店投影(camp_shop_presenter.gd——本类只接线、探针缝保缝转发)
|
var _camp_pres = null # 营地/商店投影(camp_shop_presenter.gd——本类只接线、探针缝保缝转发)
|
||||||
var _gp_ledger := GpShadowLedgerScript.new() # GP 冒险钱包影子账(gp_shadow_ledger.gd——wallet 事件投喂)
|
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.refresh_request = _refresh_presentations
|
||||||
_row_pacer.pump_ended = _on_pump_ended # T17 v3.1+演播后排窗——边沿统一派发(挂起 modal 优先,其次锁期点击重放) # T17 v3.1——演播完边沿重放锁期点击(合并批接线)
|
_row_pacer.pump_ended = _on_pump_ended # T17 v3.1+演播后排窗——边沿统一派发(挂起 modal 优先,其次锁期点击重放) # T17 v3.1——演播完边沿重放锁期点击(合并批接线)
|
||||||
add_child(_row_pacer)
|
add_child(_row_pacer)
|
||||||
# 魔法道具两步交互(T3 拆件批——迁 aux_interact_controller.gd;settlement/runner 随关卡更替,
|
# 秘宝两步交互(T3 拆件批——迁 treasure_interact_controller.gd;settlement/runner 随关卡更替,
|
||||||
# 经现值回调注入——仿 identity_resolver 只读回调先例)
|
# 经现值回调注入——仿 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)
|
func() -> Variant: return settlement, func() -> Variant: return runner)
|
||||||
|
|
||||||
board_zone.action_requested.connect(_on_board_action)
|
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.stop_pressed.connect(_on_stop_pressed)
|
||||||
board_zone.refresh_confirmed.connect(_on_refresh_confirmed)
|
board_zone.refresh_confirmed.connect(_on_refresh_confirmed)
|
||||||
board_zone.legend_toggled.connect(_on_legend_toggled)
|
board_zone.legend_toggled.connect(_on_legend_toggled)
|
||||||
@@ -434,7 +434,7 @@ func _resume_from_menu() -> void:
|
|||||||
log_view.clear()
|
log_view.clear()
|
||||||
logger.start_session(int(bp.get("master_seed", 0)))
|
logger.start_session(int(bp.get("master_seed", 0)))
|
||||||
adventure.set_hero_override(debug_overlay.atk_pct(), debug_overlay.hp_pct())
|
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("续玩恢复失败——见输出日志")
|
_fatal_screen("续玩恢复失败——见输出日志")
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -452,7 +452,7 @@ func _wire_adventure() -> void:
|
|||||||
# 迭代 10 奖励重构批——big_reward_paid 退役,三选一信号族接线
|
# 迭代 10 奖励重构批——big_reward_paid 退役,三选一信号族接线
|
||||||
adventure.bonus_choice_presented.connect(_bonus.on_presented)
|
adventure.bonus_choice_presented.connect(_bonus.on_presented)
|
||||||
adventure.bonus_resolved.connect(_bonus.on_resolved)
|
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.adventure_finished.connect(_on_adventure_finished)
|
||||||
adventure.level_started.connect(_on_adventure_level_started)
|
adventure.level_started.connect(_on_adventure_level_started)
|
||||||
adventure.set_save_manager(save_manager) # 断点承载注入(迭代 8 卡①——停点快照写盘;调试/模拟不经过此路径)
|
adventure.set_save_manager(save_manager) # 断点承载注入(迭代 8 卡①——停点快照写盘;调试/模拟不经过此路径)
|
||||||
@@ -472,7 +472,7 @@ func _start_adventure() -> void:
|
|||||||
# 永久强化注入(元进度实现批):冒险开始参数面——meta 现算 override 显式传参(全零 = 白板)
|
# 永久强化注入(元进度实现批):冒险开始参数面——meta 现算 override 显式传参(全零 = 白板)
|
||||||
# 首次冒险脚本(关卡节点图生成 v0.4):存档布尔位 false = 全关固定模板 0(教学重放);置位后逐关抽签
|
# 首次冒险脚本(关卡节点图生成 v0.4):存档布尔位 false = 全关固定模板 0(教学重放);置位后逐关抽签
|
||||||
var first_script: bool = not save_manager.is_first_adventure_done()
|
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("冒险启动失败——见输出日志")
|
_fatal_screen("冒险启动失败——见输出日志")
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -954,17 +954,17 @@ func _on_board_action(cell: Vector2i, kind: String) -> void:
|
|||||||
if not _row_queue.is_empty():
|
if not _row_queue.is_empty():
|
||||||
_locked_click = {"cell": cell, "kind": kind}
|
_locked_click = {"cell": cell, "kind": kind}
|
||||||
return
|
return
|
||||||
# 魔法道具选中态劫持(迭代 7 T4——两步交互第二步):点格=使用目标拾取,不落挖格;
|
# 秘宝选中态劫持(迭代 7 T4——两步交互第二步):点格=使用目标拾取,不落挖格;
|
||||||
# 只劫持挖掘点击(move/flag 语义不冲突——选中期玩家仍可移动/插旗)
|
# 只劫持挖掘点击(move/flag 语义不冲突——选中期玩家仍可移动/插旗)
|
||||||
var aux_sel: int = _aux.active_selection()
|
var treasure_sel: int = _treasure_ui.active_selection()
|
||||||
if aux_sel != 0 and kind == "dig":
|
if treasure_sel != 0 and kind == "dig":
|
||||||
_aux.attempt_use(aux_sel, cell)
|
_treasure_ui.attempt_use(treasure_sel, cell)
|
||||||
return
|
return
|
||||||
var outcomes: Array = settlement.minesweeper.settle_batch([{"action": kind, "cell": cell}])
|
var outcomes: Array = settlement.minesweeper.settle_batch([{"action": kind, "cell": cell}])
|
||||||
var accepted: bool = not outcomes.is_empty() and bool(outcomes[0].accepted)
|
var accepted: bool = not outcomes.is_empty() and bool(outcomes[0].accepted)
|
||||||
logger.log_action(kind, cell, accepted)
|
logger.log_action(kind, cell, accepted)
|
||||||
if runner != null and runner.aux_inventory != null:
|
if runner != null and runner.treasure_inventory != null:
|
||||||
_aux.refresh_slots() # 迭代 7 T4——授予发生在 settle_batch 结算段内(同步走完,行尾重查)
|
_treasure_ui.refresh_slots() # 迭代 7 T4——授予发生在 settle_batch 结算段内(同步走完,行尾重查)
|
||||||
_handle_outcome_feedback(outcomes[0] if not outcomes.is_empty() else {})
|
_handle_outcome_feedback(outcomes[0] if not outcomes.is_empty() else {})
|
||||||
# settle_batch 内部同步走完 结算→战斗结束→关卡推进(事件同步发射)——关卡终局时 settlement 已被
|
# settle_batch 内部同步走完 结算→战斗结束→关卡推进(事件同步发射)——关卡终局时 settlement 已被
|
||||||
# runner 置空,清图演出判定须先判 settlement(基线既有重入隐患,2026-09-13 加固)
|
# runner 置空,清图演出判定须先判 settlement(基线既有重入隐患,2026-09-13 加固)
|
||||||
|
|||||||
+19
-19
@@ -1,17 +1,17 @@
|
|||||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
# 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)→ 棋盘点格使用目标拾取的两步交互状态机 + 库存/叠加层只读投影装配。
|
# C 区槽位选中/取消(toggle)→ 棋盘点格使用目标拾取的两步交互状态机 + 库存/叠加层只读投影装配。
|
||||||
# 数据源 = runner 级库存只读面(query_inventory/query_overlays)+ 表行投影(display_name/target/effect_kinds);
|
# 数据源 = runner 级库存只读面(query_inventory/query_overlays)+ 表行投影(display_name/target/effect_kinds);
|
||||||
# 写调用唯一经 战斗结算.use_aux(core 侧四步编排——拒绝零消耗 toast 可辨认)。
|
# 写调用唯一经 战斗结算.use_treasure(core 侧四步编排——拒绝零消耗 toast 可辨认)。
|
||||||
# 装配纪律:settlement/runner 随关卡逐关更替——经组合根现值回调注入(仿 identity_resolver 只读回调
|
# 装配纪律:settlement/runner 随关卡逐关更替——经组合根现值回调注入(仿 identity_resolver 只读回调
|
||||||
# 先例);呈现句柄(信息面板/toast/棋盘叠加层)由组合根注入;ADR-0001——信号连接不在此发生,
|
# 先例);呈现句柄(信息面板/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)
|
# 无目标使用显式化(T3 收口):AP 类(target=none)本无坐标可给——原调用面伪造 Vector2i(-9,-9)
|
||||||
# 哨兵坐标;现调用面一律 attempt_use(handle)(cell 缺省=null=显式「无目标」),core 契约的
|
# 哨兵坐标;现调用面一律 attempt_use(handle)(cell 缺省=null=显式「无目标」),core 契约的
|
||||||
# Vector2i 形参收口于本类常量(aux_items.validate_use 对 ap 行忽略目标值,哨兵不出本类)。
|
# Vector2i 形参收口于本类常量(treasure_items.validate_use 对 ap 行忽略目标值,哨兵不出本类)。
|
||||||
extends RefCounted
|
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 db
|
||||||
var meta # 解锁门控数据源(工坊解锁×活行交集——冒险开始组装;组合根 _ready 建立后注入)
|
var meta # 解锁门控数据源(工坊解锁×活行交集——冒险开始组装;组合根 _ready 建立后注入)
|
||||||
@@ -35,12 +35,12 @@ func _init(db_ref, meta_ref, info_panel_ref: HeroInfoPanelView, toast_ref: Toast
|
|||||||
|
|
||||||
|
|
||||||
# aux 解锁门控集组装(迭代 7 T5——拍板③甲:工坊解锁 ∩ 过渡活行词表;罗盘退役/失义件/同调行不入集
|
# aux 解锁门控集组装(迭代 7 T5——拍板③甲:工坊解锁 ∩ 过渡活行词表;罗盘退役/失义件/同调行不入集
|
||||||
# ——迭代 11 第①批 T1 切 aux_transitional_rows 口径,同调行永不入过渡渠道)
|
# ——迭代 11 第①批 T1 切 treasure_transitional_rows 口径,同调行永不入过渡渠道)
|
||||||
func unlocked_set() -> Dictionary:
|
func unlocked_set() -> Dictionary:
|
||||||
var out := {}
|
var out := {}
|
||||||
if meta == null:
|
if meta == null:
|
||||||
return out
|
return out
|
||||||
for row in db.aux_transitional_rows():
|
for row in db.treasure_transitional_rows():
|
||||||
var iid := String(row.get("item_id", ""))
|
var iid := String(row.get("item_id", ""))
|
||||||
if meta.is_item_unlocked(iid):
|
if meta.is_item_unlocked(iid):
|
||||||
out[iid] = true
|
out[iid] = true
|
||||||
@@ -56,7 +56,7 @@ func active_selection() -> int:
|
|||||||
func on_slot_clicked(slot_handle: int) -> void:
|
func on_slot_clicked(slot_handle: int) -> void:
|
||||||
var settlement = _settlement_get.call()
|
var settlement = _settlement_get.call()
|
||||||
var runner = _runner_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
|
return
|
||||||
if slot_handle == 0:
|
if slot_handle == 0:
|
||||||
_use_selection = 0
|
_use_selection = 0
|
||||||
@@ -69,7 +69,7 @@ func on_slot_clicked(slot_handle: int) -> void:
|
|||||||
break
|
break
|
||||||
if rec.is_empty() or bool(rec.get("used", false)):
|
if rec.is_empty() or bool(rec.get("used", false)):
|
||||||
return
|
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":
|
if String(arow.get("target", "none")) == "none":
|
||||||
attempt_use(slot_handle) # AP 类:显式无目标即用(不再伪造哨兵坐标)
|
attempt_use(slot_handle) # AP 类:显式无目标即用(不再伪造哨兵坐标)
|
||||||
return
|
return
|
||||||
@@ -82,13 +82,13 @@ func on_slot_clicked(slot_handle: int) -> void:
|
|||||||
toast.show_toast("%s:点击目标格使用(9 宫窗口),再点道具取消" % String(rec.get("name", "")), "info")
|
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:
|
func attempt_use(handle: int, cell: Variant = null) -> void:
|
||||||
var settlement = _settlement_get.call()
|
var settlement = _settlement_get.call()
|
||||||
if settlement == null:
|
if settlement == null:
|
||||||
return
|
return
|
||||||
var target: Vector2i = cell if cell != null else NO_TARGET
|
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):
|
if not bool(v.ok):
|
||||||
toast.show_toast(String(v.get("reason", "无法使用")), "warn")
|
toast.show_toast(String(v.get("reason", "无法使用")), "warn")
|
||||||
return
|
return
|
||||||
@@ -96,14 +96,14 @@ func attempt_use(handle: int, cell: Variant = null) -> void:
|
|||||||
refresh_slots()
|
refresh_slots()
|
||||||
refresh_overlays()
|
refresh_overlays()
|
||||||
board_view.refresh() # 迭代 13 T8/D6——移除格即时落图(无移除态的件 diff 零变化幂等)
|
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")
|
toast.show_toast("已使用 %s" % String(arow.get("display_name", "")), "info")
|
||||||
|
|
||||||
|
|
||||||
# 库存投影(C 区四槽取数面——字形=名首字;usable=板级零信息预判回调接排雷玩法只读面)
|
# 库存投影(C 区四槽取数面——字形=名首字;usable=板级零信息预判回调接排雷玩法只读面)
|
||||||
func inventory_projection() -> Array:
|
func inventory_projection() -> Array:
|
||||||
var runner = _runner_get.call()
|
var runner = _runner_get.call()
|
||||||
if runner == null or runner.aux_inventory == null:
|
if runner == null or runner.treasure_inventory == null:
|
||||||
return []
|
return []
|
||||||
var settlement = _settlement_get.call()
|
var settlement = _settlement_get.call()
|
||||||
var ms = settlement.minesweeper if settlement != null else null
|
var ms = settlement.minesweeper if settlement != null else null
|
||||||
@@ -112,8 +112,8 @@ func inventory_projection() -> Array:
|
|||||||
cb = func(_c: Vector2i) -> bool:
|
cb = func(_c: Vector2i) -> bool:
|
||||||
return ms.has_unrevealed() # 只读查询面(排雷玩法 has_unrevealed——手搓全板双循环收口)
|
return ms.has_unrevealed() # 只读查询面(排雷玩法 has_unrevealed——手搓全板双循环收口)
|
||||||
var out: Array = []
|
var out: Array = []
|
||||||
for rec in runner.aux_inventory.query_inventory(cb):
|
for rec in runner.treasure_inventory.query_inventory(cb):
|
||||||
var arow: Dictionary = db.aux_item_row(String(rec.get("item_id", "")))
|
var arow: Dictionary = db.treasure_item_row(String(rec.get("item_id", "")))
|
||||||
var dn := String(arow.get("display_name", ""))
|
var dn := String(arow.get("display_name", ""))
|
||||||
out.append({
|
out.append({
|
||||||
"handle": int(rec.get("handle", 0)),
|
"handle": int(rec.get("handle", 0)),
|
||||||
@@ -127,13 +127,13 @@ func inventory_projection() -> Array:
|
|||||||
|
|
||||||
|
|
||||||
func refresh_slots() -> void:
|
func refresh_slots() -> void:
|
||||||
info_panel.set_aux_inventory(inventory_projection(), _use_selection)
|
info_panel.set_treasure_inventory(inventory_projection(), _use_selection)
|
||||||
|
|
||||||
|
|
||||||
# 叠加层投影注入(use 成功/三清后——棋盘标记与预读徽章重算)
|
# 叠加层投影注入(use 成功/三清后——棋盘标记与预读徽章重算)
|
||||||
func refresh_overlays() -> void:
|
func refresh_overlays() -> void:
|
||||||
var runner = _runner_get.call()
|
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
|
return
|
||||||
var ov: Dictionary = runner.aux_inventory.query_overlays()
|
var ov: Dictionary = runner.treasure_inventory.query_overlays()
|
||||||
board_view.set_aux_overlays(ov.get("mine_reveal", []), ov.get("reward_preview", []))
|
board_view.set_treasure_overlays(ov.get("mine_reveal", []), ov.get("reward_preview", []))
|
||||||
File renamed without changes.
@@ -82,7 +82,7 @@ var tex_base: Texture2D = null # ① 砖面底
|
|||||||
var tex_mutation: Texture2D = null # ② 变异纹带
|
var tex_mutation: Texture2D = null # ② 变异纹带
|
||||||
var tex_glyph: Texture2D = null # ③ 数字
|
var tex_glyph: Texture2D = null # ③ 数字
|
||||||
var tex_badge: 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 赋值不重绘=旗插上不显示)
|
set(v): # 均 setter 触发重绘;旧普通 var 赋值不重绘=旗插上不显示)
|
||||||
if tex_flag != v:
|
if tex_flag != v:
|
||||||
tex_flag = v
|
tex_flag = v
|
||||||
@@ -95,13 +95,13 @@ var facade_strip := false: # E 格开关(BoardView paint 按「已开
|
|||||||
|
|
||||||
# 变异角标(迭代 6 T6——程序化,tex_mutation 纹带槽留给变异纹带六型自产批):
|
# 变异角标(迭代 6 T6——程序化,tex_mutation 纹带槽留给变异纹带六型自产批):
|
||||||
# "flat_damage" = 未开格伤害型变异,左下角危险红三角(开格有代价的策略纹理标记)
|
# "flat_damage" = 未开格伤害型变异,左下角危险红三角(开格有代价的策略纹理标记)
|
||||||
# 叠加层标记(迭代 7 T4——魔法道具板级叠加层的格面呈现;派生信息层零回写):
|
# 叠加层标记(迭代 7 T4——秘宝板级叠加层的格面呈现;派生信息层零回写):
|
||||||
# "mine_reveal" = 真视格(危险红内缩框——「这格是雷」的确定决策标记,插旗照常计费);
|
# "mine_reveal" = 真视格(危险红内缩框——「这格是雷」的确定决策标记,插旗照常计费);
|
||||||
# "reward_preview" 格不复用本字段——预读徽章走 badge_glyph 注入(board_view refresh 注入 REWARD_BADGE 字形)
|
# "reward_preview" 格不复用本字段——预读徽章走 badge_glyph 注入(board_view refresh 注入 REWARD_BADGE 字形)
|
||||||
var aux_mark := "":
|
var treasure_mark := "":
|
||||||
set(v):
|
set(v):
|
||||||
if aux_mark != v:
|
if treasure_mark != v:
|
||||||
aux_mark = v
|
treasure_mark = v
|
||||||
queue_redraw()
|
queue_redraw()
|
||||||
var mutation_mark := "":
|
var mutation_mark := "":
|
||||||
set(v):
|
set(v):
|
||||||
@@ -212,8 +212,8 @@ func _draw() -> void:
|
|||||||
draw_texture_rect(tex_mutation, rect, false)
|
draw_texture_rect(tex_mutation, rect, false)
|
||||||
# ②' 变异角标(迭代 6 T6):左下角危险红三角(危险红=「开此格有代价」语义位,与雷族同源;
|
# ②' 变异角标(迭代 6 T6):左下角危险红三角(危险红=「开此格有代价」语义位,与雷族同源;
|
||||||
# 尺寸随格边比例——灰色可辨辅助=红对砖面明度差,禁喧宾)
|
# 尺寸随格边比例——灰色可辨辅助=红对砖面明度差,禁喧宾)
|
||||||
# ②" 魔法道具叠加层(迭代 7 T4):真视格=危险红内缩框(策略纹理——确定决策输入不喧宾)
|
# ②" 秘宝叠加层(迭代 7 T4):真视格=危险红内缩框(策略纹理——确定决策输入不喧宾)
|
||||||
if aux_mark == "mine_reveal":
|
if treasure_mark == "mine_reveal":
|
||||||
var inset := edge * 0.14
|
var inset := edge * 0.14
|
||||||
draw_rect(Rect2(inset, inset, edge - inset * 2.0, edge - inset * 2.0),
|
draw_rect(Rect2(inset, inset, edge - inset * 2.0, edge - inset * 2.0),
|
||||||
Color(UiKit.RED_MINE, 0.9), false, 2.0)
|
Color(UiKit.RED_MINE, 0.9), false, 2.0)
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ var _minesweeper = null # 排雷玩法 只读查询引用(refresh
|
|||||||
var _identity_cb := Callable() # 地图战斗资源 身份解析回调(组合根注入只读面)——Vector2i → Dictionary/null
|
var _identity_cb := Callable() # 地图战斗资源 身份解析回调(组合根注入只读面)——Vector2i → Dictionary/null
|
||||||
var _mask_cb := Callable() # 地形变异 数字遮蔽回调(组合根注入只读面)——Vector2i → bool(true = 该格数字不显示)
|
var _mask_cb := Callable() # 地形变异 数字遮蔽回调(组合根注入只读面)——Vector2i → bool(true = 该格数字不显示)
|
||||||
var _vmark_cb := Callable() # 地形变异 角标回调(迭代 6 T6 只读面)——Vector2i → String("flat_damage"=伤害型变异未开格;""=无)
|
var _vmark_cb := Callable() # 地形变异 角标回调(迭代 6 T6 只读面)——Vector2i → String("flat_damage"=伤害型变异未开格;""=无)
|
||||||
var _aux_reveal := {} # 魔法道具 真视集(迭代 7 T4——Vector2i → true;组合根 set_aux_overlays 注入投影)
|
var _treasure_reveal := {} # 秘宝 真视集(迭代 7 T4——Vector2i → true;组合根 set_treasure_overlays 注入投影)
|
||||||
var _aux_preview := {} # 魔法道具 预读集(同上——未开格徽章呈现挂点)
|
var _treasure_preview := {} # 秘宝 预读集(同上——未开格徽章呈现挂点)
|
||||||
var _diggable := {} # 可挖域(8 向相邻未开格)——呼吸微光作用集
|
var _diggable := {} # 可挖域(8 向相邻未开格)——呼吸微光作用集
|
||||||
var _breath_t := 0.0
|
var _breath_t := 0.0
|
||||||
var _contact_unit: Node2D = null # 接触带承载单元(=英雄格 CellUnit;rebuild 随清场复位)
|
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:
|
func set_variant_mark_resolver(cb: Callable) -> void:
|
||||||
_vmark_cb = cb
|
_vmark_cb = cb
|
||||||
|
|
||||||
# 魔法道具叠加层投影注入(迭代 7 T4——组合根在 use 成功/三清后调;refresh 消费)
|
# 秘宝叠加层投影注入(迭代 7 T4——组合根在 use 成功/三清后调;refresh 消费)
|
||||||
func set_aux_overlays(reveal_cells: Array, preview_cells: Array) -> void:
|
func set_treasure_overlays(reveal_cells: Array, preview_cells: Array) -> void:
|
||||||
_aux_reveal.clear()
|
_treasure_reveal.clear()
|
||||||
_aux_preview.clear()
|
_treasure_preview.clear()
|
||||||
for c in reveal_cells:
|
for c in reveal_cells:
|
||||||
_aux_reveal[Vector2i(c)] = true
|
_treasure_reveal[Vector2i(c)] = true
|
||||||
for c in preview_cells:
|
for c in preview_cells:
|
||||||
_aux_preview[Vector2i(c)] = true
|
_treasure_preview[Vector2i(c)] = true
|
||||||
refresh()
|
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:
|
if south_in and not _minesweeper.is_revealed(south_n) and _tiles_ok:
|
||||||
u.facade_strip = true
|
u.facade_strip = true
|
||||||
u.tex_facade = _tiles.get("wall_center")
|
u.tex_facade = _tiles.get("wall_center")
|
||||||
# ②( 魔法道具叠加层(迭代 7 T4):真视格=红内缩框;预读格=奖励身份徽章(identity_resolver 既有
|
# ②( 秘宝叠加层(迭代 7 T4):真视格=红内缩框;预读格=奖励身份徽章(identity_resolver 既有
|
||||||
# 只读面取字形——零数据复制,badge 位复用);已开格标记自然退位(refresh 逐拍重算)
|
# 只读面取字形——零数据复制,badge 位复用);已开格标记自然退位(refresh 逐拍重算)
|
||||||
if not revealed:
|
if not revealed:
|
||||||
u.aux_mark = "mine_reveal" if _aux_reveal.has(c) else ""
|
u.treasure_mark = "mine_reveal" if _treasure_reveal.has(c) else ""
|
||||||
if _aux_preview.has(c) and glyph == "":
|
if _treasure_preview.has(c) and glyph == "":
|
||||||
var pid = _identity_cb.call(c) if _identity_cb.is_valid() else null
|
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", ""))):
|
if pid != null and REWARD_BADGE.has(String(pid.get("cell_type", ""))):
|
||||||
glyph = String(REWARD_BADGE[String(pid.get("cell_type", ""))])
|
glyph = String(REWARD_BADGE[String(pid.get("cell_type", ""))])
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ func show_result(text: String) -> void:
|
|||||||
visible = true
|
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:
|
func open_replace(items: Array, incoming_name: String, holding: int, slots: int) -> void:
|
||||||
_label.text = "同调位已满(%d/%d)——收下「%s」需丢弃一件已有道具,或放弃新件" % [holding, slots, incoming_name]
|
_label.text = "同调位已满(%d/%d)——收下「%s」需丢弃一件已有道具,或放弃新件" % [holding, slots, incoming_name]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||||
# 实现 GDD:design/ux/battle.md(C 区角色信息 240×548——2026-09-26 信息归属拍板精简:
|
# 实现 GDD:design/ux/battle.md(C 区角色信息 240×548——2026-09-26 信息归属拍板精简:
|
||||||
# 攻击(+修正来源角标)/护甲 AC 数据框 + 魔法道具槽(预留)+ 特性列表(预留)。
|
# 攻击(+修正来源角标)/护甲 AC 数据框 + 秘宝槽(预留)+ 特性列表(预留)。
|
||||||
# HP 条/立绘占位/状态效果槽/RAP 池/GP/钥石退役——HP 与状态唯一展示面 = B 区站桩(同一数据
|
# HP 条/立绘占位/状态效果槽/RAP 池/GP/钥石退役——HP 与状态唯一展示面 = B 区站桩(同一数据
|
||||||
# hud_presenter 双投喂 B/C 两区的重复展示);RAP 迁 D 区 AP 条(贴弃图刷新消费口);
|
# hud_presenter 双投喂 B/C 两区的重复展示);RAP 迁 D 区 AP 条(贴弃图刷新消费口);
|
||||||
# GP(中循环)/钥石(大循环)迁出战斗屏)。
|
# GP(中循环)/钥石(大循环)迁出战斗屏)。
|
||||||
@@ -14,11 +14,11 @@ const COL_INK := UiKit.INK
|
|||||||
|
|
||||||
var _atk_label: Label
|
var _atk_label: Label
|
||||||
var _armor_label: Label
|
var _armor_label: Label
|
||||||
signal aux_slot_clicked(handle: int) # 迭代 7 T4——槽点击(组合根消费:AP 类即用/空间类进选中态)
|
signal treasure_slot_clicked(handle: int) # 迭代 7 T4——槽点击(组合根消费:AP 类即用/空间类进选中态)
|
||||||
var item_slots: HBoxContainer # 魔法道具槽(迭代 7 T4 接线——库存条常读+两步交互第一步)
|
var item_slots: HBoxContainer # 秘宝槽(迭代 7 T4 接线——库存条常读+两步交互第一步)
|
||||||
var _slot_panels: Array = [] # 槽 PanelContainer 引用(选中高亮/置灰重刷)
|
var _slot_panels: Array = [] # 槽 PanelContainer 引用(选中高亮/置灰重刷)
|
||||||
var _selected_handle := 0 # 选中态(0=无;组合根回写维持单源)
|
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_section: VBoxContainer # 特性(预留——空态隐藏,接线归大奖励/锻造呈现批)
|
||||||
var _bonus_list: VBoxContainer
|
var _bonus_list: VBoxContainer
|
||||||
var _relic_section: VBoxContainer # 特性持有段(迭代 12 呈现补齐——空态隐藏)
|
var _relic_section: VBoxContainer # 特性持有段(迭代 12 呈现补齐——空态隐藏)
|
||||||
@@ -51,9 +51,9 @@ func _init() -> void:
|
|||||||
_armor_label = _data_line()
|
_armor_label = _data_line()
|
||||||
data_col.add_child(_armor_label)
|
data_col.add_child(_armor_label)
|
||||||
|
|
||||||
# 魔法道具槽(预留):随身战斗用道具的唯一展示面——空槽占位承诺格子在此,
|
# 秘宝槽(预留):随身战斗用道具的唯一展示面——空槽占位承诺格子在此,
|
||||||
# 不预设交互(挖掘期指向交互归 E 区既有裁决);终稿样式/槽位数归魔法道具批
|
# 不预设交互(挖掘期指向交互归 E 区既有裁决);终稿样式/槽位数归秘宝批
|
||||||
col.add_child(UiKit.label("魔法道具", 16, true))
|
col.add_child(UiKit.label("秘宝", 16, true))
|
||||||
item_slots = HBoxContainer.new()
|
item_slots = HBoxContainer.new()
|
||||||
item_slots.add_theme_constant_override("separation", 10)
|
item_slots.add_theme_constant_override("separation", 10)
|
||||||
col.add_child(item_slots)
|
col.add_child(item_slots)
|
||||||
@@ -66,7 +66,7 @@ func _init() -> void:
|
|||||||
slot.gui_input.connect(func(ev: InputEvent):
|
slot.gui_input.connect(func(ev: InputEvent):
|
||||||
if ev is InputEventMouseButton and ev.pressed and ev.button_index == MOUSE_BUTTON_LEFT:
|
if ev is InputEventMouseButton and ev.pressed and ev.button_index == MOUSE_BUTTON_LEFT:
|
||||||
# 空槽/越界槽点击=取消选中(handle 0);有效槽发其 handle(组合根判 AP 即用/进选中态)
|
# 空槽/越界槽点击=取消选中(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)
|
item_slots.add_child(slot)
|
||||||
_slot_panels.append(slot)
|
_slot_panels.append(slot)
|
||||||
|
|
||||||
@@ -162,11 +162,11 @@ func _data_line() -> Label:
|
|||||||
l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
||||||
return l
|
return l
|
||||||
|
|
||||||
# ---- 魔法道具库存条(迭代 7 T4——C 区四槽常读+两步交互第一步)----
|
# ---- 秘宝库存条(迭代 7 T4——C 区四槽常读+两步交互第一步)----
|
||||||
# 投影行 = {handle, glyph, name, used, usable}(组合根组装:字形=道具名首字;数据源 runner 级库存只读面)。
|
# 投影行 = {handle, glyph, name, used, usable}(组合根组装:字形=道具名首字;数据源 runner 级库存只读面)。
|
||||||
# 空槽=虚位;used=暗态「已用」保留占位(Used 不可逆——受理序展示语义);不可用=置灰(板级零信息);
|
# 空槽=虚位;used=暗态「已用」保留占位(Used 不可逆——受理序展示语义);不可用=置灰(板级零信息);
|
||||||
# selected=金框高亮(两步交互第一步的可见态)。tooltip=全名+维度语义。
|
# 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
|
_selected_handle = selected_handle
|
||||||
_slot_handles.clear()
|
_slot_handles.clear()
|
||||||
for i in 4:
|
for i in 4:
|
||||||
@@ -175,7 +175,7 @@ func set_aux_inventory(items: Array, selected_handle: int) -> void:
|
|||||||
c.queue_free()
|
c.queue_free()
|
||||||
if i >= items.size():
|
if i >= items.size():
|
||||||
_slot_handles.append(0)
|
_slot_handles.append(0)
|
||||||
slot.tooltip_text = "魔法道具槽(空)"
|
slot.tooltip_text = "秘宝槽(空)"
|
||||||
slot.add_theme_stylebox_override("panel",
|
slot.add_theme_stylebox_override("panel",
|
||||||
UiKit.panel_flat(UiKit.PANEL_DATA, UiKit.PANEL_BORDER, 0, 1, Vector4(4, 4, 4, 4)))
|
UiKit.panel_flat(UiKit.PANEL_DATA, UiKit.PANEL_BORDER, 0, 1, Vector4(4, 4, 4, 4)))
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -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_SHOVEL := "res://assets/art/ui/icon_shovel.png" # 图标·铲(挖掘系商品/锻造)
|
||||||
const TEX_ICON_MEDKIT := "res://assets/art/ui/icon_medkit.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_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_COINBAG := "res://assets/art/ui/icon_coinbag.png" # 图标·金币袋
|
||||||
const TEX_ICON_KEYSHARD := "res://assets/art/ui/icon_keyshard.png" # 图标·钥石残片
|
const TEX_ICON_KEYSHARD := "res://assets/art/ui/icon_keyshard.png" # 图标·钥石残片
|
||||||
const TEX_ICON_REFRESH := "res://assets/art/ui/icon_refresh.png" # 图标·刷新(货架/候选)
|
const TEX_ICON_REFRESH := "res://assets/art/ui/icon_refresh.png" # 图标·刷新(货架/候选)
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func _initialize() -> void:
|
|||||||
var slots: int = db.attunement_growth.slots({"clear_count": 3, "boss_kill_count": 6})
|
var slots: int = db.attunement_growth.slots({"clear_count": 3, "boss_kill_count": 6})
|
||||||
var passives: Array = []
|
var passives: Array = []
|
||||||
var actives: Array = []
|
var actives: Array = []
|
||||||
for r in db.aux_attunement_rows():
|
for r in db.treasure_attunement_rows():
|
||||||
if String(r.get("form", "")) == "passive":
|
if String(r.get("form", "")) == "passive":
|
||||||
passives.append(String(r.get("item_id", "")))
|
passives.append(String(r.get("item_id", "")))
|
||||||
elif String(r.get("form", "")) == "active_charged":
|
elif String(r.get("form", "")) == "active_charged":
|
||||||
|
|||||||
@@ -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_choice_presented.connect(_on_adventure_bonus.bind(st, adr))
|
||||||
adr.bonus_resolved.connect(_on_adventure_bonus_resolved.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.adventure_finished.connect(_on_adventure_finished.bind(st, logger))
|
||||||
adr.set_hero_override(atk_pct, hp_pct)
|
adr.set_hero_override(atk_pct, hp_pct)
|
||||||
# 同调分层注入(迭代 11 第①批 T8——缺省 {} 与既有调用方逐位一致零行为变更)
|
# 同调分层注入(迭代 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:
|
static func _on_adventure_treasure_replace(items: Array, incoming: Dictionary, st: Dictionary, adr) -> void:
|
||||||
st.reward_events.append({"aux_replace": incoming.duplicate(true)})
|
st.reward_events.append({"treasure_replace": incoming.duplicate(true)})
|
||||||
if not adr.resolve_bonus_replace(-1):
|
if not adr.resolve_bonus_replace(-1):
|
||||||
st.result = "advance_failed"
|
st.result = "advance_failed"
|
||||||
|
|
||||||
|
|||||||
+16
-16
@@ -543,7 +543,7 @@ func _smoke_adventure() -> void:
|
|||||||
# ⑪ 池耗即枯竭 + 池收缩 + 满血回 0(TP0——white-box:耗尽 attack/ap 令牌后候选零出现;
|
# ⑪ 池耗即枯竭 + 池收缩 + 满血回 0(TP0——white-box:耗尽 attack/ap 令牌后候选零出现;
|
||||||
# 种类次数上限退役,「达上限剔除」语义由牌库耗尽承载)
|
# 种类次数上限退役,「达上限剔除」语义由牌库耗尽承载)
|
||||||
var a11 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(11))
|
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)")
|
"剔牌库/替换场景:冒险启动(seed 11——道具解锁集只含 blast_kit)")
|
||||||
for di in range(a11._bonus_deck.size() - 1, -1, -1):
|
for di in range(a11._bonus_deck.size() - 1, -1, -1):
|
||||||
var dk := String((a11._bonus_deck[di] as Dictionary).get("kind", ""))
|
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(稀有/罕见档余量——防「三选项全不可选」死角)")
|
check((draw as Array).size() >= 2, "池耗后候选恒 ≥2(稀有/罕见档余量——防「三选项全不可选」死角)")
|
||||||
# 池收缩(迭代 11 同调批 T7——aux 卡退役出三选一牌库:重复抽样零 aux 候选;同调位替换两路
|
# 池收缩(迭代 11 同调批 T7——aux 卡退役出三选一牌库:重复抽样零 aux 候选;同调位替换两路
|
||||||
# white-box 测试随停点渠道退役拆除——机械惰性承载,零投放零行为)
|
# white-box 测试随停点渠道退役拆除——机械惰性承载,零投放零行为)
|
||||||
var aux_seen := false
|
var treasure_seen := false
|
||||||
for i in 40:
|
for i in 40:
|
||||||
for t in a11._draw_bonus_candidates():
|
for t in a11._draw_bonus_candidates():
|
||||||
if String((t as Dictionary).get("kind", "")) == "aux_item":
|
if String((t as Dictionary).get("kind", "")) == "treasure_item":
|
||||||
aux_seen = true
|
treasure_seen = true
|
||||||
break
|
break
|
||||||
check(not aux_seen, "池收缩——40 次重抽零 aux 候选(停点渠道 aux 卡退役,迭代 11 第①批 T7)")
|
check(not treasure_seen, "池收缩——40 次重抽零 aux 候选(停点渠道 aux 卡退役,迭代 11 第①批 T7)")
|
||||||
# 满血回 0 合法(通关回血封顶口径)
|
# 满血回 0 合法(通关回血封顶口径)
|
||||||
var a12 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(12))
|
var a12 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(12))
|
||||||
a12.start_adventure(12, {"first_script": true})
|
a12.start_adventure(12, {"first_script": true})
|
||||||
@@ -577,7 +577,7 @@ func _smoke_adventure() -> void:
|
|||||||
"满血通关回血 0 合法(封顶口径——heal_gained=0 非负溢出)")
|
"满血通关回血 0 合法(封顶口径——heal_gained=0 非负溢出)")
|
||||||
# ⑬ 奖励节点共享池(迭代 10 追加批——同库同池同摘牌;TP0:attack 令牌耗尽后节点域同样零出现)
|
# ⑬ 奖励节点共享池(迭代 10 追加批——同库同池同摘牌;TP0:attack 令牌耗尽后节点域同样零出现)
|
||||||
var a13 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(13))
|
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)")
|
"节点共享池场景:冒险启动(seed 13)")
|
||||||
for di13 in range(a13._bonus_deck.size() - 1, -1, -1):
|
for di13 in range(a13._bonus_deck.size() - 1, -1, -1):
|
||||||
if String((a13._bonus_deck[di13] as Dictionary).get("kind", "")) == "attack":
|
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:
|
if r0.has(c) or by_type.size() == 5:
|
||||||
continue
|
continue
|
||||||
var ident = settlement.query_reward_identity(c)
|
var ident = settlement.query_reward_identity(c)
|
||||||
# aux 身份不入五型轴(魔法道具内容批 2026-09-29——五型齐备=格面资源历史断言轴,
|
# aux 身份不入五型轴(秘宝内容批 2026-09-29——五型齐备=格面资源历史断言轴,
|
||||||
# aux 供给挤占不改变本断言语义;扫描排除 aux 身份格)
|
# 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
|
by_type[String(ident.cell_type)] = c
|
||||||
# break 条件=percent_map 三型齐备(迭代 7 T1——aux 供给挤占下 weaken/defense 收集时机漂移,
|
# break 条件=percent_map 三型齐备(迭代 7 T1——aux 供给挤占下 weaken/defense 收集时机漂移,
|
||||||
# 直验可达性优先;五型多样性 check 保留不动)
|
# 直验可达性优先;五型多样性 check 保留不动)
|
||||||
@@ -2679,7 +2679,7 @@ func _smoke_resource_surface() -> void:
|
|||||||
check(digchain_bad == 0, "chain/dig 揭示事件 resource 恒 true(雷安同池——违例 %d)" % digchain_bad)
|
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(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)
|
check(mine_with_resource >= 1, "雷格揭示携带资源(mine ×resource=true %d——雷格不再恒无)" % mine_with_resource)
|
||||||
# 封锁格无身份 / 雷格未开恒可查(未开格恒可查——魔法道具 桥接结构前提)
|
# 封锁格无身份 / 雷格未开恒可查(未开格恒可查——秘宝 桥接结构前提)
|
||||||
var rng3 = load("res://core/rng_service.gd").new()
|
var rng3 = load("res://core/rng_service.gd").new()
|
||||||
rng3.set_master_seed(20260920)
|
rng3.set_master_seed(20260920)
|
||||||
var settlement = load("res://core/battle_orchestrator.gd").new(_db, rng3)
|
var settlement = load("res://core/battle_orchestrator.gd").new(_db, rng3)
|
||||||
@@ -2696,7 +2696,7 @@ func _smoke_resource_surface() -> void:
|
|||||||
break
|
break
|
||||||
check(settlement.query_reward_identity(r0_first) == null, "封锁格(R₀)身份查询 = null(不入摇号清单)")
|
check(settlement.query_reward_identity(r0_first) == null, "封锁格(R₀)身份查询 = null(不入摇号清单)")
|
||||||
check(mine_unrevealed != null and settlement.query_reward_identity(mine_unrevealed) != null,
|
check(mine_unrevealed != null and settlement.query_reward_identity(mine_unrevealed) != null,
|
||||||
"未开雷格身份恒可查({reward_id, cell_type, tier}——魔法道具 桥接前提)")
|
"未开雷格身份恒可查({reward_id, cell_type, tier}——秘宝 桥接前提)")
|
||||||
|
|
||||||
|
|
||||||
# 五段全序断言(战斗结算 验收"五段全序"+ 行型封闭 10 类):逐轮行相位序 = 授予 → 增益/减益 → 战斗 → 衰减 → 判定。
|
# 五段全序断言(战斗结算 验收"五段全序"+ 行型封闭 10 类):逐轮行相位序 = 授予 → 增益/减益 → 战斗 → 衰减 → 判定。
|
||||||
@@ -3895,7 +3895,7 @@ func _smoke_shop_pool() -> void:
|
|||||||
for i in 40:
|
for i in 40:
|
||||||
r8._shop_draw_shelf()
|
r8._shop_draw_shelf()
|
||||||
for c in r8.shop_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
|
cut_seen = true
|
||||||
check(not cut_seen, "切边件零入店(40 次重抽零 gp/aux——负交易切边+三轴 doctrine)")
|
check(not cut_seen, "切边件零入店(40 次重抽零 gp/aux——负交易切边+三轴 doctrine)")
|
||||||
# ⑤ 池空硬闸(库存尽剔出牌库——TP0:white-box 耗尽 attack 令牌后货架零 attack + 消费口拒绝)
|
# ⑤ 池空硬闸(库存尽剔出牌库——TP0:white-box 耗尽 attack 令牌后货架零 attack + 消费口拒绝)
|
||||||
@@ -3980,8 +3980,8 @@ func _all_entry_boss_paths(nodes: Array) -> Array:
|
|||||||
|
|
||||||
func _smoke_nine_types_gp_stream() -> void:
|
func _smoke_nine_types_gp_stream() -> void:
|
||||||
print("--- 格面资源九型 + gp_drop 流(奖励字典 18 格 + 黄金向量)---")
|
print("--- 格面资源九型 + gp_drop 流(奖励字典 18 格 + 黄金向量)---")
|
||||||
check(RewardTable.CELL_TYPES.size() == 10 and RewardTable.CELL_TYPES.has("gp") and RewardTable.CELL_TYPES.has("aux_item"),
|
check(RewardTable.CELL_TYPES.size() == 10 and RewardTable.CELL_TYPES.has("gp") and RewardTable.CELL_TYPES.has("treasure_item"),
|
||||||
"格面资源十型封闭(第九型 gp 九型批 2026-09-20 / 第十型 aux_item 魔法道具内容批 2026-09-29——词表 v1.2)")
|
"格面资源十型封闭(第九型 gp 九型批 2026-09-20 / 第十型 treasure_item 秘宝内容批 2026-09-29——词表 v1.2)")
|
||||||
var cell_rows := 0
|
var cell_rows := 0
|
||||||
var pos_weight := 0
|
var pos_weight := 0
|
||||||
var gp_pos := -1
|
var gp_pos := -1
|
||||||
@@ -3995,7 +3995,7 @@ func _smoke_nine_types_gp_stream() -> void:
|
|||||||
gp_pos = int(row.weight)
|
gp_pos = int(row.weight)
|
||||||
if String(row.get("reward_id", "")) == "gp_lose":
|
if String(row.get("reward_id", "")) == "gp_lose":
|
||||||
gp_neg = int(row.weight)
|
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 倍定价)
|
# 雷格负向直伤当量(迭代 8 卡⑧——真人反馈「三雷 3/4 血无后果感」投值:三行各抬 +3 档,负向≈正向 2 倍定价)
|
||||||
var mine_power := {"heal_backlash": 6, "pierce_snare": 8, "magic_recoil": 8} # 数值修复批 2026-10-01 再抬档(旧 4/5/5,见 numfix 报告)
|
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:
|
for row in _db.reward.rows:
|
||||||
@@ -4543,8 +4543,8 @@ func _smoke_save() -> void:
|
|||||||
var bp_visited: Array = bp.get("visited_ids", [])
|
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,
|
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", [])
|
var bp_treasure: Array = bp.get("aux_items", [])
|
||||||
check(bp_aux.size() == 1 and String(bp_aux[0].get("item_id", "")) == "aux_scout",
|
check(bp_treasure.size() == 1 and String(bp_treasure[0].get("item_id", "")) == "aux_scout",
|
||||||
"断点附随件往返:道具库存")
|
"断点附随件往返:道具库存")
|
||||||
bp["hero_hp"] = 999
|
bp["hero_hp"] = 999
|
||||||
check(int((rb.breakpoint_snapshot() as Dictionary).get("hero_hp", -1)) == 13,
|
check(int((rb.breakpoint_snapshot() as Dictionary).get("hero_hp", -1)) == 13,
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ func _ready() -> void:
|
|||||||
if main.board_zone.toast == null:
|
if main.board_zone.toast == null:
|
||||||
problems.append("D 区 toast 槽缺失")
|
problems.append("D 区 toast 槽缺失")
|
||||||
if main.info_panel.item_slots == null or main.info_panel.item_slots.get_child_count() != 4:
|
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:
|
if main.stage.hero_standee.slot_row == null:
|
||||||
problems.append("B 区站桩状态行缺失(状态效果唯一展示面——2026-09-26 C 区精简批)")
|
problems.append("B 区站桩状态行缺失(状态效果唯一展示面——2026-09-26 C 区精简批)")
|
||||||
# B 区明细带挖掘期收起断言(T17 视觉扩展批适配):结算演播期 settling 视觉延伸=mode=settle
|
# B 区明细带挖掘期收起断言(T17 视觉扩展批适配):结算演播期 settling 视觉延伸=mode=settle
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ godot --headless --path . res://smoke/<probe>.tscn
|
|||||||
timeout 120s godot --headless --script tests/run_all.gd
|
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):
|
**协议要点**(D2 冒烟协议 + ADR-0004):
|
||||||
- 冒烟脚本 `extends SceneTree` 以获得 `quit(code)`;成功 `quit(0)`、失败 `quit(1)`
|
- 冒烟脚本 `extends SceneTree` 以获得 `quit(code)`;成功 `quit(0)`、失败 `quit(1)`
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ func _suites() -> Array:
|
|||||||
{"path": "res://tests/unit/example_test.gd", "expect": 0},
|
{"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_test.gd", "expect": 0},
|
||||||
{"path": "res://tests/unit/data_config/config_db_fatal_oob_test.gd", "expect": 1},
|
{"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/treasure_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/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/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/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/pacing_queue_test.gd", "expect": 0}, # 迭代 8 卡⑦ AC⑤/T9——排空零分叉/零丢行/延迟双态
|
||||||
{"path": "res://tests/unit/presentation/reward_overlay_test.gd", "expect": 0}, # 迭代 7 hotfix——奖励节点 UI 直验(盲区补漏)
|
{"path": "res://tests/unit/presentation/reward_overlay_test.gd", "expect": 0}, # 迭代 7 hotfix——奖励节点 UI 直验(盲区补漏)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
## Battle & Level
|
## Battle & Level
|
||||||
|
|
||||||
10. 战斗段:主角先手攻击行(hero_attack 来源)、敌方行为环读怪(姿态↔下一拍)、死亡即不动手
|
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 携带
|
12. 关卡推进:节点链兑付(奖励点/恢复点)、Boss 房(Dmax 行)、层间 HP 携带
|
||||||
|
|
||||||
## Data & Perf
|
## Data & Perf
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://csqehh43v2dn2
|
||||||
@@ -26,7 +26,7 @@ func _init() -> void:
|
|||||||
var sm_a = SaveManagerScript.new(_bp_path)
|
var sm_a = SaveManagerScript.new(_bp_path)
|
||||||
var adr_a = AdventureRunnerScript.new(db, rng_a)
|
var adr_a = AdventureRunnerScript.new(db, rng_a)
|
||||||
adr_a.set_save_manager(sm_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(adr_a.start_adventure(1234, params), "冒险启动(入口停点)")
|
||||||
Kit.check_quiet(sm_a.has_breakpoint(), "入口停点断点在档")
|
Kit.check_quiet(sm_a.has_breakpoint(), "入口停点断点在档")
|
||||||
Kit.check_quiet(int((sm_a.breakpoint_snapshot() as Dictionary).get("level_index", -1)) == 1, "断点关卡序号 = 1")
|
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 sm_e = SaveManagerScript.new(_bp_path)
|
||||||
var adr_e = AdventureRunnerScript.new(db, rng_e)
|
var adr_e = AdventureRunnerScript.new(db, rng_e)
|
||||||
adr_e.set_save_manager(sm_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)")
|
Kit.check_quiet(adr_e.start_adventure(4321, params_e), "P5 冒险启动(seed 4321)")
|
||||||
adr_e._bonus_taken["attack"] = 1 # 白盒预置计数(断点附随件往返的判据面——计数不可由加算区反推)
|
adr_e._bonus_taken["attack"] = 1 # 白盒预置计数(断点附随件往返的判据面——计数不可由加算区反推)
|
||||||
adr_e._on_level_finished({"result": "victory", "hp": 30, "node_index": 1, "node_id": 1, "node_type": "shop"})
|
adr_e._on_level_finished({"result": "victory", "hp": 30, "node_index": 1, "node_id": 1, "node_type": "shop"})
|
||||||
|
|||||||
+7
-7
@@ -1,11 +1,11 @@
|
|||||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||||
# 魔法道具 AuxItems 类单测(迭代 7 T7——结构冻结断言面;设计权威 魔法道具.md + registry aux_items)。
|
# 秘宝 TreasureItems 类单测(迭代 7 T7——结构冻结断言面;设计权威 秘宝.md + registry treasure_items)。
|
||||||
# 覆盖:授予归因 / Used 不可逆 / 真视恒可用 / 预读点击级零信息拒绝 / 3×3 边缘窗口∩板 /
|
# 覆盖:授予归因 / Used 不可逆 / 真视恒可用 / 预读点击级零信息拒绝 / 3×3 边缘窗口∩板 /
|
||||||
# 叠加层三清(retire_overlays 不动库存)/ 关卡末 reset / 零随机(同操作序列重放两遍投影逐位)。
|
# 叠加层三清(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
|
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/汇总退出样板单点(静默收集通道)
|
const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:check/汇总退出样板单点(静默收集通道)
|
||||||
|
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ class StubTable:
|
|||||||
|
|
||||||
|
|
||||||
class StubDB:
|
class StubDB:
|
||||||
var aux_items: StubTable
|
var treasure_items: StubTable
|
||||||
|
|
||||||
|
|
||||||
func _stub_db() -> StubDB:
|
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"},
|
"effect_kinds": ["reward_preview"], "target": "area_3x3", "magnitude": 0, "use_phase": "active_dig"},
|
||||||
}
|
}
|
||||||
var db := StubDB.new()
|
var db := StubDB.new()
|
||||||
db.aux_items = t
|
db.treasure_items = t
|
||||||
return db
|
return db
|
||||||
|
|
||||||
|
|
||||||
func _new_inv() -> Object:
|
func _new_inv() -> Object:
|
||||||
return AuxItemsScript.new(_stub_db())
|
return TreasureItemsScript.new(_stub_db())
|
||||||
|
|
||||||
|
|
||||||
func _unrevealed(_c: Vector2i) -> bool:
|
func _unrevealed(_c: Vector2i) -> bool:
|
||||||
@@ -103,4 +103,4 @@ func _init() -> void:
|
|||||||
Kit.check_quiet(str(replay_a) == str(replay_b), "零随机重放:库存+叠加层+探针投影逐位相同")
|
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 不可逆/真视恒可用/零信息拒绝/边缘窗口/三清/零随机重放 全过"))
|
||||||
File renamed without changes.
+9
-9
@@ -1,8 +1,8 @@
|
|||||||
# 致命类用例(独立进程,期望退出码 1)
|
# 致命类用例(独立进程,期望退出码 1)
|
||||||
# reward_dangling_aux——RewardTable aux 投放行双表校验(迭代 7 T1):aux 行 effect_id 引用 retired
|
# reward_dangling_treasure——RewardTable aux 投放行双表校验(迭代 7 T1):aux 行 effect_id 引用 retired
|
||||||
# 道具(loot_compass——2026-09-29 拍板①乙退役)时,config_db 跨表校验必须报 reward_dangling_aux、
|
# 道具(loot_compass——2026-09-29 拍板①乙退役)时,config_db 跨表校验必须报 reward_dangling_treasure、
|
||||||
# load_tables 整体拒绝(退役件/失义件不得出现在掉落投放面)。
|
# 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 = 违规表被放行(回归信号)。
|
# 退出码协议:1 = 校验正确拒绝(预期);2 = 违规表被放行(回归信号)。
|
||||||
extends SceneTree
|
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 Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:BAD 表目录夹具共享(copy_tables)
|
||||||
|
|
||||||
const SRC_DIR := "res://data/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:
|
func _inject_violation() -> bool:
|
||||||
@@ -22,7 +22,7 @@ func _inject_violation() -> bool:
|
|||||||
f.close()
|
f.close()
|
||||||
# 追加式注入(2026-10-01 战斗掉落渠道退役随批——现行表已无 aux 行可作锚):向 rows 尾追加
|
# 追加式注入(2026-10-01 战斗掉落渠道退役随批——现行表已无 aux 行可作锚):向 rows 尾追加
|
||||||
# 一块引用已退役 loot_compass 的 aux 投放行,双表校验须拦(retired 不入投放面)。
|
# 一块引用已退役 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}]")
|
var idx := s.rfind("\n}]")
|
||||||
if idx < 0:
|
if idx < 0:
|
||||||
return false
|
return false
|
||||||
@@ -37,18 +37,18 @@ func _inject_violation() -> bool:
|
|||||||
|
|
||||||
func _init() -> void:
|
func _init() -> void:
|
||||||
if not Kit.copy_tables(SRC_DIR, BAD_DIR) or not _inject_violation():
|
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)
|
quit(2)
|
||||||
return
|
return
|
||||||
var db = ConfigDBScript.new()
|
var db = ConfigDBScript.new()
|
||||||
var ok: bool = db.load_tables(BAD_DIR, false)
|
var ok: bool = db.load_tables(BAD_DIR, false)
|
||||||
if ok:
|
if ok:
|
||||||
push_error("[reward_dangling_aux_test] 违规表被放行——aux 双表校验失守(回归)")
|
push_error("[reward_dangling_treasure_test] 违规表被放行——aux 双表校验失守(回归)")
|
||||||
quit(2)
|
quit(2)
|
||||||
return
|
return
|
||||||
if db.diagnostics_count("error") >= 1:
|
if db.diagnostics_count("error") >= 1:
|
||||||
print("[reward_dangling_aux_test] 双表校验触发(reward_dangling_aux 诊断在案,加载被拒)")
|
print("[reward_dangling_treasure_test] 双表校验触发(reward_dangling_treasure 诊断在案,加载被拒)")
|
||||||
quit(1)
|
quit(1)
|
||||||
return
|
return
|
||||||
push_error("[reward_dangling_aux_test] 加载被拒但无 reward_dangling_aux 诊断——校验通道静默化(回归)")
|
push_error("[reward_dangling_treasure_test] 加载被拒但无 reward_dangling_treasure 诊断——校验通道静默化(回归)")
|
||||||
quit(2)
|
quit(2)
|
||||||
File renamed without changes.
+9
-9
@@ -1,7 +1,7 @@
|
|||||||
# 致命类用例(独立进程,期望退出码 1)
|
# 致命类用例(独立进程,期望退出码 1)
|
||||||
# aux_target_violation——真视窄域护栏(魔法道具 GDD 结构冻结,迭代 7 T1):mine_reveal 行 target
|
# treasure_target_violation——真视窄域护栏(秘宝 GDD 结构冻结,迭代 7 T1):mine_reveal 行 target
|
||||||
# 越域至 board_wide 时,AuxItemTable.validate 必须报 load_bearing 错、load_tables 整体拒绝。
|
# 越域至 board_wide 时,TreasureItemTable.validate 必须报 load_bearing 错、load_tables 整体拒绝。
|
||||||
# 运行:godot --headless --path game --script res://tests/unit/data_config/aux_target_violation_test.gd
|
# 运行:godot --headless --path game --script res://tests/unit/data_config/treasure_target_violation_test.gd
|
||||||
# 退出码协议:1 = 校验正确拒绝(预期);2 = 违规表被放行(回归信号)。
|
# 退出码协议:1 = 校验正确拒绝(预期);2 = 违规表被放行(回归信号)。
|
||||||
# 时序注:纯加载期校验——不触运行期 fatal 通道,断言 load_tables 返回 false + 诊断在案即 quit(1)。
|
# 时序注:纯加载期校验——不触运行期 fatal 通道,断言 load_tables 返回 false + 诊断在案即 quit(1)。
|
||||||
extends SceneTree
|
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 Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:BAD 表目录夹具共享(copy_tables)
|
||||||
|
|
||||||
const SRC_DIR := "res://data/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:
|
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)
|
var f := FileAccess.open(path, FileAccess.READ)
|
||||||
if f == null:
|
if f == null:
|
||||||
return false
|
return false
|
||||||
@@ -44,18 +44,18 @@ func _inject_violation() -> bool:
|
|||||||
|
|
||||||
func _init() -> void:
|
func _init() -> void:
|
||||||
if not Kit.copy_tables(SRC_DIR, BAD_DIR) or not _inject_violation():
|
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)
|
quit(2)
|
||||||
return
|
return
|
||||||
var db = ConfigDBScript.new()
|
var db = ConfigDBScript.new()
|
||||||
var ok: bool = db.load_tables(BAD_DIR, false)
|
var ok: bool = db.load_tables(BAD_DIR, false)
|
||||||
if ok:
|
if ok:
|
||||||
push_error("[aux_target_violation_test] 违规表被放行——真视窄域护栏失守(回归)")
|
push_error("[treasure_target_violation_test] 违规表被放行——真视窄域护栏失守(回归)")
|
||||||
quit(2)
|
quit(2)
|
||||||
return
|
return
|
||||||
if db.diagnostics_count("error") >= 1:
|
if db.diagnostics_count("error") >= 1:
|
||||||
print("[aux_target_violation_test] 护栏触发(load_bearing 诊断在案,加载被拒)")
|
print("[treasure_target_violation_test] 护栏触发(load_bearing 诊断在案,加载被拒)")
|
||||||
quit(1)
|
quit(1)
|
||||||
return
|
return
|
||||||
push_error("[aux_target_violation_test] 加载被拒但无 load_bearing 诊断——护栏通道静默化(回归)")
|
push_error("[treasure_target_violation_test] 加载被拒但无 load_bearing 诊断——护栏通道静默化(回归)")
|
||||||
quit(2)
|
quit(2)
|
||||||
File renamed without changes.
@@ -1,6 +1,6 @@
|
|||||||
# tests/unit/test_kit.gd — 单元测试协议样板单点(T6 样板收口批 2026-10-02)
|
# tests/unit/test_kit.gd — 单元测试协议样板单点(T6 样板收口批 2026-10-02)
|
||||||
# 收口范围:11 份套件的 _check/_problems 样板(计数器 + PASS/FAIL 行 + 汇总退出)+
|
# 收口范围:11 份套件的 _check/_problems 样板(计数器 + PASS/FAIL 行 + 汇总退出)+
|
||||||
# reward_dangling_aux/aux_target_violation 两致命类用例各自复制的 BAD 表目录夹具。
|
# reward_dangling_treasure/treasure_target_violation 两致命类用例各自复制的 BAD 表目录夹具。
|
||||||
# 用法(--script 模式无 autoload/全局标识符——禁 class_name 裸引用,使用方 preload):
|
# 用法(--script 模式无 autoload/全局标识符——禁 class_name 裸引用,使用方 preload):
|
||||||
# const Kit := preload("res://tests/unit/test_kit.gd")
|
# const Kit := preload("res://tests/unit/test_kit.gd")
|
||||||
# Kit.check("断言描述", cond) # 计数 + 即时 PASS/FAIL 行
|
# Kit.check("断言描述", cond) # 计数 + 即时 PASS/FAIL 行
|
||||||
@@ -27,7 +27,7 @@ static func check(desc: String, ok: bool) -> void:
|
|||||||
|
|
||||||
|
|
||||||
# 静默收集通道:失败只记入 problems(即时零刷屏),finish 统一汇总。
|
# 静默收集通道:失败只记入 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:
|
static func check_quiet(ok: bool, desc: String) -> void:
|
||||||
checks += 1
|
checks += 1
|
||||||
if not ok:
|
if not ok:
|
||||||
@@ -49,7 +49,7 @@ static func finish(suite: String, pass_line: String = "") -> int:
|
|||||||
return 0
|
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 常量仍由各用例自持(名字互异——独立进程并行不互踩)。
|
# 整目录拷贝 src_dir → bad_dir(目录已建)。BAD_DIR 常量仍由各用例自持(名字互异——独立进程并行不互踩)。
|
||||||
static func copy_tables(src_dir: String, bad_dir: String) -> bool:
|
static func copy_tables(src_dir: String, bad_dir: String) -> bool:
|
||||||
DirAccess.make_dir_recursive_absolute(bad_dir)
|
DirAccess.make_dir_recursive_absolute(bad_dir)
|
||||||
|
|||||||
+1
-1
@@ -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「沃土+雷密对冲」形勘误作废——雷数Line truncated
|
| 迭代 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「沃土+雷密对冲」形勘误作废——雷数Line truncated
|
||||||
| 迭代 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 用户令自「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 用户令编入本迭代)**:概念层已由用户逐轮裁定定稿(《奇物》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 用户立规)
|
## 执行纪律(2026-09-27 用户立规)
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user