Skip to content

Commit cc41b27

Browse files
authored
Merge pull request #4 from saml1er/custom_ifp_animations
Custom ifp animations
2 parents c3fb1aa + b8a92b0 commit cc41b27

File tree

10 files changed

+253
-11
lines changed

10 files changed

+253
-11
lines changed

Client/game_sa/CAnimBlendHierarchySA.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class CAnimBlendHierarchySAInterface
3434
BYTE pad;
3535
int iAnimBlockID;
3636
float fTotalTime;
37+
DWORD * pLinkPtr;
3738
//class CLink<class CAnimBlendHierarchy *> * pLinkPtr;
3839
};
3940

Client/game_sa/CAnimBlockSA.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ class CAnimBlockSAInterface // 32 bytes
2727
bool bLoaded; // ?
2828
BYTE pad [ 1 ];
2929
unsigned short usRefs;
30-
BYTE pad2 [ 12 ];
30+
int idOffset;
31+
size_t nAnimations;
32+
DWORD dwAssocGroup;
3133
};
3234

3335
class CAnimBlockSA : public CAnimBlock

Client/mods/deathmatch/logic/CClientGame.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4029,7 +4029,24 @@ void CClientGame::AssocGroupCopyAnimationHandler ( CAnimBlendStaticAssociationSA
40294029
CAnimManager * pAnimationManager = g_pGame->GetAnimManager();
40304030
auto pOriginalAnimStaticAssoc = pAnimationManager->GetAnimStaticAssociation ( pAnimAssocGroup->groupID, animID );
40314031

4032-
CAnimBlendStaticAssociation_Init ( pOutAnimStaticAssoc, pClump, pOriginalAnimStaticAssoc->pAnimHeirarchy );
4032+
CClientPed * pClientPed = GetClientPedByClump ( *pClump );
4033+
if ( pClientPed != nullptr )
4034+
{
4035+
auto pReplacedAnimHeirarchyInterface = pClientPed->getReplacedAnimation ( pOriginalAnimStaticAssoc->pAnimHeirarchy );
4036+
if ( pReplacedAnimHeirarchyInterface != nullptr )
4037+
{ // Play our custom animation instead of default
4038+
CAnimBlendStaticAssociation_Init ( pOutAnimStaticAssoc, pClump, pReplacedAnimHeirarchyInterface );
4039+
}
4040+
else
4041+
{ // Play default internal animation
4042+
CAnimBlendStaticAssociation_Init ( pOutAnimStaticAssoc, pClump, pOriginalAnimStaticAssoc->pAnimHeirarchy );
4043+
}
4044+
}
4045+
else
4046+
{ // Play default internal animation
4047+
CAnimBlendStaticAssociation_Init ( pOutAnimStaticAssoc, pClump, pOriginalAnimStaticAssoc->pAnimHeirarchy );
4048+
}
4049+
40334050
pOutAnimStaticAssoc->sAnimGroup = static_cast < short > ( pAnimAssocGroup->groupID );
40344051
pOutAnimStaticAssoc->sAnimID = static_cast < short > ( animID );
40354052

@@ -6874,3 +6891,16 @@ CClientPed * CClientGame::GetClientPedByClump ( const RpClump & Clump )
68746891
}
68756892
return nullptr;
68766893
}
6894+
6895+
void CClientGame::onClientIFPUnload ( const CClientIFP & IFP )
6896+
{
6897+
// remove IFP animations from replaced animations of peds/players
6898+
for ( auto it = m_mapOfPedPointers.begin(); it != m_mapOfPedPointers.end(); it++ )
6899+
{
6900+
CEntity * pEntity = it->first->GetGameEntity();
6901+
if ( pEntity != nullptr )
6902+
{
6903+
it->first->RestoreAnimations ( IFP );
6904+
}
6905+
}
6906+
}

Client/mods/deathmatch/logic/CClientGame.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -594,11 +594,12 @@ class CClientGame
594594
void RemoveIFPPointerFromMap ( const SString & strBlockName );
595595
CClientIFP * GetIFPPointerFromMap ( const SString & strBlockName );
596596

