diff --git a/game/client/c_baseanimating.cpp b/game/client/c_baseanimating.cpp index 7e59a15b09..3fdde72c92 100644 --- a/game/client/c_baseanimating.cpp +++ b/game/client/c_baseanimating.cpp @@ -3012,8 +3012,18 @@ C_BaseAnimating* C_BaseAnimating::FindFollowedEntity() void C_BaseAnimating::InvalidateBoneCache() { - m_iMostRecentModelBoneCounter = g_iModelBoneCounter - 1; - m_flLastBoneSetupTime = -FLT_MAX; + m_iMostRecentModelBoneCounter = 0xFFFFFFFF; + m_flLastBoneSetupTime = -FLT_MAX; + + if ( m_pBoneMergeCache ) + { + delete m_pBoneMergeCache; + m_pBoneMergeCache = NULL; + // recreated in BuildTransformations + } + + Studio_DestroyBoneCache( m_hitboxBoneCacheHandle ); + m_hitboxBoneCacheHandle = 0; } diff --git a/game/client/c_baseanimating.h b/game/client/c_baseanimating.h index 0e60fc3082..3871b2b4bd 100644 --- a/game/client/c_baseanimating.h +++ b/game/client/c_baseanimating.h @@ -535,7 +535,7 @@ protected: float m_flFadeScale; bool m_bClientSideAnimation; -private: +protected: float m_flGroundSpeed; // computed linear movement rate for current sequence float m_flLastEventCheck; // cycle index of when events were last checked diff --git a/game/client/cstrike/c_cs_player.cpp b/game/client/cstrike/c_cs_player.cpp index 44dc1836e5..2a7ce79742 100644 --- a/game/client/cstrike/c_cs_player.cpp +++ b/game/client/cstrike/c_cs_player.cpp @@ -10,6 +10,7 @@ #include "c_user_message_register.h" #include "cdll_client_int.h" #include "convar.h" +#include "datacache/imdlcache.h" #include "dt_recv.h" #include "iconvar.h" #include "interpolatedvar.h" @@ -737,7 +738,7 @@ C_CSPlayer::C_CSPlayer() : m_angRenderAngles.Init(); AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR ); - AddVar( &m_angRenderAngles, &m_iv_angRenderAngles, LATCH_SIMULATION_VAR ); + // AddVar( &m_angRenderAngles, &m_iv_angRenderAngles, LATCH_SIMULATION_VAR ); m_iLastAddonBits = m_iAddonBits = 0; m_iLastPrimaryAddon = m_iLastSecondaryAddon = WEAPON_NONE; @@ -2131,8 +2132,11 @@ void C_CSPlayer::FireGameEvent( IGameEvent* event ) bool shouldShowFireBulletHitboxes = cl_showfirebullethitboxes.GetInt() == 1 || cl_showfirebullethitboxes.GetInt() == 3; + // TODO_ENHANCED: compare from client's prediction values ! const auto ShowEventHitboxes = [&]( float flDuration ) { + MDLCACHE_CRITICAL_SECTION(); + const int index = event->GetInt( "userid" ); if ( index == GetUserID() && IsLocalPlayer() ) { @@ -2173,26 +2177,27 @@ void C_CSPlayer::FireGameEvent( IGameEvent* event ) float flBackupBoneControllers[MAXSTUDIOBONECTRLS]; C_AnimationLayer backupAnimLayers[C_BaseAnimatingOverlay::MAX_OVERLAYS]; Vector vecBackupPosition = player->GetAbsOrigin(); - QAngle angBackupAngles = player->m_angRenderAngles; + QAngle angBackupAngles = player->GetRenderAngles(); auto flOldCycle = GetCycle(); auto iOldSequence = GetSequence(); - auto pStudioHdr = GetModelPtr(); + for ( int i = 0; i < MAXSTUDIOPOSEPARAM; i++ ) + { + flBackupPoseParams[i] = player->m_flPoseParameter[i]; + } - player->GetPoseParameters( pStudioHdr, flBackupPoseParams ); - player->GetBoneControllers( flBackupBoneControllers ); + for ( int i = 0; i < MAXSTUDIOBONECTRLS; i++ ) + { + flBackupBoneControllers[i] = player->m_flEncodedController[i]; + } for ( int i = 0; i < GetNumAnimOverlays(); i++ ) { - backupAnimLayers[i] = m_AnimOverlay[i]; + backupAnimLayers[i] = *player->GetAnimOverlay(i); } player->SetSequence( event->GetInt( "sequence" ) ); player->SetCycle( event->GetFloat( "cycle" ) ); - - // printf("was sequence: %i, cycle: %f\n", player->GetSequence(), player->GetCycle() ); - - // Set setup bones modifiers player->SetAbsOrigin( Vector( event->GetFloat( "position_x" ), event->GetFloat( "position_y" ), event->GetFloat( "position_z" ) ) ); @@ -2209,9 +2214,7 @@ void C_CSPlayer::FireGameEvent( IGameEvent* event ) char buffer[256]; V_sprintf_safe( buffer, "pose_param_%i", i ); - player->SetPoseParameter( i, event->GetFloat( buffer ) ); - - // printf("pose_param_%i: %f\n", i, player->GetPoseParameter(i) ); + player->m_flPoseParameter[i] = event->GetFloat( buffer ); } const auto numbonecontrollers = event->GetInt( "num_bonecontrollers" ); @@ -2222,11 +2225,7 @@ void C_CSPlayer::FireGameEvent( IGameEvent* event ) char buffer[256]; V_sprintf_safe( buffer, "bone_controller_%i", i ); - player->SetBoneController( i, event->GetFloat( buffer ) ); - - float tmp[MAXSTUDIOBONECTRLS]; - player->GetBoneControllers( tmp ); - // printf( "bone_controller_%i: %f\n", i, tmp[i] ); + player->m_flEncodedController[i] = event->GetFloat( buffer ); } auto numanimoverlays = event->GetInt( "num_anim_overlays" ); @@ -2239,32 +2238,27 @@ void C_CSPlayer::FireGameEvent( IGameEvent* event ) char buffer[256]; V_sprintf_safe( buffer, "anim_overlay_cycle_%i", i ); animOverlay->m_flCycle = event->GetFloat( buffer ); - // printf( "anim_overlay_cycle_%i: %f\n", i, animOverlay->m_flCycle.GetRaw() ); V_sprintf_safe( buffer, "anim_overlay_sequence_%i", i ); animOverlay->m_nSequence = event->GetInt( buffer ); - // printf( "anim_overlay_sequence_%i: %i\n", i, animOverlay->m_nSequence.GetRaw() ); V_sprintf_safe( buffer, "anim_overlay_weight_%i", i ); animOverlay->m_flWeight = event->GetFloat( buffer ); - // printf( "anim_overlay_weight_%i: %f\n", i,animOverlay->m_flWeight.GetRaw() ); V_sprintf_safe( buffer, "anim_overlay_order_%i", i ); animOverlay->m_nOrder = event->GetInt( buffer ); - // printf( "anim_overlay_order_%i: %i\n", i, animOverlay->m_nOrder ); + + V_sprintf_safe( buffer, "anim_overlay_flags_%i", i ); + animOverlay->m_fFlags = event->GetInt( buffer ); } - PushAllowBoneAccess( true, false, "Lag compensation context" ); + player->PushAllowBoneAccess( true, false, "Lag compensation context" ); + // Be sure we setup the bones again. player->InvalidateBoneCache(); - player->SetupBones( NULL, - MAXSTUDIOBONES, - BONE_USED_BY_HITBOX | BONE_USED_BY_ATTACHMENT | BONE_USED_BY_BONE_MERGE, - gpGlobals->curtime ); + player->SetupBones( NULL, -1, BONE_USED_BY_ANYTHING, gpGlobals->curtime ); player->DrawClientHitboxes( cl_debug_duration.GetFloat(), false ); - // Re-invalidate bone cache for the next frame - player->InvalidateBoneCache(); - PopBoneAccess( "Lag compensation context" ); + player->PopBoneAccess( "Lag compensation context" ); // Set back original stuff. player->SetSequence( iOldSequence ); @@ -2272,25 +2266,25 @@ void C_CSPlayer::FireGameEvent( IGameEvent* event ) player->SetAbsOrigin( vecBackupPosition ); player->m_angRenderAngles = angBackupAngles; - for ( int i = 0; i < numposeparams; i++ ) + for ( int i = 0; i < MAXSTUDIOPOSEPARAM; i++ ) { - player->SetPoseParameter( i, flBackupPoseParams[i] ); + player->m_flPoseParameter[i] = flBackupPoseParams[i]; } - for ( int i = 0; i < numbonecontrollers; i++ ) + for ( int i = 0; i < MAXSTUDIOBONECTRLS; i++ ) { - player->SetBoneController( i, flBackupBoneControllers[i] ); + player->m_flEncodedController[i] = flBackupBoneControllers[i]; } for ( int i = 0; i < numanimoverlays; i++ ) { auto animOverlay = player->GetAnimOverlay( i ); - - animOverlay->m_flCycle = backupAnimLayers[i].m_flCycle; - animOverlay->m_nSequence = backupAnimLayers[i].m_nSequence; - animOverlay->m_flWeight = backupAnimLayers[i].m_flWeight; - animOverlay->m_nOrder = backupAnimLayers[i].m_nOrder; + *animOverlay = backupAnimLayers[i]; } + + player->PushAllowBoneAccess( true, false, "Lag compensation context" ); + player->InvalidateBoneCache(); + player->PopBoneAccess( "Lag compensation context" ); } } }; diff --git a/game/client/in_main.cpp b/game/client/in_main.cpp index d4f8fa8f18..59830feb5c 100644 --- a/game/client/in_main.cpp +++ b/game/client/in_main.cpp @@ -1319,9 +1319,9 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo continue; } - cmd->simulationdata[pEntity->index].lerp_time = pEntity->m_flInterpolatedSimulationTime; - cmd->simulationdata[pEntity->index].animated_sim_time = pEntity->m_flAnimTime; - cmd->simulationdata[pEntity->index].entityexists = true; + cmd->simulationdata[pEntity->index].sim_time = pEntity->m_flInterpolatedSimulationTime; + cmd->simulationdata[pEntity->index].anim_time = pEntity->m_flAnimTime; + cmd->simulationdata[pEntity->index].entityexists = true; } #ifdef CSTRIKE_DLL diff --git a/game/server/baseanimating.cpp b/game/server/baseanimating.cpp index ff609238dd..5dc8be5b76 100644 --- a/game/server/baseanimating.cpp +++ b/game/server/baseanimating.cpp @@ -1615,6 +1615,10 @@ public: } }; +//----------------------------------------------------------------------------- +// Purpose: update latched IK contacts if they're in a moving reference frame. +//----------------------------------------------------------------------------- + void CBaseAnimating::UpdateIKLocks( float currentTime ) { if (!m_pIk) @@ -1643,9 +1647,7 @@ void CBaseAnimating::UpdateIKLocks( float currentTime ) } //----------------------------------------------------------------------------- -// Purpose: Find IK collisions with world -// Input : -// Output : fills out m_pIk targets, calcs floor offset for rendering +// Purpose: Find the ground or external attachment points needed by IK rules //----------------------------------------------------------------------------- void CBaseAnimating::CalculateIKLocks( float currentTime ) @@ -1668,7 +1670,7 @@ void CBaseAnimating::CalculateIKLocks( float currentTime ) // FIXME: trace based on gravity or trace based on angles? Vector up; - AngleVectors( GetAbsAngles(), NULL, NULL, &up ); + AngleVectors( GetRenderAngles(), NULL, NULL, &up ); // FIXME: check number of slots? float minHeight = FLT_MAX; @@ -1690,7 +1692,7 @@ void CBaseAnimating::CalculateIKLocks( float currentTime ) Vector p1, p2; // adjust ground to original ground position - estGround = (pTarget->est.pos - GetAbsOrigin()); + estGround = (pTarget->est.pos - GetRenderOrigin()); estGround = estGround - (estGround * up) * up; estGround = GetAbsOrigin() + estGround + pTarget->est.floor * up; @@ -1779,7 +1781,7 @@ void CBaseAnimating::CalculateIKLocks( float currentTime ) else if (trace.DidHitNonWorldEntity()) { pTarget->SetPos( trace.endpos ); - pTarget->SetAngles( GetAbsAngles() ); + pTarget->SetAngles( GetRenderAngles() ); // only do this on forward tracking or commited IK ground rules if (pTarget->est.release < 0.1) @@ -1813,7 +1815,7 @@ void CBaseAnimating::CalculateIKLocks( float currentTime ) else { pTarget->SetPos( trace.endpos ); - pTarget->SetAngles( GetAbsAngles() ); + pTarget->SetAngles( GetRenderAngles() ); pTarget->SetOnWorld( true ); } } @@ -1872,7 +1874,7 @@ void CBaseAnimating::CalculateIKLocks( float currentTime ) } } -#if defined( HL2_DLL ) +#if defined( HL2_CLIENT_DLL ) if (minHeight < FLT_MAX) { input->AddIKGroundContactInfo( entindex(), minHeight, maxHeight ); @@ -2854,6 +2856,7 @@ CBoneCache *CBaseAnimating::GetBoneCache( void ) void CBaseAnimating::InvalidateBoneCache( void ) { Studio_InvalidateBoneCache( m_boneCacheHandle ); + m_boneCacheHandle = 0; } bool CBaseAnimating::TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) diff --git a/game/server/player_lagcompensation.cpp b/game/server/player_lagcompensation.cpp index 9b11b49d36..fecdb30727 100644 --- a/game/server/player_lagcompensation.cpp +++ b/game/server/player_lagcompensation.cpp @@ -39,7 +39,8 @@ #define MAX_TICKS_SAVED 1000 ConVar sv_unlag( "sv_unlag", "1", FCVAR_DEVELOPMENTONLY, "Enables player lag compensation" ); -ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "0", 0, "Flushes entity bone cache on lag compensation" ); +// Enable by default to avoid some bugs. +ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "1", 0, "Flushes entity bone cache on lag compensation" ); //----------------------------------------------------------------------------- // Purpose: @@ -420,8 +421,8 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c int pl_index = pPlayer->entindex(); - float flTargetLerpSimTime = cmd->simulationdata[pl_index].lerp_time; - float flTargetAnimatedSimulationTime = cmd->simulationdata[pl_index].animated_sim_time; + float flTargetSimTime = cmd->simulationdata[pl_index].sim_time; + float flTargetAnimTime = cmd->simulationdata[pl_index].anim_time; // get track history of this player auto track = &m_EntityTrack[pl_index]; @@ -440,12 +441,12 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c break; } - if ( flTargetLerpSimTime == recordSim->m_flSimulationTime ) + if ( flTargetSimTime == recordSim->m_flSimulationTime ) { break; } - if ( recordSim->m_flSimulationTime < flTargetLerpSimTime ) + if ( recordSim->m_flSimulationTime < flTargetSimTime ) { prevRecordSim = track->Get( i - 1 ); break; @@ -461,7 +462,7 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c break; } - if ( recordAnim->m_flAnimTime == flTargetAnimatedSimulationTime ) + if ( recordAnim->m_flAnimTime == flTargetAnimTime ) { break; } @@ -481,7 +482,7 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c } float fracSim = 0.0f; - if ( prevRecordSim && ( recordSim->m_flSimulationTime < flTargetLerpSimTime ) + if ( prevRecordSim && ( recordSim->m_flSimulationTime < flTargetSimTime ) && ( recordSim->m_flSimulationTime < prevRecordSim->m_flSimulationTime ) ) { // we didn't find the exact time but have a valid previous record @@ -491,7 +492,7 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c Assert( flTargetLerpSimTime < prevRecordSim->m_flSimulationTime ); // calc fraction between both records - fracSim = float( ( double( flTargetLerpSimTime ) - double( recordSim->m_flSimulationTime ) ) + fracSim = float( ( double( flTargetSimTime ) - double( recordSim->m_flSimulationTime ) ) / ( double( prevRecordSim->m_flSimulationTime ) - double( recordSim->m_flSimulationTime ) ) ); Assert( fracSim > 0 && fracSim < 1 ); // should never extrapolate @@ -500,12 +501,6 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c org = Lerp( fracSim, recordSim->m_vecOrigin, prevRecordSim->m_vecOrigin ); minsPreScaled = Lerp( fracSim, recordSim->m_vecMinsPreScaled, prevRecordSim->m_vecMinsPreScaled ); maxsPreScaled = Lerp( fracSim, recordSim->m_vecMaxsPreScaled, prevRecordSim->m_vecMaxsPreScaled ); -#ifdef CSTRIKE_DLL - if ( csPlayer ) - { - renderAngles = Lerp( fracSim, recordSim->m_angRenderAngles, prevRecordSim->m_angRenderAngles ); - } -#endif } else { @@ -515,9 +510,6 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c ang = recordSim->m_vecAngles; minsPreScaled = recordSim->m_vecMinsPreScaled; maxsPreScaled = recordSim->m_vecMaxsPreScaled; -#ifdef CSTRIKE_DLL - renderAngles = recordSim->m_angRenderAngles; -#endif } // See if this represents a change for the player @@ -535,6 +527,7 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c #ifdef CSTRIKE_DLL if ( csPlayer ) { + renderAngles = recordAnim->m_angRenderAngles; restore->m_angRenderAngles = csPlayer->m_angRenderAngles; csPlayer->m_angRenderAngles = renderAngles; } @@ -638,8 +631,8 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c } // Set lag compensated player's times - pPlayer->SetSimulationTime( flTargetLerpSimTime ); - // pPlayer->SetAnimTime(animationData->m_flAnimTime); + pPlayer->SetSimulationTime( flTargetSimTime ); + pPlayer->SetAnimTime( flTargetAnimTime ); if ( sv_lagflushbonecache.GetBool() ) { diff --git a/game/shared/cstrike/cs_player_shared.cpp b/game/shared/cstrike/cs_player_shared.cpp index 88fce9954b..95b9309b7b 100644 --- a/game/shared/cstrike/cs_player_shared.cpp +++ b/game/shared/cstrike/cs_player_shared.cpp @@ -618,6 +618,9 @@ void CCSPlayer::FireBullet( V_sprintf_safe( buffer, "anim_overlay_order_%i", i ); event->SetInt( buffer, animOverlay->m_nOrder.Get() ); + + V_sprintf_safe( buffer, "anim_overlay_flags_%i", i ); + event->SetInt( buffer, animOverlay->m_fFlags.Get() ); } gameeventmanager->FireEvent( event ); diff --git a/game/shared/cstrike/cs_playeranimstate.cpp b/game/shared/cstrike/cs_playeranimstate.cpp index 19c3a1840c..ce19b5cd47 100644 --- a/game/shared/cstrike/cs_playeranimstate.cpp +++ b/game/shared/cstrike/cs_playeranimstate.cpp @@ -613,40 +613,48 @@ int CCSPlayerAnimState::CalcReloadLayerSequence( PlayerAnimEvent_t event ) return -1; } - void CCSPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd ) +void CCSPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr* pStudioHdr, + int iLayer, + bool& bEnabled, + float& flCurCycle, + int& iSequence, + bool bWaitAtEnd ) { if ( !bEnabled || iSequence < 0 ) + { return; + } - // Increment the fire sequence's cycle. - flCurCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, iSequence ) * gpGlobals->frametime; - if ( flCurCycle > 1 ) + // Increment the fire sequence's cycle. + flCurCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, iSequence ) * gpGlobals->frametime; + + if ( flCurCycle > 1 ) + { + if ( bWaitAtEnd ) { - if ( bWaitAtEnd ) - { - flCurCycle = 1; - } - else - { - // Not firing anymore. - bEnabled = false; - iSequence = 0; - return; - } + flCurCycle = 1; } + else + { + // Not firing anymore. + bEnabled = false; + iSequence = 0; + + CAnimationLayer* pLayer = m_pOuter->GetAnimOverlay( iLayer ); + pLayer->m_fFlags = 0; + return; + } + } // Now dump the state into its animation layer. - CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer ); + CAnimationLayer* pLayer = m_pOuter->GetAnimOverlay( iLayer ); - pLayer->m_flCycle = flCurCycle; - pLayer->m_nSequence = iSequence; - - pLayer->m_flPlaybackRate = 1.0f; - pLayer->m_flWeight = 1.0f; - pLayer->m_nOrder = iLayer; -#ifndef CLIENT_DLL - pLayer->m_fFlags |= ANIM_LAYER_ACTIVE; -#endif + pLayer->m_flCycle = flCurCycle; + pLayer->m_nSequence = iSequence; + pLayer->m_flPlaybackRate = 1.0f; + pLayer->m_flWeight = 1.0f; + pLayer->m_nOrder = iLayer; + pLayer->m_fFlags |= ANIM_LAYER_ACTIVE; } bool CCSPlayerAnimState::IsOuterGrenadePrimed() diff --git a/game/shared/usercmd.cpp b/game/shared/usercmd.cpp index e35d109b91..bd376f8ade 100644 --- a/game/shared/usercmd.cpp +++ b/game/shared/usercmd.cpp @@ -162,20 +162,20 @@ void WriteUsercmd( bf_write *buf, const CUserCmd *to, const CUserCmd *from ) // Write finally simulation data with entity index for ( unsigned int i = 0; i <= highestEntityIndex; i++ ) { - if ( from->simulationdata[i].lerp_time != to->simulationdata[i].lerp_time ) + if ( from->simulationdata[i].sim_time != to->simulationdata[i].sim_time ) { buf->WriteOneBit( 1 ); - buf->WriteBitFloat( to->simulationdata[i].lerp_time ); + buf->WriteBitFloat( to->simulationdata[i].sim_time ); } else { buf->WriteOneBit( 0 ); } - if ( from->simulationdata[i].animated_sim_time != to->simulationdata[i].animated_sim_time ) + if ( from->simulationdata[i].anim_time != to->simulationdata[i].anim_time ) { buf->WriteOneBit( 1 ); - buf->WriteBitFloat( to->simulationdata[i].animated_sim_time ); + buf->WriteBitFloat( to->simulationdata[i].anim_time ); } else { @@ -309,12 +309,12 @@ void ReadUsercmd( bf_read *buf, CUserCmd *move, CUserCmd *from ) { if (buf->ReadOneBit()) { - move->simulationdata[i].lerp_time = buf->ReadBitFloat(); + move->simulationdata[i].sim_time = buf->ReadBitFloat(); } if (buf->ReadOneBit()) { - move->simulationdata[i].animated_sim_time = buf->ReadBitFloat(); + move->simulationdata[i].anim_time = buf->ReadBitFloat(); } } diff --git a/game/shared/usercmd.h b/game/shared/usercmd.h index ccda00a0b0..145186249a 100644 --- a/game/shared/usercmd.h +++ b/game/shared/usercmd.h @@ -41,8 +41,8 @@ struct SimulationData // TODO_ENHANCED: // For now we send the last received update for animations. // anim time is unreliable on low fps. - float lerp_time; - float animated_sim_time; + float sim_time; + float anim_time; bool entityexists; };