Skip to content

Commit 8f3415c

Browse files
Synchronize changes from 1.6 master branch [ci skip]
1e24eac Restore "Fix anim progress & speed (PR #4245)"
2 parents 8631e05 + 1e24eac commit 8f3415c

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
@@ -2893,6 +2893,11 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses)
28932893
}
28942894
}
28952895

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

3686-
// Are we still playing animation?
3687-
if ((m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame || m_AnimationCache.progressWaitForStreamIn) && m_pAnimationBlock)
3691+
// Are we still playing a animation?
3692+
if (m_pAnimationBlock && IsAnimationInProgress())
36883693
{
36893694
if (m_bisCurrentAnimationCustom)
36903695
{
@@ -3961,8 +3966,8 @@ void CClientPed::_ChangeModel()
39613966
}
39623967
m_bDontChangeRadio = false;
39633968

3964-
// Are we still playing a looped animation?
3965-
if ((m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame || m_AnimationCache.progressWaitForStreamIn) && m_pAnimationBlock)
3969+
// Are we still playing a animation?
3970+
if (m_pAnimationBlock && IsAnimationInProgress())
39663971
{
39673972
if (m_bisCurrentAnimationCustom)
39683973
{
@@ -5729,7 +5734,23 @@ bool CClientPed::IsRunningAnimation()
57295734
}
57305735
return false;
57315736
}
5732-
return (m_AnimationCache.bLoop && m_pAnimationBlock);
5737+
return (m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame) && m_pAnimationBlock;
5738+
}
5739+
5740+
bool CClientPed::IsAnimationInProgress()
5741+
{
5742+
bool constAnim = m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame;
5743+
5744+
if (!m_pAnimationBlock)
5745+
return constAnim;
5746+
5747+
float elapsedTime = static_cast<float>(GetTimestamp() - m_AnimationCache.startTime) / 1000.0f;
5748+
5749+
auto animBlendHierarchy = g_pGame->GetAnimManager()->GetAnimation(m_AnimationCache.strName.c_str(), m_pAnimationBlock);
5750+
if (!animBlendHierarchy)
5751+
return constAnim;
5752+
5753+
return constAnim || elapsedTime < animBlendHierarchy->GetTotalTime();
57335754
}
57345755

57355756
void CClientPed::RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const char* szAnimName, int iTime, int iBlend, bool bLoop, bool bUpdatePosition,
@@ -5817,10 +5838,6 @@ void CClientPed::RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const ch
58175838
m_AnimationCache.bUpdatePosition = bUpdatePosition;
58185839
m_AnimationCache.bInterruptable = bInterruptable;
58195840
m_AnimationCache.bFreezeLastFrame = bFreezeLastFrame;
5820-
m_AnimationCache.progress = 0.0f;
5821-
m_AnimationCache.speed = 1.0f;
5822-
m_AnimationCache.progressWaitForStreamIn = false;
5823-
m_AnimationCache.elapsedTime = 0.0f;
58245841
}
58255842

58265843
void CClientPed::KillAnimation()
@@ -5859,39 +5876,45 @@ void CClientPed::RunAnimationFromCache()
58595876
if (!m_pAnimationBlock)
58605877
return;
58615878

5862-
bool needCalcProgress = m_AnimationCache.progressWaitForStreamIn;
5863-
float elapsedTime = m_AnimationCache.elapsedTime;
5864-
58655879
// Copy our name incase it gets deleted
58665880
std::string animName = m_AnimationCache.strName;
58675881

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

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

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

5881-
if (m_AnimationCache.bFreezeLastFrame) // time and loop is ignored if freezeLastFrame is true
5882-
progress = (elapsedTime / animLength) * m_AnimationCache.speed;
5903+
if (m_AnimationCache.bFreezeLastFrame) // time and loop is ignored if freezeLastFrame is true
5904+
progress = (elapsedTime / animLength) * m_AnimationCache.speed;
5905+
else
5906+
{
5907+
if (m_AnimationCache.bLoop)
5908+
progress = std::fmod(elapsedTime * m_AnimationCache.speed, animLength) / animLength;
58835909
else
5884-
{
5885-
if (m_AnimationCache.bLoop)
5886-
progress = std::fmod(elapsedTime * m_AnimationCache.speed, animLength) / animLength;
5887-
else
5888-
// For non-looped animations, limit duration to animLength if time exceeds it
5889-
progress = (elapsedTime / (m_AnimationCache.iTime <= animLength ? m_AnimationCache.iTime : animLength)) * m_AnimationCache.speed;
5890-
}
5910+
// For non-looped animations, limit duration to animLength if time exceeds it
5911+
progress = (elapsedTime / (m_AnimationCache.iTime <= animLength ? m_AnimationCache.iTime : animLength)) * m_AnimationCache.speed;
58915912
}
58925913

