//----------------------------------------------------------------------------- // Purpose: Called once per frame after all entities have had a chance to think //----------------------------------------------------------------------------- void CLagCompensationManager::FrameUpdatePostEntityThink() { if ( m_bNeedsAIUpdate ) UpdateAIIndexes(); // only bother if we haven't had one yet else // setting this true here ensures that the update happens at the start of the next frame m_bNeedsAIUpdate = true; if ( (gpGlobals->maxClients <= 1) || !sv_unlag.GetBool() ) { ClearHistory(); return; } m_flTeleportDistanceSqr = sv_lagcompensation_teleport_dist.GetFloat() * sv_lagcompensation_teleport_dist.GetFloat(); VPROF_BUDGET( "FrameUpdatePostEntityThink", "CLagCompensationManager" ); // remove all records before that time: int flDeadtime = gpGlobals->curtime - sv_maxunlag.GetFloat(); // Iterate all active players for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); CUtlFixedLinkedList< LagRecord > *track = &m_PlayerTrack[i-1]; if ( !pPlayer ) { if ( track->Count() > 0 ) { track->RemoveAll(); } continue; } Assert( track->Count() < 1000 ); // insanity check // remove tail records that are too old int tailIndex = track->Tail(); while ( track->IsValidIndex( tailIndex ) ) { LagRecord &tail = track->Element( tailIndex ); // if tail is within limits, stop if ( tail.m_flSimulationTime >= flDeadtime ) break; // remove tail, get new tail track->Remove( tailIndex ); tailIndex = track->Tail(); } // check if head has same simulation time if ( track->Count() > 0 ) { LagRecord &head = track->Element( track->Head() ); // check if player changed simulation time since last time updated if ( head.m_flSimulationTime >= pPlayer->GetSimulationTime() ) continue; // don't add new entry for same or older time } // add new record to player track LagRecord &record = track->Element( track->AddToHead() ); record.m_fFlags = 0; if ( pPlayer->IsAlive() ) { record.m_fFlags |= LC_ALIVE; } record.m_flSimulationTime = pPlayer->GetSimulationTime(); record.m_vecAngles = pPlayer->GetLocalAngles(); record.m_vecOrigin = pPlayer->GetLocalOrigin(); record.m_vecMinsPreScaled = pPlayer->CollisionProp()->OBBMinsPreScaled(); record.m_vecMaxsPreScaled = pPlayer->CollisionProp()->OBBMaxsPreScaled(); int layerCount = pPlayer->GetNumAnimOverlays(); for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) { CAnimationLayer *currentLayer = pPlayer->GetAnimOverlay(layerIndex); if( currentLayer ) { record.m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle; record.m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder; record.m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence; record.m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight; } } record.m_masterSequence = pPlayer->GetSequence(); record.m_masterCycle = pPlayer->GetCycle(); } // Iterate all active NPCs CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); int nAIs = g_AI_Manager.NumAIs(); for ( int i = 0; i < nAIs; i++ ) { CAI_BaseNPC *pNPC = ppAIs[i]; CUtlFixedLinkedList< LagRecord > *track = &m_EntityTrack[i]; if ( !pNPC ) { track->RemoveAll(); continue; } Assert( track->Count() < 1000 ); // insanity check // remove tail records that are too old int tailIndex = track->Tail(); while ( track->IsValidIndex( tailIndex ) ) { LagRecord &tail = track->Element( tailIndex ); // if tail is within limits, stop if ( tail.m_flSimulationTime >= flDeadtime ) break; // remove tail, get new tail track->Remove( tailIndex ); tailIndex = track->Tail(); } // check if head has same simulation time if ( track->Count() > 0 ) { LagRecord &head = track->Element( track->Head() ); // check if entity changed simulation time since last time updated if ( &head && head.m_flSimulationTime >= pNPC->GetSimulationTime() ) continue; // don't add new entry for same or older time // Simulation Time is set when an entity moves or rotates ... // this error occurs when whatever entity it is that breaks it moves or rotates then, presumably? } // add new record to track LagRecord &record = track->Element( track->AddToHead() ); record.m_fFlags = 0; if ( pNPC->IsAlive() ) { record.m_fFlags |= LC_ALIVE; } record.m_flSimulationTime = pNPC->GetSimulationTime(); record.m_vecAngles = pNPC->GetLocalAngles(); record.m_vecOrigin = pNPC->GetLocalOrigin(); record.m_vecMaxs = pNPC->WorldAlignMaxs(); record.m_vecMins = pNPC->WorldAlignMins(); int layerCount = pNPC->GetNumAnimOverlays(); for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) { CAnimationLayer *currentLayer = pNPC->GetAnimOverlay(layerIndex); if( currentLayer ) { record.m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle; record.m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder; record.m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence; record.m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight; } } record.m_masterSequence = pNPC->GetSequence(); record.m_masterCycle = pNPC->GetCycle(); } //Clear the current player. m_pCurrentPlayer = NULL; }
//----------------------------------------------------------------------------- // Purpose: Called once per frame after all entities have had a chance to think //----------------------------------------------------------------------------- void CLagCompensationManager::FrameUpdatePostEntityThink() { if ( (gpGlobals->maxClients <= 1) || !sv_unlag.GetBool() ) { ClearHistory(); return; } m_flTeleportDistanceSqr = sv_lagcompensation_teleport_dist.GetFloat() * sv_lagcompensation_teleport_dist.GetFloat(); VPROF_BUDGET( "FrameUpdatePostEntityThink", "CLagCompensationManager" ); // remove all records before that time: int flDeadtime = gpGlobals->curtime - sv_maxunlag.GetFloat(); // Iterate all active players for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); CUtlFixedLinkedList< LagRecord > *track = &m_PlayerTrack[i-1]; if ( !pPlayer ) { if ( track->Count() > 0 ) { track->RemoveAll(); } continue; } Assert( track->Count() < 1000 ); // insanity check // remove tail records that are too old int tailIndex = track->Tail(); while ( track->IsValidIndex( tailIndex ) ) { LagRecord &tail = track->Element( tailIndex ); // if tail is within limits, stop if ( tail.m_flSimulationTime >= flDeadtime ) break; // remove tail, get new tail track->Remove( tailIndex ); tailIndex = track->Tail(); } // check if head has same simulation time if ( track->Count() > 0 ) { LagRecord &head = track->Element( track->Head() ); // check if player changed simulation time since last time updated if ( head.m_flSimulationTime >= pPlayer->GetSimulationTime() ) continue; // don't add new entry for same or older time } // add new record to player track LagRecord &record = track->Element( track->AddToHead() ); record.m_fFlags = 0; if ( pPlayer->IsAlive() ) { record.m_fFlags |= LC_ALIVE; } record.m_flSimulationTime = pPlayer->GetSimulationTime(); record.m_vecAngles = pPlayer->GetLocalAngles(); record.m_vecOrigin = pPlayer->GetLocalOrigin(); record.m_vecMinsPreScaled = pPlayer->CollisionProp()->OBBMinsPreScaled(); record.m_vecMaxsPreScaled = pPlayer->CollisionProp()->OBBMaxsPreScaled(); int layerCount = pPlayer->GetNumAnimOverlays(); for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) { CAnimationLayer *currentLayer = pPlayer->GetAnimOverlay(layerIndex); if( currentLayer ) { record.m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle; record.m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder; record.m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence; record.m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight; } } record.m_masterSequence = pPlayer->GetSequence(); record.m_masterCycle = pPlayer->GetCycle(); } //Clear the current player. m_pCurrentPlayer = NULL; }