Skip to content

Commit 278b2b4

Browse files
Synchronize changes from 1.6 master branch [ci skip]
ad0d6bf Fix anim progress & speed (#4245)
2 parents 25dd5a5 + ad0d6bf commit 278b2b4

File tree

10 files changed

+98
-50
lines changed

10 files changed

+98
-50
lines changed

Client/mods/deathmatch/logic/CClientPed.cpp

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2895,6 +2895,11 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses)
28952895
}
28962896
}
28972897

2898+
// Are we need to update anim speed & progress?
2899+
// We need to do it here because the anim starts on the next frame after calling RunNamedAnimation
2900+
if (m_pAnimationBlock && m_AnimationCache.progressWaitForStreamIn && IsAnimationInProgress())
2901+
UpdateAnimationProgressAndSpeed();
2902+
28982903
// Update our alpha
28992904
unsigned char ucAlpha = m_ucAlpha;
29002905
// Are we in a different interior to the camera? set our alpha to 0
@@ -3685,8 +3690,8 @@ void CClientPed::_CreateModel()
36853690
Kill(WEAPONTYPE_UNARMED, 0, false, true);
36863691
}
36873692

3688-
// Are we still playing animation?
3689-
if ((m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame || m_AnimationCache.progressWaitForStreamIn) && m_pAnimationBlock)
3693+
// Are we still playing a animation?
3694+
if (m_pAnimationBlock && IsAnimationInProgress())
36903695
{
36913696
if (m_bisCurrentAnimationCustom)
36923697
{
@@ -3963,8 +3968,8 @@ void CClientPed::_ChangeModel()
39633968
}
39643969
m_bDontChangeRadio = false;
39653970

3966-
// Are we still playing a looped animation?
3967-
if ((m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame || m_AnimationCache.progressWaitForStreamIn) && m_pAnimationBlock)
3971+
// Are we still playing a animation?
3972+
if (m_pAnimationBlock && IsAnimationInProgress())
39683973
{
39693974
if (m_bisCurrentAnimationCustom)
39703975
{
@@ -5731,7 +5736,23 @@ bool CClientPed::IsRunningAnimation()
57315736
}
57325737
return false;
57335738
}
5734-
return (m_AnimationCache.bLoop && m_pAnimationBlock);
5739+
return (m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame) && m_pAnimationBlock;
5740+
}
5741+
5742+
bool CClientPed::IsAnimationInProgress()
5743+
{
5744+
bool constAnim = m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame;
5745+
5746+
if (!m_pAnimationBlock)
5747+
return constAnim;
5748+
5749+
float elapsedTime = static_cast<float>(GetTimestamp() - m_AnimationCache.startTime) / 1000.0f;
5750+
5751+
auto animBlendHierarchy = g_pGame->GetAnimManager()->GetAnimation(m_AnimationCache.strName.c_str(), m_pAnimationBlock);
5752+
if (!animBlendHierarchy)
5753+
return constAnim;
5754+
5755+
return constAnim || elapsedTime < animBlendHierarchy->GetTotalTime();
57355756
}
57365757

57375758
void CClientPed::RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const char* szAnimName, int iTime, int iBlend, bool bLoop, bool bUpdatePosition,
@@ -5819,10 +5840,6 @@ void CClientPed::RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const ch
58195840
m_AnimationCache.bUpdatePosition = bUpdatePosition;
58205841
m_AnimationCache.bInterruptable = bInterruptable;
58215842
m_AnimationCache.bFreezeLastFrame = bFreezeLastFrame;
5822-
m_AnimationCache.progress = 0.0f;
5823-
m_AnimationCache.speed = 1.0f;
5824-
m_AnimationCache.progressWaitForStreamIn = false;
5825-
m_AnimationCache.elapsedTime = 0.0f;
58265843
}
58275844

58285845
void CClientPed::KillAnimation()
@@ -5861,39 +5878,45 @@ void CClientPed::RunAnimationFromCache()
58615878
if (!m_pAnimationBlock)
58625879
return;
58635880

