Files
gplan-2/game/presentation/debug_session.gd
DKChan 1b9736f065 fix(iter37①): T1 core 域缺陷修——单据归属判定/数值入表/公式单点/信号契约载体统一
- d1 伤害控制器来源敌作废判定 `==`→`is_same`(同内容异实例不再误废;夹具双敌两断言〔wd1〕)
- d11 shop 表新增 relic_base_price/spend_discount 两 knob+域检+ConfigDB 访问器+level_runner 读表;
  level_shop_economy_test 三表值断言+relic 现价读表与迁移前字面量逐位等价〔wd11〕
- d16a HeroTable.display_name+域检+访问器+unit_container 读表;spawn 真实链断言〔wd16〕
- d14 board_generator 目标雷数公式单点 target_mine_count(两调用点改引)+legality 去 db 参数(两调用点同批改)〔wd14〕
- d15 蓄力层上限 CHARGE_LAYER_CAP 常量(两处字面量+注释随动)
- d16b unit_container/status_container 六处 Dictionary 取值显式 int() 包裹(读侧包)
- d10 minesweeper 两信号按 §2.1 三要素补契约(载荷键集按发射位并集实查)+全库 28 处信号注释载体 #→##

撤销证明:回退 d1 hunk → 同容异实例断言红(A 单据被 B 死亡误废),还原复绿;
回退 d10 契约 → 契约在位扫描 undocumented=2 红,还原归零。等价类申报(d11/d14/d15/d16)见实现报告。
代拍板:#1 target_mine_count 签名(照接口块)、#2 契约措辞与载荷键并集(实查发射位)、#4 int() 读侧包写法。
2026-10-25 03:35:55 +08:00

83 lines
3.5 KiB
GDScript
Raw Permalink 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
## 调试模式编排控制器:单场遭遇与连续两层(HP 关内延续)的模式状态机与战斗生命周期。
## 信号接线唯一归组合根——battle_created 必须先于 begin_battle 完成接线;玩家意图写调用(settle_batch/刷新)不经本类。
## 加成生效值经注入 Callable 现算、随 encounter 显式传参——零表写。
extends RefCounted
signal battle_created(settlement, level: int, carry_hp: int) ## begin_battle 前——组合根完成信号接线
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
# 单场遭遇原语(无单场用户入口——本方法仅 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[Variant, Variant] = _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