iter(36卡③): 状态面板瘦身——八键投影换代+本局信息面板三段新装两段退役+两角标tooltip换代+断言面换代(theme投影族九断言手拼夹具+探针真实入口三断言对拍独立oracle);变异验证按用户P0禁令零执行(正向验收测试照跑)
This commit is contained in:
1 parent
e74656b228
commit
477a73e763
6 files changed
+152
-140
No files matched your search
@@ -1068,18 +1068,34 @@ func _on_settings_closed() -> void:
|
||||
|
||||
# ---- 局内状态面板·只读(入口角标在两屏装配段;开合与数据喂入归组合根)----
|
||||
|
||||
# 状态面板快照投影(数据只读同源:每次开层实时读 MetaProgression 访问器现值拼装——
|
||||
# 状态面板快照投影(数据只读同源:每次开层实时读访问器现值拼装——
|
||||
# 快照仅服务单次开层生命周期(open_status 重建各行),跨开层零持有;零写调用。
|
||||
# 状态面板零锻造段)
|
||||
# 八键换代(迭代 36 卡③):跨关解锁概览退役(营地/生涯承载)——只留本局信息;
|
||||
# ledger 直取下标(键缺失=致命,禁 .get 缺省留门——fail-fast 红线);禁 null 守卫软回退
|
||||
# (两入口开层时 runner 恒在役——状态面板卡 F3 证据链)
|
||||
func _status_data() -> Dictionary:
|
||||
return {
|
||||
"balance": meta.keystone_balance(),
|
||||
"workshop": meta.treasure_shop_status(), # 秘宝匣 12 件解锁投影
|
||||
"tree": meta.tree_camp_rows(),
|
||||
"fork_groups": meta.tree_fork_groups(),
|
||||
"hero_hp": int(run_scope.runner.hero_hp), # LevelRunner 属性面(_ledger 直取下标——键缺失=致命)
|
||||
"max_hp": run_scope.runner.effective_max_hp(),
|
||||
"atk": run_scope.runner.effective_atk(),
|
||||
"ac": run_scope.runner.effective_ac(),
|
||||
"gp": int(run_scope.runner.gp),
|
||||
"curios": _status_curios(),
|
||||
"feats": HudPresenter.feat_holdings_lines(db, run_scope.runner.feats_held()),
|
||||
}
|
||||
|
||||
|
||||
# 秘宝行映射(inventory_projection 现役投影逐行取 name/used 两键——受理序沿库存投影;
|
||||
# 禁第二份投影:件名换算已在 inventory_projection 收口,此处只做键裁剪)
|
||||
func _status_curios() -> Array:
|
||||
var out: Array = []
|
||||
for row in (_treasure_ui.inventory_projection() as Array):
|
||||
var r: Dictionary = row
|
||||
out.append({"name": String(r.get("name", "")), "used": bool(r.get("used", false))})
|
||||
return out
|
||||
|
||||
|
||||
func _open_status_panel() -> void:
|
||||
_open_modal(status_panel) # 模态栈单口(开层前排空排播队列——既有层同款行为,目检确认项)
|
||||
status_panel.open_status(_status_data())
|
||||
|
||||
@@ -55,7 +55,7 @@ func _init() -> void:
|
||||
corner.add_theme_constant_override("separation", 8)
|
||||
status_badge = UiKit.button("状态", 0.0) # 角落小件豁免宽度基准
|
||||
status_badge.add_theme_font_size_override("font_size", UiKit.FS_HINT)
|
||||
status_badge.tooltip_text = "查看钥石与永久强化进度(只读)"
|
||||
status_badge.tooltip_text = "查看本局冒险进度(只读)"
|
||||
status_badge.visible = false # 显式初始化——非对局期不误现(可见性归组合根同步)
|
||||
corner.add_child(status_badge)
|
||||
corner_wrap.add_child(corner)
|
||||
|
||||
@@ -104,7 +104,7 @@ func _init() -> void:
|
||||
# 信号连接归组合根(视图零连接))
|
||||
status_badge = UiKit.button("状态", 0.0)
|
||||
status_badge.add_theme_font_size_override("font_size", UiKit.FS_HINT)
|
||||
status_badge.tooltip_text = "查看钥石与永久强化进度(只读)"
|
||||
status_badge.tooltip_text = "查看本局冒险进度(只读)"
|
||||
status_badge.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
top.add_child(status_badge)
|
||||
_title = UiKit.label(TITLE_FORK,UiKit.FS_SUB, true, UiKit.WARM)
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
## VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
## 局内状态面板·只读:钥石余额与进度概览(入口=两屏角标,本类不含入口)。
|
||||
## 局内状态面板·只读:本局信息面板(钥石总量+本局四件:带的秘宝/已获专长/当前属性/现有 GP)。
|
||||
## 跨关解锁概览(秘宝匣解锁态/天赋树已购)由营地/生涯承载——本面板不再镜像(迭代 36 卡③)。
|
||||
## 账面快照由组合根 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
|
||||
var _balance_badge: UiKit.KeystoneBadge # 钥石总量徽(badge 工厂件——Q10 甲)
|
||||
var _attrs_label: Label
|
||||
var _curios_label: Label
|
||||
var _feats_label: Label
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
@@ -19,11 +21,11 @@ func _init() -> void:
|
||||
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)
|
||||
var hint := UiKit.label("查看本局冒险进度(只读)",UiKit.FS_HINT, false, UiKit.INK_HINT)
|
||||
hint.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
box.add_child(hint)
|
||||
|
||||
# 钥石余额行(badge 工厂件——与营地顶栏钥石徽同形制)
|
||||
# 钥石总量行(badge 工厂件——与营地顶栏钥石徽同形制)
|
||||
var bal_row := HBoxContainer.new()
|
||||
bal_row.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
box.add_child(bal_row)
|
||||
@@ -31,13 +33,20 @@ func _init() -> void:
|
||||
bal_row.add_child(_balance_badge)
|
||||
|
||||
box.add_child(HSeparator.new())
|
||||
_section_head(box, "道具工坊 · 解锁态")
|
||||
_workshop_holder = _section_holder(box)
|
||||
_section_head(box, "本局状态")
|
||||
_attrs_label = UiKit.label("",UiKit.FS_HINT, false, UiKit.INK_LABEL)
|
||||
_attrs_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
box.add_child(_attrs_label)
|
||||
|
||||
_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)
|
||||
_section_head(box, "带的秘宝")
|
||||
_curios_label = UiKit.label("",UiKit.FS_HINT, false, UiKit.INK_LABEL)
|
||||
_curios_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
box.add_child(_curios_label)
|
||||
|
||||
_section_head(box, "已获专长")
|
||||
_feats_label = UiKit.label("",UiKit.FS_HINT, false, UiKit.INK_LABEL)
|
||||
_feats_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
box.add_child(_feats_label)
|
||||
|
||||
box.add_child(HSeparator.new())
|
||||
var close_row := HBoxContainer.new()
|
||||
@@ -56,80 +65,26 @@ func _section_head(box: VBoxContainer, text: String) -> void:
|
||||
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 单次开层生命周期口径)----
|
||||
|
||||
# 八键快照(组合根 _status_data 换代):balance/hero_hp/max_hp/atk/ac/gp/curios/feats——
|
||||
# 本局四件拼装在此,禁第二份投影(秘宝=inventory_projection 行映射、专长=feat_holdings_lines 现成行)
|
||||
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 行只读概览(数据源=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 = "尚未购买任何节点(天赋树在营地主柜台)"
|
||||
_attrs_label.text = "生命 %d/%d · 攻击 %d · 护甲 AC %d · GP %d" % [
|
||||
int(data.get("hero_hp", 0)), int(data.get("max_hp", 0)), int(data.get("atk", 0)),
|
||||
int(data.get("ac", 0)), int(data.get("gp", 0))]
|
||||
var curios: Array = data.get("curios", [])
|
||||
if (curios as Array).is_empty():
|
||||
_curios_label.text = "未携带秘宝"
|
||||
else:
|
||||
_tree_label.text = "已购 %d 项:%s" % [owned.size(), " · ".join(owned)]
|
||||
var parts: Array[String] = []
|
||||
for row in curios:
|
||||
var r: Dictionary = row
|
||||
parts.append(String(r.get("name", "")) + ("(已用)" if bool(r.get("used", false)) else ""))
|
||||
_curios_label.text = " · ".join(parts)
|
||||
var feats: Array = data.get("feats", [])
|
||||
_feats_label.text = "未获专长" if (feats as Array).is_empty() else " · ".join(feats)
|
||||
visible = true
|
||||
|
||||
|
||||
func _emit_closed() -> void:
|
||||
|
||||
Reference in new issue
Block a user