From aa90aa5f31e59df455af33b49e3eee5e4f107bfd Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 22 Dec 2024 00:00:47 +0100 Subject: [PATCH] Add new function testSphereAgainstWorld (Close #646) (#3787) New scriptingfunction testSphereAgainstWorld, which allows checking if there are any obstacles within a given radius --- Client/game_sa/CWorldSA.cpp | 17 +++++++++++++++++ Client/game_sa/CWorldSA.h | 3 +++ .../logic/lua/CLuaFunctionParseHelpers.cpp | 10 ++++++++++ .../logic/lua/CLuaFunctionParseHelpers.h | 1 + .../deathmatch/logic/luadefs/CLuaWorldDefs.cpp | 15 ++++++++++++++- .../deathmatch/logic/luadefs/CLuaWorldDefs.h | 3 +++ Client/sdk/game/CWorld.h | 13 +++++++++++++ 7 files changed, 61 insertions(+), 1 deletion(-) diff --git a/Client/game_sa/CWorldSA.cpp b/Client/game_sa/CWorldSA.cpp index a60e360464..72befc316e 100644 --- a/Client/game_sa/CWorldSA.cpp +++ b/Client/game_sa/CWorldSA.cpp @@ -528,6 +528,23 @@ bool CWorldSA::ProcessLineOfSight(const CVector* vecStart, const CVector* vecEnd return bReturn; } +CEntity* CWorldSA::TestSphereAgainstWorld(const CVector& sphereCenter, float radius, CEntity* ignoredEntity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool cameraIgnore, STestSphereAgainstWorldResult& result) +{ + auto entity = ((CEntitySAInterface*(__cdecl*)(CVector, float, CEntitySAInterface*, bool, bool, bool, bool, bool, bool))FUNC_CWorld_TestSphereAgainstWorld)(sphereCenter, radius, ignoredEntity ? ignoredEntity->GetInterface() : nullptr, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, cameraIgnore); + if (!entity) + return nullptr; + + result.collisionDetected = true; + result.modelID = entity->m_nModelIndex; + result.entityPosition = entity->Placeable.matrix->vPos; + ConvertMatrixToEulerAngles(*entity->Placeable.matrix, result.entityRotation.fX, result.entityRotation.fY, result.entityRotation.fZ); + result.entityRotation = -result.entityRotation; + result.lodID = entity->m_pLod ? entity->m_pLod->m_nModelIndex : 0; + result.type = static_cast(entity->nType); + + return pGame->GetPools()->GetEntity(reinterpret_cast(entity)); +} + void CWorldSA::IgnoreEntity(CEntity* pEntity) { CEntitySA* pEntitySA = dynamic_cast(pEntity); diff --git a/Client/game_sa/CWorldSA.h b/Client/game_sa/CWorldSA.h index 340db3ef5d..5da287a1a6 100644 --- a/Client/game_sa/CWorldSA.h +++ b/Client/game_sa/CWorldSA.h @@ -25,6 +25,7 @@ #define VAR_COcclusion_NumActiveOccluders 0xC73CC0 #define CALL_CCullZones_FindTunnelAttributesForCoors 0x55570D #define FUNC_CWorld_FindPositionForTrackPosition 0x6F59E0 +#define FUNC_CWorld_TestSphereAgainstWorld 0x569E20 #define VAR_IgnoredEntity 0xB7CD68 #define VAR_currArea 0xB72914 @@ -74,6 +75,8 @@ class CWorldSA : public CWorld void ResetAllSurfaceInfo() override; bool ResetSurfaceInfo(short sSurfaceID) override; + CEntity* TestSphereAgainstWorld(const CVector& sphereCenter, float radius, CEntity* ignoredEntity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool cameraIgnore, STestSphereAgainstWorldResult& result) override; + private: float m_fAircraftMaxHeight; CSurfaceType* m_pSurfaceInfo; diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index 64708dea0c..e0f79e6ba4 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -910,6 +910,16 @@ ADD_ENUM(PreloadAreaOption::COLLISIONS, "collisions") ADD_ENUM(PreloadAreaOption::ALL, "all") IMPLEMENT_ENUM_CLASS_END("preload-area-option") +IMPLEMENT_ENUM_BEGIN(eEntityType) +ADD_ENUM(ENTITY_TYPE_NOTHING, "unknown") +ADD_ENUM(ENTITY_TYPE_BUILDING, "building") +ADD_ENUM(ENTITY_TYPE_VEHICLE, "vehicle") +ADD_ENUM(ENTITY_TYPE_PED, "ped") +ADD_ENUM(ENTITY_TYPE_OBJECT, "object") +ADD_ENUM(ENTITY_TYPE_DUMMY, "dummy") +ADD_ENUM(ENTITY_TYPE_NOTINPOOLS, "unknown") +IMPLEMENT_ENUM_END("entity-type") + // // CResource from userdata // diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h index e134a73bea..fc692a8f16 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h @@ -88,6 +88,7 @@ DECLARE_ENUM(ePools); DECLARE_ENUM(eWorldProperty); DECLARE_ENUM_CLASS(eModelLoadState); DECLARE_ENUM_CLASS(PreloadAreaOption); +DECLARE_ENUM(eEntityType); class CRemoteCall; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp index 9a9e038b19..185b0ae44b 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.cpp @@ -142,7 +142,8 @@ void CLuaWorldDefs::LoadFunctions() {"isGarageOpen", IsGarageOpen}, {"isTimeFrozen", ArgumentParser}, {"isVolumetricShadowsEnabled", ArgumentParser}, - {"isDynamicPedShadowsEnabled", ArgumentParser}}; + {"isDynamicPedShadowsEnabled", ArgumentParser}, + {"testSphereAgainstWorld", ArgumentParser}}; // Add functions for (const auto& [name, func] : functions) @@ -2297,3 +2298,15 @@ bool CLuaWorldDefs::ResetDynamicPedShadows() noexcept { return g_pGame->GetSettings()->ResetDynamicPedShadows(); } + +CLuaMultiReturn CLuaWorldDefs::TestSphereAgainstWorld(CVector sphereCenter, float radius, std::optional ignoredEntity, std::optional checkBuildings, std::optional checkVehicles, std::optional checkPeds, std::optional checkObjects, std::optional checkDummies, std::optional cameraIgnore) +{ + STestSphereAgainstWorldResult result; + CClientEntity* collidedEntity = nullptr; + + CEntity* entity = g_pGame->GetWorld()->TestSphereAgainstWorld(sphereCenter, radius, ignoredEntity.has_value() ? ignoredEntity.value()->GetGameEntity() : nullptr, checkBuildings.value_or(true), checkVehicles.value_or(true), checkPeds.value_or(true), checkObjects.value_or(true), checkDummies.value_or(true), cameraIgnore.value_or(false), result); + if (entity) + collidedEntity = reinterpret_cast(entity->GetStoredPointer()); + + return {result.collisionDetected, collidedEntity, result.modelID, result.entityPosition.fX, result.entityPosition.fY, result.entityPosition.fZ, ConvertRadiansToDegrees(result.entityRotation.fX), ConvertRadiansToDegrees(result.entityRotation.fY), ConvertRadiansToDegrees(result.entityRotation.fZ), result.lodID, result.type}; +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h index f430bd63dd..3c19ed8857 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaWorldDefs.h @@ -144,5 +144,8 @@ class CLuaWorldDefs : public CLuaDefs static bool SetDynamicPedShadowsEnabled(bool enable); static bool IsDynamicPedShadowsEnabled() noexcept; static bool ResetDynamicPedShadows() noexcept; + + static CLuaMultiReturn TestSphereAgainstWorld(CVector sphereCenter, float radius, std::optional ignoredEntity, std::optional checkBuildings, std::optional checkVehicles, std::optional checkPeds, std::optional checkObjects, std::optional checkDummies, std::optional cameraIgnore); + }; diff --git a/Client/sdk/game/CWorld.h b/Client/sdk/game/CWorld.h index 3684172f01..c22762f7a8 100644 --- a/Client/sdk/game/CWorld.h +++ b/Client/sdk/game/CWorld.h @@ -10,6 +10,7 @@ *****************************************************************************/ #pragma once +#include "CEntity.h" class CEntitySAInterface; class CVector; @@ -61,6 +62,16 @@ struct SProcessLineOfSightMaterialInfoResult { bool valid{}; //< Data found in this struct is only valid if this is `true`! }; +struct STestSphereAgainstWorldResult +{ + bool collisionDetected{false}; + std::uint32_t modelID{0}; + CVector entityPosition{}; + CVector entityRotation{}; + std::uint32_t lodID{0}; + eEntityType type{ENTITY_TYPE_NOTHING}; +}; + enum eDebugCaller { CEntity_SetMatrix, @@ -274,4 +285,6 @@ class CWorld virtual CSurfaceType* GetSurfaceInfo() = 0; virtual void ResetAllSurfaceInfo() = 0; virtual bool ResetSurfaceInfo(short sSurfaceID) = 0; + + virtual CEntity* TestSphereAgainstWorld(const CVector& sphereCenter, float radius, CEntity* ignoredEntity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool cameraIgnore, STestSphereAgainstWorldResult& result) = 0; };