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:
+67
-1
@@ -9,7 +9,7 @@ from __future__ import annotations
|
||||
|
||||
from pf1e_simulator.combat import _SIZE_MODIFIERS, CombatantState, CombatEngine
|
||||
from pf1e_simulator.conditions import CONDITIONS_BY_NAME
|
||||
from pf1e_simulator.effects import ActiveCondition
|
||||
from pf1e_simulator.effects import ActiveBuff, ActiveCondition, StatModifier
|
||||
from pf1e_simulator.grid import Grid
|
||||
from pf1e_simulator.map import MapSpec, TerrainType
|
||||
from pf1e_simulator.models import (
|
||||
@@ -300,3 +300,69 @@ def test_small_or_larger_cmb_uses_strength() -> None:
|
||||
medium = make_state(_resized(make_combatant("m"), "Medium", 8, 18), "p", (0, 1))
|
||||
assert engine._maneuver_cmb(small) == 2 - 1 - 1 # bab + str + size
|
||||
assert engine._maneuver_cmb(medium) == 2 - 1 + 0 # bab + str + size
|
||||
|
||||
|
||||
def _buffed(spec: Combatant, mods: tuple[StatModifier, ...]) -> CombatantState:
|
||||
state = make_state(spec, "p", (0, 0))
|
||||
state.active_buffs.append(
|
||||
ActiveBuff(modifiers=mods, rounds_left=1, source="test")
|
||||
)
|
||||
return state
|
||||
|
||||
|
||||
def test_cmd_adds_eligible_ac_bonus_types() -> None:
|
||||
# SRD CMD: "A creature can also add any circumstance, deflection, dodge,
|
||||
# insight, luck, morale, profane, and sacred bonuses to AC to its CMD."
|
||||
# Medium str 10 dex 10 bab 2: base CMD 10 + (2+0+0) + 0 = 12.
|
||||
engine = make_engine([], [])
|
||||
base = make_state(make_combatant("b"), "p", (0, 0))
|
||||
assert engine._maneuver_cmd(base) == 12
|
||||
buffed = _buffed(
|
||||
make_combatant("b"),
|
||||
(
|
||||
StatModifier(target="ac", value=4, bonus_type="dodge"),
|
||||
StatModifier(target="ac", value=2, bonus_type="morale"),
|
||||
),
|
||||
)
|
||||
assert engine._maneuver_cmd(buffed) == 12 + 4 + 2
|
||||
|
||||
|
||||
def test_cmd_ignores_non_ac_bonus_types() -> None:
|
||||
# Enhancement/natural armor bonuses and untyped penalties are NOT added
|
||||
# to CMD (only the eight SRD-listed AC bonus types are).
|
||||
engine = make_engine([], [])
|
||||
state = _buffed(
|
||||
make_combatant("b"),
|
||||
(
|
||||
StatModifier(target="ac", value=2, bonus_type="enhancement"),
|
||||
StatModifier(target="ac", value=-4),
|
||||
),
|
||||
)
|
||||
assert engine._maneuver_cmd(state) == 12
|
||||
|
||||
|
||||
def test_cmd_flat_footed_drops_dex_bonus_keeps_penalty() -> None:
|
||||
# SRD CMD: "A flat-footed creature does not add its Dexterity bonus to
|
||||
# its CMD." A Dex penalty is not a bonus, so it still applies.
|
||||
engine = make_engine([], [])
|
||||
dexy = _resized(make_combatant("d"), "Medium", 10, 18) # dex +4
|
||||
flat = make_state(dexy, "p", (0, 0))
|
||||
flat.active_conditions.append(
|
||||
ActiveCondition(
|
||||
condition=CONDITIONS_BY_NAME["flat_footed"],
|
||||
rounds_left=1,
|
||||
source="test",
|
||||
)
|
||||
)
|
||||
assert engine._maneuver_cmd(make_state(dexy, "p", (0, 1))) == 10 + 2 + 4
|
||||
assert engine._maneuver_cmd(flat) == 10 + 2 # Dex bonus gone
|
||||
clumsy = _resized(make_combatant("c"), "Medium", 10, 6) # dex -2
|
||||
clumsy_flat = make_state(clumsy, "p", (0, 2))
|
||||
clumsy_flat.active_conditions.append(
|
||||
ActiveCondition(
|
||||
condition=CONDITIONS_BY_NAME["flat_footed"],
|
||||
rounds_left=1,
|
||||
source="test",
|
||||
)
|
||||
)
|
||||
assert engine._maneuver_cmd(clumsy_flat) == 10 + 2 - 2 # penalty kept
|
||||
|
||||
Reference in New Issue
Block a user