From ccb97331a91046109bb49ec7bdfe73841e68a4c1 Mon Sep 17 00:00:00 2001 From: Josh Anderson Date: Fri, 10 Jul 2026 10:11:38 -0500 Subject: [PATCH] Fix invisible fall-velocity buildup during Deeprun tram rides Z is intentionally locked to the tram deck while riding (the tunnel has no real floor), but CameraController's own gravity/jump physics kept running underneath that lock every frame since grounded never went true on a moving M2 deck. verticalVelocity silently grew toward terminal velocity for the whole ride and unleashed all at once the instant the lock released at disembark, clipping the player through the floor at "a weird angle." It also explains why jump appeared to do nothing while riding, since canJump requires a recent grounded frame that a tram ride never produces. Added CameraController::suppressVerticalPhysics() (zeroes verticalVelocity, forces grounded true) and call it every frame the Deeprun tram Z-lock is active. --- include/rendering/camera_controller.hpp | 10 ++++++++++ src/core/application.cpp | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/rendering/camera_controller.hpp b/include/rendering/camera_controller.hpp index 4585214b..7b2145f6 100644 --- a/include/rendering/camera_controller.hpp +++ b/include/rendering/camera_controller.hpp @@ -82,6 +82,16 @@ public: bool isGrounded() const { return grounded; } bool isJumping() const { return !grounded && verticalVelocity > 0.0f; } bool isFalling() const { return !grounded && verticalVelocity <= 0.0f; } + + // Call every frame while riding a transport that forces Z to a locked value + // externally (e.g. the Deeprun Tram, which has no real floor mid-tunnel). + // Without this, gravity keeps integrating verticalVelocity every frame since + // grounded never goes true on a moving M2 deck, even though the position + // itself is being overwritten and looks static - the huge fall speed that + // silently built up over the whole ride would then unleash all at once the + // instant the external Z lock releases at disembark, clipping the player + // through the floor. + void suppressVerticalPhysics() { verticalVelocity = 0.0f; grounded = true; } bool isJumpKeyPressed() const { return jumpBufferTimer > 0.0f; } bool isSprinting() const; bool isMovingForward() const { return moveForwardActive; } diff --git a/src/core/application.cpp b/src/core/application.cpp index 19a60e22..e0243eb0 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -1655,6 +1655,17 @@ void Application::update(float deltaTime) { } } } + // Z is fully locked for the Deeprun tram (see below), so + // CameraController's own gravity integration never sees a + // grounded frame and silently accumulates fall velocity the + // entire ride - reported live as clipping through the world + // "at a weird angle" right after disembarking, and as being + // unable to jump while riding (coyote time never has a + // grounded frame to key off). Suppress it every frame the + // lock is active so nothing is queued up to unleash later. + if (isDeeprunTram && renderer->getCameraController()) { + renderer->getCameraController()->suppressVerticalPhysics(); + } // Thunder Bluff lifts have real floor at both ends of their travel, // so letting Z track physics while airborne (jumping) is recoverable - // the player lands back on the platform. The Deeprun Tram tunnel has