///////////////////////////////////////////////////////////////
//
// CClientModelCacheManagerImpl::DoPulse
//
///////////////////////////////////////////////////////////////
void CClientModelCacheManagerImpl::DoPulse(void)
{
    m_TickCountNow = CTickCount::Now();
    ClearStats();

    if (!g_pClientGame->GetLocalPlayer())
        return;

    m_fGameFps = g_pGame->GetFPS();

    // Assess which models will be needed in the next 2 seconds

    // Update frame time
    int iDeltaTimeMs = Clamp(10, (m_TickCountNow - m_LastTimeMs).ToInt(), 100);
    m_LastTimeMs = m_TickCountNow;

    // Get camera position
    CVector        vecOldCameraPos = m_vecCameraPos;
    CClientCamera* pCamera = g_pClientGame->GetManager()->GetCamera();
    if (pCamera->IsInFixedMode())
        pCamera->GetPosition(m_vecCameraPos);
    else
        g_pClientGame->GetLocalPlayer()->GetPosition(m_vecCameraPos);

    // Calculate camera velocity
    CVector vecDif = m_vecCameraPos - vecOldCameraPos;
    float   fCameraSpeed = vecDif.Length() / (iDeltaTimeMs * 0.001f);
    float   a = m_fSmoothCameraSpeed;
    m_fSmoothCameraSpeed = Lerp(m_fSmoothCameraSpeed, 0.25f, fCameraSpeed);

    // Spread updating over 4 frames
    m_iFrameCounter = (m_iFrameCounter + 1) % 4;

    if (m_iFrameCounter == 1)
        DoPulsePedModels();
    else if (m_iFrameCounter == 3)
        DoPulseVehicleModels();

    // Handle regeneration of possibly replaced clothes textures
    if (g_pGame->GetRenderWare()->HasClothesReplacementChanged())
    {
        g_pMultiplayer->FlushClothesCache();

        CClientPlayerManager* pPlayerManager = g_pClientGame->GetPlayerManager();
        for (std::vector<CClientPlayer*>::const_iterator iter = pPlayerManager->IterBegin(); iter != pPlayerManager->IterEnd(); ++iter)
            (*iter)->RebuildModel(false);

        CClientPedManager* pPedManager = g_pClientGame->GetPedManager();
        for (std::vector<CClientPed*>::const_iterator iter = pPedManager->IterBegin(); iter != pPedManager->IterEnd(); ++iter)
            (*iter)->RebuildModel(false);
    }
}
void CClientSoundManager::DoPulse ( void )
{
    UpdateVolume ();

    CClientCamera* pCamera = m_pClientManager->GetCamera();

    CVector vecCameraPosition, vecPosition, vecLookAt, vecFront, vecVelocity;
    pCamera->GetPosition ( vecCameraPosition );
    pCamera->GetFixedTarget ( vecLookAt );
    vecFront = vecLookAt - vecCameraPosition;

    CClientPlayer* p_LocalPlayer = m_pClientManager->GetPlayerManager()->GetLocalPlayer();
    if ( p_LocalPlayer )
    {
        p_LocalPlayer->GetMoveSpeed( vecVelocity );

        if ( pCamera->IsInFixedMode() )
            vecPosition = vecCameraPosition;
        else
            p_LocalPlayer->GetPosition( vecPosition );

    }
    else
    {
        // Make sure the players position at least has something (I'd be surprised if we get here though)
        vecPosition = vecCameraPosition;
    }

    // Update volume position and velocity from all sounds
    list < CClientSound* > ::iterator iter = m_Sounds.begin ();
    for ( ; iter != m_Sounds.end () ; ++iter )
    {
        CClientSound* pSound = *iter;
        pSound->Process3D ( vecPosition, vecCameraPosition, vecLookAt );

        // Delete sound if finished
        if ( pSound->IsFinished () )
        {
            // call onClientSoundStopped
            CLuaArguments Arguments;
            Arguments.PushString ( "finished" );     // Reason
            pSound->CallEvent ( "onClientSoundStopped", Arguments, false );
            g_pClientGame->GetElementDeleter()->Delete ( pSound );
        }
    }
    UpdateDistanceStreaming ( vecPosition );
}