Files
gplan-2/game/presentation/views/bonus_pick_overlay.gd
T
DKChan a6a2bf885e 迭代11第①批:魔法道具同调实施批 T0-T10 全落(重闸 645/0 + MC off 逐位 PASS)
- T1 表与schema:attunement_growth.tres 谓词表(m1/m2/m3+Σgrant≤slot_cap 校验+slots() 求值口径)+道具表扩列(form/charges/slot_cost/unlock_requires/effective_rounds/charge_n+effect_kinds 九kind+KEY_WHITELIST 零裸flat护栏)+七同调行
- T2 save v4(boss_kill_count 收束入账+attunement_equipped+attune_refresh_level+断点 attunement_charges+迁移链 v3→v4)
- T3 Attunement 求值服务(纯函数零 await 零 RNG)
- T4 营地装配覆盖层(工坊扩容程序占位+Y 升级行 attune_refresh_upgrade 行族)
- T5 被动六件接线+装配注入链+刷新 X/Y 双源(BonusPickOverlay 刷新钮,autoplay 默认不刷)
- T6 掘进蓄能全链+摆钟能力面(骑库存面差额注入+断点充能键);炸格 P5 甲影响评估破面大→用户裁拆后批,blast_kit deferred 留位
- T7 退役面五件(BONUS_IDS 除名 aux_item+transitional_sync_slots 过渡键退役=迭代10欠账③清偿+授予路/四容量闸拆除+nest_pendulum 换装 active_charged)
- T8 冒烟六新断言(645/0)+MC attune 开关+贪心画像分层 off/on 各 N=60 双策略(on 画像功率显著带平移归调参批;off 新锚=对拍正主留盘主区 sim-data,81000 降批入口基准)
- T9 连带修订九件(魔法道具定位重写/元进度v1.6/地图战斗资源v0.16/行动经济v0.7/05不做v1.3/关卡节点地图v1.4/node-reward v2.2/registry 三处/06 收口+炸格拆后批新条)
- T10 重闸全绿:冒烟 645/0+熵增 PASS+doc 三闸零新增+MC off 复跑同种子逐位一致 PASS;出口人闸后移迭代 12(用户 2026-10-03 令)
2026-10-03 15:41:30 +08:00

