merge: 续玩停点恢复717崩值修(runner缺位守卫+快照gp兜底;ui_struct_probe⑦resume回归专项先红后绿;冒烟782/0+run_all 16套+probe_gate --click全绿)

This commit is contained in:
DKChan committed 2026-10-06 05:10:07 +08:00
commit a2b7c215ae
2 files changed
+48

No files matched your search

+7
View File
@@ -713,7 +713,14 @@ func _on_battle_finished(payload: Dictionary) -> void:
# 战利品行装配(battle.md OQ14——胜利总结结算展示 GP 总量+增量;账本语义零改动,纯呈现读数):
# 增量 = battle_finished 载荷 gp_dropped(战斗域上抛);总量 = runner.gp 现值(LevelRunner 入账
# 连接先于组合根 handler——此读数即战后入账完毕的总量)。
# runner 缺位守卫(2026-10-06 用户实机 main.gd:717 崩值定位——续玩停点恢复分支:adventure_runner
# resume_adventure 的 bonus_pending 分支在 level_started 之前同步 curio_choice_presented.emit
# 〔resume 提前 return〕,本 lambda 求值时 runner 尚未赋值;合计改读断点快照 gp 兜底——恢复源快照
# 此刻必在档,语义=续玩恢复面的合计即存档合计;与 _bonus_summary_text 同款守卫式)
func _gp_summary_text(payload: Dictionary) -> String:
if runner == null:
var bp: Dictionary = save_manager.breakpoint_snapshot() if save_manager != null else {}
return "战利品 GP +%d · 合计 %d" % [int(payload.get("gp_dropped", 0)), int(bp.get("gp", 0))]
return "战利品 GP +%d · 合计 %d" % [int(payload.get("gp_dropped", 0)), int(runner.gp)]
+41
View File
@@ -99,6 +99,28 @@ func _ready() -> void:
_settle()
await _audit("shop", [main.shop_overlay])
# ---- ⑦resume 专项:续玩停点恢复(2026-10-06 用户实机 main.gd:717 报错回归闸)----
# 三选一停点续玩分支在 level_started 之前同步 curio_choice_presented.emit(adventure_runner
# resume 提前 return)——GP 总结 lambda 求值时 runner 尚未赋值,修复前 717 炸 null。
ProbeUiUtil.isolate_save(main, "smoke_ui_struct_probe_resume", true)
main.save_manager.set_breakpoint(_resume_bp_fixture())
main._refresh_resume_button()
main.runner = null # 全新启动等价态(真机=菜单直进续玩,无前置冒险——runner 从未赋值;探针此前推流会残留旧 runner)
main._resume_from_menu()
_settle(8)
if not main._end_overlay.visible:
problems.append("[resume] 续玩恢复后胜利总结面未开(三选一停点分支中断)")
else:
var found := {"ok": false}
_find_label_text(main._end_overlay, "合计 24", found)
if not found.ok:
problems.append("[resume] 胜利总结面 GP 行未见快照合计「合计 24」(runner 缺位守卫缺位——717 回归)")
var s: String = main._gp_summary_text({"gp_dropped": 0})
if not s.contains("合计 24"):
problems.append("[resume] _gp_summary_text runner=null 守卫未取快照 gp(%s)" % s)
# 恢复现场(resume 改写了 main 的 adventure/save 态——后续无屏依赖,仅为整洁)
main._level_active = false
# ---- 判定 ----
if problems.is_empty():
print("[ui_struct_probe] PASS — 全屏结构断言零红")
@@ -109,6 +131,25 @@ func _ready() -> void:
get_tree().quit(1)
# ⑦resume 夹具:最小合法断点快照——bonus_pending 非空=三选一停点分支(合计 gp=24 供守卫兜底断言)
func _resume_bp_fixture() -> Dictionary:
return {
"master_seed": 42, "rng_counter": 0, "hero_hp": 20, "gp": 24, "keystone": 0,
"level_index": 1, "bonus": {}, "shop_purchased": {}, "relics": [],
"bonus_aux_carry": [], "keystone_drops": [], "bonus_taken": {},
"bonus_pending": {"candidates": [{"kind": "heal", "tier": "common"}], "payload": {"gp_dropped": 0}},
}
# 递归找含目标子串的 Label(⑦resume 断言读数面)
func _find_label_text(node: Node, needle: String, found: Dictionary) -> void:
for ch in node.get_children():
if ch is Label and String(ch.text).contains(needle):
found.ok = true
return
_find_label_text(ch, needle, found)
func _pick_battle_node(main: Node) -> int:
# 入口/兑付停点走 level_screen.open_choices 直传(不写 _pending_candidates)——
# 候选从视图态取:_cand_ids × runner.nodes() 的 type(编号解析=node_id_of 单一出口)