94 lines
4.3 KiB
GDScript
94 lines
4.3 KiB
GDScript
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||
# Date: 2026-09-13(封装审查 O1/O2 修复批——自 main.gd 拆出,规范 1.1 审视线 / 单一实现纪律)
|
||
# 调试模式编排控制器:单场遭遇(第 1/2 层)与连续两层(HP 关内延续)的模式状态机与战斗生命周期。
|
||
# 职责边界:层序/携带 HP + 战斗结算 生命周期编排(创建 / begin_battle)。
|
||
# 2026-09-15 格面资源批:库存与共享 地图战斗资源 随可选类道具删除下线——层间延续只剩 HP
|
||
# ("库存与 HP 关内延续"语义收窄为"HP 关内延续",O2 单一实现点随之收窄)。
|
||
# 授权先例:与 tune_sim_controller 同款(code-review 2026-09-12 批)——控制器承接模式编排,
|
||
# 组合根仍持有全部信号接线(battle_created 先于 begin_battle 发出,ADR-0001 接线唯一归组合根)
|
||
# 与终局 UI 决策;玩家意图写调用(settle_batch / 刷新)不经本类。
|
||
# E4 收口(2026-09-13):加成生效值经注入 Callable 供给(组合根从面板百分比现算)→ encounter
|
||
# 显式传入战斗——零表写,"双写叠加/双基线同步"整类隐患随表写移除。
|
||
extends RefCounted
|
||
|
||
signal battle_created(settlement, level: int, carry_hp: int) # begin_battle 前——组合根完成信号接线(ADR-0001)
|
||
signal battle_ready(settlement, level: int, carry_hp: int) # begin_battle 完成后——组合根 rebuild 棋盘 + 刷新呈现
|
||
|
||
var db
|
||
var rng # /root/RngService(组合根注入)
|
||
var _hero_override: Callable # 组合根生效值供给(→ {atk, max_hp};E4:经 encounter 传参,零表写)
|
||
var _seed_value: Callable # 组合根种子读取(LineEdit)
|
||
|
||
var _level_mode := false
|
||
var _level_battles: Array[int] = []
|
||
var _level_idx := 0
|
||
var _carry_hp := 0
|
||
var settlement = null # 当前战斗编排器(组合根在 battle_created 接线、battle_ready 接手)
|
||
|
||
|
||
func _init(db_ref, rng_ref, hero_override: Callable, seed_value: Callable) -> void:
|
||
db = db_ref
|
||
rng = rng_ref
|
||
_hero_override = hero_override
|
||
_seed_value = seed_value
|
||
|
||
|
||
func is_level_mode() -> bool:
|
||
return _level_mode
|
||
|
||
|
||
# 单场遭遇原语(2026-09-13 用户裁决:单场用户入口已删——本方法仅 ui_probe 单场段使用;
|
||
# 无延续、standalone 终局语义保留供探针战斗收尾)
|
||
func start_single(level: int) -> bool:
|
||
_level_mode = false
|
||
return _start_battle(level, -1)
|
||
|
||
|
||
# 连续两层(调试入口——HP 关内延续;首层满血开局)
|
||
func start_debug_levels() -> bool:
|
||
_level_mode = true
|
||
_level_battles = [1, 2]
|
||
_level_idx = 0
|
||
_carry_hp = 0
|
||
rng.new_adventure(_seed_value.call())
|
||
return _start_battle(_level_battles[0], -1)
|
||
|
||
|
||
# 层间"进入下一层"(组合根过渡覆盖层确认后调用)
|
||
func next_layer() -> bool:
|
||
return _start_battle(_level_battles[_level_idx], _carry_hp)
|
||
|
||
|
||
# 终局处置(组合根 battle_finished 处理器调用)→ 决策载荷:
|
||
# {outcome: "next_layer"|"level_end"|"standalone_end", layer, carry_hp}
|
||
func on_battle_finished(payload: Dictionary) -> Dictionary:
|
||
var result: String = String(payload.get("result", ""))
|
||
if result == "victory" and _level_mode and _level_idx < _level_battles.size() - 1:
|
||
_carry_hp = maxi(1, int(payload.get("hero_hp", 0))) # despawn 前捕获值
|
||
_level_idx += 1
|
||
return {"outcome": "next_layer", "layer": _level_idx, "carry_hp": _carry_hp}
|
||
var is_level_end := result == "victory" and _level_mode
|
||
return {"outcome": "level_end" if is_level_end else "standalone_end",
|
||
"layer": _level_idx, "carry_hp": _carry_hp}
|
||
|
||
|
||
# 会话复位(组合根终局出口"返回开始界面"调用)
|
||
func reset() -> void:
|
||
_level_mode = false
|
||
settlement = null
|
||
|
||
|
||
func _start_battle(level: int, carry_hp: int) -> bool:
|
||
if not _level_mode or _level_idx == 0:
|
||
rng.new_adventure(_seed_value.call())
|
||
var ov: Dictionary = _hero_override.call() # E4:生效值经 encounter 传入——零表写
|
||
settlement = BattleOrchestrator.new(db, rng)
|
||
battle_created.emit(settlement, level, carry_hp)
|
||
var hp: int = carry_hp if carry_hp > 0 else int(ov.max_hp)
|
||
if not settlement.begin_battle({"level_index": level, "node_depth": 0, "hero_hp": hp,
|
||
"hero_atk": int(ov.atk), "hero_max_hp": int(ov.max_hp)}):
|
||
push_error("[DebugSession] 战斗启动失败(level %d)" % level)
|
||
return false
|
||
battle_ready.emit(settlement, level, carry_hp)
|
||
return true
|