merge: 迭代 8 二轮修改批——A 互斥确认弹窗/B 结算框实底面板+蜡封徽记/C 结算伤害数字突出/D 退出提级一级菜单+开关换皮(用户一轮目检四裁决,click 探针同步)
This commit is contained in:
commit
7b491bdeb2
9 files changed
+195
-80
No files matched your search
+34
-23
@@ -39,9 +39,8 @@ var _adventure_mode := false # 冒险模式标记(inter 层确认分派
|
||||
var logger = null # 试玩日志器(JSONL 持久化 + 卡死诊断转储——呈现层组件)
|
||||
var _level_active := false
|
||||
var _seed_edit: LineEdit
|
||||
var _lvbtn: Button # 开始冒险按钮句柄(迭代 8 卡③——有断点时互斥二次确认文案换面)
|
||||
var _resume_btn: Button # 继续上局按钮句柄(迭代 8 卡②——有断点才亮)
|
||||
var _lv_start_armed := false # 新冒险二次确认态(首击置位、二击提交、3s 超时回落——仿放弃确认)
|
||||
var confirm_dialog: ConfirmDialog # 通用确认弹窗(二轮修改批 A——新冒险互斥确认弹窗化)
|
||||
var _settlement_stop_pending := false # 卡⑥ 战斗胜利总结结算框挂起态(确认「下一节点」后进选路页)
|
||||
var _pending_candidates: Array = [] # 结算框挂起期的选路候选暂存(choices_presented 载荷)
|
||||
var _last_gain_amount := 0 # 最近一笔钱包入账(卡⑥ GP 增量取数面——wallet_changed gain 载荷)
|
||||
@@ -185,18 +184,21 @@ func _build_ui() -> void:
|
||||
tune_panel.closed.connect(_close_tune_panel)
|
||||
tune_panel.apply_requested.connect(_on_tune_apply)
|
||||
tune_panel.simulate_requested.connect(_on_tune_simulate)
|
||||
settings_overlay = SettingsOverlay.new(settings_store) # 迭代 8 卡④——最小设置面(音量/全屏/减动效/退出)
|
||||
settings_overlay = SettingsOverlay.new(settings_store) # 迭代 8 卡④——最小设置面(音量/全屏/减动效)
|
||||
add_child(settings_overlay)
|
||||
settings_overlay.closed.connect(_on_settings_closed)
|
||||
confirm_dialog = ConfirmDialog.new() # 二轮修改批 A——新冒险互斥确认弹窗
|
||||
add_child(confirm_dialog)
|
||||
confirm_dialog.confirmed.connect(_on_confirm_new_adventure)
|
||||
confirm_dialog.cancelled.connect(_on_confirm_cancelled)
|
||||
_modals = ModalStack.new()
|
||||
for m: Control in [legend_overlay, review_overlay, node_overlay, level_screen, _end_overlay, shop_overlay, camp_overlay, tune_panel, settings_overlay]:
|
||||
for m: Control in [legend_overlay, review_overlay, node_overlay, level_screen, _end_overlay, shop_overlay, camp_overlay, tune_panel, settings_overlay, confirm_dialog]:
|
||||
_register_modal(m)
|
||||
_tune_sim = TuneSimController.new(db, tune_panel, int(db.hero.max_hp))
|
||||
|
||||
var start: Dictionary = UiAssembler.build_start_overlay(self, db)
|
||||
_start_overlay = start.overlay
|
||||
_seed_edit = start.seed_edit
|
||||
_lvbtn = start.lvbtn
|
||||
_resume_btn = start.resumebtn
|
||||
start.lvbtn.pressed.connect(_start_adventure_from_menu)
|
||||
start.resumebtn.pressed.connect(_resume_from_menu) # 迭代 8 卡②——续玩入口
|
||||
@@ -205,6 +207,7 @@ func _build_ui() -> void:
|
||||
start.dbgbtn.visible = OS.get_environment("DS_DEBUG") == "1" # 迭代 8 卡④——调试入口默认隐藏门控(DS_DEBUG=1 点亮)
|
||||
start.campbtn.pressed.connect(_open_camp)
|
||||
start.settingsbtn.pressed.connect(_open_settings) # 迭代 8 卡④——最小设置面入口
|
||||
start.quitbtn.pressed.connect(_quit_game) # 二轮修改批 D1——退出游戏提级一级菜单
|
||||
|
||||
var inter: Dictionary = UiAssembler.build_inter_overlay(self)
|
||||
_inter_overlay = inter.overlay
|
||||
@@ -250,35 +253,44 @@ func _input_locked() -> bool:
|
||||
# 模态/非战斗期棋盘输入锁(各 overlay 自身可见即锁定)
|
||||
return legend_overlay.is_open() or review_overlay.is_open() or _end_overlay.is_open() \
|
||||
or node_overlay.visible or level_screen.visible or shop_overlay.visible or tune_panel.visible \
|
||||
or _start_overlay.visible or _inter_overlay.visible or settlement == null
|
||||
or _start_overlay.visible or _inter_overlay.visible or confirm_dialog.visible or settlement == null
|
||||
|
||||
|
||||
# ==================== 冒险模式入口(唯一试玩入口——单关测试直入口退役 2026-09-23 用户拍板)====================
|
||||
|
||||
func _start_adventure_from_menu() -> void:
|
||||
# 互斥二次确认(迭代 8 卡②③):有断点时开新冒险须两击——首击转确认态(文案换面+3s 超时回落,
|
||||
# 仿放弃确认形态),二击才提交;提交即弃旧断点(clear+写盘——「开新局」覆盖语义对盘面即时生效)
|
||||
if save_manager != null and save_manager.has_breakpoint() and not _lv_start_armed:
|
||||
_lv_start_armed = true
|
||||
if _lvbtn != null:
|
||||
_lvbtn.text = "已有未完冒险——再点一次开新冒险(旧断点将被覆盖)"
|
||||
get_tree().create_timer(3.0).timeout.connect(_reset_lv_confirm)
|
||||
# 互斥确认弹窗化(二轮修改批 A——用户目检裁决「弹窗提示」):有断点时开新冒险弹实底确认框,
|
||||
# 「开新冒险」提交(弃旧断点+写盘)/「取消」回菜单
|
||||
if save_manager != null and save_manager.has_breakpoint():
|
||||
var bp: Dictionary = save_manager.breakpoint_snapshot()
|
||||
confirm_dialog.open("已有未完冒险(第 %d 关)——开新冒险将覆盖旧断点" % maxi(1, int(bp.get("level_index", 1))),
|
||||
"开新冒险", "取消")
|
||||
return
|
||||
if save_manager != null:
|
||||
save_manager.clear_breakpoint()
|
||||
save_manager.write_to_disk()
|
||||
_lv_start_armed = false
|
||||
_start_overlay.visible = false
|
||||
_start_adventure()
|
||||
|
||||
|
||||
func _reset_lv_confirm() -> void:
|
||||
_lv_start_armed = false
|
||||
if _lvbtn != null:
|
||||
_lvbtn.text = "▶ 开始冒险(三关连探:地精洞窟 → 幽暗地域 → 灰矮人矿城)"
|
||||
func _on_confirm_new_adventure() -> void:
|
||||
confirm_dialog.close()
|
||||
if save_manager != null:
|
||||
save_manager.clear_breakpoint() # 提交即弃旧断点(覆盖语义对盘面即时生效)
|
||||
save_manager.write_to_disk()
|
||||
_start_overlay.visible = false
|
||||
_start_adventure()
|
||||
|
||||
|
||||
# 继续上局按钮可见性 = 断点在档态(迭代 8 卡②——启动读盘后与每次回开始菜单刷新;确认态随面复位)
|
||||
func _on_confirm_cancelled() -> void:
|
||||
confirm_dialog.close() # 回开始菜单(无状态变更)
|
||||
|
||||
|
||||
# 退出游戏(二轮修改批 D1——一级菜单入口;设置即时落盘后退出)
|
||||
func _quit_game() -> void:
|
||||
if settings_store != null:
|
||||
settings_store.save_settings()
|
||||
get_tree().quit()
|
||||
|
||||
|
||||
# 继续上局按钮可见性 = 断点在档态(迭代 8 卡②——启动读盘后与每次回开始菜单刷新)
|
||||
func _refresh_resume_button() -> void:
|
||||
if _resume_btn == null or save_manager == null:
|
||||
return
|
||||
@@ -287,7 +299,6 @@ func _refresh_resume_button() -> void:
|
||||
if has:
|
||||
var bp: Dictionary = save_manager.breakpoint_snapshot()
|
||||
_resume_btn.text = "▶ 继续上局(第 %d 关 · 自最近停点恢复)" % maxi(1, int(bp.get("level_index", 1)))
|
||||
_reset_lv_confirm()
|
||||
|
||||
|
||||
# 继续上局(迭代 8 卡②——卡① resume_adventure 的消费入口):断点重建至最近停点
|
||||
|
||||
@@ -142,8 +142,11 @@ static func build_start_overlay(host: Control, db = null) -> Dictionary:
|
||||
box.add_child(dbgbtn)
|
||||
var campbtn := UiKit.button("营地 · 永久强化(钥石换永久属性——跨局成长账本)") # 元进度实现批——主菜单营地入口(双入口框架的主菜单一侧)
|
||||
box.add_child(campbtn)
|
||||
var settingsbtn := UiKit.button("设置(音量 / 全屏 / 减动效 / 退出游戏)") # 迭代 8 卡④——最小设置面入口
|
||||
var settingsbtn := UiKit.button("设置(音量 / 全屏 / 减动效)") # 迭代 8 卡④——最小设置面入口
|
||||
box.add_child(settingsbtn)
|
||||
# 二轮修改批 D1(2026-09-29 用户目检裁决):退出游戏与设置同层并行——只在一级菜单出现
|
||||
var quitbtn := UiKit.button("退出游戏")
|
||||
box.add_child(quitbtn)
|
||||
|
||||
# 玩法帮助文案(表值驱动——2026-09-16 AP 压速批遗留硬编码 8 随手修正;护甲等级掷点批同步"减伤"→"护甲强化")
|
||||
var help_text := "玩法:每轮 %d AP——挖开(1AP)/插旗(1AP)/移动(免费)/连锁(免费)。\n每个非封锁格都藏一种格面资源(增伤/护甲强化/回血/爆裂/削弱)。开安全格、标中雷 = 正向兑付;\n开雷格、标错安全格 = 负向兑付——全部在轮末结算逐行兑现;吃掷点的基础攻击按护甲等级判定,无 miss、最低保底 1 点。\n停手:剩余 AP 转存 RAP;弃图刷新:RAP−%d 当场换图继续挖(每轮剩 %d 次)。\n敌人全灭胜、主角倒下负。悬停可看三态光标与可挖域微光。" % [
|
||||
@@ -154,7 +157,7 @@ static func build_start_overlay(host: Control, db = null) -> Dictionary:
|
||||
|
||||
return {"overlay": overlay, "box": box, "seed_edit": seed_edit,
|
||||
"lvbtn": lvbtn, "resumebtn": resumebtn, "tunebtn": tunebtn, "dbgbtn": dbgbtn,
|
||||
"campbtn": campbtn, "settingsbtn": settingsbtn}
|
||||
"campbtn": campbtn, "settingsbtn": settingsbtn, "quitbtn": quitbtn}
|
||||
|
||||
|
||||
# 调试两层模式的层间过渡覆盖层(历史入口专用)。返回 {overlay, label, next_btn}——接线归组合根
|
||||
|
||||
@@ -23,6 +23,9 @@ var _board_rect := Rect2()
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
# 二轮修改批 B(2026-09-29 用户目检裁决):半透明浮层文字不可读 → 实底石板皮面板形态
|
||||
#(与营地/设置/图例同族)。半透明氛围 dim 保留(胜利暖纱/失败暮蓝),信息与按钮全部上板;
|
||||
# 金蜡封 = 面板头部静态徽记(原全屏坠落演出退役——落点被面板遮挡)。
|
||||
_dim = ColorRect.new()
|
||||
_dim.color = Color(COL_WARM, 0.0)
|
||||
_dim.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
@@ -30,33 +33,41 @@ func _init() -> void:
|
||||
var center := CenterContainer.new()
|
||||
center.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
_dim.add_child(center)
|
||||
var panel := PanelContainer.new()
|
||||
panel.add_theme_stylebox_override("panel", UiKit.panel_skinned(Vector4(16, 14, 16, 14)))
|
||||
center.add_child(panel)
|
||||
var box := VBoxContainer.new()
|
||||
box.custom_minimum_size = Vector2(520, 0)
|
||||
box.add_theme_constant_override("separation", 12)
|
||||
center.add_child(box)
|
||||
_verdict = UiKit.label("", 26, true)
|
||||
_verdict.add_theme_color_override("font_color", COL_WARM)
|
||||
panel.add_child(box)
|
||||
var header := HBoxContainer.new()
|
||||
header.add_theme_constant_override("separation", 12)
|
||||
header.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
box.add_child(header)
|
||||
_seal = Panel.new()
|
||||
_seal.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
var sb := UiKit.panel_flat(COL_GOLD, UiKit.GOLD_DEEP, 200, 4)
|
||||
_seal.add_theme_stylebox_override("panel", sb)
|
||||
_seal.custom_minimum_size = Vector2(34, 34)
|
||||
_seal.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
header.add_child(_seal)
|
||||
_verdict = UiKit.label("", 24, true)
|
||||
_verdict.add_theme_color_override("font_color", UiKit.INK_TITLE)
|
||||
_verdict.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
box.add_child(_verdict)
|
||||
_verdict.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
header.add_child(_verdict)
|
||||
_gp_line = UiKit.label("", 16, true)
|
||||
_gp_line.add_theme_color_override("font_color", UiKit.GOLD)
|
||||
_gp_line.add_theme_color_override("font_color", UiKit.INK_LABEL)
|
||||
_gp_line.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_gp_line.visible = false
|
||||
box.add_child(_gp_line)
|
||||
box.add_child(HSeparator.new())
|
||||
_review_btn = UiKit.button("明细回看")
|
||||
_review_btn.pressed.connect(_emit_review_pressed)
|
||||
box.add_child(_review_btn)
|
||||
_btn = UiKit.button("继续")
|
||||
_btn.pressed.connect(_emit_continue_pressed)
|
||||
box.add_child(_btn)
|
||||
# 金蜡封占位(胜利):圆形色块落于扫雷图区中央——位置由 set_board_rect 注入
|
||||
_seal = Panel.new()
|
||||
_seal.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
var sb := UiKit.panel_flat(COL_GOLD, UiKit.GOLD_DEEP, 200, 4)
|
||||
_seal.add_theme_stylebox_override("panel", sb)
|
||||
_seal.size = Vector2(72, 72)
|
||||
_seal.visible = false
|
||||
_seal.top_level = true
|
||||
add_child(_seal)
|
||||
visible = false
|
||||
|
||||
|
||||
@@ -66,14 +77,13 @@ func _init() -> void:
|
||||
func open_victory(verdict_line: String, continue_label: String, board_rect: Rect2, gp_summary: String = "") -> void:
|
||||
_dim.color = Color(COL_WARM, 0.28)
|
||||
_verdict.text = verdict_line
|
||||
_verdict.add_theme_color_override("font_color", UiKit.INK_ON_GOLD)
|
||||
_seal.visible = true # 胜利徽记(面板头部静态)
|
||||
_gp_line.text = gp_summary
|
||||
_gp_line.visible = gp_summary != ""
|
||||
_btn.text = continue_label
|
||||
_board_rect = board_rect
|
||||
visible = true
|
||||
_play_seal_fall()
|
||||
_play_crest_assemble() # 碎砖拼纹章(§2.4——样张 v2 冻结批 T3 终稿)
|
||||
_play_crest_assemble() # 碎砖拼纹章(§2.4——样张 v2 冻结批 T3 终稿;绕面板屏心环收)
|
||||
_play_flag_recall(0) # 胜利不放旗收回
|
||||
|
||||
|
||||
@@ -81,11 +91,10 @@ func open_defeat(verdict_line: String, continue_label: String, board_rect: Rect2
|
||||
# 明度不变的暮蓝色相氛围(全屏唯一暮蓝档——§2.5 最静一拍)
|
||||
_dim.color = Color(COL_DUSK, 0.45)
|
||||
_verdict.text = verdict_line
|
||||
_verdict.add_theme_color_override("font_color", COL_WARM)
|
||||
_gp_line.visible = false # GP 总量+增量归胜利总结结算(OQ14)——失败侧不呈现
|
||||
_board_rect = board_rect
|
||||
visible = true
|
||||
_seal.visible = false
|
||||
_seal.visible = false # 失败无徽记(暮蓝氛围)
|
||||
_play_dust_sadle() # 坐砖掸灰(§2.5——终稿)
|
||||
_play_flag_recall(8)
|
||||
|
||||
@@ -104,16 +113,8 @@ func verdict_text() -> String:
|
||||
return _verdict.text
|
||||
|
||||
|
||||
# 金蜡封自上落下弹跳定格于棋盘中央(§2.4 克制不狂欢——占位级)
|
||||
func _play_seal_fall() -> void:
|
||||
var target := _board_rect.get_center() - _seal.size * 0.5
|
||||
if _board_rect.size == Vector2.ZERO:
|
||||
target = get_viewport_rect().size * 0.5 - _seal.size * 0.5
|
||||
_seal.position = Vector2(target.x, -100.0)
|
||||
_seal.visible = true
|
||||
var tw := _seal.create_tween()
|
||||
tw.tween_property(_seal, "position:y", target.y - 26.0, UiKit.motion(0.42)).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
|
||||
tw.tween_property(_seal, "position:y", target.y, UiKit.motion(0.22)).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT)
|
||||
func _fx_center() -> Vector2:
|
||||
return get_viewport_rect().size * 0.5
|
||||
|
||||
|
||||
# 旗化光点收回(失败——插过的旗逐面化光点收回占位,§2.5)
|
||||
@@ -147,7 +148,7 @@ var _fx_flag_dots := 0
|
||||
func _play_crest_assemble() -> void:
|
||||
_clear_crest_bricks()
|
||||
_fx_crest_shards = 10
|
||||
var c := _board_rect.get_center() if _board_rect.size != Vector2.ZERO else get_viewport_rect().size * 0.5
|
||||
var c := _fx_center()
|
||||
for i in 10:
|
||||
var brick := ColorRect.new()
|
||||
brick.color = UiKit.BRICK if i % 2 == 0 else UiKit.FLOOR # 碎砖=砖面族色(掩尘/裸土——图底同源)
|
||||
@@ -167,7 +168,7 @@ func _play_crest_assemble() -> void:
|
||||
# 坐砖掸灰(失败 §2.5——暖灰尘絮自棋盘中带缓缓飘落,最静一拍的运动承载)
|
||||
func _play_dust_sadle() -> void:
|
||||
_fx_dust_motes = 8
|
||||
var base := _board_rect.get_center() if _board_rect.size != Vector2.ZERO else get_viewport_rect().size * 0.5
|
||||
var base := _fx_center()
|
||||
for i in 8:
|
||||
var mote := ColorRect.new()
|
||||
mote.color = Color(UiKit.WARM_FAINT, 0.85)
|
||||
|
||||
@@ -192,7 +192,9 @@ func _format_row(row: Dictionary, agg_count := -1) -> String:
|
||||
roll_txt += " · ×%d%%" % int(row.tier)
|
||||
roll_txt += "〕"
|
||||
var kill := " ⚔击杀!" if row.get("killed", false) else ""
|
||||
var body := "%s -%d%s%s%s%s" % [name_, v, roll_txt, tail, kill, suffix]
|
||||
# 二轮修改批 C(2026-09-29 用户目检——「每次结算标出的伤害数字不明显」):
|
||||
# 伤害值放大加色独立于行文(朱红大一号——数字即信息主角,非同字号色温微差)
|
||||
var body := "%s [color=#d9402a][size=17]-%d[/size][/color]%s%s%s%s" % [name_, v, roll_txt, tail, kill, suffix]
|
||||
var body_col := "#e07050" if row.get("killed", false) else ("#9a8a72" if v == 0 else "#e0a050")
|
||||
if bool(row.get("crit", false)):
|
||||
return prefix + _gold_frame(body) # nat 最大面暴击 = 金框高亮行
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# Date: 2026-09-29(迭代 8 二轮修改批 A——新冒险互斥确认弹窗化,用户目检裁决:
|
||||
# 按钮文字换面 → 实底确认弹窗「开新冒险 + 取消」)
|
||||
# 通用确认弹窗(实底石板皮面板,与营地/设置/图例同族视觉):open(text, confirm_label, cancel_label)
|
||||
# 双钮外发 confirmed/cancelled——语义装配归调用方,本类零业务触碰(纯视图边界规范 1.3)。
|
||||
class_name ConfirmDialog
|
||||
extends Control
|
||||
|
||||
signal confirmed
|
||||
signal cancelled
|
||||
|
||||
var _text: Label
|
||||
var _confirm_btn: Button
|
||||
var _cancel_btn: Button
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
var dim := ColorRect.new()
|
||||
dim.color = Color(UiKit.DIM, 0.55)
|
||||
dim.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
add_child(dim)
|
||||
var center := CenterContainer.new()
|
||||
center.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
dim.add_child(center)
|
||||
var panel := PanelContainer.new()
|
||||
panel.add_theme_stylebox_override("panel", UiKit.panel_skinned(Vector4(14, 12, 14, 12)))
|
||||
center.add_child(panel)
|
||||
var box := VBoxContainer.new()
|
||||
box.custom_minimum_size = Vector2(460, 0)
|
||||
box.add_theme_constant_override("separation", 12)
|
||||
panel.add_child(box)
|
||||
_text = UiKit.label("", 16, false)
|
||||
_text.add_theme_color_override("font_color", UiKit.INK_TITLE)
|
||||
_text.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
_text.custom_minimum_size = Vector2(430, 0)
|
||||
box.add_child(_text)
|
||||
box.add_child(HSeparator.new())
|
||||
var btn_row := HBoxContainer.new()
|
||||
btn_row.add_theme_constant_override("separation", 12)
|
||||
btn_row.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
box.add_child(btn_row)
|
||||
_cancel_btn = UiKit.button("取消")
|
||||
_cancel_btn.pressed.connect(_emit_cancelled)
|
||||
btn_row.add_child(_cancel_btn)
|
||||
_confirm_btn = UiKit.button("确认")
|
||||
_confirm_btn.pressed.connect(_emit_confirmed)
|
||||
btn_row.add_child(_confirm_btn)
|
||||
visible = false
|
||||
|
||||
|
||||
func open(text: String, confirm_label: String, cancel_label: String = "取消") -> void:
|
||||
_text.text = text
|
||||
_confirm_btn.text = confirm_label
|
||||
_cancel_btn.text = cancel_label
|
||||
visible = true
|
||||
|
||||
|
||||
func close() -> void:
|
||||
visible = false
|
||||
|
||||
|
||||
func is_open() -> bool:
|
||||
return visible
|
||||
|
||||
|
||||
func _emit_confirmed() -> void:
|
||||
confirmed.emit()
|
||||
|
||||
|
||||
func _emit_cancelled() -> void:
|
||||
cancelled.emit()
|
||||
@@ -0,0 +1 @@
|
||||
uid://dhe557khvoq3y
|
||||
@@ -1,6 +1,6 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# Date: 2026-09-29(迭代 8 卡④ 最小设置面)
|
||||
# 设置覆盖层(纯视图边界规范 1.3 同款):音量滑杆/全屏/减动效三件+退出游戏+返回。
|
||||
# 设置覆盖层(纯视图边界规范 1.3 同款):音量滑杆/全屏/减动效三件+返回(退出游戏已提级开始菜单)。
|
||||
# 生效与持久化全经 SettingsStore 单点(实时应用+即改即存);本类零核心触碰。
|
||||
# 减动效转正承载(测试调整板旧开关退役——设置面唯一入口,卡④ AC③)。
|
||||
# 探针接缝:retarget(store) = 隔离存档换注口(同 camp 换注先例);控件引用公有只读供断言。
|
||||
@@ -12,8 +12,8 @@ signal closed
|
||||
var _store
|
||||
var _volume: HSlider
|
||||
var _volume_val: Label
|
||||
var _fs_btn: CheckButton
|
||||
var _motion_btn: CheckButton
|
||||
var _fs_btn: Button
|
||||
var _motion_btn: Button
|
||||
|
||||
|
||||
func _init(store) -> void:
|
||||
@@ -65,22 +65,21 @@ func _build() -> void:
|
||||
_volume_val.custom_minimum_size = Vector2(60, 0)
|
||||
vol_row.add_child(_volume_val)
|
||||
|
||||
# 全屏(art-bible 1920 档缩放策略冲突条目挂起注记——现行视口恒等拉伸,全屏切换即窗口模式切换)
|
||||
_fs_btn = CheckButton.new()
|
||||
_fs_btn.text = "全屏"
|
||||
# 开关形态(二轮修改批 D2 2026-09-29 用户目检——原生 CheckButton 暗底不显眼,
|
||||
# 换 UiKit 按钮形态 toggle:文字「全屏:开/关」随态换面)
|
||||
_fs_btn = UiKit.button("全屏:关")
|
||||
_fs_btn.toggle_mode = true
|
||||
_fs_btn.toggled.connect(_on_fullscreen_toggled)
|
||||
box.add_child(_fs_btn)
|
||||
|
||||
# 减动效(battle.md §Transitions 承诺转正——时长减半,结算逐行兑现=信息载体不整体跳过)
|
||||
_motion_btn = CheckButton.new()
|
||||
_motion_btn.text = "减动效(动画时长减半——运动敏感/演示用)"
|
||||
_motion_btn = UiKit.button("减动效:关(动画时长减半——运动敏感/演示用)")
|
||||
_motion_btn.toggle_mode = true
|
||||
_motion_btn.toggled.connect(_on_motion_toggled)
|
||||
box.add_child(_motion_btn)
|
||||
|
||||
box.add_child(HSeparator.new())
|
||||
var quit_btn := UiKit.button("退出游戏")
|
||||
quit_btn.pressed.connect(_on_quit_pressed)
|
||||
box.add_child(quit_btn)
|
||||
# 退出游戏已提级开始菜单(D1——设置面不再承载,用户裁决「退出只在一级菜单出现」)
|
||||
var close_btn := UiKit.button("返回")
|
||||
close_btn.pressed.connect(_emit_closed)
|
||||
box.add_child(close_btn)
|
||||
@@ -90,7 +89,9 @@ func _sync() -> void:
|
||||
_volume.set_value_no_signal(roundf(_store.volume_linear * 100.0))
|
||||
_volume_val.text = "%d%%" % roundi(_store.volume_linear * 100.0)
|
||||
_fs_btn.set_pressed_no_signal(_store.fullscreen)
|
||||
_fs_btn.text = "全屏:%s" % ("开" if _store.fullscreen else "关")
|
||||
_motion_btn.set_pressed_no_signal(_store.reduced_motion)
|
||||
_motion_btn.text = "减动效:%s(动画时长减半——运动敏感/演示用)" % ("开" if _store.reduced_motion else "关")
|
||||
|
||||
|
||||
func _on_volume_changed(v: float) -> void:
|
||||
@@ -112,10 +113,5 @@ func _on_motion_toggled(on: bool) -> void:
|
||||
_store.save_settings()
|
||||
|
||||
|
||||
func _on_quit_pressed() -> void:
|
||||
_store.save_settings()
|
||||
get_tree().quit()
|
||||
|
||||
|
||||
func _emit_closed() -> void:
|
||||
closed.emit()
|
||||
@@ -100,7 +100,7 @@ func _ready() -> void:
|
||||
_problems.append("设置面未打开(点击路径)")
|
||||
else:
|
||||
# 减动效转正双态(卡④ AC③):开=0.5 引擎态即时生效+落盘持久;关=1.0 回常态
|
||||
var motion_btn: CheckButton = _find_checkbutton_by_text(main.settings_overlay, "减动效")
|
||||
var motion_btn: Button = _find_button_by_text(main.settings_overlay, "减动效") # 二轮 D2——开关已换 UiKit toggle 按钮形态
|
||||
if motion_btn == null:
|
||||
_problems.append("设置面减动效开关缺失")
|
||||
else:
|
||||
@@ -142,6 +142,11 @@ func _ready() -> void:
|
||||
var legacy_motion = _find_checkbutton_by_text(main.tune_panel, "减动效")
|
||||
if legacy_motion != null:
|
||||
_problems.append("调整板减动效旧入口未退役(设置面唯一入口失守——卡④ AC③)")
|
||||
# D1 断言(二轮):退出游戏只在一级菜单——开始菜单有、设置面无
|
||||
if _find_button_by_prefix(main._start_overlay, "退出游戏") == null:
|
||||
_problems.append("开始菜单缺退出游戏按钮(二轮 D1)")
|
||||
if _find_button_by_prefix(main.settings_overlay, "退出游戏") != null:
|
||||
_problems.append("设置面仍含退出游戏按钮(二轮 D1——只在一级菜单出现)")
|
||||
# 换回全新零档(营地购买态不泄入后续冒险段——确定性;档案残留下次段首清理兜底)
|
||||
for p0 in ["user://smoke_click_probe_reset.json", "user://smoke_click_probe_reset.json.tmp"]:
|
||||
if FileAccess.file_exists(p0):
|
||||
@@ -321,7 +326,7 @@ func _ready() -> void:
|
||||
_problems.append("断点段:续玩候选与中断前不一致(停点重建失准)")
|
||||
if not iso_chk.load_from_disk() or not iso_chk.has_breakpoint():
|
||||
_problems.append("断点段:续玩误清断点(只在三结局清)")
|
||||
# ③ 互斥二次确认(卡②③):断点在档时开新冒险首击=确认态、二击才提交
|
||||
# ③ 互斥确认弹窗(二轮修改批 A):断点在档点开始冒险 → 弹确认框;取消=回菜单;开新冒险=提交
|
||||
main._exit_level_screen()
|
||||
main._start_overlay.visible = true
|
||||
main.adventure = null
|
||||
@@ -329,13 +334,27 @@ func _ready() -> void:
|
||||
await get_tree().process_frame
|
||||
lv_btn.pressed.emit()
|
||||
await get_tree().process_frame
|
||||
if not main._start_overlay.visible or main.adventure != null:
|
||||
_problems.append("断点段:有断点首击即开新冒险(互斥二次确认失守卡②③)")
|
||||
if not main.confirm_dialog.is_open() or main.adventure != null:
|
||||
_problems.append("断点段:有断点点开始冒险未弹确认框(二轮 A 失守)")
|
||||
var cancel_btn: Button = _find_button_by_text(main.confirm_dialog, "取消")
|
||||
if cancel_btn == null:
|
||||
_problems.append("断点段:确认框取消按钮缺失")
|
||||
else:
|
||||
cancel_btn.pressed.emit()
|
||||
await get_tree().process_frame
|
||||
if main.confirm_dialog.is_open() or main.adventure != null or not main._start_overlay.visible:
|
||||
_problems.append("断点段:取消未回开始菜单(二轮 A)")
|
||||
lv_btn.pressed.emit()
|
||||
await get_tree().process_frame
|
||||
await get_tree().process_frame
|
||||
if main.adventure == null or main._start_overlay.visible:
|
||||
_problems.append("断点段:二次确认后未开新冒险")
|
||||
var confirm_btn: Button = _find_button_by_text(main.confirm_dialog, "开新冒险")
|
||||
if confirm_btn == null:
|
||||
_problems.append("断点段:确认框开新冒险按钮缺失")
|
||||
else:
|
||||
confirm_btn.pressed.emit()
|
||||
await get_tree().process_frame
|
||||
await get_tree().process_frame
|
||||
if main.adventure == null or main._start_overlay.visible or main.confirm_dialog.is_open():
|
||||
_problems.append("断点段:确认开新冒险后未开局(二轮 A)")
|
||||
print("[click_probe] 循环退出(done=%s budget=%s)问题=%d" % [
|
||||
str(_done), str(action_budget), _problems.size()])
|
||||
for p in _problems:
|
||||
@@ -526,6 +545,16 @@ func _find_button_by_prefix(root: Node, prefix: String) -> Button:
|
||||
return null
|
||||
|
||||
|
||||
func _find_button_by_text(root: Node, needle: String) -> Button:
|
||||
if root is Button and String(root.text).contains(needle):
|
||||
return root
|
||||
for child in root.get_children():
|
||||
var found := _find_button_by_text(child, needle)
|
||||
if found != null:
|
||||
return found
|
||||
return null
|
||||
|
||||
|
||||
func _find_checkbutton_by_text(root: Node, needle: String) -> CheckButton:
|
||||
if root is CheckButton and String(root.text).contains(needle):
|
||||
return root
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
uid://fjdvajc5ek85
|
||||
Reference in new issue
Block a user