fix(rules): any concealment denies sneak attack (SRD rogue: 'a creature with concealment')

This commit is contained in:
2026-09-16 19:50:40 +02:00
parent 4d45409941
commit 2807f719ca
3 changed files with 28 additions and 25 deletions
+11 -10
View File
@@ -158,26 +158,27 @@ def test_total_concealment_denies_sneak_attack() -> None:
assert not any("sneak" in line for line in eng._transcript)
def test_partial_concealment_still_allows_sneak_attack() -> None:
"""(A7) a blurred (20%) target CAN be sneak attacked — CRB rogue text is
"cannot sneak attack while striking a creature with total concealment",
so partial concealment no longer denies the precision damage."""
def test_partial_concealment_denies_sneak_attack() -> None:
"""(A7) a blurred (20%) target CANNOT be sneak attacked — SRD rogue text
is "A rogue cannot sneak attack while striking a creature with
concealment": ANY concealment denies the precision damage (the rogue
must see the target well enough to pick out a vital spot)."""
sneak = _combatant("atk", level=3, features=("Sneak Attack",))
eng = _engine(
[sneak, _combatant("tgt")],
[(0, 0), (0, 1)],
["players", "monsters"],
[15, 90, 6, 6, 4],
[15, 90, 6],
)
a, t = eng._states
_add_condition(t, "flat_footed")
_add_condition(t, "blurred")
result = eng.resolve_attack(a, t, a.combatant.attacks[0])
# d20=15 hits, d100=90 > 20% lands; 2d6 sneak (6+6=12) + 1d6 weapon (4)
# = 16 precision-inclusive damage.
assert result.damage == 16
assert t.hp == 84
assert any("sneak attack" in line and "2d6" in line for line in eng._transcript)
# d20=15 hits, d100=90 > 20% lands; sneak denied by the 20% concealment,
# so only the 1d6 weapon die (6) lands.
assert result.damage == 6
assert t.hp == 94
assert not any("sneak" in line for line in eng._transcript)
def test_concealment_miss_does_not_consume_deed() -> None: