Skip to content

Commit

Permalink
Add animation validation (PR #3557)
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Moris authored Jul 10, 2024
1 parent 8e72db1 commit 27a24b5
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 55 deletions.
70 changes: 58 additions & 12 deletions Client/game_sa/CAnimManagerSA.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CAnimManagerSA.cpp
* FILE: Client/game_sa/CAnimManagerSA.cpp
* PURPOSE: Animation manager
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
* Multi Theft Auto is available from https://multitheftauto.com/
*
*****************************************************************************/

Expand All @@ -21,7 +21,14 @@

extern CGameSA* pGame;

using std::list;
// This "gateway" animation will allow us to play custom animations by simply playing this animation
// and then in AddAnimation and AddAnimationAndSync hook, we can return our custom animation in the
// hook instead of run_wuzi. This will trick GTA SA into thinking that it is playing run_wuzi from
// ped block, but in reality, it's playing our custom animation, and Of course, we can return run_wuzi
// animation within the hook if we want to play it instead. Why run_wuzi? We can also use another animation,
// but I've tested with this one mostly, so let's stick to this.
static const char* const kGateWayBlockName = "ped";
static const char* const kGateWayAnimationName = "run_wuzi";

CAnimManagerSA::CAnimManagerSA()
{
Expand Down Expand Up @@ -195,7 +202,7 @@ int CAnimManagerSA::RegisterAnimBlock(const char* szName)
return iReturn;
}

std::unique_ptr<CAnimBlendAssocGroup> CAnimManagerSA::GetAnimBlendAssoc(AssocGroupId groupID)
std::unique_ptr<CAnimBlendAssocGroup> CAnimManagerSA::GetAnimBlendAssoc(AssocGroupId groupID) const
{
CAnimBlendAssocGroupSAInterface* pInterface = nullptr;
DWORD dwFunc = FUNC_CAnimManager_GetAnimBlendAssoc;
Expand Down Expand Up @@ -274,8 +281,12 @@ std::unique_ptr<CAnimBlendAssociation> CAnimManagerSA::CreateAnimAssociation(Ass
return nullptr;
}

CAnimManagerSA::StaticAssocIntface_type CAnimManagerSA::GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID)
CAnimManagerSA::StaticAssocIntface_type CAnimManagerSA::GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID) const
{
// We check the validity of the group, avoid crashes due to an invalid group
if (!IsValidGroup(static_cast<std::uint32_t>(animGroup)))
return nullptr;

CAnimBlendStaticAssociationSAInterface* pInterface = nullptr;
DWORD dwFunc = FUNC_CAnimManager_GetAnimAssociation;
_asm
Expand All @@ -295,6 +306,10 @@ CAnimManagerSA::StaticAssocIntface_type CAnimManagerSA::GetAnimStaticAssociation

std::unique_ptr<CAnimBlendAssociation> CAnimManagerSA::GetAnimAssociation(AssocGroupId animGroup, const char* szAnimName)
{
// We check the validity of the group, avoid crashes due to an invalid group
if (!IsValidGroup(animGroup))
return nullptr;

CAnimBlendAssociationSAInterface* pInterface = nullptr;
DWORD dwFunc = FUNC_CAnimManager_GetAnimAssociation_str;
_asm
Expand Down Expand Up @@ -363,7 +378,7 @@ std::unique_ptr<CAnimBlendAssociation> CAnimManagerSA::AddAnimationAndSync(RpClu
AnimationId animID)
{
if (!pClump)
return NULL;
return nullptr;

CAnimBlendAssociationSAInterface* pInterface = nullptr;
DWORD dwFunc = FUNC_CAnimManager_AddAnimationAndSync;
Expand All @@ -387,8 +402,8 @@ std::unique_ptr<CAnimBlendAssociation> CAnimManagerSA::AddAnimationAndSync(RpClu

std::unique_ptr<CAnimBlendAssociation> CAnimManagerSA::BlendAnimation(RpClump* pClump, AssocGroupId animGroup, AnimationId animID, float fBlendDelta)
{
if (!pClump)
return NULL;
if (!pClump || !IsValidAnim(animGroup, animID))
return nullptr;

CAnimBlendAssociationSAInterface* pInterface = nullptr;
DWORD dwFunc = FUNC_CAnimManager_BlendAnimation;
Expand Down Expand Up @@ -495,7 +510,10 @@ void CAnimManagerSA::RemoveAnimBlock(int ID)
AnimAssocDefinition* CAnimManagerSA::AddAnimAssocDefinition(const char* szBlockName, const char* szAnimName, AssocGroupId animGroup, AnimationId animID,
AnimDescriptor* pDescriptor)
{
AnimAssocDefinition* pReturn;
if (!IsValidAnim(animGroup, animID))
return nullptr;

AnimAssocDefinition* pReturn{};
DWORD dwFunc = FUNC_CAnimManager_AddAnimAssocDefinition;
_asm
{
Expand All @@ -508,7 +526,7 @@ AnimAssocDefinition* CAnimManagerSA::AddAnimAssocDefinition(const char* szBlockN
mov pReturn, eax
add esp, 0x14
}
return NULL;
return pReturn;
}

void CAnimManagerSA::ReadAnimAssociationDefinitions()
Expand Down Expand Up @@ -849,5 +867,33 @@ void CAnimManagerSA::DeleteCustomAnimSequenceInterface(CAnimBlendSequenceSAInter

bool CAnimManagerSA::isGateWayAnimationHierarchy(CAnimBlendHierarchySAInterface* pInterface)
{
return pGame->GetKeyGen()->GetUppercaseKey(m_kGateWayAnimationName.c_str()) == pInterface->uiHashKey;
return pGame->GetKeyGen()->GetUppercaseKey(kGateWayAnimationName) == pInterface->uiHashKey;
}

const char* CAnimManagerSA::GetGateWayBlockName() const
{
return kGateWayBlockName;
}

const char* CAnimManagerSA::GetGateWayAnimationName() const
{
return kGateWayAnimationName;
}

bool CAnimManagerSA::IsValidGroup(std::uint32_t uiAnimGroup) const
{
const auto pGroup = GetAnimBlendAssoc(uiAnimGroup);
return pGroup && pGroup->IsCreated();
}

bool CAnimManagerSA::IsValidAnim(std::uint32_t uiAnimGroup, std::uint32_t uiAnimID) const
{
// We get an animation for the checks
const auto pAnim = GetAnimStaticAssociation((eAnimGroup)uiAnimGroup, (eAnimID)uiAnimID);
if (!pAnim)
return false;

// We check the interface and sAnimID, if AnimID is not in GTA:SA, it will differ from our indicators in sAnimID
const auto pInterface = pAnim->GetInterface();
return pInterface && pInterface->sAnimID == uiAnimID;
}
27 changes: 10 additions & 17 deletions Client/game_sa/CAnimManagerSA.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CAnimManagerSA.h
* FILE: Client/game_sa/CAnimManagerSA.h
* PURPOSE: Header file for animation manager class
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
* Multi Theft Auto is available from https://multitheftauto.com/
*
*****************************************************************************/

Expand Down Expand Up @@ -94,14 +94,14 @@ class CAnimManagerSA : public CAnimManager
int GetAnimationBlockIndex(const char* szName);
int RegisterAnimBlock(const char* szName);

std::unique_ptr<CAnimBlendAssocGroup> GetAnimBlendAssoc(AssocGroupId groupID);
std::unique_ptr<CAnimBlendAssocGroup> GetAnimBlendAssoc(AssocGroupId groupID) const;
AssocGroupId GetFirstAssocGroup(const char* szName);

const char* GetAnimGroupName(AssocGroupId groupID);
const char* GetAnimBlockName(AssocGroupId groupID);

std::unique_ptr<CAnimBlendAssociation> CreateAnimAssociation(AssocGroupId animGroup, AnimationId animID);
StaticAssocIntface_type GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID);
StaticAssocIntface_type GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID) const;
std::unique_ptr<CAnimBlendAssociation> GetAnimAssociation(AssocGroupId animGroup, const char* szAnimName);
std::unique_ptr<CAnimBlendAssociation> AddAnimation(RpClump* pClump, AssocGroupId animGroup, AnimationId animID);
std::unique_ptr<CAnimBlendAssociation> AddAnimation(RpClump* pClump, CAnimBlendHierarchy*, int ID);
Expand Down Expand Up @@ -159,20 +159,13 @@ class CAnimManagerSA : public CAnimManager
void DeleteCustomAnimHierarchyInterface(CAnimBlendHierarchySAInterface* pInterface);
void DeleteCustomAnimSequenceInterface(CAnimBlendSequenceSAInterface* pInterface);

bool isGateWayAnimationHierarchy(CAnimBlendHierarchySAInterface* pInterface);
const SString& GetGateWayBlockName() { return m_kGateWayBlockName; };
const SString& GetGateWayAnimationName() { return m_kGateWayAnimationName; };
bool isGateWayAnimationHierarchy(CAnimBlendHierarchySAInterface* pInterface);
const char* GetGateWayBlockName() const;
const char* GetGateWayAnimationName() const;

bool IsValidGroup(std::uint32_t uiAnimGroup) const;
bool IsValidAnim(std::uint32_t uiAnimGroup, std::uint32_t uiAnimID) const;
private:
CAnimBlendAssocGroup* m_pAnimAssocGroups[MAX_ANIM_GROUPS];
CAnimBlock* m_pAnimBlocks[MAX_ANIM_BLOCKS];

// This "gateway" animation will allow us to play custom animations by simply playing this animation
// and then in AddAnimation and AddAnimationAndSync hook, we can return our custom animation in the
// hook instead of run_wuzi. This will trick GTA SA into thinking that it is playing run_wuzi from
// ped block, but in reality, it's playing our custom animation, and Of course, we can return run_wuzi
// animation within the hook if we want to play it instead. Why run_wuzi? We can also use another animation,
// but I've tested with this one mostly, so let's stick to this.
const SString m_kGateWayBlockName = "ped";
const SString m_kGateWayAnimationName = "run_wuzi";
};
16 changes: 13 additions & 3 deletions Client/game_sa/CTasksSA.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CTasksSA.cpp
* FILE: Client/game_sa/CTasksSA.cpp
* PURPOSE: Task creation
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
* Multi Theft Auto is available from https://multitheftauto.com/
*
*****************************************************************************/

Expand All @@ -23,6 +23,7 @@
#include "TaskPhysicalResponseSA.h"
#include "TaskSA.h"
#include "TaskSecondarySA.h"
#include "CAnimManagerSA.h"

extern CGameSA* pGame;

Expand Down Expand Up @@ -141,6 +142,9 @@ CTaskSimpleJetPack* CTasksSA::CreateTaskSimpleJetpack(const CVector* pVecTargetP
CTaskSimpleRunAnim* CTasksSA::CreateTaskSimpleRunAnim(const AssocGroupId animGroup, const AnimationId animID, const float fBlendDelta, const int iTaskType,
const char* pTaskName, const bool bHoldLastFrame)
{
if (!pGame->GetAnimManager()->IsValidAnim(animGroup, animID))
return nullptr;

CTaskSimpleRunAnimSA* pTask = NewTask<CTaskSimpleRunAnimSA>(animGroup, animID, fBlendDelta, iTaskType, pTaskName, bHoldLastFrame);
m_pTaskManagementSystem->AddTask(pTask);
return pTask;
Expand All @@ -160,6 +164,9 @@ CTaskComplexDie* CTasksSA::CreateTaskComplexDie(const eWeaponType eMeansOfDeath,
const float fAnimSpeed, const bool bBeingKilledByStealth, const bool bFallingToDeath, const int iFallToDeathDir,
const bool bFallToDeathOverRailing)
{
if (!pGame->GetAnimManager()->IsValidAnim(animGroup, anim))
return nullptr;

CTaskComplexDieSA* pTask = NewTask<CTaskComplexDieSA>(eMeansOfDeath, animGroup, anim, fBlendDelta, fAnimSpeed, bBeingKilledByStealth, bFallingToDeath,
iFallToDeathDir, bFallToDeathOverRailing);
m_pTaskManagementSystem->AddTask(pTask);
Expand All @@ -168,6 +175,9 @@ CTaskComplexDie* CTasksSA::CreateTaskComplexDie(const eWeaponType eMeansOfDeath,

CTaskSimpleStealthKill* CTasksSA::CreateTaskSimpleStealthKill(bool bKiller, class CPed* pPed, const AnimationId animGroup)
{
if (!pGame->GetAnimManager()->IsValidGroup(animGroup))
return nullptr;

CTaskSimpleStealthKillSA* pTask = NewTask<CTaskSimpleStealthKillSA>(bKiller, pPed, animGroup);
m_pTaskManagementSystem->AddTask(pTask);
return pTask;
Expand Down
6 changes: 3 additions & 3 deletions Client/mods/deathmatch/logic/CPacketHandler.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: mods/deathmatch/logic/CPacketHandler.cpp
* FILE: Client/mods/deathmatch/logic/CPacketHandler.cpp
* PURPOSE: Packet handling and processing
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
* Multi Theft Auto is available from https://multitheftauto.com/
*
*****************************************************************************/

Expand Down
12 changes: 6 additions & 6 deletions Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
*
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
* FILE: Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
* PURPOSE: Scripting function processing
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
* Multi Theft Auto is available from https://multitheftauto.com/
*
*****************************************************************************/

Expand Down Expand Up @@ -2242,15 +2242,15 @@ bool CStaticFunctionDefinitions::SetPedAnimation(CClientEntity& Entity, const SS
if (pIFP)
{
// Play the gateway animation
const SString& strGateWayBlockName = g_pGame->GetAnimManager()->GetGateWayBlockName();
std::unique_ptr<CAnimBlock> pBlock = g_pGame->GetAnimManager()->GetAnimationBlock(strGateWayBlockName);
const char* szGateWayBlockName = g_pGame->GetAnimManager()->GetGateWayBlockName();
std::unique_ptr<CAnimBlock> pBlock = g_pGame->GetAnimManager()->GetAnimationBlock(szGateWayBlockName);
auto pCustomAnimBlendHierarchy = pIFP->GetAnimationHierarchy(szAnimName);
if ((pBlock) && (pCustomAnimBlendHierarchy != nullptr))
{
Ped.SetNextAnimationCustom(pIFP, szAnimName);

const SString& strGateWayAnimationName = g_pGame->GetAnimManager()->GetGateWayAnimationName();
Ped.RunNamedAnimation(pBlock, strGateWayAnimationName, iTime, iBlend, bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame);
const char* szGateWayAnimationName = g_pGame->GetAnimManager()->GetGateWayAnimationName();
Ped.RunNamedAnimation(pBlock, szGateWayAnimationName, iTime, iBlend, bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame);
return true;
}
}
Expand Down
19 changes: 11 additions & 8 deletions Client/sdk/game/CAnimManager.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: sdk/game/CAnimManager.h
* FILE: Client/sdk/game/CAnimManager.h
* PURPOSE: Animation manager interface
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
* Multi Theft Auto is available from https://multitheftauto.com/
*
*****************************************************************************/

Expand Down Expand Up @@ -66,14 +66,14 @@ class CAnimManager
virtual int GetAnimationBlockIndex(const char* szName) = 0;
virtual int RegisterAnimBlock(const char* szName) = 0;

virtual AnimAssocGroup_type GetAnimBlendAssoc(AssocGroupId groupID) = 0;
virtual AnimAssocGroup_type GetAnimBlendAssoc(AssocGroupId groupID) const = 0;
virtual AssocGroupId GetFirstAssocGroup(const char* szName) = 0;

virtual const char* GetAnimGroupName(AssocGroupId groupID) = 0;
virtual const char* GetAnimBlockName(AssocGroupId groupID) = 0;

virtual AnimBlendAssoc_type CreateAnimAssociation(AssocGroupId animGroup, AnimationId animID) = 0;
virtual StaticAssocIntface_type GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID) = 0;
virtual StaticAssocIntface_type GetAnimStaticAssociation(eAnimGroup animGroup, eAnimID animID) const = 0;
virtual AnimBlendAssoc_type GetAnimAssociation(AssocGroupId animGroup, const char* szAnimName) = 0;
virtual AnimBlendAssoc_type AddAnimation(RpClump* pClump, AssocGroupId animGroup, AnimationId animID) = 0;
virtual AnimBlendAssoc_type AddAnimation(RpClump* pClump, CAnimBlendHierarchy*, int ID) = 0;
Expand Down Expand Up @@ -128,7 +128,10 @@ class CAnimManager
virtual void DeleteCustomAnimHierarchyInterface(CAnimBlendHierarchySAInterface* pInterface) = 0;
virtual void DeleteCustomAnimSequenceInterface(CAnimBlendSequenceSAInterface* pInterface) = 0;

virtual bool isGateWayAnimationHierarchy(CAnimBlendHierarchySAInterface* pInterface) = 0;
virtual const SString& GetGateWayBlockName() = 0;
virtual const SString& GetGateWayAnimationName() = 0;
virtual bool isGateWayAnimationHierarchy(CAnimBlendHierarchySAInterface* pInterface) = 0;
virtual const char* GetGateWayBlockName() const = 0;
virtual const char* GetGateWayAnimationName() const = 0;

virtual bool IsValidGroup(std::uint32_t uiAnimGroup) const = 0;
virtual bool IsValidAnim(std::uint32_t uiAnimGroup, std::uint32_t uiAnimID) const = 0;
};
6 changes: 3 additions & 3 deletions Server/mods/deathmatch/logic/CGame.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: mods/deathmatch/logic/CGame.cpp
* FILE: Server/mods/deathmatch/logic/CGame.cpp
* PURPOSE: Server game class
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
* Multi Theft Auto is available from https://multitheftauto.com/
*
*****************************************************************************/

Expand Down
6 changes: 3 additions & 3 deletions Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
* FILE: Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
* PURPOSE: Lua static function definitions class
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
* Multi Theft Auto is available from https://multitheftauto.com/
*
*****************************************************************************/

Expand Down

0 comments on commit 27a24b5

Please sign in to comment.