5864-
bool needCalcProgress = m_AnimationCache.progressWaitForStreamIn;
5865-
float elapsedTime = m_AnimationCache.elapsedTime;
5866-
58675881
// Copy our name incase it gets deleted
58685882
std::string animName = m_AnimationCache.strName;
58695883

58705884
// Run our animation
58715885
RunNamedAnimation(m_pAnimationBlock, animName.c_str(), m_AnimationCache.iTime, m_AnimationCache.iBlend, m_AnimationCache.bLoop, m_AnimationCache.bUpdatePosition, m_AnimationCache.bInterruptable, m_AnimationCache.bFreezeLastFrame);
58725886

5873-
auto animAssoc = g_pGame->GetAnimManager()->RpAnimBlendClumpGetAssociation(GetClump(), animName.c_str());
5887+
// Set anim progress & speed
5888+
m_AnimationCache.progressWaitForStreamIn = true;
5889+
}
5890+
5891+
void CClientPed::UpdateAnimationProgressAndSpeed()
5892+
{
5893+
if (!m_AnimationCache.progressWaitForStreamIn)
5894+
return;
5895+
5896+
// Get current anim
5897+
auto animAssoc = g_pGame->GetAnimManager()->RpAnimBlendClumpGetAssociation(GetClump(), m_AnimationCache.strName.c_str());
58745898
if (!animAssoc)
58755899
return;
58765900

5877-
// If the anim is synced from the server side, we need to calculate the progress
5878-
float progress = m_AnimationCache.progress;
5879-
if (needCalcProgress)
5880-
{
5881-
float animLength = animAssoc->GetLength();
5901+
float animLength = animAssoc->GetLength();
5902+
float progress = 0.0f;
5903+
float elapsedTime = static_cast<float>(GetTimestamp() - m_AnimationCache.startTime) / 1000.0f;
58825904

5883-
if (m_AnimationCache.bFreezeLastFrame) // time and loop is ignored if freezeLastFrame is true
5884-
progress = (elapsedTime / animLength) * m_AnimationCache.speed;
5905+
if (m_AnimationCache.bFreezeLastFrame) // time and loop is ignored if freezeLastFrame is true
5906+
progress = (elapsedTime / animLength) * m_AnimationCache.speed;
5907+
else
5908+
{
5909+
if (m_AnimationCache.bLoop)
5910+
progress = std::fmod(elapsedTime * m_AnimationCache.speed, animLength) / animLength;
58855911
else
5886-
{
5887-
if (m_AnimationCache.bLoop)
5888-
progress = std::fmod(elapsedTime * m_AnimationCache.speed, animLength) / animLength;
5889-
else
5890-
// For non-looped animations, limit duration to animLength if time exceeds it
5891-
progress = (elapsedTime / (m_AnimationCache.iTime <= animLength ? m_AnimationCache.iTime : animLength)) * m_AnimationCache.speed;
5892-
}
5912+
// For non-looped animations, limit duration to animLength if time exceeds it
5913+
progress = (elapsedTime / (m_AnimationCache.iTime <= animLength ? m_AnimationCache.iTime : animLength)) * m_AnimationCache.speed;
58935914
}
58945915

58955916
animAssoc->SetCurrentProgress(std::clamp(progress, 0.0f, 1.0f));
58965917
animAssoc->SetCurrentSpeed(m_AnimationCache.speed);
5918+
5919+
m_AnimationCache.progressWaitForStreamIn = false;
58975920
}
58985921

58995922
void CClientPed::PostWeaponFire()

Client/mods/deathmatch/logic/CClientPed.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,17 @@ struct SReplacedAnimation
129129

130130
struct SAnimationCache
131131
{
132-
std::string strName;
133-
int iTime{-1};
134-
bool bLoop{false};
135-
bool bUpdatePosition{false};
136-
bool bInterruptable{false};
137-
bool bFreezeLastFrame{true};
138-
int iBlend{250};
139-
float progress{0.0f};
140-
float speed{1.0f};
141-
bool progressWaitForStreamIn{false}; // for sync anim only
142-
float elapsedTime{0.0f}; // for sync anim only
132+
std::string strName;
133+
int iTime{-1};
134+
bool bLoop{false};
135+
bool bUpdatePosition{false};
136+
bool bInterruptable{false};
137+
bool bFreezeLastFrame{true};
138+
int iBlend{250};
139+
float progress{0.0f};
140+
float speed{1.0f};
141+
bool progressWaitForStreamIn{false};
142+
std::int64_t startTime{0};
143143
};
144144

145145
class CClientObject;
@@ -456,13 +456,18 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule
456456

457457
bool GetRunningAnimationName(SString& strBlockName, SString& strAnimName);
458458
bool IsRunningAnimation();
459+
460+
// It checks whether the animation is still playing based on time, not on task execution.
461+
bool IsAnimationInProgress();
462+
459463
void RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const char* szAnimName, int iTime = -1, int iBlend = 250, bool bLoop = true,
460464
bool bUpdatePosition = true, bool bInterruptable = false, bool bFreezeLastFrame = true, bool bRunInSequence = false,
461465
bool bOffsetPed = false, bool bHoldLastFrame = false);
462466
void KillAnimation();
463467
std::unique_ptr<CAnimBlock> GetAnimationBlock();
464468
const SAnimationCache& GetAnimationCache() const noexcept { return m_AnimationCache; }
465469
void RunAnimationFromCache();
470+
void UpdateAnimationProgressAndSpeed();
466471

