From 88c3240f609f7a56637fdf7802e70fc9631536ce Mon Sep 17 00:00:00 2001 From: FileEX Date: Tue, 29 Jul 2025 00:26:52 +0200 Subject: [PATCH 1/3] 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 7dbd4b0de7..ccef53943d 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 a9ef955e6e..48c99e19fc 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 6f2ba652fb..830e1fe28c 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 9d1dab664d..de3ad74321 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 6ffd9aaf6b..fb1a6bd995 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 9122d38d6c..133348f41a 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 8afade98c8..5019268c1a 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); From a0e5e8d0d9c5a58589c2980cbb6348c93c10ec36 Mon Sep 17 00:00:00 2001 From: FileEX Date: Tue, 12 Aug 2025 18:06:48 +0200 Subject: [PATCH 2/3] Review --- Client/mods/deathmatch/logic/CClientPed.cpp | 4 ++-- Shared/mods/deathmatch/logic/Utils.cpp | 20 -------------------- Shared/mods/deathmatch/logic/Utils.h | 6 ------ Shared/sdk/SharedUtil.Math.h | 21 +++++++++++++++++++++ 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 7774a38b4e..42a275d62e 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -4672,10 +4672,10 @@ bool CClientPed::IsOnGround(bool checkVehicles) GetPosition(vecPosition); float fGroundLevel = static_cast(g_pGame->GetWorld()->FindGroundZFor3DPosition(&vecPosition)); - if (definitelyLessThan(vecPosition.fZ, fGroundLevel)) + if (DefinitelyLessThan(vecPosition.fZ, fGroundLevel)) return false; - bool isOnGround = definitelyLessThan((vecPosition.fZ - fGroundLevel), 1.0f) || essentiallyEqual((vecPosition.fZ - fGroundLevel), 1.0f); + bool isOnGround = DefinitelyLessThan((vecPosition.fZ - fGroundLevel), 1.0f) || EssentiallyEqual((vecPosition.fZ - fGroundLevel), 1.0f); if (!isOnGround && checkVehicles && m_pPlayerPed) return m_pPlayerPed->IsStandingOnEntity(); diff --git a/Shared/mods/deathmatch/logic/Utils.cpp b/Shared/mods/deathmatch/logic/Utils.cpp index 9152faef05..e3107c77a6 100644 --- a/Shared/mods/deathmatch/logic/Utils.cpp +++ b/Shared/mods/deathmatch/logic/Utils.cpp @@ -1102,23 +1102,3 @@ 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 5019268c1a..8afade98c8 100644 --- a/Shared/mods/deathmatch/logic/Utils.h +++ b/Shared/mods/deathmatch/logic/Utils.h @@ -336,9 +336,3 @@ 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); diff --git a/Shared/sdk/SharedUtil.Math.h b/Shared/sdk/SharedUtil.Math.h index bd53f71110..f8d2940132 100644 --- a/Shared/sdk/SharedUtil.Math.h +++ b/Shared/sdk/SharedUtil.Math.h @@ -118,4 +118,25 @@ namespace SharedUtil { return std::fabs(a - b) <= epsilon; } + + inline bool ApproximatelyEqual(float a, float b, float epsilon = std::numeric_limits().epsilon()) noexcept + { + return std::fabs(a - b) <= std::max(std::fabs(a), std::fabs(b)) * epsilon; + } + + inline bool EssentiallyEqual(float a, float b, float epsilon = std::numeric_limits().epsilon()) noexcept + { + return std::fabs(a - b) <= std::min(std::fabs(a), std::fabs(b)) * epsilon; + } + + inline bool DefinitelyGreaterThan(float a, float b, float epsilon = std::numeric_limits().epsilon()) noexcept + { + return (a - b) > std::max(std::fabs(a), std::fabs(b)) * epsilon; + } + + inline bool DefinitelyLessThan(float a, float b, float epsilon = std::numeric_limits().epsilon()) noexcept + { + return (b - a) > std::max(std::fabs(a), std::fabs(b)) * epsilon; + } + } // namespace SharedUtil From a2e87991929a6beb1912db589a7f6177e3b04b21 Mon Sep 17 00:00:00 2001 From: FileEX Date: Thu, 21 Aug 2025 23:53:03 +0200 Subject: [PATCH 3/3] Better tolerance --- Client/mods/deathmatch/logic/CClientPed.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index aac0457079..893b883fdf 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -4682,7 +4682,7 @@ bool CClientPed::IsOnGround(bool checkVehicles) if (DefinitelyLessThan(vecPosition.fZ, fGroundLevel)) return false; - bool isOnGround = DefinitelyLessThan((vecPosition.fZ - fGroundLevel), 1.0f) || EssentiallyEqual((vecPosition.fZ - fGroundLevel), 1.0f); + bool isOnGround = DefinitelyLessThan((vecPosition.fZ - fGroundLevel), 1.0f, 1e-4f) || EssentiallyEqual((vecPosition.fZ - fGroundLevel), 1.0f, 1e-4f); if (!isOnGround && checkVehicles && m_pPlayerPed) return m_pPlayerPed->IsStandingOnEntity();