Files
spellforge/scripts/domain/spell_system/spell_context.gd
T
joywayerandClaude Opus 4.8 4725c57c72 fix(mana): heat 依真实扣蓝(ctx标记)覆盖 LOOP/CIRCUIT 子路径+卖血不升热;死亡防重入
复审 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>
2026-07-21 15:35:11 +08:00

49 lines
1.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.
## 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)