fix(rules): apply maneuver AoO damage as a penalty to the maneuver

PF1e (CRB Combat Maneuvers): "If you are hit by the target, you take the
damage normally and apply that amount as a penalty to the attack roll to
perform the maneuver." Capture the provoked AoO's damage in
_execute_maneuver and subtract it from the check total (floored at 0;
natural 20 still succeeds, natural 1 still fails; dropping below 0 hp
still forfeits). Escape and the Improved-feat exemption are untouched.

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 23:11:57 +02:00
parent 74bfeb5414
commit 1862c22b7b
3 changed files with 47 additions and 5 deletions
+17 -3
View File
@@ -3839,10 +3839,16 @@ class CombatEngine:
# PF1e (CRB, Combat Maneuver): attempting the maneuver provokes an
# attack of opportunity from the target — resolved BEFORE the CMB
# check — unless the attacker holds the Improved feat for it. Being
# knocked below 0 hp by that AoO forfeits the maneuver.
# check — unless the attacker holds the Improved feat for it. Damage
# taken from that AoO is applied as a penalty to the maneuver check
# (CRB: "apply that amount as a penalty to the attack roll to perform
# the maneuver"); being knocked below 0 hp by it forfeits the
# maneuver.
aoo_damage = 0
if not self._has_feat(state, _IMPROVED_MANEUVER_FEATS[maneuver]):
hp_before = state.hp
self._maneuver_provoked_aoo(state, target)
aoo_damage = max(0, hp_before - state.hp)
if not state.active:
return
@@ -3855,7 +3861,15 @@ class CombatEngine:
attacker_cmb = self._maneuver_cmb(state) - pa_amt
target_cmd = self._maneuver_cmd(target)
roll = self._rng.d20()
total = roll + attacker_cmb
# PF1e (CRB Combat Maneuvers): the provoked-AoO damage rides the
# check total (floored at 0); natural 20/1 keep their rules below.
total = max(0, roll + attacker_cmb - aoo_damage)
if aoo_damage:
self._log(
f"round {self._current_round} {state.combatant.id}: "
f"maneuver AoO dealt {aoo_damage} damage "
f"(-{aoo_damage} on the check)"
)
m = _ManeuverRoll(
roll=roll, attacker_cmb=attacker_cmb, total=total,
target_cmd=target_cmd,