fix(rules): firing into melee exemption measured target-to-nearest-ally, not attacker-to-target (SRD Shooting into a Melee)
This commit is contained in:
@@ -338,11 +338,13 @@ def test_firing_into_melee_minus4() -> None:
|
||||
assert t.hp == 100
|
||||
|
||||
|
||||
def test_firing_into_melee_avoided_when_target_10ft_away() -> None:
|
||||
def test_firing_into_melee_not_avoided_when_ally_engaged_5ft_away() -> None:
|
||||
# PF1e (SRD "Attack" — Shooting or Throwing into a Melee): "If your target
|
||||
# [...] is at least 10 feet away from the nearest friendly character, you
|
||||
# can avoid the -4 penalty" — the 10+ ft clause is 0, not -2 (the -2 is
|
||||
# reserved for targets two size categories larger, not modeled).
|
||||
# can avoid the -4 penalty" — the exemption is measured from the TARGET to
|
||||
# the attacker's nearest friendly character, not from the attacker. The
|
||||
# archer is 10 ft from the target, but the target is engaged at 5 ft by
|
||||
# the archer's own ally (the guard) -> the -4 still applies.
|
||||
archer = _combatant("archer", ac=99, attacks=(_bow("archer", attack_bonus=8),))
|
||||
tgt = _combatant("tgt", ac=15, attacks=(_bow("tgt"),))
|
||||
guard = _combatant("guard", ac=99)
|
||||
@@ -354,8 +356,32 @@ def test_firing_into_melee_avoided_when_target_10ft_away() -> None:
|
||||
)
|
||||
a, t, _g = eng._states
|
||||
result = eng.resolve_attack(a, t, a.combatant.attacks[0])
|
||||
assert result.total == 17
|
||||
assert result.melee_penalty == -4
|
||||
assert result.total == 13
|
||||
assert result.hit is False
|
||||
assert t.hp == 100
|
||||
|
||||
|
||||
def test_firing_into_melee_avoided_when_nearest_ally_20ft_away() -> None:
|
||||
# The target is engaged (a third-party melee threat stands next to it),
|
||||
# but the attacker's nearest friendly character is 20 ft from the target
|
||||
# -> the -4 is avoided even though the archer itself is only 5 ft away.
|
||||
# The OLD (buggy) rule measured attacker->target/attacker->threat and
|
||||
# would wrongly apply the -4 here.
|
||||
archer = _combatant("archer", ac=99, attacks=(_bow("archer", attack_bonus=8),))
|
||||
tgt = _combatant("tgt", ac=15, attacks=(_bow("tgt"),))
|
||||
ally = _combatant("ally", ac=99)
|
||||
raider = _combatant("raider") # neither the archer's side nor the target's
|
||||
eng = _engine(
|
||||
[archer, tgt, ally, raider],
|
||||
[(0, 0), (0, 1), (0, 5), (1, 2)],
|
||||
["players", "monsters", "players", "gnolls"],
|
||||
[10, 3],
|
||||
)
|
||||
a, t, _al, _r = eng._states
|
||||
result = eng.resolve_attack(a, t, a.combatant.attacks[0])
|
||||
assert result.melee_penalty == 0
|
||||
assert result.total == 18
|
||||
assert result.hit is True
|
||||
assert result.damage == 3
|
||||
|
||||
|
||||
Reference in New Issue
Block a user