From 3f46edbfa3d562bece3396dfc1953a64b9e80507 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Tue, 29 Sep 2026 19:48:40 +0800 Subject: [PATCH] =?UTF-8?q?iter8-T5=20=E5=8D=A1=E2=91=A5=20=E6=88=98?= =?UTF-8?q?=E6=96=97=E8=83=9C=E5=88=A9=E6=80=BB=E7=BB=93=E7=BB=93=E7=AE=97?= =?UTF-8?q?=E6=8E=A5=E7=BA=BF=EF=BC=9A=5Fon=5Fchoices=5Fpresented=20?= =?UTF-8?q?=E6=88=98=E6=96=97=E8=8A=82=E7=82=B9=E5=81=9C=E7=82=B9=E5=88=A4?= =?UTF-8?q?=E6=8D=AE=EF=BC=88battle=20=E5=9E=8B+current=5Fbattle=20?= =?UTF-8?q?=E5=B7=B2=E6=94=B6=E5=9C=BA+=E9=9D=9E=E7=A9=BA=E5=80=99?= =?UTF-8?q?=E9=80=89=E4=B8=89=E6=9D=A1=E4=BB=B6=E5=A4=A9=E7=84=B6=E5=88=86?= =?UTF-8?q?=E6=B5=81=E5=85=A5=E5=8F=A3/=E5=85=91=E4=BB=98/=E5=95=86?= =?UTF-8?q?=E5=BA=97=E5=81=9C=E7=82=B9=EF=BC=89=E6=8C=82=20BattleEndOverla?= =?UTF-8?q?y=20=E8=83=9C=E5=88=A9=E5=BD=A2=E6=80=81=EF=BC=88=E9=87=91?= =?UTF-8?q?=E8=9C=A1=E5=B0=81+GP=20=E5=A2=9E=E9=87=8F=E3=80=94wallet=5Fcha?= =?UTF-8?q?nged=20gain=20=E8=BD=BD=E8=8D=B7=E5=8F=96=E6=95=B0=E3=80=95+?= =?UTF-8?q?=E6=80=BB=E9=87=8F=20runner.gp+=E5=88=A4=E5=AE=9A=E8=A1=8C+?= =?UTF-8?q?=E4=B8=8B=E4=B8=80=E8=8A=82=E7=82=B9+=E6=98=8E=E7=BB=86?= =?UTF-8?q?=E5=9B=9E=E7=9C=8B=E6=97=A2=E6=9C=89=E6=8C=89=E9=92=AE=EF=BC=89?= =?UTF-8?q?=E2=80=94=E2=80=94=5Fon=5Fbattle=5Fend=5Fcontinue=20=E6=8C=82?= =?UTF-8?q?=E8=B5=B7=E5=88=86=E6=B4=BE=EF=BC=88=5Fsettlement=5Fstop=5Fpend?= =?UTF-8?q?ing=E2=86=92=E6=9A=82=E5=AD=98=E5=80=99=E9=80=89=E5=9B=9E?= =?UTF-8?q?=E6=94=BE=E8=BF=9B=E9=80=89=E8=B7=AF=E9=A1=B5=EF=BC=8Cchoices?= =?UTF-8?q?=5Fpresented=20=E9=93=BE=E4=BF=9D=E6=8C=81=E5=9C=A8=E5=90=8E?= =?UTF-8?q?=EF=BC=89=EF=BC=9BBoss=20=E8=83=9C/=E5=A4=B1=E8=B4=A5=E8=B5=B0?= =?UTF-8?q?=20level=5Ffinished=20=E5=8F=A6=E8=B7=AF=E9=9B=B6=E5=8F=98?= =?UTF-8?q?=E5=8C=96=E2=80=94=E2=80=94=E6=8E=A2=E9=92=88=EF=BC=9A=E7=BB=93?= =?UTF-8?q?=E7=AE=97=E6=A1=86=E5=B7=B2=E6=8B=8D=E6=9D=BF=E9=9D=A2=E6=96=AD?= =?UTF-8?q?=E8=A8=80=EF=BC=88GP=20=E8=A1=8C=3D=E9=92=B1=E5=8C=85=E5=AE=9E?= =?UTF-8?q?=E6=80=81=E9=80=90=E5=AD=97/=E5=88=A4=E5=AE=9A=E8=A1=8C/?= =?UTF-8?q?=E4=B8=8B=E4=B8=80=E8=8A=82=E7=82=B9=E8=BF=9B=E9=80=89=E8=B7=AF?= =?UTF-8?q?=EF=BC=89=E5=85=A5=20ui=5Fclick=5Fprobe=20=E4=B8=BB=E5=BE=AA?= =?UTF-8?q?=E7=8E=AF=EF=BC=9B=E5=9B=9B=E6=8E=A2=E9=92=88=E6=AE=B5=E9=A6=96?= =?UTF-8?q?=E6=B8=85=E5=9C=BA=E8=A1=A5=E4=B8=81=EF=BC=88=E6=AE=8B=E7=95=99?= =?UTF-8?q?=E6=96=AD=E7=82=B9=E8=A7=A6=E5=8F=91=E4=BA=92=E6=96=A5=E7=A1=AE?= =?UTF-8?q?=E8=AE=A4=E6=97=A9=E9=80=80=3D=E6=9C=AC=E8=BD=AE=20input=20?= =?UTF-8?q?=E6=8C=82=E6=AD=BB=E6=A0=B9=E5=9B=A0=E4=B9=8B=E4=BA=8C=EF=BC=89?= =?UTF-8?q?=E2=80=94=E2=80=94=E9=97=B8=EF=BC=9A=E5=86=92=E7=83=9F=20593/0+?= =?UTF-8?q?=E4=B8=89=E6=8E=A2=E9=92=88=E5=85=A8=E7=BB=BF=EF=BC=88click=20?= =?UTF-8?q?=E9=97=AE=E9=A2=98=3D0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/presentation/main.gd | 28 ++++++++++++++++++++++++++++ game/smoke/ui_click_probe.gd | 20 ++++++++++++++++++++ game/smoke/ui_input_probe.gd | 3 +++ game/smoke/ui_layout_probe.gd | 3 +++ game/smoke/ui_tune_probe.gd | 3 +++ 5 files changed, 57 insertions(+) diff --git a/game/presentation/main.gd b/game/presentation/main.gd index b32047ad..d8d7d584 100644 --- a/game/presentation/main.gd +++ b/game/presentation/main.gd @@ -42,6 +42,9 @@ var _seed_edit: LineEdit var _lvbtn: Button # 开始冒险按钮句柄(迭代 8 卡③——有断点时互斥二次确认文案换面) var _resume_btn: Button # 继续上局按钮句柄(迭代 8 卡②——有断点才亮) var _lv_start_armed := false # 新冒险二次确认态(首击置位、二击提交、3s 超时回落——仿放弃确认) +var _settlement_stop_pending := false # 卡⑥ 战斗胜利总结结算框挂起态(确认「下一节点」后进选路页) +var _pending_candidates: Array = [] # 结算框挂起期的选路候选暂存(choices_presented 载荷) +var _last_gain_amount := 0 # 最近一笔钱包入账(卡⑥ GP 增量取数面——wallet_changed gain 载荷) var _start_overlay: Control var _end_overlay: BattleEndOverlay var _inter_overlay: Control @@ -432,6 +435,14 @@ func _on_battle_end_continue() -> void: # 终局出口:返回开始界面(冒险摘要留档试玩日志;钥石已在收束时入存档——存档序列化批) _close_modal(_end_overlay) _end_overlay.close() + # 卡⑥ 挂起分派:战斗胜利总结结算框的「下一节点」≠ 终局——进选路页(暂存候选恢复呈现) + if _settlement_stop_pending: + _settlement_stop_pending = false + _enter_level_screen() + level_screen.open_choices(_pending_candidates, runner) + _pending_candidates = [] + _refresh_presentations() + return _debug.reset() if runner != null: runner.restore_hero_base() @@ -687,6 +698,20 @@ func _on_choices_presented(candidates: Array) -> void: if runner == null: return log_view.append_bb(Narrator.route_line(candidates, runner)) + # 卡⑥ 战斗胜利总结结算(battle.md OQ14 拍板面接线——欠账清偿):战斗胜利停点先弹 BattleEndOverlay + # 胜利形态(金蜡封+GP 增量+总量+判定行+「下一节点」+明细回看),确认后进选路页。判据 = 战斗节点 + # 的选路停点且战斗已收场(battle 收尾分支 _settlement 置 null 先于本信号;入口/兑付/商店停点 + # 的当前节点非 battle 型——三态天然分流)。Boss 胜/失败走 level_finished 另路不经此处。 + if _adventure_mode and runner.current_battle() == null \ + and String(runner.current_node().get("type", "")) == "battle" and not candidates.is_empty(): + _settlement_stop_pending = true + _pending_candidates = candidates.duplicate() + _end_overlay.open_victory(Narrator.battle_end_text("victory", false), "下一节点", + board_view.get_global_rect(), + "战利品 GP +%d · 合计 %d" % [_last_gain_amount, int(runner.gp)]) + _open_modal(_end_overlay) + _refresh_presentations() + return _enter_level_screen() level_screen.open_choices(candidates, runner) _refresh_presentations() @@ -953,9 +978,12 @@ func _on_wallet_changed(event: String, gp: int, extra: Dictionary) -> void: match String(event): # GP 影子账(迭代 6 T7——收束清零前取值,纯呈现零核心触碰=C1 呈现层方案) "gain", "buy": _adventure_gp_view = gp + if String(event) == "gain": + _last_gain_amount = int(extra.get("amount", 0)) # 卡⑥ GP 增量取数(每战恰一笔 gain) "clear": _adventure_gp_final = _adventure_gp_view _adventure_gp_view = 0 + _last_gain_amount = 0 if shop_overlay.visible and runner != null: shop_overlay.refresh_state(runner.shop_products(), int(runner.gp)) _refresh_presentations() diff --git a/game/smoke/ui_click_probe.gd b/game/smoke/ui_click_probe.gd index 9b7e14d5..075c0c50 100644 --- a/game/smoke/ui_click_probe.gd +++ b/game/smoke/ui_click_probe.gd @@ -26,6 +26,7 @@ var _tested_end_review := false # 迭代 6 T7——终局面板回看入口( var _tested_refresh_chain := false var _tested_tooltip := false var _inter_confirms := 0 # 大奖励屏确认计数(冒险推进停点——首见确认推进 L2,再见 = L2 通关收口) +var _settlement_confirms := 0 # 卡⑥ 胜利结算框确认计数(观测面——每场普通战斗胜利恰一) var _route_clicks := 0 # 选路覆盖层点击计数(岔路使用率观测面) @@ -142,6 +143,9 @@ func _ready() -> void: if legacy_motion != null: _problems.append("调整板减动效旧入口未退役(设置面唯一入口失守——卡④ AC③)") # 换回全新零档(营地购买态不泄入后续冒险段——确定性;档案残留下次段首清理兜底) + for p0 in ["user://smoke_click_probe_reset.json", "user://smoke_click_probe_reset.json.tmp"]: + if FileAccess.file_exists(p0): + DirAccess.remove_absolute(p0) # 段首清场——上次运行的残留断点会触发互斥确认早退 var iso_reset = load("res://core/save_manager.gd").new("user://smoke_click_probe_reset.json") iso_reset.load_from_disk() iso_reset.mark_first_adventure_done() # 对齐基线(真实档已有游玩史)——非首次脚本模式=逐关抽签模板 @@ -217,6 +221,22 @@ func _ready() -> void: break _flags_placed.clear() continue + if main._end_overlay.is_open() and main._settlement_stop_pending: + # 卡⑥ 战斗胜利总结结算框(真实信号路径——每场普通胜利到达):断言已拍板面后点「下一节点」 + if not main._input_locked(): + _problems.append("胜利结算框打开时输入未锁定") + var gp_line: String = main._end_overlay._gp_line.text + if not gp_line.contains("GP +%d" % main._last_gain_amount) or not gp_line.contains("合计 %d" % int(main.runner.gp)): + _problems.append("胜利结算框 GP 增量/总量与钱包实态不符(%s|实态 +%d/%d)" % [gp_line, main._last_gain_amount, int(main.runner.gp)]) + if main._end_overlay.verdict_text() == "": + _problems.append("胜利结算框判定行缺失") + _settlement_confirms += 1 + main._end_overlay._btn.pressed.emit() # 「下一节点」真实信号路径 + await get_tree().process_frame + await get_tree().process_frame + if main._settlement_stop_pending or not main.level_screen.visible: + _problems.append("胜利结算框「下一节点」未进选路页(卡⑥ AC②)") + continue if main._end_overlay.is_open(): # 冒险终局(失败/放弃/打穿)——单关直入口退役后无二段入口,见终局即收口(模态断言照旧) if not main._input_locked(): diff --git a/game/smoke/ui_input_probe.gd b/game/smoke/ui_input_probe.gd index 92163c50..c766672a 100644 --- a/game/smoke/ui_input_probe.gd +++ b/game/smoke/ui_input_probe.gd @@ -27,6 +27,9 @@ func _ready() -> void: await get_tree().process_frame # 存档隔离(迭代 8 卡①②——断点写盘面随冒险挂 main.save_manager;探针禁碰真实档 user://save.json, # 同 ui_click_probe 隔离纪律。首次冒险布尔位置位=对齐真实档游玩史口径,模板抽签路径不变) + for p0 in ["user://smoke_input_probe_save.json", "user://smoke_input_probe_save.json.tmp"]: + if FileAccess.file_exists(p0): + DirAccess.remove_absolute(p0) # 段首清场——上次运行的残留断点会触发互斥确认早退 var iso = load("res://core/save_manager.gd").new("user://smoke_input_probe_save.json") iso.load_from_disk() iso.mark_first_adventure_done() diff --git a/game/smoke/ui_layout_probe.gd b/game/smoke/ui_layout_probe.gd index 5e8e28e7..d0dfb026 100644 --- a/game/smoke/ui_layout_probe.gd +++ b/game/smoke/ui_layout_probe.gd @@ -11,6 +11,9 @@ func _ready() -> void: add_child(main) await get_tree().process_frame # 存档隔离(迭代 8 卡①②——停点断点写盘随 main.save_manager;探针禁碰真实档,同族探针隔离纪律) + for p0 in ["user://smoke_layout_probe_save.json", "user://smoke_layout_probe_save.json.tmp"]: + if FileAccess.file_exists(p0): + DirAccess.remove_absolute(p0) # 段首清场——上次运行的残留断点会触发互斥确认早退 var iso = load("res://core/save_manager.gd").new("user://smoke_layout_probe_save.json") iso.load_from_disk() iso.mark_first_adventure_done() diff --git a/game/smoke/ui_tune_probe.gd b/game/smoke/ui_tune_probe.gd index 0652cac8..87d7314f 100644 --- a/game/smoke/ui_tune_probe.gd +++ b/game/smoke/ui_tune_probe.gd @@ -60,6 +60,9 @@ func _ready() -> void: # ⑧ 单次加成生效回归断言:应用加成 + 启动单场战斗 → 呈现快照 hero 必须是"基线 × 单次加成" # (攻击 ×2 / 生命 +50%)——旧缺陷(残留值被当基线再乘)在 encounter 参数链上同样被抓获 # 存档隔离(迭代 8 卡①——停点断点写盘随 main.save_manager;探针禁碰真实档,同族探针隔离纪律) + for p0 in ["user://smoke_tune_probe_save.json", "user://smoke_tune_probe_save.json.tmp"]: + if FileAccess.file_exists(p0): + DirAccess.remove_absolute(p0) # 段首清场——上次运行的残留断点会触发互斥确认早退 var iso_tune = load("res://core/save_manager.gd").new("user://smoke_tune_probe_save.json") iso_tune.load_from_disk() iso_tune.mark_first_adventure_done()