一、里程碑语义立规:M3=Alpha 完整实现/M4=Beta 完整实现,未明令关闭 M3 前只排 M3 需求(roadmap M-4 节头立规注+M-3 节头口径指针+迭代 21+ 行注+06 倍率差条注);迭代 20/21/22 规划冻结(roadmap 迭代 20 行注——先解决眼前问题,重启=用户直接发令) 二、文档正确性审查批三波:全 GDD 29 份过审——状态记录按代码证据订正/里程碑删前缀(M-x+迭代N→迭代N,裸 M-4→Beta 阶段(未排期))/退役词退役件当现役清零/在役旧实现节加隔离横幅;重件=秘宝.md v1.7 老正文深层清算(横幅重写消「过渡形态已退役」误读/沿革节换代/六件旧件登记摘除/验收与 charges 矛盾订正)+奇物 v3.8+冒险结构 v0.18+关卡节点地图 v1.7+图生成 v0.7+难度曲线与Boss v0.26+战斗结算 v0.27+敌人系统 v0.16+地图战斗资源 v0.21+增益状态 v0.13+战斗表现 v0.6+元进度 v1.9+生涯 v0.3+00 v1.3+02 v1.16+03 v1.1+ux 八份(battle 23 处/camp/shop/node-reward/level-clear/interaction-patterns/settlement-summary/level-map) 三、去毒批:奇物 v3.7(魔法道具→秘宝/档名三档→四级/门票与刷新「尚未入表」假话订正/验收第 3 条改令牌口径/资源成员指路凭证件表)+秘宝 v1.6(速览旧目录退役标注/退役件示例换现役) 四、道具退役素材库新建(design/research/道具退役素材库.md,案乙已追认):秘宝退役 9 件含去向+专长退役 27 件名单+待核 4 行;魔法提灯(fog_lantern)裁退役(06 条目已裁+秘宝.md 注记换代+素材库迁表一;拆线归实装批) 五、B2/B3/B4 裁决落文:元进度.md 道具工坊行删旧写新(v1.10——旧六行登记作废、指路秘宝新目录+解锁门槛谓词分级);奇物.md P1「两项合成高阶项」注销(v3.9——用户定性脏信息);§3 刷新句按最新口径换代(刷新券替代、不进持有集) 六、天赋树独立成文(B1 裁决):新建 design/gdd/systems/跨局循环/天赋树.md v0.1(33 节点机制全按 meta_tree.tres 实态+迭代 12 落籍裁决+被删底稿 git 取证——脊柱行门槛/钥石单币/Fork A/B 面/存档 v5 域/注入双通道)+元进度.md 定名节换代(v1.11)+02-系统清单跨局循环区加行(v1.17) 七、A 类卫生包:版本历史表理排四份(秘宝/奇物含 v2.7 断裂行修复/敌人系统/图生成,只调行序)+缺号注记三处(增益状态 v0.6 未考/冒险结构 v0.15/关卡节点地图 v1.6=MC-1 批)+node-reward v2.2 双号改 a/b+07 补建版本历史表+06 删「设置与本地化」空节+「文档/结构闸存量欠账」块挪文末「文档与结构」节+「L1 商店编排」两悬空指针改指 GP 换算失衡条+难度曲线两处过期指向核销注记(v0.27)+B5「现役 UI/文案两处自相冲突」登记 06 待办(battle_narrator.gd:160 旧话/hero_info_panel 两段同标「特性」——随后续迭代修) 八、命名统一(用户令「任务书」全库改「需求卡片」):167 文件约 800 处(design/ 全部文档+roadmap+CLAUDE.md+active.md+entities.yaml+game/ 注释与数据批注);两文件改名(需求卡片-M4数值批/需求卡片-冒险前资源配比预设批);残留=自造短语全量清单(黑话证据文档故意跳过) 九、CLAUDE.md:批次工作流标准清单收口段新增第 12 条「文档同步闸」(需求卡片必列关联文档同步面、合并前同步完毕方算收口,原 12/13 顺延);呈报六问铁规适用范围补立(前序批随批落籍) 十、active.md 快照节+工作日志 414-421(并行会话 416 黑话清扫条目按共享工作日志惯例一并入库);06 中并行会话「active.md 定性与裁剪」条目未提交,按零吞并纪律留在工作区未入库 零测试(文档批两入口铁规);主区前序脏件(.gitignore/.zcode/config.json/playnote/project.godot/.zcodeignore/美术审计报告 html 等)未带
167 lines
7.5 KiB
GDScript
167 lines
7.5 KiB
GDScript
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||
# 局内暂停层·只读(迭代 17 卡③ 暂停层只读入口批 2026-10-06——需求卡片 v1.1;事实源=06-待办清单
|
||
# 「解锁界面与钥石呈现的交互形态(残余:暂停层只读入口)」)。
|
||
# 裁决落形:P1 丁=入口为战斗屏 HUD / 关卡地图屏常驻角标(入口装配在 ui_assembler/两屏,本类不含入口);
|
||
# P2 甲=登记 modal_stack 设置层同档(确认弹窗之前)带 dim 遮罩;P3 甲=展示钥石余额+三柜台进度
|
||
# (属性锻造三行已购等级 / 道具工坊六件解锁态 / 天赋树已购概览——层内行序与分组复用营地屏同序);
|
||
# P4 甲=进出零动效直开直关(无 tween 无 AnimationPlayer——R5)。
|
||
# 只读契约:R4 数据只读同源——账面快照由组合根 open_pause 喂入(每次开层实时读 MetaProgression
|
||
# 访问器重建,快照仅用单次开层生命周期,跨开层零持有);本类零核心访问、零写通路——唯一信号
|
||
# closed(关闭意图,组合根经模态栈单口收口)。R1 公共件单点:全部构成件经 UiKit 工厂产出
|
||
#(modal_shell/panel_skinned/label/button/keystone_badge),零裸色值零自建样式。
|
||
class_name PauseOverlay
|
||
extends Control
|
||
|
||
signal closed
|
||
|
||
var _balance_badge: UiKit.KeystoneBadge # 钥石余额徽(badge 工厂件——Q10 甲)
|
||
var _forge_holder: VBoxContainer
|
||
var _workshop_holder: VBoxContainer
|
||
var _tree_label: Label
|
||
|
||
|
||
func _init() -> void:
|
||
var shell: Dictionary = 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, "属性锻造 · 已购等级")
|
||
_forge_holder = _section_holder(box)
|
||
|
||
_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_pause(data: Dictionary) -> void:
|
||
_balance_badge.set_text("钥石 %d" % int(data.get("balance", 0)))
|
||
_rebuild_forge(data)
|
||
_rebuild_workshop(data)
|
||
_rebuild_tree(data)
|
||
visible = true
|
||
|
||
|
||
# 属性锻造三行(营地屏同序同文案族——名称+每级 flat / 已购等级;只读零价格零按钮)
|
||
func _rebuild_forge(data: Dictionary) -> void:
|
||
for c in _forge_holder.get_children():
|
||
c.queue_free()
|
||
for row in (data.get("forge", []) as Array):
|
||
var line := HBoxContainer.new()
|
||
line.add_theme_constant_override("separation", 8)
|
||
var name_l := UiKit.label("%s %+d/级" % [String(row.get("display_name", "")), int(row.get("flat", 0))],UiKit.FS_HINT, true, UiKit.INK)
|
||
name_l.custom_minimum_size = Vector2(150, 0)
|
||
name_l.clip_text = true
|
||
name_l.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
||
line.add_child(name_l)
|
||
var spacer := Control.new()
|
||
spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||
line.add_child(spacer)
|
||
var lvl_l := UiKit.label("Lv %d" % int(row.get("level", 0)),UiKit.FS_HINT, true, UiKit.INK_TITLE)
|
||
line.add_child(lvl_l)
|
||
_forge_holder.add_child(line)
|
||
|
||
|
||
# 道具工坊六行(解锁态文案与营地柜台同口径——退役/封存/已解锁/未解锁;进度=解锁判定量读数)
|
||
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 prog_l := UiKit.label("累计通关 %d/%d 次" % [int(row.get("progress", 0)), int(row.get("threshold", 0))],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(_workshop_state_text(row),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)
|
||
|
||
|
||
# 解锁态文案(camp_overlay_view.refresh_camp 同款判据——退役 > 封存 > 已解锁 > 未解锁)
|
||
func _workshop_state_text(row: Dictionary) -> String:
|
||
if bool(row.get("retired", false)):
|
||
return "已退役"
|
||
if bool(row.get("deferred", false)) and bool(row.get("unlocked", false)):
|
||
return "已解锁 · 能力封存中"
|
||
if bool(row.get("unlocked", false)):
|
||
return "已解锁"
|
||
return "未解锁"
|
||
|
||
|
||
# 天赋树已购概览(单条聚合文案——已购节点等级 + 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()
|