Skip to content

Commit 49ffc91

Browse files
committed
Fix 462: Player crouched state resets after setPedAnimation() was called
Added a new parameter to setPedAnimation. Setting the parameter to true will restore the crouch task when the animation ends If ped was ducked before playing animation.
1 parent 426ad3f commit 49ffc91

File tree

15 files changed

+152
-47
lines changed

15 files changed

+152
-47
lines changed

Client/game_sa/CPedIntelligenceSA.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,9 @@ CTaskSimpleUseGunSAInterface* CPedIntelligenceSA::GetTaskUseGun()
9494

9595
return pTaskUseGun;
9696
}
97+
98+
CTaskSAInterface* CPedIntelligenceSA::SetTaskDuckSecondary(unsigned short nLengthOfDuck)
99+
{
100+
auto SetTaskDuckSecondary = (CTaskSAInterface * (__thiscall*)(CPedIntelligenceSAInterface*, unsigned short))0x601230;
101+
return SetTaskDuckSecondary(internalInterface, nLengthOfDuck);
102+
}

Client/game_sa/CPedIntelligenceSA.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,5 @@ class CPedIntelligenceSA : public CPedIntelligence
6969
CVehicleScanner* GetVehicleScanner();
7070
bool TestForStealthKill(CPed* pPed, bool bUnk);
7171
CTaskSimpleUseGunSAInterface* GetTaskUseGun();
72+
CTaskSAInterface* SetTaskDuckSecondary(unsigned short nLengthOfDuck);
7273
};

Client/mods/deathmatch/logic/CClientGame.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ CClientGame::CClientGame(bool bLocalPlay)
276276
g_pMultiplayer->SetGamePlayerDestructHandler(CClientGame::StaticGamePlayerDestructHandler);
277277
g_pMultiplayer->SetGameProjectileDestructHandler(CClientGame::StaticGameProjectileDestructHandler);
278278
g_pMultiplayer->SetGameModelRemoveHandler(CClientGame::StaticGameModelRemoveHandler);
279+
g_pMultiplayer->SetGameRunNamedAnimDestructorHandler(CClientGame::StaticGameRunNamedAnimDestructorHandler);
279280
g_pMultiplayer->SetGameEntityRenderHandler(CClientGame::StaticGameEntityRenderHandler);
280281
g_pMultiplayer->SetFxSystemDestructionHandler(CClientGame::StaticFxSystemDestructionHandler);
281282
g_pMultiplayer->SetDrivebyAnimationHandler(CClientGame::StaticDrivebyAnimationHandler);
@@ -3758,6 +3759,11 @@ void CClientGame::StaticGameModelRemoveHandler(ushort usModelId)
37583759
g_pClientGame->GameModelRemoveHandler(usModelId);
37593760
}
37603761

