Files
gplan-2/game/presentation/main_debug_flow.gd
T

109 lines
6.5 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## VERTICAL SLICE - NOT FOR PRODUCTION
## 组合根调试流程承接件:调试浮窗开合与上下文同步、批量模拟入口、两层调试对局起手、诊断转储。
## 本件是 main.gd 同名函数的逐字搬运(成员访问改 root 前缀)——main 侧留同名薄委托,探针 main.X 路径零改动。
## 调试会话状态机归 debug_session.gd;本件只接线与出 UI,零成员态。
extends RefCounted
static func _on_diagnose_pressed(root: Variant) -> void:
# 本局种子现值走 _current_master_seed 只读单点
var ctx := {"mode": "level" if root.run_scope.level_active else "debug", "seed": root._current_master_seed()}
if root.run_scope.level_active and root.run_scope.runner != null:
ctx["runner"] = {"node_index": root.run_scope.runner.node_index, "level_result": String(root.run_scope.runner.level_result),
"hero_hp": root.run_scope.runner.hero_hp, "settlement_is_null": root.run_scope.runner.current_battle() == null}
if root.run_scope.settlement != null:
ctx["settlement"] = root.run_scope.settlement.diagnostic_snapshot() # 诊断观测面(私有字段零直读)
var path: String = root.logger.dump_diagnosis(ctx)
root.ui.battle.board_zone.toast.show_toast("已转储诊断: " + path, "info")
static func _show_debug_overlay(root: Variant) -> void:
# 门禁:对局中可开;本函数仍是唯一开窗入口,门禁逻辑收函数内:
# 棋盘输入锁/状态角标判据排除浮窗,
# 遮挡语义=ModalStack 登记制(他模态开时暂隐、关后自动恢复),此处零场景限制
if root.ui.modals.debug_overlay == null:
return
root.ui.modals.flow.open(root.ui.modals.debug_overlay)
_sync_debug_overlay(root)
# 调试浮窗角标点击(两屏同款处理器——与状态角标同形制守卫;仍收口 _show_debug_overlay 单口)
static func _on_debug_badge_pressed(root: Variant) -> void:
var map_on: bool = root.ui.modals.level_screen != null and root.ui.modals.level_screen.visible
if (map_on and root.ui.modals.flow.badge_greyed_map()) or (not map_on and root.ui.modals.flow.badge_greyed_battle()):
return
_show_debug_overlay(root)
# 浮窗上下文同步(当局数据刷新+对局中按钮禁用单点):调用面=开窗口与模态开合
# 单口(凡影响开态/对局态的路径必经其一——与 _sync_status_entry 同款纪律)
static func _sync_debug_overlay(root: Variant) -> void:
if root.ui.modals.debug_overlay == null:
return
root.ui.modals.debug_overlay.set_context_locked(root.run_scope.settlement != null or root.run_scope.is_adventure) # 对局中批量模拟/两层调试入口禁用(长程异步模拟与活跃结算并存态不开放)
root.ui.modals.debug_overlay.update_run_data(_debug_run_data(root)) # 当局数据只读区块喂入(开窗+模态开合信号驱动)
# 当局数据六项只读投影(零直读内部状态、零写通路):种子=adventure.master_seed 现值
# (非 _seed_value() 重算);调试两层/非对局无冒险对象=RNG 服务 master_seed 现值(只读出口,
# 未播种 -1 显「—」);关卡/节点/HP/GP=runner 成文出口、钥石=adventure 冒险账本(LevelRunner 无此域);
# 缺位=「—」占位。零动效(纯标签重查)。
static func _debug_run_data(root: Variant) -> Dictionary:
var r = root.run_scope.adventure.runner() if root.run_scope.adventure != null else null
var seed_now: int = root._current_master_seed()
var seed_txt: String = str(seed_now) if seed_now >= 0 else "—"
if r == null:
return {"seed": seed_txt, "level": "—", "node": "—", "hp": "—", "gp": "—", "keystone": "—"}
return {"seed": seed_txt, "level": int(root.run_scope.adventure.level_index), "node": int(r.node_index),
"hp": "%d/%d" % [int(r.hero_hp), int(r.effective_max_hp())], "gp": int(r.gp), "keystone": root.run_scope.adventure.journal().keystone_gained()}
static func _close_debug_overlay(root: Variant) -> void:
root.ui.modals.flow.close(root.ui.modals.debug_overlay) # 模态栈单口——开始层全程未隐藏,无需恢复
static func _on_tune_apply(root: Variant, atk_pct: int, hp_pct: int) -> void:
# 加成无持久态可"落"——各战斗开局经 board_resolvers.debug_hero_override/runner 现算生效(应用=关闭浮窗)
_close_debug_overlay(root)
static func _on_tune_simulate(root: Variant, n: int) -> void:
# 批量模拟编排 = 控制器承接(tune_sim_controller.gd);E4 后无表态需复位——模拟走 runner 覆盖参数。
# 对局中禁用兜底(长程异步模拟与活跃冒险/结算并存态不开放;探针 emit 绕过 disabled 时由此守住)
if root.run_scope.settlement != null or root.run_scope.is_adventure:
return
root._tune_sim.run(n)
static func _start_debug_levels(root: Variant) -> void:
# 守卫:调试对局与活跃冒险/结算/批量模拟并存不开放——并发会清写
# settlement/编排态=状态机破坏;模拟在跑时 reset_sliders 会作废测量读数(d5 置灰之外的信号绕过闸)
if root.run_scope.is_adventure or root.run_scope.settlement != null or root._tune_sim.is_running():
return
root.ui.modals.debug_overlay.reset_sliders()
root.ui.modals.flow.close(root.ui.modals.debug_overlay) # 浮窗内入口发起——随开随收(对局期不可再开:门禁在 _show_debug_overlay)
root.ui.screens.start_overlay.visible = false
root.ui.battle.log_view.clear()
root.ui.battle.log_view.append_bb(root.Narrator.debug_open_line(root._seed_value(), 1, true))
root._begin_session(false)
if not root._debug.start_debug_levels():
root._fatal_screen("战斗启动失败——见输出日志")
static func _on_debug_battle_created(root: Variant, settlement_ref: BattleOrchestrator, _level: int, _carry: int) -> void:
# begin_battle 前接手 + 接线(signal.connect 唯一归组合根)。settlement 必须先于 begin_battle
# 就位——begin 期间发出的 board_changed 要用新板重建棋盘并触发一次性提示(缺陷①同款时序义务)
root.run_scope.settlement = settlement_ref
root._wire_battle(settlement_ref)
static func _on_debug_battle_ready(root: Variant, settlement_ref: BattleOrchestrator, _level: int, _carry: int) -> void:
root.run_scope.settlement = settlement_ref
var board = root.run_scope.settlement.minesweeper.current_board()
root.ui.battle.board_zone.board_view.rebuild(board, root.run_scope.settlement.minesweeper)
if board != null:
root.ui.battle.stage.set_board_type(String(board.board_type)) # 舞台背景选图随板(C8——调试就绪重建点单行同步)
root._check_board_hints()
root._refresh_presentations()