diff options
Diffstat (limited to '')
-rw-r--r-- | src/vehicles/Automobile.cpp | 1488 |
1 files changed, 809 insertions, 679 deletions
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 815b2534..b0f21af7 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -51,6 +51,8 @@ #include "Bike.h" #include "Wanted.h" #include "SaveBuf.h" +#include "Streaming.h" +#include "sampman.h" bool bAllCarCheat; @@ -86,6 +88,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) switch(GetModelIndex()){ case MI_HUNTER: case MI_ANGEL: + case MI_ANGEL2: case MI_FREEWAY: m_nRadioStation = V_ROCK; break; @@ -103,6 +106,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; @@ -148,10 +153,10 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) for(i = 0; i < 6; i++) m_randomValues[i] = CGeneral::GetRandomNumberInRange(-0.15f, 0.15f); - m_fMass = pHandling->fMass; - m_fTurnMass = pHandling->fTurnMass; + m_fMass = pHandling->GetMass(); + m_fTurnMass = pHandling->GetTurnMass(); 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; @@ -192,12 +197,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); @@ -205,6 +204,10 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) m_nNumPassengers = 0; + m_pBombRigger = nil; + m_bombType = CARBOMB_NONE; + bDriverLastFrame = false; + if(m_nDoorLock == CARLOCK_UNLOCKED && (id == MI_POLICE || id == MI_ENFORCER || id == MI_RHINO)) m_nDoorLock = CARLOCK_LOCKED_INITIALLY; @@ -235,6 +238,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) bExplosionProof = true; bBulletProof = true; } + m_vehLCS_2A3 = -1; } void @@ -246,6 +250,8 @@ CAutomobile::SetModelIndex(uint32 id) #define SAND_SLOWDOWN (0.01f) float CAR_BALANCE_MULT = 0.3f; +float CAR_INAIR_ROTF = 0.0007f; +float CAR_INAIR_ROTLIM = 0.02f; float HELI_ROTOR_DOTPROD_LIMIT = 0.95f; CVector vecSeaSparrowGunPos(-0.5f, 2.4f, -0.785f); CVector vecHunterGunPos(0.0f, 4.8f, -1.3f); @@ -263,6 +269,23 @@ CAutomobile::ProcessControl(void) CColModel *colModel; float brake = 0.0f; + if(TheCamera.WorldViewerBeingUsed){ + if(bIsAmbulanceOnDuty){ + bIsAmbulanceOnDuty = false; + CCarCtrl::NumAmbulancesOnDuty--; + } + if(bIsFireTruckOnDuty){ + bIsFireTruckOnDuty = false; + CCarCtrl::NumFiretrucksOnDuty--; + } + } + + if(m_vehLCS_2A3 >= 0){ + m_vehLCS_2A4--; + if(m_vehLCS_2A4 == 0) + m_vehLCS_2A3 = -1; + } + if(bUsingSpecialColModel) colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel; else @@ -312,7 +335,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: @@ -321,16 +344,29 @@ CAutomobile::ProcessControl(void) ScanForCrimes(); } + if (pDriver) { + if (!bDriverLastFrame && m_bombType == CARBOMB_ONIGNITIONACTIVE) { + // If someone enters the car and there is a bomb, detonate + m_nBombTimer = 1000; + m_pBlowUpEntity = m_pBombRigger; + if (m_pBlowUpEntity) + m_pBlowUpEntity->RegisterReference((CEntity**)&m_pBlowUpEntity); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_TICK, 1.0f); + } + bDriverLastFrame = true; + } + else + bDriverLastFrame = false; + // 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()){ @@ -353,7 +389,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; @@ -373,11 +409,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(); } @@ -396,7 +428,8 @@ CAutomobile::ProcessControl(void) // fall through case STATUS_PLAYER: if(playerRemote || - pDriver && pDriver->GetPedState() != PED_EXIT_CAR && pDriver->GetPedState() != PED_DRAG_FROM_CAR && pDriver->GetPedState() != PED_ARRESTED){ + // TODO(LCS): ped state 64 + pDriver && pDriver->GetPedState() != PED_EXIT_CAR && pDriver->GetPedState() != PED_DRAG_FROM_CAR && pDriver->GetPedState() != PED_ARRESTED && pDriver->GetPedState() != PED_STATE64){ // process control input if controlled by player if(playerRemote || pDriver->m_nPedType == PEDTYPE_PLAYER1) ProcessControlInputs(0); @@ -421,6 +454,34 @@ CAutomobile::ProcessControl(void) }else m_vecCentreOfMass.z = pHandling->CentreOfMass.z; + // in air handling + if(m_nWheelsOnGround == 0 && + GetVehicleAppearance() != VEHICLE_APPEARANCE_PLANE && GetVehicleAppearance() != VEHICLE_APPEARANCE_HELI){ + float turnForce = m_fTurnMass * CAR_INAIR_ROTF; + turnForce *= Min(3000.0f/m_fTurnMass, 1.0f); + if(CPad::GetPad(0)->GetHandBrake()){ + float upRot = DotProduct(m_vecTurnSpeed, GetUp()); + if(upRot < CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringLeftRight() < 0.0f || + upRot > -CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringLeftRight() > 0.0f) + ApplyTurnForce(GetRight() * turnForce * (CPad::GetPad(0)->GetSteeringLeftRight()/128.0f) * CTimer::GetTimeStep(), + m_vecCentreOfMass + GetForward()); + }else if(!CPad::GetPad(0)->GetAccelerate()){ + float fwdRot = DotProduct(m_vecTurnSpeed, GetForward()); + if(fwdRot < CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringLeftRight() < 0.0f || + fwdRot > -CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringLeftRight() > 0.0f) + ApplyTurnForce(GetRight() * turnForce * (CPad::GetPad(0)->GetSteeringLeftRight()/128.0f) * CTimer::GetTimeStep(), + m_vecCentreOfMass + GetUp()); + } + + if(!CPad::GetPad(0)->GetAccelerate()){ + float rightRot = DotProduct(m_vecTurnSpeed, GetRight()); + if(rightRot < CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringUpDown() < 0.0f || + rightRot > -CAR_INAIR_ROTLIM && CPad::GetPad(0)->GetSteeringUpDown() > 0.0f) + ApplyTurnForce(GetUp() * turnForce * (CPad::GetPad(0)->GetSteeringUpDown()/128.0f) * CTimer::GetTimeStep(), + m_vecCentreOfMass + GetForward()); + } + } + if(bHoverCheat) DoHoverSuspensionRatios(); @@ -456,8 +517,6 @@ CAutomobile::ProcessControl(void) m_fBrakePedal = 1.0f; m_fGasPedal = 0.0f; } - if(CPad::GetPad(0)->CarGunJustDown()) - ActivateBomb(); break; case STATUS_SIMPLE: @@ -532,8 +591,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: @@ -627,9 +688,7 @@ CAutomobile::ProcessControl(void) // special control switch(GetModelIndex()){ - case MI_FIRETRUCK: - FireTruckControl(); - break; + // FireTruckControl in PreRender now case MI_RHINO: TankControl(); BlowUpCarsInPath(); @@ -724,7 +783,7 @@ CAutomobile::ProcessControl(void) ApplyTurnSpeed(); } bIsInSafePosition = true; - bIsStuck = false; + bIsStuck = false; } CPhysical::ProcessControl(); @@ -743,6 +802,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 @@ -766,10 +826,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); } } @@ -782,7 +845,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 || @@ -794,8 +857,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); } } @@ -817,7 +880,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 @@ -830,42 +893,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; @@ -896,16 +923,48 @@ 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()) { + if (m_bombType == CARBOMB_TIMED) { + m_bombType = CARBOMB_TIMEDACTIVE; + m_nBombTimer = 7000; + m_pBlowUpEntity = FindPlayerPed(); + CGarages::TriggerMessage("GA_12", -1, 3000, -1); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_TIMED_ACTIVATED, 1.0f); + } + else if (m_bombType == CARBOMB_ONIGNITION) { + m_bombType = CARBOMB_ONIGNITIONACTIVE; + CGarages::TriggerMessage("GA_12", -1, 3000, -1); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_ONIGNITION_ACTIVATED, 1.0f); + } + } + if(FindPlayerVehicle() != this && (strongGrip1 || CVehicle::bCheat3)){ traction *= 1.2f; acceleration *= 1.4f; @@ -915,429 +974,67 @@ 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; + // 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; } - }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; - } - m_aWheelRotation[CARWHEEL_REAR_RIGHT] += m_aWheelSpeed[CARWHEEL_REAR_RIGHT]; - } + 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()); } - - // 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; +*/ + + static float magicValue = 4.0f; + if(magicValue > 0.0f){ + float steerRange; + // looks like a bug with the wheel ids here, why only left wheels? + if(fwdSpeed > 0.01f && (m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_REAR_LEFT] > 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 = magicValue * traction * adhesion * 4.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 - 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; + steerRange = Min(magic/DEGTORAD(pHandling->fSteeringLock), 1.0f); + + }else + steerRange = 1.0f; - 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); - } + 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++){ @@ -1349,14 +1046,6 @@ CAutomobile::ProcessControl(void) 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 @@ -1367,7 +1056,7 @@ CAutomobile::ProcessControl(void) if(UsesSiren()){ if(Pads[0].bHornHistory[Pads[0].iCurrHornHistory]){ if(Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+CPad::HORNHISTORY_SIZE-1) % CPad::HORNHISTORY_SIZE] && - Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+CPad::HORNHISTORY_SIZE-2) % CPad::HORNHISTORY_SIZE]) + Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+1) % CPad::HORNHISTORY_SIZE]) m_nCarHornTimer = 1; else m_nCarHornTimer = 0; @@ -1397,10 +1086,14 @@ CAutomobile::ProcessControl(void) if(GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && GetStatus() != STATUS_PHYSICS){ if(IsRealHeli()){ bEngineOn = false; - m_aWheelSpeed[1] = Max(m_aWheelSpeed[1]-0.0005f, 0.0f); - if(GetModelIndex() != MI_RCRAIDER && GetModelIndex() != MI_RCGOBLIN) - if(m_aWheelSpeed[1] < 0.154f && m_aWheelSpeed[1] > 0.0044f) - playRotorSound = true; + if(GetStatus() == STATUS_WRECKED) + m_aWheelSpeed[1] = 0.0f; + else{ + m_aWheelSpeed[1] = Max(m_aWheelSpeed[1]-0.0005f, 0.0f); + if(GetModelIndex() != MI_RCRAIDER && GetModelIndex() != MI_RCGOBLIN) + if(m_aWheelSpeed[1] < 0.154f && m_aWheelSpeed[1] > 0.0044f) + playRotorSound = true; + } } }else if(isPlane && m_vecMoveSpeed.Magnitude() > 0.0f && CTimer::GetTimeStep() > 0.0f){ if(GetModelIndex() == MI_DODO) @@ -1470,7 +1163,7 @@ CAutomobile::ProcessControl(void) source = GetMatrix()*source + Max(DotProduct(m_vecMoveSpeed, GetForward()), 0.0f)*GetForward()*CTimer::GetTimeStep(); gun.FireProjectile(this, &source, 0.0f); - CStats::RoundsFiredByPlayer++; +// CStats::RoundsFiredByPlayer++; DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); m_nGunFiringTime = CTimer::GetTimeInMilliseconds(); // Hunter gun @@ -1480,7 +1173,7 @@ CAutomobile::ProcessControl(void) source = GetMatrix()*source + m_vecMoveSpeed*CTimer::GetTimeStep(); gun.FireInstantHit(this, &source); gun.AddGunshell(this, source, CVector2D(0.0f, 0.1f), 0.025f); - CStats::RoundsFiredByPlayer++; +// CStats::RoundsFiredByPlayer++; DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); m_nGunFiringTime = CTimer::GetTimeInMilliseconds(); } @@ -1492,7 +1185,7 @@ CAutomobile::ProcessControl(void) source = GetMatrix()*source + m_vecMoveSpeed*CTimer::GetTimeStep(); gun.FireInstantHit(this, &source); gun.AddGunshell(this, source, CVector2D(0.0f, 0.1f), 0.025f); - CStats::RoundsFiredByPlayer++; +// CStats::RoundsFiredByPlayer++; DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); m_nGunFiringTime = CTimer::GetTimeInMilliseconds(); } @@ -1593,9 +1286,10 @@ CAutomobile::ProcessControl(void) float suspShake = 0.0f; float surfShake = 0.0f; float speedsq = m_vecMoveSpeed.MagnitudeSqr(); + float wheelSpin = 0.0f; for(i = 0; i < 4; i++){ float suspChange = m_aSuspensionSpringRatioPrev[i] - m_aSuspensionSpringRatio[i]; - if(suspChange > 0.3f && !drivingInSand && speedsq > SQR(0.2f)){ + if(suspChange > 0.1f && !drivingInSand && speedsq > SQR(0.2f)){ if(Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST) DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP_2, suspChange); else @@ -1620,10 +1314,27 @@ CAutomobile::ProcessControl(void) // BUG: this only observes one of the wheels TheCamera.m_bVehicleSuspenHigh = Abs(suspChange) > 0.05f; + if((i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT) && mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) || + (i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT) && mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier)) + wheelSpin += WHEELSPIN_TARGET_RATE; + else if(m_aWheelState[i] == WHEEL_STATE_SPINNING) + wheelSpin += WHEELSPIN_INAIR_TARGET_RATE; + m_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i]; m_aSuspensionSpringRatio[i] = 1.0f; } + if(pHandling->Transmission.nDriveType == '4') + wheelSpin /= 4.0f; + else + wheelSpin /= 2.0f; + float spinChange; + if(wheelSpin < m_fWheelSpin) + spinChange = Pow(WHEELSPIN_FALL_RATE, CTimer::GetTimeStep()); + else + spinChange = Pow(WHEELSPIN_RISE_RATE, CTimer::GetTimeStep()); + m_fWheelSpin = m_fWheelSpin*spinChange + wheelSpin*(1.0f-spinChange); + // Shake pad if(!drivingInSand && (suspShake > 0.0f || surfShake > 0.0f) && GetStatus() == STATUS_PLAYER){ @@ -1651,13 +1362,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(); @@ -1710,17 +1421,262 @@ CAutomobile::ProcessControl(void) CVector(0.0f, 0.0f, 0.0f), nil, 0.7f, col, 0, 0, 0, 3000); if(CWorld::TestSphereAgainstWorld(GetPosition(), 10.0f, this, true, false, false, false, false, false) || - GetPosition().z < 6.0f) + GetPosition().z < 0.0f) if(!bRenderScorched){ // we already know this is true... CExplosion::AddExplosion(this, nil, EXPLOSION_CAR, GetPosition(), 0); bRenderScorched = true; } } + + // The rest was in PreRender + + bool onlyFrontWheels = false; + if(IsRealHeli()){ + // Looks like LCS actually uses fmodf for the angles but VC has a loop... + // top rotor + m_aWheelRotation[1] += m_aWheelSpeed[1]*CTimer::GetTimeStep(); + while(m_aWheelRotation[1] > TWOPI) m_aWheelRotation[1] -= TWOPI; + // rear rotor + m_aWheelRotation[3] += m_aWheelSpeed[1]*CTimer::GetTimeStep(); + while(m_aWheelRotation[3] > TWOPI) m_aWheelRotation[3] -= TWOPI; + onlyFrontWheels = true; + } + + CVehicleModelInfo *mi = GetModelInfo(); + CVector contactPoints[4]; // relative to model + CVector contactSpeeds[4]; // speed at contact points + CVector frontWheelFwd = Multiply3x3(GetMatrix(), CVector(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f)); + CVector rearWheelFwd = GetForward(); + for(i = 0; i < 4; i++){ + if (m_aWheelTimer[i] > 0.0f && (!onlyFrontWheels || i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)) { + contactPoints[i] = m_aWheelColPoints[i].point - GetPosition(); + contactSpeeds[i] = GetSpeed(contactPoints[i]); + if (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT) + m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], frontWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale); + else + m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], rearWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale); + m_aWheelRotation[i] += m_aWheelSpeed[i]; + } + } + + if(GetModelIndex() == MI_DODO){ + ProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT); + ProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT); + }else if(GetModelIndex() == MI_RHINO){ + }else if(IsRealHeli()){ + }else{ + ProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT); + ProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT); + ProcessSwingingDoor(CAR_DOOR_LR, DOOR_REAR_LEFT); + ProcessSwingingDoor(CAR_DOOR_RR, DOOR_REAR_RIGHT); + ProcessSwingingDoor(CAR_BONNET, DOOR_BONNET); + ProcessSwingingDoor(CAR_BOOT, DOOR_BOOT); + } } #pragma optimize("", on) 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) { CWorld::Remove(this); @@ -1735,25 +1691,24 @@ CAutomobile::Teleport(CVector pos) CWorld::Add(this); } +float gHeadlightRange = 25.0f; +float gTaxilightRange = 1.1f; +CVector gHeadlightColour(0.86f, 0.82f, 1.0f); +CVector gTaxilightColour(1.0, 1.0f, 0.5f); + void CAutomobile::PreRender(void) { int i, j, n; CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); - if(GetModelIndex() == MI_RHINO && m_aCarNodes[CAR_WINDSCREEN]){ - // Rotate Rhino turret - CMatrix m; - CVector p; - m.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WINDSCREEN])); - p = m.GetPosition(); - m.SetRotateZ(m_fCarGunLR); - m.Translate(p); - m.UpdateRW(); - } + if(GetModelIndex() == MI_FIRETRUCK) + FireTruckControl(); + + CVehicle::PreRender(); if(GetModelIndex() == MI_RCBANDIT){ - CVector pos = GetMatrix() * CVector(0.218f, -0.444f, 0.391f); + CVector pos = GetMatrix() * CVector(0.218f, -0.3f, 0.0f); CAntennas::RegisterOne((uintptr)this, GetUp(), pos, 1.0f); } @@ -1762,7 +1717,7 @@ CAutomobile::PreRender(void) // Wheel particles - if(GetModelIndex() == MI_DODO || GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR){ + if(GetModelIndex() == MI_DODO){ ; // nothing }else if(GetModelIndex() == MI_RCBANDIT){ for(i = 0; i < 4; i++){ @@ -1958,7 +1913,7 @@ CAutomobile::PreRender(void) // Rain on roof - if(!CCullZones::CamNoRain() && !CCullZones::PlayerNoRain() && + if(!CCullZones::CamNoRain() && !CCullZones::PlayerNoRain() && // LCS has those checks twice, but let's not be silly Abs(fwdSpeed) < 20.0f && CWeather::Rain > 0.02f){ CColModel *colModel = GetColModel(); @@ -1973,7 +1928,7 @@ CAutomobile::PreRender(void) p3 = GetMatrix() * p3; c = (p1 + p2 + p3)/3.0f; - n = 6.0f*CWeather::Rain; + n = 4.5f*CWeather::Rain; for(j = 0; j <= n; j++) CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, c + CVector(CGeneral::GetRandomNumberInRange(-0.4f, 0.4f), CGeneral::GetRandomNumberInRange(-0.4f, 0.4f), 0.0f), @@ -2003,8 +1958,10 @@ CAutomobile::PreRender(void) dir1.y = m_vecMoveSpeed.y; } + bool dblExhaust = false; pos1 = GetMatrix() * exhaustPos; if(pHandling->Flags & HANDLING_DBL_EXHAUST){ + dblExhaust = true; pos2 = exhaustPos; pos2.x = -pos2.x; pos2 = GetMatrix() * pos2; @@ -2013,7 +1970,8 @@ CAutomobile::PreRender(void) static float fumesLimit = 2.0f; if(CGeneral::GetRandomNumberInRange(1.0f, 3.0f)*(m_fGasPedal+1.1f) > fumesLimit) - for(i = 0; i < 4;){ +// for(i = 0; i < 4;) + { CParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos1, dir1); if(pHandling->Flags & HANDLING_DBL_EXHAUST) CParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos2, dir2); @@ -2026,6 +1984,7 @@ CAutomobile::PreRender(void) CParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos2, dir2); } +/* // Fire on Cuban hermes if(GetModelIndex() == MI_CUBAN && i == 1 && m_fGasPedal > 0.9f){ if(m_nCurrentGear == 1 || m_nCurrentGear == 3 && (CTimer::GetTimeInMilliseconds()%1500) > 750){ @@ -2063,6 +2022,7 @@ CAutomobile::PreRender(void) dir2 -= 0.05f*GetRight(); }else i = 99; +*/ } } } @@ -2082,26 +2042,26 @@ CAutomobile::PreRender(void) switch(GetModelIndex()){ case MI_FIRETRUCK: - pos1 = CVector(1.1f, 1.7f, 2.0f); - pos2 = CVector(-1.1f, 1.7f, 2.0f); + pos1 = CVector(0.91f, 1.7f, 1.86f); + pos2 = CVector(-0.91f, 1.7f, 1.86f); r1 = 255; g1 = 0; b1 = 0; r2 = 255; g2 = 255; b2 = 0; break; case MI_AMBULAN: - pos1 = CVector(1.1f, 0.9f, 1.6f); - pos2 = CVector(-1.1f, 0.9f, 1.6f); + pos1 = CVector(0.95f, 0.64f, 1.6f); + pos2 = CVector(-0.95f, 0.64f, 1.6f); r1 = 255; g1 = 0; b1 = 0; r2 = 255; g2 = 255; b2 = 255; break; case MI_POLICE: - pos1 = CVector(0.7f, -0.4f, 1.0f); - pos2 = CVector(-0.7f, -0.4f, 1.0f); + pos1 = CVector(0.47f, -0.4f, 1.0f); + pos2 = CVector(-0.47f, -0.4f, 1.0f); r1 = 255; g1 = 0; b1 = 0; r2 = 0; g2 = 0; b2 = 255; break; case MI_ENFORCER: - pos1 = CVector(1.1f, 0.8f, 1.2f); - pos2 = CVector(-1.1f, 0.8f, 1.2f); + pos1 = CVector(0.7f, 0.98f, 1.55f); + pos2 = CVector(-0.7f, 0.98f, 1.55f); r1 = 255; g1 = 0; b1 = 0; r2 = 0; g2 = 0; b2 = 255; break; @@ -2174,7 +2134,7 @@ CAutomobile::PreRender(void) } break; - case MI_FBIRANCH: + //case MI_FBIRANCH: case MI_VICECHEE: if(m_bSirenOrAlarm){ CVector pos = GetMatrix() * CVector(0.4f, 0.6f, 0.3f); @@ -2200,11 +2160,39 @@ CAutomobile::PreRender(void) break; case MI_TAXI: + if(bTaxiLight){ + CVector pos = GetPosition() + GetForward()*-0.3f + GetUp()*0.9f; + CCoronas::RegisterCorona((uintptr)this + 21, + 128, 128, 0, 255, + pos, 0.8f, 50.0f, + CCoronas::TYPE_NORMAL, + CCoronas::FLARE_NONE, + CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + CPointLights::AddLight(CPointLights::LIGHT_POINT, + pos, CVector(0.0f, 0.0f, 0.0f), gTaxilightRange, + gTaxilightColour.x, gTaxilightColour.y, gTaxilightColour.z, CPointLights::FOG_NONE, true); + } + break; + case MI_CABBIE: - case MI_ZEBRA: + if(bTaxiLight){ + CVector pos = GetPosition() + GetUp()*0.9f; + CCoronas::RegisterCorona((uintptr)this + 21, + 128, 128, 0, 255, + pos, 0.8f, 50.0f, + CCoronas::TYPE_NORMAL, + CCoronas::FLARE_NONE, + CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); + CPointLights::AddLight(CPointLights::LIGHT_POINT, + pos, CVector(0.0f, 0.0f, 0.0f), gTaxilightRange, + gTaxilightColour.x, gTaxilightColour.y, gTaxilightColour.z, CPointLights::FOG_NONE, true); + } + break; + + case MI_BORGNINE: case MI_KAUFMAN: if(bTaxiLight){ - CVector pos = GetPosition() + GetUp()*0.95f; + CVector pos = GetPosition() + GetForward()*-0.3f + GetUp()*0.85f; CCoronas::RegisterCorona((uintptr)this + 21, 128, 128, 0, 255, pos, 0.8f, 50.0f, @@ -2212,8 +2200,8 @@ CAutomobile::PreRender(void) CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); CPointLights::AddLight(CPointLights::LIGHT_POINT, - pos, CVector(0.0f, 0.0f, 0.0f), 10.0f, - 1.0f, 1.0f, 0.5f, CPointLights::FOG_NONE, true); + pos, CVector(0.0f, 0.0f, 0.0f), gTaxilightRange, + gTaxilightColour.x, gTaxilightColour.y, gTaxilightColour.z, CPointLights::FOG_NONE, true); } break; } @@ -2250,7 +2238,8 @@ CAutomobile::PreRender(void) else alarmOff = true; } - if(bEngineOn && bLightsOn || alarmOn || alarmOff){ + bool playerRemote = this == FindPlayerVehicle() && CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle; + if((bEngineOn && bLightsOn && !m_bGarageTurnedLightsOff || alarmOn || alarmOff) && !playerRemote){ CVector lookVector = GetPosition() - TheCamera.GetPosition(); float camDist = lookVector.Magnitude(); if(camDist != 0.0f) @@ -2374,12 +2363,12 @@ CAutomobile::PreRender(void) intensity += 0.4f; size += 0.3f; if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK) - CCoronas::RegisterCorona((uintptr)this + 14, 128*intensity, 128*intensity, 128*intensity, 255, + CCoronas::RegisterCorona((uintptr)this + 2, 128*intensity, 128*intensity, 128*intensity, 255, lightL, size, 50.0f*TheCamera.LODDistMultiplier, CCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle); if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK) - CCoronas::RegisterCorona((uintptr)this + 15, 128*intensity, 128*intensity, 128*intensity, 255, + CCoronas::RegisterCorona((uintptr)this + 3, 128*intensity, 128*intensity, 128*intensity, 255, lightR, size, 50.0f*TheCamera.LODDistMultiplier, CCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle); @@ -2391,23 +2380,23 @@ CAutomobile::PreRender(void) if(alarmOff){ if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK) - CCoronas::RegisterCorona((uintptr)this + 14, 0, 0, 0, 0, + CCoronas::RegisterCorona((uintptr)this + 2, 0, 0, 0, 0, lightL, size, 0.0f, CCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle); if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK) - CCoronas::RegisterCorona((uintptr)this + 15, 0, 0, 0, 0, + CCoronas::RegisterCorona((uintptr)this + 3, 0, 0, 0, 0, lightR, size, 0.0f, CCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle); }else{ if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK) - CCoronas::RegisterCorona((uintptr)this + 14, 128*intensity, 0, 0, 255, + CCoronas::RegisterCorona((uintptr)this + 2, 128*intensity, 0, 0, 255, lightL, size, 50.0f*TheCamera.LODDistMultiplier, CCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle); if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK) - CCoronas::RegisterCorona((uintptr)this + 15, 128*intensity, 0, 0, 255, + CCoronas::RegisterCorona((uintptr)this + 3, 128*intensity, 0, 0, 255, lightR, size, 50.0f*TheCamera.LODDistMultiplier, CCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle); @@ -2433,27 +2422,52 @@ CAutomobile::PreRender(void) CVector pos = GetPosition(); CVector2D fwd(GetForward()); fwd.Normalise(); - float f = headLightPos.y + 6.0f; + float f = headLightPos.y + 7.0f; pos += CVector(f*fwd.x, f*fwd.y, 2.0f); - if(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK || - Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK) + if(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK && + Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK) CShadows::StoreCarLightShadow(this, (uintptr)this + 22, gpShadowHeadLightsTex, &pos, - 7.0f*fwd.x, 7.0f*fwd.y, 5.5f*fwd.y, -5.5f*fwd.x, 45, 45, 45, 7.0f); + 7.0f*fwd.x, 7.0f*fwd.y, -3.5f*fwd.y, 3.5f*fwd.x, 145, 145, 145, 7.0f, true, -0.4f, 1.4f); + else if(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK) + CShadows::StoreCarLightShadow(this, (uintptr)this + 22, gpShadowHeadLightsTex, &pos, + 7.0f*fwd.x, 7.0f*fwd.y, -3.5f*fwd.y, 3.5f*fwd.x, 145, 145, 145, 7.0f, false, 9.9f, 1.4f); + else if(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK) + CShadows::StoreCarLightShadow(this, (uintptr)this + 22, gpShadowHeadLightsTex, &pos, + 7.0f*fwd.x, 7.0f*fwd.y, -3.5f*fwd.y, 3.5f*fwd.x, 145, 145, 145, 7.0f, false, -0.4f, 1.4f); - f = (tailLightPos.y - 2.5f) - (headLightPos.y + 6.0f); + f = (tailLightPos.y - 2.1f) - (headLightPos.y + 7.0f); pos += CVector(f*fwd.x, f*fwd.y, 0.0f); - if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK || - Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK) - CShadows::StoreCarLightShadow(this, (uintptr)this + 25, gpShadowExplosionTex, &pos, - 3.0f, 0.0f, 0.0f, -3.0f, 35, 0, 0, 4.0f); + if(m_fGasPedal < 0.0f){ + if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK && + Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK) + CShadows::StoreCarLightShadow(this, (uintptr)this + 25, gpShadowHeadLightsTex, &pos, + -2.0f*fwd.x, -2.0f*fwd.y, 1.5f*fwd.y, -1.5f*fwd.x, 58, 58, 58, 4.0f, true, -0.5f, 1.5f); + else if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK) + CShadows::StoreCarLightShadow(this, (uintptr)this + 25, gpShadowHeadLightsTex, &pos, + -2.0f*fwd.x, -2.0f*fwd.y, 1.5f*fwd.y, -1.5f*fwd.x, 58, 58, 58, 4.0f, false, 9.9f, 1.5f); + else if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK) + CShadows::StoreCarLightShadow(this, (uintptr)this + 25, gpShadowHeadLightsTex, &pos, + -2.0f*fwd.x, -2.0f*fwd.y, 1.5f*fwd.y, -1.5f*fwd.x, 58, 58, 58, 4.0f, false, -0.5f, 1.5f); + }else{ + if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK && + Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK) + CShadows::StoreCarLightShadow(this, (uintptr)this + 25, gpShadowHeadLightsTex, &pos, + -2.0f*fwd.x, -2.0f*fwd.y, 1.5f*fwd.y, -1.5f*fwd.x, 56, 0, 0, 4.0f, true, -0.5f, 1.5f); + else if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK) + CShadows::StoreCarLightShadow(this, (uintptr)this + 25, gpShadowHeadLightsTex, &pos, + -2.0f*fwd.x, -2.0f*fwd.y, 1.5f*fwd.y, -1.5f*fwd.x, 56, 0, 0, 4.0f, false, 9.9f, 1.5f); + else if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK) + CShadows::StoreCarLightShadow(this, (uintptr)this + 25, gpShadowHeadLightsTex, &pos, + -2.0f*fwd.x, -2.0f*fwd.y, 1.5f*fwd.y, -1.5f*fwd.x, 56, 0, 0, 4.0f, false, -0.5f, 1.5f); + } } if(this == FindPlayerVehicle() && !alarmOff){ if(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK || Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK) CPointLights::AddLight(CPointLights::LIGHT_DIRECTIONAL, GetPosition(), GetForward(), - 20.0f, 1.0f, 1.0f, 1.0f, + gHeadlightRange, gHeadlightColour.x, gHeadlightColour.y, gHeadlightColour.z, FindPlayerVehicle()->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.45f) ? CPointLights::FOG_NORMAL : CPointLights::FOG_NONE, false); CVector pos = GetPosition() - 4.0f*GetForward(); @@ -2461,15 +2475,15 @@ CAutomobile::PreRender(void) Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK) { if(m_fBrakePedal > 0.0f) CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), - 10.0f, 1.0f, 0.0f, 0.0f, + 8.39f, 1.0f, 0.0f, 0.0f, CPointLights::FOG_NONE, false); else CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), - 7.0f, 0.6f, 0.0f, 0.0f, + 5.13f, 0.64f, 0.0f, 0.0f, CPointLights::FOG_NONE, false); } } - }else if(GetStatus() != STATUS_ABANDONED && GetStatus() != STATUS_WRECKED){ + }else if(GetStatus() != STATUS_ABANDONED && GetStatus() != STATUS_WRECKED && !m_bGarageTurnedLightsOff && !playerRemote){ // Lights off CVector lightPos = mi->m_positions[CAR_POS_TAILLIGHTS]; @@ -2538,7 +2552,7 @@ CAutomobile::PreRender(void) else CShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_CAR); - DoSunGlare(); +// DoSunGlare(); // Heli dust if(IsRealHeli() && m_aWheelSpeed[1] > 0.1125f && GetPosition().z < 30.0f){ @@ -2559,31 +2573,13 @@ CAutomobile::PreRender(void) CMatrix mat; CVector pos; - bool onlyFrontWheels = false; - if(IsRealHeli()){ - // top rotor - m_aWheelRotation[1] += m_aWheelSpeed[1]*CTimer::GetTimeStep(); - while(m_aWheelRotation[1] > TWOPI) m_aWheelRotation[1] -= TWOPI; - // rear rotor - m_aWheelRotation[3] += m_aWheelSpeed[1]*CTimer::GetTimeStep(); - while(m_aWheelRotation[3] > TWOPI) m_aWheelRotation[3] -= TWOPI; - onlyFrontWheels = true; - } - - CVector contactPoints[4]; // relative to model - CVector contactSpeeds[4]; // speed at contact points - CVector frontWheelFwd = Multiply3x3(GetMatrix(), CVector(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f)); - CVector rearWheelFwd = GetForward(); - for(i = 0; i < 4; i++){ - if (m_aWheelTimer[i] > 0.0f && (!onlyFrontWheels || i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)) { - contactPoints[i] = m_aWheelColPoints[i].point - GetPosition(); - contactSpeeds[i] = GetSpeed(contactPoints[i]); - if (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT) - m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], frontWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale); - else - m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], rearWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale); - m_aWheelRotation[i] += m_aWheelSpeed[i]; - } + // what's this supposed to be? Rhino doesn't have this node + if(GetModelIndex() == MI_RHINO && m_aCarNodes[CAR_BONNET]){ + mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BONNET])); + pos = mat.GetPosition(); + mat.SetRotateZ(m_fCarGunLR); + mat.Translate(pos); + mat.UpdateRW(); } RwRGBA hoverParticleCol = { 255, 255, 255, 32 }; @@ -2773,9 +2769,6 @@ CAutomobile::PreRender(void) mat.Translate(pos); mat.UpdateRW(); } - - ProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT); - ProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT); }else if(GetModelIndex() == MI_RHINO){ // Front right wheel mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF])); @@ -2849,8 +2842,8 @@ CAutomobile::PreRender(void) }else{ CParticle::AddParticle(PARTICLE_CAR_SPLASH, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].point, 0.3f*m_vecMoveSpeed+0.15f*GetRight()+CVector(0.0f, 0.0f, 0.1f), nil, 0.15f, hoverParticleCol, - CGeneral::GetRandomNumberInRange(0.0f, 90.0f), - CGeneral::GetRandomNumberInRange(0.0f, 10.0f), 1); + CGeneral::GetRandomNumberInRange(0.0f, 10.0f), + CGeneral::GetRandomNumberInRange(0.0f, 90.0f), 1); } #ifdef BETTER_ALLCARSAREDODO_CHEAT } else if (bAllDodosCheat && m_nDriveWheelsOnGround == 0 && m_nDriveWheelsOnGroundPrev == 0) { @@ -2890,8 +2883,8 @@ CAutomobile::PreRender(void) }else{ CParticle::AddParticle(PARTICLE_CAR_SPLASH, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].point, 0.3f*m_vecMoveSpeed-0.15f*GetRight()+CVector(0.0f, 0.0f, 0.1f), nil, 0.15f, hoverParticleCol, - CGeneral::GetRandomNumberInRange(0.0f, 90.0f), - CGeneral::GetRandomNumberInRange(0.0f, 10.0f), 1); + CGeneral::GetRandomNumberInRange(0.0f, 10.0f), + CGeneral::GetRandomNumberInRange(0.0f, 90.0f), 1); } #ifdef BETTER_ALLCARSAREDODO_CHEAT } else if (bAllDodosCheat && m_nDriveWheelsOnGround == 0 && m_nDriveWheelsOnGroundPrev == 0) { @@ -2911,13 +2904,6 @@ CAutomobile::PreRender(void) mat.Scale(mi->m_wheelScale); mat.Translate(pos); mat.UpdateRW(); - - ProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT); - ProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT); - ProcessSwingingDoor(CAR_DOOR_LR, DOOR_REAR_LEFT); - ProcessSwingingDoor(CAR_DOOR_RR, DOOR_REAR_RIGHT); - ProcessSwingingDoor(CAR_BONNET, DOOR_BONNET); - ProcessSwingingDoor(CAR_BOOT, DOOR_BOOT); } if((GetModelIndex() == MI_PHEONIX || GetModelIndex() == MI_BFINJECT) && @@ -2968,6 +2954,7 @@ CAutomobile::Render(void) { CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); + m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 3000; mi->SetVehicleColour(m_currentColour1, m_currentColour2); if(IsRealHeli()){ @@ -3093,6 +3080,9 @@ static float fMouseCentreMult = 0.975f; 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() || @@ -3103,6 +3093,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(); @@ -3115,7 +3106,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; @@ -3209,10 +3202,11 @@ CAutomobile::ProcessControlInputs(uint8 pad) // Brake if player isn't in control // BUG: game always uses pad 0 here #ifdef FIX_BUGS - if(CPad::GetPad(pad)->ArePlayerControlsDisabled()){ + if((CPad::GetPad(pad)->ArePlayerControlsDisabled() || CPad::GetPad(pad)->bApplyBrakes || m_bSuperBrake) && #else - if(CPad::GetPad(0)->ArePlayerControlsDisabled()){ + if((CPad::GetPad(0)->ArePlayerControlsDisabled() || CPad::GetPad(0)->bApplyBrakes || m_bSuperBrake) && #endif + (gMultiplayerSuperBrakeOnPause || m_bSuperBrake)){ m_fBrakePedal = 1.0f; bIsHandbrakeOn = true; m_fGasPedal = 0.0f; @@ -3226,67 +3220,119 @@ CAutomobile::ProcessControlInputs(uint8 pad) } } +// not sure if global variables +float FIRETRUCK_LR_SPEED = 0.05f; +float FIRETRUCK_UD_SPEED = 0.02f; + void CAutomobile::FireTruckControl(void) { if(this == FindPlayerVehicle()){ - if(!CPad::GetPad(0)->GetCarGunFired()) - return; -#ifdef FREE_CAM - if (!CCamera::bFreeCam) -#endif - { - m_fCarGunLR += CPad::GetPad(0)->GetCarGunLeftRight() * 0.00025f * CTimer::GetTimeStep(); - m_fCarGunUD += CPad::GetPad(0)->GetCarGunUpDown() * 0.0001f * CTimer::GetTimeStep(); - } - m_fCarGunUD = Clamp(m_fCarGunUD, 0.05f, 0.3f); - - - CVector cannonPos(0.0f, 1.5f, 1.9f); - cannonPos = GetMatrix() * cannonPos; - CVector cannonDir( - Sin(m_fCarGunLR) * Cos(m_fCarGunUD), - Cos(m_fCarGunLR) * Cos(m_fCarGunUD), - Sin(m_fCarGunUD)); - cannonDir = Multiply3x3(GetMatrix(), cannonDir); - cannonDir.z += (CGeneral::GetRandomNumber()&0xF)/1000.0f; - CWaterCannons::UpdateOne((uintptr)this, &cannonPos, &cannonDir); - }else if(GetStatus() == STATUS_PHYSICS){ - CFire *fire = gFireManager.FindFurthestFire_NeverMindFireMen(GetPosition(), 10.0f, 35.0f); - if(fire == nil) - return; + if(CPad::GetPad(0)->GetCarGunFired()){ + if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING){ + // android code differs + CVector localFront = Multiply3x3(TheCamera.Cams[TheCamera.ActiveCam].Front, GetMatrix()); + float targetDirLR = localFront.Heading(); + float targetDirUD = Atan2(localFront.z, localFront.Magnitude2D()); + + targetDirUD += DEGTORAD(15.0f); + if(m_fCarGunLR + PI < targetDirLR) + targetDirLR -= TWOPI; + else if(m_fCarGunLR - PI > targetDirLR) + targetDirLR += TWOPI; + + if(targetDirLR - m_fCarGunLR > CTimer::GetTimeStep()*FIRETRUCK_LR_SPEED) + m_fCarGunLR += CTimer::GetTimeStep()*FIRETRUCK_LR_SPEED; + else if(targetDirLR - m_fCarGunLR < -CTimer::GetTimeStep()*FIRETRUCK_LR_SPEED) + m_fCarGunLR -= CTimer::GetTimeStep()*FIRETRUCK_LR_SPEED; + else + m_fCarGunLR = targetDirLR; - // Target cannon onto fire - float targetAngle = CGeneral::GetATanOfXY(fire->m_vecPos.x-GetPosition().x, fire->m_vecPos.y-GetPosition().y); - float fwdAngle = CGeneral::GetATanOfXY(GetForward().x, GetForward().y); - float targetCannonAngle = fwdAngle - targetAngle; - float angleDelta = CTimer::GetTimeStep()*0.01f; - float cannonDelta = targetCannonAngle - m_fCarGunLR; - while(cannonDelta < PI) cannonDelta += TWOPI; - while(cannonDelta > PI) cannonDelta -= TWOPI; - if(Abs(cannonDelta) < angleDelta) - m_fCarGunLR = targetCannonAngle; - else if(cannonDelta > 0.0f) - m_fCarGunLR += angleDelta; - else - m_fCarGunLR -= angleDelta; - - // Go up and down a bit - float upDown = Sin((float)(CTimer::GetTimeInMilliseconds() & 0xFFF)/0x1000 * TWOPI); - m_fCarGunUD = 0.2f + 0.2f*upDown; - - // Spray water every once in a while - if((CTimer::GetTimeInMilliseconds()>>10) & 3){ - CVector cannonPos(0.0f, 0.0f, 2.2f); // different position than player's firetruck! - cannonPos = GetMatrix() * cannonPos; - CVector cannonDir( - Sin(m_fCarGunLR) * Cos(m_fCarGunUD), - Cos(m_fCarGunLR) * Cos(m_fCarGunUD), - Sin(m_fCarGunUD)); - cannonDir = Multiply3x3(GetMatrix(), cannonDir); + if(targetDirUD - m_fCarGunUD > CTimer::GetTimeStep()*FIRETRUCK_UD_SPEED) + m_fCarGunUD += CTimer::GetTimeStep()*FIRETRUCK_UD_SPEED; + else if(targetDirUD - m_fCarGunUD < -CTimer::GetTimeStep()*FIRETRUCK_UD_SPEED) + m_fCarGunUD -= CTimer::GetTimeStep()*FIRETRUCK_UD_SPEED; + else + m_fCarGunUD = targetDirUD; + }else{ + m_fCarGunLR -= CPad::GetPad(0)->GetCarGunLeftRight()/128.0f * FIRETRUCK_LR_SPEED * CTimer::GetTimeStep(); + m_fCarGunUD += CPad::GetPad(0)->GetCarGunUpDown()/128.0f * FIRETRUCK_UD_SPEED * CTimer::GetTimeStep(); + } + + if(m_fCarGunLR < -PI) m_fCarGunLR += TWOPI; + else if(m_fCarGunLR > PI) m_fCarGunLR -= TWOPI; + m_fCarGunUD = Clamp(m_fCarGunUD, -0.06f, 0.3f); + + CVector cannonPos, cannonDir; + CVector localOffset(0.0f, 0.75f, 0.0f); + CVector localPos(0.0f, 1.05f, 2.02f); + CMatrix rotMat; + rotMat.SetUnity(); + rotMat.SetRotateZ(m_fCarGunLR); + localOffset = rotMat * localOffset; + localPos += localOffset; + cannonPos = GetMatrix() * localPos; + cannonDir = Multiply3x3(GetMatrix(), CVector(-Sin(m_fCarGunLR) * Cos(m_fCarGunUD), + Cos(m_fCarGunLR) * Cos(m_fCarGunUD), + Sin(m_fCarGunUD))); cannonDir.z += (CGeneral::GetRandomNumber()&0xF)/1000.0f; CWaterCannons::UpdateOne((uintptr)this, &cannonPos, &cannonDir); } + }else if(GetStatus() == STATUS_PHYSICS){ + CFire *fire = gFireManager.FindFurthestFire_NeverMindFireMen(GetPosition(), 10.0f, 35.0f); + if(fire){ + + // Target cannon onto fire + float targetAngle = CGeneral::GetATanOfXY(fire->m_vecPos.x-GetPosition().x, fire->m_vecPos.y-GetPosition().y); + float fwdAngle = CGeneral::GetATanOfXY(GetForward().x, GetForward().y); +#ifdef FIX_BUGS + // angle direction changed but they didn't notice + targetAngle = TWOPI - targetAngle; + fwdAngle = TWOPI - fwdAngle; +#endif + float targetCannonAngle = fwdAngle - targetAngle; + float angleDelta = CTimer::GetTimeStep()*0.01f; + float cannonDelta = CGeneral::LimitRadianAngle(targetCannonAngle - m_fCarGunLR); + if(Abs(cannonDelta) < angleDelta) + m_fCarGunLR = targetCannonAngle; + else if(cannonDelta > 0.0f) + m_fCarGunLR += angleDelta; + else + m_fCarGunLR -= angleDelta; + + // Go up and down a bit + float upDown = Sin((float)(CTimer::GetTimeInMilliseconds() & 0xFFF)/0x1000 * TWOPI); + m_fCarGunUD = 0.2f + 0.2f*upDown; + + // Spray water every once in a while + if((CTimer::GetTimeInMilliseconds()>>10) & 3){ + CVector cannonPos, cannonDir; + CVector localOffset(0.0f, 0.75f, 0.0f); + CVector localPos(0.0f, 1.05f, 2.02f); + CMatrix rotMat; + rotMat.SetUnity(); + rotMat.SetRotateZ(m_fCarGunLR); + localOffset = rotMat * localOffset; + localPos += localOffset; + cannonPos = GetMatrix() * localPos; + cannonDir = Multiply3x3(GetMatrix(), CVector(-Sin(m_fCarGunLR) * Cos(m_fCarGunUD), + Cos(m_fCarGunLR) * Cos(m_fCarGunUD), + Sin(m_fCarGunUD))); + cannonDir.z += (CGeneral::GetRandomNumber()&0xF)/1000.0f; +#ifdef FIX_BUGS + // actual call missing?!? + CWaterCannons::UpdateOne((uintptr)this, &cannonPos, &cannonDir); +#endif + } + } + } + + if(m_aCarNodes[CAR_BUMP_REAR]){ + CMatrix mat(RwFrameGetMatrix(m_aCarNodes[CAR_BUMP_REAR])); + CVector pos = mat.GetPosition(); + mat.SetRotateZ(m_fCarGunLR); + mat.Translate(pos); + mat.UpdateRW(); } } @@ -3307,10 +3353,7 @@ CAutomobile::TankControl(void) // Rotate turret float prevAngle = m_fCarGunLR; -#ifdef FREE_CAM - if(!CCamera::bFreeCam) -#endif - m_fCarGunLR -= CPad::GetPad(0)->GetCarGunLeftRight() * 0.00015f * CTimer::GetTimeStep(); + m_fCarGunLR -= CPad::GetPad(0)->GetCarGunLeftRight() * 0.00015f * CTimer::GetTimeStep(); if(m_fCarGunLR < 0.0f) m_fCarGunLR += TWOPI; @@ -3387,6 +3430,14 @@ CAutomobile::TankControl(void) flashPos += 0.1f*shotDir; CParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.15f, black, 0, 0, 0, lifeSpan); } + + if(m_aCarNodes[CAR_WINDSCREEN]){ + CMatrix mat(RwFrameGetMatrix(m_aCarNodes[CAR_WINDSCREEN])); + CVector pos = mat.GetPosition(); + mat.SetRotateZ(m_fCarGunLR); + mat.Translate(pos); + mat.UpdateRW(); + } } #define HYDRAULIC_UPPER_EXT (-0.16f) @@ -3691,8 +3742,8 @@ CAutomobile::ProcessBuoyancy(void) if(mod_Buoyancy.ProcessBuoyancy(this, m_fBuoyancy, &point, &impulse)){ bTouchingWater = true; - float timeStep = Max(CTimer::GetTimeStep(), 0.01f); - float impulseRatio = impulse.z / (GRAVITY * m_fMass * timeStep); + float timeStep = Max(CTimer::GetTimeStep(), 0.5f); // this seems awfully high + float impulseRatio = impulse.z / ((bIsHeavy?GRAVITY/3.0f:GRAVITY) * m_fMass * timeStep); float waterResistance = Pow(1.0f - 0.05f*impulseRatio, CTimer::GetTimeStep()); m_vecMoveSpeed *= waterResistance; m_vecTurnSpeed *= waterResistance; @@ -3737,8 +3788,11 @@ CAutomobile::ProcessBuoyancy(void) if(pDriver){ pDriver->bIsInWater = true; - if(pDriver->IsPlayer() || !bWaterTight) + if(pDriver->IsPlayer() || !bWaterTight){ + if(pDriver->m_fHealth < 30.0f) + SampleManager.SetMusicFadeVolume(Max(0, SampleManager.GetMusicFadeVolume()-4)); pDriver->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); + } } for(i = 0; i < m_nNumMaxPassengers; i++) if(pPassengers[i]){ @@ -3907,7 +3961,7 @@ CAutomobile::DoDriveByShootings(void) if (!anim || !anim->IsRunning()) { if (CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer) { weapon->FireFromCar(this, lookingLeft, true); - weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70; + weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + weapon->GetInfo()->m_nFiringRate; } } }else{ @@ -4158,14 +4212,14 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) case CAR_PIECE_BUMP_FRONT: GetComponentWorldPosition(CAR_BUMP_FRONT, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_BUMPER_FRONT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_BUMPER_FRONT, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetBumperDamage(CAR_BUMP_FRONT, VEHBUMPER_FRONT); if(m_aCarNodes[CAR_BONNET] && Damage.GetPanelStatus(VEHBUMPER_FRONT) == PANEL_STATUS_MISSING){ case CAR_PIECE_BONNET: GetComponentWorldPosition(CAR_BONNET, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); if(GetModelIndex() != MI_DODO) - if(Damage.ApplyDamage(COMPONENT_DOOR_BONNET, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_DOOR_BONNET, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetDoorDamage(CAR_BONNET, DOOR_BONNET); } break; @@ -4173,13 +4227,13 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) case CAR_PIECE_BUMP_REAR: GetComponentWorldPosition(CAR_BUMP_REAR, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_BUMPER_REAR, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_BUMPER_REAR, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetBumperDamage(CAR_BUMP_REAR, VEHBUMPER_REAR); if(m_aCarNodes[CAR_BOOT] && Damage.GetPanelStatus(VEHBUMPER_REAR) == PANEL_STATUS_MISSING){ case CAR_PIECE_BOOT: GetComponentWorldPosition(CAR_BOOT, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_DOOR_BOOT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_DOOR_BOOT, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetDoorDamage(CAR_BOOT, DOOR_BOOT); } break; @@ -4187,50 +4241,50 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) case CAR_PIECE_DOOR_LF: GetComponentWorldPosition(CAR_DOOR_LF, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_DOOR_FRONT_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_DOOR_FRONT_LEFT, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT); break; case CAR_PIECE_DOOR_RF: GetComponentWorldPosition(CAR_DOOR_RF, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_DOOR_FRONT_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_DOOR_FRONT_RIGHT, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT); break; case CAR_PIECE_DOOR_LR: GetComponentWorldPosition(CAR_DOOR_LR, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_DOOR_REAR_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_DOOR_REAR_LEFT, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT); break; case CAR_PIECE_DOOR_RR: GetComponentWorldPosition(CAR_DOOR_RR, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_DOOR_REAR_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_DOOR_REAR_RIGHT, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT); break; case CAR_PIECE_WING_LF: GetComponentWorldPosition(CAR_WING_LF, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_LEFT, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetPanelDamage(CAR_WING_LF, VEHPANEL_FRONT_LEFT); break; case CAR_PIECE_WING_RF: GetComponentWorldPosition(CAR_WING_RF, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_RIGHT, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetPanelDamage(CAR_WING_RF, VEHPANEL_FRONT_RIGHT); break; case CAR_PIECE_WING_LR: GetComponentWorldPosition(CAR_WING_LR, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_PANEL_REAR_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_PANEL_REAR_LEFT, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetPanelDamage(CAR_WING_LR, VEHPANEL_REAR_LEFT); break; case CAR_PIECE_WING_RR: GetComponentWorldPosition(CAR_WING_RR, pos); dmgDrawCarCollidingParticles(pos, impulse*damageMultiplier); - if(Damage.ApplyDamage(COMPONENT_PANEL_REAR_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)) + if(Damage.ApplyDamage(COMPONENT_PANEL_REAR_RIGHT, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())) SetPanelDamage(CAR_WING_RR, VEHPANEL_REAR_RIGHT); break; @@ -4241,7 +4295,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) break; case CAR_PIECE_WINDSCREEN: - if(Damage.ApplyDamage(COMPONENT_PANEL_WINDSCREEN, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){ + if(Damage.ApplyDamage(COMPONENT_PANEL_WINDSCREEN, impulse*impulseMult, pHandling->GetCollisionDamageMultiplier())){ uint8 oldStatus = Damage.GetPanelStatus(VEHPANEL_WINDSCREEN); SetPanelDamage(CAR_WINDSCREEN, VEHPANEL_WINDSCREEN); if(oldStatus != Damage.GetPanelStatus(VEHPANEL_WINDSCREEN)){ @@ -4252,7 +4306,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) } } - float damage = (impulse-minImpulse)*pHandling->fCollisionDamageMultiplier*0.6f*damageMultiplier; + float damage = (impulse-minImpulse)*pHandling->GetCollisionDamageMultiplier()*0.6f*damageMultiplier; if(GetModelIndex() == MI_SECURICA && m_pDamageEntity && m_pDamageEntity->GetStatus() == STATUS_PLAYER) damage *= 7.0f; @@ -4274,6 +4328,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) int oldHealth = m_fHealth; if(this == FindPlayerVehicle()) + // android has other values here m_fHealth -= bTakeLessDamage ? damage/6.0f : damage/2.0f; else if(bTakeLessDamage) m_fHealth -= damage/12.0f; @@ -4311,6 +4366,35 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece) Damage.SetEngineStatus(100); } } + + if(bHitByTrain){ + for(i = 0; i < PHYSICAL_MAX_COLLISIONRECORDS; i++){ + CVehicle *train = (CVehicle*)m_aCollisionRecords[i]; + if(train && train->IsVehicle() && + train->GetModelIndex() == MI_TRAIN && + train->GetSpeed(CVector(0.0f, 0.0, 0.0f)).MagnitudeSqr() > SQR(0.001f)){ + CPed *ped = KnockPedOutCar(WEAPONTYPE_RAMMEDBYCAR, CAR_DOOR_LF, pDriver); + if(ped){ +//TODO(LCS): ped->NailToSubwayTrack(); + ped->SetDie(); + } + BlowUpCar(train); + } + } + } + + if(pDriver && pDriver->IsPlayer()){ + for(i = 0; i < PHYSICAL_MAX_COLLISIONRECORDS; i++){ + CVehicle *airtrain = (CVehicle*)m_aCollisionRecords[i]; + if(airtrain && airtrain->IsVehicle() && + airtrain->GetModelIndex() == MI_AIRTRAIN){ + CPed *ped = KnockPedOutCar(WEAPONTYPE_RAMMEDBYCAR, CAR_DOOR_LF, pDriver); + if(ped) + ped->SetDie(); + BlowUpCar(airtrain); + } + } + } } void @@ -4339,6 +4423,7 @@ CAutomobile::dmgDrawCarCollidingParticles(const CVector &pos, float amount) CVector(0.0f, 0.0f, 0.0f), nil, 0.5f); n = (int)amount/50 + 1; + n = Min(n, 10); for(i = 0; i < n; i++) CParticle::AddParticle(PARTICLE_CAR_DEBRIS, pos, CVector(CGeneral::GetRandomNumberInRange(-0.25f, 0.25f), @@ -4346,7 +4431,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, 40), 0, CGeneral::GetRandomNumberInRange(0, 4)); @@ -4591,7 +4676,9 @@ CAutomobile::OpenDoor(int32 component, eDoors door, float openRatio) if(Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING) Damage.SetDoorStatus(door, DOOR_STATUS_OK); // huh? ShowAllComps(); - DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_DOOR_CLOSE_BONNET + door, 0.0f); + // TODO(LCS): this makes no sense at all to me + if(component != CAR_DOOR_LR || IsDoorReady(DOOR_REAR_RIGHT)) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_DOOR_CLOSE_BONNET + door, 0.0f); } axes[Doors[door].m_nAxis] = Doors[door].m_fAngle; @@ -4644,6 +4731,19 @@ CAutomobile::ProcessOpenDoor(uint32 component, uint32 anim, float time) { eDoors door; + if(bIsVan){ + if(component == CAR_DOOR_RR){ + if(anim == ANIM_STD_VAN_OPEN_DOOR_REAR_RHS || anim == ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS) + if(IsDoorReady(DOOR_REAR_LEFT)) + ProcessOpenDoor(CAR_DOOR_LR, anim, time); + } + if(component == CAR_DOOR_LR){ + if(anim == ANIM_STD_VAN_OPEN_DOOR_REAR_LHS || anim == ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS) + if(IsDoorReady(DOOR_REAR_RIGHT)) + ProcessOpenDoor(CAR_DOOR_RR, anim, time); + } + } + switch(component){ case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break; case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break; @@ -4665,7 +4765,7 @@ CAutomobile::ProcessOpenDoor(uint32 component, uint32 anim, float time) case ANIM_STD_CAR_CLOSE_DOOR_LO_LHS: case ANIM_STD_CAR_CLOSE_DOOR_RHS: case ANIM_STD_CAR_CLOSE_DOOR_LO_RHS: - ProcessDoorCloseAnimation(this, component, door, time, 0.2f, 0.45f); + ProcessDoorCloseAnimation(this, component, door, time, 0.2f, 0.63f); break; case ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS: case ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS: @@ -4679,7 +4779,7 @@ CAutomobile::ProcessOpenDoor(uint32 component, uint32 anim, float time) break; case ANIM_STD_CAR_CLOSE_LHS: case ANIM_STD_CAR_CLOSE_RHS: - ProcessDoorCloseAnimation(this, component, door, time, 0.1f, 0.23f); + ProcessDoorCloseAnimation(this, component, door, time, 0.35f, 0.5f); break; case ANIM_STD_CAR_PULL_OUT_PED_RHS: case ANIM_STD_CAR_PULL_OUT_PED_LO_RHS: @@ -4996,7 +5096,9 @@ CAutomobile::PlayCarHorn(void) { uint32 r; - if (IsAlarmOn() || m_nCarHornTimer != 0) + if (IsAlarmOn() || + this == FindPlayerVehicle() && CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle || + m_nCarHornTimer != 0) return; if (m_nCarHornDelay) { @@ -5047,6 +5149,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++){ @@ -5086,6 +5196,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 @@ -5108,6 +5233,7 @@ CAutomobile::BlowUpCarsInPath(void) for(i = 0; i < m_nCollisionRecords; i++) if(m_aCollisionRecords[i] && m_aCollisionRecords[i]->IsVehicle() && + IsVehiclePointerValid((CVehicle*)m_aCollisionRecords[i]) && m_aCollisionRecords[i]->GetModelIndex() != MI_RHINO && !m_aCollisionRecords[i]->bRenderScorched){ if(this == FindPlayerVehicle()) @@ -5402,6 +5528,7 @@ CAutomobile::Fix(void) for(component = 0; component < 4; component++) Damage.SetWheelStatus(component, WHEEL_STATUS_OK); +/* if(GetModelIndex() == MI_HUNTER){ RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0); RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0); @@ -5411,6 +5538,7 @@ CAutomobile::Fix(void) RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0); RpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0); } +*/ } void @@ -5472,6 +5600,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) if(obj == nil) return nil; + phys_lcs_unk1 = false; if(component == CAR_WINDSCREEN){ obj->SetModelIndexNoCreate(MI_CAR_BONNET); }else switch(type){ @@ -5510,6 +5639,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) *RwFrameGetMatrix(frame) = *matrix; RpAtomicSetFrame(atomic, frame); CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); + CStreaming::RegisterInstance(atomic, nil); obj->AttachToRwObject((RwObject*)atomic); obj->bDontStream = true; @@ -5554,7 +5684,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) CVector dist = obj->GetPosition() - GetPosition(); dist.Normalise(); if(component == COMPGROUP_BONNET || component == COMPGROUP_BOOT || component == CAR_WINDSCREEN){ - // push these up some + // push these up some dist += GetUp(); if(GetUp().z > 0.0f){ // simulate fast upward movement if going fast @@ -5577,9 +5707,9 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) ApplyMoveForce(5.0f*dist); } - if(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(), - this->GetMatrix(), *this->GetColModel(), - CWorld::m_aTempColPts, nil, nil) > 0) +// if(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(), +// this->GetMatrix(), *this->GetColModel(), +// CWorld::m_aTempColPts, nil, nil) > 0) obj->m_pCollidingEntity = this; if(bRenderScorched) |