From fa15a3de1fa064ac46e7a4c6a8573fe5f6e7fd47 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sun, 29 Mar 2026 20:14:45 -0700 Subject: [PATCH] fix: transport elapsed time lost millisecond precision after ~4.5 hours MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit elapsedTime_ was float (32-bit, ~7 significant digits). At 16384 seconds the float can only represent integers, so elapsedTime_*1000 jumps in 1-second steps — ships and elevators visibly jerk. Changed to double (53-bit mantissa) which maintains sub-millisecond precision for ~285 million years. Also changed lastServerUpdate to double to match. --- include/game/transport_manager.hpp | 6 ++++-- src/game/transport_manager.cpp | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/game/transport_manager.hpp b/include/game/transport_manager.hpp index 496380c4..57eaa6bc 100644 --- a/include/game/transport_manager.hpp +++ b/include/game/transport_manager.hpp @@ -64,7 +64,7 @@ struct ActiveTransport { bool serverYawFlipped180; // Auto-correction when server yaw is consistently opposite movement int serverYawAlignmentScore; // Hysteresis score for yaw flip detection - float lastServerUpdate; // Time of last server movement update + double lastServerUpdate; // Time of last server movement update int serverUpdateCount; // Number of server updates received // Dead-reckoning from latest authoritative updates (used only when updates are sparse). @@ -147,7 +147,9 @@ private: rendering::WMORenderer* wmoRenderer_ = nullptr; rendering::M2Renderer* m2Renderer_ = nullptr; bool clientSideAnimation_ = false; // DISABLED - use server positions instead of client prediction - float elapsedTime_ = 0.0f; // Total elapsed time (seconds) + // double: float loses millisecond precision after ~4.5 hours (2^23 / 1000), + // causing transport path interpolation to visibly jerk in long play sessions. + double elapsedTime_ = 0.0; }; } // namespace wowee::game diff --git a/src/game/transport_manager.cpp b/src/game/transport_manager.cpp index fd91c1fd..04284add 100644 --- a/src/game/transport_manager.cpp +++ b/src/game/transport_manager.cpp @@ -98,7 +98,7 @@ void TransportManager::registerTransport(uint64_t guid, uint32_t wmoInstanceId, if (transport.useClientAnimation && path.durationMs > 0) { // Seed to a stable phase based on our local clock so elevators don't all start at t=0. - transport.localClockMs = static_cast(elapsedTime_ * 1000.0f) % path.durationMs; + transport.localClockMs = static_cast(elapsedTime_ * 1000.0) % path.durationMs; LOG_INFO("TransportManager: Enabled client animation for transport 0x", std::hex, guid, std::dec, " path=", pathId, " durationMs=", path.durationMs, " seedMs=", transport.localClockMs, @@ -259,7 +259,7 @@ void TransportManager::updateTransportMovement(ActiveTransport& transport, float } // Evaluate path time - uint32_t nowMs = static_cast(elapsedTime_ * 1000.0f); + uint32_t nowMs = static_cast(elapsedTime_ * 1000.0); uint32_t pathTimeMs = 0; if (transport.hasServerClock) { @@ -1154,7 +1154,7 @@ bool TransportManager::assignTaxiPathToTransport(uint32_t entry, uint32_t taxiPa // Seed local clock to a deterministic phase if (path.durationMs > 0) { - transport.localClockMs = static_cast(elapsedTime_ * 1000.0f) % path.durationMs; + transport.localClockMs = static_cast(elapsedTime_ * 1000.0) % path.durationMs; } updateTransformMatrices(transport);