diff --git a/game/smoke/ui_click_probe.gd b/game/smoke/ui_click_probe.gd index a0c17e6b..7b6c8343 100644 --- a/game/smoke/ui_click_probe.gd +++ b/game/smoke/ui_click_probe.gd @@ -163,6 +163,9 @@ func _ready() -> void: _problems.append("[savesel] sl12 动线序违约:开始层在落点帧恢复(回闪一帧)") if main.save_manager.active_slot() != 1 or not FileAccess.file_exists(csel_tpl % 1): _problems.append("[savesel] sl5 新档链失守(active=%d 应=1 且槽1 白板应落盘)" % main.save_manager.active_slot()) + var occluded: Array = main._modals._occluded.get(main.camp_overlay, []) + if not occluded.has(main.save_select_overlay): + _problems.append("[savesel] sl12 选档层被关闭而非栈记账挂起(先关后开形态——遮挡挂起中间态钉死)") if int((JSON.parse_string(FileAccess.get_file_as_string(csel_tpl % 1)) as Dictionary).get("meta", {}).get("keystone_balance", -1)) != 0: _problems.append("[savesel] sl5 新档非白板(槽1 落盘应全零)") main._on_camp_closed() diff --git a/game/smoke/ui_struct_probe.gd b/game/smoke/ui_struct_probe.gd index 67e6f580..a1b829e2 100644 --- a/game/smoke/ui_struct_probe.gd +++ b/game/smoke/ui_struct_probe.gd @@ -376,20 +376,27 @@ func _save_select_contract(main: Node, tpl: String) -> void: var scroll_count := _count_scroll(sso) if scroll_count > 0: problems.append("[savesel] 子树出现滚动容器 ×%d(sl1 禁滚动长列表)" % scroll_count) - # sl4 操作集二分:槽1 有档=进档+删档零新档;槽2 空=新档零进档删档;槽3 坏档=按空槽呈现(Q2 甲) + # sl4 操作集二分(渲染面实测——扫真实按钮文本,不走簿记缝):槽1 有档=进档+删档零新档; + # 槽2 空=新档零进档删档;槽3 坏档=按空槽呈现(Q2 甲) var occ: Dictionary = sso._occupied_flags if not (bool(occ.get(1, false)) and not bool(occ.get(2, false)) and not bool(occ.get(3, false))): problems.append("[savesel] 槽态判定失守(occ=%s 应=1有/2空/3坏按空)〔sl4〕" % str(occ)) - for slot in [1, 2, 3]: - var has_load: bool = sso._load_btns.has(slot) - var has_del: bool = sso._delete_btns.has(slot) - var has_new: bool = sso._new_btns.has(slot) - if slot == 1: + var row_idx := 0 + for row_c in rows.get_children(): + if not (row_c is Control) or row_c.is_queued_for_deletion(): + continue + row_idx += 1 + var btn_texts: Array[String] = [] + _collect_button_texts(row_c, btn_texts) + var has_load := btn_texts.has("进档") + var has_del := btn_texts.has("删档") + var has_new := btn_texts.has("新档") + if row_idx == 1: if not (has_load and has_del and not has_new): - problems.append("[savesel] 槽1 操作集失守(有档槽应=进档+删档、零新档)〔sl4〕") + problems.append("[savesel] 行1 操作集失守(有档槽应=进档+删档、零新档——渲染面实测)〔sl4〕") else: if not (has_new and not has_load and not has_del): - problems.append("[savesel] 槽%d 操作集失守(空/坏槽应=仅新档、零进档删档含置灰形态)〔sl4〕" % slot) + problems.append("[savesel] 行%d 操作集失守(空/坏槽应=仅新档、零进档删档含置灰形态)〔sl4〕" % row_idx) # sl2 摘要三项逐槽读数:槽1 喂入值逐字(钥石 555/通关 2 局/冒险 7 局) var sum1: Label = sso._summary_labels.get(1) if sum1 == null or sum1.text != "通关 2 局 · 冒险 7 局": @@ -402,8 +409,9 @@ func _save_select_contract(main: Node, tpl: String) -> void: has_keystone = true if not has_keystone: problems.append("[savesel] 槽1 钥石徽读数缺失(应=钥石 555)〔sl2〕") - # sl3 摘要禁项:断点/种子/「继续」字样零命中(裁决 4——零未完冒险读数) - for needle in ["断点", "种子", "继续"]: + # sl3 摘要禁项:断点/种子/「继续」/停点/「 关」(关数形——「通关」无空格不误伤)零命中 + #(裁决 4——零未完冒险读数;词形覆盖=对照表 sl3 变异「断点关数拼进槽卡」的拦截面) + for needle in ["断点", "种子", "继续", "停点", " 关"]: for t in all_texts: if t.contains(needle): problems.append("[savesel] 摘要禁项命中「%s」(label=「%s」)〔sl3〕" % [needle, t]) @@ -420,6 +428,13 @@ func _count_scroll(node: Node) -> int: return count +func _collect_button_texts(node: Node, out: Array[String]) -> void: + if node is Button and node.visible: + out.append(String(node.text)) + for c in node.get_children(): + _collect_button_texts(c, out) + + func _collect_labels(node: Node, out: Array[String]) -> void: if node is Label: out.append(String(node.text))