diff --git a/game/presentation/battle_narrator.gd b/game/presentation/battle_narrator.gd index d66cf267..fdb1f7cd 100644 --- a/game/presentation/battle_narrator.gd +++ b/game/presentation/battle_narrator.gd @@ -47,7 +47,7 @@ static func debug_open_line(seed_val: int, level: int, level_mode: bool) -> Stri # 调试战斗终局文案(level_end = 关内两层模式的关卡末) static func battle_end_text(result: String, level_end: bool) -> String: if level_end: - return "关卡通关!" + return "关卡完成!" if result == "victory": return "战斗胜利!敌人全灭。" return "战斗失败……探险者倒下了。" @@ -87,9 +87,9 @@ static func curio_pick_header(payload: Dictionary) -> String: var lines: Array[String] = ["第 %d 层通过!" % int(payload.get("level_index", 0))] var heal := int(payload.get("heal_gained", 0)) if heal > 0: - lines.append("通关回血 +%d(生命 %d → %d)" % [heal, int(payload.get("hp_before", 0)), int(payload.get("hp_after", 0))]) + lines.append("关卡完成回血 +%d(生命 %d → %d)" % [heal, int(payload.get("hp_before", 0)), int(payload.get("hp_after", 0))]) else: - lines.append("生命已满——通关回血 0(合法态)") + lines.append("生命已满——关卡完成回血 0(合法态)") lines.append("选择一件提升带走(另两件丢弃不可反悔):") return "\n".join(lines) @@ -151,19 +151,19 @@ static func bonus_keystone_line(payload: Dictionary) -> String: return "钥石 +%d · 累计 %d" % [int(payload.get("keystone_gained", 0)), int(payload.get("keystone_total", 0))] -# 奖励节点三选一头部行(与通关三选一共享同库;渠道白名单分流——node-reward.md v2) +# 奖励节点三选一头部行(与关卡完成三选一共享同库;渠道白名单分流——node-reward.md v2) static func node_curio_header() -> String: - return "关卡奖励点\n从冒险牌库抽三选一(属性值提升与补给;与通关专长三选一同库分流):\n选择一件带走:" + return "关卡奖励点\n从冒险牌库抽三选一(属性值提升与补给;与关卡完成专长三选一同库分流):\n选择一件带走:" -# 冒险结算屏文案(摘要五件事:打穿没有 / 通关几关 / 止步第几关 / 钥石合计 / 主种子) +# 冒险结算屏文案(摘要五件事:打穿没有 / 完成几关 / 止步第几关 / 钥石合计 / 主种子) static func adventure_summary_text(summary: Dictionary) -> String: var verdict := "冒险失败 · 未打穿" if bool(summary.get("cleared", false)): verdict = "冒险完成 · 已打穿" elif String(summary.get("result", "")) == "abandoned": verdict = "冒险放弃 · 未打穿" - return "%s\n通关 %d 关 · 止步第 %d 层 · 钥石合计 %d · 主种子 %d" % [ + return "%s\n完成 %d 关 · 止步第 %d 层 · 钥石合计 %d · 主种子 %d" % [ verdict, int(summary.get("levels_cleared", 0)), int(summary.get("stopped_at", 0)), int(summary.get("keystone_total", 0)), int(summary.get("master_seed", 0))] diff --git a/game/presentation/hud_presenter.gd b/game/presentation/hud_presenter.gd index d11cbf0c..0f6aaf79 100644 --- a/game/presentation/hud_presenter.gd +++ b/game/presentation/hud_presenter.gd @@ -188,10 +188,10 @@ static func outcome_text(outcome: Dictionary) -> String: static func tune_sim_report(n: int, atk_pct: int, hp_pct: int, wins: int, dmg_all: Array, hp_left_win: Array, hp_boss: Array, rounds_all: Array, death_nodes: Dictionary, base_hp: int) -> String: var lines: Array[String] = [] lines.append("[b]模拟 N=%d(atk+%d%% / hp+%d%%)[/b]" % [n, atk_pct, hp_pct]) - lines.append("通关率 [color=#%s]%.0f%%[/color](%d/%d)" % [UiKit.HEX_LOG_WIN, 100.0 * float(wins) / float(maxi(1, n)), wins, n]) + lines.append("关卡完成率 [color=#%s]%.0f%%[/color](%d/%d)" % [UiKit.HEX_LOG_WIN, 100.0 * float(wins) / float(maxi(1, n)), wins, n]) lines.append("整关承伤:均 %.1f · p90 %.0f(基础 HP %d)" % [_mean(dmg_all), _p90(dmg_all), base_hp]) if not hp_left_win.is_empty(): - lines.append("通关剩余 HP 均 %.1f · 进 Boss HP 均 %.1f" % [_mean(hp_left_win), _mean(hp_boss)]) + lines.append("关卡完成剩余 HP 均 %.1f · 进 Boss HP 均 %.1f" % [_mean(hp_left_win), _mean(hp_boss)]) lines.append("平均轮数 %.1f" % _mean(rounds_all)) if death_nodes.is_empty(): lines.append("败北节点:—") diff --git a/game/presentation/views/camp_overlay_view.gd b/game/presentation/views/camp_overlay_view.gd index 36d95259..f9e6903d 100644 --- a/game/presentation/views/camp_overlay_view.gd +++ b/game/presentation/views/camp_overlay_view.gd @@ -542,7 +542,7 @@ func _rebuild_recent(data: Dictionary) -> void: verdict = "完成" elif String(s.get("result", "")) == "abandoned": verdict = "放弃" - lines.append("最近冒险:%s · 通关 %d 关 · 钥石 +%d · 种子 %d" % [verdict, + lines.append("最近冒险:%s · 完成 %d 关 · 钥石 +%d · 种子 %d" % [verdict, int(s.get("levels_cleared", 0)), int(s.get("keystone_total", 0)), int(s.get("master_seed", 0))]) _recent_list.text = " | ".join(lines) diff --git a/game/presentation/views/career_overlay.gd b/game/presentation/views/career_overlay.gd index 3b169e8e..796935b5 100644 --- a/game/presentation/views/career_overlay.gd +++ b/game/presentation/views/career_overlay.gd @@ -8,8 +8,8 @@ extends Control signal closed var _total_label: Label # 冒险总局数(开局即计含放弃与失败) -var _cleared_label: Label # 通关局数(三关全通才计 1) -var _clears_label: Label # 各关通关次数(一行三关——display_name ×次数) +var _cleared_label: Label # 冒险成功局数(三关全通才计 1) +var _clears_label: Label # 各关完成次数(一行三关——display_name ×次数) var _boss_first_label: Label # Boss 首杀(已首杀关数/总关数) var _boss_kills_label: Label # Boss 总击杀(含重复) var _keystone_badge: UiKit.KeystoneBadge # 钥石余额(badge 工厂件——状态面板同形制) @@ -33,14 +33,14 @@ func _init() -> void: UiKit.FS_HINT, false, UiKit.WARM_SOFT) box.add_child(hint) - # 组一·冒险战绩(终身计数域——存档 v6:总局数开局即计、通关局数三关全通才计) + # 组一·冒险战绩(终身计数域——存档 v6:总局数开局即计、冒险成功局数三关全通才计) # 对比度口径:页底=暖亮档深棕(BG_BRIGHT),文字全用亮墨族 token(WARM 9.0:1 / WARM_SOFT 8.0:1 / # CANDLE 7.2:1 / INK_L_GOLD 9.1:1 实测对 BG_BRIGHT 全过 §7.2 ≥4.5:1——深墨族〔INK_LABEL〕 # 压深棕底仅 ~1.3:1 属违例,禁用) _section_head(box, "冒险战绩") _total_label = _row(box, "冒险总局数") - _cleared_label = _row(box, "通关局数") - _clears_label = _row(box, "各关通关次数") + _cleared_label = _row(box, "冒险成功局数") + _clears_label = _row(box, "各关完成次数") _boss_first_label = _row(box, "Boss 首杀") _boss_kills_label = _row(box, "Boss 总击杀") diff --git a/game/presentation/views/save_select_overlay.gd b/game/presentation/views/save_select_overlay.gd index bd7ac8dd..0d308ae4 100644 --- a/game/presentation/views/save_select_overlay.gd +++ b/game/presentation/views/save_select_overlay.gd @@ -1,5 +1,5 @@ ## VERTICAL SLICE - NOT FOR PRODUCTION -## 选档界面·全屏页:3 存档位(新档/进档/删档)+ 槽摘要三项(钥石余额/通关局数/冒险总局数)。 +## 选档界面·全屏页:3 存档位(新档/进档/删档)+ 槽摘要三项(钥石余额/冒险成功局数/冒险总局数)。 ## 结构树层级:选档 → 进档 → 营地(本面零存档内功能入口——禁营地/冒险/生涯跳转与购买/查看入口); ## 删档必经二次确认(确认弹窗与分派归组合根消费方编排——本面只发意图信号)。 ## 槽数与槽态(空/有档)唯一来自组合根喂入数据(open_save_select 每开重建——组合根经卡① 窥视 API @@ -15,7 +15,7 @@ signal load_slot_requested(slot: int) signal delete_slot_requested(slot: int) var _rows_box: VBoxContainer -var _summary_labels: Dictionary[int, Label] = {} # 槽号→摘要读数 label(通关/冒险两值——探针取值缝) +var _summary_labels: Dictionary[int, Label] = {} # 槽号→摘要读数 label(冒险成功/冒险两值——探针取值缝) var _occupied_flags: Dictionary[int, bool] = {} # 槽号→有档态(操作集二分断言缝;判定源=喂入数据) var _new_btns: Dictionary[int, Button] = {} # 槽号→新档钮(空/坏槽——操作集断言与点击链驱动缝) var _load_btns: Dictionary[int, Button] = {} # 槽号→进档钮(有档槽) @@ -84,7 +84,7 @@ func _build_slot_row(sd: Dictionary) -> void: sp.size_flags_horizontal = Control.SIZE_EXPAND_FILL if occupied: row.add_child(UiKit.keystone_badge("钥石 %d" % int(sd.get("keystone", 0)))) - var summary_l := UiKit.label("通关 %d 局 · 冒险 %d 局" % [int(sd.get("cleared", 0)), int(sd.get("total", 0))], + var summary_l := UiKit.label("冒险成功 %d 局 · 冒险 %d 局" % [int(sd.get("cleared", 0)), int(sd.get("total", 0))], UiKit.FS_BODY, false, UiKit.CANDLE) _summary_labels[slot] = summary_l # 摘要读数缝(禁词断言枚举 Label 全集时含此件) row.add_child(summary_l) diff --git a/game/presentation/views/ui_kit.gd b/game/presentation/views/ui_kit.gd index 7431323b..aabf3afd 100644 --- a/game/presentation/views/ui_kit.gd +++ b/game/presentation/views/ui_kit.gd @@ -208,7 +208,7 @@ const HEX_LOG_DMG_BODY := "e0a050" # 伤害行正文橙 const HEX_LOG_VOIDED := "b08060" # 未生效行暗橙(⚠ 划线) const HEX_LOG_CAST := "b09a72" # 施放行暖石(✦ 具名技能) const HEX_LOG_DECAY := "8a9ab0" # 状态衰减蓝灰 -const HEX_LOG_WIN := "80d080" # 胜利判定绿(模拟报告通关率同档) +const HEX_LOG_WIN := "80d080" # 胜利判定绿(模拟报告关卡完成率同档) const HEX_ROUTE_NOTE := "d0c090" # 奖励点预告暗金(narrator 行) const HEX_SEED_NOTE := "c8a860" # 种子/开场行暗金(narrator 行) @@ -400,7 +400,7 @@ const FS_H1 := 34 # 主标题/演算暴击 # ── 秘宝解锁条件计数键 → 呈现标签(秘宝匣柜台条件进度文案单点;键域= # TreasureItemTable.UNLOCK_COUNTER_KEYS 封闭枚举,键出域走「条件」兜底不炸)── -const TREASURE_REQ_LABELS := {"adventure_cleared": "通关", "boss_kill_count": "Boss击杀", "vision_used": "真视使用"} +const TREASURE_REQ_LABELS := {"adventure_cleared": "冒险成功", "boss_kill_count": "Boss击杀", "vision_used": "真视使用"} # 秘宝档位 → 呈现名(契约 2 三档;legendary 传说空集合法不在柜) const TREASURE_TIER_LABELS := {"common": "普通", "excellent": "优秀", "rare": "稀有", "legendary": "传说"} diff --git a/game/tests/unit/presentation/battle_narrator_test.gd b/game/tests/unit/presentation/battle_narrator_test.gd index ce7dd670..eb733b9d 100644 --- a/game/tests/unit/presentation/battle_narrator_test.gd +++ b/game/tests/unit/presentation/battle_narrator_test.gd @@ -22,6 +22,7 @@ func _init() -> void: _test_end_text_differs_by_result() _test_phase_text_nonempty() _test_boss_name_uses_boss_rowset() + _test_level_clear_wording() quit(Kit.finish("battle_narrator_test")) @@ -36,9 +37,9 @@ func _test_numeric_lines_carry_values() -> void: func _test_end_text_differs_by_result() -> void: - # 关卡收束(level_end=true)恒为「关卡通关!」——单场胜负文案只在非收束态出现 + # 关卡收束(level_end=true)恒为「关卡完成!」——单场胜负文案只在非收束态出现 var level: String = NarratorScript.battle_end_text("lose", true) - Kit.check("关卡收束态恒为「关卡通关!」(实际「%s」)" % level, level == "关卡通关!") + Kit.check("关卡收束态恒为「关卡完成!」(实际「%s」)" % level, level == "关卡完成!") var win: String = NarratorScript.battle_end_text("victory", false) var lose: String = NarratorScript.battle_end_text("lose", false) Kit.check("单场胜负文案互异(胜「%s」/负「%s」)" % [win, lose], win != lose) @@ -80,3 +81,21 @@ func _test_boss_name_uses_boss_rowset() -> void: var got: String = NarratorScript.boss_name(runner, db) Kit.check("Boss 名取自 Boss 行集首行(期望「%s」实际「%s」)〔fv24〕" % [boss_expect, got], got == boss_expect) Kit.check("Boss 名与同深度战斗行集名不同(期望「%s」≠「%s」——行类路由可判别)〔fv24〕" % [boss_expect, battle_name], boss_expect != battle_name) + + +# 关卡完成停点文案族措辞钉子(通关口径换代批):回血行/满血合法态/渠道句/摘要关数行—— +# 「通关」退役后玩家可见面由本组断言钉在新措辞上(撤销证明:回退 battle_narrator 对应行→断言红→复原复绿) +func _test_level_clear_wording() -> void: + var healed: String = NarratorScript.curio_pick_header({"level_index": 1, "heal_gained": 5, "hp_before": 10, "hp_after": 15}) + Kit.check("关卡完成回血行带入回血量与生命区间(实际「%s」)〔通关换代 V1〕" % healed, + healed.contains("关卡完成回血 +5(生命 10 → 15)")) + var full_hp: String = NarratorScript.curio_pick_header({"level_index": 1, "heal_gained": 0, "hp_before": 12, "hp_after": 12}) + Kit.check("满血零回血合法态文案(实际「%s」)〔通关换代 V1〕" % full_hp, + full_hp.contains("生命已满——关卡完成回血 0(合法态)")) + var node_header: String = NarratorScript.node_curio_header() + Kit.check("奖励节点头部行渠道句点明关卡完成三选一(实际「%s」)〔通关换代 V2〕" % node_header, + node_header.contains("与关卡完成专长三选一同库分流")) + var summary: String = NarratorScript.adventure_summary_text( + {"cleared": false, "result": "failed", "levels_cleared": 1, "stopped_at": 2, "keystone_total": 4, "master_seed": 42}) + Kit.check("冒险摘要完成关数行(实际「%s」)〔通关换代 V3〕" % summary, + summary.contains("完成 1 关 · 止步第 2 层") and not summary.contains("通关"))