复审 nit: - heat 之前仅在主循环 cast_fired 记录,LOOP 体/CIRCUIT 分支扣蓝漏记 → 递增蓝耗对这两类拓扑失效。 改为 _charge_mana 真实 spend_mana 成功时置 ctx.mana_spent_this_cast,施法末据此升 heat。 - 顺带修正 infinite 卖血(未真实扣蓝)也升 heat 的问题:卖血不升热。 - combat_manager._on_player_died 加 GAME_OVER 防重入(子弹命中+卖血同帧双死不重复结算)。 MCP 实测:LOOP heat 0.010(修复前0)、卖血 heat 0、线性回归 0.010。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
49 lines
1.7 KiB
GDScript
49 lines
1.7 KiB
GDScript
## SpellContext — 法术执行上下文(对象池化)
|
||
## 权威来源:architecture_design.md §3.2, implementation_plan.md §2.2
|
||
## registers 跨帧持久(LOGIC_EVERY_N_SHOTS 必须使用此处,禁用 CastState.registers)
|
||
extends RefCounted
|
||
class_name SpellContext
|
||
|
||
var caster_id: int = 0
|
||
var stats: CastStats = null # 本次施法的修改层
|
||
## 跨帧持久寄存器(长度固定 4,P6-N48)
|
||
## R1-R4:供 LOGIC_EVERY_N_SHOTS 等指令跨帧计数
|
||
var registers: PackedFloat32Array = PackedFloat32Array()
|
||
var hp_cost_accum: float = 0.0 # 本次施法累积 HP 代价(heavy_cost + infinite),施法末结算
|
||
var mana_spent_this_cast: bool = false # 本次施法是否真实扣过蓝(含 LOOP/CIRCUIT 子路径)→ 决定 heat 上升
|
||
|
||
func _init() -> void:
|
||
stats = CastStats.new()
|
||
registers.resize(4)
|
||
registers.fill(0.0)
|
||
|
||
func reset() -> void:
|
||
caster_id = 0
|
||
if stats:
|
||
stats.reset()
|
||
else:
|
||
stats = CastStats.new()
|
||
hp_cost_accum = 0.0
|
||
mana_spent_this_cast = false
|
||
# registers 小心:仅当 Core 没有 PERSISTENT_MEMORY Feature 时才清零
|
||
# 具体清空逻辑在 SpellContextPool.acquire_for_wand() 中处理
|
||
|
||
func clear_registers() -> void:
|
||
registers.fill(0.0)
|
||
|
||
|
||
## CastState — 单次 execute() 的临时工作状态(不入池,每次 new)
|
||
## 注意区分:CastState.registers 每次 execute() 开始时重置,不跨调用保留
|
||
## LOGIC_EVERY_N_SHOTS 「必须」使用 SpellContext.registers,严禁使用 CastState.registers
|
||
class CastState:
|
||
var trigger_depth: int = 0
|
||
var registers: PackedFloat32Array = PackedFloat32Array()
|
||
|
||
func _init() -> void:
|
||
registers.resize(4)
|
||
registers.fill(0.0)
|
||
|
||
func reset() -> void:
|
||
trigger_depth = 0
|
||
registers.fill(0.0)
|