597-
void InsertPedPointerToMap ( CClientPed * pPed );
598-
void RemovePedPointerFromMap ( CClientPed * pPed );
599-
CClientPed * GetClientPedByClump ( const RpClump & Clump );
600-
597+
void InsertPedPointerToMap ( CClientPed * pPed );
598+
void RemovePedPointerFromMap ( CClientPed * pPed );
599+
CClientPed * GetClientPedByClump ( const RpClump & Clump );
601600

601+
void onClientIFPUnload ( const CClientIFP & IFP );
602+
602603
private:
603604
eStatus m_Status;
604605
eServerType m_ServerType;

Client/mods/deathmatch/logic/CClientIFP.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ void CClientIFP::UnloadIFP ( void )
5050
{
5151
printf ("CClientIFP::UnloadIFP ( ) called!\n");
5252

53-
53+
// first remove IFP from map, so we can indicate that it does not exist
54+
g_pClientGame->RemoveIFPPointerFromMap ( m_strBlockName );
55+
56+
// remove IFP animations from replaced animations of peds/players
57+
g_pClientGame->onClientIFPUnload ( *this );
58+
5459
for ( size_t i = 0; i < m_Animations.size(); i++ )
5560
{
5661
IFP_Animation * ifpAnimation = &m_Animations[i];
@@ -80,9 +85,7 @@ void CClientIFP::UnloadIFP ( void )
8085
delete ifpAnimation->pSequencesMemory;
8186
}
8287

83-
g_pClientGame->RemoveIFPPointerFromMap ( m_strBlockName );
84-
85-
printf ("IFP unloaded sucessfully, removed from map as well.\n");
88+
printf ("IFP unloaded sucessfully with block name '%s'\n", m_strBlockName.c_str());
8689
}
8790
}
8891

Client/mods/deathmatch/logic/CClientPed.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6191,6 +6191,61 @@ CAnimBlendAssociation * CClientPed::GetFirstAnimation ( void )
61916191
return NULL;
61926192
}
61936193

6194+
void CClientPed::ReplaceAnimation ( CAnimBlendHierarchy * pInternalAnimHierarchy, CClientIFP * pIFP, CAnimBlendHierarchySAInterface * pCustomAnimHierarchy )
6195+
{
6196+
SReplacedAnimation replacedAnimation;
6197+
replacedAnimation.pIFP = pIFP;
6198+
replacedAnimation.pAnimationHierarchy = pCustomAnimHierarchy;
6199+
6200+
m_mapOfReplacedAnimations [ pInternalAnimHierarchy->GetInterface () ] = replacedAnimation;
6201+
}
6202+
6203+
void CClientPed::RestoreAnimation ( CAnimBlendHierarchy * pInternalAnimHierarchy )
6204+
{
6205+
m_mapOfReplacedAnimations.erase ( pInternalAnimHierarchy->GetInterface () );
6206+
}
6207+
6208+
void CClientPed::RestoreAnimations ( const CClientIFP & IFP )
6209+
{
6210+
for ( auto const& x : m_mapOfReplacedAnimations )
6211+
{
6212+
const CClientIFP & replacedAnimationIFP = *x.second.pIFP;
6213+
if ( std::addressof ( IFP ) == std::addressof ( replacedAnimationIFP ) )
6214+
{
6215+
m_mapOfReplacedAnimations.erase ( x.first );
6216+
}
6217+
}
6218+
}
6219+
6220+
#include "../game_sa/CAnimBlockSA.h" // REMOVE THIS LATER, USE FACTORY METHOD!!!!!!
6221+
6222+
void CClientPed::RestoreAnimations ( CAnimBlock & animationBlock )
6223+
{
6224+
const CAnimBlockSAInterface * pInternalBlockInterface = animationBlock.GetInterface ( );
6225+
DWORD iAnimationIndex = pInternalBlockInterface->idOffset;
6226+
for ( size_t i = 0; i < pInternalBlockInterface->nAnimations; i++ )
6227+
{
6228+
auto pAnimHierarchyInterface = (CAnimBlendHierarchySAInterface*)((BYTE*)ARRAY_CAnimManager_Animations + sizeof(CAnimBlendHierarchySAInterface) * iAnimationIndex);
6229+
m_mapOfReplacedAnimations.erase ( pAnimHierarchyInterface );
6230+
iAnimationIndex ++;
6231+
}
6232+
}
6233+
6234+
void CClientPed::RestoreAllAnimations ( void )
6235+
{
6236+
m_mapOfReplacedAnimations.clear ( );
6237+
}
6238+
6239+
CAnimBlendHierarchySAInterface * CClientPed::getReplacedAnimation ( CAnimBlendHierarchySAInterface * pInternalHierarchyInterface )
6240+
{
6241+
CClientPed::ReplacedAnim_type::iterator it;
6242+
it = m_mapOfReplacedAnimations.find ( pInternalHierarchyInterface );
6243+
if ( it != m_mapOfReplacedAnimations.end ( ) )
6244+
{
6245+
return it->second.pAnimationHierarchy;
6246+
}
6247+
return nullptr;
6248+
}
61946249

