fix(rules): allow a Will save to halve channeled energy damage

PF1e CRB (Channel Energy): creatures damaged by channeled energy get a Will
save (DC 10 + half the channeler's level + her Charisma modifier) for half
damage (floor). Harm mode only; heal mode unchanged. Charisma is used RAW
even for casters whose spellcasting ability differs (channeling is a
Charisma class feature).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-09-11 20:24:51 +02:00
parent 6f784d3369
commit e321c67779
3 changed files with 47 additions and 12 deletions
+19 -2
View File
@@ -155,15 +155,32 @@ def test_oni_channel_harm_does_not_damage_living_enemy() -> None:
def test_oni_channel_harm_damages_undead() -> None:
"""Harm mode damages undead creatures in the burst regardless of side."""
"""Harm mode damages undead creatures in the burst regardless of side;
a failed Will save takes full damage (CRB Channel Energy)."""
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])
engine, me, enemy = _engine(oni, [lich], rng_queue=[11, 5])
action = Action(kind="channel_energy", target_id=lich.id, channel_mode="harm")
engine._execute(me, action)
assert enemy[0].hp == 100 - (1 + 11) # 2d6 = 1 + roll_die(11)
# Will save fails: d20 5 + will 4 = 9 < DC 14 (10 + lvl//2 2 + cha 2)
assert any("Will DC14" in line and "FAILED full" in line for line in engine._transcript)
def test_oni_channel_harm_will_save_halves_damage() -> None:
"""CRB Channel Energy: an undead that passes the Will save takes half
damage (floor)."""
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, 20])
action = Action(kind="channel_energy", target_id=lich.id, channel_mode="harm")
engine._execute(me, action)
assert enemy[0].hp == 100 - (1 + 11) // 2 # 2d6 = 12, saved for half = 6
assert any("Will DC14" in line and "SAVED half" in line for line in engine._transcript)
def test_oni_channel_heal_heals_living_enemies_in_range() -> None: