From b3b1cc80c627e77c2954c387101e94ec4e5032a7 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sat, 7 Feb 2026 23:50:44 -0800 Subject: [PATCH] Fix tunnel/cave floor snapping to prevent floating through terrain selectReachableFloor now picks the floor closest to the player instead of the highest, so tunnels and caves use the WMO floor rather than the terrain surface above. --- src/rendering/camera_controller.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/rendering/camera_controller.cpp b/src/rendering/camera_controller.cpp index 244b4f9f..ee5a24b2 100644 --- a/src/rendering/camera_controller.cpp +++ b/src/rendering/camera_controller.cpp @@ -20,17 +20,23 @@ std::optional selectReachableFloor(const std::optional& terrainH, const std::optional& wmoH, float refZ, float maxStepUp) { - std::optional best; - auto consider = [&](const std::optional& h) { - if (!h) return; - if (*h > refZ + maxStepUp) return; // Ignore roofs/floors too far above us. - if (!best || *h > *best) { - best = *h; // Choose highest reachable floor. - } - }; - consider(terrainH); - consider(wmoH); - return best; + // Filter to reachable floors (not too far above) + std::optional reachTerrain; + std::optional reachWmo; + if (terrainH && *terrainH <= refZ + maxStepUp) reachTerrain = terrainH; + if (wmoH && *wmoH <= refZ + maxStepUp) reachWmo = wmoH; + + if (reachTerrain && reachWmo) { + // Both available: prefer the one closest to the player's feet. + // This prevents tunnels/caves from snapping the player up to the + // terrain surface above, while still working on top of buildings. + float distTerrain = std::abs(*reachTerrain - refZ); + float distWmo = std::abs(*reachWmo - refZ); + return (distWmo <= distTerrain) ? reachWmo : reachTerrain; + } + if (reachWmo) return reachWmo; + if (reachTerrain) return reachTerrain; + return std::nullopt; } std::optional selectHighestFloor(const std::optional& a,