467472
bool IsUsingGun();
468473

Client/mods/deathmatch/logic/CPacketHandler.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4010,7 +4010,8 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream)
40104010
std::string blockName, animName;
40114011
int time, blendTime;
40124012
bool looped, updatePosition, interruptable, freezeLastFrame, taskRestore;
4013-
float elapsedTime, speed;
4013+
float speed;
4014+
double startTime;
40144015

40154016
// Read data
40164017
bitStream.ReadString(blockName);
@@ -4022,15 +4023,14 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream)
40224023
bitStream.ReadBit(freezeLastFrame);
40234024
bitStream.Read(blendTime);
40244025
bitStream.ReadBit(taskRestore);
4025-
bitStream.Read(elapsedTime);
4026+
bitStream.Read(startTime);
40264027
bitStream.Read(speed);
40274028

40284029
// Run anim
40294030
CStaticFunctionDefinitions::SetPedAnimation(*pPed, blockName, animName.c_str(), time, blendTime, looped, updatePosition, interruptable, freezeLastFrame);
4030-
pPed->m_AnimationCache.progressWaitForStreamIn = true;
4031-
pPed->m_AnimationCache.elapsedTime = elapsedTime;
4032-
4033-
CStaticFunctionDefinitions::SetPedAnimationSpeed(*pPed, animName, speed);
4031+
pPed->m_AnimationCache.startTime = static_cast<std::int64_t>(startTime);
4032+
pPed->m_AnimationCache.speed = speed;
4033+
pPed->m_AnimationCache.progress = 0.0f;
40344034