173 lines
7.3 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
# Date: 2026-10-01(迭代 10 奖励重构批——level-clear.md v2 三选一选择面承载)
# 提升三选一覆盖层(模态):非末关通关的选择停点呈现——部分回血反馈 + 三卡点选 + 确认兑付 +
# 同调位替换子交互。高内聚边界:文案拼装归 Narrator(组合根喂入),选择意图经信号外发;
# 视图零核心引用。交互范式 = node_overlay choice_box 按钮族 + 选路两段式(点选→确认)复用,零新原语。
# 状态机:pick(三卡点选→确认)→ [replace(满位 N+1 选 N)] → result(兑付反馈→继续)。
class_name BonusPickOverlay
extends Control
signal pick_confirmed(item_id: String)
signal replace_chosen(discard_index: int) # -1 = 放弃新件不获取
signal continue_pressed
signal refresh_requested # 三选一刷新意图(迭代 11 第①批 T5b——P1 甲 X/Y 双源;重抽归组合根)
var _label: Label
var _choice_box: HBoxContainer # 三卡按钮区(pick 态)
var _replace_box: VBoxContainer # 替换子面板(replace 态)
var _confirm_btn: Button # 确认钮(点选后点亮——两段式第二拍)
var _continue_btn: Button # 继续钮(兑付反馈态唯一出口)
var _refresh_btn: Button # 刷新钮(迭代 11 第①批 T5b——余量>0 才显示)
var _refresh_l: Label # 刷新余量读数(X 优先 + Y 冒险池)
var _refresh_allowance := 0 # 组合根投喂余量(本视图零核心引用)
var _selected := "" # 点选暂存(确认前可改选)
var _header := "" # 停点头部文案(选择态保持显示)
var _card_meta: Array = [] # open_pick 缓存 [{id, text}]——高亮还原读面
func _init() -> void:
var box: VBoxContainer = UiKit.modal_shell(self, Color(0, 0, 0, 0.6)).box
_label = UiKit.label("", 20, true, UiKit.WARM)
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(_label)
_choice_box = HBoxContainer.new()
_choice_box.add_theme_constant_override("separation", 12)
_choice_box.alignment = BoxContainer.ALIGNMENT_CENTER
box.add_child(_choice_box)
_confirm_btn = UiKit.button("确认选择")
_confirm_btn.pressed.connect(_on_confirm_pressed)
_confirm_btn.visible = false
box.add_child(_confirm_btn)
# 三选一刷新面(迭代 11 第①批 T5b——程序占位用 UiKit 既有件;余量 0 = 隐藏)
_refresh_btn = UiKit.button("刷新候选")
_refresh_btn.pressed.connect(_emit_refresh_requested)
_refresh_btn.visible = false
box.add_child(_refresh_btn)
_refresh_l = UiKit.label("", 13, false, UiKit.STONE)
box.add_child(_refresh_l)
_replace_box = VBoxContainer.new()
_replace_box.add_theme_constant_override("separation", 8)
_replace_box.alignment = BoxContainer.ALIGNMENT_CENTER
box.add_child(_replace_box)
_continue_btn = UiKit.button("继续")
_continue_btn.pressed.connect(_emit_continue_pressed)
_continue_btn.visible = false
box.add_child(_continue_btn)
visible = false
# 选择态:header = 停点头部(回血+钥石增量行,Narrator 装配);cards = [{id, text}]
#(组合根组装——视图纯呈现)。确认前可改选;确认经 pick_confirmed 外发。
func open_pick(header: String, cards: Array) -> void:
_header = header
_label.text = header
_selected = ""
_card_meta = (cards as Array).duplicate(true)
for c in _choice_box.get_children():
c.queue_free()
for ch in cards:
var cid := String(ch.get("id", ""))
var btn := UiKit.button(String(ch.get("text", "")))
btn.custom_minimum_size = Vector2(170, 88)
btn.pressed.connect(_select_card.bind(cid)) # 具名方法 bind(仓内惯例——内联 lambda 退役)
_choice_box.add_child(btn)
_choice_box.visible = true
_confirm_btn.visible = false
_replace_box.visible = false
_continue_btn.visible = false
_refresh_btn.visible = false # 刷新余量随 set_refresh_info 投喂后现形(open 先归零防残留)
_refresh_l.text = ""
visible = true
# 三选一刷新余量投喂(组合根读 adventure.attune_refresh_left()——0 = 刷新面隐藏)
func set_refresh_info(allowance: int) -> void:
_refresh_allowance = maxi(0, int(allowance))
_refresh_btn.visible = _refresh_allowance > 0
_refresh_l.text = "可刷新 %d 次(装配刷新件 X 优先消耗,Y 为冒险池)" % _refresh_allowance if _refresh_allowance > 0 else ""
func _emit_refresh_requested() -> void:
refresh_requested.emit()
func _select_card(id: String) -> void:
_selected = id
for i in _choice_box.get_child_count():
var btn := _choice_box.get_child(i) as Button
var meta: Dictionary = _card_meta[i] if i < _card_meta.size() else {}
var base_text := String(meta.get("text", ""))
btn.text = ("✓ " + base_text) if String(meta.get("id", "")) == id else base_text
_confirm_btn.visible = true
func _on_confirm_pressed() -> void:
if _selected != "":
pick_confirmed.emit(_selected)
# 探针/测试复用:以真实按钮路径触发点选、确认与继续(树序遮挡纪律——断言走真实信号路径)
func press_card(index: int) -> void:
if index >= 0 and index < _choice_box.get_child_count():
(_choice_box.get_child(index) as Button).pressed.emit()
func press_confirm() -> void:
_confirm_btn.pressed.emit()
func press_continue() -> void:
_continue_btn.pressed.emit()
func selected_id() -> String:
return _selected
# 兑付反馈态(bonus_resolved 到达——结果行追加在头部之后;唯一出口 = 继续)
func show_result(text: String) -> void:
_label.text = _header + "\n" + text
_choice_box.visible = false
_confirm_btn.visible = false
_replace_box.visible = false
_continue_btn.visible = true
visible = true
# 同调位替换子态(aux_replace_presented 到达):items = [{index, item_id, display_name}](组合根
# 喂显示名)。两路出口:丢旧收新(逐件钮)/ 放弃新件——终态恒 ≤ 同调位由核心受理面保证。
func open_replace(items: Array, incoming_name: String, holding: int, slots: int) -> void:
_label.text = "同调位已满(%d/%d)——收下「%s」需丢弃一件已有道具,或放弃新件" % [holding, slots, incoming_name]
for c in _replace_box.get_children():
c.queue_free()
for it in items:
var tag: int = int(it.get("index", it.get("handle", -1))) # 通关渠道=携带序号 / 节点渠道=库存句柄(核心分发面裁决)
var btn := UiKit.button("丢弃「%s」换新" % String(it.get("display_name", it.get("item_id", ""))))
btn.pressed.connect(_emit_replace_chosen.bind(tag))
_replace_box.add_child(btn)
var decline := UiKit.button("放弃新件(不获取)")
decline.pressed.connect(_emit_replace_chosen.bind(-1))
_replace_box.add_child(decline)
_choice_box.visible = false
_confirm_btn.visible = false
_replace_box.visible = true
_continue_btn.visible = false
visible = true
# 收屏(组合根在 continue_pressed 处理毕调——推进下一关同拍)
func close_pick() -> void:
_choice_box.visible = false
_replace_box.visible = false
_continue_btn.visible = false
_confirm_btn.visible = false
visible = false
func _emit_continue_pressed() -> void:
continue_pressed.emit()
func _emit_replace_chosen(tag: int) -> void:
replace_chosen.emit(tag)