- 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() 读侧包写法。
83 lines
3.5 KiB
GDScript
83 lines
3.5 KiB
GDScript
## 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
|