Files
gplan-2/game/presentation/battle_narrator.gd
T

113 lines
5.7 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VERTICAL SLICE - NOT FOR PRODUCTION
# Date: 2026-09-12(code-review 修复批——自 main.gd 拆出,规范 1.1/1.3 文案拼装独立成装配器)
# 战斗流程叙事文案装配器:组合根在模式流转点的玩家可见文案(棋盘日志横幅 / 节点行 / 终局文案 /
# 相位指示)在此统一拼装——main.gd 头注"本类不拼呈现字符串"由本类兑现。静态无状态。
# 数值口径注记:胜利文案携带的 HP/道具数 = 关卡载荷快照值(每关口径)。
extends RefCounted
# 节点进入横幅(棋盘日志——battle/boss 用;节点编号 = 行进器编号空间读面)
static func node_banner(runner, node: Dictionary, t: String) -> String:
return "[color=#e0b860]── 节点 %d/%d · %s(编号 %d)──[/color]" % [
runner.node_index + 1, runner.nodes().size(),
"Boss 房" if t == "boss" else "战斗", runner.node_id_of(node)]
static func reward_line() -> String:
return "[color=#d0c090]关卡奖励点(节点内容待定——直通)[/color]"
static func rest_line(healed: int, hp: int, max_hp: int) -> String:
return "[color=#7cc47c]恢复点:回复 %d HP(→ %d/%d)[/color]" % [healed, hp, max_hp]
# 商店房行(GP+商店房实施批——到达即开店;购买/离开归玩家意图)
static func shop_line(gp: int) -> String:
return "[color=#e0b860]商店房:金币 %d——购买即时生效,离开后选下一跳[/color]" % gp
# 选路口行(零自动推进停点——战斗胜利/兑付确认后出现)
static func route_line(candidates: Array, runner) -> String:
var names: Array = []
for cand in candidates:
names.append("节点 %d" % runner.node_id_of(cand))
return "[color=#e0b860]── 岔路口:可选下一跳 %s ──[/color]" % " / ".join(names)
# 关卡开场行(种子/加成口径注记——面板加成是否生效由调用方传入)
static func level_open_line(level_display: String, seed_val: int, atk: int, max_hp: int, boosted: bool) -> String:
return "[color=#c8a860]%s · 种子 %d · 攻击 %d / 生命 %d%s[/color]" % [
level_display, seed_val, atk, max_hp, "(含面板加成)" if boosted else ""]
# 调试开场行
static func debug_open_line(seed_val: int, level: int, level_mode: bool) -> String:
return "[color=#c8a860]种子 %d · 遭遇 %d 层%s[/color]" % [
seed_val, level, "(关卡模式 · HP 延续)" if level_mode else ""]
# 调试战斗终局文案(level_end = 关内两层模式的关卡末)
static func battle_end_text(result: String, level_end: bool) -> String:
if level_end:
return "关卡通关!"
if result == "victory":
return "战斗胜利!敌人全灭。"
return "战斗失败……探险者倒下了。"
# 相位指示文本(B 区轮次·阶段行)
static func phase_text(round_index: int, battle_result: String, waiting: bool, boss_active: bool, boss_name: String) -> String:
var boss_tag := " · Boss:%s" % boss_name if boss_active else ""
if battle_result != "":
return "第 %d 轮 · 战斗结束%s" % [round_index, boss_tag]
if waiting:
return "第 %d 轮 · 结算中%s" % [round_index, boss_tag]
return "第 %d 轮 · 挖掘中%s" % [round_index, boss_tag]
# Boss 名解析(runner Boss 节点 → enemy 表行名;缺省遗迹守卫)
static func boss_name(runner, db) -> String:
if runner != null:
var node: Dictionary = runner.current_node()
if String(node.get("type", "")) == "boss":
var row: Dictionary = db.resolve_enemy_rowset(int(runner.level_row.level_index), int(node.get("node_depth", -1)))
return String(row.get("display_name", ""))
return "遗迹守卫"
# 大奖励屏文案(冒险结构实现批——兑付三件:上限提升/血回满/钥石入账;读数 = big_reward_paid 载荷快照)
static func big_reward_text(reward: Dictionary) -> String:
return "第 %d 层通过!大奖励:生命上限 +%d(新上限 %d),生命回满,钥石 +%d(累计 %d)" % [
int(reward.get("from_level", 0)), int(reward.get("hp_bonus", 0)),
int(reward.get("new_max_hp", 0)), int(reward.get("keystone_gained", 0)),
int(reward.get("keystone_total", 0))]
# 冒险结算屏文案(摘要五件事:打穿没有 / 通关几关 / 止步第几关 / 钥石合计 / 主种子)
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" % [
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))]
# 钥石入账明细文案(元进度实现批——settle_adventure 明细的结算屏追加段:大奖励 / 逐关 Boss
# 首杀或重复两档 / 新解锁道具;name_lookup = item_id → 显示名投影,由组合根自 meta 表喂入)
static func keystone_settle_text(detail: Dictionary, name_lookup: Dictionary = {}) -> String:
var parts: Array = ["大奖励 +%d" % int(detail.get("big_reward", 0))]
for d in detail.get("boss_drops", []):
parts.append("第 %d 关 Boss %s +%d" % [int(d.get("level", 0)),
"首杀" if bool(d.get("first", false)) else "重复杀", int(d.get("amount", 0))])
var line := "钥石入账:" + " · ".join(parts)
var unlocks: Array = detail.get("new_unlocks", [])
if not unlocks.is_empty():
var names: Array = []
for iid in unlocks:
names.append(String(name_lookup.get(String(iid), String(iid))))
line += "\n工坊新解锁:" + "、".join(names)
return line + "\n本局入账合计 +%d 钥石" % int(detail.get("total", 0))