3762+
void CClientGame::StaticGameRunNamedAnimDestructorHandler(class CTaskSimpleRunNamedAnimSAInterface* pTask)
3763+
{
3764+
g_pClientGame->GameRunNamedAnimDestructorHandler(pTask);
3765+
}
3766+
37613767
void CClientGame::StaticGameEntityRenderHandler(CEntitySAInterface* pGameEntity)
37623768
{
37633769
if (pGameEntity)
@@ -4773,7 +4779,7 @@ bool CClientGame::ObjectDamageHandler(CObjectSAInterface* pObjectInterface, floa
47734779
{
47744780
return true;
47754781
}
4776-
CLuaArguments Arguments;
4782+
CLuaArguments Arguments;
47774783
Arguments.PushNumber(fLoss);
47784784

47794785
CClientEntity* pClientAttacker = pPools->GetClientEntity((DWORD*)pAttackerInterface);
@@ -4919,6 +4925,20 @@ void CClientGame::GameModelRemoveHandler(ushort usModelId)
49194925
// m_pGameEntityXRefManager->OnGameModelRemove(usModelId);
49204926
}
49214927

4928+
void CClientGame::GameRunNamedAnimDestructorHandler(class CTaskSimpleRunNamedAnimSAInterface* pTask)
4929+
{
4930+
auto it = m_mapOfRunNamedAnimTasks.find(pTask);
4931+
if (it != m_mapOfRunNamedAnimTasks.end())
4932+
{
4933+
CClientPed* pPed = it->second;
4934+
if (pPed && pPed->IsCrouchToBeSetOnAnimEnd())
4935+
{
4936+
pPed->GetGamePlayer()->GetPedIntelligence()->SetTaskDuckSecondary(0);
4937+
}
4938+
m_mapOfRunNamedAnimTasks.erase(pTask);
4939+
}
4940+
}
4941+
49224942
void CClientGame::TaskSimpleBeHitHandler(CPedSAInterface* pPedAttacker, ePedPieceTypes hitBodyPart, int hitBodySide, int weaponId)
49234943
{
49244944
bool bOldBehaviour = !IsGlitchEnabled(GLITCH_HITANIM);
@@ -6930,6 +6950,11 @@ void CClientGame::RemoveAnimationAssociationFromMap(CAnimBlendAssociationSAInter
69306950
m_mapOfCustomAnimationAssociations.erase(pAnimAssociation);
69316951
}
69326952

6953+
void CClientGame::InsertRunNamedAnimTaskToMap(class CTaskSimpleRunNamedAnimSAInterface* pTask, CClientPed* pPed)
6954+
{
6955+
m_mapOfRunNamedAnimTasks[pTask] = pPed;
6956+
}
6957+
69336958
void CClientGame::PedStepHandler(CPedSAInterface* pPedSA, bool bFoot)
69346959
{
69356960
CLuaArguments Arguments;

Client/mods/deathmatch/logic/CClientGame.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class CClientGame
7373
{
7474
friend class CPacketHandler;
7575
typedef std::map<CAnimBlendAssociationSAInterface*, std::shared_ptr<CIFPAnimations> > AnimAssociations_type;
76+
typedef std::map<class CTaskSimpleRunNamedAnimSAInterface*, CClientPed*> RunNamedAnimTask_type;
7677

7778
public:
7879
enum eStatus
@@ -520,6 +521,7 @@ class CClientGame
520521
static void StaticGamePlayerDestructHandler(CEntitySAInterface* pPlayer);
521522
static void StaticGameProjectileDestructHandler(CEntitySAInterface* pProjectile);
522523
static void StaticGameModelRemoveHandler(ushort usModelId);
524+
static void StaticGameRunNamedAnimDestructorHandler(class CTaskSimpleRunNamedAnimSAInterface* pTask);
523525
static bool StaticWorldSoundHandler(const SWorldSoundEvent& event);
524526
static void StaticGameEntityRenderHandler(CEntitySAInterface* pEntity);
525527
static void StaticTaskSimpleBeHitHandler(CPedSAInterface* pPedAttacker, ePedPieceTypes hitBodyPart, int hitBodySide, int weaponId);
@@ -562,6 +564,7 @@ class CClientGame
562564
void GamePlayerDestructHandler(CEntitySAInterface* pPlayer);
563565
void GameProjectileDestructHandler(CEntitySAInterface* pProjectile);
564566
void GameModelRemoveHandler(ushort usModelId);
567+
void GameRunNamedAnimDestructorHandler(class CTaskSimpleRunNamedAnimSAInterface* pTask);
565568
bool WorldSoundHandler(const SWorldSoundEvent& event);
566569
void TaskSimpleBeHitHandler(CPedSAInterface* pPedAttacker, ePedPieceTypes hitBodyPart, int hitBodySide, int weaponId);
567570
AnimationId DrivebyAnimationHandler(AnimationId animGroup, AssocGroupId animId);
@@ -615,6 +618,7 @@ class CClientGame
615618

616619
void InsertAnimationAssociationToMap(CAnimBlendAssociationSAInterface* pAnimAssociation, const std::shared_ptr<CIFPAnimations>& pIFPAnimations);
617620
void RemoveAnimationAssociationFromMap(CAnimBlendAssociationSAInterface* pAnimAssociation);
621+
void InsertRunNamedAnimTaskToMap(class CTaskSimpleRunNamedAnimSAInterface* pTask, CClientPed* pPed);
618622

619623
void PedStepHandler(CPedSAInterface* pPed, bool bFoot);
620624
void VehicleWeaponHitHandler(SVehicleWeaponHitEvent& event);
@@ -834,6 +838,8 @@ class CClientGame
834838
std::map<unsigned int, std::shared_ptr<CClientIFP> > m_mapOfIfpPointers;
835839
std::set<CClientPed*> m_setOfPedPointers;
836840
AnimAssociations_type m_mapOfCustomAnimationAssociations;
841+
// Key is the task and value is the CClientPed*
842+
RunNamedAnimTask_type m_mapOfRunNamedAnimTasks;
837843
};
838844

839845
extern CClientGame* g_pClientGame;

Client/mods/deathmatch/logic/CClientPed.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ void CClientPed::Init(CClientManager* pManager, unsigned long ulModelID, bool bI
9090

9191
m_pRequester = pManager->GetModelRequestManager();
9292

93+
m_bCrouchToBeSetOnAnimEnd = false;
9394
m_bisNextAnimationCustom = false;
9495
m_bisCurrentAnimationCustom = false;
9596
m_strCustomIFPBlockName = "Default";
@@ -5094,7 +5095,7 @@ CClientEntity* CClientPed::GetContactEntity()
50945095
if (pEntity)
50955096
{
50965097
CEntitySAInterface* pInterface = pEntity->GetInterface();
5097-
eEntityType entityType = pInterface ? pEntity->GetEntityType() : ENTITY_TYPE_NOTHING;
5098+
eEntityType entityType = pInterface ? pEntity->GetEntityType() : ENTITY_TYPE_NOTHING;
50985099
if (entityType == ENTITY_TYPE_VEHICLE || entityType == ENTITY_TYPE_OBJECT)
50995100
{
51005101
return pPools->GetClientEntity((DWORD*)pInterface);
@@ -5666,8 +5667,8 @@ void CClientPed::RunAnimation(AssocGroupId animGroup, AnimationId animID)
56665667
}
56675668
}
56685669

5669-
void CClientPed::RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const char* szAnimName, int iTime, int iBlend, bool bLoop, bool bUpdatePosition, bool bInterruptable,
5670-
bool bFreezeLastFrame, bool bRunInSequence, bool bOffsetPed, bool bHoldLastFrame)
5670+
void CClientPed::RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const char* szAnimName, int iTime, int iBlend, bool bLoop, bool bUpdatePosition,
5671+
bool bInterruptable, bool bFreezeLastFrame, bool bRunInSequence, bool bOffsetPed, bool bHoldLastFrame)
56715672
{
56725673
/* lil_Toady: this seems to break things
56735674
// Kill any current animation that might be running
@@ -5725,6 +5726,7 @@ void CClientPed::RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const ch
57255726
if (pTask)
57265727
{
57275728
pTask->SetAsPedTask(m_pPlayerPed, TASK_PRIORITY_PRIMARY);
5729+
g_pClientGame->InsertRunNamedAnimTaskToMap(reinterpret_cast<CTaskSimpleRunNamedAnimSAInterface*>(pTask->GetInterface()), this);
57285730
}
57295731
}
57305732
else
@@ -5775,16 +5777,16 @@ void CClientPed::KillAnimation()
57755777
}
57765778

57775779
std::unique_ptr<CAnimBlock> CClientPed::GetAnimationBlock()
5778-
{
5780+
{
57795781
if (m_pAnimationBlock)
57805782
{
57815783
return g_pGame->GetAnimManager()->GetAnimBlock(m_pAnimationBlock->GetInterface());
57825784
}
5783-
return nullptr;
5785+
return nullptr;
57845786
}
57855787
const char* CClientPed::GetAnimationName()
5786-
{
5787-
return m_strAnimationName;
5788+
{
5789+
return m_strAnimationName;
57885790
}
57895791

57905792
void CClientPed::PostWeaponFire()
@@ -6177,21 +6179,21 @@ std::unique_ptr<CAnimBlendAssociation> CClientPed::GetAnimAssociation(CAnimBlend
61776179
return nullptr;
61786180
}
61796181

6180-
auto pReplacedAnimation = GetReplacedAnimation(pOriginalHierarchyInterface);
6182+
auto pReplacedAnimation = GetReplacedAnimation(pOriginalHierarchyInterface);
61816183
CAnimBlendHierarchySAInterface* pReplacedInterface = nullptr;
61826184
if (pReplacedAnimation != nullptr)
61836185
{
61846186
pReplacedInterface = pReplacedAnimation->pAnimationHierarchy;
61856187
}
61866188

61876189
CAnimManager* pAnimationManager = g_pGame->GetAnimManager();
6188-
auto pAnimAssociation = pAnimationManager->RpAnimBlendClumpGetFirstAssociation(pClump);
6190+
auto pAnimAssociation = pAnimationManager->RpAnimBlendClumpGetFirstAssociation(pClump);
61896191
while (pAnimAssociation)
61906192
{
61916193
auto pAnimNextAssociation = pAnimationManager->RpAnimBlendGetNextAssociation(pAnimAssociation);
61926194
auto pAnimHierarchy = pAnimAssociation->GetAnimHierarchy();
61936195
if (pAnimHierarchy)
6194-
{
6196+
{
61956197
CAnimBlendHierarchySAInterface* pInterface = pAnimHierarchy->GetInterface();
61966198
if (pInterface == pOriginalHierarchyInterface)
61976199
{
@@ -6205,7 +6207,6 @@ std::unique_ptr<CAnimBlendAssociation> CClientPed::GetAnimAssociation(CAnimBlend
62056207
pAnimAssociation = std::move(pAnimNextAssociation);
62066208
}
62076209
return nullptr;
6208-
62096210
}
62106211

62116212
CSphere CClientPed::GetWorldBoundingSphere()

Client/mods/deathmatch/logic/CClientPed.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -418,12 +418,12 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule
418418
bool IsDoingGangDriveby();
419419
void SetDoingGangDriveby(bool bDriveby);
420420

421-
bool IsRunningAnimation();
422-
void RunAnimation(AssocGroupId animGroup, AnimationId animID);
423-
void RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const char* szAnimName, int iTime = -1, int iBlend = 250, bool bLoop = true, bool bUpdatePosition = true,
424-
bool bInterruptable = false, bool bFreezeLastFrame = true, bool bRunInSequence = false, bool bOffsetPed = false,
425-
bool bHoldLastFrame = false);
426-
void KillAnimation();
421+
bool IsRunningAnimation();
422+
void RunAnimation(AssocGroupId animGroup, AnimationId animID);
423+
void RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const char* szAnimName, int iTime = -1, int iBlend = 250, bool bLoop = true,
424+
bool bUpdatePosition = true, bool bInterruptable = false, bool bFreezeLastFrame = true, bool bRunInSequence = false,
425+
bool bOffsetPed = false, bool bHoldLastFrame = false);
426+
void KillAnimation();
427427
std::unique_ptr<CAnimBlock> GetAnimationBlock();
428428
const char* GetAnimationName();
429429

@@ -541,6 +541,8 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule
541541
void _GetIntoVehicle(CClientVehicle* pVehicle, unsigned int uiSeat, unsigned char ucDoor);
542542

543543
void Respawn(CVector* pvecPosition = NULL, bool bRestoreState = false, bool bCameraCut = false);
544+
void SetCrouchToBeSetOnAnimEnd(bool bSetOnEnd) { m_bCrouchToBeSetOnAnimEnd = bSetOnEnd; }
545+
bool IsCrouchToBeSetOnAnimEnd() { return m_bCrouchToBeSetOnAnimEnd; }
544546

545547
void NotifyCreate();
546548
void NotifyDestroy();
@@ -709,4 +711,5 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule
709711

710712
// Key: Internal GTA animation, Value: Custom Animation
711713
ReplacedAnim_type m_mapOfReplacedAnimations;
714+
bool m_bCrouchToBeSetOnAnimEnd;
712715
};

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,6 +1990,7 @@ int CLuaPedDefs::SetPedAnimation(lua_State* luaVM)
19901990
bool bUpdatePosition = true;
19911991
bool bInterruptable = true;
19921992
bool bFreezeLastFrame = true;
1993+
bool bCrouchToBeSetOnAnimEnd = false;
19931994

19941995
CScriptArgReader argStream(luaVM);
19951996
argStream.ReadUserData(pEntity);
@@ -2006,13 +2007,21 @@ int CLuaPedDefs::SetPedAnimation(lua_State* luaVM)
20062007
argStream.ReadBool(bInterruptable, true);
20072008
argStream.ReadBool(bFreezeLastFrame, true);
20082009
argStream.ReadNumber(iBlend, 250);
2010+
argStream.ReadBool(bCrouchToBeSetOnAnimEnd, false);
20092011

20102012
if (!argStream.HasErrors())
20112013
{
20122014
if (CStaticFunctionDefinitions::SetPedAnimation(*pEntity, strBlockName == "" ? NULL : strBlockName.c_str(),
20132015
strAnimName == "" ? NULL : strAnimName.c_str(), iTime, iBlend, bLoop, bUpdatePosition, bInterruptable,
20142016
bFreezeLastFrame))
20152017
{
2018+
CClientPed* pPed = static_cast<CClientPed*>(pEntity);
2019+
if (!pPed->IsDucked())
2020+
{
2021+
bCrouchToBeSetOnAnimEnd = false;
2022+
}
2023+
2024+
pPed->SetCrouchToBeSetOnAnimEnd(bCrouchToBeSetOnAnimEnd);
20162025
lua_pushboolean(luaVM, true);
20172026
return 1;
20182027
}

Client/mods/deathmatch/logic/rpc/CPedRPCs.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -252,23 +252,29 @@ void CPedRPCs::SetPedAnimation(CClientEntity* pSource, NetBitStreamInterface& bi
252252
if (!blockName.empty())
253253
{
254254
std::string animName;
255-
int iTime;
256-
int iBlend = 250;
257-
bool bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame;
258-
259-
if (bitStream.ReadString<unsigned char>(animName) &&
260-
bitStream.Read(iTime) &&
261-
bitStream.ReadBit(bLoop) &&
262-
bitStream.ReadBit(bUpdatePosition) &&
263-
bitStream.ReadBit(bInterruptable) &&
264-
bitStream.ReadBit(bFreezeLastFrame))
265-
{
255+
int iTime;
256+
int iBlend = 250;
257+
bool bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame, bCrouchToBeSetOnAnimEnd;
258+
259+
if (bitStream.ReadString<unsigned char>(animName) && bitStream.Read(iTime) && bitStream.ReadBit(bLoop) && bitStream.ReadBit(bUpdatePosition) &&
260+
bitStream.ReadBit(bInterruptable) && bitStream.ReadBit(bFreezeLastFrame))
261+
{
266262
if (bitStream.Version() >= 0x065)
263+
{
267264
bitStream.Read(iBlend);
265+
bitStream.ReadBit(bCrouchToBeSetOnAnimEnd);
266+
if (!pPed->IsDucked())
267+
{
268+
bCrouchToBeSetOnAnimEnd = false;
269+
}
270+
}
268271

269272
std::unique_ptr<CAnimBlock> pBlock = g_pGame->GetAnimManager()->GetAnimationBlock(blockName.c_str());
270273
if (pBlock)
274+
{
271275
pPed->RunNamedAnimation(pBlock, animName.c_str(), iTime, iBlend, bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame);
276+
pPed->SetCrouchToBeSetOnAnimEnd(bCrouchToBeSetOnAnimEnd);
277+
}
272278
}
273279
}
274280
else
@@ -283,7 +289,7 @@ void CPedRPCs::SetPedAnimationProgress(CClientEntity* pSource, NetBitStreamInter
283289
{
284290
// Read out the player and vehicle id
285291
std::string animName;
286-
float fProgress;
292+
float fProgress;
287293

288294
if (bitStream.ReadString<unsigned char>(animName))
289295
{
@@ -313,7 +319,7 @@ void CPedRPCs::SetPedAnimationProgress(CClientEntity* pSource, NetBitStreamInter
313319
void CPedRPCs::SetPedAnimationSpeed(CClientEntity* pSource, NetBitStreamInterface& bitStream)
314320
{
315321
std::string animName;
316-
float fSpeed;
322+
float fSpeed;
317323

318324
if (bitStream.ReadString<unsigned char>(animName))
319325
{

Client/multiplayer_sa/CMultiplayerSA.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class CMultiplayerSA : public CMultiplayer
130130
void SetGamePlayerDestructHandler(GamePlayerDestructHandler* pHandler);
131131
void SetGameProjectileDestructHandler(GameProjectileDestructHandler* pHandler);
132132
void SetGameModelRemoveHandler(GameModelRemoveHandler* pHandler);
133+
void SetGameRunNamedAnimDestructorHandler(GameRunNamedAnimDestructorHandler* pHandler);
133134
void SetGameEntityRenderHandler(GameEntityRenderHandler* pHandler);
134135
void SetFxSystemDestructionHandler(FxSystemDestructionHandler* pHandler);
135136
void SetDrivebyAnimationHandler(DrivebyAnimationHandler* pHandler);

0 commit comments

Comments
 (0)