bool CClientDFF::ReplaceVehicleModel ( RpClump* pClump, ushort usModel, bool bAlphaTransparency )
{
    // Make sure previous model+collision is loaded
    m_pManager->GetModelRequestManager ()->RequestBlocking ( usModel, "CClientDFF::ReplaceVehicleModel" );

    // Grab the model info for that model and replace the model
    CModelInfo* pModelInfo = g_pGame->GetModelInfo ( usModel );
    pModelInfo->SetCustomModel ( pClump );

    pModelInfo->SetAlphaTransparencyEnabled( bAlphaTransparency );

    // Remember that we've replaced that vehicle model
    m_Replaced.push_back ( usModel );

    // Stream out all the vehicle models with matching ID.
    // Streamer will stream them back in async after a frame
    // or so.
    m_pManager->GetVehicleManager ()->RestreamVehicles ( usModel );

    // Success
    return true;
}
Beispiel #2
0
void DumpPlayer ( CClientPlayer* pPlayer, CFile *file )
{
    unsigned int uiIndex = 0;

    // Player
    file->Printf( "%s\n", "*** START OF PLAYER ***" );

    // Write the data
    file->Printf( "Nick: %s\n", pPlayer->GetNick () );
    
    CVector vecTemp;
    pPlayer->GetPosition ( vecTemp );
    file->Printf( "Position: %f %f %f\n", vecTemp.fX, vecTemp.fY, vecTemp.fZ );

    file->Printf( "Nametag text: %s\n", pPlayer->GetNametagText () );

    unsigned char ucR, ucG, ucB;
    pPlayer->GetNametagColor ( ucR, ucG, ucB );
    file->Printf( "Nametag color: %u %u %u\n", ucR, ucG, ucB );

    file->Printf( "Nametag show: %u\n", pPlayer->IsNametagShowing () );

    file->Printf( "Local player: %u\n", pPlayer->IsLocalPlayer () );
    file->Printf( "Dead: %u\n", pPlayer->IsDead () );

    file->Printf( "Exp aim: %u\n", pPlayer->IsExtrapolatingAim () );
    file->Printf( "Latency: %u\n", pPlayer->GetLatency () );

    file->Printf( "Last psync time: %u\n", pPlayer->GetLastPuresyncTime () );
    file->Printf( "Has con trouble: %u\n\n", pPlayer->HasConnectionTrouble () );

    CClientTeam* pTeam = pPlayer->GetTeam ();
    if ( pTeam )
        file->Printf( "Team: %s\n", pTeam->GetTeamName () );

    // Get the matrix
    RwMatrix matPlayer;
    pPlayer->GetMatrix ( matPlayer );

    file->Printf( "Matrix: vecRoll: %f %f %f\n", matPlayer.vRight.fX, matPlayer.vRight.fY, matPlayer.vRight.fZ );
    file->Printf( "        vecDir:  %f %f %f\n", matPlayer.vFront.fX, matPlayer.vFront.fY, matPlayer.vFront.fZ );
    file->Printf( "        vecWas:  %f %f %f\n", matPlayer.vUp.fX, matPlayer.vUp.fY, matPlayer.vUp.fZ );
    file->Printf( "        vecPos:  %f %f %f\n\n", matPlayer.vPos.fX, matPlayer.vPos.fY, matPlayer.vPos.fZ );

    file->Printf( "Euler rot: %f\n", pPlayer->GetCurrentRotation () );
    file->Printf( "Cam rot: %f\n", pPlayer->GetCameraRotation () );

    pPlayer->GetMoveSpeed ( vecTemp );
    file->Printf( "Move speed: %f %f %f\n", vecTemp.fX, vecTemp.fY, vecTemp.fZ );

    pPlayer->GetTurnSpeed ( vecTemp );
    file->Printf( "Turn speed: %f %f %f\n", vecTemp.fX, vecTemp.fY, vecTemp.fZ );

    CControllerState State;
    pPlayer->GetControllerState ( State );

    signed short* pController = reinterpret_cast < signed short* > ( &State );
    file->Printf( "CContr state: \n" );
    for ( uiIndex = 0; uiIndex < 36; uiIndex++ )
    {
        file->Printf( "State [%u] = %i\n", uiIndex, pController [uiIndex] );
    }

    pPlayer->GetLastControllerState ( State );

    pController = reinterpret_cast < signed short* > ( &State );
    file->Printf( "LContr state: \n" );
    for ( uiIndex = 0; uiIndex < 36; uiIndex++ )
    {
        file->Printf( "State [%u] = %i\n", uiIndex, pController [uiIndex] );
    }

    file->Printf( "\nVeh IO state: %i\n", pPlayer->GetVehicleInOutState () );
    file->Printf( "Visible: %u\n", pPlayer->IsVisible () );
    file->Printf( "Health: %f\n", pPlayer->GetHealth () );
    file->Printf( "Armor: %f\n", pPlayer->GetArmor () );
    file->Printf( "On screen: %u\n", pPlayer->IsOnScreen () );
    file->Printf( "Frozen: %u\n", pPlayer->IsFrozen () );
    file->Printf( "Respawn state: %i\n", pPlayer->GetRespawnState () );

    file->Printf( "Cur weapon slot: %i\n", static_cast < int > ( pPlayer->GetCurrentWeaponSlot () ) );
    file->Printf( "Cur weapon type: %i\n", static_cast < int > ( pPlayer->GetCurrentWeaponType () ) );

    CWeapon* pWeapon = pPlayer->GetWeapon ();
    if ( pWeapon )
    {
        file->Printf( "Cur weapon state: %i\n", static_cast < int > ( pWeapon->GetState () ) );
        file->Printf( "Cur weapon ammo clip: %u\n", pWeapon->GetAmmoInClip () );
        file->Printf( "Cur weapon ammo total: %u\n", pWeapon->GetAmmoTotal () );
    }

    CTaskManager* pTaskMgr = pPlayer->GetTaskManager ();
    if ( pTaskMgr )
    {
        // Primary task
        CTask* pTask = pTaskMgr->GetTask ( TASK_PRIORITY_PRIMARY );
        if ( pTask )
        {
            file->Printf( "Primary task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Primary task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Primary task: none\n" );

        // Physical response task
        pTask = pTaskMgr->GetTask ( TASK_PRIORITY_PHYSICAL_RESPONSE );
        if ( pTask )
        {
            file->Printf( "Physical response task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Physical response task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Physical response task: none\n" );

        // Event response task temp
        pTask = pTaskMgr->GetTask ( TASK_PRIORITY_EVENT_RESPONSE_TEMP );
        if ( pTask )
        {
            file->Printf( "Event rsp tmp task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Event rsp tmp task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Event rsp tmp task: none\n" );

        // Event response task nontemp
        pTask = pTaskMgr->GetTask ( TASK_PRIORITY_EVENT_RESPONSE_NONTEMP );
        if ( pTask )
        {
            file->Printf( "Event rsp nontmp task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Event rsp nontmp task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Event rsp nontmp task: none\n" );

        // Event response task nontemp
        pTask = pTaskMgr->GetTask ( TASK_PRIORITY_DEFAULT );
        if ( pTask )
        {
            file->Printf( "Default task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Default task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Default task: none\n" );

        // Secondary attack
        pTask = pTaskMgr->GetTaskSecondary ( TASK_SECONDARY_ATTACK );
        if ( pTask )
        {
            file->Printf( "Secondary attack task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Secondary attack task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Secondary attack task task: none\n" );

        // Secondary duck
        pTask = pTaskMgr->GetTaskSecondary ( TASK_SECONDARY_DUCK );
        if ( pTask )
        {
            file->Printf( "Secondary duck task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Secondary duck task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Secondary duck task task: none\n" );

        // Secondary say
        pTask = pTaskMgr->GetTaskSecondary ( TASK_SECONDARY_SAY );
        if ( pTask )
        {
            file->Printf( "Secondary say task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Secondary say task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Secondary say task task: none\n" );

        // Secondary facial complex
        pTask = pTaskMgr->GetTaskSecondary ( TASK_SECONDARY_FACIAL_COMPLEX );
        if ( pTask )
        {
            file->Printf( "Secondary facial task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Secondary facial task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Secondary facial task task: none\n" );

        // Secondary partial anim
        pTask = pTaskMgr->GetTaskSecondary ( TASK_SECONDARY_PARTIAL_ANIM );
        if ( pTask )
        {
            file->Printf( "Secondary partial anim task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Secondary partial anim task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Secondary partial anim task task: none\n" );

        // Secondary IK
        pTask = pTaskMgr->GetTaskSecondary ( TASK_SECONDARY_IK );
        if ( pTask )
        {
            file->Printf( "Secondary IK task name: %s\n", pTask->GetTaskName () );
            file->Printf( "Secondary IK task type: %i\n", pTask->GetTaskType () );
        }
        else
            file->Printf( "Secondary IK task task: none\n" );
    }

    float fX, fY;
    pPlayer->GetAim ( fX, fY );
    file->Printf( "Aim: %f %f\n", fX, fY );

    vecTemp = pPlayer->GetAimSource ();
    file->Printf( "Aim source: %f %f %f\n", vecTemp.fX, vecTemp.fY, vecTemp.fZ );

    vecTemp = pPlayer->GetAimTarget ();
    file->Printf( "Aim target: %f %f %f\n", vecTemp.fX, vecTemp.fY, vecTemp.fZ );

    file->Printf( "Veh aim anim: %u\n", pPlayer->GetVehicleAimAnim () );
    file->Printf( "Ducked: %u\n", pPlayer->IsDucked () );
    file->Printf( "Wearing googles: %u\n", pPlayer->IsWearingGoggles () );
    file->Printf( "Has jetpack: %u\n", pPlayer->HasJetPack () );
    file->Printf( "In water: %u\n", pPlayer->IsInWater () );
    file->Printf( "On ground: %u\n", pPlayer->IsOnGround () );
    file->Printf( "Is climbing: %u\n", pPlayer->IsClimbing () );
    file->Printf( "Interiour: %u\n", pPlayer->GetInterior () );
    file->Printf( "Fight style: %u\n", static_cast < int > ( pPlayer->GetFightingStyle () ) );
    file->Printf( "Satchel count: %u\n", pPlayer->CountProjectiles ( WEAPONTYPE_REMOTE_SATCHEL_CHARGE ) );

    CRemoteDataStorage* pRemote = pPlayer->GetRemoteData ();
    if ( pRemote )
    {
        vecTemp = pRemote->GetAkimboTarget ();
        file->Printf( "Akimbo target: %f %f %f\n", vecTemp.fX, vecTemp.fY, vecTemp.fZ );
        file->Printf( "Akimbo aim up: %u\n", pRemote->GetAkimboTargetUp () );
    }
    else
        file->Printf( "Remote: no\n" );

    file->Printf( "Using gun: %u\n", pPlayer->IsUsingGun () );
    file->Printf( "Entering veh: %u\n", pPlayer->IsEnteringVehicle () );
    file->Printf( "Getting jacked: %u\n", pPlayer->IsGettingJacked () );
    file->Printf( "Alpha: %u\n", pPlayer->GetAlpha () );
    

    file->Printf( "Stats:\n" );

    for ( uiIndex = 0; uiIndex < NUM_PLAYER_STATS; uiIndex++ )
    {
        file->Printf( "Stat [%u] = %f\n", uiIndex, pPlayer->GetStat ( uiIndex ) );
    }

    file->Printf( "Streamed in: %u\n", pPlayer->IsStreamedIn () );


    file->Printf( "Model: %u\n", pPlayer->GetModel () );

    // Write model data
    CModelInfo* pInfo = g_pGame->GetModelInfo ( pPlayer->GetModel () );
    file->Printf( "Model ref count: %i\n", pInfo->GetRefCount () );
    file->Printf( "Model loaded: %u\n", pInfo->IsLoaded () );
    file->Printf( "Model valid: %u\n", pInfo->IsValid () );

    // End of player
    file->Printf( "%s", "\n*** END OF PLAYER ***\n\n\n\n" );
}
Beispiel #3
0
bool CClientModelRequestManager::Request ( unsigned short usModelID, CClientEntity* pRequester )
{
    assert ( pRequester );
    SClientModelRequest* pEntry;

    // Grab the model info for that model
    CModelInfo* pInfo = g_pGame->GetModelInfo ( usModelID );
    if ( pInfo )
    {
        // Has it already requested something?
        list < SClientModelRequest* > ::iterator iter;
        if ( GetRequestEntry ( pRequester, iter ) )
        {
            // Get the entry
            pEntry = *iter;

            // The same model?
            if ( pInfo == pEntry->pModel )
            {
                // He has to wait more for it
                return false;
            }
            else
            {
                // Remove the reference to the old model
                pEntry->pModel->RemoveRef ();

                // Is it loaded?
                if ( pInfo->IsLoaded () )
                {
                    // Delete it, remove the it from the list and return true.
                    delete pEntry;
                    m_Requests.erase ( iter );

                    pInfo->MakeCustomModel ();
                    return true;
                }
                else
                {
                    // If not loaded. Replace the model we're going to load.
                    // Also remember that we requested it now.
                    pEntry->pModel = pInfo;
                    pEntry->dwTimeRequested = timeGetTime ();

                    // Start loading the new model.
                    pInfo->AddRef ( false );

                    // He has to wait for it.
                    return false;
                }
            }
        }
        else
        {
            // Already loaded? Don't bother adding to the list.
            if ( pInfo->IsLoaded () )
            {
                pInfo->MakeCustomModel ();

                return true;
            }

            // Boost loading priority if the object is close to the local player
            bool bHighPriority = false;
            if ( pRequester->GetDistanceBetweenBoundingSpheres ( g_pClientGame->GetLocalPlayer () ) < 20 )
                bHighPriority = true;

            // Request it
            pInfo->AddRef ( false, bHighPriority );

            // Add him to the list over models we're waiting for.
            pEntry = new SClientModelRequest;
            pEntry->pModel = pInfo;
            pEntry->pEntity = pRequester;
            pEntry->dwTimeRequested = timeGetTime ();
            m_Requests.push_back ( pEntry );

            // Return false. Caller needs to wait.
            return false;
        }
    }

    // Error, model is bad. Caller should not do this.
    return false;
}
eClientVehicleType CClientVehicleManager::GetVehicleType ( unsigned long ulModel )
{
    // Valid vehicle id?
    if ( IsValidModel ( ulModel ) )
    {
        // Grab the model info for the current vehicle
        CModelInfo* pModelInfo = g_pGame->GetModelInfo ( ulModel );
        if ( pModelInfo )
        {
            // Return the appropriate type
            if ( pModelInfo->IsCar () ) return CLIENTVEHICLE_CAR;
            if ( pModelInfo->IsBike () ) return CLIENTVEHICLE_BIKE;
            if ( pModelInfo->IsPlane () ) return CLIENTVEHICLE_PLANE;
            if ( pModelInfo->IsHeli () ) return CLIENTVEHICLE_HELI;
            if ( pModelInfo->IsBoat () ) return CLIENTVEHICLE_BOAT;
            if ( pModelInfo->IsQuadBike () ) return CLIENTVEHICLE_QUADBIKE;
            if ( pModelInfo->IsBmx () ) return CLIENTVEHICLE_BMX;
            if ( pModelInfo->IsMonsterTruck () ) return CLIENTVEHICLE_MONSTERTRUCK;
            if ( pModelInfo->IsTrailer () ) return CLIENTVEHICLE_TRAILER;
            if ( pModelInfo->IsTrain () ) return CLIENTVEHICLE_TRAIN;
        }
    }

    // Invalid vehicle id or some other error
    return CLIENTVEHICLE_NONE;
}
Beispiel #5
0
void CHandlingRPCs::SetVehicleHandlingProperty ( CClientEntity* pSource, NetBitStreamInterface& bitStream )
{
    // Read out the property id
    unsigned char ucProperty;
    if ( bitStream.Read ( ucProperty ) )
    {
        // Check its type
        if ( pSource && pSource->GetType () == CCLIENTVEHICLE )
        {
            // Grab the vehicle handling entry
            CClientVehicle& vehicle = static_cast < CClientVehicle& > ( *pSource );
            CHandlingEntry* pHandlingEntry = vehicle.GetHandlingData ( );
            CModelInfo * pModelInfo = vehicle.GetModelInfo ( );

            bool bReadSuspension = false;
            if ( pModelInfo )
                bReadSuspension = pModelInfo->IsCar ( ) || pModelInfo->IsMonsterTruck ( );

            // Temporary storage for reading out data
            union
            {
                unsigned char ucChar;
                unsigned int uiInt;
                float fFloat;
            };

            // Depending on what property
            switch ( ucProperty )
            {
                case HANDLING_MASS:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetMass ( fFloat );
                    break;
                    
                case HANDLING_TURNMASS:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetTurnMass ( fFloat );
                    break;

                case HANDLING_DRAGCOEFF:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetDragCoeff ( fFloat );
                    break;

                case HANDLING_CENTEROFMASS:
                {
                    CVector vecVector;
                    bitStream.Read ( vecVector.fX );
                    bitStream.Read ( vecVector.fY );
                    bitStream.Read ( vecVector.fZ );
                    pHandlingEntry->SetCenterOfMass ( vecVector );
                    break;
                }

                case HANDLING_PERCENTSUBMERGED:
                    bitStream.Read ( uiInt );
                    pHandlingEntry->SetPercentSubmerged ( uiInt );
                    break;

                case HANDLING_TRACTIONMULTIPLIER:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetTractionMultiplier ( fFloat );
                    break;

                case HANDLING_DRIVETYPE:
                {
                    bitStream.Read ( ucChar );
                    if ( ucChar != CHandlingEntry::FOURWHEEL &&
                         ucChar != CHandlingEntry::RWD &&
                         ucChar != CHandlingEntry::FWD )
                    {
                        ucChar = CHandlingEntry::RWD;
                    }

                    pHandlingEntry->SetCarDriveType ( static_cast < CHandlingEntry::eDriveType > ( ucChar ) );
                    break;
                }

                case HANDLING_ENGINETYPE:
                {
                    bitStream.Read ( ucChar );
                    if ( ucChar != CHandlingEntry::DIESEL &&
                         ucChar != CHandlingEntry::ELECTRIC &&
                         ucChar != CHandlingEntry::PETROL )
                    {
                        ucChar = CHandlingEntry::PETROL;
                    }

                    pHandlingEntry->SetCarEngineType ( static_cast < CHandlingEntry::eEngineType > ( ucChar ) );
                    break;
                }

                case HANDLING_NUMOFGEARS:
                    bitStream.Read ( ucChar );
                    pHandlingEntry->SetNumberOfGears ( ucChar );
                    break;

                case HANDLING_ENGINEACCELERATION:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetEngineAcceleration ( fFloat );
                    break;

                case HANDLING_ENGINEINERTIA:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetEngineInertia ( fFloat );
                    break;

                case HANDLING_MAXVELOCITY:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetMaxVelocity ( fFloat );
                    break;

                case HANDLING_BRAKEDECELERATION:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetBrakeDeceleration ( fFloat );
                    break;

                case HANDLING_BRAKEBIAS:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetBrakeBias ( fFloat );
                    break;

                case HANDLING_ABS:
                    bitStream.Read ( ucChar );
                    pHandlingEntry->SetABS ( ucChar != 0 );
                    break;

                case HANDLING_STEERINGLOCK:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetSteeringLock ( fFloat );
                    break;

                case HANDLING_TRACTIONLOSS:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetTractionLoss ( fFloat );
                    break;

                case HANDLING_TRACTIONBIAS:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetTractionBias ( fFloat );
                    break;

                case HANDLING_SUSPENSION_FORCELEVEL:
                {

                    bitStream.Read ( fFloat );
                    if ( bReadSuspension )
                    {
                        pHandlingEntry->SetSuspensionForceLevel ( fFloat );
                    }
                    break;
                }

                case HANDLING_SUSPENSION_DAMPING:
                {
                    bitStream.Read ( fFloat );
                    if ( bReadSuspension )
                    {
                        pHandlingEntry->SetSuspensionDamping ( fFloat );
                    }
                    break;
                }

                case HANDLING_SUSPENSION_HIGHSPEEDDAMPING:
                {
                    bitStream.Read ( fFloat );
                    if ( bReadSuspension )
                    {
                        pHandlingEntry->SetSuspensionHighSpeedDamping ( fFloat );
                    }
                    break;
                }

                case HANDLING_SUSPENSION_UPPER_LIMIT:
                {
                    bitStream.Read ( fFloat );
                    if ( bReadSuspension )
                    {
                        pHandlingEntry->SetSuspensionUpperLimit ( fFloat );
                    }
                    break;
                }

                case HANDLING_SUSPENSION_LOWER_LIMIT:
                {
                    bitStream.Read ( fFloat );
                    if ( bReadSuspension )
                    {
                        pHandlingEntry->SetSuspensionLowerLimit ( fFloat );
                    }
                    break;
                }

                case HANDLING_SUSPENSION_FRONTREARBIAS:
                {
                    bitStream.Read ( fFloat );
                    if ( bReadSuspension )
                    {
                        pHandlingEntry->SetSuspensionFrontRearBias ( fFloat );
                    }
                    break;
                }

                case HANDLING_SUSPENSION_ANTIDIVEMULTIPLIER:
                {
                    bitStream.Read ( fFloat );
                    if ( bReadSuspension )
                    {
                        pHandlingEntry->SetSuspensionAntiDiveMultiplier ( fFloat );
                    }
                    break;
                }

                case HANDLING_COLLISIONDAMAGEMULTIPLIER:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetCollisionDamageMultiplier ( fFloat );
                    break;

                case HANDLING_SEATOFFSETDISTANCE:
                    bitStream.Read ( fFloat );
                    pHandlingEntry->SetSeatOffsetDistance ( fFloat );
                    break;

                /*case HANDLING_MONETARY:
                    bitStream.Read ( uiInt );
                    pHandlingEntry->SetMonetary ( uiInt );
                    break;*/

                case HANDLING_HANDLINGFLAGS:
                    bitStream.Read ( uiInt );
                    pHandlingEntry->SetHandlingFlags ( uiInt );
                    break;

                case HANDLING_MODELFLAGS:
                    bitStream.Read ( uiInt );
                    pHandlingEntry->SetModelFlags ( uiInt );
                    break;

                /*case HANDLING_HEADLIGHT:
                    bitStream.Read ( ucChar );
                    if ( ucChar > CHandlingEntry::TALL )
                        ucChar = CHandlingEntry::TALL;

                    pHandlingEntry->SetHeadLight ( static_cast < CHandlingEntry::eLightType > ( ucChar ) );
                    break;

                case HANDLING_TAILLIGHT:
                    bitStream.Read ( ucChar );
                    if ( ucChar > CHandlingEntry::TALL ) 
                        ucChar = CHandlingEntry::TALL;

                    pHandlingEntry->SetTailLight ( static_cast < CHandlingEntry::eLightType > ( ucChar ) );
                    break;*/

                case HANDLING_ANIMGROUP:
                    bitStream.Read ( ucChar );
                    //pHandlingEntry->SetAnimGroup ( ucChar );
                    break;
            }

            vehicle.ApplyHandling();
        }
    }
}
bool CClientModelRequestManager::Request ( unsigned short usModelID, CClientEntity* pRequester )
{
    assert ( pRequester );
    SClientModelRequest* pEntry;

    // Grab the model info for that model
    CModelInfo* pInfo = g_pGame->GetModelInfo ( usModelID );
    if ( pInfo )
    {
        // Has it already requested something?
        list < SClientModelRequest* > ::iterator iter;
        if ( GetRequestEntry ( pRequester, iter ) )
        {
            // Get the entry
            pEntry = *iter;

            // The same model?
            if ( pInfo == pEntry->pModel )
            {
                // He has to wait more for it
                return false;
            }
            else
            {
                // Remove the reference to the old model
                pEntry->pModel->RemoveRef ();

                // Is it loaded?
                if ( pInfo->IsLoaded () )
                {
                    // Delete it, remove the it from the list and return true.
                    delete pEntry;
                    m_Requests.erase ( iter );

                    pInfo->MakeCustomModel ();
                    return true;
                }
                else
                {
                    // If not loaded. Replace the model we're going to load.
                    // Also remember that we requested it now.
                    pEntry->pModel = pInfo;
                    pEntry->requestTimer.Reset ();

                    // Start loading the new model.
                    pInfo->ModelAddRef ( NON_BLOCKING, "CClientModelRequestManager::Request" );

                    // He has to wait for it.
                    return false;
                }
            }
        }
        else
        {
            // Already loaded? Don't bother adding to the list.
            if ( pInfo->IsLoaded () )
            {
                pInfo->MakeCustomModel ();

                return true;
            }

            // Request it
            pInfo->ModelAddRef ( NON_BLOCKING, "CClientModelRequestManager::Request #2" );

            // Add him to the list over models we're waiting for.
            pEntry = new SClientModelRequest;
            pEntry->pModel = pInfo;
            pEntry->pEntity = pRequester;
            pEntry->requestTimer.SetMaxIncrement ( 500 );
            pEntry->requestTimer.Reset ();
            m_Requests.push_back ( pEntry );

            // Return false. Caller needs to wait.
            return false;
        }
    }

    // Error, model is bad. Caller should not do this.
    return false;
}
///////////////////////////////////////////////////////////////
//
// CModelCacheManagerImpl::SubModelRefCount
//
///////////////////////////////////////////////////////////////
void CModelCacheManagerImpl::SubModelRefCount ( ushort usModelId )
{
    CModelInfo* pModelInfo = m_pGame->GetModelInfo ( usModelId );
    if ( pModelInfo )
        pModelInfo->RemoveRef ();
}
///////////////////////////////////////////////////////////////
//
// CModelCacheManagerImpl::AddModelRefCount
//
///////////////////////////////////////////////////////////////
void CModelCacheManagerImpl::AddModelRefCount ( ushort usModelId )
{
    CModelInfo* pModelInfo = m_pGame->GetModelInfo ( usModelId );
    if ( pModelInfo )
        pModelInfo->ModelAddRef ( NON_BLOCKING, "cache" );
}