fix(spells): make the bleed spell bleed
PF1e (SRD spells/bleed.md): "Saving Throw Will negates" and the target takes 1 point of damage per round. Two divergences: the JSON declared a Fortitude save, and the bleeding condition never set the engine's bleed_damage field, so the spell was a no-op. Bleed now saves Will; _apply_condition_effect sets bleed_damage = 1 when a spell applies bleeding, and _decrement_durations lands the final tick as the last bleeding condition expires before clearing the field (heal-path clearing already existed in _stop_bleeding). README updated. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1732,17 +1732,31 @@ class CombatEngine:
|
||||
return speed_mult
|
||||
|
||||
def _decrement_durations(self, state: CombatantState) -> None:
|
||||
"""Decrement duration rounds for buffs and conditions; remove expired ones."""
|
||||
"""Decrement duration rounds for buffs and conditions; remove expired ones.
|
||||
|
||||
A bleeding condition's last round ends with its bleed tick: the DoT
|
||||
lives on ``bleed_damage`` (CRB Conditions — bleeding), so the final
|
||||
damage is applied as the last condition instance expires and the
|
||||
field is cleared (mirrors ``_stop_bleeding`` on healing).
|
||||
"""
|
||||
state.active_buffs[:] = [
|
||||
ActiveBuff(modifiers=b.modifiers, rounds_left=b.rounds_left - 1, source=b.source)
|
||||
for b in state.active_buffs
|
||||
if b.rounds_left > 1
|
||||
]
|
||||
state.active_conditions[:] = [
|
||||
kept_conditions = [
|
||||
ActiveCondition(condition=c.condition, rounds_left=c.rounds_left - 1, source=c.source)
|
||||
for c in state.active_conditions
|
||||
if c.rounds_left > 1
|
||||
]
|
||||
bleeding_expired = (
|
||||
any(ac.condition.name == "bleeding" for ac in state.active_conditions)
|
||||
and not any(ac.condition.name == "bleeding" for ac in kept_conditions)
|
||||
)
|
||||
state.active_conditions[:] = kept_conditions
|
||||
if bleeding_expired and state.bleed_damage > 0:
|
||||
self._apply_bleed_damage(state)
|
||||
state.bleed_damage = 0
|
||||
|
||||
def _turn_gate(self, state: CombatantState) -> bool | None:
|
||||
"""Start-of-turn effects: bleed tick, confused d% roll, cant_act flag.
|
||||
@@ -5571,6 +5585,11 @@ class CombatEngine:
|
||||
source=f"spell: {spell_name}",
|
||||
)
|
||||
)
|
||||
if effect.condition_name == "bleeding":
|
||||
# The bleeding condition's damage-over-time is engine-driven
|
||||
# (CombatantState.bleed_damage, CRB Conditions — bleeding); the
|
||||
# SRD Bleed cantrip (spells/bleed.md) deals 1 bleed damage/round.
|
||||
target.bleed_damage = max(target.bleed_damage, 1)
|
||||
return f"{effect.condition_name} ({effect.duration_rounds}r)"
|
||||
|
||||
def _apply_heal_effect(
|
||||
|
||||
Reference in New Issue
Block a user