diff --git a/Core/GameEngine/Include/Common/GameDefines.h b/Core/GameEngine/Include/Common/GameDefines.h index 7a6f4be4d11..1c87cd72938 100644 --- a/Core/GameEngine/Include/Common/GameDefines.h +++ b/Core/GameEngine/Include/Common/GameDefines.h @@ -87,6 +87,17 @@ #define PRESERVE_RETAIL_SCRIPTED_CAMERA (1) // Retain scripted camera behavior present in retail Generals 1.08 and Zero Hour 1.04 #endif +// Whether to preserve the 1.41x speed discrepancy between straight and diagonal movements of all objects. +#ifndef PRESERVE_RETAIL_PHYSICS_FORWARD_SPEED +#define PRESERVE_RETAIL_PHYSICS_FORWARD_SPEED (1) +#endif + +// Whether to preserve the 1.41x speed discrepancy between straight and diagonal movements of all scripted objects. +// This setting is very relevant for legacy missions and cinematic sequences. +#ifndef PRESERVE_RETAIL_SCRIPTED_PHYSICS_FORWARD_SPEED +#define PRESERVE_RETAIL_SCRIPTED_PHYSICS_FORWARD_SPEED (1) +#endif + #ifndef RETAIL_COMPATIBLE_CRC #define RETAIL_COMPATIBLE_CRC (1) // Game is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 #endif diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp index 78b256e5b88..8c9085a3e62 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp @@ -957,21 +957,39 @@ Real PhysicsBehavior::getVelocityMagnitude() const Real PhysicsBehavior::getForwardSpeed2D() const { const Coord3D *dir = getObject()->getUnitDirectionVector2D(); - Real vx = m_vel.x * dir->x; Real vy = m_vel.y * dir->y; - Real dot = vx + vy; - Real speedSquared = vx*vx + vy*vy; -// DEBUG_ASSERTCRASH( speedSquared != 0, ("zero speedSquared will overflow sqrtf()!") );// lorenzen... sanity check - - Real speed = (Real)sqrtf( speedSquared ); +#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_PHYSICS_FORWARD_SPEED + Real speed = (Real)sqrtf( vx*vx + vy*vy ); if (dot >= 0.0f) return speed; - return -speed; + +#else + +#if PRESERVE_RETAIL_SCRIPTED_PHYSICS_FORWARD_SPEED + if (const AIUpdateInterface *ai = getObject()->getAIUpdateInterface()) + { + if (ai->getLastCommandSource() == CMD_FROM_SCRIPT) + { + Real speed = (Real)sqrtf( vx*vx + vy*vy ); + if (dot >= 0.0f) + return speed; + return -speed; + } + } +#endif + + // Inverse scale len by (1 + sqrt(2)) / 2 to adjust to the average of the former min/max movement speed. + // The inverse looks intuitively wrong, but it is correct, because the value returned by this function is + // used to determine the additional velocity needed to reach the target speed. + constexpr const Real DiagonalCompensation = 1.0f / 1.20710678f; + return dot * DiagonalCompensation; + +#endif } //------------------------------------------------------------------------------------------------- @@ -982,19 +1000,40 @@ Real PhysicsBehavior::getForwardSpeed2D() const Real PhysicsBehavior::getForwardSpeed3D() const { Vector3 dir = getObject()->getTransformMatrix()->Get_X_Vector(); - Real vx = m_vel.x * dir.X; Real vy = m_vel.y * dir.Y; Real vz = m_vel.z * dir.Z; - Real dot = vx + vy + vz; - Real speed = (Real)sqrtf( vx*vx + vy*vy + vz*vz ); +#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_PHYSICS_FORWARD_SPEED + Real speed = (Real)sqrtf( vx*vx + vy*vy + vz*vz ); if (dot >= 0.0f) return speed; - return -speed; + +#else + +#if PRESERVE_RETAIL_SCRIPTED_PHYSICS_FORWARD_SPEED + if (const AIUpdateInterface *ai = getObject()->getAIUpdateInterface()) + { + if (ai->getLastCommandSource() == CMD_FROM_SCRIPT) + { + Real speed = (Real)sqrtf( vx*vx + vy*vy + vz*vz ); + if (dot >= 0.0f) + return speed; + return -speed; + } + } +#endif + + // Inverse scale len by (1 + sqrt(3)) / 2 to adjust to the average of the former min/max movement speed. + // The inverse looks intuitively wrong, but it is correct, because the value returned by this function is + // used to determine the additional velocity needed to reach the target speed. + constexpr const Real DiagonalCompensation = 1.0f / 1.36602540f; + return dot * DiagonalCompensation; + +#endif } //-------------------------------------------------------------------------------------------------