From d799b4b347436992cafb636490c1d7d9d0d8bef3 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 24 Sep 2026 15:12:48 +0800 Subject: [PATCH] =?UTF-8?q?feat(ui):=20=E7=8A=B6=E6=80=81=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E6=8E=A5=E5=85=A5=E6=89=B9=E2=80=94=E2=80=94=E6=88=98?= =?UTF-8?q?=E6=96=97=20HUD=20=E7=8A=B6=E6=80=81=E6=A7=BD=E5=8D=A0=E4=BD=8D?= =?UTF-8?q?=E5=AD=97=E5=BD=A2=E9=80=80=E5=BD=B9=E6=8D=A2=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E9=AA=8C=E6=94=B6=E5=AE=9A=E7=A8=BF=E4=B9=9D=E6=9E=9A=20PNG?= =?UTF-8?q?=EF=BC=88C=20=E5=8C=BA=E6=A7=BD=2024px/B=20=E5=8C=BA=E7=AB=99?= =?UTF-8?q?=E6=A1=A9=2016px=20=E7=BA=B9=E7=90=86=EF=BC=8Ceffect=5Fid?= =?UTF-8?q?=E2=86=92status=5F.png=20=E6=81=92=E5=AE=9A?= =?UTF-8?q?=E6=98=A0=E5=B0=84=E5=9C=A3=E7=BB=8F=20=C2=A78.3=EF=BC=9B?= =?UTF-8?q?=E5=8F=A0=E5=B1=82=20=C3=97N=20=E8=A7=92=E6=A0=87=E4=BF=9D?= =?UTF-8?q?=E7=95=99=EF=BC=8C=E6=9E=81=E6=80=A7=E6=9F=93=E8=89=B2=E4=B8=8E?= =?UTF-8?q?=E6=B8=85=E5=9C=BA=20=E2=9C=95=20=E5=89=8D=E7=BC=80=E9=80=80?= =?UTF-8?q?=E5=BD=B9=EF=BC=9Bui=5Fprobe=20=E6=96=AD=E8=A8=80=E6=94=B9?= =?UTF-8?q?=E7=BA=B9=E7=90=86=E5=88=A4=E6=8D=AE+=E4=B9=9D=E9=94=AE?= =?UTF-8?q?=E5=85=A8=E8=A6=86=E7=9B=96=EF=BC=9B=E8=B5=84=E4=BA=A7=E5=85=A5?= =?UTF-8?q?=E5=BA=93=20game/assets/ui/icons/=202026-09-24=EF=BC=8C?= =?UTF-8?q?=E5=8F=B0=E8=B4=A6=20156=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/assets/ui/icons/status_ac_up.png | Bin 0 -> 297 bytes game/assets/ui/icons/status_alert.png | Bin 0 -> 207 bytes game/assets/ui/icons/status_attack_up.png | Bin 0 -> 264 bytes game/assets/ui/icons/status_empower.png | Bin 0 -> 260 bytes game/assets/ui/icons/status_enrage.png | Bin 0 -> 264 bytes game/assets/ui/icons/status_fortify.png | Bin 0 -> 297 bytes game/assets/ui/icons/status_off_guard.png | Bin 0 -> 303 bytes game/assets/ui/icons/status_sapped.png | Bin 0 -> 252 bytes game/assets/ui/icons/status_weaken.png | Bin 0 -> 252 bytes game/presentation/views/standee_view.gd | 35 ++++++--- game/presentation/views/status_slot_row.gd | 79 ++++++++++++--------- game/smoke/ui_probe.gd | 29 ++++---- 12 files changed, 86 insertions(+), 57 deletions(-) create mode 100644 game/assets/ui/icons/status_ac_up.png create mode 100644 game/assets/ui/icons/status_alert.png create mode 100644 game/assets/ui/icons/status_attack_up.png create mode 100644 game/assets/ui/icons/status_empower.png create mode 100644 game/assets/ui/icons/status_enrage.png create mode 100644 game/assets/ui/icons/status_fortify.png create mode 100644 game/assets/ui/icons/status_off_guard.png create mode 100644 game/assets/ui/icons/status_sapped.png create mode 100644 game/assets/ui/icons/status_weaken.png diff --git a/game/assets/ui/icons/status_ac_up.png b/game/assets/ui/icons/status_ac_up.png new file mode 100644 index 0000000000000000000000000000000000000000..5b0291952bc111aa917d64d1c209449a45baaadb GIT binary patch literal 297 zcmV+^0oMMBP)wim1A52 zDrHls!AjXEm>H_3^I|0=;c-kkeqU39;wnh8claFzQd9_K-{}?c1E0Q*yBF#5uzr5u z_gA>s8)lcl28N8k=9BZguLMpBU`z$hK1AL}UkRKN00+TYyL-Pc{pPewItAzLF>g|_ v5@Qq3DdDT&NX36dHAk(=bJ}c3Wohay6z33)y!}uT;=mVf?tCgMr~d%8t^79UeV~*Y8y)JyX+NXX^Vm zH^UcP+ZDZl$4y1viKHani4E&ASlK;Xb)AzWE#9*T3(M z|BQNVnJ>l9FZG4PyPj#fkJL}z-5iP@S+!a~H)ZIF3$nStS?ah<63AolboFyt=akR{ E0QX->@&Et; literal 0 HcmV?d00001 diff --git a/game/assets/ui/icons/status_attack_up.png b/game/assets/ui/icons/status_attack_up.png new file mode 100644 index 0000000000000000000000000000000000000000..17a0f777bde1700bd7e182642e511d367c82da15 GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ^PVn_Ar*6y6C_v{Cy4NrfA|js z%xQ)k0zt=}xVt?A&%1b^mIQ*A&l>)x95WSOtD}DGdq^RJ>a^fD3|_j+PcUBDFeisS z;B?U@83*6fo@ESMb=6-mq;O{@THfGEl66@3^jOxV0^@V{s!n+X#U40u;)F-%`NV0( zXAK%Y7)$(HY~9o;(YzwjvZq%@iAB~S?`PlHqL{t}l@!ZO{Tn+InYaDk(^>Q*arxRC zyh_)UoEV-2e+giS>@w&27ku&)W9Ebj%n=t@Up)QnD9p5&fx+-)@jRcSA8dhMWAJqK Kb6Mw<&;$UM_G(N3 literal 0 HcmV?d00001 diff --git a/game/assets/ui/icons/status_empower.png b/game/assets/ui/icons/status_empower.png new file mode 100644 index 0000000000000000000000000000000000000000..1726b3485f6032ed967836dc645ce534f8ccb152 GIT binary patch literal 260 zcmV+f0sH=mP))x95WSOtD}DGdq^RJ>a^fD3|_j+PcUBDFeisS z;B?U@83*6fo@ESMb=6-mq;O{@THfGEl66@3^jOxV0^@V{s!n+X#U40u;)F-%`NV0( zXAK%Y7)$(HY~9o;(YzwjvZq%@iAB~S?`PlHqL{t}l@!ZO{Tn+InYaDk(^>Q*arxRC zyh_)UoEV-2e+giS>@w&27ku&)W9Ebj%n=t@Up)QnD9p5&fx+-)@jRcSA8dhMWAJqK Kb6Mw<&;$UM_G(N3 literal 0 HcmV?d00001 diff --git a/game/assets/ui/icons/status_fortify.png b/game/assets/ui/icons/status_fortify.png new file mode 100644 index 0000000000000000000000000000000000000000..5b0291952bc111aa917d64d1c209449a45baaadb GIT binary patch literal 297 zcmV+^0oMMBP)wim1A52 zDrHls!AjXEm>H_3^I|0=;c-kkeqU39;wnh8claFzQd9_K-{}?c1E0Q*yBF#5uzr5u z_gA>s8)lcl28N8k=9BZguLMpBU`z$hK1AL}UkRKN00+TYyL-Pc{pPewItAzLF>g|_ v5@Qq3DdDT&NX36dHAk(=b~47o6I#@jLh7B)bf+p*){0a^zl zqGCV*RZQ4IR!ve!YN`nkLijlI-m7iYAR?OQnOY&fB@T3h0oFb6ttoMfa}QvRQLe#y z`JfvNv<%+u2}wDQHRJa)PtaWjP4$f73V_C#E93E6+wpQI&3E<(x*p$cPq#a$KO+GL zF3B5{n?6CvESZ*N#ZW0wQlX`KMw0?U#8pe>txIQWaY~g)$+`K~{NlSuc-s7Sx$aLP z(|{HUaAlWey(!~SM2iGUNu+xKtrEy3k&^FV1ztE&1%_8Y^8o+=002ovPDHLkV1hs@ Be*FLd literal 0 HcmV?d00001 diff --git a/game/assets/ui/icons/status_sapped.png b/game/assets/ui/icons/status_sapped.png new file mode 100644 index 0000000000000000000000000000000000000000..e2872b239419c500db68ae165d5f917a573e3c6e GIT binary patch literal 252 zcmVHxL!ssISNI{-@V3V@Us2SCf!0CQo4 z{B?#kfJc5BdL9qMV(oajlDPx4Awg7b3J@(9%rg*0*5ouJB2=fzJ?)p_vwXWvkIw_Q zHxL!ssISNI{-@V3V@Us2SCf!0CQo4 z{B?#kfJc5BdL9qMV(oajlDPx4Awg7b3J@(9%rg*0*5ouJB2=fzJ?)p_vwXWvkIw_Q z void: set_effects([]) -# 主角/敌方共用——状态小图标行重建(B 区迷你版:icon + 层数角标;完整 tooltip 义务归 C 区状态槽) +# 主角/敌方共用——状态小图标行重建(B 区迷你版:定稿纹理 16px + 层数 ×N 角标; +# 完整 tooltip 义务归 C 区状态槽。2026-09-24 状态图标接入批:占位字形+极性染色退役) func set_effects(effects: Array) -> void: for c in _status_row.get_children(): _status_row.remove_child(c) c.queue_free() for eff in effects: - var cfg: Array = _icon_cfg(String(eff.get("effect_id", ""))) + var tex := _icon_tex(String(eff.get("effect_id", ""))) var layers := maxi(1, int(eff.get("layers", 1))) - var lab := UiKit.label(String(cfg[0]) + ("×%d" % layers if layers > 1 else ""), 12, true) - lab.add_theme_color_override("font_color", cfg[1]) - lab.mouse_filter = Control.MOUSE_FILTER_IGNORE - _status_row.add_child(lab) + if tex != null: + var icon := TextureRect.new() + icon.texture = tex + icon.custom_minimum_size = Vector2(16, 16) # 32px 源 ÷2 整数档缩放 + icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + icon.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR + icon.mouse_filter = Control.MOUSE_FILTER_IGNORE + _status_row.add_child(icon) + else: + var ph := UiKit.label(StatusSlotRow.ICON_PLACEHOLDER, 12, true) # release 回退占位(debug 已断言) + ph.mouse_filter = Control.MOUSE_FILTER_IGNORE + _status_row.add_child(ph) + if layers > 1: + var lab := UiKit.label("×%d" % layers, 12, true) + lab.mouse_filter = Control.MOUSE_FILTER_IGNORE + _status_row.add_child(lab) func set_order(i: int) -> void: @@ -283,10 +298,10 @@ func _refresh_portrait_glyph() -> void: # 状态图标键解析(词汇单点复用 C 区 StatusSlotRow——HUD框架:查不到的键按错误处理, -# 立即断言 + ? 占位纹样 + 诊断,禁止静默显示空图标) -func _icon_cfg(effect_id: String) -> Array: +# 立即断言 + ? 占位 + 诊断,禁止静默显示空图标) +func _icon_tex(effect_id: String) -> Texture2D: if StatusSlotRow.EFFECT_ICON.has(effect_id): return StatusSlotRow.EFFECT_ICON[effect_id] push_error("[站桩] 未知状态图标键(映射表外键——立即断言): %s" % effect_id) assert(false, "未知状态图标键: " + effect_id) - return ["?", UiKit.PANEL_BORDER, "?"] + return null diff --git a/game/presentation/views/status_slot_row.gd b/game/presentation/views/status_slot_row.gd index 11d22ea0..6197e5fa 100644 --- a/game/presentation/views/status_slot_row.gd +++ b/game/presentation/views/status_slot_row.gd @@ -1,7 +1,9 @@ # VERTICAL SLICE - NOT FOR PRODUCTION -# 实现 GDD:design/ux/battle.md(C 区状态效果槽 ×4〔增益状态 D1×①〕——effect_id→icon 形状+色相双通道、 +# 实现 GDD:design/ux/battle.md(C 区状态效果槽 ×4〔增益状态 D1×①〕——effect_id→定稿 PNG 纹理图标、 # 层数角标、剩余结算次数点、悬停 tooltip(来源+语义+剩余);空态 = 槽隐藏(数据框上移补位, # EC12 空态裁决);极性映射 = 战斗结算 SettlementTable 效果语义而非 magnitude 符号〔增益状态 D1×③〕)。 +# 2026-09-24 状态图标接入批:程序化占位字形(▲◇▼◎⚔✕☾⇧▣)+ 按极性染色退役——定稿九枚 PNG +# (白剑/白盾/白眼+绿↑红↓箭头语言,用户逐键验收,圣经 §4.6.1 v2.2 纹样系统)自带极性,裸图标呈现。 # Date: 2026-09-12 # 高内聚边界:纯视图——效果投影装配归 hud_presenter.gd;增益状态 纯被动容器零信号——刷新绑 战斗结算 # 结算编排完成时点(battle.md 更新触发注记)。 @@ -9,22 +11,28 @@ class_name StatusSlotRow extends HBoxContainer const MAX_SLOTS := 4 -# 极性/语义映射(数据源 = SettlementTable.effect_pool_map 效果语义 + StatusEffectTable display_name): -# 益 = ▲/◆/▼/◇(金/蓝族);害 = ⚡/⚔/✕/☾/⇧/▣(旗朱族;⇧/▣ = 敌方增益威胁纹样)——形状+色相双通道, -# 文字名常驻第三通道。状态表九行全映射(attack_up/ac_up/weaken/alert/enrage/off_guard/sapped/empower/fortify) -# ——HUD框架 图标键契约"一键一枚专属纹样,查不到的键立即断言 + ? 占位 + 诊断" +# 纹理映射(2026-09-24 状态图标接入批):effect_id→定稿纹理,全局恒定禁换图(图标键契约 §4.6 的 +# 文件侧延伸——文件键 = status_.png,命名规范圣经 §8.3「对象键 = 数据表主键」)。 +# 状态表九行全映射(attack_up/ac_up/weaken/alert/enrage/off_guard/sapped/empower/fortify) +# ——HUD框架 图标键契约"一键一枚专属纹样,查不到的键立即断言 + 占位 + 诊断" # (2026-09-15 格面资源批补 sapped;2026-09-16 护甲等级掷点批 defense_up → ac_up 换装; # 同日 敌人技能池批补 empower/fortify 敌方增益两键——敌方增益显示 = 敌卡状态行文本 + 本图标键词汇)。 const EFFECT_ICON := { - "attack_up": ["▲", UiKit.GOLD_DEEP, "益"], - "ac_up": ["◇", UiKit.HERO_BLUE, "益"], - "weaken": ["▼", UiKit.HERO_BLUE, "益"], - "alert": ["◎", UiKit.FLAG_RED, "害"], - "enrage": ["⚔", UiKit.FLAG_RED, "害"], - "off_guard": ["✕", UiKit.FLAG_RED, "害"], - "sapped": ["☾", UiKit.FLAG_RED, "害"], - "empower": ["⇧", UiKit.FLAG_RED, "害"], - "fortify": ["▣", UiKit.PANEL_BORDER, "害"], + "attack_up": preload("res://assets/ui/icons/status_attack_up.png"), + "ac_up": preload("res://assets/ui/icons/status_ac_up.png"), + "weaken": preload("res://assets/ui/icons/status_weaken.png"), + "alert": preload("res://assets/ui/icons/status_alert.png"), + "enrage": preload("res://assets/ui/icons/status_enrage.png"), + "off_guard": preload("res://assets/ui/icons/status_off_guard.png"), + "sapped": preload("res://assets/ui/icons/status_sapped.png"), + "empower": preload("res://assets/ui/icons/status_empower.png"), + "fortify": preload("res://assets/ui/icons/status_fortify.png"), +} +# 极性词(tooltip 第三通道;运行时不再按极性染色/画框——绿↑红↓极性语言已内化于定稿图标本体) +const EFFECT_POLARITY := { + "attack_up": "益", "ac_up": "益", "weaken": "益", + "alert": "害", "enrage": "害", "off_guard": "害", + "sapped": "害", "empower": "害", "fortify": "害", } const EFFECT_SEMANTIC := { "attack_up": "主角攻击加成(hero_offense 池加算)", @@ -38,8 +46,8 @@ const EFFECT_SEMANTIC := { "fortify": "敌方防御 −50(enemy_defense 池——硬化技施放,主角攻击 ×0.5;持续 1 个有效结算)", } const SOURCE_NAMES := {"safe_cell": "安全格", "flag_hit": "标中旗", "mine_hit": "踩雷", "clear_reward": "清图奖励"} -# 未知图标键的占位纹样(HUD框架:占位也要可见,禁静默空图标) -const ICON_PLACEHOLDER := ["?", UiKit.PANEL_BORDER, "?"] +# 未知图标键的占位(HUD框架:占位也要可见,禁静默空图标——debug 断言先行,release 回退槽内 ? 文本) +const ICON_PLACEHOLDER := "?" var _tip: PanelContainer var _tip_label: Label @@ -71,15 +79,13 @@ func set_effects(effects: Array) -> void: _slots[i].visible = true -# battle_over 反馈(增益状态×4④):逐槽化光收回 + 微文案(下次 set_effects 恢复常态) +# battle_over 反馈(增益状态×4④):逐槽化光收回 + 微灰化(下次 set_effects 恢复常态; +# 2026-09-24 状态图标接入批:原字形 "✕ " 前缀随占位字形退役,灰化即清场反馈) func set_cleared_feedback() -> void: _cleared_feedback = true for slot in _slots: slot.visible = true slot.modulate = Color(0.7, 0.7, 0.7, 0.5) - var col := slot.get_child(0) as VBoxContainer - var icon := col.get_child(0) as Label - icon.text = "✕ " + icon.text func _sync_slots(n: int) -> void: @@ -105,8 +111,13 @@ func _make_slot() -> PanelContainer: var col := VBoxContainer.new() col.alignment = BoxContainer.ALIGNMENT_CENTER slot.add_child(col) - var icon := UiKit.label("", 16, true) - icon.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + # 定稿纹理图标(32px 源 → 24px 槽内呈现;线性过滤匹配抗锯齿矢量风源图) + var icon := TextureRect.new() + icon.custom_minimum_size = Vector2(24, 24) + icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + icon.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR + icon.mouse_filter = Control.MOUSE_FILTER_IGNORE col.add_child(icon) var meta := UiKit.label("", 11, false) meta.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER @@ -118,17 +129,19 @@ func _fill_slot(slot: PanelContainer, eff: Dictionary) -> void: slot.modulate = Color(1, 1, 1) slot.set_meta("eff", eff) var col := slot.get_child(0) as VBoxContainer - var icon := col.get_child(0) as Label + var icon := col.get_child(0) as TextureRect var meta := col.get_child(1) as Label - var icon_cfg: Array = _icon_cfg(String(eff.effect_id)) - icon.text = String(icon_cfg[0]) - icon.add_theme_color_override("font_color", icon_cfg[1]) - # 层数角标 + 剩余结算次数点(● 未耗余量) + # 层数角标 + 剩余结算次数点(● 未耗余量)——叠层数字呈现逻辑保持不动 var dots := "" var left: int = int(eff.get("remaining_settlements", 0)) for i in maxi(left, 1): dots += "●" if i < left else "○" meta.text = "×%d %s" % [int(eff.get("layers", 1)), dots] + var tex := _icon_tex(String(eff.effect_id)) + icon.visible = tex != null + icon.texture = tex + if tex == null: + meta.text = ICON_PLACEHOLDER + " " + meta.text # release 回退占位(debug 已断言) func _on_slot_hover(slot: Control) -> void: @@ -136,11 +149,11 @@ func _on_slot_hover(slot: Control) -> void: if not slot.has_meta("eff"): return var eff: Dictionary = slot.get_meta("eff") - var icon_cfg: Array = _icon_cfg(String(eff.effect_id)) + var eid := String(eff.effect_id) var src: String = String(SOURCE_NAMES.get(String(eff.get("source_class", "")), String(eff.get("source_class", "")))) - var semantic: String = String(EFFECT_SEMANTIC.get(String(eff.effect_id), String(eff.get("display_name", "")))) + var semantic: String = String(EFFECT_SEMANTIC.get(eid, String(eff.get("display_name", "")))) _tip_label.text = "%s〔%s〕\n%s\n剩余结算 %d 次\n来源:%s(第 %d 轮)" % [ - String(eff.get("display_name", "")), String(icon_cfg[2]), semantic, + String(eff.get("display_name", "")), String(EFFECT_POLARITY.get(eid, ICON_PLACEHOLDER)), semantic, int(eff.get("remaining_settlements", 0)), src, int(eff.get("round_index", 0))] if not _tip.is_inside_tree(): add_child(_tip) @@ -159,10 +172,10 @@ func _on_slot_hover(slot: Control) -> void: _tip.visible = true -# 图标键解析(HUD框架:查不到的键按错误处理——立即断言 + ? 占位纹样 + 诊断,禁止静默显示空图标) -func _icon_cfg(effect_id: String) -> Array: +# 图标键解析(HUD框架:查不到的键按错误处理——立即断言 + 占位 + 诊断,禁止静默显示空图标) +func _icon_tex(effect_id: String) -> Texture2D: if EFFECT_ICON.has(effect_id): return EFFECT_ICON[effect_id] push_error("[状态槽] 未知图标键(映射表外键——立即断言): %s" % effect_id) assert(false, "未知图标键: " + effect_id) - return ICON_PLACEHOLDER + return null diff --git a/game/smoke/ui_probe.gd b/game/smoke/ui_probe.gd index c1e76fb0..13d15b76 100644 --- a/game/smoke/ui_probe.gd +++ b/game/smoke/ui_probe.gd @@ -137,20 +137,21 @@ func _ready() -> void: elif slots_row._slots.size() != 1 or slots_row._slots[0] == slots_row._tip: problems.append("BUG-0001 回归:tooltip 入树后槽引用错位") else: - var icon_lab: Label = slots_row._slots[0].get_child(0).get_child(0) - if icon_lab.text != "▲": - problems.append("BUG-0001 回归:悬停后重刷槽未填充(icon=%s)" % icon_lab.text) + var icon_rect: TextureRect = slots_row._slots[0].get_child(0).get_child(0) + if icon_rect.texture == null: + problems.append("BUG-0001 回归:悬停后重刷槽未填充(texture=null)") slots_row.set_effects([probe_eff[0], probe_eff[0], probe_eff[0], probe_eff[0], probe_eff[0], probe_eff[0]]) if slots_row._slots.size() != 4: problems.append("BUG-0001 回归:超上限效果未截断至 4 槽(%d)" % slots_row._slots.size()) slots_row.set_effects([]) if not slots_row._slots.is_empty(): problems.append("BUG-0001 回归:空态未清槽(%d)" % slots_row._slots.size()) - # ---- 图标键回归(HUD框架 图标键契约:状态表七行全映射、格面资源 cell_type 九型全映射〔gp 键 = 九型批 2026-09-20〕; - # 查不到的键 fail-fast + ? 占位——此处钉死映射不残缺,未知键断言由 _icon_cfg/_badge_glyph 承担)---- - if not StatusSlotRow.EFFECT_ICON.has("enrage") or not StatusSlotRow.EFFECT_ICON.has("off_guard") \ - or not StatusSlotRow.EFFECT_ICON.has("sapped"): - problems.append("状态图标表缺暴走/失衡/乏力键(states 表七行须全映射)") + # ---- 图标键回归(HUD框架 图标键契约:状态表九行全映射〔定稿 PNG 纹理,2026-09-24 状态图标接入批〕、 + # 格面资源 cell_type 九型全映射〔gp 键 = 九型批 2026-09-20〕;查不到的键 fail-fast + ? 占位 + # ——此处钉死映射不残缺,未知键断言由 _icon_tex/_badge_glyph 承担)---- + for eid in ["attack_up", "ac_up", "alert", "weaken", "enrage", "off_guard", "sapped", "empower", "fortify"]: + if not StatusSlotRow.EFFECT_ICON.has(eid) or StatusSlotRow.EFFECT_ICON[eid] == null: + problems.append("状态图标九键纹理映射缺失(%s)" % eid) for cat in ["attack", "defense", "heal", "blast", "weaken", "pierce", "magic", "action", "gp"]: if not BoardView.REWARD_BADGE.has(cat): problems.append("奖励图标表缺键(%s)" % cat) @@ -162,12 +163,12 @@ func _ready() -> void: if slots_row._slots.size() != 2: problems.append("图标键回归:enrage/off_guard 未建槽(%d)" % slots_row._slots.size()) else: - var ic_enrage: Label = slots_row._slots[0].get_child(0).get_child(0) - var ic_off: Label = slots_row._slots[1].get_child(0).get_child(0) - if ic_enrage.text == "?" or ic_enrage.text == "": - problems.append("暴走图标键未映射(icon=%s)" % ic_enrage.text) - if ic_off.text == "?" or ic_off.text == "": - problems.append("失衡图标键未映射(icon=%s)" % ic_off.text) + var ic_enrage: TextureRect = slots_row._slots[0].get_child(0).get_child(0) + var ic_off: TextureRect = slots_row._slots[1].get_child(0).get_child(0) + if ic_enrage.texture == null: + problems.append("暴走图标键未映射(texture=null)") + if ic_off.texture == null: + problems.append("失衡图标键未映射(texture=null)") slots_row.set_effects([]) # ---- L2 单场段(debug_session 单场原语 + 去饱和接口可用性;雾格机制已整体移除,不再断言变体呈现)---- # 2026-09-13 单场用户入口已删——探针直调 debug_session 原语(battle_created/ready 仍经组合根接线;