61956250
CSphere CClientPed::GetWorldBoundingSphere ( void )
61966251
{

Client/mods/deathmatch/logic/CClientPed.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class CClientPed;
2424

2525
#include <multiplayer/CMultiplayer.h>
2626
#include "CClientPad.h"
27+
#include <../game_sa/CAnimBlendHierarchySA.h>
28+
#include <memory>
2729

2830
class CClientCamera;
2931
class CClientManager;
@@ -116,6 +118,14 @@ struct SRestoreWeaponItem
116118
eWeaponType eWeaponID;
117119
};
118120

121+
class CClientIFP;
122+
123+
struct SReplacedAnimation
124+
{
125+
CClientIFP * pIFP;
126+
CAnimBlendHierarchySAInterface * pAnimationHierarchy;
127+
};
128+
119129
class CClientObject;
120130

121131
// To hide the ugly "pointer truncation from DWORD* to unsigned long warning
@@ -124,6 +134,7 @@ class CClientObject;
124134
class CClientPed : public CClientStreamElement, public CAntiCheatModule
125135
{
126136
DECLARE_CLASS( CClientPed, CClientStreamElement )
137+
typedef std::map < CAnimBlendHierarchySAInterface *, SReplacedAnimation > ReplacedAnim_type;
127138
friend class CClientCamera;
128139
friend class CClientPlayer;
129140
friend class CClientVehicle;
@@ -464,6 +475,12 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule
464475
const SString & GetNextAnimationCustomBlockName ( void ) { return m_strCustomIFPBlockName; }
465476
const SString & GetNextAnimationCustomName ( void ) { return m_strCustomIFPAnimationName; }
466477

478+
void ReplaceAnimation ( CAnimBlendHierarchy * pInternalAnimHierarchy, CClientIFP * pIFP, CAnimBlendHierarchySAInterface * pCustomAnimHierarchy );
479+
void RestoreAnimation ( CAnimBlendHierarchy * pInternalAnimHierarchy );
480+
void RestoreAnimations ( const CClientIFP & IFP );
481+
void RestoreAnimations ( CAnimBlock & animationBlock );
482+
void RestoreAllAnimations ( void );
483+
CAnimBlendHierarchySAInterface * getReplacedAnimation ( CAnimBlendHierarchySAInterface * pInternalHierarchyInterface );
467484
protected:
468485
// This constructor is for peds managed by a player. These are unknown to the ped manager.
469486
CClientPed ( CClientManager* pManager, unsigned long ulModelID, ElementID ID, bool bIsLocalPlayer );
@@ -664,6 +681,9 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule
664681
bool m_bisCurrentAnimationCustom;
665682
SString m_strCustomIFPBlockName;
666683
SString m_strCustomIFPAnimationName;
684+
685+
// Key: Internal GTA animation, Value: Custom Animation
686+
ReplacedAnim_type m_mapOfReplacedAnimations;
667687
};
668688

669689
#endif

