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>
This commit is contained in:
2026-07-21 15:35:11 +08:00
co-authored by Claude Opus 4.8
parent 0fd01caebb
commit 4725c57c72
3 changed files with 7 additions and 4 deletions
@@ -324,9 +324,9 @@ func execute_compiled(compiled: CompiledDeck, caster_id: int, spawn_pos: Vector2
var persistent: bool = compiled.feature_tags == CoreFeatureTag.PERSISTENT_MEMORY
var ctx: SpellContext = _acquire_ctx(caster_id, persistent)
ctx.hp_cost_accum = 0.0
ctx.mana_spent_this_cast = false
var infinite: bool = compiled.feature_tags == CoreFeatureTag.INFINITE_SPELLS
var heat_mult: float = 1.0 + PlayerStats.mana_heat
var cast_fired: bool = false
var deck: SpellDeck = compiled.make_runtime_deck()
var ops_count: int = 0
var max_ops: int = MAX_OPS_PER_CPU * 5
@@ -337,8 +337,6 @@ func execute_compiled(compiled: CompiledDeck, caster_id: int, spawn_pos: Vector2
var mana_cost: float = float(node.meta.get("mana_cost", 0.0))
if not _charge_mana(mana_cost, ctx, infinite, heat_mult):
break # 蓝不足且非 infinite → 停施
if mana_cost > 0.0:
cast_fired = true
match node.type:
SpellNode.SpellType.ACTION:
_push_projectile(node, ctx, spawn_pos, -1)
@@ -364,7 +362,7 @@ func execute_compiled(compiled: CompiledDeck, caster_id: int, spawn_pos: Vector2
break
if ctx.hp_cost_accum > 0.0:
PlayerStats.spend_hp_cost(minf(ctx.hp_cost_accum, PlayerStats.hp_max * SettingsManager.hp_cost_cap_ratio()))
if cast_fired:
if ctx.mana_spent_this_cast:
PlayerStats.mana_heat = minf(SettingsManager.mana_heat_max(), PlayerStats.mana_heat + SettingsManager.mana_heat_per_cast())
if ops_count >= max_ops:
push_warning("SpellEvaluator: MAX_OPS reached (caster=%d)" % caster_id)
@@ -501,6 +499,7 @@ func _charge_mana(base_cost: float, ctx: SpellContext, infinite: bool, heat_mult
if base_cost <= 0.0:
return true
if PlayerStats.spend_mana(base_cost * heat_mult):
ctx.mana_spent_this_cast = true # 真实扣蓝才记(infinite 卖血不算)→ heat 只对真实施法上升
return true
if infinite:
ctx.hp_cost_accum += SettingsManager.infinite_hp_per_shot()