From 480363ee1f5552f3d0538c957e9ab0534a274bd8 Mon Sep 17 00:00:00 2001 From: FileEX Date: Wed, 4 Sep 2024 12:59:36 +0200 Subject: [PATCH] Initial commit --- Client/game_sa/CObjectSA.cpp | 34 +++++++++++++++ Client/game_sa/CObjectSA.h | 5 ++- .../mods/deathmatch/logic/CClientObject.cpp | 42 +++++++++++++++++++ Client/mods/deathmatch/logic/CClientObject.h | 2 + .../logic/lua/CLuaFunctionParseHelpers.cpp | 6 +++ .../logic/luadefs/CLuaObjectDefs.cpp | 9 ++++ .../deathmatch/logic/luadefs/CLuaObjectDefs.h | 2 + Client/sdk/game/CObject.h | 3 ++ Shared/mods/deathmatch/logic/Enums.h | 8 ++++ 9 files changed, 110 insertions(+), 1 deletion(-) diff --git a/Client/game_sa/CObjectSA.cpp b/Client/game_sa/CObjectSA.cpp index ef31e9b37a..0dbe3c97dc 100644 --- a/Client/game_sa/CObjectSA.cpp +++ b/Client/game_sa/CObjectSA.cpp @@ -304,3 +304,37 @@ void CObjectSA::ResetScale() { SetScale(1.0f, 1.0f, 1.0f); } + +bool CObjectSA::SetFramePosition(const std::string& frameName, const CVector& position) +{ + RpClump* clump = GetInterface()->m_pRwObject; + if (!clump) + return false; + + RwFrame* frame = ((RwFrame*(__cdecl*)(RpClump*, const char*))0x4C5400)(clump, frameName.c_str()); + if (!frame) + return false; + + pGame->GetRenderWareSA()->RwMatrixSetPosition(frame->modelling, position); + return true; +} + +bool CObjectSA::GetObjectParentToRootMatrix(CMatrix& matrixOut) +{ + RpClump* clump = GetInterface()->m_pRwObject; + if (!clump) + return false; + + CMatrix newMatrix; + + RwFrame* parentFrame = static_cast(clump->object.parent); + for (; parentFrame && parentFrame != parentFrame->root; parentFrame = static_cast(parentFrame->object.parent)) + { + CMatrix frameMatrix; + pGame->GetRenderWareSA()->RwMatrixToCMatrix(parentFrame->modelling, frameMatrix); + newMatrix = newMatrix * frameMatrix; + } + + matrixOut = newMatrix; + return true; +} diff --git a/Client/game_sa/CObjectSA.h b/Client/game_sa/CObjectSA.h index 77b44772a7..6876800423 100644 --- a/Client/game_sa/CObjectSA.h +++ b/Client/game_sa/CObjectSA.h @@ -153,6 +153,9 @@ class CObjectSA : public virtual CObject, public virtual CPhysicalSA CVector* GetScale(); void ResetScale(); + bool SetFramePosition(const std::string& frameName, const CVector& position); + bool GetObjectParentToRootMatrix(CMatrix& matrixOut); + private: void CheckForGangTag(); -}; \ No newline at end of file +}; diff --git a/Client/mods/deathmatch/logic/CClientObject.cpp b/Client/mods/deathmatch/logic/CClientObject.cpp index 27eacc0efa..fc6042b371 100644 --- a/Client/mods/deathmatch/logic/CClientObject.cpp +++ b/Client/mods/deathmatch/logic/CClientObject.cpp @@ -855,3 +855,45 @@ void CClientObject::SetVisibleInAllDimensions(bool bVisible, unsigned short usNe SetDimension(usNewDimension); } } + +bool CClientObject::SetFramePosition(const std::string& frameName, CVector& position, EFrameBase positionBase) +{ + if (!m_pObject) + return false; + + // Convert position to relative to parent + if (positionBase != EFrameBase::PARENT) + { + CMatrix tempMatrix(position); + + switch (positionBase) + { + case EFrameBase::ROOT: + { + CMatrix parentMatrixToRoot; + if (!m_pObject->GetObjectParentToRootMatrix(parentMatrixToRoot)) + return false; + + tempMatrix = tempMatrix * parentMatrixToRoot.Inverse(); + break; + } + case EFrameBase::WORLD: + { + CMatrix matrixToWorld; + GetMatrix(matrixToWorld); + tempMatrix = tempMatrix * matrixToWorld.Inverse(); + + CMatrix parentMatrixToRoot; + if (!m_pObject->GetObjectParentToRootMatrix(parentMatrixToRoot)) + return false; + + tempMatrix = tempMatrix * parentMatrixToRoot.Inverse(); + break; + } + } + + position = tempMatrix.GetPosition(); + } + + return m_pObject->SetFramePosition(frameName, position); +} diff --git a/Client/mods/deathmatch/logic/CClientObject.h b/Client/mods/deathmatch/logic/CClientObject.h index a016facd5c..203d81e51f 100644 --- a/Client/mods/deathmatch/logic/CClientObject.h +++ b/Client/mods/deathmatch/logic/CClientObject.h @@ -119,6 +119,8 @@ class CClientObject : public CClientStreamElement bool IsBeingRespawned() { return m_bBeingRespawned; }; void SetBeingRespawned(bool bBeingRespawned) { m_bBeingRespawned = bBeingRespawned; }; + bool SetFramePosition(const std::string& frameName, CVector& position, EFrameBase positionBase); + protected: void StreamIn(bool bInstantly); void StreamOut(); diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index 64708dea0c..2576bce78f 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -910,6 +910,12 @@ ADD_ENUM(PreloadAreaOption::COLLISIONS, "collisions") ADD_ENUM(PreloadAreaOption::ALL, "all") IMPLEMENT_ENUM_CLASS_END("preload-area-option") +IMPLEMENT_ENUM_CLASS_BEGIN(EFrameBase) +ADD_ENUM(EFrameBase::ROOT, "root") +ADD_ENUM(EFrameBase::PARENT, "parent") +ADD_ENUM(EFrameBase::WORLD, "world") +IMPLEMENT_ENUM_CLASS_END("frame-base") + // // CResource from userdata // diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp index 81d1b4d704..9535fc96d7 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp @@ -38,6 +38,7 @@ void CLuaObjectDefs::LoadFunctions() {"toggleObjectRespawn", ToggleObjectRespawn}, {"setObjectMass", SetObjectMass}, {"setObjectProperty", SetObjectProperty}, + {"setObjectFramePosition", ArgumentParser}, }; // Add functions @@ -721,3 +722,11 @@ bool CLuaObjectDefs::IsObjectRespawnable(CClientEntity* const pEntity) noexcept return pObject->IsRespawnEnabled(); } + +bool CLuaObjectDefs::SetObjectFramePosition(CClientObject* const object, const std::string frameName, CVector position, std::optional positionBase) +{ + if (frameName.empty()) + return false; + + return object->SetFramePosition(frameName, position, positionBase.value_or(EFrameBase::ROOT)); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h index 1ce12ad20e..7c8262cf8d 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.h @@ -43,4 +43,6 @@ class CLuaObjectDefs : public CLuaDefs LUA_DECLARE(ToggleObjectRespawn); LUA_DECLARE(SetObjectMass); LUA_DECLARE(SetObjectProperty); + + static bool SetObjectFramePosition(CClientObject* const object, const std::string frameName, CVector position, std::optional positionBase); }; diff --git a/Client/sdk/game/CObject.h b/Client/sdk/game/CObject.h index cb04b499c3..7f7d3fbb89 100644 --- a/Client/sdk/game/CObject.h +++ b/Client/sdk/game/CObject.h @@ -41,4 +41,7 @@ class CObject : public virtual CPhysical virtual void SetScale(float fX, float fY, float fZ) = 0; virtual CVector* GetScale() = 0; virtual void ResetScale() = 0; + + virtual bool SetFramePosition(const std::string& frameName, const CVector& position) = 0; + virtual bool GetObjectParentToRootMatrix(CMatrix& matrixOut) = 0; }; diff --git a/Shared/mods/deathmatch/logic/Enums.h b/Shared/mods/deathmatch/logic/Enums.h index e975d0d907..8eee30a6c3 100644 --- a/Shared/mods/deathmatch/logic/Enums.h +++ b/Shared/mods/deathmatch/logic/Enums.h @@ -94,4 +94,12 @@ enum class WorldSpecialProperty }; DECLARE_ENUM_CLASS(WorldSpecialProperty); +enum class EFrameBase +{ + WORLD, + ROOT, + PARENT, +}; +DECLARE_ENUM_CLASS(EFrameBase); + DECLARE_ENUM(ePacketID);