feat(ui): 放弃入口界面呈现——选路停点挂放弃按钮(冒险模式开/单关直入口关,战斗中拒绝防御分支;用户拍板台账 119)

This commit is contained in:
DKChan committed 2026-09-21 14:31:03 +08:00
1 parent 5fd8d86da6
commit a569f1935d
3 files changed
+48 -2

No files matched your search

@@ -137,6 +137,7 @@ func _build_ui() -> void:
review_overlay.closed.connect(_on_modal_closed.bind(review_overlay))
node_overlay.continue_pressed.connect(_on_node_continue)
route_overlay.route_chosen.connect(_on_route_chosen)
route_overlay.abandon_requested.connect(_on_abandon_requested) # 放弃入口(2026-09-21 用户拍板——台账 119)
shop_overlay.buy_requested.connect(_on_shop_buy)
shop_overlay.leave_pressed.connect(_on_shop_leave)
_end_overlay.review_pressed.connect(_on_end_review)
@@ -223,6 +224,7 @@ func _start_full_level(level_index: int = 1) -> void:
runner.wallet_changed.connect(_on_wallet_changed)
_level_active = true
_adventure_mode = false
route_overlay.set_abandon_available(false) # 单关测试直入口无冒险可放弃(放弃语义对象 = 整局冒险)
_reset_run_scope()
log_view.clear()
var seed_val := _seed_value()
@@ -250,6 +252,7 @@ func _start_adventure() -> void:
adventure.adventure_finished.connect(_on_adventure_finished)
adventure.level_started.connect(_on_adventure_level_started)
_level_active = true
route_overlay.set_abandon_available(true) # 放弃入口挂选路停点(天然非战斗期——2026-09-21 用户拍板)
_reset_run_scope()
log_view.clear()
var seed_val := _seed_value()
@@ -311,7 +314,7 @@ func _on_level_finished(payload: Dictionary) -> void:
_level_active = false
var result: String = String(payload.get("result", ""))
settlement = null
route_overlay.visible = false # 终局兜底(选路口非 Boss 节点才有——防御性收层)
_close_modal(route_overlay) # 终局兜底(放弃入口新场景:选路层在开态——走模态栈恢复其遮挡面;未开过时 close 容错)
_sync_settlement_visuals() # → 全关
info_panel.set_status_cleared_feedback() # 状态槽全清可见反馈(增益状态×4④)
stage.gray_all_enemies() # 死亡兜底:站桩灰化残位(禁瞬消语义的战斗收尾面)
@@ -344,7 +347,7 @@ func _on_adventure_finished(summary: Dictionary) -> void:
_level_active = false
var result: String = String(summary.get("result", ""))
settlement = null
route_overlay.visible = false # 终局兜底(选路口非 Boss 节点才有——防御性收层)
_close_modal(route_overlay) # 终局兜底(放弃入口新场景:选路层在开态——走模态栈恢复其遮挡面;未开过时 close 容错)
_sync_settlement_visuals() # → 全关
info_panel.set_status_cleared_feedback() # 状态槽全清可见反馈(增益状态×4④)
stage.gray_all_enemies() # 死亡兜底:站桩灰化残位(禁瞬消语义的战斗收尾面)
@@ -608,6 +611,17 @@ func _on_route_chosen(node_id: int) -> void:
push_error("[组合根] 选路被拒(编号 %d 不在候选)" % node_id)
func _on_abandon_requested() -> void:
# 放弃入口(2026-09-21 用户拍板「放弃接口也要有」——推翻 冒险结构.md「MVP 无界面入口」后置条款;
# 入口挂选路停点 = 天然非战斗期,拒绝分支仅防御在案):受理 → 冒险放弃结算(同失败型,
# 已获大奖励不追回)→ adventure_finished 同步到达 → 终局面收层
if not _adventure_mode or adventure == null:
return
if not adventure.abandon():
logger.log_ux("ux_reject", {"source": "abandon", "sub_reason": "battle_in_flight"})
board_zone.toast.show_toast("战斗进行中——无法放弃", "warn")
# ---- 商店覆盖层与 GP 钱包(GP+商店房实施批——写调用唯一归组合根)----
func _on_shop_buy(product_id: String) -> void:
@@ -5,10 +5,14 @@
# 唯一前进通道 = 点候选按钮 → route_chosen(node_id) → 组合根转 runner.pick_next_node。
# 高内聚边界:只读 runner 成文出口(nodes()/visited_ids()/node_index/next_candidate_ids())做渲染,
# 无任何写面;图形为程序化占位质量(占位纪律)。
# 放弃入口(2026-09-21 用户拍板「放弃接口也要有」——台账 119;推翻 冒险结构.md「MVP 无界面入口」
# 后置条款):选路停点 = 天然非战斗期(接口契约:战斗中放弃一律拒绝),按钮常驻本层底部;
# 可见性归组合根(冒险模式开、单关测试直入口关——放弃的语义对象是"整局冒险")。
class_name RouteOverlay
extends Control
signal route_chosen(node_id: int)
signal abandon_requested
const COL_ROOM_DONE := UiKit.GOLD_DIM # 已到——暗金
const COL_ROOM_CURRENT := UiKit.GOLD # 当前——奖励金
@@ -21,6 +25,7 @@ const NODE_LABELS := {"battle": "战", "reward": "赏", "rest": "疗", "boss": "
var _runner = null
var _btn_box: VBoxContainer
var _title: Label
var abandon_btn: Button # 放弃入口(可见性归组合根 set_abandon_available——冒险模式开/单关测试直入口关)
func _init() -> void:
@@ -45,9 +50,23 @@ func _init() -> void:
_btn_box = VBoxContainer.new()
_btn_box.add_theme_constant_override("separation", 6)
box.add_child(_btn_box)
abandon_btn = UiKit.button("🏳 放弃冒险(同失败结算——已获大奖励保留)")
abandon_btn.add_theme_color_override("font_color", UiKit.FLAG_RED)
abandon_btn.pressed.connect(_emit_abandon)
abandon_btn.visible = false
box.add_child(abandon_btn)
visible = false
# 放弃入口可见性(组合根在冒险启动/单关直入口启动时切换——语义对象 = 整局冒险)
func set_abandon_available(v: bool) -> void:
abandon_btn.visible = v
func _emit_abandon() -> void:
abandon_requested.emit()
# 打开选路口(cands = 候选节点引用数组;runner 只读用于整图渲染)
func open_choices(cands: Array, runner) -> void:
_runner = runner
@@ -13,10 +13,23 @@ func _ready() -> void:
var main = load("res://presentation/main.tscn").instantiate()
add_child(main)
await get_tree().process_frame
# ---- 放弃入口(2026-09-21 用户拍板——台账 119):默认隐藏(单关测试直入口无冒险可放弃)----
if main.route_overlay.abandon_btn == null or main.route_overlay.abandon_btn.visible:
print("[ui_probe] FAIL — 放弃按钮默认应隐藏(单关测试直入口关)")
get_tree().quit(1)
return
main._start_full_level()
await get_tree().process_frame
await get_tree().process_frame
var problems: Array = []
# ---- 放弃入口·冒险模式可见 + 战斗中按下被拒(真实按钮路径——入口挂选路停点,战斗中拒绝为防御分支)----
if main.route_overlay.abandon_btn == null or not main.route_overlay.abandon_btn.visible:
problems.append("冒险模式放弃按钮未开放(选路停点入口在案)")
else:
main.route_overlay.abandon_btn.pressed.emit()
await get_tree().process_frame
if main.adventure == null or String(main.adventure.state) != "running":
problems.append("首战中放弃未被拒(战斗域单事务在飞——state 应保持 running)")
# ---- 既有断言(回归基线)----
if main.board_view._cells.is_empty():
problems.append("棋盘格未生成(cells=0)")