Skip to content

Commit 5226d55

Browse files
roumingAJenbo
authored andcommitted
lighting: fix vision through diagonally adjacent tiles
This commit fixes a very subtle case where players could see through diagonally adjacent tiles. The bug was introduced in the recent commit: 88d0cb7 ("lighting: fix long-standing issue with invisible objects (diasurgical#7901)"). The following 2D grid illustrates the bug: ``` . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # . . . . . . . # # . . . . . . . # # . . . . . . . # # . . . x . . . # # . . . . . . . # # . . . . . . . # # . . . . . . . # # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ``` Where 'x' represents the player, surrounded by walls with diagonally adjacent corners, and '.' represents visible tiles reached by vision rays cast from the player's position. The figure clearly shows that rays "leak" through corners. The fix is quite simple: stop traversing the ray if "light" can't pass through the adjacent tiles or if the ray hits a tile that doesn't allow "light" to pass through. Previously, the ray continued to be traversed even when the "light" couldn't pass through the adjacent tiles, which is incorrect and leads to the described issue. Here is the Python script which simulates the bug and the fix: https://gist.github.com/rouming/8a24789fd5d18c36c40e2b4925915d16 Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
1 parent c1e3ced commit 5226d55

1 file changed

Lines changed: 6 additions & 6 deletions

File tree

Source/lighting.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,6 @@ void DoVision(Point position, uint8_t radius, MapExplorationType doAutomap, bool
254254
if (!InDungeonBounds(rayPoint))
255255
break;
256256

257-
bool visible = true;
258-
259-
//
260257
// We've cast an approximated ray on an integer 2D
261258
// grid, so we need to check if a ray can pass through
262259
// the diagonally adjacent tiles. For example, consider
@@ -283,10 +280,13 @@ void DoVision(Point position, uint8_t radius, MapExplorationType doAutomap, bool
283280
Displacement adjacent1 = { -quadrant.deltaX, 0 };
284281
Displacement adjacent2 = { 0, -quadrant.deltaY };
285282

286-
visible = (TileAllowsLight(rayPoint + adjacent1) || TileAllowsLight(rayPoint + adjacent2));
283+
bool passesLight = (TileAllowsLight(rayPoint + adjacent1) || TileAllowsLight(rayPoint + adjacent2));
284+
if (!passesLight)
285+
// Diagonally adjacent tiles do not pass the
286+
// light further, we are done with this ray
287+
break;
287288
}
288-
if (visible)
289-
DoVisionFlags(rayPoint, doAutomap, visible);
289+
DoVisionFlags(rayPoint, doAutomap, visible);
290290

291291
bool passesLight = TileAllowsLight(rayPoint);
292292
if (!passesLight)

0 commit comments

Comments
 (0)