diff options
Diffstat (limited to 'src/vehicles')
-rw-r--r-- | src/vehicles/Automobile.cpp | 856 | ||||
-rw-r--r-- | src/vehicles/Automobile.h | 3 | ||||
-rw-r--r-- | src/vehicles/Bike.cpp | 9 | ||||
-rw-r--r-- | src/vehicles/Bike.h | 1 | ||||
-rw-r--r-- | src/vehicles/Boat.cpp | 5 | ||||
-rw-r--r-- | src/vehicles/Cranes.cpp | 10 | ||||
-rw-r--r-- | src/vehicles/DamageManager.cpp | 5 | ||||
-rw-r--r-- | src/vehicles/DamageManager.h | 1 | ||||
-rw-r--r-- | src/vehicles/Door.cpp | 55 | ||||
-rw-r--r-- | src/vehicles/Door.h | 19 | ||||
-rw-r--r-- | src/vehicles/Ferry.h | 13 | ||||
-rw-r--r-- | src/vehicles/HandlingMgr.cpp | 160 | ||||
-rw-r--r-- | src/vehicles/HandlingMgr.h | 93 | ||||
-rw-r--r-- | src/vehicles/Heli.cpp | 2 | ||||
-rw-r--r-- | src/vehicles/Train.cpp | 58 | ||||
-rw-r--r-- | src/vehicles/Transmission.cpp | 119 | ||||
-rw-r--r-- | src/vehicles/Transmission.h | 2 | ||||
-rw-r--r-- | src/vehicles/Vehicle.cpp | 44 | ||||
-rw-r--r-- | src/vehicles/Vehicle.h | 10 |
19 files changed, 729 insertions, 736 deletions
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 041db625..2df57a10 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -102,6 +102,8 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) pHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId); pFlyingHandling = mod_HandlingManager.GetFlyingPointer((tVehicleType)mi->m_handlingId); + m_fEngineInertiaVar1 = 0.0f; + m_fEngineInertiaVar2 = 0.0f; m_auto_unused1 = 20.0f; m_auto_unused2 = 0; @@ -150,7 +152,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) m_fMass = pHandling->fMass; m_fTurnMass = pHandling->fTurnMass; m_vecCentreOfMass = pHandling->CentreOfMass; - m_fAirResistance = pHandling->Dimension.x*pHandling->Dimension.z/m_fMass; + m_fAirResistance = pHandling->fDragMult > 0.01f ? pHandling->fDragMult*0.0005f : pHandling->fDragMult; m_fElasticity = 0.05f; m_fBuoyancy = pHandling->fBuoyancy; @@ -191,12 +193,6 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) m_fTraction = 1.0f; m_fTireTemperature = 1.0f; - CColModel *colModel = mi->GetColModel(); - if(colModel->lines == nil){ - colModel->lines = (CColLine*)RwMalloc(4*sizeof(CColLine)); - colModel->numLines = 4; - } - SetupSuspensionLines(); SetStatus(STATUS_SIMPLE); @@ -256,6 +252,10 @@ CVector vecDAMAGE_ENGINE_POS_BIG(-0.5f, -0.3f, 0.0f); void CAutomobile::ProcessControl(void) { + // TODO(LCS): + // TheCamera can remove service vehicles + // some audio (?) stuff + int i; float wheelRot; CColModel *colModel; @@ -310,7 +310,7 @@ CAutomobile::ProcessControl(void) if(GetStatus() != STATUS_ABANDONED && GetStatus() != STATUS_WRECKED && GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && GetStatus() != STATUS_PLAYER_DISABLED){ switch(GetModelIndex()) - case MI_FBIRANCH: + case MI_FBICAR: case MI_POLICE: case MI_ENFORCER: case MI_SECURICA: @@ -319,16 +319,18 @@ CAutomobile::ProcessControl(void) ScanForCrimes(); } + // TODO(LCS): the fields used by this function are weird + ActivateBombWhenEntered(); + // Process driver - if(pDriver) + if(pDriver){ if(IsUpsideDown() && CanPedEnterCar()){ if(!pDriver->IsPlayer() && !(pDriver->m_leader && pDriver->m_leader->bInVehicle) && pDriver->CharCreatedBy != MISSION_CHAR) pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, this); } - - ActivateBombWhenEntered(); + } // Process passengers if(m_nNumPassengers != 0 && IsUpsideDown() && CanPedEnterCar()){ @@ -351,7 +353,7 @@ CAutomobile::ProcessControl(void) if(strongGrip1 || bCheat3) m_vecCentreOfMass.z = 0.3f*m_aSuspensionSpringLength[0] + -1.0f*m_fHeightAboveRoad; else if(pHandling->Flags & HANDLING_NONPLAYER_STABILISER && GetStatus() == STATUS_PHYSICS) - m_vecCentreOfMass.z = pHandling->CentreOfMass.z - 0.2f*pHandling->Dimension.z; + m_vecCentreOfMass.z = pHandling->CentreOfMass.z + (colModel->boundingBox.min.z - pHandling->CentreOfMass.z)*0.4f; else m_vecCentreOfMass = pHandling->CentreOfMass; @@ -371,11 +373,7 @@ CAutomobile::ProcessControl(void) bool playerRemote = false; switch(GetStatus()){ case STATUS_PLAYER_REMOTE: -#ifdef FIX_BUGS if(CPad::GetPad(0)->CarGunJustDown() && !bDisableRemoteDetonation){ -#else - if(CPad::GetPad(0)->WeaponJustDown() && !bDisableRemoteDetonation){ -#endif BlowUpCar(FindPlayerPed()); CRemote::TakeRemoteControlledCarFromPlayer(); } @@ -394,6 +392,7 @@ CAutomobile::ProcessControl(void) // fall through case STATUS_PLAYER: if(playerRemote || + // TODO(LCS): ped state 64 pDriver && pDriver->GetPedState() != PED_EXIT_CAR && pDriver->GetPedState() != PED_DRAG_FROM_CAR && pDriver->GetPedState() != PED_ARRESTED){ // process control input if controlled by player if(playerRemote || pDriver->m_nPedType == PEDTYPE_PLAYER1) @@ -419,6 +418,8 @@ CAutomobile::ProcessControl(void) }else m_vecCentreOfMass.z = pHandling->CentreOfMass.z; + // TODO(LCS): some in air handling? + if(bHoverCheat) DoHoverSuspensionRatios(); @@ -454,8 +455,6 @@ CAutomobile::ProcessControl(void) m_fBrakePedal = 1.0f; m_fGasPedal = 0.0f; } - if(CPad::GetPad(0)->CarGunJustDown()) - ActivateBomb(); break; case STATUS_SIMPLE: @@ -495,7 +494,7 @@ CAutomobile::ProcessControl(void) m_aSuspensionSpringRatio[1] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[1].surfaceB) == ADHESIVE_SAND || m_aSuspensionSpringRatio[2] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[2].surfaceB) == ADHESIVE_SAND || m_aSuspensionSpringRatio[3] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[3].surfaceB) == ADHESIVE_SAND){ - if(GetModelIndex() != MI_RCBANDIT && GetModelIndex() != MI_SANDKING && GetModelIndex() != MI_BFINJECT){ + if(GetModelIndex() != MI_RCBANDIT /*&& GetModelIndex() != MI_SANDKING*/ && GetModelIndex() != MI_BFINJECT){ bStuckInSand = true; if(CWeather::WetRoads > 0.0f) ApplyMoveForce(m_vecMoveSpeed * -CTimer::GetTimeStep()*SAND_SLOWDOWN*m_fMass * (1.0f-CWeather::WetRoads)); @@ -530,8 +529,10 @@ CAutomobile::ProcessControl(void) m_fSteerAngle = 0.0f; m_fGasPedal = 0.0f; - if(!IsAlarmOn()) - m_nCarHornTimer = 0; + m_nCarHornTimer = 0; + // TODO(LCS): + // CWeapon::::RemovePlayersRemoteDetonatorForThisVehicle + m_pBombRigger = nil; break; case STATUS_PLAYER_DISABLED: @@ -625,14 +626,13 @@ CAutomobile::ProcessControl(void) // special control switch(GetModelIndex()){ - case MI_FIRETRUCK: - FireTruckControl(); - break; + // FireTruckControl in PreRender now case MI_RHINO: TankControl(); BlowUpCarsInPath(); break; - case MI_VOODOO: + // LCS: this is gone but i'm keeping it! + case MI_YARDIE: HydraulicControl(); break; default: @@ -722,7 +722,7 @@ CAutomobile::ProcessControl(void) ApplyTurnSpeed(); } bIsInSafePosition = true; - bIsStuck = false; + bIsStuck = false; } CPhysical::ProcessControl(); @@ -741,6 +741,7 @@ CAutomobile::ProcessControl(void) CVector contactPoints[4]; // relative to model CVector contactSpeeds[4]; // speed at contact points CVector springDirections[4]; // normalized, in world space + float springForces[4]; for(i = 0; i < 4; i++){ // Set spring under certain circumstances @@ -764,10 +765,13 @@ CAutomobile::ProcessControl(void) } // get points and directions if spring is compressed + springDirections[i] = -GetUp(); // springs are always pointing down anyway if(m_aSuspensionSpringRatio[i] < 1.0f){ contactPoints[i] = m_aWheelColPoints[i].point - GetPosition(); - springDirections[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1 - colModel->lines[i].p0); - springDirections[i].Normalise(); +// springDirections[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1 - colModel->lines[i].p0); +// springDirections[i].Normalise(); + }else{ + contactPoints[i] = CVector(0.0f, 0.0f, 0.0f); } } @@ -780,7 +784,7 @@ CAutomobile::ProcessControl(void) ApplySpringCollisionAlt(pHandling->fSuspensionForceLevel, springDirections[i], contactPoints[i], - m_aSuspensionSpringRatio[i], bias, m_aWheelColPoints[i].normal); + m_aSuspensionSpringRatio[i], bias, m_aWheelColPoints[i].normal, springForces[i]); m_aWheelSkidmarkUnk[i] = false; if(m_aWheelColPoints[i].surfaceB == SURFACE_GRASS || @@ -792,8 +796,8 @@ CAutomobile::ProcessControl(void) m_aWheelSkidmarkUnk[i] = true; }else m_aWheelSkidmarkType[i] = SKIDMARK_NORMAL; - }else{ - contactPoints[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1); +// }else{ +// contactPoints[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1); } } @@ -815,7 +819,7 @@ CAutomobile::ProcessControl(void) // dampen springs for(i = 0; i < 4; i++) if(m_aSuspensionSpringRatio[i] < 0.99999f) - ApplySpringDampening(pHandling->fSuspensionDampingLevel, + ApplySpringDampening(pHandling->fSuspensionDampingLevel, springForces[i], springDirections[i], contactPoints[i], contactSpeeds[i]); // Get speed at contact points again @@ -828,42 +832,6 @@ CAutomobile::ProcessControl(void) } } - bool gripCheat = true; - fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward()); - if(!strongGrip1 && !CVehicle::bCheat3) - gripCheat = false; - float acceleration = pHandling->Transmission.CalculateDriveAcceleration(m_fGasPedal, m_nCurrentGear, m_fChangeGearTime, fwdSpeed, gripCheat); - acceleration /= m_fForceMultiplier; - - if(IsRealHeli() || IsRealPlane()) - acceleration = 0.0f; - - if(bAudioChangingGear && m_fGasPedal > 0.4f && m_fBrakePedal < 0.1f && fwdSpeed > 0.15f && - this == FindPlayerVehicle() && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){ - if(GetStatus() == STATUS_PLAYER && !(pHandling->Flags & HANDLING_IS_BUS)){ - if(m_nBusDoorTimerEnd == 0) - m_nBusDoorTimerEnd = 1000; - else { - uint32 timeStepInMs = CTimer::GetTimeStepInMilliseconds(); - if(m_nBusDoorTimerEnd > timeStepInMs) - m_nBusDoorTimerEnd -= timeStepInMs; - else - m_nBusDoorTimerEnd = 0; - } - } - - if((m_aSuspensionSpringRatio[0] < 1.0f || m_aSuspensionSpringRatio[2] < 1.0f) && - (m_aSuspensionSpringRatio[1] < 1.0f || m_aSuspensionSpringRatio[3] < 1.0f)) - ApplyTurnForce(-GRAVITY*Min(m_fTurnMass, 2500.0f)*GetUp(), -1.0f*GetForward()); - } - - brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep(); - bool neutralHandling = GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && (pHandling->Flags & HANDLING_NEUTRALHANDLING); - float brakeBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fBrakeBias; - float brakeBiasRear = neutralHandling ? 1.0f : 2.0f-pHandling->fBrakeBias; // looks like a bug, but it was correct in III... - float tractionBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fTractionBias; - float tractionBiasRear = neutralHandling ? 1.0f : 2.0f-tractionBiasFront; - // Count how many wheels are touching the ground m_nWheelsOnGround = 0; @@ -894,16 +862,36 @@ CAutomobile::ProcessControl(void) } } + bool gripCheat = true; + fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward()); + if(!strongGrip1 && !CVehicle::bCheat3) + gripCheat = false; + float acceleration = pHandling->Transmission.CalculateDriveAcceleration(m_fGasPedal, m_nCurrentGear, m_fChangeGearTime, fwdSpeed, + &m_fEngineInertiaVar1, &m_fEngineInertiaVar2, m_nDriveWheelsOnGround, gripCheat); + acceleration /= m_fForceMultiplier; + + if(IsRealHeli() || IsRealPlane()) + acceleration = 0.0f; + + if(Abs(acceleration) > 0.0f) + m_fEngineEnergy += Abs(acceleration); + else + m_fEngineEnergy = 0.0f; + float traction; if(GetStatus() == STATUS_PHYSICS) traction = 0.004f * m_fTraction; else traction = 0.004f; - traction *= pHandling->fTractionMultiplier / 4.0f; + traction *= pHandling->GetTractionMultiplier() / 4.0f; traction /= m_fForceMultiplier; if(CVehicle::bCheat3) traction *= 4.0f; + if(FindPlayerVehicle() && FindPlayerVehicle() == this) + if(CPad::GetPad(0)->CarGunJustDown()) + ActivateBomb(); + if(FindPlayerVehicle() != this && (strongGrip1 || CVehicle::bCheat3)){ traction *= 1.2f; acceleration *= 1.4f; @@ -913,448 +901,73 @@ CAutomobile::ProcessControl(void) } } - static float fThrust; - static tWheelState WheelState[4]; - - bool rearWheelsFirst = !!(pHandling->Flags & HANDLING_REARWHEEL_1ST); - - // Process front wheels on ground - first try - - if(!rearWheelsFirst){ - if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){ - float s = Sin(m_fSteerAngle); - float c = Cos(m_fSteerAngle); - - CVector wheelFwd, wheelRight, tmp; - - if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f){ - if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier)) - fThrust = acceleration; - else - fThrust = 0.0f; - - wheelFwd = GetForward(); - wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal; - wheelFwd.Normalise(); - wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal); - wheelRight.Normalise(); - tmp = c*wheelFwd - s*wheelRight; - wheelRight = s*wheelFwd + c*wheelRight; - wheelFwd = tmp; - - 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); - WheelState[CARWHEEL_FRONT_LEFT] = m_aWheelState[CARWHEEL_FRONT_LEFT]; - - if(Damage.GetWheelStatus(CARWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST) - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT], - m_nWheelsOnGround, fThrust, - brake*brakeBiasFront, - adhesion*tractionBiasFront*Damage.m_fWheelDamageEffect, - CARWHEEL_FRONT_LEFT, - &m_aWheelSpeed[CARWHEEL_FRONT_LEFT], - &WheelState[CARWHEEL_FRONT_LEFT], - WHEEL_STATUS_BURST); - else - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT], - m_nWheelsOnGround, fThrust, - brake*brakeBiasFront, - adhesion*tractionBiasFront, - CARWHEEL_FRONT_LEFT, - &m_aWheelSpeed[CARWHEEL_FRONT_LEFT], - &WheelState[CARWHEEL_FRONT_LEFT], - WHEEL_STATUS_OK); - } - - if(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){ - if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier)) - fThrust = acceleration; - else - fThrust = 0.0f; - - wheelFwd = GetForward(); - wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal; - wheelFwd.Normalise(); - wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal); - wheelRight.Normalise(); - tmp = c*wheelFwd - s*wheelRight; - wheelRight = s*wheelFwd + c*wheelRight; - wheelFwd = tmp; - - 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); - WheelState[CARWHEEL_FRONT_RIGHT] = m_aWheelState[CARWHEEL_FRONT_RIGHT]; - - if(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST) - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT], - m_nWheelsOnGround, fThrust, - brake*brakeBiasFront, - adhesion*tractionBiasFront*Damage.m_fWheelDamageEffect, - CARWHEEL_FRONT_RIGHT, - &m_aWheelSpeed[CARWHEEL_FRONT_RIGHT], - &WheelState[CARWHEEL_FRONT_RIGHT], - WHEEL_STATUS_BURST); - else - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT], - m_nWheelsOnGround, fThrust, - brake*brakeBiasFront, - adhesion*tractionBiasFront, - CARWHEEL_FRONT_RIGHT, - &m_aWheelSpeed[CARWHEEL_FRONT_RIGHT], - &WheelState[CARWHEEL_FRONT_RIGHT], - WHEEL_STATUS_OK); - } - } - - // Process front wheels off ground - - if(!IsRealHeli()){ - if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] <= 0.0f){ - if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){ - if(acceleration > 0.0f){ - if(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] < 2.0f) - m_aWheelSpeed[CARWHEEL_FRONT_LEFT] -= 0.2f; - }else{ - if(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] > -2.0f) - m_aWheelSpeed[CARWHEEL_FRONT_LEFT] += 0.1f; - } - }else{ - m_aWheelSpeed[CARWHEEL_FRONT_LEFT] *= 0.95f; - } - m_aWheelRotation[CARWHEEL_FRONT_LEFT] += m_aWheelSpeed[CARWHEEL_FRONT_LEFT]; - } - if(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] <= 0.0f){ - if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){ - if(acceleration > 0.0f){ - if(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] < 2.0f) - m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] -= 0.2f; - }else{ - if(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] > -2.0f) - m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] += 0.1f; - } - }else{ - m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] *= 0.95f; - } - m_aWheelRotation[CARWHEEL_FRONT_RIGHT] += m_aWheelSpeed[CARWHEEL_FRONT_RIGHT]; - } - } - } - - // Process rear wheels - - if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_REAR_RIGHT] > 0.0f){ - CVector wheelFwd = GetForward(); - CVector wheelRight = GetRight(); // overwritten for resp. wheel - - float rearBrake = brake; - float rearTraction = traction; - if(bIsHandbrakeOn){ -#ifdef FIX_BUGS - // Not sure if this is needed, but brake usually has timestep as a factor - rearBrake = 20000.0f * CTimer::GetTimeStepFix(); -#else - rearBrake = 20000.0f; -#endif - if(fwdSpeed > 0.1f && pHandling->Flags & HANDLING_HANDBRAKE_TYRE){ - m_fTireTemperature += 0.005*CTimer::GetTimeStep(); - if(m_fTireTemperature > 2.0f) - m_fTireTemperature = 2.0f; - } - }else if(m_doingBurnout && mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier)){ - rearBrake = 0.0f; - rearTraction = 0.0f; - // BUG: missing timestep - ApplyTurnForce(contactPoints[CARWHEEL_REAR_LEFT], -0.001f*m_fTurnMass*m_fSteerAngle*GetRight()); - }else if(m_fTireTemperature > 1.0f){ - rearTraction *= m_fTireTemperature; - } - - if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f){ - if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier)) - fThrust = acceleration; - else - fThrust = 0.0f; - - wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_LEFT].normal)*m_aWheelColPoints[CARWHEEL_REAR_LEFT].normal; - wheelFwd.Normalise(); - wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_LEFT].normal); - wheelRight.Normalise(); - - m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceA = SURFACE_WHEELBASE; - float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_LEFT])*rearTraction; - if(GetStatus() == STATUS_PLAYER) - adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB); - WheelState[CARWHEEL_REAR_LEFT] = m_aWheelState[CARWHEEL_REAR_LEFT]; - - if(Damage.GetWheelStatus(CARWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST) - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_REAR_LEFT], contactPoints[CARWHEEL_REAR_LEFT], - m_nWheelsOnGround, fThrust, - rearBrake*brakeBiasRear, - adhesion*tractionBiasRear*Damage.m_fWheelDamageEffect, - CARWHEEL_REAR_LEFT, - &m_aWheelSpeed[CARWHEEL_REAR_LEFT], - &WheelState[CARWHEEL_REAR_LEFT], - WHEEL_STATUS_BURST); - else - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_REAR_LEFT], contactPoints[CARWHEEL_REAR_LEFT], - m_nWheelsOnGround, fThrust, - rearBrake*brakeBiasRear, - adhesion*tractionBiasRear, - CARWHEEL_REAR_LEFT, - &m_aWheelSpeed[CARWHEEL_REAR_LEFT], - &WheelState[CARWHEEL_REAR_LEFT], - WHEEL_STATUS_OK); - } - -#ifdef FIX_BUGS - // Shouldn't we reset these after the left wheel? - wheelFwd = GetForward(); - wheelRight = GetRight(); // actually useless -#endif - - if(m_aWheelTimer[CARWHEEL_REAR_RIGHT] > 0.0f){ - if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier)) - fThrust = acceleration; - else - fThrust = 0.0f; - - wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_RIGHT].normal)*m_aWheelColPoints[CARWHEEL_REAR_RIGHT].normal; - wheelFwd.Normalise(); - wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_RIGHT].normal); - wheelRight.Normalise(); - - m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceA = SURFACE_WHEELBASE; - float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_RIGHT])*rearTraction; - if(GetStatus() == STATUS_PLAYER) - adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB); - WheelState[CARWHEEL_REAR_RIGHT] = m_aWheelState[CARWHEEL_REAR_RIGHT]; - - if(Damage.GetWheelStatus(CARWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST) - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_REAR_RIGHT], contactPoints[CARWHEEL_REAR_RIGHT], - m_nWheelsOnGround, fThrust, - rearBrake*brakeBiasRear, - adhesion*tractionBiasRear*Damage.m_fWheelDamageEffect, - CARWHEEL_REAR_RIGHT, - &m_aWheelSpeed[CARWHEEL_REAR_RIGHT], - &WheelState[CARWHEEL_REAR_RIGHT], - WHEEL_STATUS_BURST); - else - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_REAR_RIGHT], contactPoints[CARWHEEL_REAR_RIGHT], - m_nWheelsOnGround, fThrust, - rearBrake*brakeBiasRear, - adhesion*tractionBiasRear, - CARWHEEL_REAR_RIGHT, - &m_aWheelSpeed[CARWHEEL_REAR_RIGHT], - &WheelState[CARWHEEL_REAR_RIGHT], - WHEEL_STATUS_OK); - } - } - - if(m_doingBurnout && mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) && - (m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING || m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING)){ - m_fTireTemperature += 0.001f*CTimer::GetTimeStep(); - if(m_fTireTemperature > 3.0f) - m_fTireTemperature = 3.0f; - }else if(m_fTireTemperature > 1.0f){ - m_fTireTemperature = (m_fTireTemperature - 1.0f)*Pow(0.995f, CTimer::GetTimeStep()) + 1.0f; - } - - // Process rear wheels off ground - - if(!IsRealHeli()){ - if(m_aWheelTimer[CARWHEEL_REAR_LEFT] <= 0.0f){ - if(bIsHandbrakeOn) - m_aWheelSpeed[CARWHEEL_REAR_LEFT] = 0.0f; - else if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){ - if(acceleration > 0.0f){ - if(m_aWheelSpeed[CARWHEEL_REAR_LEFT] < 2.0f) - m_aWheelSpeed[CARWHEEL_REAR_LEFT] -= 0.2f; - }else{ - if(m_aWheelSpeed[CARWHEEL_REAR_LEFT] > -2.0f) - m_aWheelSpeed[CARWHEEL_REAR_LEFT] += 0.1f; - } - }else{ - m_aWheelSpeed[CARWHEEL_REAR_LEFT] *= 0.95f; - } - m_aWheelRotation[CARWHEEL_REAR_LEFT] += m_aWheelSpeed[CARWHEEL_REAR_LEFT]; - } - if(m_aWheelTimer[CARWHEEL_REAR_RIGHT] <= 0.0f){ - if(bIsHandbrakeOn) - m_aWheelSpeed[CARWHEEL_REAR_RIGHT] = 0.0f; - else if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){ - if(acceleration > 0.0f){ - if(m_aWheelSpeed[CARWHEEL_REAR_RIGHT] < 2.0f) - m_aWheelSpeed[CARWHEEL_REAR_RIGHT] -= 0.2f; - }else{ - if(m_aWheelSpeed[CARWHEEL_REAR_RIGHT] > -2.0f) - m_aWheelSpeed[CARWHEEL_REAR_RIGHT] += 0.1f; - } - }else{ - m_aWheelSpeed[CARWHEEL_REAR_RIGHT] *= 0.95f; + // TODO(LCS): where did this go? +/* + if(bAudioChangingGear && m_fGasPedal > 0.4f && m_fBrakePedal < 0.1f && fwdSpeed > 0.15f && + this == FindPlayerVehicle() && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){ + if(GetStatus() == STATUS_PLAYER && !(pHandling->Flags & HANDLING_IS_BUS)){ + if(m_nBusDoorTimerEnd == 0) + m_nBusDoorTimerEnd = 1000; + else { + uint32 timeStepInMs = CTimer::GetTimeStepInMilliseconds(); + if(m_nBusDoorTimerEnd > timeStepInMs) + m_nBusDoorTimerEnd -= timeStepInMs; + else + m_nBusDoorTimerEnd = 0; } - m_aWheelRotation[CARWHEEL_REAR_RIGHT] += m_aWheelSpeed[CARWHEEL_REAR_RIGHT]; } - } - - // Process front wheels on ground - second try - if(rearWheelsFirst){ - if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){ - float s = Sin(m_fSteerAngle); - float c = Cos(m_fSteerAngle); - - CVector wheelFwd, wheelRight, tmp; - - if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f){ - if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier)) - fThrust = acceleration; - else - fThrust = 0.0f; - - wheelFwd = GetForward(); - wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal; - wheelFwd.Normalise(); - wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal); - wheelRight.Normalise(); - tmp = c*wheelFwd - s*wheelRight; - wheelRight = s*wheelFwd + c*wheelRight; - wheelFwd = tmp; - - 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); - WheelState[CARWHEEL_FRONT_LEFT] = m_aWheelState[CARWHEEL_FRONT_LEFT]; - - if(Damage.GetWheelStatus(CARWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST) - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT], - m_nWheelsOnGround, fThrust, - brake*brakeBiasFront, - adhesion*tractionBiasFront*Damage.m_fWheelDamageEffect, - CARWHEEL_FRONT_LEFT, - &m_aWheelSpeed[CARWHEEL_FRONT_LEFT], - &WheelState[CARWHEEL_FRONT_LEFT], - WHEEL_STATUS_BURST); - else - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT], - m_nWheelsOnGround, fThrust, - brake*brakeBiasFront, - adhesion*tractionBiasFront, - CARWHEEL_FRONT_LEFT, - &m_aWheelSpeed[CARWHEEL_FRONT_LEFT], - &WheelState[CARWHEEL_FRONT_LEFT], - WHEEL_STATUS_OK); - } - - if(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){ - if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier)) - fThrust = acceleration; - else - fThrust = 0.0f; - - wheelFwd = GetForward(); - wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal; - wheelFwd.Normalise(); - wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal); - wheelRight.Normalise(); - tmp = c*wheelFwd - s*wheelRight; - wheelRight = s*wheelFwd + c*wheelRight; - wheelFwd = tmp; - - 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); - WheelState[CARWHEEL_FRONT_RIGHT] = m_aWheelState[CARWHEEL_FRONT_RIGHT]; - - if(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST) - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT], - m_nWheelsOnGround, fThrust, - brake*brakeBiasFront, - adhesion*tractionBiasFront*Damage.m_fWheelDamageEffect, - CARWHEEL_FRONT_RIGHT, - &m_aWheelSpeed[CARWHEEL_FRONT_RIGHT], - &WheelState[CARWHEEL_FRONT_RIGHT], - WHEEL_STATUS_BURST); - else - ProcessWheel(wheelFwd, wheelRight, - contactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT], - m_nWheelsOnGround, fThrust, - brake*brakeBiasFront, - adhesion*tractionBiasFront, - CARWHEEL_FRONT_RIGHT, - &m_aWheelSpeed[CARWHEEL_FRONT_RIGHT], - &WheelState[CARWHEEL_FRONT_RIGHT], - WHEEL_STATUS_OK); - } + if((m_aSuspensionSpringRatio[0] < 1.0f || m_aSuspensionSpringRatio[2] < 1.0f) && + (m_aSuspensionSpringRatio[1] < 1.0f || m_aSuspensionSpringRatio[3] < 1.0f)) + ApplyTurnForce(-GRAVITY*Min(m_fTurnMass, 2500.0f)*GetUp(), -1.0f*GetForward()); } +*/ + + float steerRange; + if(fwdSpeed > 0.01f && m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f && m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f && GetStatus() == STATUS_PLAYER){ + CColPoint point; + point.surfaceA = SURFACE_WHEELBASE; + point.surfaceB = SURFACE_TARMAC; + float rightSpeed = DotProduct(m_vecMoveSpeed, GetRight()); + float adhesion = CSurfaceTable::GetAdhesiveLimit(point); + // i have no idea what's going on here + float magic = traction * adhesion * 16.0f / SQR(fwdSpeed); + magic = clamp(magic, -1.0f, 1.0f); + magic = Asin(magic); + if(m_fSteerAngle < 0.0f && rightSpeed > 0.05f || + m_fSteerAngle > 0.0f && rightSpeed < -0.05f || + bIsHandbrakeOn) + steerRange = 1.0f; + else + steerRange = Min(magic/DEGTORAD(pHandling->fSteeringLock), 1.0f); + + }else + steerRange = 1.0f; + m_fSteerAngle *= steerRange; - // Process front wheels off ground + brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep(); - if (!IsRealHeli()) { - if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] <= 0.0f){ - if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){ - if(acceleration > 0.0f){ - if(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] < 2.0f) - m_aWheelSpeed[CARWHEEL_FRONT_LEFT] -= 0.2f; - }else{ - if(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] > -2.0f) - m_aWheelSpeed[CARWHEEL_FRONT_LEFT] += 0.1f; - } - }else{ - m_aWheelSpeed[CARWHEEL_FRONT_LEFT] *= 0.95f; - } - m_aWheelRotation[CARWHEEL_FRONT_LEFT] += m_aWheelSpeed[CARWHEEL_FRONT_LEFT]; - } - if(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] <= 0.0f){ - if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){ - if(acceleration > 0.0f){ - if(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] < 2.0f) - m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] -= 0.2f; - }else{ - if(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] > -2.0f) - m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] += 0.1f; - } - }else{ - m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] *= 0.95f; - } - m_aWheelRotation[CARWHEEL_FRONT_RIGHT] += m_aWheelSpeed[CARWHEEL_FRONT_RIGHT]; - } - } + if(pHandling->Flags & HANDLING_REARWHEEL_1ST){ + ProcessCarWheelPair(CARWHEEL_REAR_LEFT, CARWHEEL_REAR_RIGHT, -999.0f, contactSpeeds, contactPoints, + traction, acceleration, brake, false); + ProcessCarWheelPair(CARWHEEL_FRONT_LEFT, CARWHEEL_FRONT_RIGHT, m_fSteerAngle, contactSpeeds, contactPoints, + traction, acceleration, brake, true); + }else{ + ProcessCarWheelPair(CARWHEEL_FRONT_LEFT, CARWHEEL_FRONT_RIGHT, m_fSteerAngle, contactSpeeds, contactPoints, + traction, acceleration, brake, true); + ProcessCarWheelPair(CARWHEEL_REAR_LEFT, CARWHEEL_REAR_RIGHT, -999.0f, contactSpeeds, contactPoints, + traction, acceleration, brake, false); } for(i = 0; i < 4; i++){ float wheelPos = colModel->lines[i].p0.z; if(m_aSuspensionSpringRatio[i] > 0.0f) wheelPos -= m_aSuspensionSpringRatio[i]*m_aSuspensionSpringLength[i]; - if(GetModelIndex() == MI_VOODOO && bUsingSpecialColModel) + if(GetModelIndex() == MI_YARDIE && bUsingSpecialColModel) // not original LCS m_aWheelPosition[i] = wheelPos; else m_aWheelPosition[i] += (wheelPos - m_aWheelPosition[i])*0.75f; } - for(i = 0; i < 4; i++) - m_aWheelState[i] = WheelState[i]; - if(m_fGasPedal < 0.0f){ - if(m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING) - m_aWheelState[CARWHEEL_REAR_LEFT] = WHEEL_STATE_NORMAL; - if(m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING) - m_aWheelState[CARWHEEL_REAR_RIGHT] = WHEEL_STATE_NORMAL; - } // Process horn @@ -1649,13 +1262,13 @@ CAutomobile::ProcessControl(void) // TODO: make the numbers defines float heading; - if(GetPosition().x > 1950.0f-400.0f){ + if(GetPosition().x > 1950.0f){ if(m_vecMoveSpeed.x > 0.0f) m_vecMoveSpeed.x *= -1.0f; heading = GetForward().Heading(); if(heading > 0.0f) // going west SetHeading(-heading); - }else if(GetPosition().x < -1950.0f-400.0f){ + }else if(GetPosition().x < -1950.0f){ if(m_vecMoveSpeed.x < 0.0f) m_vecMoveSpeed.x *= -1.0f; heading = GetForward().Heading(); @@ -1718,6 +1331,207 @@ CAutomobile::ProcessControl(void) #pragma optimize("", on) +//--LCS: done +void +CAutomobile::ProcessCarWheelPair(int leftWheel, int rightWheel, float steerAngle, CVector *contactSpeeds, CVector *contactPoints, float traction, float acceleration, float brake, bool bFront) +{ + bool driveWheels; + float suspensionBias; + + if(bFront){ + driveWheels = mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier); + suspensionBias = 2.0f*pHandling->fSuspensionBias; + }else{ + driveWheels = mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier); + suspensionBias = 2.0f*(1.0f-pHandling->fSuspensionBias); + + float fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward()); + if(bIsHandbrakeOn && Abs(fwdSpeed) > 0.01f){ +#ifdef FIX_BUGS + // Not sure if this is needed, but brake usually has timestep as a factor + brake = 20000.0f * CTimer::GetTimeStepFix(); +#else + brake = 20000.0f; +#endif +/* + if(fwdSpeed > 0.1f && pHandling->Flags & HANDLING_HANDBRAKE_TYRE){ + m_fTireTemperature += 0.005*CTimer::GetTimeStep(); + if(m_fTireTemperature > 2.0f) + m_fTireTemperature = 2.0f; + } +*/ + }else if(driveWheels && m_doingBurnout){ + brake = 0.0f; + traction = 0.0f; + // BUG: missing timestep + ApplyTurnForce(contactPoints[leftWheel], -0.003f*m_fTurnMass*Min(3000.0f/m_fTurnMass, 1.0f)*m_fSteerAngle*GetRight()); + }else if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier)){ + traction *= m_fTireTemperature; + } + } + + // Wheels on ground + if(m_aWheelTimer[leftWheel] > 0.0f || m_aWheelTimer[rightWheel] > 0.0f){ + CVector wheelFwd, wheelRight; + float s, c; + bool canSteer = steerAngle > -100.0f; + if(canSteer){ + s = Sin(steerAngle); + c = Cos(steerAngle); + } + + bool neutralHandling = GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && (pHandling->Flags & HANDLING_NEUTRALHANDLING); + float brakeBias, tractionBias; + if(bFront){ + brakeBias = neutralHandling ? 1.0f : 2.0f*pHandling->fBrakeBias; + tractionBias = neutralHandling ? 1.0f : 2.0f*pHandling->fTractionBias; + }else{ + brakeBias = neutralHandling ? 1.0f : 2.0f*(1.0f-pHandling->fBrakeBias); + tractionBias = neutralHandling ? 1.0f : 2.0f*(1.0f-pHandling->fTractionBias); + } + + if(m_aWheelTimer[leftWheel] > 0.0f){ + float fThrust = driveWheels ? acceleration : 0.0f; + + wheelFwd = GetForward(); + wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[leftWheel].normal)*m_aWheelColPoints[leftWheel].normal; + wheelFwd.Normalise(); + wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[leftWheel].normal); + wheelRight.Normalise(); + if(canSteer){ + CVector tmp = c*wheelFwd - s*wheelRight; + wheelRight = s*wheelFwd + c*wheelRight; + wheelFwd = tmp; + } + + m_aWheelColPoints[leftWheel].surfaceA = SURFACE_WHEELBASE; + float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[leftWheel])*traction; + if(GetStatus() == STATUS_PLAYER){ + adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[leftWheel].surfaceB); + adhesion *= Min(suspensionBias*pHandling->fSuspensionForceLevel*4.0f*(1.0f-m_aSuspensionSpringRatio[leftWheel]), 2.0f); + } + tWheelState WheelState = m_aWheelState[leftWheel]; + if(Damage.GetWheelStatus(leftWheel) == WHEEL_STATUS_BURST) + ProcessWheel(wheelFwd, wheelRight, + contactSpeeds[leftWheel], contactPoints[leftWheel], + m_nWheelsOnGround, fThrust, + brake*brakeBias, + adhesion*tractionBias*Damage.m_fWheelDamageEffect, + leftWheel, + &m_aWheelRotation[leftWheel], + &WheelState, + WHEEL_STATUS_BURST); + else + ProcessWheel(wheelFwd, wheelRight, + contactSpeeds[leftWheel], contactPoints[leftWheel], + m_nWheelsOnGround, fThrust, + brake*brakeBias, + adhesion*tractionBias, + leftWheel, + &m_aWheelRotation[leftWheel], + &WheelState, + WHEEL_STATUS_OK); + + if(driveWheels && m_fGasPedal < 0.0f && WheelState == WHEEL_STATE_SPINNING) + m_aWheelState[leftWheel] = WHEEL_STATE_NORMAL; + else + m_aWheelState[leftWheel] = WheelState; + } + + if(m_aWheelTimer[rightWheel] > 0.0f){ + float fThrust = driveWheels ? acceleration : 0.0f; + + wheelFwd = GetForward(); + wheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[rightWheel].normal)*m_aWheelColPoints[rightWheel].normal; + wheelFwd.Normalise(); + wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[rightWheel].normal); + wheelRight.Normalise(); + if(canSteer){ + CVector tmp = c*wheelFwd - s*wheelRight; + wheelRight = s*wheelFwd + c*wheelRight; + wheelFwd = tmp; + } + + m_aWheelColPoints[rightWheel].surfaceA = SURFACE_WHEELBASE; + float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[rightWheel])*traction; + if(GetStatus() == STATUS_PLAYER){ + adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[rightWheel].surfaceB); + adhesion *= Min(suspensionBias*pHandling->fSuspensionForceLevel*4.0f*(1.0f-m_aSuspensionSpringRatio[rightWheel]), 2.0f); + } + tWheelState WheelState = m_aWheelState[rightWheel]; + if(Damage.GetWheelStatus(rightWheel) == WHEEL_STATUS_BURST) + ProcessWheel(wheelFwd, wheelRight, + contactSpeeds[rightWheel], contactPoints[rightWheel], + m_nWheelsOnGround, fThrust, + brake*brakeBias, + adhesion*tractionBias*Damage.m_fWheelDamageEffect, + rightWheel, + &m_aWheelRotation[rightWheel], + &WheelState, + WHEEL_STATUS_BURST); + else + ProcessWheel(wheelFwd, wheelRight, + contactSpeeds[rightWheel], contactPoints[rightWheel], + m_nWheelsOnGround, fThrust, + brake*brakeBias, + adhesion*tractionBias, + rightWheel, + &m_aWheelRotation[rightWheel], + &WheelState, + WHEEL_STATUS_OK); + + if(driveWheels && m_fGasPedal < 0.0f && WheelState == WHEEL_STATE_SPINNING) + m_aWheelState[rightWheel] = WHEEL_STATE_NORMAL; + else + m_aWheelState[rightWheel] = WheelState; + } + } + + if(!bFront){ + if(m_doingBurnout && driveWheels && + (m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING || m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING)){ + m_fTireTemperature += 0.001f*CTimer::GetTimeStep(); + if(m_fTireTemperature > 3.0f) + m_fTireTemperature = 3.0f; + }else if(m_fTireTemperature > 1.0f){ + m_fTireTemperature = (m_fTireTemperature - 1.0f)*Pow(0.995f, CTimer::GetTimeStep()) + 1.0f; + } + } + + // Process wheels off ground + + if(!IsRealHeli()){ + if(m_aWheelTimer[leftWheel] <= 0.0f){ + if(driveWheels && acceleration != 0.0f){ + if(acceleration > 0.0f){ + if(m_aWheelSpeed[leftWheel] < 1.0f) + m_aWheelSpeed[leftWheel] -= 0.1f; + }else{ + if(m_aWheelSpeed[leftWheel] > -1.0f) + m_aWheelSpeed[leftWheel] += 0.05f; + } + }else{ + m_aWheelSpeed[leftWheel] *= 0.95f; + } + m_aWheelRotation[leftWheel] += m_aWheelSpeed[leftWheel]*CTimer::GetTimeStep(); + } + if(m_aWheelTimer[rightWheel] <= 0.0f){ + if(driveWheels && acceleration != 0.0f){ + if(acceleration > 0.0f){ + if(m_aWheelSpeed[rightWheel] < 1.0f) + m_aWheelSpeed[rightWheel] -= 0.1f; + }else{ + if(m_aWheelSpeed[rightWheel] > -1.0f) + m_aWheelSpeed[rightWheel] += 0.05f; + } + }else{ + m_aWheelSpeed[rightWheel] *= 0.95f; + } + m_aWheelRotation[rightWheel] += m_aWheelSpeed[rightWheel]*CTimer::GetTimeStep(); + } + } +} + void CAutomobile::Teleport(CVector pos) { @@ -1739,6 +1553,11 @@ CAutomobile::PreRender(void) int i, j, n; CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); + if(GetModelIndex() == MI_FIRETRUCK) + FireTruckControl(); + + CVehicle::PreRender(); + if(GetModelIndex() == MI_RHINO && m_aCarNodes[CAR_WINDSCREEN]){ // Rotate Rhino turret CMatrix m; @@ -2045,6 +1864,7 @@ CAutomobile::PreRender(void) if(DotProduct(GetForward(), camDist) > 0.0f || TheCamera.GetLookDirection() == LOOKING_LEFT || TheCamera.GetLookDirection() == LOOKING_RIGHT){ + /* CParticle::AddParticle(PARTICLE_HEATHAZE, pos1, CVector(0.0f, 0.0f, 0.0f)); if(pHandling->Flags & HANDLING_DBL_EXHAUST) CParticle::AddParticle(PARTICLE_HEATHAZE, pos2, CVector(0.0f, 0.0f, 0.0f)); @@ -2052,6 +1872,7 @@ CAutomobile::PreRender(void) CParticle::AddParticle(PARTICLE_HEATHAZE, pos1, CVector(0.0f, 0.0f, 0.0f)); if(pHandling->Flags & HANDLING_DBL_EXHAUST) CParticle::AddParticle(PARTICLE_HEATHAZE, pos2, CVector(0.0f, 0.0f, 0.0f)); + */ } } @@ -2201,8 +2022,7 @@ CAutomobile::PreRender(void) case MI_TAXI: case MI_CABBIE: - case MI_ZEBRA: - case MI_KAUFMAN: + case MI_BORGNINE: if(bTaxiLight){ CVector pos = GetPosition() + GetUp()*0.95f; CCoronas::RegisterCorona((uintptr)this + 21, @@ -3018,6 +2838,7 @@ CAutomobile::Render(void) CEntity::Render(); } +//--LCS: done int32 CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) { @@ -3089,9 +2910,13 @@ static float fMouseCentreRange = 0.35f; static float fMouseSteerSens = -0.0035f; static float fMouseCentreMult = 0.975f; +//--LCS: done except TODO void CAutomobile::ProcessControlInputs(uint8 pad) { + if(this == FindPlayerVehicle() && CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle) + return; + float speed = DotProduct(m_vecMoveSpeed, GetForward()); if(!CPad::GetPad(pad)->GetExitVehicle() || @@ -3102,6 +2927,7 @@ CAutomobile::ProcessControlInputs(uint8 pad) bIsHandbrakeOn = true; // Steer left/right +#if 0 // LCS: removed, need mouse for free cam if(CCamera::m_bUseMouse3rdPerson && !CVehicle::m_bDisableMouseSteering){ if(CPad::GetPad(pad)->GetMouseX() != 0.0f){ m_fSteerInput += fMouseSteerSens*CPad::GetPad(pad)->GetMouseX(); @@ -3114,7 +2940,9 @@ CAutomobile::ProcessControlInputs(uint8 pad) 0.2f*CTimer::GetTimeStep(); nLastControlInput = 0; } - }else{ + }else +#endif + { m_fSteerInput += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerInput)* 0.2f*CTimer::GetTimeStep(); nLastControlInput = 0; @@ -3207,6 +3035,7 @@ CAutomobile::ProcessControlInputs(uint8 pad) // Brake if player isn't in control // BUG: game always uses pad 0 here + // TODO(LCS): more conditions here #ifdef FIX_BUGS if(CPad::GetPad(pad)->ArePlayerControlsDisabled()){ #else @@ -3929,6 +3758,7 @@ CAutomobile::DoDriveByShootings(void) } } +//--LCS: done void CAutomobile::DoHoverSuspensionRatios(void) { @@ -4344,7 +4174,7 @@ CAutomobile::dmgDrawCarCollidingParticles(const CVector &pos, float amount) CGeneral::GetRandomNumberInRange(0.1f, 0.25f)), nil, CGeneral::GetRandomNumberInRange(0.02f, 0.08f), - CVehicleModelInfo::ms_vehicleColourTable[m_currentColour1], + CVehicleModelInfo::mspInfo->ms_vehicleColourTable[m_currentColour1], CGeneral::GetRandomNumberInRange(-40.0f, 40.0f), 0, CGeneral::GetRandomNumberInRange(0.0f, 4.0f)); @@ -5025,6 +4855,7 @@ CAutomobile::ResetSuspension(void) } } +//--LCS: done void CAutomobile::SetupSuspensionLines(void) { @@ -5033,6 +4864,14 @@ CAutomobile::SetupSuspensionLines(void) CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); CColModel *colModel = mi->GetColModel(); + bool adjustColModel; + if(colModel->lines == nil){ + adjustColModel = true; + colModel->lines = new CColLine[4]; + colModel->numLines = 4; + }else + adjustColModel = false; + // Each suspension line starts at the uppermost wheel position // and extends down to the lowermost point on the tyre for(i = 0; i < 4; i++){ @@ -5072,6 +4911,21 @@ CAutomobile::SetupSuspensionLines(void) for(i = 0; i < colModel->numSpheres; i++) colModel->spheres[i].radius = 0.3f; } + + if(pHandling->Flags & HANDLING_FORCE_GRND_CLR && adjustColModel){ + // 0.25 is the min distance between ground and col spheres, everything above it is safe + float safePos = 0.25f - m_fHeightAboveRoad; + for(i = 0; i < colModel->numSpheres; i++){ + CColSphere *sph = &colModel->spheres[i]; + if(sph->center.z - sph->radius < safePos){ + // sphere extends too far down, so move it up + // or decrease the radius for bigger spheres + if(radius > 0.4f) + sph->radius = Max(sph->center.z - safePos, 0.4f); + sph->center.z = safePos + sph->radius; + } + } + } } // called on police cars diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index 16d86917..4f4ab500 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -26,6 +26,8 @@ public: float m_aSuspensionSpringRatioPrev[4]; float m_aWheelTimer[4]; // set to 4.0 when wheel is touching ground, then decremented float m_auto_unused1; + float m_fEngineInertiaVar1; + float m_fEngineInertiaVar2; eSkidmarkType m_aWheelSkidmarkType[4]; bool m_aWheelSkidmarkBloody[4]; bool m_aWheelSkidmarkUnk[4]; @@ -114,6 +116,7 @@ public: float GetHeightAboveRoad(void); void PlayCarHorn(void); + void ProcessCarWheelPair(int leftWheel, int rightWheel, float steerAngle, CVector *contactSpeeds, CVector *contactPoints, float traction, float acceleration, float brake, bool bFront); void FireTruckControl(void); void TankControl(void); void HydraulicControl(void); diff --git a/src/vehicles/Bike.cpp b/src/vehicles/Bike.cpp index 0b6d4e3a..ae567ae2 100644 --- a/src/vehicles/Bike.cpp +++ b/src/vehicles/Bike.cpp @@ -79,9 +79,10 @@ CBike::CBike(int32 id, uint8 CreatedBy) m_bikeAnimType = ASSOCGRP_BIKE_STANDARD; break; case MI_SANCHEZ: + case MI_SANCHEZ2: m_bikeAnimType = ASSOCGRP_BIKE_DIRT; break; - default: assert(0 && "invalid bike model ID"); + default: m_bikeAnimType = ASSOCGRP_BIKE_STANDARD; //assert(0 && "invalid bike model ID"); // TODO } m_vehType = VEHICLE_TYPE_BIKE; @@ -109,7 +110,7 @@ CBike::CBike(int32 id, uint8 CreatedBy) m_fTurnMass = pHandling->fTurnMass; m_vecCentreOfMass = pHandling->CentreOfMass; m_vecCentreOfMass.z = 0.1f; - m_fAirResistance = pHandling->Dimension.x*pHandling->Dimension.z/m_fMass; + m_fAirResistance = pHandling->fDragMult > 0.01f ? pHandling->fDragMult*0.0005f : pHandling->fDragMult; m_fElasticity = 0.05f; m_fBuoyancy = pHandling->fBuoyancy; @@ -133,6 +134,8 @@ CBike::CBike(int32 id, uint8 CreatedBy) bIsOnFire = false; bWheelieCam = false; + bFixedColour = false; // <- figure out actual place (TODO) + m_fTireTemperature = 1.0f; m_fBrakeDestabilization = 0.0f; m_fVelocityChangeForAudio = 0; @@ -1722,7 +1725,7 @@ CBike::PreRender(void) TheCamera.GetLookDirection() == LOOKING_RIGHT) pos1 -= 0.2f*GetForward(); - CParticle::AddParticle(PARTICLE_HEATHAZE, pos1, CVector(0.0f, 0.0f, 0.0f)); + //CParticle::AddParticle(PARTICLE_HEATHAZE, pos1, CVector(0.0f, 0.0f, 0.0f)); } } } diff --git a/src/vehicles/Bike.h b/src/vehicles/Bike.h index 219d8872..611cd11d 100644 --- a/src/vehicles/Bike.h +++ b/src/vehicles/Bike.h @@ -75,6 +75,7 @@ public: uint8 bExtraSpeed : 1; // leaning forward uint8 bIsOnFire : 1; uint8 bWheelieCam : 1; + uint8 bFixedColour : 1; // <- figure out its actual place (TODO) int16 m_doingBurnout; float m_fTireTemperature; float m_fBrakeDestabilization; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index 0bc653c6..3b9290ea 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -71,7 +71,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) m_fMass = pHandling->fMass; m_fTurnMass = pHandling->fTurnMass / 2.0f; m_vecCentreOfMass = pHandling->CentreOfMass; - m_fAirResistance = pHandling->Dimension.x * pHandling->Dimension.z / m_fMass; + m_fAirResistance = pHandling->fDragMult > 0.01f ? pHandling->fDragMult*0.0005f : pHandling->fDragMult; m_fElasticity = 0.1f; m_fBuoyancy = pHandling->fBuoyancy; m_fSteerAngle = 0.0f; @@ -681,6 +681,7 @@ CBoat::ProcessControl(void) } // Spray waterdrops on screen + /* if(TheCamera.GetLookingForwardFirstPerson() && FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && m_nDeltaVolumeUnderWater > 0 && numWaterDropOnScreen < 20){ CVector dropPos; @@ -711,7 +712,7 @@ CBoat::ProcessControl(void) if(CParticle::AddParticle(PARTICLE_WATERDROP, dropPos, dropDir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.15f), dropColor, 0, 0, frm)) numWaterDropOnScreen++; - } + }*/ if(m_fPrevVolumeUnderWater == 0.0f && m_fVolumeUnderWater > 0.0f && GetModelIndex() == MI_SKIMMER){ CVector splashDir(0.0f, 0.0f, 0.25f*speed); diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index b5926867..a675fe4e 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -12,7 +12,7 @@ #include "Object.h" #include "World.h" -#define MAX_DISTANCE_TO_FIND_CRANE (10.0f) +#define MAX_DISTANCE_TO_FIND_CRANE (100.0f) #define CRANE_UPDATE_RADIUS (300.0f) #define CRANE_MOVEMENT_PROCESSING_RADIUS (150.0f) #define CRUSHER_Z (-0.951f) @@ -60,7 +60,8 @@ void CCranes::InitCranes(void) } } } - for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_MAINLAND).first; pNode; pNode = pNode->next) { + // TODO(LCS) + for (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_INDUSTRIAL).first; pNode; pNode = pNode->next) { CEntity* pEntity = (CEntity*)pNode->item; if (MODELID_CRANE_1 == pEntity->GetModelIndex() || MODELID_CRANE_2 == pEntity->GetModelIndex() || @@ -70,6 +71,7 @@ void CCranes::InitCranes(void) MODELID_CRANE_6 == pEntity->GetModelIndex()) AddThisOneCrane(pEntity); } + } void CCranes::AddThisOneCrane(CEntity* pEntity) @@ -462,7 +464,7 @@ bool CCranes::DoesMilitaryCraneHaveThisOneAlready(uint32 mi) case MI_FIRETRUCK: return (CarsCollectedMilitaryCrane & 1); case MI_AMBULAN: return (CarsCollectedMilitaryCrane & 2); case MI_ENFORCER: return (CarsCollectedMilitaryCrane & 4); - case MI_FBIRANCH: return (CarsCollectedMilitaryCrane & 8); + case (uint32)MI_FBIRANCH: return (CarsCollectedMilitaryCrane & 8); case MI_RHINO: return (CarsCollectedMilitaryCrane & 0x10); case MI_BARRACKS: return (CarsCollectedMilitaryCrane & 0x20); case MI_POLICE: return (CarsCollectedMilitaryCrane & 0x40); @@ -477,7 +479,7 @@ void CCranes::RegisterCarForMilitaryCrane(uint32 mi) case MI_FIRETRUCK: CarsCollectedMilitaryCrane |= 1; break; case MI_AMBULAN: CarsCollectedMilitaryCrane |= 2; break; case MI_ENFORCER: CarsCollectedMilitaryCrane |= 4; break; - case MI_FBIRANCH: CarsCollectedMilitaryCrane |= 8; break; + case (uint32)MI_FBIRANCH: CarsCollectedMilitaryCrane |= 8; break; case MI_RHINO: CarsCollectedMilitaryCrane |= 0x10; break; case MI_BARRACKS: CarsCollectedMilitaryCrane |= 0x20; break; case MI_POLICE: CarsCollectedMilitaryCrane |= 0x40; break; diff --git a/src/vehicles/DamageManager.cpp b/src/vehicles/DamageManager.cpp index 8ba235b7..b74e7086 100644 --- a/src/vehicles/DamageManager.cpp +++ b/src/vehicles/DamageManager.cpp @@ -10,7 +10,8 @@ float G_aComponentDamage[] = { 2.5f, 1.25f, 3.2f, 1.4f, 2.5f, 2.8f, 0.5f }; CDamageManager::CDamageManager(void) { ResetDamageStatus(); - m_fWheelDamageEffect = 0.5f; + m_fWheelDamageEffect = 0.65f; + m_bSmashedDoorDoesntClose = false; field_18 = 1; } @@ -136,6 +137,8 @@ void CDamageManager::SetDoorStatus(int32 door, uint32 status) { m_doorStatus[door] = status; + if(m_bSmashedDoorDoesntClose && door != DOOR_BONNET && status == DOOR_STATUS_SMASHED) + m_doorStatus[door] = DOOR_STATUS_SWINGING; } int32 diff --git a/src/vehicles/DamageManager.h b/src/vehicles/DamageManager.h index 312006e3..1f836429 100644 --- a/src/vehicles/DamageManager.h +++ b/src/vehicles/DamageManager.h @@ -81,6 +81,7 @@ class CDamageManager public: float m_fWheelDamageEffect; + bool m_bSmashedDoorDoesntClose; uint8 m_engineStatus; uint8 m_wheelStatus[4]; uint8 m_doorStatus[6]; diff --git a/src/vehicles/Door.cpp b/src/vehicles/Door.cpp index c80965aa..72a30339 100644 --- a/src/vehicles/Door.cpp +++ b/src/vehicles/Door.cpp @@ -168,3 +168,58 @@ CTrainDoor::IsClosed(void) { return m_fPosn == RetTranslationWhenClosed(); } + +bool +CFerryDoor::IsInUse(void) +{ + float translationDifference = m_fPrevPosn - m_fPosn; + m_fPrevPosn = m_fPosn; + return Abs(translationDifference) > 0.002f; +} + +float +CFerryDoor::RetTranslationWhenClosed(void) +{ + if(Abs(m_fClosedPosn) < Abs(m_fOpenPosn)) + return m_fClosedPosn; + else + return m_fOpenPosn; +} + +bool +CFerryDoor::IsClosed(void) +{ + return m_fPosn == RetTranslationWhenClosed(); +} + +float +CFerryDoor::RetTranslationWhenOpen(void) +{ + if(Abs(m_fClosedPosn) < Abs(m_fOpenPosn)) + return m_fOpenPosn; + else + return m_fClosedPosn; +} + +bool +CFerryDoor::IsFullyOpen(void) +{ + if(Abs(m_fPosn) < Abs(RetTranslationWhenOpen()) - 0.5f) + return false; + return true; +} + +void +CFerryDoor::Open(float ratio) +{ + float open; + + m_fPrevPosn = m_fPosn; + open = RetTranslationWhenOpen(); + if(ratio < 1.0f){ + m_fPosn = open*ratio; + }else{ + m_nDoorState = DOORST_OPEN; + m_fPosn = open; + } +}
\ No newline at end of file diff --git a/src/vehicles/Door.h b/src/vehicles/Door.h index 567d3263..da5a3de0 100644 --- a/src/vehicles/Door.h +++ b/src/vehicles/Door.h @@ -67,3 +67,22 @@ public: float RetTranslationWhenOpen(void); void Open(float ratio); }; + + +class CFerryDoor { +private: + float m_fClosedPosn; + float m_fOpenPosn; + int8 m_nDirn; + int8 m_nAxis; + int8 m_nDoorState; + float m_fPosn; + float m_fPrevPosn; +public: + bool IsInUse(void); + float RetTranslationWhenClosed(void); + float RetTranslationWhenOpen(void); + bool IsClosed(void); + bool IsFullyOpen(void); + void Open(float ratio); +};
\ No newline at end of file diff --git a/src/vehicles/Ferry.h b/src/vehicles/Ferry.h new file mode 100644 index 00000000..375dfce1 --- /dev/null +++ b/src/vehicles/Ferry.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Vehicle.h" +#include "Door.h" + +enum eFerryNodes +{ + FERRY_DOOR_FRONT = 1, + FERRY_RAMP_FRONT, + FERRY_DOOR_BACK, + FERRY_RAMP_BACK, + NUM_FERRY_NODES +}; diff --git a/src/vehicles/HandlingMgr.cpp b/src/vehicles/HandlingMgr.cpp index 8438c5c9..b5dc7658 100644 --- a/src/vehicles/HandlingMgr.cpp +++ b/src/vehicles/HandlingMgr.cpp @@ -42,6 +42,7 @@ const char VehicleNames[NUMHANDLINGS][14] = { "RHINO", "BARRACKS", "TRAIN", + "FERRY", "HELI", "DODO", "COACH", @@ -54,66 +55,40 @@ const char VehicleNames[NUMHANDLINGS][14] = { "DEADDODO", "FLATBED", "YANKEE", - "GOLFCART", - "VOODOO", - "WASHING", - "CUBAN", - "ROMERO", - "PACKER", - "ADMIRAL", - "GANGBUR", - "ZEBRA", - "TOPFUN", - "GLENDALE", - "OCEANIC", - "HERMES", - "SABRE1", - "SABRETUR", - "PHEONIX", - "WALTON", - "REGINA", - "COMET", - "DELUXO", - "BURRITO", - "SPAND", - "BAGGAGE", - "KAUFMAN", - "RANCHER", - "FBIRANCH", - "VIRGO", - "GREENWOO", - "HOTRING", - "SANDKING", - "BLISTAC", - "BOXVILLE", - "BENSON", - "DESPERAD", - "LOVEFIST", - "BLOODRA", - "BLOODRB", + "BLISTA", + "BELLYUP", + "MRWONGS", + "YARDIE", + "YAKUZA", + "DIABLOS", + "COLUMB", + "HOODS", + "PANLANT", + "BORGNINE", + "CAMPVAN", + "BALLOT", + "SPIDER", + "SHELBY", + "PONTIAC", + "ESPRIT", + "MINI", + "HOTROD", + "SINDACCO", + "FORELLI", "BIKE", "MOPED", "DIRTBIKE", "ANGEL", + "DIRTBIK2", + "ANGE2", "FREEWAY", "PREDATOR", "SPEEDER", "REEFER", - "RIO", - "SQUALO", - "TROPIC", - "COASTGRD", - "DINGHY", - "MARQUIS", - "CUPBOAT", - "SEAPLANE", - "SPARROW", - "SEASPAR", "MAVERICK", "COASTMAV", "POLMAV", "HUNTER", - "RCBARON", "RCGOBLIN", "RCCOPTER" }; @@ -138,18 +113,17 @@ void cHandlingDataMgr::LoadHandlingData(void) { char *start, *end; - char line[201]; // weird value + char line[300]; char delim[4]; // not sure char *word; int field, handlingId; - int keepGoing; tHandlingData *handling; tFlyingHandlingData *flyingHandling; tBoatHandlingData *boatHandling; tBikeHandlingData *bikeHandling; CFileMgr::SetDir("DATA"); - CFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), "r"); + ssize_t filesz = CFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), "r"); CFileMgr::SetDir(""); start = (char*)work_buff; @@ -158,21 +132,18 @@ cHandlingDataMgr::LoadHandlingData(void) flyingHandling = nil; boatHandling = nil; bikeHandling = nil; - keepGoing = 1; - while(keepGoing){ + while(start < (char*)&work_buff[filesz]){ // find end of line while(*end != '\n') end++; // get line strncpy(line, start, end - start); line[end - start] = '\0'; - start = end+1; - end = start+1; // yeah, this is kinda crappy if(strcmp(line, ";the end") == 0) - keepGoing = 0; + break; else if(line[0] != ';'){ if(line[0] == '!'){ // Bike data @@ -286,19 +257,19 @@ cHandlingDataMgr::LoadHandlingData(void) handling->nIdentifier = (tVehicleType)handlingId; break; case 1: handling->fMass = atof(word); break; - case 2: handling->Dimension.x = atof(word); break; - case 3: handling->Dimension.y = atof(word); break; - case 4: handling->Dimension.z = atof(word); break; - case 5: handling->CentreOfMass.x = atof(word); break; - case 6: handling->CentreOfMass.y = atof(word); break; - case 7: handling->CentreOfMass.z = atof(word); break; - case 8: handling->nPercentSubmerged = atoi(word); break; - case 9: handling->fTractionMultiplier = atof(word); break; - case 10: handling->fTractionLoss = atof(word); break; - case 11: handling->fTractionBias = atof(word); break; - case 12: handling->Transmission.nNumberOfGears = atoi(word); break; - case 13: handling->Transmission.fMaxVelocity = atof(word); break; - case 14: handling->Transmission.fEngineAcceleration = atof(word) * 0.4; break; + case 2: handling->fTurnMass = atof(word); break; + case 3: handling->fDragMult = atof(word); break; + case 4: handling->CentreOfMass.x = atof(word); break; + case 5: handling->CentreOfMass.y = atof(word); break; + case 6: handling->CentreOfMass.z = atof(word); break; + case 7: handling->nPercentSubmerged = atoi(word); break; + case 8: handling->fTractionMultiplier = atof(word); break; + case 9: handling->fTractionLoss = atof(word); break; + case 10: handling->fTractionBias = atof(word); break; + case 11: handling->Transmission.nNumberOfGears = atoi(word); break; + case 12: handling->Transmission.fMaxVelocity = atof(word); break; + case 13: handling->Transmission.fEngineAcceleration = atof(word) * 0.4; break; + case 14: handling->Transmission.fEngineInertia = atof(word); break; case 15: handling->Transmission.nDriveType = word[0]; break; case 16: handling->Transmission.nEngineType = word[0]; break; case 17: handling->fBrakeDeceleration = atof(word); break; @@ -307,25 +278,28 @@ cHandlingDataMgr::LoadHandlingData(void) case 20: handling->fSteeringLock = atof(word); break; case 21: handling->fSuspensionForceLevel = atof(word); break; case 22: handling->fSuspensionDampingLevel = atof(word); break; - case 23: handling->fSeatOffsetDistance = atof(word); break; - case 24: handling->fCollisionDamageMultiplier = atof(word); break; - case 25: handling->nMonetaryValue = atoi(word); break; - case 26: handling->fSuspensionUpperLimit = atof(word); break; - case 27: handling->fSuspensionLowerLimit = atof(word); break; - case 28: handling->fSuspensionBias = atof(word); break; - case 29: handling->fSuspensionAntidiveMultiplier = atof(word); break; - case 30: + // case 23: // fSuspensionHighSpdComDamp unused + case 24: handling->fSuspensionUpperLimit = atof(word); break; + case 25: handling->fSuspensionLowerLimit = atof(word); break; + case 26: handling->fSuspensionBias = atof(word); break; + case 27: handling->fSuspensionAntidiveMultiplier = atof(word); break; + case 28: handling->fSeatOffsetDistance = atof(word); break; + case 29: handling->fCollisionDamageMultiplier = atof(word); break; + case 30: handling->nMonetaryValue = atoi(word); break; + case 31: sscanf(word, "%x", &handling->Flags); - handling->Transmission.Flags = handling->Flags; + // handling->Transmission.Flags = handling->Flags; break; - case 31: handling->FrontLights = atoi(word); break; - case 32: handling->RearLights = atoi(word); break; + case 32: handling->FrontLights = atoi(word); break; + case 33: handling->RearLights = atoi(word); break; } field++; } ConvertDataToGameUnits(handling); } } + start = end+1; + end = start+1; } } @@ -353,12 +327,9 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling) handling->Transmission.fEngineAcceleration *= 1.0f/(50.0f*50.0f); handling->Transmission.fMaxVelocity *= 1000.0f/(60.0f*60.0f * 50.0f); handling->fBrakeDeceleration *= 1.0f/(50.0f*50.0f); - handling->fTurnMass = (sq(handling->Dimension.x) + sq(handling->Dimension.y)) * handling->fMass / 12.0f; - if(handling->fTurnMass < 10.0f) - handling->fTurnMass *= 5.0f; - handling->fInvMass = 1.0f/handling->fMass; - handling->fCollisionDamageMultiplier *= 2000.0f/handling->fMass; - handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * GRAVITY*handling->fMass; + handling->fInvMass = 1.0f/handling->GetMass(); + handling->fCollisionDamageMultiplier = handling->GetCollisionDamageMultiplier() * 2000.0f/handling->GetMass(); + handling->fBuoyancy = 100.0f/handling->nPercentSubmerged * GRAVITY*handling->GetMass(); // Don't quite understand this. What seems to be going on is that // we calculate a drag (air resistance) deceleration for a given velocity and @@ -371,10 +342,13 @@ cHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling) velocity -= 0.01f; // what's the 1/6? a = handling->Transmission.fEngineAcceleration/6.0f; - // no density or drag coefficient here... - float a_drag = 0.5f*SQR(velocity) * handling->Dimension.x*handling->Dimension.z / handling->fMass; - // can't make sense of this... maybe v - v/(drag + 1) ? but that doesn't make so much sense either - b = -velocity * (1.0f/(a_drag + 1.0f) - 1.0f); + // no idea what's happening here + float drag; + if(handling->fDragMult < 0.01f) + drag = 1.0f - 1.0f/(SQR(velocity)*handling->fDragMult + 1.0f); + else + drag = 0.0005f*handling->fDragMult * velocity; + b = velocity * drag; } if(handling->nIdentifier == HANDLING_RCBANDIT){ @@ -420,15 +394,15 @@ cHandlingDataMgr::GetHandlingId(const char *name) tFlyingHandlingData* cHandlingDataMgr::GetFlyingPointer(uint8 id) { - if(id >= HANDLING_SEAPLANE && id <= HANDLING_RCCOPTER) - return &FlyingHandlingData[id-HANDLING_SEAPLANE]; + if(id >= HANDLING_MAVERICK && id <= HANDLING_RCCOPTER) + return &FlyingHandlingData[id-HANDLING_MAVERICK]; return &FlyingHandlingData[0]; } tBoatHandlingData* cHandlingDataMgr::GetBoatPointer(uint8 id) { - if(id >= HANDLING_PREDATOR && id <= HANDLING_SEAPLANE) + if(id >= HANDLING_PREDATOR && id <= HANDLING_MAVERICK) return &BoatHandlingData[id-HANDLING_PREDATOR]; return &BoatHandlingData[0]; } diff --git a/src/vehicles/HandlingMgr.h b/src/vehicles/HandlingMgr.h index 8d290f7d..2d49761c 100644 --- a/src/vehicles/HandlingMgr.h +++ b/src/vehicles/HandlingMgr.h @@ -36,6 +36,7 @@ enum tVehicleType HANDLING_RHINO, HANDLING_BARRACKS, HANDLING_TRAIN, + HANDLING_FERRY, HANDLING_HELI, HANDLING_DODO, HANDLING_COACH, @@ -48,76 +49,51 @@ enum tVehicleType HANDLING_DEADDODO, HANDLING_FLATBED, HANDLING_YANKEE, - HANDLING_GOLFCART, - HANDLING_VOODOO, - HANDLING_WASHING, - HANDLING_CUBAN, - HANDLING_ROMERO, - HANDLING_PACKER, - HANDLING_ADMIRAL, - HANDLING_GANGBUR, - HANDLING_ZEBRA, - HANDLING_TOPFUN, - HANDLING_GLENDALE, - HANDLING_OCEANIC, - HANDLING_HERMES, - HANDLING_SABRE1, - HANDLING_SABRETUR, - HANDLING_PHEONIX, - HANDLING_WALTON, - HANDLING_REGINA, - HANDLING_COMET, - HANDLING_DELUXO, - HANDLING_BURRITO, - HANDLING_SPAND, - HANDLING_BAGGAGE, - HANDLING_KAUFMAN, - HANDLING_RANCHER, - HANDLING_FBIRANCH, - HANDLING_VIRGO, - HANDLING_GREENWOO, - HANDLING_HOTRING, - HANDLING_SANDKING, - HANDLING_BLISTAC, - HANDLING_BOXVILLE, - HANDLING_BENSON, - HANDLING_DESPERAD, - HANDLING_LOVEFIST, - HANDLING_BLOODRA, - HANDLING_BLOODRB, + HANDLING_BLISTA, + HANDLING_BELLYUP, + HANDLING_MRWONGS, + HANDLING_YARDIE, + HANDLING_YAKUZA, + HANDLING_DIABLOS, + HANDLING_COLUMB, + HANDLING_HOODS, + HANDLING_PANLANT, + HANDLING_BORGNINE, + HANDLING_CAMPVAN, + HANDLING_BALLOT, + HANDLING_SPIDER, + HANDLING_SHELBY, + HANDLING_PONTIAC, + HANDLING_ESPRIT, + HANDLING_MINI, + HANDLING_HOTROD, + HANDLING_SINDACCO, + HANDLING_FORELLI, HANDLING_BIKE, HANDLING_MOPED, HANDLING_DIRTBIKE, HANDLING_ANGEL, + HANDLING_DIRTBIK2, + HANDLING_ANGE2, HANDLING_FREEWAY, HANDLING_PREDATOR, HANDLING_SPEEDER, HANDLING_REEFER, - HANDLING_RIO, - HANDLING_SQUALO, - HANDLING_TROPIC, - HANDLING_COASTGRD, - HANDLING_DINGHY, - HANDLING_MARQUIS, - HANDLING_CUPBOAT, - HANDLING_SEAPLANE, // both boat and plane! - HANDLING_SPARROW, - HANDLING_SEASPAR, + HANDLING_MAVERICK, HANDLING_COASTMAV, HANDLING_POLMAV, HANDLING_HUNTER, - HANDLING_RCBARON, HANDLING_RCGOBLIN, HANDLING_RCCOPTER, NUMHANDLINGS, NUMBIKEHANDLINGS = HANDLING_FREEWAY+1 - HANDLING_BIKE, - NUMFLYINGHANDLINGS = HANDLING_RCCOPTER+1 - HANDLING_SEAPLANE, - NUMBOATHANDLINGS = HANDLING_SEAPLANE+1 - HANDLING_PREDATOR, + NUMFLYINGHANDLINGS = HANDLING_RCCOPTER+1 - HANDLING_MAVERICK, + NUMBOATHANDLINGS = HANDLING_REEFER+1 - HANDLING_PREDATOR, }; enum tField // most likely a handling field enum, never used so :shrug: @@ -155,19 +131,21 @@ enum HANDLING_NARROW_FRONTW = 0x2000000, HANDLING_GOOD_INSAND = 0x4000000, HANDLING_UNKNOWN = 0x8000000, // something for helis and planes + HANDLING_FORCE_GRND_CLR = 0x10000000 }; struct tHandlingData { - tVehicleType nIdentifier; float fMass; - float fInvMass; float fTurnMass; - CVector Dimension; + float fTractionMultiplier; + float fCollisionDamageMultiplier; + tVehicleType nIdentifier; + float fInvMass; + float fDragMult; CVector CentreOfMass; int8 nPercentSubmerged; float fBuoyancy; - float fTractionMultiplier; cTransmission Transmission; float fBrakeDeceleration; float fBrakeBias; @@ -182,12 +160,17 @@ struct tHandlingData float fSuspensionLowerLimit; float fSuspensionBias; float fSuspensionAntidiveMultiplier; - float fCollisionDamageMultiplier; uint32 Flags; float fSeatOffsetDistance; int32 nMonetaryValue; int8 FrontLights; int8 RearLights; + int unk[4]; + + float GetMass(void) const { return fMass; } + float GetTurnMass(void) const { return fTurnMass; } + float GetTractionMultiplier(void) const { return fTractionMultiplier; } + float GetCollisionDamageMultiplier(void) const { return fCollisionDamageMultiplier; } }; struct tBikeHandlingData diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index bf14416c..3f01ff41 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -756,7 +756,7 @@ CHeli::InitHelis(void) for(i = 0; i < NUM_HELIS; i++) pHelis[i] = nil; - ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1); + ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&gpTempColModels->ms_colModelPed1); } CHeli* diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp index 5f0cf36a..55be4a20 100644 --- a/src/vehicles/Train.cpp +++ b/src/vehicles/Train.cpp @@ -459,11 +459,11 @@ CTrain::InitTrains(void) CStreaming::LoadAllRequestedModels(false); // El-Train wagons - float wagonPositions[] = { 0.0f, 20.0f, 40.0f, 0.0f, 20.0f }; - int8 firstWagon[] = { 1, 0, 0, 1, 0 }; - int8 lastWagon[] = { 0, 0, 1, 0, 1 }; - int16 wagonGroup[] = { 0, 0, 0, 1, 1 }; - for(i = 0; i < 5; i++){ + float wagonPositions[] = { 0.0f, 20.0f, 0.0f, 20.0f }; + int8 firstWagon[] = { 1, 0, 1, 0 }; + int8 lastWagon[] = { 0, 1, 0, 1 }; + int16 wagonGroup[] = { 0, 0, 1, 1 }; + for(i = 0; i < 4; i++){ train = new CTrain(MI_TRAIN, PERMANENT_VEHICLE); train->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f); train->SetStatus(STATUS_ABANDONED); @@ -650,52 +650,6 @@ 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) -{ -#ifdef GTA_TRAIN - 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; - } - } - } - } -#endif -} - -void CTrain::UpdateTrains(void) { #ifdef GTA_TRAIN @@ -732,8 +686,6 @@ CTrain::UpdateTrains(void) // time offset for each train time += 0x20000/2; } - - ProcessTrainAnnouncements(); } // Update Subway diff --git a/src/vehicles/Transmission.cpp b/src/vehicles/Transmission.cpp index 1aeabfe0..f7851f47 100644 --- a/src/vehicles/Transmission.cpp +++ b/src/vehicles/Transmission.cpp @@ -4,6 +4,7 @@ #include "HandlingMgr.h" #include "Transmission.h" +//--LCS: file done void cTransmission::InitGearRatios(void) { @@ -14,11 +15,14 @@ cTransmission::InitGearRatios(void) memset(Gears, 0, sizeof(Gears)); + float baseVelocity = 0.5f*fMaxVelocity / nNumberOfGears; + float step = (fMaxVelocity - baseVelocity) / nNumberOfGears; + for(i = 1; i <= nNumberOfGears; i++){ pGearRatio0 = &Gears[i-1]; pGearRatio1 = &Gears[i]; - pGearRatio1->fMaxVelocity = (float)i / nNumberOfGears * fMaxVelocity; + pGearRatio1->fMaxVelocity = baseVelocity + i*step; velocityDiff = pGearRatio1->fMaxVelocity - pGearRatio0->fMaxVelocity; @@ -45,9 +49,12 @@ cTransmission::CalculateGearForSimpleCar(float speed, uint8 &gear) pGearRatio = &Gears[gear]; fCurVelocity = speed; - if(speed > pGearRatio->fShiftUpVelocity) - gear++; - else if(speed < pGearRatio->fShiftDownVelocity){ + if(speed > pGearRatio->fShiftUpVelocity){ + if(gear + 1 > nNumberOfGears) + gear = nNumberOfGears; + else + gear++; + }else if(speed < pGearRatio->fShiftDownVelocity){ if(gear - 1 < 0) gear = 0; else @@ -55,6 +62,110 @@ cTransmission::CalculateGearForSimpleCar(float speed, uint8 &gear) } } +float TRANSMISSION_NITROS_INERTIA_MULT = 0.5f; +float TRANSMISSION_AI_CHEAT_INERTIA_MULT = 0.75f; +float TRANSMISSION_NITROS_MULT = 2.0f; +float TRANSMISSION_AI_CHEAT_MULT = 1.2f; +float TRANSMISSION_SMOOTHER_FRAC = 0.85f; +float TRANSMISSION_FREE_ACCELERATION = 0.1f; + +//--LCS: done +float +cTransmission::CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, float *inertiaVar1, float *inertiaVar2, uint8 nDriveWheels, uint8 cheat) +{ + static float fAcceleration = 0.0f; + static float fVelocity; + static float fCheat; + static tGear *pGearRatio; + + fVelocity = velocity; + if(fVelocity < fMaxReverseVelocity) + return 0.0f; + if(fVelocity > fMaxVelocity) + return 0.0f; + fCurVelocity = fVelocity; + + assert(gear <= nNumberOfGears); + + pGearRatio = &Gears[gear]; + if(fVelocity > pGearRatio->fShiftUpVelocity){ + if(gear != 0 || gasPedal > 0.0f){ + gear++; + return CalculateDriveAcceleration(gasPedal, gear, time, fVelocity, nil, nil, 0, false); + } + }else if(fVelocity < pGearRatio->fShiftDownVelocity && gear != 0){ + if(gear != 1 || gasPedal < 0.0f){ + gear--; + return CalculateDriveAcceleration(gasPedal, gear, time, fVelocity, nil, nil, 0, false); + } + } + + float accelMul; + + if(nNumberOfGears == 1){ + accelMul = 1.0f; + }else if(gear == 0){ + accelMul = 4.5f; + }else{ + float f = 1.0f - (gear-1.0f)/(nNumberOfGears-1.0f); + if(Flags & HANDLING_1G_BOOST) + accelMul = SQR(f)*5.0f + 1.0f; + else if(Flags & HANDLING_2G_BOOST) + accelMul = SQR(f)*4.0f + 1.0f; + else + accelMul = SQR(f)*3.0f + 1.0f; + } + + fCheat = 1.0f; + float nitroMult = 1.0f; + if(cheat == 1) + fCheat = TRANSMISSION_AI_CHEAT_MULT; + else if(cheat == 2) + nitroMult = TRANSMISSION_NITROS_MULT; + + fAcceleration = fEngineAcceleration*CTimer::GetTimeStep()*0.4f*accelMul*gasPedal*fCheat*nitroMult; + + if(inertiaVar1 != nil && inertiaVar2 != nil){ + if(nDriveWheels == 0){ + float f = TRANSMISSION_FREE_ACCELERATION*CTimer::GetTimeStep()*Abs(gasPedal)/fEngineInertia; + *inertiaVar1 = Min(*inertiaVar1 + f, 1.0f); + *inertiaVar2 = 0.1f; + }else{ + float var1; + // What is being calculated here? + // TODO: find better names for the inertia vars + if(gear == 0){ + var1 = ((fMaxVelocity/nNumberOfGears)*(1.0f-0.6667f) - fVelocity) / + ((fMaxVelocity/nNumberOfGears)*(1.0f-0.6667f) - Gears[gear].fShiftDownVelocity); + }else if(gear == 1){ + var1 = ((fMaxVelocity/nNumberOfGears)*(1.0f-0.6667f) + fVelocity) / + ((fMaxVelocity/nNumberOfGears)*(1.0f-0.6667f) + Gears[gear].fShiftUpVelocity); + }else{ + var1 = (fVelocity - Gears[gear].fShiftDownVelocity) / + (Gears[gear].fShiftUpVelocity - Gears[gear].fShiftDownVelocity); + } + float inertiaMult = var1 - *inertiaVar1; + if(cheat == 1) + inertiaMult *= TRANSMISSION_AI_CHEAT_INERTIA_MULT; + else if(cheat == 2) + inertiaMult *= TRANSMISSION_NITROS_INERTIA_MULT; + float var2target = 1.0f - inertiaMult*fEngineInertia; + var2target = clamp(var2target, 0.1f, 1.0f); + *inertiaVar2 = (1.0f-TRANSMISSION_SMOOTHER_FRAC)*var2target + TRANSMISSION_SMOOTHER_FRAC*(*inertiaVar2); + *inertiaVar1 = var1; + fAcceleration *= *inertiaVar2; + } + } + + float targetVelocity = Gears[gear].fMaxVelocity*fCheat; + if(Gears[gear].fMaxVelocity < 0.0f && targetVelocity > fVelocity) + fAcceleration *= 1.0f - Min((targetVelocity - fVelocity)/0.05f, 1.0f); + else if(Gears[gear].fMaxVelocity > 0.0f && targetVelocity < fVelocity) + fAcceleration *= 1.0f - Min((fVelocity - targetVelocity)/0.05f, 1.0f); + return fAcceleration; +} + +// TEMP old VC code until we have bikes float cTransmission::CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, bool cheat) { diff --git a/src/vehicles/Transmission.h b/src/vehicles/Transmission.h index a3d15513..8aea7b02 100644 --- a/src/vehicles/Transmission.h +++ b/src/vehicles/Transmission.h @@ -17,6 +17,7 @@ public: int8 nNumberOfGears; uint8 Flags; float fEngineAcceleration; + float fEngineInertia; float fMaxVelocity; float fMaxCruiseVelocity; float fMaxReverseVelocity; @@ -24,5 +25,6 @@ public: void InitGearRatios(void); void CalculateGearForSimpleCar(float speed, uint8 &gear); + float CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, float *inertiaVar1, float *inertiaVar2, uint8 nDriveWheels, uint8 cheat); float CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, bool cheat); }; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 4e6c24ef..a05a32a1 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -133,6 +133,7 @@ CVehicle::CVehicle(uint8 CreatedBy) bCreatedAsPoliceVehicle = false; bRestingOnPhysical = false; bParking = false; + m_bGarageTurnedLightsOff = false; bCanPark = CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.0f; // never true. probably doesn't work very well bIsVan = false; bIsBus = false; @@ -217,8 +218,8 @@ void CVehicle::SetModelIndex(uint32 id) { CEntity::SetModelIndex(id); - m_aExtras[0] = CVehicleModelInfo::ms_compsUsed[0]; - m_aExtras[1] = CVehicleModelInfo::ms_compsUsed[1]; + m_aExtras[0] = CVehicleModelInfo::mspInfo->ms_compsUsed[0]; + m_aExtras[1] = CVehicleModelInfo::mspInfo->ms_compsUsed[1]; m_nNumMaxPassengers = CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(id); } @@ -771,7 +772,9 @@ CVehicle::BladeColSectorList(CPtrList &list, CColModel &rotorColModel, CMatrix & } -float fBurstSpeedMax = 0.3f; +float WS_ALREADY_SPINNING_LOSS = 0.2f; +float WS_TRAC_FRAC_LIMIT = 0.3f; +float fBurstSpeedMax = 0.2f; float fBurstTyreMod = 0.13f; void @@ -799,13 +802,15 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon float contactSpeedFwd = DotProduct(wheelContactSpeed, wheelFwd); float contactSpeedRight = DotProduct(wheelContactSpeed, wheelRight); - if(*wheelState != WHEEL_STATE_NORMAL) + adhesion *= CTimer::GetTimeStep(); + if(*wheelState != WHEEL_STATE_NORMAL){ bAlreadySkidding = true; + adhesion *= pHandling->fTractionLoss; + if(*wheelState == WHEEL_STATE_SPINNING && (GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PLAYER_REMOTE)) + adhesion *= 1.0f - Abs(m_fGasPedal) * WS_ALREADY_SPINNING_LOSS; + } *wheelState = WHEEL_STATE_NORMAL; - adhesion *= CTimer::GetTimeStep(); - if(bAlreadySkidding) - adhesion *= pHandling->fTractionLoss; // moving sideways if(contactSpeedRight != 0.0f){ @@ -845,13 +850,15 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon if(!bBraking){ if(m_fGasPedal < 0.01f){ if(IsBike()) - brake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->fMass + 200.0f); - else if(pHandling->fMass < 500.0f) - brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass; + brake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->GetMass() + 200.0f); + else if(IsPlane()) + brake = 0.0f; + else if(pHandling->GetMass() < 500.0f) + brake = 0.1f * mod_HandlingManager.fWheelFriction / pHandling->GetMass(); else if(GetModelIndex() == MI_RCBANDIT) - brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass; + brake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->GetMass(); else - brake = mod_HandlingManager.fWheelFriction / pHandling->fMass; + brake = mod_HandlingManager.fWheelFriction / pHandling->GetMass(); #ifdef FIX_BUGS brake *= CTimer::GetTimeStepFix(); #endif @@ -875,7 +882,10 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon float speedSq = sq(right) + sq(fwd); if(sq(adhesion) < speedSq){ if(*wheelState != WHEEL_STATE_FIXED){ - if(bDriving && contactSpeedFwd < 0.2f) + float tractionLimit = WS_TRAC_FRAC_LIMIT; + if(contactSpeedFwd > 0.15f && (wheelId == CARWHEEL_FRONT_LEFT || wheelId == CARWHEEL_FRONT_RIGHT)) + tractionLimit *= 2.0f; + if(bDriving && tractionLimit*adhesion < Abs(fwd)) *wheelState = WHEEL_STATE_SPINNING; else *wheelState = WHEEL_STATE_SKIDDING; @@ -883,6 +893,8 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon float l = Sqrt(speedSq); float tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss; + if(*wheelState == WHEEL_STATE_SPINNING && (GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PLAYER_REMOTE)) + tractionLoss *= 1.0f - Abs(m_fGasPedal) * WS_ALREADY_SPINNING_LOSS; right *= adhesion * tractionLoss / l; fwd *= adhesion * tractionLoss / l; } @@ -891,7 +903,7 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon CVector totalSpeed = fwd*wheelFwd + right*wheelRight; CVector turnDirection = totalSpeed; - bool separateTurnForce = false; // BUG: not initialized on PC + bool separateTurnForce = false; if(pHandling->fSuspensionAntidiveMultiplier > 0.0f){ if(bBraking){ separateTurnForce = true; @@ -928,6 +940,7 @@ float fBurstBikeSpeedMax = 0.12f; float fBurstBikeTyreMod = 0.05f; float fTweakBikeWheelTurnForce = 2.0f; +//--LCS: done void CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint, int32 wheelsOnGround, float thrust, float brake, float adhesion, float destabTraction, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus) @@ -1848,8 +1861,7 @@ CVehicle::SetDriver(CPed *driver) case MI_TAXI: case MI_CABBIE: - case MI_ZEBRA: - case MI_KAUFMAN: + case MI_BORGNINE: CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 12; break; diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index 2fb2caf4..db4c598a 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -240,16 +240,19 @@ public: uint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed uint8 bParking : 1; uint8 bCanPark : 1; -#if (!defined GTA_PS2 || defined FIX_BUGS) +#if (!defined GTA_PS2 || defined FIX_BUGS) // <- I think this can be moved back to CAutomobile? uint8 m_bombType : 3; #endif uint8 bDriverLastFrame : 1; + uint8 bRewardVehicle : 1; // 25B_40 int8 m_numPedsUseItAsCover; uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default) int8 m_nPacManPickupsCarried; uint8 m_nRoadblockType; + bool m_bGarageTurnedLightsOff; float m_fHealth; // 1000.0f = full health. 250.0f = fire. 0 -> explode + float m_fEngineEnergy; // TODO(LCS): better name. it adds up acceleration force, so possibly kinetic energy?? uint8 m_nCurrentGear; float m_fChangeGearTime; #if (!defined GTA_PS2 || defined FIX_BUGS) @@ -288,6 +291,7 @@ public: ~CVehicle(void); // from CEntity void SetModelIndex(uint32 id); + void PreRender(void) {} bool SetupLighting(void); void RemoveLighting(bool); void FlagToDestroyWhenNextProcessed(void) {} @@ -384,8 +388,8 @@ public: bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1 && GetStatus() != STATUS_WRECKED; } CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); } - bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA || GetModelIndex() == MI_KAUFMAN; } - bool IsLimo(void) { return GetModelIndex() == MI_STRETCH || GetModelIndex() == MI_LOVEFIST; } + bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE; } + bool IsLimo(void) { return GetModelIndex() == MI_STRETCH; } bool IsRealHeli(void) { return !!(pHandling->Flags & HANDLING_IS_HELI); } bool IsRealPlane(void) { return !!(pHandling->Flags & HANDLING_IS_PLANE); } |