diff options
Diffstat (limited to '')
-rw-r--r-- | src/vehicles/Automobile.cpp | 222 | ||||
-rw-r--r-- | src/vehicles/Automobile.h | 17 | ||||
-rw-r--r-- | src/vehicles/Boat.cpp | 4 | ||||
-rw-r--r-- | src/vehicles/CarGen.cpp | 2 | ||||
-rw-r--r-- | src/vehicles/Cranes.cpp | 11 | ||||
-rw-r--r-- | src/vehicles/DamageManager.cpp | 10 | ||||
-rw-r--r-- | src/vehicles/DamageManager.h | 2 | ||||
-rw-r--r-- | src/vehicles/HandlingMgr.cpp | 2 | ||||
-rw-r--r-- | src/vehicles/HandlingMgr.h | 6 | ||||
-rw-r--r-- | src/vehicles/Heli.cpp | 6 | ||||
-rw-r--r-- | src/vehicles/Plane.cpp | 4 | ||||
-rw-r--r-- | src/vehicles/Plane.h | 7 | ||||
-rw-r--r-- | src/vehicles/Train.cpp | 51 | ||||
-rw-r--r-- | src/vehicles/Train.h | 9 | ||||
-rw-r--r-- | src/vehicles/Vehicle.cpp | 137 | ||||
-rw-r--r-- | src/vehicles/Vehicle.h | 18 |
16 files changed, 284 insertions, 224 deletions
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 83fe44d5..eb1bad97 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -67,7 +67,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id); m_fFireBlowUpTimer = 0.0f; - field_4E0 = 0; + m_auto_unk1 = 0; bTaxiLight = m_sAllTaxiLights; bFixedColour = false; bBigWheels = false; @@ -77,8 +77,8 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId); - field_49C = 20.0f; - field_4D8 = 0; + m_auto_unused1 = 20.0f; + m_auto_unused2 = 0; mi->ChooseVehicleColour(m_currentColour1, m_currentColour2); @@ -145,8 +145,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) for(i = 0; i < 4; i++){ m_aGroundPhysical[i] = nil; m_aGroundOffset[i] = CVector(0.0f, 0.0f, 0.0f); - m_aSuspensionSpringRatio[i] = 1.0f; - m_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i]; + m_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i] = 1.0f; m_aWheelTimer[i] = 0.0f; m_aWheelRotation[i] = 0.0f; m_aWheelSpeed[i] = 0.0f; @@ -175,7 +174,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) m_nNumPassengers = 0; m_bombType = CARBOMB_NONE; - bHadDriver = false; + bDriverLastFrame = false; m_pBombRigger = nil; if(m_nDoorLock == CARLOCK_UNLOCKED && @@ -221,6 +220,7 @@ void CAutomobile::ProcessControl(void) { int i; + float wheelRot; CColModel *colModel; if(bUsingSpecialColModel) @@ -236,23 +236,16 @@ CAutomobile::ProcessControl(void) // Improve grip of vehicles in certain cases bool strongGrip1 = false; bool strongGrip2 = false; - if(FindPlayerVehicle() && this != FindPlayerVehicle()){ - switch(AutoPilot.m_nCarMission){ - case MISSION_RAMPLAYER_FARAWAY: - case MISSION_RAMPLAYER_CLOSE: - case MISSION_BLOCKPLAYER_FARAWAY: - case MISSION_BLOCKPLAYER_CLOSE: - if(FindPlayerSpeed().Magnitude() > 0.3f){ - strongGrip1 = true; - if(FindPlayerSpeed().Magnitude() > 0.4f){ - if(m_vecMoveSpeed.Magnitude() < 0.3f) - strongGrip2 = true; - }else{ - if((GetPosition() - FindPlayerCoors()).Magnitude() > 50.0f) - strongGrip2 = true; - } - } - default: break; + if(FindPlayerVehicle() && this != FindPlayerVehicle() && + (AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY || AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE || + AutoPilot.m_nCarMission == MISSION_BLOCKPLAYER_FARAWAY || AutoPilot.m_nCarMission == MISSION_BLOCKPLAYER_CLOSE)){ + if(FindPlayerSpeed().Magnitude() > 0.3f){ + strongGrip1 = true; + if(FindPlayerSpeed().Magnitude() > 0.4f && + m_vecMoveSpeed.Magnitude() < 0.3f) + strongGrip2 = true; + else if((GetPosition() - FindPlayerCoors()).Magnitude() > 50.0f) + strongGrip2 = true; } } @@ -263,7 +256,7 @@ CAutomobile::ProcessControl(void) // Scan if this car sees the player committing any crimes if(GetStatus() != STATUS_ABANDONED && GetStatus() != STATUS_WRECKED && - GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && GetStatus() != STATUS_PLAYER_DISABLED){ + GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && GetStatus() != STATUS_PLAYER_DISABLED){ switch(GetModelIndex()) case MI_FBICAR: case MI_POLICE: @@ -276,7 +269,7 @@ CAutomobile::ProcessControl(void) // Process driver if(pDriver){ - if(!bHadDriver && m_bombType == CARBOMB_ONIGNITIONACTIVE){ + if(!bDriverLastFrame && m_bombType == CARBOMB_ONIGNITIONACTIVE){ // If someone enters the car and there is a bomb, detonate m_nBombTimer = 1000; m_pBlowUpEntity = m_pBombRigger; @@ -284,7 +277,7 @@ CAutomobile::ProcessControl(void) m_pBlowUpEntity->RegisterReference((CEntity**)&m_pBlowUpEntity); DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_TICK, 1.0f); } - bHadDriver = true; + bDriverLastFrame = true; if(IsUpsideDown() && CanPedEnterCar()){ if(!pDriver->IsPlayer() && @@ -293,7 +286,7 @@ CAutomobile::ProcessControl(void) pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this); } }else - bHadDriver = false; + bDriverLastFrame = false; // Process passengers if(m_nNumPassengers != 0 && IsUpsideDown() && CanPedEnterCar()){ @@ -380,11 +373,9 @@ CAutomobile::ProcessControl(void) pHandling->Transmission.CalculateGearForSimpleCar(AutoPilot.m_fMaxTrafficSpeed/50.0f, m_nCurrentGear); - { - float wheelRot = ProcessWheelRotation(WHEEL_STATE_NORMAL, GetForward(), m_vecMoveSpeed, 0.35f); + wheelRot = ProcessWheelRotation(WHEEL_STATE_NORMAL, GetForward(), m_vecMoveSpeed, 0.35f); for(i = 0; i < 4; i++) m_aWheelRotation[i] += wheelRot; - } PlayHornIfNecessary(); ReduceHornCounter(); @@ -596,7 +587,7 @@ CAutomobile::ProcessControl(void) m_aSuspensionSpringRatio[i] = (m_aSuspensionSpringRatio[i]-wheelRadius)/(1.0f-wheelRadius); } - float fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward()); + float fwdSpeed = Abs(DotProduct(m_vecMoveSpeed, GetForward())); CVector contactPoints[4]; // relative to model CVector contactSpeeds[4]; // speed at contact points CVector springDirections[4]; // normalized, in model space @@ -626,7 +617,7 @@ CAutomobile::ProcessControl(void) for(i = 0; i < 4; i++){ if(m_aSuspensionSpringRatio[i] < 1.0f){ float bias = pHandling->fSuspensionBias; - if(i == 1 || i == 3) // rear + if(i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT) bias = 1.0f - bias; ApplySpringCollision(pHandling->fSuspensionForceLevel, @@ -634,7 +625,7 @@ CAutomobile::ProcessControl(void) m_aSuspensionSpringRatio[i], bias); m_aWheelSkidmarkMuddy[i] = m_aWheelColPoints[i].surfaceB == SURFACE_GRASS || - m_aWheelColPoints[i].surfaceB == SURFACE_DIRTTRACK || + m_aWheelColPoints[i].surfaceB == SURFACE_MUD_DRY || m_aWheelColPoints[i].surfaceB == SURFACE_SAND; }else{ contactPoints[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1); @@ -689,7 +680,7 @@ CAutomobile::ProcessControl(void) float brakeBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fBrakeBias; float brakeBiasRear = neutralHandling ? 1.0f : 2.0f*(1.0f-pHandling->fBrakeBias); float tractionBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fTractionBias; - float tractionBiasRear = neutralHandling ? 1.0f : 2.0f*(1.0f-pHandling->fTractionBias); + float tractionBiasRear = neutralHandling ? 1.0f : 2.0f-tractionBiasFront; // Count how many wheels are touching the ground @@ -771,7 +762,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_LEFT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB); @@ -805,7 +796,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB); @@ -871,8 +862,14 @@ CAutomobile::ProcessControl(void) CVector wheelFwd = GetForward(); CVector wheelRight = GetRight(); +#ifdef FIX_BUGS + // Not sure if this is needed, but brake usually has timestep as a factor + if(bIsHandbrakeOn) + brake = 20000.0f * CTimer::GetTimeStepFix(); +#else if(bIsHandbrakeOn) brake = 20000.0f; +#endif if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f){ if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier)) @@ -880,7 +877,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_LEFT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB); @@ -914,7 +911,7 @@ CAutomobile::ProcessControl(void) else fThrust = acceleration; - m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceA = SURFACE_RUBBER29; + m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceA = SURFACE_WHEELBASE; float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_RIGHT])*traction; if(GetStatus() == STATUS_PLAYER) adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB); @@ -1129,10 +1126,10 @@ CAutomobile::ProcessControl(void) } uint8 surf = m_aWheelColPoints[i].surfaceB; - if(surf == SURFACE_DIRT || surf == SURFACE_PUDDLE || surf == SURFACE_HEDGE){ + if(surf == SURFACE_GRAVEL || surf == SURFACE_WATER || surf == SURFACE_HEDGE){ if(surfShake < 0.2f) surfShake = 0.3f; - }else if(surf == SURFACE_DIRTTRACK || surf == SURFACE_SAND){ + }else if(surf == SURFACE_MUD_DRY || surf == SURFACE_SAND){ if(surfShake < 0.1f) surfShake = 0.2f; }else if(surf == SURFACE_GRASS){ @@ -1154,7 +1151,7 @@ CAutomobile::ProcessControl(void) uint8 freq = Min(200.0f*suspShake*speed*2000.0f/m_fMass + 100.0f, 250.0f); CPad::GetPad(0)->StartShake(20000.0f*CTimer::GetTimeStep()/freq, freq); }else{ - uint8 freq = Min(200.0f*surfShake*speed*2000.0f/m_fMass + 40.0f, 145.0f); + uint8 freq = Min(200.0f*surfShake*speed*2000.0f/m_fMass + 40.0f, 150.0f); CPad::GetPad(0)->StartShake(5000.0f*CTimer::GetTimeStep()/freq, freq); } } @@ -1296,7 +1293,7 @@ CAutomobile::PreRender(void) int drawParticles = Abs(fwdSpeed) < 90.0f; if(GetStatus() == STATUS_SIMPLE || GetStatus() == STATUS_PHYSICS || - GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PLAYER_PLAYBACKFROMBUFFER){ + GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PLAYER_PLAYBACKFROMBUFFER){ bool rearSkidding = false; if(m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SKIDDING || m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SKIDDING) @@ -1428,7 +1425,7 @@ CAutomobile::PreRender(void) n = 6.0f*CWeather::Rain; for(j = 0; j <= n; j++) CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, - c + CVector(CGeneral::GetRandomNumberInRange(-.04f, 0.4f), CGeneral::GetRandomNumberInRange(-.04f, 0.4f), 0.0f), + c + CVector(CGeneral::GetRandomNumberInRange(-0.4f, 0.4f), CGeneral::GetRandomNumberInRange(-0.4f, 0.4f), 0.0f), CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, 0, 0, CGeneral::GetRandomNumber() & 1); } @@ -1616,11 +1613,9 @@ CAutomobile::PreRender(void) break; } - if(GetModelIndex() == MI_RCBANDIT || GetModelIndex() == MI_DODO || - GetModelIndex() == MI_RHINO) { - CShadows::StoreShadowForCar(this); - return; - } + if(GetModelIndex() != MI_RCBANDIT && GetModelIndex() != MI_DODO && + GetModelIndex() != MI_RHINO) { + // Process lights // Turn lights on/off bool shouldLightsBeOn = @@ -1867,14 +1862,9 @@ CAutomobile::PreRender(void) CPointLights::FOG_NONE, false); } } - }else{ + }else if(GetStatus() != STATUS_ABANDONED && GetStatus() != STATUS_WRECKED){ // Lights off - if(GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED) { - CShadows::StoreShadowForCar(this); - return; - } - CVector lightPos = mi->m_positions[CAR_POS_TAILLIGHTS]; CVector lightR = GetMatrix() * lightPos; CVector lightL = lightR; @@ -1931,6 +1921,8 @@ CAutomobile::PreRender(void) CCoronas::UpdateCoronaCoors((uintptr)this + 3, lightR, 50.0f*TheCamera.LODDistMultiplier, 0.0f); } } + // end of lights + } CShadows::StoreShadowForCar(this); } @@ -2247,22 +2239,22 @@ CAutomobile::ProcessControlInputs(uint8 pad) // Steer left/right if(CCamera::m_bUseMouse3rdPerson && !CVehicle::m_bDisableMouseSteering){ if(CPad::GetPad(pad)->GetMouseX() != 0.0f){ - m_fSteerRatio += fMouseSteerSens*CPad::GetPad(pad)->GetMouseX(); + m_fSteerInput += fMouseSteerSens*CPad::GetPad(pad)->GetMouseX(); nLastControlInput = 2; - if(Abs(m_fSteerRatio) < fMouseCentreRange) - m_fSteerRatio *= Pow(fMouseCentreMult, CTimer::GetTimeStep()); + if(Abs(m_fSteerInput) < fMouseCentreRange) + m_fSteerInput *= Pow(fMouseCentreMult, CTimer::GetTimeStep()); }else if(CPad::GetPad(pad)->GetSteeringLeftRight() || nLastControlInput != 2){ // mouse hasn't move, steer with pad like below - m_fSteerRatio += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerRatio)* + m_fSteerInput += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerInput)* 0.2f*CTimer::GetTimeStep(); nLastControlInput = 0; } }else{ - m_fSteerRatio += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerRatio)* + m_fSteerInput += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerInput)* 0.2f*CTimer::GetTimeStep(); nLastControlInput = 0; } - m_fSteerRatio = clamp(m_fSteerRatio, -1.0f, 1.0f); + m_fSteerInput = clamp(m_fSteerInput, -1.0f, 1.0f); // Accelerate/Brake float acceleration = (CPad::GetPad(pad)->GetAccelerate() - CPad::GetPad(pad)->GetBrake())/255.0f; @@ -2313,13 +2305,24 @@ CAutomobile::ProcessControlInputs(uint8 pad) // Actually turn wheels static float fValue; // why static? - if(m_fSteerRatio < 0.0f) - fValue = -sq(m_fSteerRatio); + if(m_fSteerInput < 0.0f) + fValue = -sq(m_fSteerInput); else - fValue = sq(m_fSteerRatio); + fValue = sq(m_fSteerInput); m_fSteerAngle = DEGTORAD(pHandling->fSteeringLock) * fValue; if(bComedyControls){ +#if 0 // old comedy controls from PS2 - same as bike's + if(((CTimer::GetTimeInMilliseconds() >> 10) & 0xF) < 12) + m_fGasPedal = 1.0f; + if((((CTimer::GetTimeInMilliseconds() >> 10)+6) & 0xF) < 12) + m_fBrakePedal = 0.0f; + bIsHandbrakeOn = false; + if(CTimer::GetTimeInMilliseconds() & 0x800) + m_fSteerAngle += 0.08f; + else + m_fSteerAngle -= 0.03f; +#else int rnd = CGeneral::GetRandomNumber() % 10; switch(m_comedyControlState){ case 0: @@ -2339,8 +2342,10 @@ CAutomobile::ProcessControlInputs(uint8 pad) m_comedyControlState = 0; break; } - }else + }else{ m_comedyControlState = 0; +#endif + } // Brake if player isn't in control // BUG: game always uses pad 0 here @@ -2501,7 +2506,7 @@ CAutomobile::TankControl(void) float f = i/15.0f; CParticle::AddParticle(PARTICLE_GUNSMOKE2, point1, shotDir*CGeneral::GetRandomNumberInRange(0.3f, 1.0f)*f, - nil, CGeneral::GetRandomNumberInRange(0.5f, 1.0f)*f, black); + nil, CGeneral::GetRandomNumberInRange(0.5f, 1.5f)*f, black); } // And some gun flashes near the gun @@ -2533,6 +2538,9 @@ CAutomobile::TankControl(void) } } +#define HYDRAULIC_UPPER_EXT (-0.12f) +#define HYDRAULIC_LOWER_EXT (0.14f) + void CAutomobile::HydraulicControl(void) { @@ -2595,8 +2603,8 @@ CAutomobile::HydraulicControl(void) m_hydraulicState = 20; else{ m_hydraulicState = 0; - normalUpperLimit += -0.12f; - normalSpringLength = normalUpperLimit - (normalLowerLimit+0.14f); + normalUpperLimit += HYDRAULIC_UPPER_EXT; + normalSpringLength = normalUpperLimit - (normalLowerLimit+HYDRAULIC_LOWER_EXT); DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f); } @@ -2629,7 +2637,7 @@ CAutomobile::HydraulicControl(void) float radius = Max(specialColModel->boundingBox.min.Magnitude(), specialColModel->boundingBox.max.Magnitude()); if(specialColModel->boundingSphere.radius < radius) specialColModel->boundingSphere.radius = radius; - + return; } if(playerInfo->m_WBState != WBSTATE_PLAYING) @@ -2668,8 +2676,8 @@ CAutomobile::HydraulicControl(void) if(m_hydraulicState < 100){ if(m_hydraulicState == 0){ - normalUpperLimit += -0.12f; - normalLowerLimit += 0.14f; + normalUpperLimit += HYDRAULIC_UPPER_EXT; + normalLowerLimit += HYDRAULIC_LOWER_EXT; normalSpringLength = normalUpperLimit - normalLowerLimit; } @@ -2734,8 +2742,8 @@ CAutomobile::HydraulicControl(void) // Lowered, move wheels up if(m_hydraulicState == 0){ - normalUpperLimit += -0.12f; - normalLowerLimit += 0.14f; + normalUpperLimit += HYDRAULIC_UPPER_EXT; + normalLowerLimit += HYDRAULIC_LOWER_EXT; normalSpringLength = normalUpperLimit - normalLowerLimit; } @@ -2776,8 +2784,8 @@ CAutomobile::HydraulicControl(void) } if(m_fVelocityChangeForAudio < 0.1f){ - normalUpperLimit += -0.12f; - normalLowerLimit += 0.14f; + normalUpperLimit += HYDRAULIC_UPPER_EXT; + normalLowerLimit += HYDRAULIC_LOWER_EXT; normalSpringLength = normalUpperLimit - normalLowerLimit; } @@ -2914,7 +2922,7 @@ CAutomobile::ProcessBuoyancy(void) DMAudio.PlayOneShot(m_audioEntityId, SOUND_WATER_FALL, 0.0f); } - if(nGenerateWaterCircles > 0 && nGenerateWaterCircles < CTimer::GetTimeInMilliseconds()){ + if(nGenerateWaterCircles > 0 && nGenerateWaterCircles <= CTimer::GetTimeInMilliseconds()){ CVector pos = GetPosition(); float waterLevel = 0.0f; if(CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &waterLevel, false)) @@ -2934,7 +2942,7 @@ CAutomobile::ProcessBuoyancy(void) } } - if(nGenerateRaindrops > 0 && nGenerateRaindrops < CTimer::GetTimeInMilliseconds()){ + if(nGenerateRaindrops > 0 && nGenerateRaindrops <= CTimer::GetTimeInMilliseconds()){ CVector pos = GetPosition(); float waterLevel = 0.0f; if(CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &waterLevel, false)) @@ -2955,7 +2963,7 @@ CAutomobile::ProcessBuoyancy(void) static RwRGBA smokeCol = {255, 255, 255, 255}; for(i = 0; i < 4; i++){ - if(m_aSuspensionSpringRatio[i] < 1.0f && m_aWheelColPoints[i].surfaceB == SURFACE_PUDDLE){ + if(m_aSuspensionSpringRatio[i] < 1.0f && m_aWheelColPoints[i].surfaceB == SURFACE_WATER){ CVector pos = m_aWheelColPoints[i].point + 0.3f*GetUp() - GetPosition(); CVector vSpeed = GetSpeed(pos); vSpeed.z = 0.0f; @@ -3226,7 +3234,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) if(impulse > 25.0f && GetStatus() != STATUS_WRECKED){ if(bIsLawEnforcer && FindPlayerVehicle() && FindPlayerVehicle() == m_pDamageEntity && - GetStatus() != STATUS_ABANDONED && + GetStatus() != STATUS_ABANDONED && FindPlayerVehicle()->m_vecMoveSpeed.Magnitude() >= m_vecMoveSpeed.Magnitude() && FindPlayerVehicle()->m_vecMoveSpeed.Magnitude() > 0.1f) FindPlayerPed()->SetWantedLevelNoDrop(1); @@ -3270,6 +3278,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) case CAR_PIECE_BONNET: GetComponentWorldPosition(CAR_BONNET, pos); dmgDrawCarCollidingParticles(pos, impulse); + if(GetModelIndex() != MI_DODO) if(Damage.ApplyDamage(COMPONENT_DOOR_BONNET, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ SetDoorDamage(CAR_BONNET, DOOR_BONNET); doubleMoney = true; @@ -3280,7 +3289,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) case CAR_PIECE_BUMP_REAR: GetComponentWorldPosition(CAR_BUMP_REAR, pos); dmgDrawCarCollidingParticles(pos, impulse); - if(Damage.ApplyDamage(COMPONENT_BUMPER_FRONT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + if(Damage.ApplyDamage(COMPONENT_BUMPER_REAR, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ SetBumperDamage(CAR_BUMP_REAR, VEHBUMPER_REAR); doubleMoney = true; } @@ -3536,8 +3545,8 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) int i; CVector dir; static RwRGBA grassCol = { 8, 24, 8, 255 }; - static RwRGBA dirtCol = { 64, 64, 64, 255 }; - static RwRGBA dirttrackCol = { 64, 32, 16, 255 }; + static RwRGBA gravelCol = { 64, 64, 64, 255 }; + static RwRGBA mudCol = { 64, 32, 16, 255 }; static RwRGBA waterCol = { 48, 48, 64, 0 }; if(!belowEffectSpeed) @@ -3553,22 +3562,22 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed) CGeneral::GetRandomNumberInRange(0.02f, 0.1f), grassCol); } return 0; - case SURFACE_DIRT: + case SURFACE_GRAVEL: dir.x = -0.05f*m_vecMoveSpeed.x; dir.y = -0.05f*m_vecMoveSpeed.y; for(i = 0; i < 4; i++){ dir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f); CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil, - CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirtCol); + CGeneral::GetRandomNumberInRange(0.02f, 0.06f), gravelCol); } return 1; - case SURFACE_DIRTTRACK: + case SURFACE_MUD_DRY: dir.x = -0.05f*m_vecMoveSpeed.x; dir.y = -0.05f*m_vecMoveSpeed.y; for(i = 0; i < 4; i++){ dir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f); CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil, - CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirttrackCol); + CGeneral::GetRandomNumberInRange(0.02f, 0.06f), mudCol); } return 0; default: @@ -3912,19 +3921,19 @@ CAutomobile::SetUpWheelColModel(CColModel *colModel) CMatrix mat; mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF])); - colModel->spheres[0].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LF); + colModel->spheres[0].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LF); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LB])); - colModel->spheres[1].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LR); + colModel->spheres[1].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LR); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF])); - colModel->spheres[2].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RF); + colModel->spheres[2].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RF); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RB])); - colModel->spheres[3].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RR); + colModel->spheres[3].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RR); if(m_aCarNodes[CAR_WHEEL_LM] != nil && m_aCarNodes[CAR_WHEEL_RM] != nil){ mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LM])); - colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RF); + colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LR); mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RM])); - colModel->spheres[5].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RR); + colModel->spheres[5].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RR); colModel->numSpheres = 6; }else colModel->numSpheres = 4; @@ -3952,8 +3961,8 @@ CAutomobile::BurstTyre(uint8 wheel) CCarCtrl::SwitchVehicleToRealPhysics(this); } - ApplyMoveForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f)); - ApplyTurnForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f), GetForward()); + ApplyMoveForce(GetRight() * m_fMass * CGeneral::GetRandomNumberInRange(-0.03f, 0.03f)); + ApplyTurnForce(GetRight() * m_fTurnMass * CGeneral::GetRandomNumberInRange(-0.03f, 0.03f), GetForward()); } } @@ -3968,10 +3977,10 @@ CAutomobile::IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset) CVector seatPos; switch(component){ case CAR_DOOR_RF: - seatPos = mi->m_positions[mi->m_vehicleType == VEHICLE_TYPE_BOAT ? BOAT_POS_FRONTSEAT : CAR_POS_FRONTSEAT]; + seatPos = mi->GetFrontSeatPosn(); break; case CAR_DOOR_LF: - seatPos = mi->m_positions[mi->m_vehicleType == VEHICLE_TYPE_BOAT ? BOAT_POS_FRONTSEAT : CAR_POS_FRONTSEAT]; + seatPos = mi->GetFrontSeatPosn(); seatPos.x = -seatPos.x; break; case CAR_DOOR_RR: @@ -4308,7 +4317,7 @@ GetCurrentAtomicObjectCB(RwObject *object, void *data) return object; } -CColPoint spherepoints[MAX_COLLISION_POINTS]; +static CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; CObject* CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) @@ -4414,7 +4423,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) dist += GetUp(); if(GetUp().z > 0.0f){ // simulate fast upward movement if going fast - float speed = CVector2D(m_vecMoveSpeed).MagnitudeSqr(); + float speed = CVector2D(m_vecMoveSpeed).Magnitude(); obj->GetMatrix().Translate(GetUp()*speed); } } @@ -4428,7 +4437,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) if(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(), this->GetMatrix(), *this->GetColModel(), - spherepoints, nil, nil) > 0) + aTempPedColPts, nil, nil) > 0) obj->m_pCollidingEntity = this; if(bRenderScorched) @@ -4446,8 +4455,11 @@ CAutomobile::RemoveBonnetInPedCollision(void) if(Damage.GetDoorStatus(DOOR_BONNET) == DOOR_STATUS_SWINGING && Doors[DOOR_BONNET].RetAngleWhenOpen()*0.4f < Doors[DOOR_BONNET].m_fAngle){ - // BUG? why not COMPGROUP_BONNET? +#ifdef FIX_BUGS + obj = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_BONNET); +#else obj = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_DOOR); +#endif // make both doors invisible on car SetComponentVisibility(m_aCarNodes[CAR_BONNET], ATOMIC_FLAG_NONE); Damage.SetDoorStatus(DOOR_BONNET, DOOR_STATUS_MISSING); @@ -4508,13 +4520,16 @@ CAutomobile::SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents status = DOOR_STATUS_MISSING; } - if(status == DOOR_STATUS_SMASHED){ + switch(status){ + case DOOR_STATUS_SMASHED: // show damaged part SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_DAM); - }else if(status == DOOR_STATUS_SWINGING){ + break; + case DOOR_STATUS_SWINGING: // turn off angle cull for swinging doors RwFrameForAllObjects(m_aCarNodes[component], CVehicleModelInfo::SetAtomicFlagCB, (void*)ATOMIC_FLAG_NOCULL); - }else if(status == DOOR_STATUS_MISSING){ + break; + case DOOR_STATUS_MISSING: if(!noFlyingComponents){ if(door == DOOR_BONNET) SpawnFlyingComponent(component, COMPGROUP_BONNET); @@ -4525,6 +4540,7 @@ CAutomobile::SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents } // hide both SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_NONE); + break; } } @@ -4555,7 +4571,7 @@ CAutomobile::SetupModelNodes(void) int i; for(i = 0; i < NUM_CAR_NODES; i++) m_aCarNodes[i] = nil; - CClumpModelInfo::FillFrameArray((RpClump*)m_rwObject, m_aCarNodes); + CClumpModelInfo::FillFrameArray(GetClump(), m_aCarNodes); } void diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index a3e8ac17..604bed17 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -30,15 +30,6 @@ enum eCarNodes NUM_CAR_NODES, }; -enum eCarPositions -{ - CAR_POS_HEADLIGHTS, - CAR_POS_TAILLIGHTS, - CAR_POS_FRONTSEAT, - CAR_POS_BACKSEAT, - CAR_POS_EXHAUST = 9, -}; - // These are used for all the wheel arrays // DON'T confuse with VEHWHEEL, which are vehicle components enum { @@ -77,23 +68,23 @@ public: float m_aSuspensionSpringRatio[4]; float m_aSuspensionSpringRatioPrev[4]; float m_aWheelTimer[4]; // set to 4.0 when wheel is touching ground, then decremented - float field_49C; + float m_auto_unused1; bool m_aWheelSkidmarkMuddy[4]; bool m_aWheelSkidmarkBloody[4]; float m_aWheelRotation[4]; float m_aWheelPosition[4]; float m_aWheelSpeed[4]; - uint8 field_4D8; + uint8 m_auto_unused2; uint8 m_bombType : 3; uint8 bTaxiLight : 1; - uint8 bHadDriver : 1; // for bombs + uint8 bDriverLastFrame : 1; // for bombs uint8 bFixedColour : 1; uint8 bBigWheels : 1; uint8 bWaterTight : 1; // no damage for non-player peds uint8 bNotDamagedUpsideDown : 1; uint8 bMoreResistantToDamage : 1; CEntity *m_pBombRigger; - int16 field_4E0; + int16 m_auto_unk1; uint16 m_hydraulicState; uint32 m_nBusDoorTimerEnd; uint32 m_nBusDoorTimerStart; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 72fca542..d86627de 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -79,7 +79,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) bIsInWater = true; - unk1 = 0.0f; + m_phys_unused1 = 0.0f; m_bIsAnchored = true; m_fOrientation = INVALID_ORIENTATION; bTouchingWater = true; @@ -904,6 +904,8 @@ CBoat::AddWakePoint(CVector point) } m_avec2dWakePoints[0] = point; m_afWakePointLifeTime[0] = 400.0f; + if(m_nNumWakePoints < ARRAY_SIZE(m_afWakePointLifeTime)) + m_nNumWakePoints++; } }else{ m_avec2dWakePoints[0] = point; diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index 72b6c30c..cb21b918 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -226,7 +226,7 @@ INITSAVEBUF WriteSaveBuf(buffer, ProcessCounter); WriteSaveBuf(buffer, GenerateEvenIfPlayerIsCloseCounter); WriteSaveBuf(buffer, (int16)0); // alignment - WriteSaveBuf(buffer, sizeof(CarGeneratorArray)); + WriteSaveBuf(buffer, (uint32)sizeof(CarGeneratorArray)); for (int i = 0; i < NUM_CARGENS; i++) WriteSaveBuf(buffer, CarGeneratorArray[i]); VALIDATESAVEBUF(*size) diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index 9c8f9fda..757974a6 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -184,7 +184,7 @@ bool CCranes::IsThisCarPickedUp(float X, float Y, CVehicle* pVehicle) result = true; } } - return true; + return result; } void CCranes::UpdateCranes(void) @@ -243,8 +243,11 @@ void CCrane::Update(void) Abs(m_pVehiclePickedUp->GetMoveSpeed().x) > CAR_MOVING_SPEED_THRESHOLD || Abs(m_pVehiclePickedUp->GetMoveSpeed().y) > CAR_MOVING_SPEED_THRESHOLD || Abs(m_pVehiclePickedUp->GetMoveSpeed().z) > CAR_MOVING_SPEED_THRESHOLD || - FindPlayerPed()->GetPedState() == PED_ENTER_CAR && // TODO: fix carjack bug - FindPlayerPed()->m_pSeekTarget == m_pVehiclePickedUp) { + (FindPlayerPed()->GetPedState() == PED_ENTER_CAR +#ifdef FIX_BUGS + || FindPlayerPed()->GetPedState() == PED_CARJACK +#endif + ) && FindPlayerPed()->m_pSeekTarget == m_pVehiclePickedUp) { m_pVehiclePickedUp = nil; m_nCraneState = IDLE; } @@ -395,7 +398,7 @@ bool CCrane::RotateCarriedCarProperly() float fDeltaThisFrame = CAR_ROTATION_SPEED * CTimer::GetTimeStep(); if (Abs(fAngleDelta) <= fDeltaThisFrame) // no rotation is actually applied? return true; - m_pVehiclePickedUp->GetMatrix().RotateZ(Abs(fDeltaThisFrame)); + m_pVehiclePickedUp->GetMatrix().RotateZ(fAngleDelta < 0 ? -fDeltaThisFrame : fDeltaThisFrame); return false; } diff --git a/src/vehicles/DamageManager.cpp b/src/vehicles/DamageManager.cpp index 6b59ccda..c625a4e7 100644 --- a/src/vehicles/DamageManager.cpp +++ b/src/vehicles/DamageManager.cpp @@ -11,7 +11,7 @@ CDamageManager::CDamageManager(void) { ResetDamageStatus(); m_fWheelDamageEffect = 0.75f; - field_24 = 1; + field_18 = 1; } void @@ -28,12 +28,8 @@ CDamageManager::FuckCarCompletely(void) m_wheelStatus[0] = WHEEL_STATUS_MISSING; // wheels 1-3 not reset? - m_doorStatus[0] = DOOR_STATUS_MISSING; - m_doorStatus[1] = DOOR_STATUS_MISSING; - m_doorStatus[2] = DOOR_STATUS_MISSING; - m_doorStatus[3] = DOOR_STATUS_MISSING; - m_doorStatus[4] = DOOR_STATUS_MISSING; - m_doorStatus[5] = DOOR_STATUS_MISSING; + for(i = 0; i < ARRAY_SIZE(m_doorStatus); i++) + m_doorStatus[i] = DOOR_STATUS_MISSING; for(i = 0; i < 3; i++){ #ifdef FIX_BUGS diff --git a/src/vehicles/DamageManager.h b/src/vehicles/DamageManager.h index bf0c59a1..312006e3 100644 --- a/src/vehicles/DamageManager.h +++ b/src/vehicles/DamageManager.h @@ -86,7 +86,7 @@ public: uint8 m_doorStatus[6]; uint32 m_lightStatus; uint32 m_panelStatus; - uint32 field_24; + uint8 field_18; CDamageManager(void); diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp index 3ac0da38..5beed29e 100644 --- a/src/vehicles/HandlingMgr.cpp +++ b/src/vehicles/HandlingMgr.cpp @@ -78,7 +78,7 @@ cHandlingDataMgr::Initialise(void) { LoadHandlingData(); field_0 = 0.1f; - field_4 = 0.9f; + fWheelFriction = 0.9f; field_8 = 1.0f; field_C = 0.8f; field_10 = 0.98f; diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h index 398a415f..10e25573 100644 --- a/src/vehicles/HandlingMgr.h +++ b/src/vehicles/HandlingMgr.h @@ -60,7 +60,9 @@ enum eHandlingId HANDLING_PANLANT, HANDLING_FLATBED, HANDLING_YANKEE, - HANDLING_BORGNINE + HANDLING_BORGNINE, + + NUMHANDLINGS }; enum @@ -120,7 +122,7 @@ class cHandlingDataMgr { float field_0; // unused it seems public: - float field_4; // wheel related + float fWheelFriction; // wheel related private: float field_8; // float field_C; // unused it seems diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 7b62b461..4966a228 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -570,7 +570,7 @@ CHeli::PreRender(void) i = 0; for(angle = 0.0f; angle < TWOPI; angle += TWOPI/32){ CVector pos(radius*Cos(angle), radius*Sin(angle), 0.0f); - CVector dir = pos*0.01f; + CVector dir = CVector(pos.x, pos.y, 1.0f)*0.01f; pos += GetPosition(); if(CWorld::ProcessVerticalLine(pos, testLowZ, point, entity, true, false, false, false, true, false, nil)) @@ -590,12 +590,12 @@ CHeli::PreRender(void) g = 6; b = 3; break; - case SURFACE_DIRT: + case SURFACE_GRAVEL: r = 10; g = 8; b = 7; break; - case SURFACE_DIRTTRACK: + case SURFACE_MUD_DRY: r = 10; g = 6; b = 3; diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp index 71189d84..3bf385a0 100644 --- a/src/vehicles/Plane.cpp +++ b/src/vehicles/Plane.cpp @@ -84,6 +84,10 @@ CPlane::CPlane(int32 id, uint8 CreatedBy) SetStatus(STATUS_PLANE); bIsBIGBuilding = true; m_level = LEVEL_NONE; + +#ifdef FIX_BUGS + m_isFarAway = true; +#endif } CPlane::~CPlane() diff --git a/src/vehicles/Plane.h b/src/vehicles/Plane.h index a6f6e1d9..783c53b3 100644 --- a/src/vehicles/Plane.h +++ b/src/vehicles/Plane.h @@ -9,13 +9,6 @@ enum ePlaneNodes NUM_PLANE_NODES }; -enum ePlanePositions -{ - PLANE_POS_LIGHT_LEFT, - PLANE_POS_LIGHT_RIGHT, - PLANE_POS_LIGHT_TAIL, -}; - struct CPlaneNode { CVector p; // position diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp index 1d47ca3a..26d0dee7 100644 --- a/src/vehicles/Train.cpp +++ b/src/vehicles/Train.cpp @@ -13,6 +13,7 @@ #include "DMAudio.h" #include "HandlingMgr.h" #include "Train.h" +#include "AudioScriptObject.h" static CTrainNode* pTrackNodes; static int16 NumTrackNodes; @@ -35,6 +36,8 @@ static float EngineTrackSpeed_S[4]; CVector CTrain::aStationCoors[3]; CVector CTrain::aStationCoors_S[4]; +static bool bTrainArrivalAnnounced[3] = {false, false, false}; + CTrain::CTrain(int32 id, uint8 CreatedBy) : CVehicle(CreatedBy) { @@ -60,6 +63,10 @@ CTrain::CTrain(int32 id, uint8 CreatedBy) bUsesCollision = true; SetStatus(STATUS_TRAIN_MOVING); + +#ifdef FIX_BUGS + m_isFarAway = true; +#endif } void @@ -197,7 +204,7 @@ CTrain::ProcessControl(void) if(m_bTrainStopping){ m_nDoorTimer = CTimer::GetTimeInMilliseconds() + 1000; m_nDoorState = TRAIN_DOOR_OPENING; - DMAudio.PlayOneShot(m_audioEntityId, SOUND_18, 0.0f); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_TRAIN_DOOR_CLOSE, 0.0f); } break; @@ -214,7 +221,7 @@ CTrain::ProcessControl(void) if(!m_bTrainStopping){ m_nDoorTimer = CTimer::GetTimeInMilliseconds() + 1000; m_nDoorState = TRAIN_DOOR_CLOSING; - DMAudio.PlayOneShot(m_audioEntityId, SOUND_19, 0.0f); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_TRAIN_DOOR_OPEN, 0.0f); } break; @@ -619,9 +626,47 @@ CTrain::ReadAndInterpretTrackFile(Const char *filename, CTrainNode **nodes, int1 } void +PlayAnnouncement(uint8 sound, uint8 station) +{ + // this was gone in a PC version but inlined on PS2 + cAudioScriptObject *obj = new cAudioScriptObject; + obj->AudioId = sound; + obj->Posn = CTrain::aStationCoors[station]; + obj->AudioEntity = AEHANDLE_NONE; + DMAudio.CreateOneShotScriptObject(obj); +} + +void ProcessTrainAnnouncements(void) { - // TODO but unused + for (int i = 0; i < ARRAY_SIZE(StationDist); i++) { + for (int j = 0; j < ARRAY_SIZE(EngineTrackPosition); j++) { + if (!bTrainArrivalAnnounced[i]) { + float preDist = StationDist[i] - 100.0f; + if (preDist < 0.0f) + preDist += TotalLengthOfTrack; + if (EngineTrackPosition[j] > preDist && EngineTrackPosition[j] < StationDist[i]) { + bTrainArrivalAnnounced[i] = true; + PlayAnnouncement(SCRIPT_SOUND_TRAIN_ANNOUNCEMENT_1, i); + break; + } + } else { + float postDist = StationDist[i] + 10.0f; +#ifdef FIX_BUGS + if (postDist > TotalLengthOfTrack) + postDist -= TotalLengthOfTrack; +#else + if (postDist < 0.0f) // does this even make sense here? + postDist += TotalLengthOfTrack; +#endif + if (EngineTrackPosition[j] > StationDist[i] && EngineTrackPosition[j] < postDist) { + bTrainArrivalAnnounced[i] = false; + PlayAnnouncement(SCRIPT_SOUND_TRAIN_ANNOUNCEMENT_2, i); + break; + } + } + } + } } void diff --git a/src/vehicles/Train.h b/src/vehicles/Train.h index c645ecaf..3446eeb5 100644 --- a/src/vehicles/Train.h +++ b/src/vehicles/Train.h @@ -24,15 +24,6 @@ enum eTrainNodes NUM_TRAIN_NODES }; -enum eTrainPositions -{ - TRAIN_POS_LIGHT_FRONT, - TRAIN_POS_LIGHT_REAR, - TRAIN_POS_LEFT_ENTRY, - TRAIN_POS_MID_ENTRY, - TRAIN_POS_RIGHT_ENTRY -}; - struct CTrainNode { CVector p; // position diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 5dc7bc72..e21ad07c 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -50,15 +50,18 @@ CVehicle::CVehicle(uint8 CreatedBy) { int i; - m_nCurrentGear = 0; - m_fChangeGearTime = 0; - m_fSteerRatio = 0.0f; + m_nCurrentGear = 1; + m_fChangeGearTime = 0.0f; + m_fSteerInput = 0.0f; m_type = ENTITY_TYPE_VEHICLE; VehicleCreatedBy = CreatedBy; bIsLocked = false; bIsLawEnforcer = false; bIsAmbulanceOnDuty = false; bIsFireTruckOnDuty = false; +#ifdef FIX_BUGS + bIsHandbrakeOn = false; +#endif CCarCtrl::UpdateCarCount(this, false); m_fHealth = 1000.0f; bEngineOn = true; @@ -96,7 +99,7 @@ CVehicle::CVehicle(uint8 CreatedBy) m_numPedsUseItAsCover = 0; bIsCarParkVehicle = false; bHasAlreadyBeenRecorded = false; - m_bSirenOrAlarm = 0; + m_bSirenOrAlarm = false; m_nCarHornTimer = 0; m_nCarHornPattern = 0; m_nAlarmState = 0; @@ -280,90 +283,91 @@ CVehicle::FlyingControl(eFlightModel flightModel) float turnSpeed = m_vecTurnSpeed.MagnitudeSqr(); if(turnSpeed > SQR(0.2f)) m_vecTurnSpeed *= 0.2f/Sqrt(turnSpeed); - } break; + } case FLIGHT_MODEL_RCPLANE: case FLIGHT_MODEL_SEAPLANE: { // thrust float fForwSpeed = DotProduct(GetMoveSpeed(), GetForward()); - CVector vecWidthForward = GetColModel()->boundingBox.min.y * GetForward(); + CVector vecTail = GetColModel()->boundingBox.min.y * GetForward(); float fThrust = (CPad::GetPad(0)->GetAccelerate() - CPad::GetPad(0)->GetBrake()) / 255.0f; if (fForwSpeed > 0.1f || (flightModel == FLIGHT_MODEL_RCPLANE && fForwSpeed > 0.02f)) fThrust += 1.0f; else if (fForwSpeed > 0.0f && fThrust < 0.0f) fThrust = 0.0f; - float fThrustImpulse; + float fThrustAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) - fThrustImpulse = (fThrust - fRCPropFallOff * fForwSpeed) * fRCAeroThrust; + fThrustAccel = (fThrust - fRCPropFallOff * fForwSpeed) * fRCAeroThrust; else - fThrustImpulse = (fThrust - fSeaPropFallOff * fForwSpeed) * fSeaThrust; - ApplyMoveForce(fThrustImpulse * GetForward() * m_fMass * CTimer::GetTimeStep()); + fThrustAccel = (fThrust - fSeaPropFallOff * fForwSpeed) * fSeaThrust; + ApplyMoveForce(fThrustAccel * GetForward() * m_fMass * CTimer::GetTimeStep()); // left/right float fSideSpeed = -DotProduct(GetMoveSpeed(), GetRight()); float fSteerLR = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f; - float fSideSlipImpulse; + float fSideSlipAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) - fSideSlipImpulse = Abs(fSideSpeed) * fSideSpeed * fRCSideSlipMult; + fSideSlipAccel = Abs(fSideSpeed) * fSideSpeed * fRCSideSlipMult; else - fSideSlipImpulse = Abs(fSideSpeed) * fSideSpeed * fSeaSideSlipMult; - ApplyMoveForce(m_fMass * GetRight() * fSideSlipImpulse * CTimer::GetTimeStep()); + fSideSlipAccel = Abs(fSideSpeed) * fSideSpeed * fSeaSideSlipMult; + ApplyMoveForce(m_fMass * GetRight() * fSideSlipAccel * CTimer::GetTimeStep()); - float fYaw = -DotProduct(CrossProduct(m_vecTurnSpeed + m_vecTurnFriction, vecWidthForward) + m_vecMoveSpeed + m_vecMoveFriction, GetRight()); - float fYawImpulse; + float fYaw = -DotProduct(GetSpeed(vecTail), GetRight()); + float fYawAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) - fYawImpulse = fRCRudderMult * fYaw * Abs(fYaw) + fRCYawMult * fSteerLR * fForwSpeed; + fYawAccel = fRCRudderMult * fYaw * Abs(fYaw) + fRCYawMult * fSteerLR * fForwSpeed; else - fYawImpulse = fSeaRudderMult * fYaw * Abs(fYaw) + fSeaYawMult * fSteerLR * fForwSpeed; - ApplyTurnForce(fYawImpulse * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), vecWidthForward); + fYawAccel = fSeaRudderMult * fYaw * Abs(fYaw) + fSeaYawMult * fSteerLR * fForwSpeed; + ApplyTurnForce(fYawAccel * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), vecTail); - float fRollImpulse; + float fRollAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) { float fDirectionMultiplier = CPad::GetPad(0)->GetLookRight(); if (CPad::GetPad(0)->GetLookLeft()) fDirectionMultiplier = -1; - fRollImpulse = (0.5f * fDirectionMultiplier + fSteerLR) * fRCRollMult; + fRollAccel = (0.5f * fDirectionMultiplier + fSteerLR) * fRCRollMult; } else - fRollImpulse = fSteerLR * fSeaRollMult; - ApplyTurnForce(GetRight() * fRollImpulse * fForwSpeed * m_fTurnMass * CTimer::GetTimeStep(), GetUp()); + fRollAccel = fSteerLR * fSeaRollMult; + ApplyTurnForce(GetRight() * fRollAccel * fForwSpeed * m_fTurnMass * CTimer::GetTimeStep(), GetUp()); CVector vecFRight = CrossProduct(GetForward(), CVector(0.0f, 0.0f, 1.0f)); CVector vecStabilise = (GetUp().z > 0.0f) ? vecFRight : -vecFRight; float fStabiliseDirection = (GetRight().z > 0.0f) ? -1.0f : 1.0f; - float fStabiliseImpulse; + float fStabiliseSpeed; if (flightModel == FLIGHT_MODEL_RCPLANE) - fStabiliseImpulse = fRCRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); + fStabiliseSpeed = fRCRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); else - fStabiliseImpulse = fSeaRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); - ApplyTurnForce(fStabiliseImpulse * m_fTurnMass * GetRight(), GetUp()); // no CTimer::GetTimeStep(), is it right? VC doesn't have it too + fStabiliseSpeed = fSeaRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z)); + ApplyTurnForce(fStabiliseSpeed * m_fTurnMass * GetRight(), GetUp()); // no CTimer::GetTimeStep(), is it right? VC doesn't have it too // up/down - float fTail = -DotProduct(CrossProduct(m_vecTurnSpeed + m_vecTurnFriction, vecWidthForward) + m_vecMoveSpeed + m_vecMoveFriction, GetUp()); + float fTail = -DotProduct(GetSpeed(vecTail), GetUp()); float fSteerUD = -CPad::GetPad(0)->GetSteeringUpDown() / 128.0f; - float fPitchImpulse; + float fPitchAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) - fPitchImpulse = fRCTailMult * fTail * Abs(fTail) + fRCPitchMult * fSteerUD * fForwSpeed; + fPitchAccel = fRCTailMult * fTail * Abs(fTail) + fRCPitchMult * fSteerUD * fForwSpeed; else - fPitchImpulse = fSeaTailMult * fTail * Abs(fTail) + fSeaPitchMult * fSteerUD * fForwSpeed; - ApplyTurnForce(fPitchImpulse * m_fTurnMass * GetUp() * CTimer::GetTimeStep(), vecWidthForward); + fPitchAccel = fSeaTailMult * fTail * Abs(fTail) + fSeaPitchMult * fSteerUD * fForwSpeed; + ApplyTurnForce(fPitchAccel * m_fTurnMass * GetUp() * CTimer::GetTimeStep(), vecTail); float fLift = -DotProduct(GetMoveSpeed(), GetUp()) / Max(0.01f, GetMoveSpeed().Magnitude()); - float fLiftImpluse; + float fLiftAccel; if (flightModel == FLIGHT_MODEL_RCPLANE) - fLiftImpluse = (fRCAttackLiftMult * fLift + fRCFormLiftMult) * fForwSpeed * fForwSpeed; + fLiftAccel = (fRCAttackLiftMult * fLift + fRCFormLiftMult) * fForwSpeed * fForwSpeed; else - fLiftImpluse = (fSeaAttackLiftMult * fLift + fSeaFormLiftMult) * fForwSpeed * fForwSpeed; - float fLiftForce = fLiftImpluse * m_fMass * CTimer::GetTimeStep(); - if (GRAVITY * CTimer::GetTimeStep() * m_fMass < fLiftImpluse) { + fLiftAccel = (fSeaAttackLiftMult * fLift + fSeaFormLiftMult) * fForwSpeed * fForwSpeed; + float fLiftImpulse = fLiftAccel * m_fMass * CTimer::GetTimeStep(); + if (GRAVITY * CTimer::GetTimeStep() * m_fMass < fLiftImpulse) { if (flightModel == FLIGHT_MODEL_RCPLANE && GetPosition().z > 50.0f) - fLiftForce = CTimer::GetTimeStep() * 0.0072 * m_fMass; + fLiftImpulse = CTimer::GetTimeStep() * 0.9f*GRAVITY * m_fMass; else if (flightModel == FLIGHT_MODEL_SEAPLANE && GetPosition().z > 80.0f) - fLiftForce = CTimer::GetTimeStep() * 0.0072 * m_fMass; + fLiftImpulse = CTimer::GetTimeStep() * 0.9f*GRAVITY * m_fMass; } - ApplyMoveForce(fLiftForce * GetUp()); + ApplyMoveForce(fLiftImpulse * GetUp()); + CVector vecResistance; if (flightModel == FLIGHT_MODEL_RCPLANE) vecResistance = vecRCAeroResistance; @@ -425,10 +429,9 @@ CVehicle::FlyingControl(eFlightModel flightModel) } if (CPad::GetPad(0)->GetHorn()) { fYaw = 0.0f; - fPitch = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetUp()), -200.0f, 1.3f); + fPitch = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetForward()), -200.0f, 1.3f); fRoll = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetRight()), -200.0f, 1.3f); } - debug("fPitch: %f\n", fPitch); ApplyTurnForce(fPitch * GetUp() * fPitchVar * m_fTurnMass * CTimer::GetTimeStep(), GetForward()); ApplyTurnForce(fRoll * GetUp() * fRollVar * m_fTurnMass * CTimer::GetTimeStep(), GetRight()); ApplyTurnForce(fYaw * GetForward() * fYawVar * m_fTurnMass * CTimer::GetTimeStep(), GetRight()); @@ -442,11 +445,11 @@ CVehicle::FlyingControl(eFlightModel flightModel) float rY = Pow(vecResistance.y, CTimer::GetTimeStep()); float rZ = Pow(vecResistance.z, CTimer::GetTimeStep()); CVector vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix()); - float fResistanceMultiplier = Pow(1.0f / (fSpinSpeedRes * SQR(vecTurnSpeed.z) + 1.0f), CTimer::GetTimeStep()); + float fResistanceMultiplier = Pow(1.0f / (fSpinSpeedRes * SQR(vecTurnSpeed.z) + 1.0f) * rZ, CTimer::GetTimeStep()); float fResistance = vecTurnSpeed.z * fResistanceMultiplier - vecTurnSpeed.z; vecTurnSpeed.x *= rX; vecTurnSpeed.y *= rY; - vecTurnSpeed.z *= rZ; + vecTurnSpeed.z *= fResistanceMultiplier; m_vecTurnSpeed = Multiply3x3(GetMatrix(), vecTurnSpeed); ApplyTurnForce(-GetRight() * fResistance * m_fTurnMass, GetForward() + Multiply3x3(GetMatrix(), m_vecCentreOfMass)); break; @@ -454,6 +457,9 @@ CVehicle::FlyingControl(eFlightModel flightModel) } } +float fBurstSpeedMax = 0.3f; +float fBurstTyreMod = 0.1f; + void CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, int32 wheelsOnGround, float thrust, float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, uint16 wheelStatus) @@ -463,6 +469,10 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon static bool bBraking; static bool bDriving; +#ifdef FIX_SIGNIFICANT_BUGS + bAlreadySkidding = false; +#endif + // how much force we want to apply in these axes float fwd = 0.0f; float right = 0.0f; @@ -487,10 +497,15 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon if(contactSpeedRight != 0.0f){ // exert opposing force right = -contactSpeedRight/wheelsOnGround; +#ifdef FIX_BUGS + // contactSpeedRight is independent of framerate but right has timestep as a factor + // so we probably have to fix this + right *= CTimer::GetTimeStepFix(); +#endif if(wheelStatus == WHEEL_STATUS_BURST){ - float fwdspeed = Min(contactSpeedFwd, 0.3f); - right += fwdspeed * CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + float fwdspeed = Min(contactSpeedFwd, fBurstSpeedMax); + right += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstTyreMod, fBurstTyreMod); } } @@ -507,13 +522,21 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon } }else if(contactSpeedFwd != 0.0f){ fwd = -contactSpeedFwd/wheelsOnGround; +#ifdef FIX_BUGS + // contactSpeedFwd is independent of framerate but fwd has timestep as a factor + // so we probably have to fix this + fwd *= CTimer::GetTimeStepFix(); +#endif if(!bBraking){ if(m_fGasPedal < 0.01f){ if(GetModelIndex() == MI_RCBANDIT) - brake = 0.2f * mod_HandlingManager.field_4 / m_fMass; + brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass; else - brake = mod_HandlingManager.field_4 / m_fMass; + brake = mod_HandlingManager.fWheelFriction / m_fMass; +#ifdef FIX_BUGS + brake *= CTimer::GetTimeStepFix(); +#endif } } @@ -531,7 +554,8 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon } } - if(sq(adhesion) < sq(right) + sq(fwd)){ + float speedSq = sq(right) + sq(fwd); + if(sq(adhesion) < speedSq){ if(*wheelState != WHEEL_STATE_FIXED){ if(bDriving && contactSpeedFwd < 0.2f) *wheelState = WHEEL_STATE_SPINNING; @@ -539,7 +563,7 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon *wheelState = WHEEL_STATE_SKIDDING; } - float l = Sqrt(sq(right) + sq(fwd)); + float l = Sqrt(speedSq); float tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss; right *= adhesion * tractionLoss / l; fwd *= adhesion * tractionLoss / l; @@ -658,7 +682,7 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage break; } } - if (oldHealth > DAMAGE_HEALTH_TO_CATCH_FIRE && m_fHealth < DAMAGE_HEALTH_TO_CATCH_FIRE) { + if (oldHealth >= DAMAGE_HEALTH_TO_CATCH_FIRE && m_fHealth < DAMAGE_HEALTH_TO_CATCH_FIRE) { if (IsCar()) { CAutomobile* pThisCar = (CAutomobile*)this; pThisCar->Damage.SetEngineStatus(ENGINE_STATUS_ON_FIRE); @@ -759,7 +783,7 @@ CVehicle::ShufflePassengersToMakeSpace(void) return false; if (pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR) && - IsRoomForPedToLeaveCar(COMPONENT_DOOR_REAR_LEFT, nil)) { + IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) { if (!pPassengers[2] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RR)) { pPassengers[2] = pPassengers[1]; pPassengers[1] = nil; @@ -776,7 +800,7 @@ CVehicle::ShufflePassengersToMakeSpace(void) } if (pPassengers[2] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RR) && - IsRoomForPedToLeaveCar(COMPONENT_DOOR_REAR_RIGHT, nil)) { + IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) { if (!pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR)) { pPassengers[1] = pPassengers[2]; pPassengers[2] = nil; @@ -793,7 +817,7 @@ CVehicle::ShufflePassengersToMakeSpace(void) } if (pPassengers[0] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RF) && - IsRoomForPedToLeaveCar(COMPONENT_DOOR_FRONT_RIGHT, nil)) { + IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) { if (!pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR)) { pPassengers[1] = pPassengers[0]; pPassengers[0] = nil; @@ -977,9 +1001,8 @@ CVehicle::CanPedOpenLocks(CPed *ped) bool CVehicle::CanPedEnterCar(void) { - CVector up = GetUp(); // can't enter when car is on side - if(up.z > 0.1f || up.z < -0.1f){ + if(GetUp().z > 0.1f || GetUp().z < -0.1f){ // also when car is moving too fast if(m_vecMoveSpeed.MagnitudeSqr() > sq(0.2f)) return false; @@ -1172,7 +1195,7 @@ CVehicle::ProcessCarAlarm(void) { uint32 step; - if(m_nAlarmState == 0 || m_nAlarmState == -1) + if(!IsAlarmOn()) return; step = CTimer::GetTimeStepInMilliseconds(); diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index f7205c7d..48546e68 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -28,12 +28,6 @@ enum eCarLock { CARLOCK_SKIP_SHUT_DOORS }; - -enum -{ - BOAT_POS_FRONTSEAT -}; - enum eDoors { DOOR_BONNET = 0, @@ -86,8 +80,8 @@ enum CAR_PIECE_WING_LR, CAR_PIECE_WING_RR, CAR_PIECE_WHEEL_LF, - CAR_PIECE_WHEEL_LR, CAR_PIECE_WHEEL_RF, + CAR_PIECE_WHEEL_LR, CAR_PIECE_WHEEL_RR, CAR_PIECE_WINDSCREEN, }; @@ -109,9 +103,6 @@ enum eFlightModel FLIGHT_MODEL_SEAPLANE }; -// Or Weapon.h? -void FireOneInstantHitRound(CVector *shotSource, CVector *shotTarget, int32 damage); - class CVehicle : public CPhysical { public: @@ -197,7 +188,7 @@ public: bool m_bSirenOrAlarm; int8 m_comedyControlState; CStoredCollPoly m_aCollPolys[2]; // poly which is under front/rear part of car - float m_fSteerRatio; + float m_fSteerInput; eVehicleType m_vehType; static void *operator new(size_t); @@ -274,8 +265,11 @@ public: void InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage); void DoFixedMachineGuns(void); - +#ifdef FIX_BUGS + bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1 && GetStatus() != STATUS_WRECKED; } +#else bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; } +#endif CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); } bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE; } AnimationId GetDriverAnim(void) { return IsCar() && bLowVehicle ? ANIM_CAR_LSIT : (IsBoat() && GetModelIndex() != MI_SPEEDER ? ANIM_DRIVE_BOAT : ANIM_CAR_SIT); } |