fix(rules): line spells stop at a line-of-effect barrier (SRD aiming-a-spell.md: a line 'extends to the limit of its range or until it strikes a barrier that blocks line of effect') - line_cells truncates at the first blocks_los cell, creatures behind a solid wall are never caught
This commit is contained in:
@@ -14,8 +14,12 @@ PF1e (CRB, Magic — Aiming a Spell):
|
||||
line's length. The line "starts from any corner of your square", so the
|
||||
CASTER's own square is NOT one of the affected squares: the affected
|
||||
squares are the ones beyond the origin along the ray (SRD Lightning Bolt:
|
||||
"The bolt begins at your fingertips" — it leaves your square, it does not
|
||||
fill it).
|
||||
"The bolt begins at your fingertips" - it leaves your square, it does not
|
||||
fill it). The line also stops at the first square that blocks line of
|
||||
effect (CRB, Magic - Aiming a Spell, Line: it "extends to the limit of its
|
||||
range or until it strikes a barrier that blocks line of effect"): the
|
||||
barrier square itself and everything beyond it are outside the template,
|
||||
so a bolt never reaches creatures behind a solid wall.
|
||||
|
||||
Bursts need no template here: they are circles around a center cell and are
|
||||
resolved by ``CombatEngine._creatures_in_range`` (unchanged).
|
||||
@@ -78,10 +82,13 @@ def line_cells(
|
||||
The line runs along the Bresenham ray from the origin toward ``aim``,
|
||||
extended to ``length_cells`` squares (CRB: it "extends to the limit of
|
||||
its range"). The line "starts from any corner of your square" (CRB, Magic
|
||||
— Aiming a Spell), so the CASTER's own square is NOT affected: the
|
||||
- Aiming a Spell), so the CASTER's own square is NOT affected: the
|
||||
``length_cells`` affected squares are the ones *beyond* the origin along
|
||||
the ray. Out-of-bounds cells simply drop out of the template (creatures
|
||||
only exist in bounds). A degenerate aim (origin == aim) affects nothing.
|
||||
only exist in bounds). The ray stops at the first cell that blocks line
|
||||
of effect (CRB, Line: "or until it strikes a barrier that blocks line of
|
||||
effect") - that barrier cell and everything beyond it are excluded. A
|
||||
degenerate aim (origin == aim) affects nothing.
|
||||
"""
|
||||
if length_cells <= 0:
|
||||
return frozenset()
|
||||
@@ -98,7 +105,14 @@ def line_cells(
|
||||
# 120 ft / 5 ft = 24 squares, none of them the caster's own (SRD Lightning
|
||||
# Bolt: "The bolt begins at your fingertips" — it leaves your square).
|
||||
ray = _bresenham(origin, end)
|
||||
return frozenset(cell for cell in ray[1 : length_cells + 1] if grid.in_bounds(cell))
|
||||
cells: list[Pos] = []
|
||||
for cell in ray[1 : length_cells + 1]:
|
||||
if not grid.in_bounds(cell):
|
||||
continue
|
||||
if grid.terrain_at(cell).blocks_los:
|
||||
break
|
||||
cells.append(cell)
|
||||
return frozenset(cells)
|
||||
|
||||
|
||||
def _bresenham(start: Pos, end: Pos) -> list[Pos]:
|
||||
|
||||
Reference in New Issue
Block a user