fix(rules): Combat Casting's +4 no longer applies to the entangled concentration check (SRD combat-casting: the feat covers only casting defensively or while grappled)
This commit is contained in:
@@ -3809,14 +3809,19 @@ class CombatEngine:
|
|||||||
damage_taken: int,
|
damage_taken: int,
|
||||||
*,
|
*,
|
||||||
dc_override: int | None = None,
|
dc_override: int | None = None,
|
||||||
|
combat_casting_applies: bool = True,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Concentration check: DC depends on situation.
|
"""Concentration check: DC depends on situation.
|
||||||
|
|
||||||
PF1e (CRB): the check is d20 + caster level + the ability modifier
|
PF1e (CRB): the check is d20 + caster level + the ability modifier
|
||||||
used to determine bonus spells (Int/Wis/Cha) — NOT Constitution.
|
used to determine bonus spells (Int/Wis/Cha) — NOT Constitution.
|
||||||
Combat Casting's +4 applies only when casting defensively, while
|
Combat Casting's +4 applies only when casting defensively or while
|
||||||
grappled/pinned, or while entangled, never for damage taken while
|
grappled (SRD feats/combat-casting.md: "a +4 bonus on concentration
|
||||||
casting. ``dc_override`` pins the DC (used by the entangled gate).
|
checks made to cast a spell or use a spell-like ability when
|
||||||
|
casting on the defensive or while grappled") - never for damage
|
||||||
|
taken while casting, never while entangled. ``combat_casting_applies``
|
||||||
|
is passed False by the situations outside the feat (entangled);
|
||||||
|
``dc_override`` pins the DC (used by the entangled gate).
|
||||||
"""
|
"""
|
||||||
dc = (
|
dc = (
|
||||||
self._concentration_dc(caster, spell_level, damage_taken)
|
self._concentration_dc(caster, spell_level, damage_taken)
|
||||||
@@ -3824,7 +3829,9 @@ class CombatEngine:
|
|||||||
else dc_override
|
else dc_override
|
||||||
)
|
)
|
||||||
injured_while_casting = damage_taken > 0 and caster.grappled_with is None
|
injured_while_casting = damage_taken > 0 and caster.grappled_with is None
|
||||||
has_combat_casting = self._has_feat(caster, _COMBAT_CASTING_FEAT)
|
has_combat_casting = (
|
||||||
|
combat_casting_applies and self._has_feat(caster, _COMBAT_CASTING_FEAT)
|
||||||
|
)
|
||||||
bonus = 0 if injured_while_casting else (4 if has_combat_casting else 0)
|
bonus = 0 if injured_while_casting else (4 if has_combat_casting else 0)
|
||||||
roll = self._rng.d20()
|
roll = self._rng.d20()
|
||||||
total = (
|
total = (
|
||||||
@@ -6168,9 +6175,14 @@ class CombatEngine:
|
|||||||
if self._has_condition_named(caster, "entangled"):
|
if self._has_condition_named(caster, "entangled"):
|
||||||
# PF1e (SRD Table 9-1 Concentration Check DCs): "Entangled while
|
# PF1e (SRD Table 9-1 Concentration Check DCs): "Entangled while
|
||||||
# casting" requires a DC 15 + spell level check or the spell is
|
# casting" requires a DC 15 + spell level check or the spell is
|
||||||
# lost. Combat Casting's +4 applies (not an injury check).
|
# lost. Combat Casting's +4 does NOT apply: the feat covers only
|
||||||
|
# "casting on the defensive or while grappled" (SRD
|
||||||
|
# feats/combat-casting.md).
|
||||||
dc = self._entangled_concentration_dc(spell_level)
|
dc = self._entangled_concentration_dc(spell_level)
|
||||||
if not self._check_concentration(caster, spell_level, 0, dc_override=dc):
|
if not self._check_concentration(
|
||||||
|
caster, spell_level, 0,
|
||||||
|
dc_override=dc, combat_casting_applies=False,
|
||||||
|
):
|
||||||
self._log(
|
self._log(
|
||||||
f"round {self._current_round} {caster.combatant.id}: "
|
f"round {self._current_round} {caster.combatant.id}: "
|
||||||
f"casting while entangled: concentration failed (DC {dc}), "
|
f"casting while entangled: concentration failed (DC {dc}), "
|
||||||
|
|||||||
@@ -211,10 +211,12 @@ class TestEntangledCasting:
|
|||||||
engine, c = self._entangled_engine(11)
|
engine, c = self._entangled_engine(11)
|
||||||
assert engine._spell_cast_interrupted(c, 1, cast_defensively=False) is False
|
assert engine._spell_cast_interrupted(c, 1, cast_defensively=False) is False
|
||||||
|
|
||||||
def test_combat_casting_helps_while_entangled(self) -> None:
|
def test_combat_casting_does_not_help_while_entangled(self) -> None:
|
||||||
# d20 7 + level 5 + wis 0 + 4 = 16 >= 16 -> PASS with the feat.
|
# SRD feats/combat-casting.md: the +4 covers only "casting on the
|
||||||
|
# defensive or while grappled" - NOT the entangled check. d20 7 +
|
||||||
|
# level 5 + wis 0 = 12 < DC 16 -> spell lost even with the feat.
|
||||||
engine, c = self._entangled_engine(7, combat_casting=True)
|
engine, c = self._entangled_engine(7, combat_casting=True)
|
||||||
assert engine._spell_cast_interrupted(c, 1, cast_defensively=False) is False
|
assert engine._spell_cast_interrupted(c, 1, cast_defensively=False) is True
|
||||||
|
|
||||||
def test_entangled_carries_minus4_dex_skills(self) -> None:
|
def test_entangled_carries_minus4_dex_skills(self) -> None:
|
||||||
mods = {m.target: m.value for m in ENTANGLED.modifiers}
|
mods = {m.target: m.value for m in ENTANGLED.modifiers}
|
||||||
|
|||||||
Reference in New Issue
Block a user