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 );
		}
	}
}
void CNPC_CombineDropship::SpawnTroops( void )
{
	int				i;
//	char			szAttachmentName[ 32 ];
	Vector			vecLocation;
	QAngle			vecAngles;
	QAngle			vecSpawnAngles;

//	memset( szAttachmentName, 0, 32 );

	vecSpawnAngles = GetLocalAngles();
	vecSpawnAngles.y = UTIL_AngleMod( vecSpawnAngles.y - 180 );
	vecSpawnAngles.x = 0;
	vecSpawnAngles.z = 0;

	for( i = 1 ; i <= m_soldiersToDrop ; i++ )
	{

//		Q_snprintf( szAttachmentName,sizeof(szAttachmentName), "spot%d", i );
//		GetAttachment( szAttachmentName, vecLocation, vecAngles );

		vecLocation = GetAbsOrigin();
		vecAngles = GetAbsAngles();

		// troops spawn behind vehicle at all times
		Vector shipDir, shipLeft;
		AngleVectors( vecAngles, &shipDir, &shipLeft, NULL );
		vecLocation -= shipDir * 250;

		// set spawn position for spawning in formation
		switch( i )
		{
		case 1:
			vecLocation -= shipLeft * DROPSHIP_TROOP_GRID;
			break;
		case 3:
			vecLocation += shipLeft * DROPSHIP_TROOP_GRID;
			break;
		case 4:
			vecLocation -= shipDir * DROPSHIP_TROOP_GRID - shipLeft * DROPSHIP_TROOP_GRID;
			break;
		case 5:
			vecLocation -= shipDir * DROPSHIP_TROOP_GRID;
			break;
		case 6:
			vecLocation -= shipDir * DROPSHIP_TROOP_GRID + shipLeft * DROPSHIP_TROOP_GRID;
		}

		// spawn based upon template
		CAI_BaseNPC	*pEnt = NULL;
		CBaseEntity *pEntity = NULL;
		MapEntity_ParseEntity( pEntity, STRING(m_sNPCTemplateData), NULL );
		if ( pEntity != NULL )
		{
			pEnt = (CAI_BaseNPC *)pEntity;
		}
		else
		{
			Warning("Dropship could not create template NPC\n" );
			return;
		}

		pEnt->SetLocalOrigin( vecLocation );
		pEnt->SetLocalAngles( vecSpawnAngles );
		DispatchSpawn( pEnt );

		pEnt->m_NPCState = NPC_STATE_IDLE;
		pEnt->SetOwnerEntity( this );
		pEnt->Activate();
	}
}