Client/mods/deathmatch/logic/CResource.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class CResource
9292
inline CClientEntity* GetResourceCOLModelRoot ( void ) { return m_pResourceCOLRoot; };
9393
inline CClientEntity* GetResourceDFFRoot ( void ) { return m_pResourceDFFEntity; };
9494
inline CClientEntity* GetResourceTXDRoot ( void ) { return m_pResourceTXDRoot; };
95+
inline CClientEntity* GetResourceIFPRoot ( void ) { return m_pResourceIFPRoot; };
9596

9697
// This is to delete all the elements created in this resource that are created locally in this client
9798
void DeleteClientChildren ( void );

Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ void CLuaEngineDefs::LoadFunctions ( void )
2222
CLuaCFunctions::AddFunction ( "engineRestoreCOL", EngineRestoreCOL );
2323
CLuaCFunctions::AddFunction ( "engineReplaceModel", EngineReplaceModel );
2424
CLuaCFunctions::AddFunction ( "engineRestoreModel", EngineRestoreModel );
25+
CLuaCFunctions::AddFunction ( "engineReplaceAnimation", EngineReplaceAnimation );
26+
CLuaCFunctions::AddFunction ( "engineRestoreAnimation", EngineRestoreAnimation );
2527
CLuaCFunctions::AddFunction ( "engineGetModelLODDistance", EngineGetModelLODDistance );
2628
CLuaCFunctions::AddFunction ( "engineSetModelLODDistance", EngineSetModelLODDistance );
2729
CLuaCFunctions::AddFunction ( "engineSetAsynchronousLoading", EngineSetAsynchronousLoading );
@@ -304,7 +306,7 @@ int CLuaEngineDefs::EngineLoadIFP ( lua_State* luaVM )
304306
if ( CResourceManager::ParseResourcePathInput( strFile, pResource, &strPath ) )
305307
{
306308
// Grab the resource root entity
307-
CClientEntity* pRoot = pResource->GetResourceTXDRoot ();
309+
CClientEntity* pRoot = pResource->GetResourceIFPRoot ();
308310

309311
// Check whether the IFP blockname exists or not
310312
if ( g_pClientGame->GetIFPPointerFromMap ( strBlockName ) == nullptr )
@@ -507,6 +509,131 @@ int CLuaEngineDefs::EngineRestoreModel ( lua_State* luaVM )
507509
}
508510

509511

