fix(rules): entangled casting needs DC 15+level concentration; add -4 dex_skills
This commit is contained in:
@@ -3635,17 +3635,31 @@ class CombatEngine:
|
||||
return 10 + damage_taken + spell_level
|
||||
return 15 + 2 * spell_level
|
||||
|
||||
def _entangled_concentration_dc(self, spell_level: int) -> int:
|
||||
"""SRD Table 9-1: "Entangled while casting" => DC 15 + spell level."""
|
||||
return 15 + spell_level
|
||||
|
||||
def _check_concentration(
|
||||
self, caster: CombatantState, spell_level: int, damage_taken: int
|
||||
self,
|
||||
caster: CombatantState,
|
||||
spell_level: int,
|
||||
damage_taken: int,
|
||||
*,
|
||||
dc_override: int | None = None,
|
||||
) -> bool:
|
||||
"""Concentration check: DC depends on situation.
|
||||
|
||||
PF1e (CRB): the check is d20 + caster level + the ability modifier
|
||||
used to determine bonus spells (Int/Wis/Cha) — NOT Constitution.
|
||||
Combat Casting's +4 applies only when casting defensively or while
|
||||
grappled/pinned, never for damage taken while casting.
|
||||
Combat Casting's +4 applies only when casting defensively, while
|
||||
grappled/pinned, or while entangled, never for damage taken while
|
||||
casting. ``dc_override`` pins the DC (used by the entangled gate).
|
||||
"""
|
||||
dc = self._concentration_dc(caster, spell_level, damage_taken)
|
||||
dc = (
|
||||
self._concentration_dc(caster, spell_level, damage_taken)
|
||||
if dc_override is None
|
||||
else dc_override
|
||||
)
|
||||
injured_while_casting = damage_taken > 0 and caster.grappled_with is None
|
||||
has_combat_casting = self._has_feat(caster, _COMBAT_CASTING_FEAT)
|
||||
bonus = 0 if injured_while_casting else (4 if has_combat_casting else 0)
|
||||
@@ -5836,6 +5850,18 @@ class CombatEngine:
|
||||
)
|
||||
return True
|
||||
return False
|
||||
if self._has_condition_named(caster, "entangled"):
|
||||
# PF1e (SRD Table 9-1 Concentration Check DCs): "Entangled while
|
||||
# casting" requires a DC 15 + spell level check or the spell is
|
||||
# lost. Combat Casting's +4 applies (not an injury check).
|
||||
dc = self._entangled_concentration_dc(spell_level)
|
||||
if not self._check_concentration(caster, spell_level, 0, dc_override=dc):
|
||||
self._log(
|
||||
f"round {self._current_round} {caster.combatant.id}: "
|
||||
f"casting while entangled: concentration failed (DC {dc}), "
|
||||
f"spell lost"
|
||||
)
|
||||
return True
|
||||
return self._check_casting_aoo(caster, spell_level)
|
||||
|
||||
def _spell_delivery_blocked(
|
||||
|
||||
@@ -122,13 +122,17 @@ EXHAUSTED = Condition(
|
||||
)
|
||||
|
||||
# Entangled: -2 attack, -4 DEX; half speed; can't run or charge (CRB)
|
||||
# Approximation: -2 attack, -2 AC (from -4 DEX), -2 ref (from -4 DEX)
|
||||
# Approximation: -2 attack, -2 AC (from -4 DEX), -2 ref (from -4 DEX),
|
||||
# -4 to Dexterity skills (mirrors grappled/pinned). Casting while entangled
|
||||
# requires a DC 15 + spell level concentration check — enforced in
|
||||
# ``CombatEngine._spell_cast_interrupted`` (SRD Table 9-1).
|
||||
ENTANGLED = Condition(
|
||||
name="entangled",
|
||||
modifiers=(
|
||||
StatModifier(target="attack", value=-2),
|
||||
StatModifier(target="ac", value=-2),
|
||||
StatModifier(target="ref", value=-2),
|
||||
StatModifier(target="dex_skills", value=-4), # -4 to Dex skills
|
||||
),
|
||||
cant_charge=True,
|
||||
speed_mult=0.5,
|
||||
|
||||
Reference in New Issue
Block a user