void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player ) { VPROF_BUDGET_FLAGS( "FinishLagCompensation", VPROF_BUDGETGROUP_OTHER_NETWORKING, BUDGETFLAG_CLIENT|BUDGETFLAG_SERVER ); m_pCurrentPlayer = NULL; if ( !m_bNeedToRestore ) return; // no player was changed at all // Iterate all active players for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { int pl_index = i - 1; if ( !m_RestorePlayer.Get( pl_index ) ) { // player wasn't changed by lag compensation continue; } CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); if ( !pPlayer ) { continue; } LagRecord *restore = &m_RestoreData[ pl_index ]; LagRecord *change = &m_ChangeData[ pl_index ]; bool restoreSimulationTime = false; if ( restore->m_fFlags & LC_SIZE_CHANGED ) { restoreSimulationTime = true; // see if simulation made any changes, if no, then do the restore, otherwise, // leave new values in if ( pPlayer->CollisionProp()->OBBMinsPreScaled() == change->m_vecMinsPreScaled && pPlayer->CollisionProp()->OBBMaxsPreScaled() == change->m_vecMaxsPreScaled ) { // Restore it pPlayer->SetSize( restore->m_vecMinsPreScaled, restore->m_vecMaxsPreScaled ); } else { Warning( "Should we really not restore the size?\n" ); } } if ( restore->m_fFlags & LC_ANGLES_CHANGED ) { restoreSimulationTime = true; if ( pPlayer->GetLocalAngles() == change->m_vecAngles ) { pPlayer->SetLocalAngles( restore->m_vecAngles ); } } if ( restore->m_fFlags & LC_ORIGIN_CHANGED ) { restoreSimulationTime = true; // Okay, let's see if we can do something reasonable with the change Vector delta = pPlayer->GetLocalOrigin() - change->m_vecOrigin; // If it moved really far, just leave the player in the new spot!!! if ( delta.Length2DSqr() < m_flTeleportDistanceSqr ) { RestorePlayerTo( pPlayer, restore->m_vecOrigin + delta ); } } if( restore->m_fFlags & LC_ANIMATION_CHANGED ) { restoreSimulationTime = true; pPlayer->SetSequence(restore->m_masterSequence); pPlayer->SetCycle(restore->m_masterCycle); int layerCount = pPlayer->GetNumAnimOverlays(); for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) { CAnimationLayer *currentLayer = pPlayer->GetAnimOverlay(layerIndex); if( currentLayer ) { currentLayer->m_flCycle = restore->m_layerRecords[layerIndex].m_cycle; currentLayer->m_nOrder = restore->m_layerRecords[layerIndex].m_order; currentLayer->m_nSequence = restore->m_layerRecords[layerIndex].m_sequence; currentLayer->m_flWeight = restore->m_layerRecords[layerIndex].m_weight; } } } if ( restoreSimulationTime ) { pPlayer->SetSimulationTime( restore->m_flSimulationTime ); } } // also iterate all monsters 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]; if ( !m_RestoreEntity.Get( i ) ) { // entity wasn't changed by lag compensation continue; } LagRecord *restore = &m_EntityRestoreData[ i ]; LagRecord *change = &m_EntityChangeData[ i ]; bool restoreSimulationTime = false; if ( restore->m_fFlags & LC_SIZE_CHANGED ) { restoreSimulationTime = true; // see if simulation made any changes, if no, then do the restore, otherwise, // leave new values in if ( pNPC->WorldAlignMins() == change->m_vecMins && pNPC->WorldAlignMaxs() == change->m_vecMaxs ) { // Restore it pNPC->SetSize( restore->m_vecMins, restore->m_vecMaxs ); } } if ( restore->m_fFlags & LC_ANGLES_CHANGED ) { restoreSimulationTime = true; if ( pNPC->GetLocalAngles() == change->m_vecAngles ) { pNPC->SetLocalAngles( restore->m_vecAngles ); } } if ( restore->m_fFlags & LC_ORIGIN_CHANGED ) { restoreSimulationTime = true; // Okay, let's see if we can do something reasonable with the change Vector delta = pNPC->GetLocalOrigin() - change->m_vecOrigin; // If it moved really far, just leave the player in the new spot!!! if ( delta.LengthSqr() < LAG_COMPENSATION_TELEPORTED_DISTANCE_SQR ) { RestoreEntityTo( pNPC, restore->m_vecOrigin + delta ); } } if( restore->m_fFlags & LC_ANIMATION_CHANGED ) { restoreSimulationTime = true; pNPC->SetSequence(restore->m_masterSequence); pNPC->SetCycle(restore->m_masterCycle); int layerCount = pNPC->GetNumAnimOverlays(); for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) { CAnimationLayer *currentLayer = pNPC->GetAnimOverlay(layerIndex); if( currentLayer ) { currentLayer->m_flCycle = restore->m_layerRecords[layerIndex].m_cycle; currentLayer->m_nOrder = restore->m_layerRecords[layerIndex].m_order; currentLayer->m_nSequence = restore->m_layerRecords[layerIndex].m_sequence; currentLayer->m_flWeight = restore->m_layerRecords[layerIndex].m_weight; } } } if ( restoreSimulationTime ) { pNPC->SetSimulationTime( restore->m_flSimulationTime ); } } }