fix(rules): add AC bonuses and flat-footed Dexterity to CMD
PF1e (SRD Combat Maneuver Defense): "A creature can also add any circumstance, deflection, dodge, insight, luck, morale, profane, and sacred bonuses to AC to its CMD [...] A flat-footed creature does not add its Dexterity bonus to its CMD." _maneuver_cmd now sums the target's eligible AC bonus modifiers (plus the dodge/circumstance runtime bonuses from total defense, fight defensively and aid another) and drops the Dexterity bonus (keeping any penalty) while the target denies its Dexterity to AC. 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:
@@ -303,6 +303,15 @@ _NEIGHBOR_OFFSETS: tuple[tuple[int, int], ...] = (
|
||||
)
|
||||
|
||||
|
||||
# PF1e (SRD Combat Maneuver Defense): the AC bonus types a creature may add
|
||||
# to its CMD. Penalties and other bonus types (armor, shield, natural,
|
||||
# enhancement, competence, untyped) stay out of the CMD.
|
||||
_CMD_AC_BONUS_TYPES: frozenset[str] = frozenset({
|
||||
"circumstance", "deflection", "dodge", "insight", "luck", "morale",
|
||||
"profane", "sacred",
|
||||
})
|
||||
|
||||
|
||||
def _save_label(result: SaveResult | None) -> str:
|
||||
if result is None:
|
||||
return "NO SAVE"
|
||||
@@ -4051,8 +4060,29 @@ class CombatEngine:
|
||||
)
|
||||
|
||||
def _maneuver_cmd(self, target: CombatantState) -> int:
|
||||
if target.combatant.cmd:
|
||||
return target.combatant.cmd
|
||||
target_cmb = self._maneuver_cmb(target)
|
||||
return target.combatant.cmd or (10 + target_cmb + target.combatant.abilities.dex_mod)
|
||||
# PF1e (SRD Combat Maneuver Defense): "A creature can also add any
|
||||
# circumstance, deflection, dodge, insight, luck, morale, profane,
|
||||
# and sacred bonuses to AC to its CMD. [...] A flat-footed creature
|
||||
# does not add its Dexterity bonus to its CMD." A Dexterity penalty
|
||||
# is not a bonus, so it still applies when flat-footed.
|
||||
dex_mod = target.combatant.abilities.dex_mod
|
||||
if self.has_condition_flag(target, "denies_dex_to_ac"):
|
||||
dex_mod = min(0, dex_mod)
|
||||
ac_bonuses = resolve_modifiers(
|
||||
m
|
||||
for m in self._stat_modifiers(target, "ac")
|
||||
if m.bonus_type in _CMD_AC_BONUS_TYPES
|
||||
)
|
||||
# defensive_ac_bonus (total defense / fight defensively) is a dodge
|
||||
# bonus and aid_ac_bonus a circumstance bonus to AC — both types the
|
||||
# SRD lets a creature add to its CMD.
|
||||
return (
|
||||
10 + target_cmb + dex_mod + ac_bonuses
|
||||
+ target.defensive_ac_bonus + target.aid_ac_bonus
|
||||
)
|
||||
|
||||
def _maneuver_trip(
|
||||
self, state: CombatantState, target: CombatantState, m: _ManeuverRoll
|
||||
|
||||
Reference in New Issue
Block a user