512+
int CLuaEngineDefs::EngineReplaceAnimation ( lua_State* luaVM )
513+
{
514+
CClientEntity * pEntity = nullptr;
515+
SString strInternalBlockName = "";
516+
SString strInternalAnimName = "";
517+
SString strCustomBlockName = "";
518+
SString strCustomAnimName = "";
519+
520+
CScriptArgReader argStream ( luaVM );
521+
argStream.ReadUserData ( pEntity );
522+
argStream.ReadString ( strInternalBlockName );
523+
argStream.ReadString ( strInternalAnimName );
524+
argStream.ReadString ( strCustomBlockName );
525+
argStream.ReadString ( strCustomAnimName );
526+
527+
if ( !argStream.HasErrors () )
528+
{
529+
if ( IS_PED ( pEntity ) )
530+
{
531+
CClientPed& Ped = static_cast < CClientPed& > ( *pEntity );
532+
533+
CAnimBlock * pInternalBlock = g_pGame->GetAnimManager ()->GetAnimationBlock ( strInternalBlockName );
534+
CClientIFP * pCustomIFP = g_pClientGame->GetIFPPointerFromMap ( strCustomBlockName );
535+
if ( pInternalBlock && pCustomIFP )
536+
{
537+
CAnimBlendHierarchy * pInternalAnimHierarchy = g_pGame->GetAnimManager ()->GetAnimation ( strInternalAnimName, pInternalBlock );
538+
CAnimBlendHierarchySAInterface * pCustomAnimHierarchyInterface = pCustomIFP->GetAnimationHierarchy ( strCustomAnimName );
539+
if ( pInternalAnimHierarchy && pCustomAnimHierarchyInterface )
540+
{
541+
Ped.ReplaceAnimation ( pInternalAnimHierarchy, pCustomIFP, pCustomAnimHierarchyInterface );
542+
lua_pushboolean ( luaVM, true );
543+
return 1;
544+
}
545+
else
546+
argStream.SetCustomError ( "Incorrect Animation name" );
547+
}
548+
else
549+
argStream.SetCustomError ( "Incorrect Block name" );
550+
}
551+
}
552+
if ( argStream.HasErrors () )
553+
m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage () );
554+
555+
lua_pushboolean ( luaVM, false );
556+
return 1;
557+
}
558+
559+
560+
int CLuaEngineDefs::EngineRestoreAnimation ( lua_State* luaVM )
561+
{
562+
CClientEntity * pEntity = nullptr;
563+
bool bRestoreAllAnimations = false;
564+
bool bRestoreBlockAnimations = false;
565+
SString strInternalBlockName = "";
566+
SString strInternalAnimName = "";
567+
568+
CScriptArgReader argStream ( luaVM );
569+
argStream.ReadUserData ( pEntity );
570+
if ( argStream.NextIsNil ( ) || argStream.NextIsNone ( ) )
571+
{
572+
bRestoreAllAnimations = true;
573+
}
574+
else
575+
{
576+
argStream.ReadString ( strInternalBlockName );
577+
if ( argStream.NextIsNil ( ) || argStream.NextIsNone ( ) )
578+
{
579+
bRestoreBlockAnimations = true;
580+
}
581+
else
582+
{
583+
argStream.ReadString ( strInternalAnimName );
584+
}
585+
}
586+
587+
if ( !argStream.HasErrors () )
588+
{
589+
if ( IS_PED ( pEntity ) )
590+
{
591+
CClientEntity & Entity = *pEntity;
592+
CClientPed& Ped = static_cast < CClientPed& > ( Entity );
593+
594+
if ( bRestoreAllAnimations )
595+
{
596+
Ped.RestoreAllAnimations ( );
597+
lua_pushboolean ( luaVM, true );
598+
return 1;
599+
}
600+
else
601+
{
602+
CAnimBlock * pInternalBlock = g_pGame->GetAnimManager ()->GetAnimationBlock ( strInternalBlockName );
603+
if ( pInternalBlock )
604+
{
605+
if ( bRestoreBlockAnimations )
606+
{
607+
Ped.RestoreAnimations ( *pInternalBlock );
608+
lua_pushboolean ( luaVM, true );
609+
return 1;
610+
}
611+
else
612+
{
613+
CAnimBlendHierarchy * pInternalAnimHierarchy = g_pGame->GetAnimManager ()->GetAnimation ( strInternalAnimName, pInternalBlock );
614+
if ( pInternalAnimHierarchy )
615+
{
616+
Ped.RestoreAnimation ( pInternalAnimHierarchy );
617+
lua_pushboolean ( luaVM, true );
618+
return 1;
619+
}
620+
else
621+
argStream.SetCustomError ( "Incorrect Animation name" );
622+
}
623+
}
624+
else
625+
argStream.SetCustomError ( "Incorrect Block name" );
626+
}
627+
}
628+
}
629+
if ( argStream.HasErrors () )
630+
m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage () );
631+
632+
lua_pushboolean ( luaVM, false );
633+
return 1;
634+
}
635+
636+
510637
int CLuaEngineDefs::EngineGetModelLODDistance ( lua_State* luaVM )
511638
{
512639
// float engineGetModelLODDistance ( int/string modelID )

Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class CLuaEngineDefs : public CLuaDefs
2727
LUA_DECLARE ( EngineRestoreCOL );
2828
LUA_DECLARE ( EngineReplaceModel );
2929
LUA_DECLARE ( EngineRestoreModel );
30+
LUA_DECLARE ( EngineReplaceAnimation );
31+
LUA_DECLARE ( EngineRestoreAnimation );
3032
LUA_DECLARE ( EngineReplaceMatchingAtomics );
3133
LUA_DECLARE ( EngineReplaceWheelAtomics );
3234
LUA_DECLARE ( EnginePositionAtomic );

0 commit comments

Comments
 (0)