58935914
animAssoc->SetCurrentProgress(std::clamp(progress, 0.0f, 1.0f));
58945915
animAssoc->SetCurrentSpeed(m_AnimationCache.speed);
5916+
5917+
m_AnimationCache.progressWaitForStreamIn = false;
58955918
}
58965919

58975920
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
@@ -3929,7 +3929,8 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream)
39293929
std::string blockName, animName;
39303930
int time, blendTime;
39313931
bool looped, updatePosition, interruptable, freezeLastFrame, taskRestore;
3932-
float elapsedTime, speed;
3932+
float speed;
3933+
double startTime;
39333934

39343935
// Read data
39353936
bitStream.ReadString(blockName);
@@ -3941,15 +3942,14 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream)
39413942
bitStream.ReadBit(freezeLastFrame);
39423943
bitStream.Read(blendTime);
39433944
bitStream.ReadBit(taskRestore);
3944-
bitStream.Read(elapsedTime);
3945+
bitStream.Read(startTime);
39453946
bitStream.Read(speed);
39463947

39473948
// Run anim
39483949
CStaticFunctionDefinitions::SetPedAnimation(*pPed, blockName, animName.c_str(), time, blendTime, looped, updatePosition, interruptable, freezeLastFrame);
3949-
pPed->m_AnimationCache.progressWaitForStreamIn = true;
3950-
pPed->m_AnimationCache.elapsedTime = elapsedTime;
3951-
3952-
CStaticFunctionDefinitions::SetPedAnimationSpeed(*pPed, animName, speed);
3950+
pPed->m_AnimationCache.startTime = static_cast<std::int64_t>(startTime);
3951+
pPed->m_AnimationCache.speed = speed;
3952+
pPed->m_AnimationCache.progress = 0.0f;
39533953

39543954
pPed->SetHasSyncedAnim(true);
39553955
}

Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,8 @@ bool CStaticFunctionDefinitions::SetPedAnimation(CClientEntity& Entity, const SS
22762276
}
22772277
}
22782278
}
2279+
2280+
Ped.m_AnimationCache.startTime = GetTimestamp();
22792281
}
22802282
else
22812283
{

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,12 @@ void CPedRPCs::SetPedAnimation(CClientEntity* pSource, NetBitStreamInterface& bi
273273
pPed->RunNamedAnimation(pBlock, animName.c_str(), iTime, iBlend, bLoop, bUpdatePosition, bInterruptable, bFreezeLastFrame);
274274
pPed->SetTaskToBeRestoredOnAnimEnd(bTaskToBeRestoredOnAnimEnd);
275275
pPed->SetTaskTypeToBeRestoredOnAnimEnd((eTaskType)TASK_SIMPLE_DUCK);
276+
277+
pPed->m_AnimationCache.startTime = GetTimestamp();
278+
pPed->m_AnimationCache.speed = 1.0f;
279+
pPed->m_AnimationCache.progress = 0.0f;
280+
281+
pPed->SetHasSyncedAnim(true);
276282
}
277283
}
278284
}
@@ -304,6 +310,7 @@ void CPedRPCs::SetPedAnimationProgress(CClientEntity* pSource, NetBitStreamInter
304310
if (pAnimAssociation)
305311
{
306312
pAnimAssociation->SetCurrentProgress(fProgress);
313+
pPed->m_AnimationCache.progress = fProgress;
307314
}
308315
}
309316
}
@@ -331,6 +338,7 @@ void CPedRPCs::SetPedAnimationSpeed(CClientEntity* pSource, NetBitStreamInterfac
331338
if (pAnimAssociation)
332339
{
333340
pAnimAssociation->SetCurrentSpeed(fSpeed);
341+
pPed->m_AnimationCache.speed = fSpeed;
334342
}
335343
}
336344
}

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
@@ -973,9 +973,8 @@ bool CEntityAddPacket::Write(NetBitStreamInterface& BitStream) const
973973
BitStream.Write(animData.blendTime);
974974
BitStream.WriteBit(animData.taskToBeRestoredOnAnimEnd);
975975

976-
// Write elapsed time & speed
977-
float elapsedTime = GetTickCount64_() - animData.startedTick;
978-
BitStream.Write(elapsedTime);
976+
// Write start time & speed
977+
BitStream.Write(static_cast<double>(animData.startTime));
979978
BitStream.Write(animData.speed);
980979
}
981980

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)