diff --git a/game/presentation/views/camp_scene_view.gd b/game/presentation/views/camp_scene_view.gd index 2019288c..eb0f563b 100644 --- a/game/presentation/views/camp_scene_view.gd +++ b/game/presentation/views/camp_scene_view.gd @@ -48,6 +48,10 @@ var _desat_mat: ShaderMaterial # 禁用态共享材质(strength var _hud_slot: Control # 顶栏预留位(卡⑤ set_hud_band 填值) +func _init() -> void: + visible = false # 登记模态初始隐(开合走栈——模态纪律;boot 态场景根不得盖菜单) + + func setup_layers(layout: CampSceneLayoutTable) -> void: if layout == null: push_error("[CampSceneView] 布局表缺位——组合根须注入 db.presentation.camp_scene_layout") diff --git a/game/probe/screen_flow_probe.gd b/game/probe/screen_flow_probe.gd index d90071e5..1f939d5e 100644 --- a/game/probe/screen_flow_probe.gd +++ b/game/probe/screen_flow_probe.gd @@ -51,7 +51,7 @@ func _ready() -> void: func _screen_seals() -> Dictionary: return { "菜单": main.ui.screens.start_overlay != null and main.ui.screens.start_overlay.visible, - "营地": main.ui.modals.camp.overlay != null and main.ui.modals.camp.overlay.visible, + "营地": main.ui.modals.camp.scene != null and main.ui.modals.camp.scene.visible, "冒险": main.run_scope != null and main.run_scope.is_adventure, "终局": main.ui.modals.end_overlay != null and main.ui.modals.end_overlay.visible, } @@ -115,14 +115,14 @@ func _step_menu_to_camp() -> void: _expect_exclusive("②菜单→营地", "营地") -# ---- ③ 营地 → 菜单(回退路径:营地关闭发自覆盖层自身信号)---- +# ---- ③ 营地 → 菜单(回退路径:篝火二次确认动线——卡④ 营地唯一回菜单出口;选档层随关层收闭同收)---- func _step_camp_back_to_menu() -> void: - if main.ui.modals.camp.overlay == null: - _problems.append("③营地→菜单:营地覆盖层句柄缺失〔句柄子容器批 V1〕") + if main.ui.modals.camp.scene == null: + _problems.append("③营地→菜单:营地场景根句柄缺失〔句柄子容器批 V1〕") return - main.ui.modals.camp.overlay.closed.emit() + main.ui.modals.camp.scene.object_pressed.emit(&"campfire") await _frames() - main._on_save_select_closed() # 关闭被栈还原的选档层(动线序中间态——卡④ 换代点) + main.ui.modals.confirm_dialog.confirmed.emit() # 二次确认离场(回主菜单——卡④ T4) await _frames() _expect_exclusive("③营地→菜单(回退)", "菜单") diff --git a/game/probe/shot_probe.gd b/game/probe/shot_probe.gd index 0fe9021d..90184d93 100644 --- a/game/probe/shot_probe.gd +++ b/game/probe/shot_probe.gd @@ -53,7 +53,7 @@ func _ready() -> void: var top_ry := -1 for c: Node in [main.ui.screens.start_overlay, main.ui.screens.battle_root, main.ui.screens.inter_overlay, main.ui.modals.legend_overlay, main.ui.modals.node_overlay, main.ui.modals.level_screen, main.ui.modals.curio_overlay, - main.ui.modals.end_overlay, main.ui.modals.shop_overlay, main.ui.modals.camp.overlay, main.ui.modals.settings_overlay, + main.ui.modals.end_overlay, main.ui.modals.shop_overlay, main.ui.modals.camp.scene, main.ui.modals.settings_overlay, main.ui.modals.status_panel, main.ui.modals.career_overlay, main.ui.modals.confirm_dialog, main.ui.modals.debug_overlay]: if c == null or not (c is CanvasItem) or not (c as CanvasItem).visible: continue @@ -119,17 +119,15 @@ func _ready() -> void: await get_tree().process_frame if main.ui.modals.career_overlay.visible or not main.ui.screens.start_overlay.visible: _problems.append("生涯页关闭后页未隐藏或开始层未恢复") - # ② 营地(进档开层新路径——卡② mn9;槽模板注入隔离命名空间) + # ② 营地场景图(进档开层新路径——卡② mn9;截图=可点击场景图形态——卡④ 契约 9 V1 验收载体) if not ProbeUiUtil.open_camp_via_savesel(main, "smoke_shot_probe_camp"): _problems.append("营地入口缺失(选档层新档钮——新路径驱动中断)〔句柄子容器批 V1〕") else: await get_tree().process_frame await _snap("camp") - var close_btn: Button = ProbeUiUtil.find_button(main.ui.modals.camp.overlay, "关闭营地", "contains") - if close_btn != null: - close_btn.pressed.emit() - await get_tree().process_frame - main._on_save_select_closed() # 关闭被栈还原的选档层(动线序中间态) + main.ui.modals.camp.scene.object_pressed.emit(&"campfire") # 收闭改接篝火动线(营地根态无关闭钮——卡④ T5) + await get_tree().process_frame + main.ui.modals.confirm_dialog.confirmed.emit() # 二次确认离场(关层收闭——选档层随收) await get_tree().process_frame # ③ 关卡画面(开始冒险→停点出图——入口停点语义;函数直调中间态 mn10) main._start_adventure_from_menu() diff --git a/game/probe/ui_click_probe.gd b/game/probe/ui_click_probe.gd index 6cef204f..309e8526 100644 --- a/game/probe/ui_click_probe.gd +++ b/game/probe/ui_click_probe.gd @@ -65,17 +65,19 @@ func _ready() -> void: _problems.append("营地入口缺失(选档层新档钮——mn9 新路径驱动中断)〔句柄子容器批 V1〕") else: await get_tree().process_frame - if not main.ui.modals.camp.overlay.visible: - _problems.append("营地层未打开(进档开层新路径)〔句柄子容器批 V1〕") - elif main.ui.modals.camp.overlay._tree_buy_btns.is_empty(): - _problems.append("树淬炼柜台购买钮缺失(点击路径——四柜台重排后树=主界面)〔句柄子容器批 V1〕") + if not main.ui.modals.camp.scene.visible: + _problems.append("营地场景根未打开(进档开层新路径)〔句柄子容器批 V1〕") + main.ui.modals.camp.scene.object_pressed.emit(&"dummy") # 场景点选真实路由(木桩→天赋树子界面——卡④ T5) + await get_tree().process_frame + if main.ui.modals.camp.tree._tree_buy_btns.is_empty(): + _problems.append("树淬炼购买钮缺失(四柜台拆解后树=独立子界面)〔句柄子容器批 V1〕") else: # 树钮句柄用后即取(refresh_camp 随刷重建树行板——旧钮 queue_free,跨刷新句柄必失效) iso_c.meta_state._add_keystone(9999) - main.ui.modals.camp.overlay.refresh_camp(main._camp_data()) + main.ui.modals.camp.tree.refresh_camp(main._camp_data()) await get_tree().process_frame var buy_btn: Button = null - for card in main.ui.modals.camp.overlay._tree_buy_btns: + for card in main.ui.modals.camp.tree._tree_buy_btns: if String(card.node_id) == "sp_hp": buy_btn = card.btn if buy_btn == null: @@ -93,16 +95,16 @@ func _ready() -> void: _problems.append("营地树购买未持久(reload 后级 != 1)〔句柄子容器批 V1〕") # Fork 双态切换点击路径(V20——购=解锁默认 A,钮切 B;前置=同调位 1,先点亮) var socket_btn: Button = null - for card in main.ui.modals.camp.overlay._tree_buy_btns: + for card in main.ui.modals.camp.tree._tree_buy_btns: if String(card.node_id) == "att_socket1": socket_btn = card.btn if socket_btn != null: socket_btn.pressed.emit() await get_tree().process_frame - main.ui.modals.camp.overlay.refresh_camp(main._camp_data()) + main.ui.modals.camp.tree.refresh_camp(main._camp_data()) await get_tree().process_frame var fork_btn: Button = null - for card in main.ui.modals.camp.overlay._tree_buy_btns: + for card in main.ui.modals.camp.tree._tree_buy_btns: if String(card.node_id) == "fork_posture": fork_btn = card.btn if fork_btn == null: @@ -110,10 +112,10 @@ func _ready() -> void: else: fork_btn.pressed.emit() await get_tree().process_frame - main.ui.modals.camp.overlay.refresh_camp(main._camp_data()) + main.ui.modals.camp.tree.refresh_camp(main._camp_data()) await get_tree().process_frame var side_b: Button = null - for fk in main.ui.modals.camp.overlay._tree_fork_btns: + for fk in main.ui.modals.camp.tree._tree_fork_btns: if String(fk.group) == "fg_posture" and String(fk.side) == "b": side_b = fk.btn if side_b == null: @@ -125,29 +127,23 @@ func _ready() -> void: iso_fk.load_from_disk() if String(iso_fk.meta_state.tree_state().fork_sides.get("fg_posture", "")) != "b": _problems.append("Fork 切态未持久(reload 后激活态 != b)〔句柄子容器批 V1〕") - # ---- 营地六处灰字取色断言(迭代36 wc4——真实入口开营地后按文本锚取 label, - # font_color 逐处 == STONE_DEEP;六源位 :167 图鉴锁文/:417+:476 行状态字/:509 同调形态/:513 档位标签/:525 刷新行)---- - var camp_labels: Array = [] - _collect_labels_by_text(main.ui.modals.camp.overlay, camp_labels) - var atlas_locks := _labels_with_text(camp_labels, "柜台结构位预留") - if atlas_locks.is_empty(): - _problems.append("营地灰字:图鉴柜台锁文 label 未找到(wc4 定位锚失守)〔句柄子容器批 V1〕") - for l in atlas_locks: - if l.get_theme_color("font_color") != UiKit.STONE_DEEP: - _problems.append("营地灰字:图鉴锁文未用 STONE_DEEP(wc4 :167)〔句柄子容器批 V1〕") - # 「未解锁」锚收窄到秘宝匣行容器子树(树行/锻造行也有「未解锁」态字样——非 wc4 目标位) - var locked_status: Array = [] - if main.ui.modals.camp.overlay.get("_workshop_holder") != null: - var ws_labels: Array = [] - _collect_labels_by_text(main.ui.modals.camp.overlay._workshop_holder, ws_labels) - locked_status = _labels_with_text(ws_labels, "未解锁") + # ---- 营地灰字取色断言(迭代36 wc4——四子界面拆分后按视图分扫;卡④ T5 迁移): + # 图鉴锁文→codex 视图(锚随形态订正去『柜台』);秘宝行未解锁/同调形态/档位/刷新行→treasure 视图 + # _workshop_holder 子树。font_color 逐处 == STONE_DEEP;树链段已闭树界面。 + main.ui.modals.camp.tree.closed.emit() # 树界面返回(关层归 presenter 单口) + await get_tree().process_frame + main.ui.modals.camp.scene.object_pressed.emit(&"chest") # 宝箱→秘宝匣(灰字四源位宿主) + await get_tree().process_frame + var ws_labels: Array = [] + _collect_labels_by_text(main.ui.modals.camp.treasure._workshop_holder, ws_labels) + var locked_status: Array = _labels_with_text(ws_labels, "未解锁") if locked_status.is_empty(): _problems.append("营地灰字:秘宝匣行「未解锁」态 label 未找到(wc4 夹具前提失守——新档应有锁定秘宝行)〔句柄子容器批 V1〕") for l in locked_status: if l.get_theme_color("font_color") != UiKit.STONE_DEEP: _problems.append("营地灰字:秘宝行「未解锁」态未用 STONE_DEEP(wc4 :417/:476)〔句柄子容器批 V1〕") var form_found := false - for l in camp_labels: + for l in ws_labels: if l.text == "被动" or l.text == "主动·充能": form_found = true if l.get_theme_color("font_color") != UiKit.STONE_DEEP: @@ -158,7 +154,7 @@ func _ready() -> void: for v in UiKit.TREASURE_TIER_LABELS.values(): tier_vals[String(v)] = true var tier_found := false - for l in camp_labels: + for l in ws_labels: if tier_vals.has(l.text): tier_found = true if l.get_theme_color("font_color") != UiKit.STONE_DEEP: @@ -166,18 +162,30 @@ func _ready() -> void: if not tier_found: _problems.append("营地灰字:同调档位标签未找到(wc4 定位锚失守)〔句柄子容器批 V1〕") var refresh_inked := false - for l in camp_labels: + for l in ws_labels: if String(l.text).contains("三选一刷新"): refresh_inked = true if l.get_theme_color("font_color") != UiKit.STONE_DEEP: _problems.append("营地灰字:刷新行未用 STONE_DEEP(wc4 :525)〔句柄子容器批 V1〕") if not refresh_inked: _problems.append("营地灰字:刷新行 label 未找到(wc4 定位锚失守)〔句柄子容器批 V1〕") - main._on_camp_closed() + main.ui.modals.camp.treasure.closed.emit() + await get_tree().process_frame + main.ui.modals.camp.scene.object_pressed.emit(&"board") # 布告板→图鉴占位(锁文宿主) + await get_tree().process_frame + var codex_labels: Array = [] + _collect_labels_by_text(main.ui.modals.camp.codex, codex_labels) + var atlas_locks := _labels_with_text(codex_labels, "结构位预留") + if atlas_locks.is_empty(): + _problems.append("营地灰字:图鉴锁文 label 未找到(wc4 定位锚失守——锚随形态订正去『柜台』)〔句柄子容器批 V1〕") + for l in atlas_locks: + if l.get_theme_color("font_color") != UiKit.STONE_DEEP: + _problems.append("营地灰字:图鉴锁文未用 STONE_DEEP(wc4 :167)〔句柄子容器批 V1〕") + main.ui.modals.camp.codex.closed.emit() + await get_tree().process_frame + main._on_camp_closed() # 关层收闭(营地与选档层同收+开始层恢复——卡④ T3) await get_tree().process_frame - main._on_save_select_closed() # 关闭被栈还原的选档层(动线序中间态——卡④ 换代点) - await get_tree().process_frame - if main.ui.modals.camp.overlay.visible or not main.ui.screens.start_overlay.visible: + if main.ui.modals.camp.scene.visible or not main.ui.screens.start_overlay.visible: _problems.append("营地关闭后未恢复开始层〔句柄子容器批 V1〕") # ---- 选档界面行为走查(迭代 33 卡③):sl5 空槽新档链/sl6 有档槽进档链/sl7 删档二次确认双路径 # /sl8 消费方分派单口/sl12 动线序不回闪。开层=函数直调(「进入存档」钮归卡② mn3——中间态在案); @@ -208,7 +216,7 @@ func _ready() -> void: new_btn.pressed.emit() # 真实按钮信号路径 → _on_save_select_new → create_slot+open_camp for fi in 3: await get_tree().process_frame - samples.append([main.ui.modals.save_select_overlay.visible, main.ui.modals.camp.overlay.visible, main.ui.screens.start_overlay.visible]) + samples.append([main.ui.modals.save_select_overlay.visible, main.ui.modals.camp.scene.visible, main.ui.screens.start_overlay.visible]) if samples[0][0]: _problems.append("[savesel] sl12 新档后选档层仍可见(落点开层未发生)") elif not samples[0][1]: @@ -217,7 +225,7 @@ func _ready() -> void: _problems.append("[savesel] sl12 动线序违约:开始层在落点帧恢复(回闪一帧)") if main.save_manager.slots.active_slot() != 1 or not FileAccess.file_exists(csel_tpl % 1): _problems.append("[savesel] sl5 新档链失守(active=%d 应=1 且槽1 白板应落盘)" % main.save_manager.slots.active_slot()) - var occluded: Array = main.ui.modals.flow.stack._occluded.get(main.ui.modals.camp.overlay, []) + var occluded: Array = main.ui.modals.flow.stack._occluded.get(main.ui.modals.camp.scene, []) if not occluded.has(main.ui.modals.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: @@ -235,7 +243,7 @@ func _ready() -> void: await get_tree().process_frame if main.save_manager.slots.active_slot() != 2: _problems.append("[savesel] sl6 进档链失守(active=%d 应=2——激活该槽)" % main.save_manager.slots.active_slot()) - if not main.ui.modals.camp.overlay.visible or main.ui.modals.save_select_overlay.visible: + if not main.ui.modals.camp.scene.visible or main.ui.modals.save_select_overlay.visible: _problems.append("[savesel] sl6 落点未开营地层或选档未隐藏") main._on_camp_closed() await get_tree().process_frame @@ -668,6 +676,51 @@ func _ready() -> void: # 卡④大门 T5 接收,两头登记禁静默删除;续玩钮已退役,主菜单确认链已摘 mn6)。 # ① 战斗收口断点写盘断言保留(上方——冒险流直调中间态 mn10)。 + # ---- 大门两分支断言段(卡④ T5 接收——卡② 移交落点;V3 断言面)---- + # 驱动=营地场景根点选信号(真实路由)→组合根 _on_camp_object_pressed→确认弹窗。 + # 无断点=两出口(是/否);有断点=三出口(set_breakpoint 注入选路停点形——同下方开场行③先例)。 + # 判据绑可观测提交面:点大门不直接进冒险(is_adventure 翻转只在 confirmed 后);cancelled 恒= + # 无变更退回营地(写口零调用——余额读数不变+营地根 visible);开局后营地场景屏隐藏。 + ProbeUiUtil.isolate_save(main, "smoke_click_probe_gate", true, false, true) + main._camp_pres.open_camp() + await get_tree().process_frame + var bal_gate: int = main._camp_data()["balance"] + main.ui.modals.camp.scene.object_pressed.emit(&"gate") + await get_tree().process_frame + if not main.ui.modals.confirm_dialog.is_open(): + _problems.append("大门无断点:确认弹窗未开(点大门应先出确认不直接进冒险)〔营地图批 V3〕") + if main.run_scope.is_adventure: + _problems.append("大门无断点:未确认即进冒险〔营地图批 V3〕") + if main.ui.modals.confirm_dialog._secondary_btn.visible: + _problems.append("大门无断点:次钮应隐藏(两出口形态)〔营地图批 V3〕") + main.ui.modals.confirm_dialog.cancelled.emit() + await get_tree().process_frame + if not main.ui.modals.camp.scene.visible or main.run_scope.is_adventure or main._camp_data()["balance"] != bal_gate: + _problems.append("大门取消:未无变更退回营地(写口零调用/营地根 visible 失守)〔营地图批 V3〕") + main.ui.modals.camp.scene.object_pressed.emit(&"gate") + await get_tree().process_frame + main.ui.modals.confirm_dialog.confirmed.emit() # 「是」→开始新冒险 + await get_tree().process_frame + if not main.run_scope.is_adventure or main.ui.modals.camp.scene.visible: + _problems.append("大门确认:冒险未发起或营地场景屏未隐藏〔营地图批 V3〕") + # 有断点三出口(选路停点形注入——同开场行③ set_breakpoint 先例) + main.save_manager.set_breakpoint({ + "master_seed": 42, "rng_counter": 0, "hero_hp": 30, "gp": 10, "keystone": 0, + "level_index": 1, "bonus": {"atk": 0, "max_hp": 0, "armor_class": 0, "ap": 0}, + "shop_purchased": {}, "relics": [], "keystone_drops": [], "bonus_taken": {}, + "node_id": -1, "visited_ids": [], "graph_gen_v2": 1, + }) + main._camp_pres.open_camp() + await get_tree().process_frame + main.ui.modals.camp.scene.object_pressed.emit(&"gate") + await get_tree().process_frame + if not main.ui.modals.confirm_dialog.is_open() or not main.ui.modals.confirm_dialog._secondary_btn.visible: + _problems.append("大门有断点:三出口形态失守(次钮应现形)〔营地图批 V3〕") + main.ui.modals.confirm_dialog.secondary_confirmed.emit() # 「开始新冒险」出口 + await get_tree().process_frame + if not main.run_scope.is_adventure or main.ui.modals.camp.scene.visible: + _problems.append("大门有断点次确认:冒险未发起或营地未隐藏〔营地图批 V3〕") + # ---- 开场行三路径段(迭代36 wc1/wc2——真实入口驱动;隔离新档)---- # 驱动设计(0/0 白板局生存性不成立的实证处置——L2 记录进实现报告): # ① 菜单开新局·白板反向=独立短局:0/0 滑条开局断言 L1 开场行零后缀(不开驱动—— diff --git a/game/probe/ui_contrast_probe.gd b/game/probe/ui_contrast_probe.gd index 652fb04e..eaae9ffb 100644 --- a/game/probe/ui_contrast_probe.gd +++ b/game/probe/ui_contrast_probe.gd @@ -45,15 +45,11 @@ func _pairs() -> Array: ["商店·爬价规则墨/暖亮页底", UiKit.WARM_SOFT, UiKit.BG_BRIGHT, 1.0],# 货架面爬价规则行(page_shell 亮底) ["商店·货架卡名墨/货架板", UiKit.INK_TITLE, UiKit.PANEL_DATA, 1.0], # bcard 货架卡商品名(换 TG 带后未机检位) ["商店·货架价签墨/货架板", UiKit.GOLD_INK, UiKit.PANEL_DATA, 1.0], # bcard 价签「N ◈」(深金墨 5.21:1) - ["营地·等级章字/头带深棕", UiKit.INK_ON_DEEP, UiKit.CAMP_HEADER_BAND, 1.0],# 锻造行 Lv 章(木底小章亮墨) - ["营地·柜台头带字/头带深棕", UiKit.WARM, UiKit.CAMP_HEADER_BAND, 1.0], # 三柜台头带标题(暖白 bold) - ["营地·铭牌副题墨/铭牌板", UiKit.STONE_DEEP, UiKit.PANEL_DATA, 1.0],# 营地铭牌副题「跨局成长账本…」(灰石深化 5.98:1) ["营地·行名墨/行板", UiKit.INK, UiKit.CAMP_ROW_PLATE, 1.0], # 锻造/工坊行名(墨族压暖米行板) ["营地·行价格墨/行板", UiKit.STONE_DEEP, UiKit.CAMP_ROW_PLATE, 1.0],# 锻造行「N 钥石」价签/工坊进度行(灰石深化 6.70:1) ["营地·树分组头墨/柜台板", UiKit.GOLD_INK, UiKit.PANEL_DATA, 1.0],# 天赋树脉分组头「·锻造脉·」(深金墨 5.21:1) ["营地·树行名墨/柜台板", UiKit.INK_LABEL, UiKit.PANEL_DATA, 1.0], # 天赋树行「名 Lv0/1」(标签深墨) ["营地·工坊状态墨/行板", UiKit.GOLD_INK, UiKit.CAMP_ROW_PLATE, 1.0],# 工坊状态字「已解锁」(深金墨 5.84:1·最不利现役态) - ["营地·最近冒险墨/暖亮底", UiKit.WARM_SOFT, UiKit.BG_BRIGHT, 1.0], # 底栏最近冒险条带(暖白次级) ["设置·警示文/设置板", UiKit.INK_HINT, UiKit.PANEL_DATA, 1.0], # 设置警示文/后果说明(暖棕提示墨) ["设置·选项标签/设置板", UiKit.INK_LABEL, UiKit.PANEL_DATA, 1.0], # 设置行标签/状态字(标签深墨) ["三选一·停点头部墨/暗页底", UiKit.WARM_SOFT, UiKit.BG_ROOT, 1.0], # 三选一停点头部/回血反馈行(page_shell 根底档) diff --git a/game/probe/ui_probe.gd b/game/probe/ui_probe.gd index 22b3790d..65d5b429 100644 --- a/game/probe/ui_probe.gd +++ b/game/probe/ui_probe.gd @@ -28,30 +28,40 @@ func _ready() -> void: problems.append("营地入口缺失(选档层新档钮——mn9 新路径驱动中断)〔句柄子容器批 V1〕") else: await get_tree().process_frame - if not main.ui.modals.camp.overlay.visible: - problems.append("营地层未打开(进档开层新路径)〔句柄子容器批 V1〕") + if not main.ui.modals.camp.scene.visible: + problems.append("营地场景根未打开(进档开层新路径)〔句柄子容器批 V1〕") elif main.ui.screens.start_overlay.visible: problems.append("营地层打开时开始层未隐藏(规范 2.3 遮挡纪律)〔句柄子容器批 V1〕") else: - if not String(main.ui.modals.camp.overlay._balance_label.text).begins_with("钥石"): - problems.append("营地余额文案缺失(%s)〔句柄子容器批 V1〕" % main.ui.modals.camp.overlay._balance_label.text) - if main.ui.modals.camp.overlay._tree_buy_btns.is_empty(): - problems.append("树淬炼柜台购买钮缺失(四柜台重排后树=主界面)〔句柄子容器批 V1〕") + # 天赋树子界面(场景点选真实路由——木桩命中区进树界面;卡④ T5 深员改指) + main.ui.modals.camp.scene.object_pressed.emit(&"dummy") + await get_tree().process_frame + if not main.ui.modals.camp.tree.visible: + problems.append("天赋树子界面未打开(场景点选路由中断)〔营地图批 V2〕") + if not String(main.ui.modals.camp.tree._balance_label.text).begins_with("钥石"): + problems.append("营地余额文案缺失(%s)〔句柄子容器批 V1〕" % main.ui.modals.camp.tree._balance_label.text) + if main.ui.modals.camp.tree._tree_buy_btns.is_empty(): + problems.append("树淬炼购买钮缺失(四柜台拆解后树=独立子界面)〔句柄子容器批 V1〕") else: var btn_by_id := {} - for card2 in main.ui.modals.camp.overlay._tree_buy_btns: + for card2 in main.ui.modals.camp.tree._tree_buy_btns: btn_by_id[String(card2.node_id)] = card2.btn if not btn_by_id.has("sp_hp") or bool(btn_by_id["sp_hp"].disabled): problems.append("脊柱生命 L1 白板可购钮未启用(无门槛——can_buy 不含余额面语义)〔句柄子容器批 V1〕") if not btn_by_id.has("att_socket2") or not bool(btn_by_id["att_socket2"].disabled): problems.append("同调位 2 前置未亮应禁用(点亮前置语义)〔句柄子容器批 V1〕") - if main.ui.modals.camp.overlay._workshop_rows.size() != 12: - problems.append("秘宝匣柜台行数错误(%d ≠ 12——迭代 22 秘宝批换代)〔句柄子容器批 V1〕" % main.ui.modals.camp.overlay._workshop_rows.size()) - main._on_camp_closed() + main.ui.modals.camp.tree.closed.emit() + await get_tree().process_frame + # 秘宝匣子界面(场景点选真实路由——宝箱命中区) + main.ui.modals.camp.scene.object_pressed.emit(&"chest") + await get_tree().process_frame + if main.ui.modals.camp.treasure._workshop_rows.size() != 12: + problems.append("秘宝匣行数错误(%d ≠ 12——迭代 22 秘宝批换代)〔句柄子容器批 V1〕" % main.ui.modals.camp.treasure._workshop_rows.size()) + main.ui.modals.camp.treasure.closed.emit() + await get_tree().process_frame + main._on_camp_closed() # 关层收闭(营地与选档层同收+开始层恢复——卡④ T3) await get_tree().process_frame - main._on_save_select_closed() # 关闭被栈还原的选档层(动线序中间态——卡④ 换代点) - await get_tree().process_frame - if main.ui.modals.camp.overlay.visible or not main.ui.screens.start_overlay.visible: + if main.ui.modals.camp.scene.visible or not main.ui.screens.start_overlay.visible: problems.append("营地关闭后未恢复开始层(开合往返失守)〔句柄子容器批 V1〕") # 换回全新零档(营地段购买态不泄入后续冒险段——确定性;先删后建防陈旧档泄入) ProbeUiUtil.isolate_save(main, "smoke_ui_probe_camp", true, false, true) diff --git a/game/probe/ui_struct_probe.gd b/game/probe/ui_struct_probe.gd index 7f800104..bf485e30 100644 --- a/game/probe/ui_struct_probe.gd +++ b/game/probe/ui_struct_probe.gd @@ -42,33 +42,70 @@ func _ready() -> void: problems.append("[camp] 营地入口缺失(选档层新档钮——mn9 新路径驱动中断)〔句柄子容器批 V1〕") else: _settle() - await _audit("camp", [main.ui.modals.camp.overlay]) - # 营地灰字源 token 扫描(迭代36 wc4 静态半——源内零裸 UiKit.STONE;判别式= - # STONE 出现次数 == STONE_DEEP 出现次数,即每处 STONE 都带 _DEEP 后缀) - var camp_src := FileAccess.get_file_as_string("res://presentation/views/camp_overlay_view.gd") - if camp_src.count("UiKit.STONE") != camp_src.count("UiKit.STONE_DEEP"): - problems.append("[camp] camp_overlay_view.gd 存在裸 UiKit.STONE(非 _DEEP 后缀——wc4 源扫描)〔句柄子容器批 V1〕") - main._on_camp_closed() + await _audit("camp", [main.ui.modals.camp.scene]) # 审计根=营地场景图(卡④ T5——CampOverlay 退役) + # 营地灰字源 token 扫描(迭代36 wc4 静态半——营地域视图源内零裸 UiKit.STONE;判别式= + # STONE 出现次数 == STONE_DEEP 出现次数;卡④ T5 改扫场景根+四子界面+公共壳六件) + var camp_stone := 0 + var camp_stone_deep := 0 + for vf in ["camp_scene_view", "forge_view", "treasure_view", "tree_view", "codex_view", "camp_sub_view_base"]: + var vf_src := FileAccess.get_file_as_string("res://presentation/views/%s.gd" % vf) + camp_stone += vf_src.count("UiKit.STONE") + camp_stone_deep += vf_src.count("UiKit.STONE_DEEP") + if camp_stone != camp_stone_deep: + problems.append("[camp] 营地域视图存在裸 UiKit.STONE(非 _DEEP 后缀——wc4 源扫描)〔句柄子容器批 V1〕") + # ---- 营地场景层序段(卡④ V1①——子节点序=layout 表 z 序逐层相等、各层纹理矩形与表逐值一致; + # 锻炉可达(V2 场景点选路由)+顶栏位在座(V8 结构)+根态反参照(V9——根态零文字按钮))---- + var layout: CampSceneLayoutTable = main.db.presentation.camp_scene_layout + var order_ok := true + var rect_ok := true + for i in layout.layers.size(): + var layer_node: Control = main.ui.modals.camp.scene.get_child(i) + if String(layer_node.name) != "Layer_%s" % layout.layers[i].key: + order_ok = false + if layer_node.position != layout.layers[i].texture_rect.position or layer_node.size != layout.layers[i].texture_rect.size: + rect_ok = false + if not order_ok: + problems.append("[camp] 场景子节点序≠layout 表 z 序(逐层相等失守)〔营地图批 V1〕") + if not rect_ok: + problems.append("[camp] 层贴图矩形≠layout 表(逐值一致失守)〔营地图批 V1〕") + main.ui.modals.camp.scene.object_pressed.emit(&"forge") _settle() - main._on_save_select_closed() # 关闭被栈还原的选档层(动线序中间态——卡④ 换代点) + if not main.ui.modals.camp.forge.visible: + problems.append("[camp] 点选锻炉→锻造子界面未开(场景点选路由中断)〔营地图批 V2〕") + var hud_slot: Control = main.ui.modals.camp.scene.get_node_or_null("HudBandSlot") + if hud_slot == null or hud_slot.custom_minimum_size.y != 48: + problems.append("[camp] 顶栏 HUD 预留位缺失或高≠48(浮层覆盖不挤压画面)〔营地图批 V8〕") + var scene_buttons := 0 + for n in main.ui.modals.camp.scene.get_children(): + if n is Button: + scene_buttons += 1 + if scene_buttons != 0: + problems.append("[camp] 场景根态存在文字按钮(反参照纪律——禁文字按钮列表形态)〔营地图批 V9〕") + main.ui.modals.camp.forge.closed.emit() + _settle() + main._on_camp_closed() # 关层收闭(营地与选档层同收+开始层恢复——卡④ T3) _settle() - # ---- 生涯页:入口点击链(合成点击真路径=pressed.emit→组合根 _open_career)→ + # ---- 生涯页:入口=帐篷旁笔记本(卡④ T3 改挂——场景点选信号真实路由→组合根 _open_career)→ # 结构断言族→只读巡检(契约 3)+零动效契约+零跳转契约(提纲 P4 甲)→组合根真实路径关闭。 #(登记序/树序契约统一在全模态 _modal_registry_contract——boot 段跑)---- - # 生涯页驱动=函数直调中间态(卡② mn9/mn10——careerbtn 已撤,卡④ 营地笔记本改挂前无 UI 路径) - main._open_career() + # 营地语境:开始层全程隐藏(笔记本入口在营地场景根——关生涯回营地不回开始层,卡④ T3 语境分支) + main._camp_pres.open_camp() # 重开营地场景根(笔记本入口语境) + _settle() + main.ui.modals.camp.scene.object_pressed.emit(&"notebook") _settle() if not main.ui.modals.career_overlay.visible or main.ui.screens.start_overlay.visible: - problems.append("[career] 生涯页未打开或开始层未隐藏(函数直调中间态断裂)") + problems.append("[career] 生涯页未打开或开始层未隐藏(笔记本改挂路径断裂)〔营地图批 V5〕") await _audit("career", [main.ui.modals.career_overlay]) _career_readonly_contract(main) _career_zero_motion_contract(main) _career_nojump_contract(main) main._on_career_closed() _settle() - if main.ui.modals.career_overlay.visible or not main.ui.screens.start_overlay.visible: - problems.append("[career] 关闭后页未隐藏或开始层未恢复(模态栈单口失守)") + if main.ui.modals.career_overlay.visible or main.ui.screens.start_overlay.visible: + problems.append("[career] 关闭后页未隐藏或开始层回弹(营地语境分支失守)〔营地图批 V5〕") + main._on_camp_closed() # 关营地复归菜单语境(后续选档段前提) + _settle() # ---- 选档界面(迭代 33 卡③):函数直调开层(「进入存档」钮归卡② mn3——点击链在卡② 承接), # sl1 三槽呈现/sl2 摘要三项逐槽读数/sl3 摘要禁项/sl4 操作集二分/sl9 重启链不预选。 @@ -394,7 +431,7 @@ func _career_zero_motion_contract(main: Node) -> void: # ⑫模态登记/树序全量合同(V1——career 专属登记序契约推广到全部模态+屏壳; # 判据=main.ui.LAYER_CONTRACT 单一事实源:登记册序==合同模态序、直接子层树序==合同序逐对相等。 # 两特例按合同数据表达:level_screen 宿住冒险屏壳(树序随宿主=全模态之下,遮挡语义归模态栈 -# screen_state 登记)、camp_overlay 成员与 camp_screen 屏壳同槽(屏壳树序代言成员登记位)。 +# screen_state 登记)、camp_scene 成员与 camp_screen 屏壳同槽(屏壳树序代言成员登记位)。 # _career_registry_contract 的断言(career=状态面板后/确认弹窗前、树序同步)由本全量合同覆盖) # ⑭选档界面契约(卡③ sl1/sl2/sl3/sl4/sl9——呈现面全部来自喂入数据,视图零自判) func _save_select_contract(main: Node, tpl: String) -> void: @@ -516,7 +553,7 @@ func _modal_registry_contract(main: Node) -> void: elif lv.get_parent().get_index() >= main.ui.modals.legend_overlay.get_index(): problems.append("[registry] 冒险屏壳应在全模态之下(宿主 idx=%d legend idx=%d)〔装配生命批 V1〕" % [ lv.get_parent().get_index(), main.ui.modals.legend_overlay.get_index()]) - # ④ 营地同槽特例:camp_screen 屏壳树序夹商店层与设置层之间(成员 camp_overlay 登记位代言) + # ④ 营地同槽特例:camp_screen 屏壳树序夹商店层与设置层之间(成员 camp_scene 登记位代言) var cs: Node = main.ui.screens.camp_screen if cs.get_index() <= main.ui.modals.shop_overlay.get_index() or cs.get_index() >= main.ui.modals.settings_overlay.get_index(): problems.append("[registry] camp_screen 屏壳树序应夹商店与设置层之间(idx=%d shop=%d settings=%d)〔装配生命批 V1〕" % [