diff --git a/Client/game_sa/CEntitySA.cpp b/Client/game_sa/CEntitySA.cpp index 4466a53fe4b..a55470adf6f 100644 --- a/Client/game_sa/CEntitySA.cpp +++ b/Client/game_sa/CEntitySA.cpp @@ -603,6 +603,28 @@ bool CEntitySA::GetBoneRotation(eBone boneId, float& yaw, float& pitch, float& r return false; } +bool CEntitySA::GetBoneRotationQuat(eBone boneId, float& x, float& y, float& z, float& w) +{ + RpClump* clump = GetRpClump(); + if (clump) + { + // updating the bone frame orientation will also update its children + // This rotation is only applied when UpdateElementRpHAnim is called + CAnimBlendClumpDataSAInterface* clumpDataInterface = *pGame->GetClumpData(clump); + AnimBlendFrameData* frameData = clumpDataInterface->GetFrameDataByNodeId(boneId); + if (frameData) + { + RtQuat* boneOrientation = &frameData->m_pIFrame->orientation; + x = boneOrientation->imag.x; + y = boneOrientation->imag.y; + z = boneOrientation->imag.z; + w = boneOrientation->real; + return true; + } + } + return false; +} + bool CEntitySA::SetBoneRotation(eBone boneId, float yaw, float pitch, float roll) { RpClump* clump = GetRpClump(); @@ -628,6 +650,33 @@ bool CEntitySA::SetBoneRotation(eBone boneId, float yaw, float pitch, float roll return false; } +bool CEntitySA::SetBoneRotationQuat(eBone boneId, float x, float y, float z, float w) +{ + RpClump* clump = GetRpClump(); + if (clump) + { + // updating the bone frame orientation will also update its children + // This rotation is only applied when UpdateElementRpHAnim is called + CAnimBlendClumpDataSAInterface* clumpDataInterface = *pGame->GetClumpData(clump); + AnimBlendFrameData* frameData = clumpDataInterface->GetFrameDataByNodeId(boneId); + if (frameData) + { + RtQuat* boneOrientation = &frameData->m_pIFrame->orientation; + boneOrientation->imag.x = x; + boneOrientation->imag.y = y; + boneOrientation->imag.z = z; + boneOrientation->real = w; + CEntitySAInterface* theInterface = GetInterface(); + if (theInterface) + { + theInterface->bDontUpdateHierarchy = false; + } + return true; + } + } + return false; +} + bool CEntitySA::GetBonePosition(eBone boneId, CVector& position) { RwMatrix* rwBoneMatrix = GetBoneRwMatrix(boneId); diff --git a/Client/game_sa/CEntitySA.h b/Client/game_sa/CEntitySA.h index 9de57edc0a8..548cb657f6b 100644 --- a/Client/game_sa/CEntitySA.h +++ b/Client/game_sa/CEntitySA.h @@ -324,7 +324,9 @@ class CEntitySA : public virtual CEntity bool SetBoneMatrix(eBone boneId, const CMatrix& matrix); bool GetBoneRotation(eBone boneId, float& yaw, float& pitch, float& roll); + bool GetBoneRotationQuat(eBone boneId, float& x, float& y, float& z, float& w); bool SetBoneRotation(eBone boneId, float yaw, float pitch, float roll); + bool SetBoneRotationQuat(eBone boneId, float x, float y, float z, float w); bool GetBonePosition(eBone boneId, CVector& position); bool SetBonePosition(eBone boneId, const CVector& position); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index 63c37110646..6f6e4205e01 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -54,8 +54,10 @@ void CLuaPedDefs::LoadFunctions() {"getPedBonePosition", GetPedBonePosition}, {"setElementBonePosition", ArgumentParser}, {"setElementBoneRotation", ArgumentParser}, + {"setElementBoneQuaternion", ArgumentParser}, {"getElementBonePosition", ArgumentParser}, {"getElementBoneRotation", ArgumentParser}, + {"getElementBoneQuaternion", ArgumentParser}, {"setElementBoneMatrix", ArgumentParser}, {"getElementBoneMatrix", ArgumentParser}, {"updateElementRpHAnim", ArgumentParser}, @@ -998,19 +1000,31 @@ int CLuaPedDefs::CanPedBeKnockedOffBike(lua_State* luaVM) return 1; } -bool CLuaPedDefs::SetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, CVector position) +bool CLuaPedDefs::SetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, CVector position) { CEntity* theEntity = entity->GetGameEntity(); return theEntity ? theEntity->SetBonePosition(static_cast(boneId), position) : false; } -bool CLuaPedDefs::SetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, float yaw, float pitch, float roll) +bool CLuaPedDefs::SetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, float yaw, float pitch, float roll) { + if (boneId > BONE_RIGHTFOOT) + throw LuaFunctionError("Invalid bone ID"); + CEntity* theEntity = entity->GetGameEntity(); return theEntity ? theEntity->SetBoneRotation(static_cast(boneId), yaw, pitch, roll) : false; } -std::variant> CLuaPedDefs::GetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId) +bool CLuaPedDefs::SetElementBoneQuaternion(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, float x, float y, float z, float w) +{ + if (boneId > BONE_RIGHTFOOT) + throw LuaFunctionError("Invalid bone ID"); + + CEntity* theEntity = entity->GetGameEntity(); + return theEntity ? theEntity->SetBoneRotationQuat(static_cast(boneId), x, y, z, w) : false; +} + +std::variant> CLuaPedDefs::GetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId) { CEntity* theEntity = entity->GetGameEntity(); CVector position; @@ -1019,8 +1033,11 @@ std::variant> CLuaPedDefs::GetElement return false; } -std::variant> CLuaPedDefs::GetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId) +std::variant> CLuaPedDefs::GetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId) { + if (boneId > BONE_RIGHTFOOT) + throw LuaFunctionError("Invalid bone ID"); + float yaw = 0.0f, pitch = 0.0f, roll = 0.0f; CEntity* theEntity = entity->GetGameEntity(); if (theEntity && theEntity->GetBoneRotation(static_cast(boneId), yaw, pitch, roll)) @@ -1028,13 +1045,25 @@ std::variant> CLuaPedDefs::GetElement return false; } -bool CLuaPedDefs::SetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, CMatrix boneMatrix) +std::variant> CLuaPedDefs::GetElementBoneQuaternion(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId) +{ + if (boneId > BONE_RIGHTFOOT) + throw LuaFunctionError("Invalid bone ID"); + + float x = 0.0f, y = 0.0f, z = 0.0f, w = 0.0f; + CEntity* theEntity = entity->GetGameEntity(); + if (theEntity && theEntity->GetBoneRotationQuat(static_cast(boneId), x, y, z, w)) + return std::make_tuple(x, y, z, w); + return false; +} + +bool CLuaPedDefs::SetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, CMatrix boneMatrix) { CEntity* theEntity = entity->GetGameEntity(); return theEntity ? theEntity->SetBoneMatrix(static_cast(boneId), boneMatrix) : false; } -std::variant, 4>> CLuaPedDefs::GetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId) +std::variant, 4>> CLuaPedDefs::GetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId) { CEntity* theEntity = entity->GetGameEntity(); if (theEntity) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index 1758011f705..126c463af7c 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -50,15 +50,17 @@ class CLuaPedDefs : public CLuaDefs LUA_DECLARE(GetPedContactElement); LUA_DECLARE(GetPedRotation); LUA_DECLARE(CanPedBeKnockedOffBike); - static bool SetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, CVector position); - static bool SetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, float yaw, float pitch, float roll); - static std::variant> GetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId); + static bool SetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, CVector position); + static bool SetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, float yaw, float pitch, float roll); + static bool SetElementBoneQuaternion(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, float x, float y, float z, float w); + static std::variant> GetElementBonePosition(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId); - static std::variant> GetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId); + static std::variant> GetElementBoneRotation(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId); + static std::variant> GetElementBoneQuaternion(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId); - static bool SetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId, CMatrix boneMatrix); + static bool SetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId, CMatrix boneMatrix); - static std::variant, 4>> GetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::int32_t boneId); + static std::variant, 4>> GetElementBoneMatrix(lua_State* const luaVM, CClientPed* entity, std::uint32_t boneId); static bool UpdateElementRpHAnim(lua_State* const luaVM, CClientEntity* entity); LUA_DECLARE_OOP(GetPedBonePosition); diff --git a/Client/sdk/game/CEntity.h b/Client/sdk/game/CEntity.h index 085d92ab0e4..32b803d544a 100644 --- a/Client/sdk/game/CEntity.h +++ b/Client/sdk/game/CEntity.h @@ -112,7 +112,9 @@ class CEntity virtual bool SetBoneMatrix(eBone boneId, const CMatrix& matrix) = 0; virtual bool GetBoneRotation(eBone boneId, float& yaw, float& pitch, float& roll) = 0; + virtual bool GetBoneRotationQuat(eBone boneId, float& x, float& y, float& z, float& w) = 0; virtual bool SetBoneRotation(eBone boneId, float yaw, float pitch, float roll) = 0; + virtual bool SetBoneRotationQuat(eBone boneId, float x, float y, float z, float w) = 0; virtual bool GetBonePosition(eBone boneId, CVector& position) = 0; virtual bool SetBonePosition(eBone boneId, const CVector& position) = 0; };