按 code-conventions §1.4.1 第三轮定稿执行:core 22+schemas 18+presentation 根 14+views 28,全部头注 #→##、删日期/变更叙事/GDD 与架构反向链接/字段与域清单/机制描述,保留职责摘要+真实使用约束(防事故禁令/单一入口/信号契约每信号一行)。main.gd 31→5 行、save_manager 45→5 行、adventure_runner 37→5 行为最大单件。子代理分模块执行(波一 core+schemas、波二 presentation+views,并发≤2)。验收=tools/verify_comment_only_change.py 逐字节校验(82 文件头注区外逐行一致=零行为变更)+audit_file_headers 全绿;纯注释批免冒烟(先例 5843270)
137 lines
5.9 KiB
GDScript
137 lines
5.9 KiB
GDScript
## VERTICAL SLICE - NOT FOR PRODUCTION
|
|
## 局内状态面板·只读:钥石余额与进度概览(入口=两屏角标,本类不含入口)。
|
|
## 账面快照由组合根 open_status 喂入;进出零动效直开直关;构成件全部经 UiKit 工厂产出——禁裸色值自建样式。
|
|
class_name StatusPanel
|
|
extends Control
|
|
|
|
signal closed
|
|
|
|
var _balance_badge: UiKit.KeystoneBadge # 钥石余额徽(badge 工厂件——Q10 甲)
|
|
var _workshop_holder: VBoxContainer
|
|
var _tree_label: Label
|
|
|
|
|
|
func _init() -> void:
|
|
var shell: Dictionary[Variant, Variant] = UiKit.modal_shell(self, Color(UiKit.DIM, 0.55), Vector2(560, 0), 10, true,
|
|
UiKit.panel_skinned(Vector4(20, 16, 20, 16))) # 石板皮(缺位回退数据板——同设置面先例)
|
|
var box: VBoxContainer = shell.box
|
|
|
|
var title := UiKit.label("状态",UiKit.FS_TITLE, true, UiKit.INK_TITLE)
|
|
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
box.add_child(title)
|
|
var hint := UiKit.label("查看本局钥石与永久强化进度(只读——购买请回营地)",UiKit.FS_HINT, false, UiKit.INK_HINT)
|
|
hint.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
box.add_child(hint)
|
|
|
|
# 钥石余额行(badge 工厂件——与营地顶栏钥石徽同形制)
|
|
var bal_row := HBoxContainer.new()
|
|
bal_row.alignment = BoxContainer.ALIGNMENT_CENTER
|
|
box.add_child(bal_row)
|
|
_balance_badge = UiKit.keystone_badge("钥石 0")
|
|
bal_row.add_child(_balance_badge)
|
|
|
|
box.add_child(HSeparator.new())
|
|
_section_head(box, "道具工坊 · 解锁态")
|
|
_workshop_holder = _section_holder(box)
|
|
|
|
_section_head(box, "天赋树 · 已购概览")
|
|
_tree_label = UiKit.label("",UiKit.FS_HINT, false, UiKit.INK_LABEL)
|
|
_tree_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
|
box.add_child(_tree_label)
|
|
|
|
box.add_child(HSeparator.new())
|
|
var close_row := HBoxContainer.new()
|
|
close_row.alignment = BoxContainer.ALIGNMENT_CENTER
|
|
box.add_child(close_row)
|
|
var close_btn := UiKit.button("继续", 90.0) # 紧凑返回钮(设置面先例形制;文案=代拍板白名单「继续」级措辞)
|
|
close_btn.tooltip_text = "关闭状态面板,继续当前冒险(本层只读,不发生任何购买或修改)"
|
|
close_btn.pressed.connect(_emit_closed)
|
|
close_row.add_child(close_btn)
|
|
visible = false # 显式初始化——不靠树序巧合(缺陷⑤家族纪律)
|
|
|
|
|
|
# 分组小节头(营地屏分组同构——fs 副标题档深墨)
|
|
func _section_head(box: VBoxContainer, text: String) -> void:
|
|
var head := UiKit.label(text,UiKit.FS_BODY, true, UiKit.INK_LABEL)
|
|
box.add_child(head)
|
|
|
|
|
|
func _section_holder(box: VBoxContainer) -> VBoxContainer:
|
|
var holder := VBoxContainer.new()
|
|
holder.add_theme_constant_override("separation", 4)
|
|
box.add_child(holder)
|
|
return holder
|
|
|
|
|
|
# ---- 开层(组合根唯一调用口——快照随开随建,R4 单次开层生命周期口径)----
|
|
|
|
func open_status(data: Dictionary) -> void:
|
|
_balance_badge.set_text("钥石 %d" % int(data.get("balance", 0)))
|
|
_rebuild_workshop(data)
|
|
_rebuild_tree(data)
|
|
visible = true
|
|
|
|
|
|
# 道具工坊六行(解锁态文案与营地柜台同口径——退役/封存/已解锁/未解锁;进度=解锁判定量读数)
|
|
# 秘宝匣 12 行只读概览(迭代 22 T2 换代——旧工坊六行退役;数据源=treasure_shop_status 投影,
|
|
# 解锁态文案与营地柜台同口径;进度列=解锁混合制三形态:钥石价/条件进度拼接/已入手)
|
|
func _rebuild_workshop(data: Dictionary) -> void:
|
|
for c in _workshop_holder.get_children():
|
|
c.queue_free()
|
|
for row in (data.get("workshop", []) as Array):
|
|
var line := HBoxContainer.new()
|
|
line.add_theme_constant_override("separation", 8)
|
|
var name_l := UiKit.label(String(row.get("display_name", "")),UiKit.FS_HINT, true, UiKit.INK)
|
|
name_l.custom_minimum_size = Vector2(120, 0)
|
|
name_l.clip_text = true
|
|
name_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
|
line.add_child(name_l)
|
|
var unlocked := bool(row.get("unlocked", false))
|
|
var prog_text := "已入手"
|
|
if not unlocked:
|
|
if String(row.get("mode", "")) == "keystone":
|
|
prog_text = "钥石 %d" % int(row.get("price", 0))
|
|
else:
|
|
var parts: Array[String] = []
|
|
for req_v in (row.get("reqs", []) as Array):
|
|
var req: Dictionary[Variant, Variant] = req_v as Dictionary
|
|
var lbl := String(UiKit.TREASURE_REQ_LABELS.get(String(req.get("key", "")), "条件"))
|
|
parts.append("%s %d/%d" % [lbl, int(req.get("progress", 0)), int(req.get("threshold", 0))])
|
|
prog_text = "、".join(parts)
|
|
var prog_l := UiKit.label(prog_text,UiKit.FS_HINT, false, UiKit.INK_HINT)
|
|
prog_l.custom_minimum_size = Vector2(150, 0)
|
|
prog_l.clip_text = true
|
|
prog_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
|
line.add_child(prog_l)
|
|
var st_l := UiKit.label("已解锁" if unlocked else "未解锁",UiKit.FS_HINT, true, UiKit.INK_LABEL)
|
|
st_l.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
line.add_child(st_l)
|
|
_workshop_holder.add_child(line)
|
|
|
|
|
|
# 天赋树已购概览(单条聚合文案——已购节点等级 + Fork 组激活侧;零已购=空态句)
|
|
func _rebuild_tree(data: Dictionary) -> void:
|
|
var owned: Array[String] = []
|
|
for row in (data.get("tree", []) as Array):
|
|
var lvl := int(row.get("level", 0))
|
|
if lvl > 0:
|
|
owned.append("%s Lv%d/%d" % [String(row.get("display_name", "")), lvl, int(row.get("cap", 1))])
|
|
for fg in (data.get("fork_groups", []) as Array):
|
|
var active := String(fg.get("active_side", ""))
|
|
if active == "":
|
|
continue
|
|
var side_name := active
|
|
for sd in (fg.get("sides", []) as Array):
|
|
if String(sd.get("side", "")) == active:
|
|
side_name = String(sd.get("display_name", active))
|
|
break
|
|
owned.append("%s·激活 %s" % [String(fg.get("display_name", "")), side_name])
|
|
if owned.is_empty():
|
|
_tree_label.text = "尚未购买任何节点(天赋树在营地主柜台)"
|
|
else:
|
|
_tree_label.text = "已购 %d 项:%s" % [owned.size(), " · ".join(owned)]
|
|
|
|
|
|
func _emit_closed() -> void:
|
|
closed.emit()
|