fix(rules): apply AC penalties to CMD
PF1e (SRD Combat Maneuvers): "Any penalties to a creature's AC also apply to its CMD." _maneuver_cmd now folds negative AC modifiers into the sum regardless of bonus type (grappled -2, other untyped penalties), and — a maneuver being a melee attack roll — the prone -4 melee AC penalty. Positive modifiers keep the eight SRD-listed types. The test that pinned the old ignore-penalties convention is updated; README documents the rule. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
+26
-4
@@ -504,9 +504,10 @@ def test_cmd_adds_eligible_ac_bonus_types() -> None:
|
||||
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).
|
||||
def test_cmd_ignores_non_ac_bonus_types_keeps_penalties() -> None:
|
||||
# Enhancement bonuses are NOT among the eight SRD-listed types — ignored.
|
||||
# But "Any penalties to a creature's AC also apply to its CMD" (SRD
|
||||
# Combat Maneuvers): the untyped -4 penalty rides the CMD.
|
||||
engine = make_engine([], [])
|
||||
state = _buffed(
|
||||
make_combatant("b"),
|
||||
@@ -515,7 +516,28 @@ def test_cmd_ignores_non_ac_bonus_types() -> None:
|
||||
StatModifier(target="ac", value=-4),
|
||||
),
|
||||
)
|
||||
assert engine._maneuver_cmd(state) == 12
|
||||
assert engine._maneuver_cmd(state) == 12 - 4
|
||||
|
||||
|
||||
def test_cmd_includes_prone_and_grappled_penalties() -> None:
|
||||
# A maneuver is a melee attack roll, so the prone -4 melee AC penalty and
|
||||
# the grappled -2 AC penalty both apply to CMD (SRD: "Any penalties to a
|
||||
# creature's AC also apply to its CMD").
|
||||
engine = make_engine([], [])
|
||||
prone = make_state(make_combatant("p"), "p", (0, 0))
|
||||
prone.active_conditions.append(
|
||||
ActiveCondition(
|
||||
condition=CONDITIONS_BY_NAME["prone"], rounds_left=1, source="test"
|
||||
)
|
||||
)
|
||||
assert engine._maneuver_cmd(prone) == 12 - 4
|
||||
grappled = make_state(make_combatant("g"), "p", (0, 1))
|
||||
grappled.active_conditions.append(
|
||||
ActiveCondition(
|
||||
condition=CONDITIONS_BY_NAME["grappled"], rounds_left=1, source="test"
|
||||
)
|
||||
)
|
||||
assert engine._maneuver_cmd(grappled) == 12 - 2
|
||||
|
||||
|
||||
def test_cmd_flat_footed_drops_dex_bonus_keeps_penalty() -> None:
|
||||
|
||||
Reference in New Issue
Block a user