diff --git a/src/rendering/m2_renderer.cpp b/src/rendering/m2_renderer.cpp index 494cbc8e..a8682006 100644 --- a/src/rendering/m2_renderer.cpp +++ b/src/rendering/m2_renderer.cpp @@ -2544,7 +2544,7 @@ bool M2Renderer::checkCollision(const glm::vec3& from, const glm::vec3& to, if (allowEscapeRelax) { continue; } - if (stepableLowObject && localFrom.z >= rawMax.z - 0.35f) { + if (stepableLowObject && localFrom.z >= effectiveTop - 0.35f) { // Already on/near top surface: don't apply lateral push that ejects // the player from the object (carpets, platforms, etc). continue; diff --git a/src/rendering/wmo_renderer.cpp b/src/rendering/wmo_renderer.cpp index 8a8b8bf9..ad437d81 100644 --- a/src/rendering/wmo_renderer.cpp +++ b/src/rendering/wmo_renderer.cpp @@ -2037,8 +2037,16 @@ bool WMORenderer::checkWallCollision(const glm::vec3& from, const glm::vec3& to, float side = fromDist > 0.0f ? 1.0f : -1.0f; glm::vec3 safeLocal = hitPoint + normal * side * (PLAYER_RADIUS + 0.05f); glm::vec3 pushLocal(safeLocal.x - localTo.x, safeLocal.y - localTo.y, 0.0f); - localTo.x = safeLocal.x; - localTo.y = safeLocal.y; + // Cap swept pushback so walls don't shove the player violently + float pushLen = glm::length(glm::vec2(pushLocal.x, pushLocal.y)); + const float MAX_SWEPT_PUSH = 0.15f; + if (pushLen > MAX_SWEPT_PUSH) { + float scale = MAX_SWEPT_PUSH / pushLen; + pushLocal.x *= scale; + pushLocal.y *= scale; + } + localTo.x += pushLocal.x; + localTo.y += pushLocal.y; glm::vec3 pushWorld = glm::vec3(instance.modelMatrix * glm::vec4(pushLocal, 0.0f)); adjustedPos.x += pushWorld.x; adjustedPos.y += pushWorld.y;