From 88c3240f609f7a56637fdf7802e70fc9631536ce Mon Sep 17 00:00:00 2001 From: FileEX Date: Tue, 29 Jul 2025 00:26:52 +0200 Subject: [PATCH] Fix isPedOnGround --- Client/game_sa/CPedSA.h | 1 + Client/mods/deathmatch/logic/CClientPed.cpp | 12 +++++++++-- Client/mods/deathmatch/logic/CClientPed.h | 2 +- .../deathmatch/logic/luadefs/CLuaPedDefs.cpp | 4 +++- Client/sdk/game/CPed.h | 1 + Shared/mods/deathmatch/logic/Utils.cpp | 20 +++++++++++++++++++ Shared/mods/deathmatch/logic/Utils.h | 6 ++++++ 7 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index 7dbd4b0de7a..ccef53943de 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -421,6 +421,7 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra = 6) override; CEntity* GetContactEntity() const override; + bool IsStandingOnEntity() const override { return GetPedInterface()->pContactEntity != nullptr; }; int GetRunState() const override { return GetPedInterface()->moveState; } diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index a9ef955e6e3..48c99e19fc7 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -4649,12 +4649,20 @@ float CClientPed::GetDistanceFromGround() return (vecPosition.fZ - fGroundLevel); } -bool CClientPed::IsOnGround() +bool CClientPed::IsOnGround(bool checkVehicles) { CVector vecPosition; GetPosition(vecPosition); float fGroundLevel = static_cast(g_pGame->GetWorld()->FindGroundZFor3DPosition(&vecPosition)); - return (vecPosition.fZ > fGroundLevel && (vecPosition.fZ - fGroundLevel) <= 1.0f); + + if (definitelyLessThan(vecPosition.fZ, fGroundLevel)) + return false; + + bool isOnGround = definitelyLessThan((vecPosition.fZ - fGroundLevel), 1.0f) || essentiallyEqual((vecPosition.fZ - fGroundLevel), 1.0f); + if (!isOnGround && checkVehicles && m_pPlayerPed) + return m_pPlayerPed->IsStandingOnEntity(); + + return isOnGround; } bool CClientPed::IsClimbing() diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index 6f2ba652fb4..830e1fe28c1 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -374,7 +374,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule void SetInWater(bool bIsInWater) { m_bIsInWater = bIsInWater; }; bool IsInWater(); - bool IsOnGround(); + bool IsOnGround(bool checkVehicles = false); bool IsClimbing(); bool IsRadioOn() const noexcept { return m_bRadioOn; }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index 9d1dab664de..de3ad74321e 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -914,13 +914,15 @@ int CLuaPedDefs::IsPedOnGround(lua_State* luaVM) { // Verify the argument CClientPed* pPed = NULL; + bool checkVehicles = false; CScriptArgReader argStream(luaVM); argStream.ReadUserData(pPed); + argStream.ReadBool(checkVehicles, false); if (!argStream.HasErrors()) { // Find out whether he's on the ground or not and return it - bool bOnGround = pPed->IsOnGround(); + bool bOnGround = pPed->IsOnGround(checkVehicles); lua_pushboolean(luaVM, bOnGround); return 1; } diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index 6ffd9aaf6b7..fb1a6bd9953 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -253,6 +253,7 @@ class CPed : public virtual CPhysical virtual void SetFightingStyle(eFightingStyle style, std::uint8_t styleExtra) = 0; virtual CEntity* GetContactEntity() const = 0; + virtual bool IsStandingOnEntity() const = 0; virtual int GetRunState() const = 0; diff --git a/Shared/mods/deathmatch/logic/Utils.cpp b/Shared/mods/deathmatch/logic/Utils.cpp index 9122d38d6ca..133348f41ac 100644 --- a/Shared/mods/deathmatch/logic/Utils.cpp +++ b/Shared/mods/deathmatch/logic/Utils.cpp @@ -1107,3 +1107,23 @@ CVector ConvertEulerRotationOrder(const CVector& a_vRotation, eEulerRotationOrde return a_vRotation; } } + +bool approximatelyEqual(float a, float b, float epsilon) +{ + return std::fabs(a - b) <= std::max(std::fabs(a), std::fabs(b)) * epsilon; +} + +bool essentiallyEqual(float a, float b, float epsilon) +{ + return std::fabs(a - b) <= std::min(std::fabs(a), std::fabs(b)) * epsilon; +} + +bool definitelyGreaterThan(float a, float b, float epsilon) +{ + return (a - b) > std::max(std::fabs(a), std::fabs(b)) * epsilon; +} + +bool definitelyLessThan(float a, float b, float epsilon) +{ + return (b - a) > std::max(std::fabs(a), std::fabs(b)) * epsilon; +} diff --git a/Shared/mods/deathmatch/logic/Utils.h b/Shared/mods/deathmatch/logic/Utils.h index 8afade98c81..5019268c1a8 100644 --- a/Shared/mods/deathmatch/logic/Utils.h +++ b/Shared/mods/deathmatch/logic/Utils.h @@ -336,3 +336,9 @@ void DeletePointersAndClearList(T& elementList) delete *iter; } } + +// Comparing floating point numbers +bool approximatelyEqual(float a, float b, float epsilon = FLOAT_EPSILON); +bool essentiallyEqual(float a, float b, float epsilon = FLOAT_EPSILON); +bool definitelyGreaterThan(float a, float b, float epsilon = FLOAT_EPSILON); +bool definitelyLessThan(float a, float b, float epsilon = FLOAT_EPSILON);