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.
This commit is contained in:
Kelsi 2026-02-07 23:50:44 -08:00
parent 7a2bb28dc0
commit b3b1cc80c6

View file

@ -20,17 +20,23 @@ std::optional<float> selectReachableFloor(const std::optional<float>& terrainH,
const std::optional<float>& wmoH, const std::optional<float>& wmoH,
float refZ, float refZ,
float maxStepUp) { float maxStepUp) {
std::optional<float> best; // Filter to reachable floors (not too far above)
auto consider = [&](const std::optional<float>& h) { std::optional<float> reachTerrain;
if (!h) return; std::optional<float> reachWmo;
if (*h > refZ + maxStepUp) return; // Ignore roofs/floors too far above us. if (terrainH && *terrainH <= refZ + maxStepUp) reachTerrain = terrainH;
if (!best || *h > *best) { if (wmoH && *wmoH <= refZ + maxStepUp) reachWmo = wmoH;
best = *h; // Choose highest reachable floor.
} if (reachTerrain && reachWmo) {
}; // Both available: prefer the one closest to the player's feet.
consider(terrainH); // This prevents tunnels/caves from snapping the player up to the
consider(wmoH); // terrain surface above, while still working on top of buildings.
return best; 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<float> selectHighestFloor(const std::optional<float>& a, std::optional<float> selectHighestFloor(const std::optional<float>& a,