fix(rules): entangled casting needs DC 15+level concentration; add -4 dex_skills
This commit is contained in:
@@ -15,6 +15,7 @@ from __future__ import annotations
|
||||
|
||||
from pf1e_simulator.abilities import AbilitySpec
|
||||
from pf1e_simulator.combat import CombatantState, CombatEngine
|
||||
from pf1e_simulator.conditions import ENTANGLED
|
||||
from pf1e_simulator.dice import parse_dice
|
||||
from pf1e_simulator.grid import Grid
|
||||
from pf1e_simulator.map import MapSpec, TerrainType
|
||||
@@ -175,3 +176,46 @@ class TestCombatCastingPlacement:
|
||||
grappler = _combatant("grappler", cmb=3)
|
||||
engine, c, _ = _make_engine(caster, grappler, [5], grappled=True)
|
||||
assert engine._check_concentration(c, 1, damage_taken=0) is True
|
||||
|
||||
|
||||
class TestEntangledCasting:
|
||||
"""SRD Table 9-1: "Entangled while casting" => DC 15 + spell level. The
|
||||
casting gate must force the check and lose the spell on a failure."""
|
||||
|
||||
def _entangled_engine(
|
||||
self, roll: int, *, combat_casting: bool = False
|
||||
) -> tuple[CombatEngine, CombatantState]:
|
||||
caster = _combatant("caster", level=5, combat_casting=combat_casting)
|
||||
foe = _combatant("foe")
|
||||
c = CombatantState(combatant=caster, side="players", pos=(0, 0), hp=caster.hp_max)
|
||||
f = CombatantState(combatant=foe, side="monsters", pos=(3, 3), hp=foe.hp_max)
|
||||
c.conditions.append(ENTANGLED)
|
||||
legend = {".": TerrainType(type="floor", move_cost=1)}
|
||||
spec = MapSpec(name="test", terrain=tuple(["." * 4] * 4), legend=legend)
|
||||
engine = CombatEngine(ScriptedRng([roll]), Grid.from_spec(spec), [c, f])
|
||||
return engine, c
|
||||
|
||||
def test_entangled_concentration_dc_is_15_plus_spell_level(self) -> None:
|
||||
caster = _combatant("caster", level=5)
|
||||
engine = _make_engine(caster, _combatant("grappler"), [])[0]
|
||||
assert engine._entangled_concentration_dc(2) == 15 + 2
|
||||
|
||||
def test_failed_check_loses_the_spell(self) -> None:
|
||||
# DC 16 (15 + level 1). d20 10 + level 5 + wis 0 = 15 < 16 -> spell lost.
|
||||
engine, c = self._entangled_engine(10)
|
||||
assert engine._spell_cast_interrupted(c, 1, cast_defensively=False) is True
|
||||
|
||||
def test_successful_check_keeps_the_spell(self) -> None:
|
||||
# d20 11 + level 5 + wis 0 = 16 >= 16 -> pass (foe at (3,3) does not
|
||||
# threaten, so no AoO gate either).
|
||||
engine, c = self._entangled_engine(11)
|
||||
assert engine._spell_cast_interrupted(c, 1, cast_defensively=False) is False
|
||||
|
||||
def test_combat_casting_helps_while_entangled(self) -> None:
|
||||
# d20 7 + level 5 + wis 0 + 4 = 16 >= 16 -> PASS with the feat.
|
||||
engine, c = self._entangled_engine(7, combat_casting=True)
|
||||
assert engine._spell_cast_interrupted(c, 1, cast_defensively=False) is False
|
||||
|
||||
def test_entangled_carries_minus4_dex_skills(self) -> None:
|
||||
mods = {m.target: m.value for m in ENTANGLED.modifiers}
|
||||
assert mods["dex_skills"] == -4
|
||||
|
||||
Reference in New Issue
Block a user