fix(stats): channel-energy heal is no longer counted as damage_dealt (attrition tracks damage only, README 'dégâts infligés/subis'; consistent with spell HealEffect which is counted nowhere) - harm mode still records damage_dealt/damage_taken, pinned by new tests

This commit is contained in:
2026-09-19 16:52:04 +02:00
parent 24e208ea41
commit 2e2873f331
2 changed files with 40 additions and 1 deletions
+3 -1
View File
@@ -5652,7 +5652,9 @@ class CombatEngine:
if affected_state.hp < 0: if affected_state.hp < 0:
affected_state.stabilized_hp = affected_state.hp affected_state.stabilized_hp = affected_state.hp
actual = affected_state.hp - old_hp actual = affected_state.hp - old_hp
self._stats[state.combatant.id].damage_dealt += actual # Healing is NOT damage dealt: the attrition counters track damage only
# (README "degats infligés/subis"), consistent with spell healing
# (HealEffect), which is counted nowhere.
self._stop_bleeding(affected_state) self._stop_bleeding(affected_state)
self._log( self._log(
f"round {self._current_round} {state.combatant.id}: " f"round {self._current_round} {state.combatant.id}: "
+37
View File
@@ -202,6 +202,43 @@ def test_oni_channel_heal_heals_living_enemies_in_range() -> None:
assert enemy[0].hp == min(2 + (1 + 5), 6) # healed, capped at hp_max assert enemy[0].hp == min(2 + (1 + 5), 6) # healed, capped at hp_max
def test_oni_channel_heal_is_not_counted_as_damage_dealt() -> None:
"""Attrition counts damage only (README "dégâts infligés/subis"): channel
healing restores hp but must leave damage_dealt at 0, while the harm mode
of the same feature still records its damage."""
oni = _combatant("oni", resources={"channel_energy": 6}, hp_max=30)
goblin = _combatant("goblin", hp_max=6)
engine, me, enemy = _engine(oni, [goblin], rng_queue=[5])
enemy[0].hp = 2
engine._execute(
me,
Action(kind="channel_energy", target_id=me.combatant.id, channel_mode="heal"),
)
assert enemy[0].hp == 6 # the heal itself still lands
assert engine._stats["oni"].damage_dealt == 0
assert engine._stats["oni"].damage_taken == 0
assert engine._stats["goblin"].damage_taken == 0
def test_oni_channel_harm_is_counted_as_damage_dealt() -> None:
"""The damage mode of the same feature still records damage_dealt and
damage_taken (a failed Will save takes full 2d6)."""
oni = _combatant("oni", resources={"channel_energy": 6}, hp_max=30)
lich = _combatant("lich", hp_max=100, creature_type="undead")
engine, me, enemy = _engine(oni, [lich], rng_queue=[11, 5])
engine._execute(
me, Action(kind="channel_energy", target_id=lich.id, channel_mode="harm")
)
dealt = 1 + 11 # 2d6 scripted, save failed
assert enemy[0].hp == 100 - dealt
assert engine._stats["oni"].damage_dealt == dealt
assert engine._stats["lich"].damage_taken == dealt
def test_oni_emits_channel_harm_only_for_grouped_undead() -> None: def test_oni_emits_channel_harm_only_for_grouped_undead() -> None:
"""Channel harm is emitted only when at least 2 undead enemies are grouped at 30ft """Channel harm is emitted only when at least 2 undead enemies are grouped at 30ft
— living enemies are never harmed by positive energy.""" — living enemies are never harmed by positive energy."""