40354035
pPed->SetHasSyncedAnim(true);
40364036
}

Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2247,6 +2247,8 @@ bool CStaticFunctionDefinitions::SetPedAnimation(CClientEntity& Entity, const SS
22472247
}
22482248
}
22492249
}
2250+
2251+
Ped.m_AnimationCache.startTime = GetTimestamp();
22502252
}
22512253
else
22522254
{

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,12 @@ void CPedRPCs::SetPedAnimation(CClientEntity* pSource, NetBitStreamInterface& bi
276276
pPed->RunNamedAnimation(pBlock, animName.c_str(), iTime, iBlend, bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame);
277277
pPed->SetTaskToBeRestoredOnAnimEnd(bTaskToBeRestoredOnAnimEnd);
278278
pPed->SetTaskTypeToBeRestoredOnAnimEnd((eTaskType)TASK_SIMPLE_DUCK);
279+
280+
pPed->m_AnimationCache.startTime = GetTimestamp();
281+
pPed->m_AnimationCache.speed = 1.0f;
282+
pPed->m_AnimationCache.progress = 0.0f;
283+
284+
pPed->SetHasSyncedAnim(true);
279285
}
280286
}
281287
}
@@ -307,6 +313,7 @@ void CPedRPCs::SetPedAnimationProgress(CClientEntity* pSource, NetBitStreamInter
307313
if (pAnimAssociation)
308314
{
309315
pAnimAssociation->SetCurrentProgress(fProgress);
316+
pPed->m_AnimationCache.progress = fProgress;
310317
}
311318
}
312319
}
@@ -334,6 +341,7 @@ void CPedRPCs::SetPedAnimationSpeed(CClientEntity* pSource, NetBitStreamInterfac
334341
if (pAnimAssociation)
335342
{
336343
pAnimAssociation->SetCurrentSpeed(fSpeed);
344+
pPed->m_AnimationCache.speed = fSpeed;
337345
}
338346
}
339347
}

Server/mods/deathmatch/logic/CPed.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ struct SPlayerAnimData
115115
int blendTime{250};
116116
bool taskToBeRestoredOnAnimEnd{false};
117117

118-
std::int64_t startedTick{0};
118+
std::int64_t startTime{0};
119119

120120
float progress{0.0f};
121121
float speed{1.0f};

Server/mods/deathmatch/logic/CPedSync.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ void CPedSync::OverrideSyncer(CPed* pPed, CPlayer* pPlayer, bool bPersist)
8282

8383
void CPedSync::UpdateAllSyncer()
8484
{
85-
auto currentTick = GetTickCount64_();
85+
auto currentTimestamp = GetTimestamp();
8686

8787
// Update all the ped's sync states
8888
for (auto iter = m_pPedManager->IterBegin(); iter != m_pPedManager->IterEnd(); iter++)
@@ -91,7 +91,7 @@ void CPedSync::UpdateAllSyncer()
9191
const SPlayerAnimData& animData = (*iter)->GetAnimationData();
9292
if (animData.IsAnimating())
9393
{
94-
float deltaTime = currentTick - animData.startedTick;
94+
float deltaTime = static_cast<float>(currentTimestamp - animData.startTime);
9595
if (!animData.freezeLastFrame && animData.time > 0 && deltaTime >= animData.time)
9696
(*iter)->SetAnimationData({});
9797
}

Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,9 +1005,8 @@ bool CEntityAddPacket::Write(NetBitStreamInterface& BitStream) const
10051005
BitStream.Write(animData.blendTime);
10061006
BitStream.WriteBit(animData.taskToBeRestoredOnAnimEnd);
10071007

1008-
// Write elapsed time & speed
1009-
float elapsedTime = GetTickCount64_() - animData.startedTick;
1010-
BitStream.Write(elapsedTime);
1008+
// Write start time & speed
1009+
BitStream.Write(static_cast<double>(animData.startTime));
10111010
BitStream.Write(animData.speed);
10121011
}
10131012
}

Shared/sdk/SharedUtil.Time.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ namespace SharedUtil
4141
//
4242
double GetSecondCount();
4343

44+
std::int64_t GetTimestamp();
45+
4446
//
4547
// Get the time as a sortable string.
4648
// Set bDate to include the date, bMs to include milliseconds

Shared/sdk/SharedUtil.Time.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ double SharedUtil::GetSecondCount()
8686
return GetTickCount64_() * (1 / 1000.0);
8787
}
8888

89+
//
90+
// Returns a timestamp in ms
91+
//
92+
std::int64_t SharedUtil::GetTimestamp()
93+
{
94+
auto now = std::chrono::system_clock::now();
95+
return std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
96+
}
97+
8998
//
9099
// Get the time as a sortable string.
91100
// Set bDate to include the date, bMs to include milliseconds

0 commit comments

Comments
 (0)