Skip to content

Commit b2b7ef9

Browse files
saml1ercodenullsStrixG
authored
New bone functions and onClientPedsProcessed event (#1673)
* bonestuff * Fix all bugs all functions seem to work properly now.. * bone API usage cleanup * Refactor bones code * remove combineType parameter from setBoneRotation * Remove console debug code * Refactor Rw To MTA and vice-versa code * Remove useless comment in CLuaPedDefs::GetElementBoneRotation Co-authored-by: saml1er <[email protected]> Co-authored-by: Nikita Obrekht <[email protected]>
1 parent 7268aed commit b2b7ef9

35 files changed

+695
-86
lines changed

Client/game_sa/BoneNode_cSA.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "StdInc.h"
2+
#include "BoneNode_cSA.h"
3+
4+
void BoneNode_cSAInterface::QuatToEuler(RtQuat* quat, RwV3d* angles)
5+
{
6+
auto BoneNode_c_QuatToEuler = (void(__cdecl*)(RtQuat*, RwV3d*))0x617080;
7+
BoneNode_c_QuatToEuler(quat, angles);
8+
}
9+
10+
void BoneNode_cSAInterface::EulerToQuat(RwV3d* angles, RtQuat* quat)
11+
{
12+
auto BoneNode_c_EulerToQuat = (void(__cdecl*)(RwV3d*, RtQuat*))0x6171F0;
13+
BoneNode_c_EulerToQuat(angles, quat);
14+
}

Client/game_sa/BoneNode_cSA.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
#include "gamesa_renderware.h"
3+
4+
class BoneNode_cSAInterface
5+
{
6+
public:
7+
static void QuatToEuler(RtQuat* quat, RwV3d* angles);
8+
static void EulerToQuat(RwV3d* angles, RtQuat* quat);
9+
};

Client/game_sa/CAnimBlendAssociationSA.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@
1313

1414
extern CGameSA* pGame;
1515

16+
AnimBlendFrameData* CAnimBlendClumpDataSAInterface::GetFrameDataByNodeId(unsigned int nodeId)
17+
{
18+
for (int i = 0; i < m_dwNumBones; i++)
19+
{
20+
AnimBlendFrameData& frameData = m_frames[i];
21+
if (frameData.m_nNodeId == nodeId)
22+
return &frameData;
23+
}
24+
return nullptr;
25+
}
26+
1627
CAnimBlendAssociationSAInterface* CAnimBlendAssociationSA::Constructor(CAnimBlendStaticAssociationSAInterface& staticAssociationByReference)
1728
{
1829
DWORD DwFunc = 0x4CF080;

Client/game_sa/CAnimBlendAssociationSA.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,64 @@
2020
class CAnimBlendAssocGroupSA;
2121
class CAnimBlendHierarchySAInterface;
2222

23+
struct RpHAnimBlendInterpFrame
24+
{
25+
RtQuat orientation;
26+
RwV3d translation;
27+
};
28+
class AnimBlendFrameData
29+
{
30+
public:
31+
union
32+
{
33+
struct
34+
{
35+
unsigned char m_bf1 : 1; // doesn't seem to be used
36+
unsigned char m_IsIFrameOrientationToAffectedByNodes : 1; // m_IFrame orientation will be affected
37+
unsigned char m_IsIFrameTranslationToAffectedByNodes : 1; // m_IFrame translation will be affected
38+
unsigned char m_bIsInitialized : 1;
39+
unsigned char m_bUpdateSkinnedWith3dVelocityExtraction : 1;
40+
unsigned char m_bCheckBlendNodeClumpKeyFrames : 1; // key frames of CAninBlendNode bones will be checked
41+
unsigned char m_bIsCompressed : 1;
42+
unsigned char m_bUpdatingFrame : 1; // doesn't seem to be used
43+
};
44+
unsigned char m_nFlags;
45+
};
46+
char pad[3];
47+
CVector m_vecOffset;
48+
RpHAnimBlendInterpFrame* m_pIFrame;
49+
unsigned int m_nNodeId;
50+
};
51+
52+
struct SClumpAnimAssocSAInterface
53+
{
54+
SClumpAnimAssocSAInterface* m_pNext;
55+
SClumpAnimAssocSAInterface* m_pPrevious;
56+
std::int16_t m_nNumBlendNodes;
57+
std::int16_t m_nAnimGroup;
58+
class CAnimBlendNodeSAInterface* m_pNodeArray;
59+
CAnimBlendHierarchySAInterface* m_pHierarchy;
60+
float m_fBlendAmount;
61+
float m_fBlendDelta;
62+
float m_fCurrentTime;
63+
float m_fSpeed;
64+
float fTimeStep;
65+
std::int16_t m_nAnimId;
66+
std::int16_t m_nFlags;
67+
};
68+
69+
class CAnimBlendClumpDataSAInterface
70+
{
71+
public:
72+
SClumpAnimAssocSAInterface* m_pFirstAssociation;
73+
int field_4;
74+
int m_dwNumBones;
75+
int field_C;
76+
AnimBlendFrameData* m_frames;
77+
78+
AnimBlendFrameData* GetFrameDataByNodeId(unsigned int nodeId);
79+
};
80+
2381
class CAnimBlendAssociationSAInterface
2482
{
2583
public:

Client/game_sa/CEntitySA.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
*****************************************************************************/
1111

1212
#include "StdInc.h"
13+
#include "gamesa_renderware.h"
14+
#include "BoneNode_cSA.h"
1315

1416
extern CGameSA* pGame;
1517

@@ -65,6 +67,12 @@ CEntitySA::CEntitySA()
6567
m_ulArrayID = INVALID_POOL_ARRAY_ID;
6668
}
6769

70+
void CEntitySA::UpdateRpHAnim()
71+
{
72+
auto CEntity_UpdateRpHAnim = (void(__thiscall*)(CEntitySAInterface*))0x532B20;
73+
CEntity_UpdateRpHAnim(m_pInterface);
74+
}
75+
6876
/*VOID CEntitySA::SetModelAlpha ( int iAlpha )
6977
{
7078
this->internalInterface->ModelClump->SetAlpha(iAlpha);
@@ -583,6 +591,104 @@ bool CEntitySA::IsPlayingAnimation(char* szAnimName)
583591
else return false;
584592
}
585593

594+
RwMatrixTag* CEntitySA::GetBoneRwMatrix(eBone boneId)
595+
{
596+
RpClump* clump = GetRpClump();
597+
if (!clump)
598+
return nullptr;
599+
RpHAnimHierarchy* hAnimHier = GetAnimHierarchyFromSkinClump(clump);
600+
if (hAnimHier)
601+
{
602+
int boneAnimIdIndex = RpHAnimIDGetIndex(hAnimHier, boneId);
603+
if (boneAnimIdIndex != -1)
604+
return &RpHAnimHierarchyGetMatrixArray(hAnimHier)[boneAnimIdIndex];
605+
}
606+
return nullptr;
607+
}
608+
609+
bool CEntitySA::SetBoneMatrix(eBone boneId, const CMatrix& matrix)
610+
{
611+
RwMatrixTag* rwBoneMatrix = GetBoneRwMatrix(boneId);
612+
if (rwBoneMatrix)
613+
{
614+
CMatrixSAInterface boneMatrix(rwBoneMatrix, false);
615+
boneMatrix.SetMatrix(matrix.vRight, matrix.vFront, matrix.vUp, matrix.vPos);
616+
boneMatrix.UpdateRW();
617+
return true;
618+
}
619+
return false;
620+
}
621+
622+
bool CEntitySA::GetBoneRotation(eBone boneId, float& yaw, float& pitch, float& roll)
623+
{
624+
RpClump* clump = GetRpClump();
625+
if (clump)
626+
{
627+
// updating the bone frame orientation will also update its children
628+
// This rotation is only applied when UpdateElementRpHAnim is called
629+
CAnimBlendClumpDataSAInterface* clumpDataInterface = *pGame->GetClumpData(clump);
630+
AnimBlendFrameData* frameData = clumpDataInterface->GetFrameDataByNodeId(boneId);
631+
if (frameData)
632+
{
633+
RtQuat* boneOrientation = &frameData->m_pIFrame->orientation;
634+
RwV3d angles = {yaw, roll, pitch};
635+
BoneNode_cSAInterface::QuatToEuler(boneOrientation, &angles);
636+
yaw = angles.x;
637+
roll = angles.y;
638+
pitch = angles.z;
639+
return true;
640+
}
641+
}
642+
return false;
643+
644+
}
645+
646+
bool CEntitySA::SetBoneRotation(eBone boneId, float yaw, float pitch, float roll)
647+
{
648+
RpClump* clump = GetRpClump();
649+
if (clump)
650+
{
651+
// updating the bone frame orientation will also update its children
652+
// This rotation is only applied when UpdateElementRpHAnim is called
653+
CAnimBlendClumpDataSAInterface* clumpDataInterface = *pGame->GetClumpData(clump);
654+
AnimBlendFrameData* frameData = clumpDataInterface->GetFrameDataByNodeId(boneId);
655+
if (frameData)
656+
{
657+
RtQuat* boneOrientation = &frameData->m_pIFrame->orientation;
658+
RwV3d angles = {yaw, roll, pitch};
659+
BoneNode_cSAInterface::EulerToQuat(&angles, boneOrientation);
660+
return true;
661+
}
662+
}
663+
return false;
664+
}
665+
666+
bool CEntitySA::GetBonePosition(eBone boneId, CVector& position)
667+
{
668+
RwMatrixTag* rwBoneMatrix = GetBoneRwMatrix(boneId);
669+
if (rwBoneMatrix)
670+
{
671+
const RwV3d& pos = rwBoneMatrix->pos;
672+
position = {pos.x, pos.y, pos.z};
673+
return true;
674+
}
675+
return false;
676+
}
677+
678+
// NOTE: The position will be reset if UpdateElementRpHAnim is called after this.
679+
bool CEntitySA::SetBonePosition(eBone boneId, const CVector& position)
680+
{
681+
RwMatrixTag* rwBoneMatrix = GetBoneRwMatrix(boneId);
682+
if (rwBoneMatrix)
683+
{
684+
CMatrixSAInterface boneMatrix(rwBoneMatrix, false);
685+
boneMatrix.SetTranslateOnly(position);
686+
boneMatrix.UpdateRW();
687+
return true;
688+
}
689+
return false;
690+
}
691+
586692
BYTE CEntitySA::GetAreaCode()
587693
{
588694
return m_pInterface->m_areaCode;

Client/game_sa/CEntitySA.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ class CEntitySA : public virtual CEntity
242242
CEntitySAInterface* GetInterface() { return m_pInterface; };
243243
VOID SetInterface(CEntitySAInterface* intInterface) { m_pInterface = intInterface; };
244244

245+
bool IsPed() { return GetEntityType() == ENTITY_TYPE_PED; }
246+
void UpdateRpHAnim();
245247
VOID SetPosition(float fX, float fY, float fZ);
246248
VOID Teleport(float fX, float fY, float fZ);
247249
VOID ProcessControl();
@@ -306,6 +308,14 @@ class CEntitySA : public virtual CEntity
306308
unsigned long GetArrayID() { return m_ulArrayID; }
307309
void SetArrayID(unsigned long ulID) { m_ulArrayID = ulID; }
308310

311+
RwMatrixTag* GetBoneRwMatrix(eBone boneId);
312+
bool SetBoneMatrix(eBone boneId, const CMatrix& matrix);
313+
314+
bool GetBoneRotation(eBone boneId, float& yaw, float& pitch, float& roll);
315+
bool SetBoneRotation(eBone boneId, float yaw, float pitch, float roll);
316+
bool GetBonePosition(eBone boneId, CVector& position);
317+
bool SetBonePosition(eBone boneId, const CVector& position);
318+
309319
// CEntitySA interface
310320
virtual void OnChangingPosition(const CVector& vecNewPosition) {}
311321

Client/game_sa/CGameSA.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "D3DResourceSystemSA.h"
1717
#include "CFileLoaderSA.h"
1818

19+
unsigned int& CGameSA::ClumpOffset = *(unsigned int*)0xB5F878;
1920
unsigned long* CGameSA::VAR_SystemTime;
2021
unsigned long* CGameSA::VAR_IsAtMenu;
2122
unsigned long* CGameSA::VAR_IsGameLoaded;

Client/game_sa/CGameSA.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ struct SCheatSA
9797
m_bCanBeSet = bCanBeSet;
9898
}
9999
};
100+
101+
class CAnimBlendClumpDataSAInterface;
102+
100103
class CGameSA : public CGame
101104
{
102105
friend class COffsets;
@@ -426,6 +429,7 @@ class CGameSA : public CGame
426429
void SetPreWeaponFireHandler(PreWeaponFireHandler* pPreWeaponFireHandler) { m_pPreWeaponFireHandler = pPreWeaponFireHandler; }
427430
void SetPostWeaponFireHandler(PostWeaponFireHandler* pPostWeaponFireHandler) { m_pPostWeaponFireHandler = pPostWeaponFireHandler; }
428431
void SetTaskSimpleBeHitHandler(TaskSimpleBeHitHandler* pTaskSimpleBeHitHandler) { m_pTaskSimpleBeHitHandler = pTaskSimpleBeHitHandler; }
432+
CAnimBlendClumpDataSAInterface** GetClumpData(RpClump* clump) { return RWPLUGINOFFSET(CAnimBlendClumpDataSAInterface*, clump, ClumpOffset); }
429433

430434
PreWeaponFireHandler* m_pPreWeaponFireHandler;
431435
PostWeaponFireHandler* m_pPostWeaponFireHandler;
@@ -493,6 +497,7 @@ class CGameSA : public CGame
493497
int m_iCheckStatus;
494498
bool m_bUnderworldWarp;
495499

500+
static unsigned int& ClumpOffset;
496501
static unsigned long* VAR_SystemTime;
497502
static unsigned long* VAR_IsAtMenu;
498503
static unsigned long* VAR_IsGameLoaded;
@@ -512,6 +517,6 @@ class CGameSA : public CGame
512517

513518
SFixedArray<bool, WEAPONTYPE_LAST_WEAPONTYPE> m_JetpackWeapons;
514519

515-
CPed* m_pPedContext;
516-
CTickCount m_llASyncLoadingAutoUnsuspendTime;
520+
CPed* m_pPedContext;
521+
CTickCount m_llASyncLoadingAutoUnsuspendTime;
517522
};

Client/game_sa/CMatrixSA.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include "StdInc.h"
2+
3+
CMatrixSAInterface::CMatrixSAInterface(CMatrixSAInterface const& matrix)
4+
{
5+
((void(__thiscall*)(CMatrixSAInterface*, CMatrixSAInterface const&))0x59BCF0)(this, matrix);
6+
}
7+
8+
CMatrixSAInterface::CMatrixSAInterface(RwMatrixTag* matrix, bool temporary)
9+
{
10+
((void(__thiscall*)(CMatrixSAInterface*, RwMatrixTag*, bool))0x59C050)(this, matrix, temporary);
11+
}
12+
13+
// destructor detaches matrix if attached
14+
CMatrixSAInterface::~CMatrixSAInterface()
15+
{
16+
((void(__thiscall*)(CMatrixSAInterface*))0x59ACD0)(this);
17+
}
18+
19+
void CMatrixSAInterface::ConvertToEulerAngles(float& x, float& y, float& z, std::int32_t flags)
20+
{
21+
((void(__thiscall*)(CMatrixSAInterface*, float&, float&, float&, std::int32_t))0x59A840)(this, x, y, z, flags);
22+
}
23+
void CMatrixSAInterface::ConvertFromEulerAngles(float x, float y, float z, std::int32_t flags)
24+
{
25+
((void(__thiscall*)(CMatrixSAInterface*, float, float, float, std::int32_t))0x59AA40)(this, x, y, z, flags);
26+
}
27+
28+
void CMatrixSAInterface::UpdateRW()
29+
{
30+
((void(__thiscall*)(CMatrixSAInterface*))0x59BBB0)(this);
31+
}

Client/game_sa/CMatrixSA.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#pragma once
2+
#include "CVector.h"
3+
#include "CRenderWareSA.h"
4+
5+
class CMatrixSAInterface
6+
{
7+
private:
8+
// RwV3d-like:
9+
CVector m_right;
10+
unsigned int flags;
11+
CVector m_forward;
12+
unsigned int pad1;
13+
CVector m_up;
14+
unsigned int pad2;
15+
CVector m_pos;
16+
unsigned int pad3;
17+
18+
public:
19+
RwMatrixTag* m_pAttachMatrix = nullptr;
20+
bool m_bOwnsAttachedMatrix = false; // do we need to delete attaching matrix at detaching
21+
22+
CMatrixSAInterface(CMatrixSAInterface const& matrix);
23+
CMatrixSAInterface(RwMatrixTag* matrix, bool temporary); // like previous + attach
24+
~CMatrixSAInterface(); // destructor detaches matrix if attached
25+
26+
void ConvertToEulerAngles(float& x, float& y, float& z, std::int32_t flags);
27+
void ConvertFromEulerAngles(float x, float y, float z, std::int32_t flags);
28+
void UpdateRW();
29+
void SetTranslateOnly(CVector position) { m_pos = position; }
30+
void SetMatrix(const CVector& right, const CVector& forward, const CVector& up, const CVector& pos)
31+
{
32+
m_right = right;
33+
m_forward = forward;
34+
m_up = up;
35+
m_pos = pos;
36+
}
37+
};

0 commit comments

Comments
 (0)