fix(rules): set the slumber hex duration to the witch level

PF1e (APG Slumber): the target "remains asleep for a number of rounds equal to the witch's level" (Will negates). _hex_slumber hardcoded 1 round; it now uses the caster's level. The RAW clause that the hex ends when the target takes damage is not modeled (no wake-on-damage hook in the engine) — documented in README. Two behavioral tests pin the failed-save duration (= level) and the saved case.

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-12 12:52:52 +02:00
parent f9c369380d
commit 68699ad6c7
3 changed files with 49 additions and 3 deletions
+7 -3
View File
@@ -4783,7 +4783,10 @@ class CombatEngine:
def _hex_slumber(
self, state: CombatantState, target: CombatantState, hex_dc: int
) -> None:
"""Slumber: asleep/disabled if Will fails."""
"""Slumber (APG): the target remains asleep for a number of rounds
equal to the witch's level; a successful Will save negates.
Simplification documented in README: the RAW ending of the hex when
the target takes damage is not modeled (no wake-on-damage hook)."""
save_result = self.resolve_save(target, "will", hex_dc)
if save_result.success:
self._log(
@@ -4791,16 +4794,17 @@ class CombatEngine:
f"{target.combatant.id} -> SAVED"
)
return
rounds = state.combatant.level
target.active_conditions.append(
ActiveCondition(
condition=CONDITIONS_BY_NAME["asleep"],
rounds_left=1,
rounds_left=rounds,
source=f"hex: slumber by {state.combatant.id}",
)
)
self._log(
f"round {self._current_round} {state.combatant.id}: slumber on "
f"{target.combatant.id} -> asleep (1r)"
f"{target.combatant.id} -> asleep ({rounds}r)"
)
def _hex_cackle(self, state: CombatantState, target: CombatantState) -> None: