summaryrefslogtreecommitdiffstats
path: root/src/vehicles
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/vehicles/Automobile.cpp50
-rw-r--r--src/vehicles/Automobile.cpp.autosave4560
-rw-r--r--src/vehicles/Automobile.h2
-rw-r--r--src/vehicles/Boat.cpp2
-rw-r--r--src/vehicles/Heli.cpp8
-rw-r--r--src/vehicles/Heli.cpp.autosave1055
-rw-r--r--src/vehicles/Plane.cpp8
-rw-r--r--src/vehicles/Plane.cpp.autosave985
-rw-r--r--src/vehicles/Vehicle.cpp12
-rw-r--r--src/vehicles/Vehicle.h4
10 files changed, 29 insertions, 6657 deletions
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 0fe59cd0..18c74478 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -7,13 +7,9 @@
#include "ModelIndices.h"
#include "VisibilityPlugins.h"
#include "DMAudio.h"
-<<<<<<< HEAD
#include "Clock.h"
-#include "TimeCycle.h"
-#include "ZoneCull.h"
-=======
#include "Timecycle.h"
->>>>>>> More audio ped
+#include "ZoneCull.h"
#include "Camera.h"
#include "Darkel.h"
#include "Rubbish.h"
@@ -132,7 +128,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
m_fGasPedal = 0.0f;
m_fBrakePedal = 0.0f;
m_pSetOnFireEntity = nil;
- field_594 = 0;
+ m_fGasPedalAudio = 0;
bNotDamagedUpsideDown = false;
bMoreResistantToDamage = false;
m_fVelocityChangeForAudio = 0.0f;
@@ -695,7 +691,7 @@ CAutomobile::ProcessControl(void)
if(m_aSuspensionSpringRatio[i] < 1.0f)
m_aWheelTimer[i] = 4.0f;
else
- m_aWheelTimer[i] = Max(m_aWheelTimer[i]-CTimer::GetTimeStep(), 0.0f);
+ m_aWheelTimer[i] = max(m_aWheelTimer[i]-CTimer::GetTimeStep(), 0.0f);
if(m_aWheelTimer[i] > 0.0f){
m_nWheelsOnGround++;
@@ -1013,7 +1009,7 @@ CAutomobile::ProcessControl(void)
if(m_status != STATUS_PLAYER && m_status != STATUS_PLAYER_REMOTE && m_status != STATUS_PHYSICS){
if(GetModelIndex() == MI_MIAMI_RCRAIDER || GetModelIndex() == MI_MIAMI_SPARROW)
- m_aWheelSpeed[0] = Max(m_aWheelSpeed[0]-0.0005f, 0.0f);
+ m_aWheelSpeed[0] = max(m_aWheelSpeed[0]-0.0005f, 0.0f);
}else if((GetModelIndex() == MI_DODO || CVehicle::bAllDodosCheat) &&
m_vecMoveSpeed.Magnitude() > 0.0f && CTimer::GetTimeStep() > 0.0f){
FlyingControl(FLIGHT_MODEL_DODO);
@@ -1021,7 +1017,7 @@ CAutomobile::ProcessControl(void)
FlyingControl(FLIGHT_MODEL_HELI);
}else if(GetModelIndex() == MI_MIAMI_RCRAIDER || GetModelIndex() == MI_MIAMI_SPARROW || bAllCarCheat){
if(CPad::GetPad(0)->GetCircleJustDown())
- m_aWheelSpeed[0] = Max(m_aWheelSpeed[0]-0.03f, 0.0f);
+ m_aWheelSpeed[0] = max(m_aWheelSpeed[0]-0.03f, 0.0f);
if(m_aWheelSpeed[0] < 0.22f)
m_aWheelSpeed[0] += 0.0001f;
if(m_aWheelSpeed[0] > 0.15f)
@@ -1133,10 +1129,10 @@ CAutomobile::ProcessControl(void)
if(speed > sq(0.1f)){
speed = Sqrt(speed);
if(suspShake > 0.0f){
- uint8 freq = Min(200.0f*suspShake*speed*2000.0f/m_fMass + 100.0f, 250.0f);
+ uint8 freq = min(200.0f*suspShake*speed*2000.0f/m_fMass + 100.0f, 250.0f);
CPad::GetPad(0)->StartShake(20000.0f*CTimer::GetTimeStep()/freq, freq);
}else{
- uint8 freq = Min(200.0f*surfShake*speed*2000.0f/m_fMass + 40.0f, 145.0f);
+ uint8 freq = min(200.0f*surfShake*speed*2000.0f/m_fMass + 40.0f, 145.0f);
CPad::GetPad(0)->StartShake(5000.0f*CTimer::GetTimeStep()/freq, freq);
}
}
@@ -2590,7 +2586,7 @@ CAutomobile::HydraulicControl(void)
float minz = pos.z + extendedLowerLimit - wheelRadius;
if(minz < specialColModel->boundingBox.min.z)
specialColModel->boundingBox.min.z = minz;
- float radius = Max(specialColModel->boundingBox.min.Magnitude(), specialColModel->boundingBox.max.Magnitude());
+ float radius = max(specialColModel->boundingBox.min.Magnitude(), specialColModel->boundingBox.max.Magnitude());
if(specialColModel->boundingSphere.radius < radius)
specialColModel->boundingSphere.radius = radius;
@@ -2689,10 +2685,10 @@ CAutomobile::HydraulicControl(void)
float front = -rear;
float right = CPad::GetPad(0)->GetCarGunLeftRight()/128.0f;
float left = -right;
- suspChange[CARWHEEL_FRONT_LEFT] = Max(front+left, 0.0f);
- suspChange[CARWHEEL_REAR_LEFT] = Max(rear+left, 0.0f);
- suspChange[CARWHEEL_FRONT_RIGHT] = Max(front+right, 0.0f);
- suspChange[CARWHEEL_REAR_RIGHT] = Max(rear+right, 0.0f);
+ suspChange[CARWHEEL_FRONT_LEFT] = max(front+left, 0.0f);
+ suspChange[CARWHEEL_REAR_LEFT] = max(rear+left, 0.0f);
+ suspChange[CARWHEEL_FRONT_RIGHT] = max(front+right, 0.0f);
+ suspChange[CARWHEEL_REAR_RIGHT] = max(rear+right, 0.0f);
if(m_hydraulicState < 100){
// Lowered, move wheels up
@@ -2808,7 +2804,7 @@ CAutomobile::ProcessBuoyancy(void)
ApplyTurnForce(impulse, point);
CVector initialSpeed = m_vecMoveSpeed;
- float timeStep = Max(CTimer::GetTimeStep(), 0.01f);
+ float timeStep = max(CTimer::GetTimeStep(), 0.01f);
float impulseRatio = impulse.z / (GRAVITY * m_fMass * timeStep);
float waterResistance = Pow(1.0f - 0.05f*impulseRatio, CTimer::GetTimeStep());
m_vecMoveSpeed *= waterResistance;
@@ -2901,7 +2897,7 @@ CAutomobile::ProcessBuoyancy(void)
float fSpeed = vSpeed.MagnitudeSqr();
if(fSpeed > sq(0.05f)){
fSpeed = Sqrt(fSpeed);
- float size = Min((fSpeed < 0.15f ? 0.25f : 0.75f)*fSpeed, 0.6f);
+ float size = min((fSpeed < 0.15f ? 0.25f : 0.75f)*fSpeed, 0.6f);
CVector right = 0.2f*fSpeed*GetRight() + 0.2f*vSpeed;
CParticle::AddParticle(PARTICLE_PED_SPLASH,
@@ -2983,11 +2979,11 @@ CAutomobile::DoDriveByShootings(void)
// TODO: what is this?
if(!lookingLeft && m_weaponDoorTimerLeft > 0.0f){
- m_weaponDoorTimerLeft = Max(m_weaponDoorTimerLeft - CTimer::GetTimeStep()*0.1f, 0.0f);
+ m_weaponDoorTimerLeft = max(m_weaponDoorTimerLeft - CTimer::GetTimeStep()*0.1f, 0.0f);
ProcessOpenDoor(CAR_DOOR_LF, NUM_ANIMS, m_weaponDoorTimerLeft);
}
if(!lookingRight && m_weaponDoorTimerRight > 0.0f){
- m_weaponDoorTimerRight = Max(m_weaponDoorTimerRight - CTimer::GetTimeStep()*0.1f, 0.0f);
+ m_weaponDoorTimerRight = max(m_weaponDoorTimerRight - CTimer::GetTimeStep()*0.1f, 0.0f);
ProcessOpenDoor(CAR_DOOR_RF, NUM_ANIMS, m_weaponDoorTimerRight);
}
}
@@ -3135,7 +3131,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece)
FindPlayerPed()->SetWantedLevelNoDrop(1);
if(m_status == STATUS_PLAYER && impulse > 50.0f){
- uint8 freq = Min(0.4f*impulse*2000.0f/m_fMass + 100.0f, 250.0f);
+ uint8 freq = min(0.4f*impulse*2000.0f/m_fMass + 100.0f, 250.0f);
CPad::GetPad(0)->StartShake(40000/freq, freq);
}
@@ -3288,7 +3284,7 @@ CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece)
if(m_pDamageEntity && m_pDamageEntity == FindPlayerVehicle() && impulse > 10.0f){
int money = (doubleMoney ? 2 : 1) * impulse*pHandling->nMonetaryValue/1000000.0f;
- money = Min(money, 40);
+ money = min(money, 40);
if(money > 2){
sprintf(gString, "$%d", money);
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += money;
@@ -3991,7 +3987,7 @@ CAutomobile::SetupSuspensionLines(void)
// adjust col model to include suspension lines
if(colModel->boundingBox.min.z > colModel->lines[0].p1.z)
colModel->boundingBox.min.z = colModel->lines[0].p1.z;
- float radius = Max(colModel->boundingBox.min.Magnitude(), colModel->boundingBox.max.Magnitude());
+ float radius = max(colModel->boundingBox.min.Magnitude(), colModel->boundingBox.max.Magnitude());
if(colModel->boundingSphere.radius < radius)
colModel->boundingSphere.radius = radius;
@@ -4483,16 +4479,8 @@ CAutomobile::SetAllTaxiLights(bool set)
class CAutomobile_ : public CAutomobile
{
public:
-<<<<<<< HEAD
-<<<<<<< HEAD
void ctor(int32 id, uint8 CreatedBy) { ::new (this) CAutomobile(id, CreatedBy); }
void dtor() { CAutomobile::~CAutomobile(); }
-=======
- void dtor() { this->~CAutomobile(); }
->>>>>>> More audio ped
-=======
- void dtor() { CAutomobile::~CAutomobile(); }
->>>>>>> fix
void SetModelIndex_(uint32 id) { CAutomobile::SetModelIndex(id); }
void ProcessControl_(void) { CAutomobile::ProcessControl(); }
void Teleport_(CVector v) { CAutomobile::Teleport(v); }
diff --git a/src/vehicles/Automobile.cpp.autosave b/src/vehicles/Automobile.cpp.autosave
deleted file mode 100644
index 140633b8..00000000
--- a/src/vehicles/Automobile.cpp.autosave
+++ /dev/null
@@ -1,4560 +0,0 @@
-#include "common.h"
-#include "main.h"
-#include "patcher.h"
-#include "General.h"
-#include "RwHelper.h"
-#include "Pad.h"
-#include "ModelIndices.h"
-#include "VisibilityPlugins.h"
-#include "DMAudio.h"
-#include "Clock.h"
-#include "Timecycle.h"
-#include "ZoneCull.h"
-#include "Camera.h"
-#include "Darkel.h"
-#include "Rubbish.h"
-#include "Fire.h"
-#include "Explosion.h"
-#include "Particle.h"
-#include "ParticleObject.h"
-#include "Antennas.h"
-#include "Skidmarks.h"
-#include "Shadows.h"
-#include "PointLights.h"
-#include "Coronas.h"
-#include "SpecialFX.h"
-#include "WaterCannon.h"
-#include "WaterLevel.h"
-#include "Floater.h"
-#include "World.h"
-#include "SurfaceTable.h"
-#include "Weather.h"
-#include "HandlingMgr.h"
-#include "Record.h"
-#include "Remote.h"
-#include "Population.h"
-#include "CarCtrl.h"
-#include "CarAI.h"
-#include "Garages.h"
-#include "PathFind.h"
-#include "AnimManager.h"
-#include "RpAnimBlend.h"
-#include "Ped.h"
-#include "PlayerPed.h"
-#include "Object.h"
-#include "Automobile.h"
-
-bool bAllCarCheat; // unused
-
-RwObject *GetCurrentAtomicObjectCB(RwObject *object, void *data);
-
-bool &CAutomobile::m_sAllTaxiLights = *(bool*)0x95CD21;
-
-CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
- : CVehicle(CreatedBy)
-{
- int i;
-
- m_vehType = VEHICLE_TYPE_CAR;
-
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
- m_fFireBlowUpTimer = 0.0f;
- field_4E0 = 0;
- bTaxiLight = m_sAllTaxiLights;
- m_auto_flagA20 = false;
- m_auto_flagA40 = false;
- bWaterTight = false;
-
- SetModelIndex(id);
-
- pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId);
-
- field_49C = 20.0f;
- field_4D8 = 0;
-
- mi->ChooseVehicleColour(m_currentColour1, m_currentColour2);
-
- bIsVan = !!(pHandling->Flags & HANDLING_IS_VAN);
- bIsBig = !!(pHandling->Flags & HANDLING_IS_BIG);
- bIsBus = !!(pHandling->Flags & HANDLING_IS_BUS);
- bLowVehicle = !!(pHandling->Flags & HANDLING_IS_LOW);
-
- // Doors
- if(bIsBus){
- Doors[DOOR_FRONT_LEFT].Init(-HALFPI, 0.0f, 0, 2);
- Doors[DOOR_FRONT_RIGHT].Init(0.0f, HALFPI, 1, 2);
- }else{
- Doors[DOOR_FRONT_LEFT].Init(-PI*0.4f, 0.0f, 0, 2);
- Doors[DOOR_FRONT_RIGHT].Init(0.0f, PI*0.4f, 1, 2);
- }
- if(bIsVan){
- Doors[DOOR_REAR_LEFT].Init(-HALFPI, 0.0f, 1, 2);
- Doors[DOOR_REAR_RIGHT].Init(0.0f, HALFPI, 0, 2);
- }else{
- Doors[DOOR_REAR_LEFT].Init(-PI*0.4f, 0.0f, 0, 2);
- Doors[DOOR_REAR_RIGHT].Init(0.0f, PI*0.4f, 1, 2);
- }
- if(pHandling->Flags & HANDLING_REV_BONNET)
- Doors[DOOR_BONNET].Init(-PI*0.3f, 0.0f, 1, 0);
- else
- Doors[DOOR_BONNET].Init(0.0f, PI*0.3f, 1, 0);
- if(pHandling->Flags & HANDLING_HANGING_BOOT)
- Doors[DOOR_BOOT].Init(PI*0.4f, 0.0f, 0, 0);
- else if(pHandling->Flags & HANDLING_TAILGATE_BOOT)
- Doors[DOOR_BOOT].Init(0.0, HALFPI, 1, 0);
- else
- Doors[DOOR_BOOT].Init(-PI*0.3f, 0.0f, 1, 0);
- if(pHandling->Flags & HANDLING_NO_DOORS){
- Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_MISSING);
- Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_MISSING);
- Damage.SetDoorStatus(DOOR_REAR_LEFT, DOOR_STATUS_MISSING);
- Damage.SetDoorStatus(DOOR_REAR_RIGHT, DOOR_STATUS_MISSING);
- }
-
- for(i = 0; i < 6; i++)
- m_randomValues[i] = CGeneral::GetRandomNumberInRange(-0.15f, 0.15f);
-
- m_fMass = pHandling->fMass;
- m_fTurnMass = pHandling->fTurnMass;
- m_vecCentreOfMass = pHandling->CentreOfMass;
- m_fAirResistance = pHandling->Dimension.x*pHandling->Dimension.z/m_fMass;
- m_fElasticity = 0.05f;
- m_fBuoyancy = pHandling->fBuoyancy;
-
- m_nBusDoorTimerEnd = 0;
- m_nBusDoorTimerStart = 0;
-
- m_fSteerAngle = 0.0f;
- m_fGasPedal = 0.0f;
- m_fBrakePedal = 0.0f;
- m_pSetOnFireEntity = nil;
- field_594 = 0;
- bNotDamagedUpsideDown = false;
- bMoreResistantToDamage = false;
- m_fVelocityChangeForAudio = 0.0f;
- m_hydraulicState = 0;
-
- for(i = 0; i < 4; i++){
- m_aGroundPhysical[i] = nil;
- m_aGroundOffset[i] = CVector(0.0f, 0.0f, 0.0f);
- m_aSuspensionSpringRatio[i] = 1.0f;
- m_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i];
- m_aWheelTimer[i] = 0.0f;
- m_aWheelRotation[i] = 0.0f;
- m_aWheelSpeed[i] = 0.0f;
- m_aWheelState[i] = WHEEL_STATE_NORMAL;
- m_aWheelSkidmarkMuddy[i] = false;
- m_aWheelSkidmarkBloody[i] = false;
- }
-
- m_nWheelsOnGround = 0;
- m_nDriveWheelsOnGround = 0;
- m_nDriveWheelsOnGroundPrev = 0;
- m_fHeightAboveRoad = 0.0f;
- m_fTraction = 1.0f;
-
- CColModel *colModel = mi->GetColModel();
- if(colModel->lines == nil){
- colModel->lines = (CColLine*)RwMalloc(4*sizeof(CColLine));
- colModel->numLines = 4;
- }
-
- SetupSuspensionLines();
-
- m_status = STATUS_SIMPLE;
- bUseCollisionRecords = true;
-
- m_nNumPassengers = 0;
-
- m_bombType = CARBOMB_NONE;
- bHadDriver = false;
- m_pBombRigger = nil;
-
- if(m_nDoorLock == CARLOCK_UNLOCKED &&
- (id == MI_POLICE || id == MI_ENFORCER || id == MI_RHINO))
- m_nDoorLock = CARLOCK_LOCKED_INITIALLY;
-
- m_fCarGunLR = 0.0f;
- m_fCarGunUD = 0.05f;
- m_fPropellerRotation = 0.0f;
- m_weaponDoorTimerLeft = 0.0f;
- m_weaponDoorTimerRight = m_weaponDoorTimerLeft;
-
- if(GetModelIndex() == MI_DODO){
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
- CMatrix mat1;
- mat1.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
- CMatrix mat2(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
- mat1.GetPosition() += CVector(mat2.GetPosition().x + 0.1f, 0.0f, mat2.GetPosition().z);
- mat1.UpdateRW();
- }else if(GetModelIndex() == MI_MIAMI_SPARROW || GetModelIndex() == MI_MIAMI_RCRAIDER){
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0);
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);
- RpAtomicSetFlags(GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);
- }else if(GetModelIndex() == MI_RHINO){
- bExplosionProof = true;
- bBulletProof = true;
- }
-}
-
-
-void
-CAutomobile::SetModelIndex(uint32 id)
-{
- CVehicle::SetModelIndex(id);
- SetupModelNodes();
-}
-
-CVector vecDAMAGE_ENGINE_POS_SMALL(-0.1f, -0.1f, 0.0f);
-CVector vecDAMAGE_ENGINE_POS_BIG(-0.5f, -0.3f, 0.0f);
-
-void
-CAutomobile::ProcessControl(void)
-{
- int i;
- CColModel *colModel;
-
- if(bUsingSpecialColModel)
- colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;
- else
- colModel = GetColModel();
- bWarnedPeds = false;
-
- // skip if the collision isn't for the current level
- if(colModel->level > LEVEL_NONE && colModel->level != CCollision::ms_collisionInMemory)
- return;
-
- // Improve grip of vehicles in certain cases
- bool strongGrip1 = false;
- bool strongGrip2 = false;
- if(FindPlayerVehicle() && this != FindPlayerVehicle()){
- switch(AutoPilot.m_nCarMission){
- case MISSION_RAMPLAYER_FARAWAY:
- case MISSION_RAMPLAYER_CLOSE:
- case MISSION_BLOCKPLAYER_FARAWAY:
- case MISSION_BLOCKPLAYER_CLOSE:
- if(FindPlayerSpeed().Magnitude() > 0.3f){
- strongGrip1 = true;
- if(FindPlayerSpeed().Magnitude() > 0.4f){
- if(m_vecMoveSpeed.Magnitude() < 0.3f)
- strongGrip2 = true;
- }else{
- if((GetPosition() - FindPlayerCoors()).Magnitude() > 50.0f)
- strongGrip2 = true;
- }
- }
- }
- }
-
- if(bIsBus)
- ProcessAutoBusDoors();
-
- ProcessCarAlarm();
-
- // Scan if this car is committing a crime that the police can see
- if(m_status != STATUS_ABANDONED && m_status != STATUS_WRECKED &&
- m_status != STATUS_PLAYER && m_status != STATUS_PLAYER_REMOTE && m_status != STATUS_PLAYER_DISABLED){
- switch(GetModelIndex())
- case MI_FBICAR:
- case MI_POLICE:
- case MI_ENFORCER:
- case MI_SECURICA:
- case MI_RHINO:
- case MI_BARRACKS:
- ScanForCrimes();
- }
-
- // Process driver
- if(pDriver){
- if(!bHadDriver && 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);
- }
- bHadDriver = true;
-
- if(IsUpsideDown() && CanPedEnterCar()){
- if(!pDriver->IsPlayer() &&
- !(pDriver->m_leader && pDriver->m_leader->bInVehicle) &&
- pDriver->CharCreatedBy != MISSION_CHAR)
- pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this);
- }
- }else
- bHadDriver = false;
-
- // Process passengers
- if(m_nNumPassengers != 0 && IsUpsideDown() && CanPedEnterCar()){
- for(i = 0; i < m_nNumMaxPassengers; i++)
- if(pPassengers[i])
- if(!pPassengers[i]->IsPlayer() &&
- !(pPassengers[i]->m_leader && pPassengers[i]->m_leader->bInVehicle) &&
- pPassengers[i]->CharCreatedBy != MISSION_CHAR)
- pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this);
- }
-
- CRubbish::StirUp(this);
-
- // blend in clump
- int clumpAlpha = CVisibilityPlugins::GetClumpAlpha((RpClump*)m_rwObject);
- if(bFadeOut){
- clumpAlpha -= 8;
- if(clumpAlpha < 0)
- clumpAlpha = 0;
- }else if(clumpAlpha < 255){
- clumpAlpha += 16;
- if(clumpAlpha > 255)
- clumpAlpha = 255;
- }
- CVisibilityPlugins::SetClumpAlpha((RpClump*)m_rwObject, clumpAlpha);
-
- AutoPilot.m_bSlowedDownBecauseOfCars = false;
- AutoPilot.m_bSlowedDownBecauseOfPeds = false;
-
- // Set Center of Mass to make car more stable
- if(strongGrip1 || bCheat3)
- m_vecCentreOfMass.z = 0.3f*m_aSuspensionSpringLength[0] + -1.0*m_fHeightAboveRoad;
- else if(pHandling->Flags & HANDLING_NONPLAYER_STABILISER && m_status == STATUS_PHYSICS)
- m_vecCentreOfMass.z = pHandling->CentreOfMass.z - 0.2f*pHandling->Dimension.z;
- else
- m_vecCentreOfMass.z = pHandling->CentreOfMass.z;
-
- // Process depending on status
-
- bool playerRemote = false;
- switch(m_status){
- case STATUS_PLAYER_REMOTE:
- if(CPad::GetPad(0)->WeaponJustDown()){
- BlowUpCar(FindPlayerPed());
- CRemote::TakeRemoteControlledCarFromPlayer();
- }
-
- if(GetModelIndex() == MI_RCBANDIT){
- CVector pos = GetPosition();
- // FindPlayerCoors unused
- if(RcbanditCheckHitWheels() || bIsInWater || CPopulation::IsPointInSafeZone(&pos)){
- if(CPopulation::IsPointInSafeZone(&pos))
- CGarages::TriggerMessage("HM2_5", -1, 5000, -1);
- CRemote::TakeRemoteControlledCarFromPlayer();
- BlowUpCar(FindPlayerPed());
- }
- }
-
- if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle == this)
- playerRemote = true;
- // fall through
- case STATUS_PLAYER:
- if(playerRemote ||
- pDriver && pDriver->GetPedState() != PED_EXIT_CAR && pDriver->GetPedState() != PED_DRAG_FROM_CAR){
- // process control input if controlled by player
- if(playerRemote || pDriver->m_nPedType == PEDTYPE_PLAYER1)
- ProcessControlInputs(0);
-
- PruneReferences();
-
- if(m_status == STATUS_PLAYER && CRecordDataForChase::Status != RECORDSTATE_1)
- DoDriveByShootings();
- }
- break;
-
- case STATUS_SIMPLE:
- CCarAI::UpdateCarAI(this);
- CPhysical::ProcessControl();
- CCarCtrl::UpdateCarOnRails(this);
-
- m_nWheelsOnGround = 4;
- m_nDriveWheelsOnGroundPrev = m_nDriveWheelsOnGround;
- m_nDriveWheelsOnGround = 4;
-
- pHandling->Transmission.CalculateGearForSimpleCar(AutoPilot.m_fMaxTrafficSpeed/50.0f, m_nCurrentGear);
-
- {
- float wheelRot = ProcessWheelRotation(WHEEL_STATE_NORMAL, GetForward(), m_vecMoveSpeed, 0.35f);
- for(i = 0; i < 4; i++)
- m_aWheelRotation[i] += wheelRot;
- }
-
- PlayHornIfNecessary();
- ReduceHornCounter();
- bVehicleColProcessed = false;
- // that's all we do for simple vehicles
- return;
-
- case STATUS_PHYSICS:
- CCarAI::UpdateCarAI(this);
- CCarCtrl::SteerAICarWithPhysics(this);
- PlayHornIfNecessary();
- break;
-
- case STATUS_ABANDONED:
- m_fBrakePedal = 0.2f;
- bIsHandbrakeOn = false;
-
- m_fSteerAngle = 0.0f;
- m_fGasPedal = 0.0f;
- m_nCarHornTimer = 0;
- break;
-
- case STATUS_WRECKED:
- m_fBrakePedal = 0.05f;
- bIsHandbrakeOn = true;
-
- m_fSteerAngle = 0.0f;
- m_fGasPedal = 0.0f;
- m_nCarHornTimer = 0;
- break;
-
- case STATUS_PLAYER_DISABLED:
- m_fBrakePedal = 1.0f;
- bIsHandbrakeOn = true;
-
- m_fSteerAngle = 0.0f;
- m_fGasPedal = 0.0f;
- m_nCarHornTimer = 0;
- break;
- }
-
- // what's going on here?
- if(GetPosition().z < -0.6f &&
- Abs(m_vecMoveSpeed.x) < 0.05f &&
- Abs(m_vecMoveSpeed.y) < 0.05f)
- m_vecTurnSpeed *= Pow(0.95f, CTimer::GetTimeStep());
-
- // Skip physics if object is found to have been static recently
- bool skipPhysics = false;
- if(!bIsStuck && (m_status == STATUS_ABANDONED || m_status == STATUS_WRECKED)){
- bool makeStatic = false;
- float moveSpeedLimit, turnSpeedLimit, distanceLimit;
-
- if(!bVehicleColProcessed &&
- m_vecMoveSpeed.IsZero() &&
- // BUG? m_aSuspensionSpringRatioPrev[3] is checked twice in the game. also, why 3?
- m_aSuspensionSpringRatioPrev[3] != 1.0f)
- makeStatic = true;
-
- if(m_status == STATUS_WRECKED){
- moveSpeedLimit = 0.006f;
- turnSpeedLimit = 0.0015f;
- distanceLimit = 0.015f;
- }else{
- moveSpeedLimit = 0.003f;
- turnSpeedLimit = 0.0009f;
- distanceLimit = 0.005f;
- }
-
- m_vecMoveSpeedAvg = (m_vecMoveSpeedAvg + m_vecMoveSpeed)/2.0f;
- m_vecTurnSpeedAvg = (m_vecTurnSpeedAvg + m_vecTurnSpeed)/2.0f;
-
- if(m_vecMoveSpeedAvg.MagnitudeSqr() <= sq(moveSpeedLimit*CTimer::GetTimeStep()) &&
- m_vecTurnSpeedAvg.MagnitudeSqr() <= sq(turnSpeedLimit*CTimer::GetTimeStep()) &&
- m_fDistanceTravelled < distanceLimit ||
- makeStatic){
- m_nStaticFrames++;
-
- if(m_nStaticFrames > 10 || makeStatic)
- if(!CCarCtrl::MapCouldMoveInThisArea(GetPosition().x, GetPosition().y)){
- if(!makeStatic || m_nStaticFrames > 10)
- m_nStaticFrames = 10;
-
- skipPhysics = true;
-
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- }
- }else
- m_nStaticFrames = 0;
- }
-
- // Postpone
- for(i = 0; i < 4; i++)
- if(m_aGroundPhysical[i] && !CWorld::bForceProcessControl && m_aGroundPhysical[i]->bIsInSafePosition){
- bWasPostponed = true;
- return;
- }
-
- VehicleDamage(0.0f, 0);
-
- // special control
- switch(GetModelIndex()){
- case MI_FIRETRUCK:
- FireTruckControl();
- break;
- case MI_RHINO:
- TankControl();
- BlowUpCarsInPath();
- break;
- case MI_YARDIE:
- // beta also had esperanto here it seems
- HydraulicControl();
- break;
- default:
- if(CVehicle::bCheat3){
- // Make vehicle jump when horn is sounded
- if(m_status == STATUS_PLAYER && m_vecMoveSpeed.MagnitudeSqr() > sq(0.2f) &&
- // BUG: game checks [0] four times, instead of all wheels
- m_aSuspensionSpringRatio[0] < 1.0f &&
- CPad::GetPad(0)->HornJustDown()){
-
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_1, 0.0f);
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP, 1.0f);
-
- CParticle::AddParticle(PARTICLE_ENGINE_STEAM,
- m_aWheelColPoints[0].point + 0.5f*GetUp(),
- 1.3f*m_vecMoveSpeed, nil, 2.5f);
- CParticle::AddParticle(PARTICLE_ENGINE_SMOKE,
- m_aWheelColPoints[0].point + 0.5f*GetUp(),
- 1.2f*m_vecMoveSpeed, nil, 2.0f);
-
- CParticle::AddParticle(PARTICLE_ENGINE_STEAM,
- m_aWheelColPoints[2].point + 0.5f*GetUp(),
- 1.3f*m_vecMoveSpeed, nil, 2.5f);
- CParticle::AddParticle(PARTICLE_ENGINE_SMOKE,
- m_aWheelColPoints[2].point + 0.5f*GetUp(),
- 1.2f*m_vecMoveSpeed, nil, 2.0f);
-
- CParticle::AddParticle(PARTICLE_ENGINE_STEAM,
- m_aWheelColPoints[0].point + 0.5f*GetUp() - GetForward(),
- 1.3f*m_vecMoveSpeed, nil, 2.5f);
- CParticle::AddParticle(PARTICLE_ENGINE_SMOKE,
- m_aWheelColPoints[0].point + 0.5f*GetUp() - GetForward(),
- 1.2f*m_vecMoveSpeed, nil, 2.0f);
-
- CParticle::AddParticle(PARTICLE_ENGINE_STEAM,
- m_aWheelColPoints[2].point + 0.5f*GetUp() - GetForward(),
- 1.3f*m_vecMoveSpeed, nil, 2.5f);
- CParticle::AddParticle(PARTICLE_ENGINE_SMOKE,
- m_aWheelColPoints[2].point + 0.5f*GetUp() - GetForward(),
- 1.2f*m_vecMoveSpeed, nil, 2.0f);
-
- ApplyMoveForce(CVector(0.0f, 0.0f, 1.0f)*m_fMass*0.4f);
- ApplyTurnForce(GetUp()*m_fMass*0.035f, GetForward()*1.0f);
- }
- }
- break;
- }
-
- float brake;
- if(skipPhysics){
- bHasContacted = false;
- bIsInSafePosition = false;
- bWasPostponed = false;
- bHasHitWall = false;
- m_nCollisionRecords = 0;
- bHasCollided = false;
- bVehicleColProcessed = false;
- m_nDamagePieceType = 0;
- m_fDamageImpulse = 0.0f;
- m_pDamageEntity = nil;
- m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);
- m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);
- }else{
-
- // This has to be done if ProcessEntityCollision wasn't called
- if(!bVehicleColProcessed){
- CMatrix mat(GetMatrix());
- bIsStuck = false;
- bHasContacted = false;
- bIsInSafePosition = false;
- bWasPostponed = false;
- bHasHitWall = false;
- m_fDistanceTravelled = 0.0f;
- field_EF = false;
- m_phy_flagA80 = false;
- ApplyMoveSpeed();
- ApplyTurnSpeed();
- for(i = 0; CheckCollision() && i < 5; i++){
- GetMatrix() = mat;
- ApplyMoveSpeed();
- ApplyTurnSpeed();
- }
- bIsInSafePosition = true;
- bIsStuck = false;
- }
-
- CPhysical::ProcessControl();
-
- ProcessBuoyancy();
-
- // Rescale spring ratios, i.e. subtract wheel radius
- for(i = 0; i < 4; i++){
- // wheel radius in relation to suspension line
- float wheelRadius = 1.0f - m_aSuspensionSpringLength[i]/m_aSuspensionLineLength[i];
- // rescale such that 0.0 is fully compressed and 1.0 is fully extended
- m_aSuspensionSpringRatio[i] = (m_aSuspensionSpringRatio[i]-wheelRadius)/(1.0f-wheelRadius);
- }
-
- float fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward());
- CVector contactPoints[4]; // relative to model
- CVector contactSpeeds[4]; // speed at contact points
- CVector springDirections[4]; // normalized, in model space
-
- for(i = 0; i < 4; i++){
- // Set spring under certain circumstances
- if(Damage.GetWheelStatus(i) == WHEEL_STATUS_MISSING)
- m_aSuspensionSpringRatio[i] = 1.0f;
- else if(Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST){
- // wheel more bumpy the faster we are
- if(CGeneral::GetRandomNumberInRange(0, (uint16)(40*fwdSpeed) + 98) < 100){
- m_aSuspensionSpringRatio[i] += 0.3f*(m_aSuspensionLineLength[i]-m_aSuspensionSpringLength[i])/m_aSuspensionSpringLength[i];
- if(m_aSuspensionSpringRatio[i] > 1.0f)
- m_aSuspensionSpringRatio[i] = 1.0f;
- }
- }
-
- // get points and directions if spring is compressed
- 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();
- }
- }
-
- // Make springs push up vehicle
- for(i = 0; i < 4; i++){
- if(m_aSuspensionSpringRatio[i] < 1.0f){
- float bias = pHandling->fSuspensionBias;
- if(i == 1 || i == 3) // rear
- bias = 1.0f - bias;
-
- ApplySpringCollision(pHandling->fSuspensionForceLevel,
- springDirections[i], contactPoints[i],
- m_aSuspensionSpringRatio[i], bias);
- m_aWheelSkidmarkMuddy[i] =
- m_aWheelColPoints[i].surfaceB == SURFACE_GRASS ||
- m_aWheelColPoints[i].surfaceB == SURFACE_DIRTTRACK ||
- m_aWheelColPoints[i].surfaceB == SURFACE_SAND;
- }else{
- contactPoints[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1);
- }
- }
-
- // Get speed at contact points
- for(i = 0; i < 4; i++){
- contactSpeeds[i] = GetSpeed(contactPoints[i]);
- if(m_aGroundPhysical[i]){
- // subtract movement of physical we're standing on
- contactSpeeds[i] -= m_aGroundPhysical[i]->GetSpeed(m_aGroundOffset[i]);
-#ifndef FIX_BUGS
- // this shouldn't be reset because we still need it below
- m_aGroundPhysical[i] = nil;
-#endif
- }
- }
-
- // dampen springs
- for(i = 0; i < 4; i++)
- if(m_aSuspensionSpringRatio[i] < 1.0f)
- ApplySpringDampening(pHandling->fSuspensionDampingLevel,
- springDirections[i], contactPoints[i], contactSpeeds[i]);
-
- // Get speed at contact points again
- for(i = 0; i < 4; i++){
- contactSpeeds[i] = GetSpeed(contactPoints[i]);
- if(m_aGroundPhysical[i]){
- // subtract movement of physical we're standing on
- contactSpeeds[i] -= m_aGroundPhysical[i]->GetSpeed(m_aGroundOffset[i]);
- m_aGroundPhysical[i] = nil;
- }
- }
-
-
- 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 /= fForceMultiplier;
-
- // unused
- if(GetModelIndex() == MI_MIAMI_RCBARON ||
- GetModelIndex() == MI_MIAMI_RCRAIDER ||
- GetModelIndex() == MI_MIAMI_SPARROW)
- acceleration = 0.0f;
-
- brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep();
- bool neutralHandling = !!(pHandling->Flags & HANDLING_NEUTRALHANDLING);
- float brakeBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fBrakeBias;
- float brakeBiasRear = neutralHandling ? 1.0f : 2.0f*(1.0f-pHandling->fBrakeBias);
- float tractionBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fTractionBias;
- float tractionBiasRear = neutralHandling ? 1.0f : 2.0f*(1.0f-pHandling->fTractionBias);
-
- // Count how many wheels are touching the ground
-
- m_nWheelsOnGround = 0;
- m_nDriveWheelsOnGroundPrev = m_nDriveWheelsOnGround;
- m_nDriveWheelsOnGround = 0;
-
- for(i = 0; i < 4; i++){
- if(m_aSuspensionSpringRatio[i] < 1.0f)
- m_aWheelTimer[i] = 4.0f;
- else
- m_aWheelTimer[i] = Max(m_aWheelTimer[i]-CTimer::GetTimeStep(), 0.0f);
-
- if(m_aWheelTimer[i] > 0.0f){
- m_nWheelsOnGround++;
- switch(pHandling->Transmission.nDriveType){
- case '4':
- m_nDriveWheelsOnGround++;
- break;
- case 'F':
- if(i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)
- m_nDriveWheelsOnGround++;
- break;
- case 'R':
- if(i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT)
- m_nDriveWheelsOnGround++;
- break;
- }
- }
- }
-
- float traction;
- if(m_status == STATUS_PHYSICS)
- traction = 0.004f * m_fTraction;
- else
- traction = 0.004f;
- traction *= pHandling->fTractionMultiplier / 4.0f;
- traction /= fForceMultiplier;
- if(CVehicle::bCheat3)
- traction *= 4.0f;
-
- if(FindPlayerVehicle() && FindPlayerVehicle() == this){
- if(CPad::GetPad(0)->WeaponJustDown()){
- 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);
- }
- }
- }else if(strongGrip1 || CVehicle::bCheat3){
- traction *= 1.2f;
- acceleration *= 1.4f;
- if(strongGrip2 || CVehicle::bCheat3){
- traction *= 1.3f;
- acceleration *= 1.4f;
- }
- }
-
- static float fThrust;
- static tWheelState WheelState[4];
-
- // Process front wheels on ground
-
- 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 = Multiply3x3(GetMatrix(), CVector(-s, c, 0.0f));
- CVector wheelRight = Multiply3x3(GetMatrix(), CVector(c, s, 0.0f));
-
- if(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f){
- if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier))
- fThrust = 0.0f;
- else
- fThrust = acceleration;
-
- m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_RUBBER29;
- float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_LEFT])*traction;
- if(m_status == STATUS_PLAYER)
- adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB);
- WheelState[CARWHEEL_FRONT_LEFT] = m_aWheelState[CARWHEEL_FRONT_LEFT];
-
- if(Damage.GetWheelStatus(VEHWHEEL_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.HasRearWheelDrive(pHandling->nIdentifier))
- fThrust = 0.0f;
- else
- fThrust = acceleration;
-
- m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_RUBBER29;
- float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT])*traction;
- if(m_status == STATUS_PLAYER)
- adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB);
- WheelState[CARWHEEL_FRONT_RIGHT] = m_aWheelState[CARWHEEL_FRONT_RIGHT];
-
- if(Damage.GetWheelStatus(VEHWHEEL_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(m_aWheelTimer[CARWHEEL_FRONT_LEFT] <= 0.0f){
- if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) || acceleration == 0.0f)
- m_aWheelSpeed[CARWHEEL_FRONT_LEFT] *= 0.95f;
- else{
- 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;
- }
- }
- m_aWheelRotation[CARWHEEL_FRONT_LEFT] += m_aWheelSpeed[CARWHEEL_FRONT_LEFT];
- }
- if(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] <= 0.0f){
- if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) || acceleration == 0.0f)
- m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] *= 0.95f;
- else{
- 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;
- }
- }
- 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();
-
- if(bIsHandbrakeOn)
- brake = 20000.0f;
-
- if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f){
- if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier))
- fThrust = 0.0f;
- else
- fThrust = acceleration;
-
- m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceA = SURFACE_RUBBER29;
- float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_LEFT])*traction;
- if(m_status == STATUS_PLAYER)
- adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB);
- WheelState[CARWHEEL_REAR_LEFT] = m_aWheelState[CARWHEEL_REAR_LEFT];
-
- if(Damage.GetWheelStatus(VEHWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST)
- ProcessWheel(wheelFwd, wheelRight,
- contactSpeeds[CARWHEEL_REAR_LEFT], contactPoints[CARWHEEL_REAR_LEFT],
- m_nWheelsOnGround, fThrust,
- brake*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,
- brake*brakeBiasRear,
- adhesion*tractionBiasRear,
- CARWHEEL_REAR_LEFT,
- &m_aWheelSpeed[CARWHEEL_REAR_LEFT],
- &WheelState[CARWHEEL_REAR_LEFT],
- WHEEL_STATUS_OK);
- }
-
- if(m_aWheelTimer[CARWHEEL_REAR_RIGHT] > 0.0f){
- if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier))
- fThrust = 0.0f;
- else
- fThrust = acceleration;
-
- m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceA = SURFACE_RUBBER29;
- float adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_RIGHT])*traction;
- if(m_status == STATUS_PLAYER)
- adhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB);
- WheelState[CARWHEEL_REAR_RIGHT] = m_aWheelState[CARWHEEL_REAR_RIGHT];
-
- if(Damage.GetWheelStatus(VEHWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST)
- ProcessWheel(wheelFwd, wheelRight,
- contactSpeeds[CARWHEEL_REAR_RIGHT], contactPoints[CARWHEEL_REAR_RIGHT],
- m_nWheelsOnGround, fThrust,
- brake*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,
- brake*brakeBiasRear,
- adhesion*tractionBiasRear,
- CARWHEEL_REAR_RIGHT,
- &m_aWheelSpeed[CARWHEEL_REAR_RIGHT],
- &WheelState[CARWHEEL_REAR_RIGHT],
- WHEEL_STATUS_OK);
- }
- }
-
- // Process rear wheels off ground
-
- if(m_aWheelTimer[CARWHEEL_REAR_LEFT] <= 0.0f){
- if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) || acceleration == 0.0f)
- m_aWheelSpeed[CARWHEEL_REAR_LEFT] *= 0.95f;
- else{
- 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;
- }
- }
- m_aWheelRotation[CARWHEEL_REAR_LEFT] += m_aWheelSpeed[CARWHEEL_REAR_LEFT];
- }
- if(m_aWheelTimer[CARWHEEL_REAR_RIGHT] <= 0.0f){
- if(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) || acceleration == 0.0f)
- m_aWheelSpeed[CARWHEEL_REAR_RIGHT] *= 0.95f;
- else{
- 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;
- }
- }
- m_aWheelRotation[CARWHEEL_REAR_RIGHT] += m_aWheelSpeed[CARWHEEL_REAR_RIGHT];
- }
-
- 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];
- m_aWheelPosition[i] += (wheelPos - m_aWheelPosition[i])*0.75f;
- }
- for(i = 0; i < 4; i++)
- m_aWheelState[i] = WheelState[i];
-
- // Process horn
-
- if(m_status != STATUS_PLAYER){
- ReduceHornCounter();
- }else{
- if(GetModelIndex() == MI_MRWHOOP){
- if(Pads[0].bHornHistory[Pads[0].iCurrHornHistory] &&
- !Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+4) % 5]){
- m_bSirenOrAlarm = !m_bSirenOrAlarm;
- printf("m_bSirenOrAlarm toggled to %d\n", m_bSirenOrAlarm);
- }
- }else if(UsesSiren(GetModelIndex())){
- if(Pads[0].bHornHistory[Pads[0].iCurrHornHistory]){
- if(Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+4) % 5] &&
- Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+3) % 5])
- m_nCarHornTimer = 1;
- else
- m_nCarHornTimer = 0;
- }else if(Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+4) % 5] &&
- !Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+1) % 5]){
- m_nCarHornTimer = 0;
- m_bSirenOrAlarm = !m_bSirenOrAlarm;
- }else
- m_nCarHornTimer = 0;
- }else if(GetModelIndex() != MI_YARDIE && !CVehicle::bCheat3){
- if(Pads[0].GetHorn())
- m_nCarHornTimer = 1;
- else
- m_nCarHornTimer = 0;
- }
- }
-
- // Flying
-
- if(m_status != STATUS_PLAYER && m_status != STATUS_PLAYER_REMOTE && m_status != STATUS_PHYSICS){
- if(GetModelIndex() == MI_MIAMI_RCRAIDER || GetModelIndex() == MI_MIAMI_SPARROW)
- m_aWheelSpeed[0] = Max(m_aWheelSpeed[0]-0.0005f, 0.0f);
- }else if((GetModelIndex() == MI_DODO || CVehicle::bAllDodosCheat) &&
- m_vecMoveSpeed.Magnitude() > 0.0f && CTimer::GetTimeStep() > 0.0f){
- FlyingControl(FLIGHT_MODEL_DODO);
- }else if(GetModelIndex() == MI_MIAMI_RCBARON){
- FlyingControl(FLIGHT_MODEL_HELI);
- }else if(GetModelIndex() == MI_MIAMI_RCRAIDER || GetModelIndex() == MI_MIAMI_SPARROW || bAllCarCheat){
- if(CPad::GetPad(0)->GetCircleJustDown())
- m_aWheelSpeed[0] = Max(m_aWheelSpeed[0]-0.03f, 0.0f);
- if(m_aWheelSpeed[0] < 0.22f)
- m_aWheelSpeed[0] += 0.0001f;
- if(m_aWheelSpeed[0] > 0.15f)
- FlyingControl(FLIGHT_MODEL_HELI);
- }
- }
-
-
-
- // Process car on fire
- // A similar calculation of damagePos is done elsewhere for smoke
-
- uint8 engineStatus = Damage.GetEngineStatus();
- CVector damagePos = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->m_positions[CAR_POS_HEADLIGHTS];
-
- switch(Damage.GetDoorStatus(DOOR_BONNET)){
- case DOOR_STATUS_OK:
- case DOOR_STATUS_SMASHED:
- // Bonnet is still there, smoke comes out at the edge
- damagePos += vecDAMAGE_ENGINE_POS_SMALL;
- break;
- case DOOR_STATUS_SWINGING:
- case DOOR_STATUS_MISSING:
- // Bonnet is gone, smoke comes out at the engine
- damagePos += vecDAMAGE_ENGINE_POS_BIG;
- break;
- }
-
- // move fire forward if in first person
- if(this == FindPlayerVehicle() && TheCamera.GetLookingForwardFirstPerson())
- if(m_fHealth < 250.0f && m_status != STATUS_WRECKED){
- if(GetModelIndex() == MI_FIRETRUCK)
- damagePos += CVector(0.0f, 3.0f, -0.2f);
- else
- damagePos += CVector(0.0f, 1.2f, -0.8f);
- }
-
- damagePos = GetMatrix()*damagePos;
- damagePos.z += 0.15f;
-
- if(m_fHealth < 250.0f && m_status != STATUS_WRECKED){
- // Car is on fire
-
- CParticle::AddParticle(PARTICLE_CARFLAME, damagePos,
- CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.01125f, 0.09f)),
- nil, 0.9f);
-
- CVector coors = damagePos;
- coors.x += CGeneral::GetRandomNumberInRange(-0.5625f, 0.5625f),
- coors.y += CGeneral::GetRandomNumberInRange(-0.5625f, 0.5625f),
- coors.z += CGeneral::GetRandomNumberInRange(0.5625f, 2.25f);
- CParticle::AddParticle(PARTICLE_CARFLAME_SMOKE, coors, CVector(0.0f, 0.0f, 0.0f));
-
- CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, damagePos, CVector(0.0f, 0.0f, 0.0f), nil, 0.5f);
-
- // Blow up car after 5 seconds
- m_fFireBlowUpTimer += CTimer::GetTimeStepInMilliseconds();
- if(m_fFireBlowUpTimer > 5000.0f){
- CWorld::Players[CWorld::PlayerInFocus].AwardMoneyForExplosion(this);
- BlowUpCar(m_pSetOnFireEntity);
- }
- }else
- m_fFireBlowUpTimer = 0.0f;
-
- // Decrease car health if engine is damaged badly
- if(engineStatus > ENGINE_STATUS_ON_FIRE && m_fHealth > 250.0f)
- m_fHealth -= 2.0f;
-
- ProcessDelayedExplosion();
-
-
- if(m_bSirenOrAlarm && (CTimer::GetFrameCounter()&7) == 5 &&
- UsesSiren(GetModelIndex()) && GetModelIndex() != MI_RCBANDIT)
- CCarAI::MakeWayForCarWithSiren(this);
-
-
- // Find out how much to shake the pad depending on suspension and ground surface
-
- float suspShake = 0.0f;
- float surfShake = 0.0f;
- for(i = 0; i < 4; i++){
- float suspChange = m_aSuspensionSpringRatioPrev[i] - m_aSuspensionSpringRatio[i];
- if(suspChange > 0.3f){
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP, suspChange);
- if(suspChange > suspShake)
- suspShake = suspChange;
- }
-
- uint8 surf = m_aWheelColPoints[i].surfaceB;
- if(surf == SURFACE_DIRT || surf == SURFACE_PUDDLE || surf == SURFACE_HEDGE){
- if(surfShake < 0.2f)
- surfShake = 0.3f;
- }else if(surf == SURFACE_DIRTTRACK || surf == SURFACE_SAND){
- if(surfShake < 0.1f)
- surfShake = 0.2f;
- }else if(surf == SURFACE_GRASS){
- if(surfShake < 0.05f)
- surfShake = 0.1f;
- }
-
- m_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i];
- m_aSuspensionSpringRatio[i] = 1.0f;
- }
-
- // Shake pad
-
- if((suspShake > 0.0f || surfShake > 0.0f) && m_status == STATUS_PLAYER){
- float speed = m_vecMoveSpeed.MagnitudeSqr();
- if(speed > sq(0.1f)){
- speed = Sqrt(speed);
- if(suspShake > 0.0f){
- uint8 freq = Min(200.0f*suspShake*speed*2000.0f/m_fMass + 100.0f, 250.0f);
- CPad::GetPad(0)->StartShake(20000.0f*CTimer::GetTimeStep()/freq, freq);
- }else{
- uint8 freq = Min(200.0f*surfShake*speed*2000.0f/m_fMass + 40.0f, 145.0f);
- CPad::GetPad(0)->StartShake(5000.0f*CTimer::GetTimeStep()/freq, freq);
- }
- }
- }
-
- bVehicleColProcessed = false;
-
- if(!bWarnedPeds)
- CCarCtrl::ScanForPedDanger(this);
-
-
- // Turn around at the edge of the world
- // TODO: make the numbers defines
-
- float heading;
- if(GetPosition().x > 1900.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 < -1900.0f){
- if(m_vecMoveSpeed.x < 0.0f)
- m_vecMoveSpeed.x *= -1.0f;
- heading = GetForward().Heading();
- if(heading < 0.0f) // going east
- SetHeading(-heading);
- }
- if(GetPosition().y > 1900.0f){
- if(m_vecMoveSpeed.y > 0.0f)
- m_vecMoveSpeed.y *= -1.0f;
- heading = GetForward().Heading();
- if(heading < HALFPI && heading > 0.0f)
- SetHeading(PI-heading);
- else if(heading > -HALFPI && heading < 0.0f)
- SetHeading(-PI-heading);
- }else if(GetPosition().y < -1900.0f){
- if(m_vecMoveSpeed.y < 0.0f)
- m_vecMoveSpeed.y *= -1.0f;
- heading = GetForward().Heading();
- if(heading > HALFPI)
- SetHeading(PI-heading);
- else if(heading < -HALFPI)
- SetHeading(-PI-heading);
- }
-
- if(bInfiniteMass){
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);
- m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);
- }else if(!skipPhysics &&
- (m_fGasPedal == 0.0f && brake == 0.0f || m_status == STATUS_WRECKED)){
- if(Abs(m_vecMoveSpeed.x) < 0.005f &&
- Abs(m_vecMoveSpeed.y) < 0.005f &&
- Abs(m_vecMoveSpeed.z) < 0.005f){
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- m_vecTurnSpeed.z = 0.0f;
- }
- }
-}
-
-void
-CAutomobile::Teleport(CVector pos)
-{
- CWorld::Remove(this);
-
- GetPosition() = pos;
- SetOrientation(0.0f, 0.0f, 0.0f);
- SetMoveSpeed(0.0f, 0.0f, 0.0f);
- SetTurnSpeed(0.0f, 0.0f, 0.0f);
-
- ResetSuspension();
-
- CWorld::Add(this);
-}
-
-void
-CAutomobile::PreRender(void)
-{
- int i, j, n;
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
-
- if(GetModelIndex() == MI_RCBANDIT){
- CVector pos = GetMatrix() * CVector(0.218f, -0.444f, 0.391f);
- CAntennas::RegisterOne((uintptr)this, GetUp(), pos, 1.0f);
- }
-
- float fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward())*180.0f;
-
-
- // Wheel particles
-
- if(GetModelIndex() == MI_DODO){
- ; // nothing
- }else if(GetModelIndex() == MI_RCBANDIT){
- for(i = 0; i < 4; i++){
- // Game has same code three times here
- switch(m_aWheelState[i]){
- case WHEEL_STATE_SPINNING:
- case WHEEL_STATE_SKIDDING:
- case WHEEL_STATE_FIXED:
- CParticle::AddParticle(PARTICLE_RUBBER_SMOKE,
- m_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.05f),
- CVector(0.0f, 0.0f, 0.0f), nil, 0.1f);
- break;
- }
- }
- }else{
- if(m_status == STATUS_SIMPLE){
- CMatrix mat;
- CVector pos;
-
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RB]));
- pos = mat.GetPosition();
- pos.z = 1.5f*m_aWheelPosition[CARWHEEL_REAR_RIGHT];
- m_aWheelColPoints[CARWHEEL_REAR_RIGHT].point = GetMatrix() * pos;
- m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB = SURFACE_DEFAULT;
-
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LB]));
- pos = mat.GetPosition();
- pos.z = 1.5f*m_aWheelPosition[CARWHEEL_REAR_LEFT];
- m_aWheelColPoints[CARWHEEL_REAR_LEFT].point = GetMatrix() * pos;
- m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB = SURFACE_DEFAULT;
-
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
- pos = mat.GetPosition();
- pos.z = 1.5f*m_aWheelPosition[CARWHEEL_FRONT_RIGHT];
- m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].point = GetMatrix() * pos;
- m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB = SURFACE_DEFAULT;
-
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
- pos = mat.GetPosition();
- pos.z = 1.5f*m_aWheelPosition[CARWHEEL_FRONT_LEFT];
- m_aWheelColPoints[CARWHEEL_FRONT_LEFT].point = GetMatrix() * pos;
- m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB = SURFACE_DEFAULT;
- }
-
- int drawParticles = Abs(fwdSpeed) < 90.0f;
- if(m_status == STATUS_SIMPLE || m_status == STATUS_PHYSICS ||
- m_status == STATUS_PLAYER || m_status == STATUS_PLAYER_PLAYBACKFROMBUFFER){
- bool rearSkidding = false;
- if(m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SKIDDING ||
- m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SKIDDING)
- rearSkidding = true;
-
- for(i = 0; i < 4; i++){
- switch(m_aWheelState[i]){
- case WHEEL_STATE_SPINNING:
- if(AddWheelDirtAndWater(&m_aWheelColPoints[i], drawParticles)){
- CParticle::AddParticle(PARTICLE_BURNINGRUBBER_SMOKE,
- m_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.25f),
- CVector(0.0f, 0.0f, 0.0f));
-
- CParticle::AddParticle(PARTICLE_BURNINGRUBBER_SMOKE,
- m_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.25f),
- CVector(0.0f, 0.0f, 0.05f));
- }
-
- CParticle::AddParticle(PARTICLE_RUBBER_SMOKE,
- m_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.25f),
- CVector(0.0f, 0.0f, 0.0f));
-
- if(m_aWheelTimer[i] > 0.0f)
- CSkidmarks::RegisterOne((uintptr)this + i, m_aWheelColPoints[i].point,
- GetForward().x, GetForward().y,
- &m_aWheelSkidmarkMuddy[i], &m_aWheelSkidmarkBloody[i]);
- break;
-
- case WHEEL_STATE_SKIDDING:
- if(i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT || rearSkidding){
- // same as below
-
- AddWheelDirtAndWater(&m_aWheelColPoints[i], drawParticles);
-
- CParticle::AddParticle(PARTICLE_RUBBER_SMOKE,
- m_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.25f),
- CVector(0.0f, 0.0f, 0.0f));
-
- if(m_aWheelTimer[i] > 0.0f)
- CSkidmarks::RegisterOne((uintptr)this + i, m_aWheelColPoints[i].point,
- GetForward().x, GetForward().y,
- &m_aWheelSkidmarkMuddy[i], &m_aWheelSkidmarkBloody[i]);
- }
- break;
-
- case WHEEL_STATE_FIXED:
- AddWheelDirtAndWater(&m_aWheelColPoints[i], drawParticles);
-
- CParticle::AddParticle(PARTICLE_RUBBER_SMOKE,
- m_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.25f),
- CVector(0.0f, 0.0f, 0.0f));
-
- if(m_aWheelTimer[i] > 0.0f)
- CSkidmarks::RegisterOne((uintptr)this + i, m_aWheelColPoints[i].point,
- GetForward().x, GetForward().y,
- &m_aWheelSkidmarkMuddy[i], &m_aWheelSkidmarkBloody[i]);
- break;
-
- default:
- if(Abs(fwdSpeed) > 0.5f)
- AddWheelDirtAndWater(&m_aWheelColPoints[i], drawParticles);
- if(m_aWheelSkidmarkBloody[i] && m_aWheelTimer[i] > 0.0f)
- CSkidmarks::RegisterOne((uintptr)this + i, m_aWheelColPoints[i].point,
- GetForward().x, GetForward().y,
- &m_aWheelSkidmarkMuddy[i], &m_aWheelSkidmarkBloody[i]);
- }
- }
- }
- }
-
- if(m_aCarNodes[CAR_WHEEL_RM]){
- // assume middle wheels are two units before rear ones
- CVector offset = GetForward()*2.0f;
-
- switch(m_aWheelState[CARWHEEL_REAR_LEFT]){
- // Game has same code three times here
- case WHEEL_STATE_SPINNING:
- case WHEEL_STATE_SKIDDING:
- case WHEEL_STATE_FIXED:
- CParticle::AddParticle(PARTICLE_RUBBER_SMOKE,
- m_aWheelColPoints[CARWHEEL_REAR_LEFT].point + CVector(0.0f, 0.0f, 0.25f) + offset,
- CVector(0.0f, 0.0f, 0.0f));
-
- if(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f)
- CSkidmarks::RegisterOne((uintptr)this + CARWHEEL_REAR_LEFT,
- m_aWheelColPoints[CARWHEEL_REAR_LEFT].point + offset,
- GetForward().x, GetForward().y,
- &m_aWheelSkidmarkMuddy[CARWHEEL_REAR_LEFT], &m_aWheelSkidmarkBloody[CARWHEEL_REAR_LEFT]);
- break;
- }
-
- switch(m_aWheelState[CARWHEEL_REAR_RIGHT]){
- // Game has same code three times here
- case WHEEL_STATE_SPINNING:
- case WHEEL_STATE_SKIDDING:
- case WHEEL_STATE_FIXED:
- CParticle::AddParticle(PARTICLE_RUBBER_SMOKE,
- m_aWheelColPoints[CARWHEEL_REAR_RIGHT].point + CVector(0.0f, 0.0f, 0.25f) + offset,
- CVector(0.0f, 0.0f, 0.0f));
-
- if(m_aWheelTimer[CARWHEEL_REAR_RIGHT] > 0.0f)
- CSkidmarks::RegisterOne((uintptr)this + CARWHEEL_REAR_RIGHT,
- m_aWheelColPoints[CARWHEEL_REAR_RIGHT].point + offset,
- GetForward().x, GetForward().y,
- &m_aWheelSkidmarkMuddy[CARWHEEL_REAR_RIGHT], &m_aWheelSkidmarkBloody[CARWHEEL_REAR_RIGHT]);
- break;
- }
- }
-
-
- // Rain on roof
- if(!CCullZones::CamNoRain() && !CCullZones::PlayerNoRain() &&
- Abs(fwdSpeed) < 20.0f && CWeather::Rain > 0.02f){
- CColModel *colModel = GetColModel();
-
- for(i = 0; i < colModel->numTriangles; i++){
- CVector p1, p2, p3, c;
-
- colModel->GetTrianglePoint(p1, colModel->triangles[i].a);
- p1 = GetMatrix() * p1;
- colModel->GetTrianglePoint(p2, colModel->triangles[i].b);
- p2 = GetMatrix() * p2;
- colModel->GetTrianglePoint(p3, colModel->triangles[i].c);
- p3 = GetMatrix() * p3;
- c = (p1 + p2 + p3)/3.0f;
-
- n = 6.0f*CWeather::Rain;
- for(j = 0; j <= n; j++)
- CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP,
- c + CVector(CGeneral::GetRandomNumberInRange(-.04f, 0.4f), CGeneral::GetRandomNumberInRange(-.04f, 0.4f), 0.0f),
- CVector(0.0f, 0.0f, 0.0f),
- nil, 0.0f, 0, 0, CGeneral::GetRandomNumber() & 1);
- }
- }
-
- AddDamagedVehicleParticles();
-
- // Exhaust smoke
- if(bEngineOn && fwdSpeed < 90.0f){
- CVector exhaustPos = mi->m_positions[CAR_POS_EXHAUST];
- CVector pos1, pos2, dir;
-
- if(exhaustPos != CVector(0.0f, 0.0f, 0.0f)){
- dir.z = 0.0f;
- if(fwdSpeed < 10.0f){
- CVector steerFwd(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f);
- steerFwd = Multiply3x3(GetMatrix(), steerFwd);
- float r = CGeneral::GetRandomNumberInRange(-0.06f, -0.03f);
- dir.x = steerFwd.x * r;
- dir.y = steerFwd.y * r;
- }else{
- dir.x = m_vecMoveSpeed.x;
- dir.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;
- }
-
- n = 4.0f*m_fGasPedal;
- if(dblExhaust)
- for(i = 0; i <= n; i++){
- CParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos1, dir);
- CParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos2, dir);
- }
- else
- for(i = 0; i <= n; i++)
- CParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos1, dir);
- }
- }
-
-
- // Siren and taxi lights
- switch(GetModelIndex()){
- case MI_FIRETRUCK:
- case MI_AMBULAN:
- case MI_POLICE:
- case MI_ENFORCER:
- if(m_bSirenOrAlarm){
- CVector pos1, pos2;
- uint8 r1, g1, b1;
- uint8 r2, g2, b2;
- uint8 r, g, b;
-
- switch(GetModelIndex()){
- case MI_FIRETRUCK:
- pos1 = CVector(1.1f, 1.7f, 2.0f);
- pos2 = CVector(-1.1f, 1.7f, 2.0f);
- 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);
- 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);
- 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);
- r1 = 255; g1 = 0; b1 = 0;
- r2 = 0; g2 = 0; b2 = 255;
- break;
- }
-
- uint32 t = CTimer::GetTimeInMilliseconds() & 0x3FF; // 1023
- if(t < 512){
- r = r1/6;
- g = g1/6;
- b = b1/6;
- }else{
- r = r2/6;
- g = g2/6;
- b = b2/6;
- }
-
- t = CTimer::GetTimeInMilliseconds() & 0x1FF; // 511
- if(t < 100){
- float f = t/100.0f;
- r *= f;
- g *= f;
- b *= f;
- }else if(t > 412){
- float f = (512-t)/100.0f;
- r *= f;
- g *= f;
- b *= f;
- }
-
- CVector pos = GetPosition();
- float angle = (CTimer::GetTimeInMilliseconds() & 0x3FF)*TWOPI/0x3FF;
- float s = 8.0f*Sin(angle);
- float c = 8.0f*Cos(angle);
- CShadows::StoreCarLightShadow(this, (uintptr)this + 21, gpShadowHeadLightsTex,
- &pos, c, s, s, -c, r, g, b, 8.0f);
-
- CPointLights::AddLight(CPointLights::LIGHT_POINT,
- pos + GetUp()*2.0f, CVector(0.0f, 0.0f, 0.0f), 12.0f,
- r*0.02f, g*0.02f, b*0.02f, CPointLights::FOG_NONE, true);
-
- pos1 = GetMatrix() * pos1;
- pos2 = GetMatrix() * pos2;
-
- for(i = 0; i < 4; i++){
- uint8 sirenTimer = ((CTimer::GetTimeInMilliseconds() + (i<<6))>>8) & 3;
- pos = (pos1*i + pos2*(3.0f-i))/3.0f;
-
- switch(sirenTimer){
- case 0:
- CCoronas::RegisterCorona((uintptr)this + 21 + i,
- r1, g1, b1, 255,
- pos, 0.4f, 50.0f,
- CCoronas::TYPE_STAR,
- i == 1 ? CCoronas::FLARE_HEADLIGHTS : CCoronas::FLARE_NONE,
- CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- break;
- case 2:
- CCoronas::RegisterCorona((uintptr)this + 21 + i,
- r2, g2, b2, 255,
- pos, 0.4f, 50.0f,
- CCoronas::TYPE_STAR,
- CCoronas::FLARE_NONE,
- CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- break;
- default:
- CCoronas::UpdateCoronaCoors((uintptr)this + 21 + i, pos, 50.0f, 0.0f);
- break;
- }
- }
- }
- break;
-
- case MI_FBICAR:
- if(m_bSirenOrAlarm){
- CVector pos = GetMatrix() * CVector(0.4f, 0.6f, 0.3f);
- if(CTimer::GetTimeInMilliseconds() & 0x100 &&
- DotProduct(GetForward(), GetPosition() - TheCamera.GetPosition()) < 0.0f)
- CCoronas::RegisterCorona((uintptr)this + 21,
- 0, 0, 255, 255,
- pos, 0.4f, 50.0f,
- CCoronas::TYPE_STAR,
- CCoronas::FLARE_NONE,
- CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- else
- CCoronas::UpdateCoronaCoors((uintptr)this + 21, pos, 50.0f, 0.0f);
- }
- break;
-
- case MI_TAXI:
- case MI_CABBIE:
- case MI_BORGNINE:
- if(bTaxiLight){
- CVector pos = GetPosition() + GetUp()*0.95f;
- 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), 10.0f,
- 1.0f, 1.0f, 0.5f, CPointLights::FOG_NONE, true);
- }
- break;
- }
-
- if(GetModelIndex() == MI_RCBANDIT ||
- GetModelIndex() == MI_DODO ||
- GetModelIndex() == MI_RHINO)
- goto nolights;
-
- // Turn lights on/off
- bool shouldLightsBeOn =
- CClock::GetHours() > 20 ||
- CClock::GetHours() > 19 && CClock::GetMinutes() > (m_randomSeed & 0x3F) ||
- CClock::GetHours() < 7 ||
- CClock::GetHours() < 8 && CClock::GetMinutes() < (m_randomSeed & 0x3F) ||
- m_randomSeed/50000.0f < CWeather::Foggyness ||
- m_randomSeed/50000.0f < CWeather::WetRoads;
- if(shouldLightsBeOn != bLightsOn && m_status != STATUS_WRECKED){
- if(m_status == STATUS_ABANDONED){
- // Turn off lights on abandoned vehicles only when we they're far away
- if(bLightsOn &&
- Abs(TheCamera.GetPosition().x - GetPosition().x) + Abs(TheCamera.GetPosition().y - GetPosition().y) > 100.0f)
- bLightsOn = false;
- }else
- bLightsOn = shouldLightsBeOn;
- }
-
- // Actually render the lights
- bool alarmOn = false;
- bool alarmOff = false;
- if(IsAlarmOn()){
- if(CTimer::GetTimeInMilliseconds() & 0x100)
- alarmOn = true;
- else
- alarmOff = true;
- }
- if(bEngineOn && bLightsOn || alarmOn || alarmOff){
- CVector lookVector = GetPosition() - TheCamera.GetPosition();
- float camDist = lookVector.Magnitude();
- if(camDist != 0.0f)
- lookVector *= 1.0f/camDist;
- else
- lookVector = CVector(1.0f, 0.0f, 0.0f);
-
- // 1.0 if directly behind car, -1.0 if in front
- // BUG on PC: Abs of DotProduct is taken
- float behindness = DotProduct(lookVector, GetForward());
- behindness = clamp(behindness, -1.0f, 1.0f); // shouldn't be necessary
- // 0.0 if behind car, PI if in front
- // Abs not necessary
- float angle = Abs(Acos(behindness));
-
- // Headlights
-
- CVector headLightPos = mi->m_positions[CAR_POS_HEADLIGHTS];
- CVector lightR = GetMatrix() * headLightPos;
- CVector lightL = lightR;
- lightL -= GetRight()*2.0f*headLightPos.x;
-
- // Headlight coronas
- if(behindness < 0.0f){
- // In front of car
- float intensity = -0.5f*behindness + 0.3f;
- float size = 1.0f - behindness;
-
- if(behindness < -0.97f && camDist < 30.0f){
- // Directly in front and not too far away
- if(pHandling->Flags & HANDLING_HALOGEN_LIGHTS){
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 6, 150, 150, 195, 255,
- lightL, 1.2f, 45.0f*TheCamera.LODDistMultiplier,
- CCoronas::TYPE_HEADLIGHT, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, angle);
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 7, 150, 150, 195, 255,
- lightR, 1.2f, 45.0f*TheCamera.LODDistMultiplier,
- CCoronas::TYPE_HEADLIGHT, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, angle);
- }else{
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 6, 160, 160, 140, 255,
- lightL, 1.2f, 45.0f*TheCamera.LODDistMultiplier,
- CCoronas::TYPE_HEADLIGHT, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, angle);
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 7, 160, 160, 140, 255,
- lightR, 1.2f, 45.0f*TheCamera.LODDistMultiplier,
- CCoronas::TYPE_HEADLIGHT, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, angle);
- }
- }
-
- if(alarmOff){
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this, 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_FRONT_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 1, 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(pHandling->Flags & HANDLING_HALOGEN_LIGHTS){
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this, 190*intensity, 190*intensity, 255*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_FRONT_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 1, 190*intensity, 190*intensity, 255*intensity, 255,
- lightR, size, 50.0f*TheCamera.LODDistMultiplier,
- CCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);
- }else{
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this, 210*intensity, 210*intensity, 195*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_FRONT_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 1, 210*intensity, 210*intensity, 195*intensity, 255,
- lightR, size, 50.0f*TheCamera.LODDistMultiplier,
- CCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);
- }
- }
- }else{
- // Behind car
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)
- CCoronas::UpdateCoronaCoors((uintptr)this, lightL, 50.0f*TheCamera.LODDistMultiplier, angle);
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::UpdateCoronaCoors((uintptr)this + 1, lightR, 50.0f*TheCamera.LODDistMultiplier, angle);
- }
-
- // bright lights
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK && !bNoBrightHeadLights)
- CBrightLights::RegisterOne(lightL, GetUp(), GetRight(), GetForward(), pHandling->FrontLights + 4);
- if(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK && !bNoBrightHeadLights)
- CBrightLights::RegisterOne(lightR, GetUp(), GetRight(), GetForward(), pHandling->FrontLights + 4);
-
- // Taillights
-
- CVector tailLightPos = mi->m_positions[CAR_POS_TAILLIGHTS];
- lightR = GetMatrix() * tailLightPos;
- lightL = lightR;
- lightL -= GetRight()*2.0f*tailLightPos.x;
-
- // Taillight coronas
- if(behindness > 0.0f){
- // Behind car
- float intensity = 0.4f*behindness + 0.4;
- float size = (behindness + 1.0f)/2.0f;
-
- if(m_fGasPedal < 0.0f){
- // reversing
- intensity += 0.4f;
- size += 0.3f;
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)
- 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 + 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);
- }else{
- if(m_fBrakePedal > 0.0){
- intensity += 0.4f;
- size += 0.3f;
- }
-
- if(alarmOff){
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)
- 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 + 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 + 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 + 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);
- }
- }
- }else{
- // In front of car
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)
- CCoronas::UpdateCoronaCoors((uintptr)this + 2, lightL, 50.0f*TheCamera.LODDistMultiplier, angle);
- if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::UpdateCoronaCoors((uintptr)this + 3, lightR, 50.0f*TheCamera.LODDistMultiplier, angle);
- }
-
- // bright lights
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)
- CBrightLights::RegisterOne(lightL, GetUp(), GetRight(), GetForward(), pHandling->RearLights + 8);
- if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)
- CBrightLights::RegisterOne(lightR, GetUp(), GetRight(), GetForward(), pHandling->RearLights + 8);
-
- // Light shadows
- if(!alarmOff){
- CVector pos = GetPosition();
- CVector2D fwd(GetForward());
- fwd.Normalise();
- float f = headLightPos.y + 6.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)
- CShadows::StoreCarLightShadow(this, (uintptr)this + 22, gpShadowHeadLightsTex, &pos,
- 7.0f*fwd.x, 7.0f*fwd.y, 7.0f*fwd.y, -7.0f*fwd.x, 45, 45, 45, 7.0f);
-
- f = (tailLightPos.y - 2.5f) - (headLightPos.y + 6.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(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,
- FindPlayerVehicle()->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.45f) ? CPointLights::FOG_NORMAL : CPointLights::FOG_NONE,
- false);
- CVector pos = GetPosition() - 4.0f*GetForward();
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK ||
- 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,
- 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,
- CPointLights::FOG_NONE, false);
- }
- }else{
- // Lights off
-
- if(m_status == STATUS_ABANDONED || m_status == STATUS_WRECKED)
- goto nolights;
-
- CVector lightPos = mi->m_positions[CAR_POS_TAILLIGHTS];
- CVector lightR = GetMatrix() * lightPos;
- CVector lightL = lightR;
- lightL -= GetRight()*2.0f*lightPos.x;
-
- if(m_fBrakePedal > 0.0f || m_fGasPedal < 0.0f){
- CVector lookVector = GetPosition() - TheCamera.GetPosition();
- lookVector.Normalise();
- float behindness = DotProduct(lookVector, GetForward());
- if(behindness > 0.0f){
- if(m_fGasPedal < 0.0f){
- // reversing
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 2, 120, 120, 120, 255,
- lightL, 1.2f, 50.0f*TheCamera.LODDistMultiplier,
- CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
- if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 3, 120, 120, 120, 255,
- lightR, 1.2f, 50.0f*TheCamera.LODDistMultiplier,
- CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)
- CBrightLights::RegisterOne(lightL, GetUp(), GetRight(), GetForward(), pHandling->RearLights + 4);
- if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)
- CBrightLights::RegisterOne(lightR, GetUp(), GetRight(), GetForward(), pHandling->RearLights + 4);
- }else{
- // braking
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 2, 120, 0, 0, 255,
- lightL, 1.2f, 50.0f*TheCamera.LODDistMultiplier,
- CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
- if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::RegisterCorona((uintptr)this + 3, 120, 0, 0, 255,
- lightR, 1.2f, 50.0f*TheCamera.LODDistMultiplier,
- CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)
- CBrightLights::RegisterOne(lightL, GetUp(), GetRight(), GetForward(), pHandling->RearLights + 8);
- if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)
- CBrightLights::RegisterOne(lightR, GetUp(), GetRight(), GetForward(), pHandling->RearLights + 8);
- }
- }else{
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)
- CCoronas::UpdateCoronaCoors((uintptr)this + 2, lightL, 50.0f*TheCamera.LODDistMultiplier, 0.0f);
- if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::UpdateCoronaCoors((uintptr)this + 3, lightR, 50.0f*TheCamera.LODDistMultiplier, 0.0f);
- }
- }else{
- if(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)
- CCoronas::UpdateCoronaCoors((uintptr)this + 2, lightL, 50.0f*TheCamera.LODDistMultiplier, 0.0f);
- if(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)
- CCoronas::UpdateCoronaCoors((uintptr)this + 3, lightR, 50.0f*TheCamera.LODDistMultiplier, 0.0f);
- }
- }
-
-nolights:
- CShadows::StoreShadowForCar(this);
-}
-
-void
-CAutomobile::Render(void)
-{
- int i;
- CMatrix mat;
- CVector pos;
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
-
- if(GetModelIndex() == MI_RHINO && m_aCarNodes[CAR_BONNET]){
- // Rhino has no bonnet...what are we doing here?
- CMatrix m;
- CVector p;
- m.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BONNET]));
- p = m.GetPosition();
- m.SetRotateZ(m_fCarGunLR);
- m.Translate(p);
- m.UpdateRW();
- }
-
- 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++){
- 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];
- }
-
- // Rear right wheel
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RB]));
- pos.x = mat.GetPosition().x;
- pos.y = mat.GetPosition().y;
- pos.z = m_aWheelPosition[CARWHEEL_REAR_RIGHT];
- if(Damage.GetWheelStatus(CARWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST)
- mat.SetRotate(m_aWheelRotation[CARWHEEL_REAR_RIGHT], 0.0f, 0.3f*Sin(m_aWheelRotation[CARWHEEL_REAR_RIGHT]));
- else
- mat.SetRotateX(m_aWheelRotation[CARWHEEL_REAR_RIGHT]);
- mat.Scale(mi->m_wheelScale);
- mat.Translate(pos);
- mat.UpdateRW();
- if(CVehicle::bWheelsOnlyCheat)
- RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]));
-
- // Rear left wheel
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LB]));
- pos.x = mat.GetPosition().x;
- pos.y = mat.GetPosition().y;
- pos.z = m_aWheelPosition[CARWHEEL_REAR_LEFT];
- if(Damage.GetWheelStatus(CARWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST)
- mat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI+0.3f*Sin(-m_aWheelRotation[CARWHEEL_REAR_LEFT]));
- else
- mat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI);
- mat.Scale(mi->m_wheelScale);
- mat.Translate(pos);
- mat.UpdateRW();
- if(CVehicle::bWheelsOnlyCheat)
- RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]));
-
- // Mid right wheel
- if(m_aCarNodes[CAR_WHEEL_RM]){
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RM]));
- pos.x = mat.GetPosition().x;
- pos.y = mat.GetPosition().y;
- pos.z = m_aWheelPosition[CARWHEEL_REAR_RIGHT];
- if(Damage.GetWheelStatus(CARWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST)
- mat.SetRotate(m_aWheelRotation[CARWHEEL_REAR_RIGHT], 0.0f, 0.3f*Sin(m_aWheelRotation[CARWHEEL_REAR_RIGHT]));
- else
- mat.SetRotateX(m_aWheelRotation[CARWHEEL_REAR_RIGHT]);
- mat.Scale(mi->m_wheelScale);
- mat.Translate(pos);
- mat.UpdateRW();
- if(CVehicle::bWheelsOnlyCheat)
- RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RM]));
- }
-
- // Mid left wheel
- if(m_aCarNodes[CAR_WHEEL_LM]){
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LM]));
- pos.x = mat.GetPosition().x;
- pos.y = mat.GetPosition().y;
- pos.z = m_aWheelPosition[CARWHEEL_REAR_LEFT];
- if(Damage.GetWheelStatus(CARWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST)
- mat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI+0.3f*Sin(-m_aWheelRotation[CARWHEEL_REAR_LEFT]));
- else
- mat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI);
- mat.Scale(mi->m_wheelScale);
- mat.Translate(pos);
- mat.UpdateRW();
- if(CVehicle::bWheelsOnlyCheat)
- RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LM]));
- }
-
- if(GetModelIndex() == MI_DODO){
- // Front wheel
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
- pos.x = mat.GetPosition().x;
- pos.y = mat.GetPosition().y;
- pos.z = m_aWheelPosition[CARWHEEL_FRONT_RIGHT];
- if(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST)
- mat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle+0.3f*Sin(m_aWheelRotation[CARWHEEL_FRONT_RIGHT]));
- else
- mat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle);
- mat.Scale(mi->m_wheelScale);
- mat.Translate(pos);
- mat.UpdateRW();
- if(CVehicle::bWheelsOnlyCheat)
- RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]));
-
- // Rotate propeller
- if(m_aCarNodes[CAR_WINDSCREEN]){
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WINDSCREEN]));
- pos = mat.GetPosition();
- mat.SetRotateY(m_fPropellerRotation);
- mat.Translate(pos);
- mat.UpdateRW();
-
- m_fPropellerRotation += m_fGasPedal != 0.0f ? TWOPI/13.0f : TWOPI/26.0f;
- if(m_fPropellerRotation > TWOPI)
- m_fPropellerRotation -= TWOPI;
- }
-
- // Rudder
- if(Damage.GetDoorStatus(DOOR_BOOT) != DOOR_STATUS_MISSING && m_aCarNodes[CAR_BOOT]){
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BOOT]));
- pos = mat.GetPosition();
- mat.SetRotate(0.0f, 0.0f, -m_fSteerAngle);
- mat.Rotate(0.0f, Sin(m_fSteerAngle)*DEGTORAD(22.0f), 0.0f);
- 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]));
- pos.x = mat.GetPosition().x;
- pos.y = mat.GetPosition().y;
- pos.z = m_aWheelPosition[CARWHEEL_FRONT_RIGHT];
- // no damaged wheels or steering
- mat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, 0.0f);
- mat.Scale(mi->m_wheelScale);
- mat.Translate(pos);
- mat.UpdateRW();
- if(CVehicle::bWheelsOnlyCheat)
- RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]));
-
- // Front left wheel
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
- pos.x = mat.GetPosition().x;
- pos.y = mat.GetPosition().y;
- pos.z = m_aWheelPosition[CARWHEEL_FRONT_LEFT];
- // no damaged wheels or steering
- mat.SetRotate(-m_aWheelRotation[CARWHEEL_FRONT_LEFT], 0.0f, PI);
- mat.Scale(mi->m_wheelScale);
- mat.Translate(pos);
- mat.UpdateRW();
- if(CVehicle::bWheelsOnlyCheat)
- RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]));
- }else{
- // Front right wheel
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
- pos.x = mat.GetPosition().x;
- pos.y = mat.GetPosition().y;
- pos.z = m_aWheelPosition[CARWHEEL_FRONT_RIGHT];
- if(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST)
- mat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle+0.3f*Sin(m_aWheelRotation[CARWHEEL_FRONT_RIGHT]));
- else
- mat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle);
- mat.Scale(mi->m_wheelScale);
- mat.Translate(pos);
- mat.UpdateRW();
- if(CVehicle::bWheelsOnlyCheat)
- RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]));
-
- // Front left wheel
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
- pos.x = mat.GetPosition().x;
- pos.y = mat.GetPosition().y;
- pos.z = m_aWheelPosition[CARWHEEL_FRONT_LEFT];
- if(Damage.GetWheelStatus(CARWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST)
- mat.SetRotate(-m_aWheelRotation[CARWHEEL_FRONT_LEFT], 0.0f, PI+m_fSteerAngle+0.3f*Sin(-m_aWheelRotation[CARWHEEL_FRONT_LEFT]));
- else
- mat.SetRotate(-m_aWheelRotation[CARWHEEL_FRONT_LEFT], 0.0f, PI+m_fSteerAngle);
- mat.Scale(mi->m_wheelScale);
- mat.Translate(pos);
- mat.UpdateRW();
- if(CVehicle::bWheelsOnlyCheat)
- RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]));
-
- 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);
-
- mi->SetVehicleColour(m_currentColour1, m_currentColour2);
- }
-
- if(!CVehicle::bWheelsOnlyCheat)
- CEntity::Render();
-}
-
-int32
-CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
-{
- int i;
- CColModel *colModel;
-
- if(m_status != STATUS_SIMPLE)
- bVehicleColProcessed = true;
-
- if(bUsingSpecialColModel)
- colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;
- else
- colModel = GetColModel();
-
- int numWheelCollisions = 0;
- float prevRatios[4] = { 0.0f, 0.0f, 0.0f, 0.0f};
- for(i = 0; i < 4; i++)
- prevRatios[i] = m_aSuspensionSpringRatio[i];
-
- int numCollisions = CCollision::ProcessColModels(GetMatrix(), *colModel,
- ent->GetMatrix(), *ent->GetColModel(),
- colpoints,
- m_aWheelColPoints, m_aSuspensionSpringRatio);
-
- // m_aSuspensionSpringRatio are now set to the point where the tyre touches ground.
- // In ProcessControl these will be re-normalized to ignore the tyre radius.
-
- if(field_EF || m_phy_flagA80 ||
- GetModelIndex() == MI_DODO && (ent->IsPed() || ent->IsVehicle())){
- // don't do line collision
- for(i = 0; i < 4; i++)
- m_aSuspensionSpringRatio[i] = prevRatios[i];
- }else{
- for(i = 0; i < 4; i++)
- if(m_aSuspensionSpringRatio[i] < 1.0f && m_aSuspensionSpringRatio[i] < prevRatios[i]){
- numWheelCollisions++;
-
- // wheel is touching a physical
- if(ent->IsVehicle() || ent->IsObject()){
- CPhysical *phys = (CPhysical*)ent;
-
- m_aGroundPhysical[i] = phys;
- phys->RegisterReference((CEntity**)&m_aGroundPhysical[i]);
- m_aGroundOffset[i] = m_aWheelColPoints[i].point - phys->GetPosition();
-
- if(phys->GetModelIndex() == MI_BODYCAST && m_status == STATUS_PLAYER){
- // damage body cast
- float speed = m_vecMoveSpeed.MagnitudeSqr();
- if(speed > 0.1f){
- CObject::nBodyCastHealth -= 0.1f*m_fMass*speed;
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_PED_BODYCAST_HIT, 0.0f);
- }
-
- // move body cast
- if(phys->bIsStatic){
- phys->bIsStatic = false;
- phys->m_nStaticFrames = 0;
- phys->ApplyMoveForce(m_vecMoveSpeed / speed);
- phys->AddToMovingList();
- }
- }
- }
-
- m_nSurfaceTouched = m_aWheelColPoints[i].surfaceB;
- if(ent->IsBuilding())
- m_pCurGroundEntity = ent;
- }
- }
-
- if(numCollisions > 0 || numWheelCollisions > 0){
- AddCollisionRecord(ent);
- if(!ent->IsBuilding())
- ((CPhysical*)ent)->AddCollisionRecord(this);
-
- if(numCollisions > 0)
- if(ent->IsBuilding() ||
- ent->IsObject() && ((CPhysical*)ent)->bInfiniteMass)
- bHasHitWall = true;
- }
-
- return numCollisions;
-}
-
-static int16 nLastControlInput;
-static float fMouseCentreRange = 0.35f;
-static float fMouseSteerSens = -0.0035f;
-static float fMouseCentreMult = 0.975f;
-
-void
-CAutomobile::ProcessControlInputs(uint8 pad)
-{
- float speed = DotProduct(m_vecMoveSpeed, GetForward());
-
- if(CPad::GetPad(pad)->GetExitVehicle())
- bIsHandbrakeOn = true;
- else
- bIsHandbrakeOn = !!CPad::GetPad(pad)->GetHandBrake();
-
- // Steer left/right
- if(CCamera::m_bUseMouse3rdPerson && !CVehicle::m_bDisableMouseSteering){
- if(CPad::GetPad(pad)->GetMouseX() != 0.0f){
- m_fSteerRatio += fMouseSteerSens*CPad::GetPad(pad)->GetMouseX();
- nLastControlInput = 2;
- if(Abs(m_fSteerRatio) < fMouseCentreRange)
- m_fSteerRatio *= Pow(fMouseCentreMult, CTimer::GetTimeStep());
- }else if(CPad::GetPad(pad)->GetSteeringLeftRight() || nLastControlInput != 2){
- // mouse hasn't move, steer with pad like below
- m_fSteerRatio += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerRatio)*
- 0.2f*CTimer::GetTimeStep();
- nLastControlInput = 0;
- }
- }else{
- m_fSteerRatio += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerRatio)*
- 0.2f*CTimer::GetTimeStep();
- nLastControlInput = 0;
- }
- m_fSteerRatio = clamp(m_fSteerRatio, -1.0f, 1.0f);
-
- // Accelerate/Brake
- float acceleration = (CPad::GetPad(pad)->GetAccelerate() - CPad::GetPad(pad)->GetBrake())/255.0f;
- if(GetModelIndex() == MI_DODO && acceleration < 0.0f)
- acceleration *= 0.3f;
- if(Abs(speed) < 0.01f){
- // standing still, go into direction we want
- m_fGasPedal = acceleration;
- m_fBrakePedal = 0.0f;
- }else{
-#if 1
- // simpler than the code below
- if(speed * acceleration < 0.0f){
- // if opposite directions, have to brake first
- m_fGasPedal = 0.0f;
- m_fBrakePedal = Abs(acceleration);
- }else{
- // accelerating in same direction we were already going
- m_fGasPedal = acceleration;
- m_fBrakePedal = 0.0f;
- }
-#else
- if(speed < 0.0f){
- // moving backwards currently
- if(acceleration < 0.0f){
- // still go backwards
- m_fGasPedal = acceleration;
- m_fBrakePedal = 0.0f;
- }else{
- // want to go forwards, so brake
- m_fGasPedal = 0.0f;
- m_fBrakePedal = acceleration;
- }
- }else{
- // moving forwards currently
- if(acceleration < 0.0f){
- // want to go backwards, so brake
- m_fGasPedal = 0.0f;
- m_fBrakePedal = -acceleration;
- }else{
- // still go forwards
- m_fGasPedal = acceleration;
- m_fBrakePedal = 0.0f;
- }
- }
-#endif
- }
-
- // Actually turn wheels
- static float fValue; // why static?
- if(m_fSteerRatio < 0.0f)
- fValue = -sq(m_fSteerRatio);
- else
- fValue = sq(m_fSteerRatio);
- m_fSteerAngle = DEGTORAD(pHandling->fSteeringLock) * fValue;
-
- if(bComedyControls){
- int rnd = CGeneral::GetRandomNumber() % 10;
- switch(m_comedyControlState){
- case 0:
- if(rnd < 2)
- m_comedyControlState = 1;
- else if(rnd < 4)
- m_comedyControlState = 2;
- break;
- case 1:
- m_fSteerAngle += 0.05f;
- if(rnd < 2)
- m_comedyControlState = 0;
- break;
- case 2:
- m_fSteerAngle -= 0.05f;
- if(rnd < 2)
- m_comedyControlState = 0;
- break;
- }
- }else
- m_comedyControlState = 0;
-
- // Brake if player isn't in control
- // BUG: game always uses pad 0 here
- if(CPad::GetPad(pad)->DisablePlayerControls){
- m_fBrakePedal = 1.0f;
- bIsHandbrakeOn = true;
- m_fGasPedal = 0.0f;
-
- FindPlayerPed()->KeepAreaAroundPlayerClear();
-
- // slow down car immediately
- speed = m_vecMoveSpeed.Magnitude();
- if(speed > 0.28f)
- m_vecMoveSpeed *= 0.28f/speed;
- }
-}
-
-void
-CAutomobile::FireTruckControl(void)
-{
- if(this == FindPlayerVehicle()){
- if(!CPad::GetPad(0)->GetWeapon())
- return;
- 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(m_status == STATUS_PHYSICS){
- CFire *fire = gFireManager.FindFurthestFire_NeverMindFireMen(GetPosition(), 10.0f, 35.0f);
- if(fire == nil)
- return;
-
- // 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);
- cannonDir.z += (CGeneral::GetRandomNumber()&0xF)/1000.0f;
- CWaterCannons::UpdateOne((uintptr)this, &cannonPos, &cannonDir);
- }
- }
-}
-
-void
-CAutomobile::TankControl(void)
-{
- int i;
-
- // These coords are 1 unit higher then they should be relative to model center
- CVector turrentBase(0.0f, -1.394f, 2.296f);
- CVector gunEnd(0.0f, 1.813f, 2.979f);
- CVector baseToEnd = gunEnd - turrentBase;
-
- if(this != FindPlayerVehicle())
- return;
- if(CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING)
- return;
-
- // Rotate turret
- float prevAngle = m_fCarGunLR;
- m_fCarGunLR -= CPad::GetPad(0)->GetCarGunLeftRight() * 0.00015f * CTimer::GetTimeStep();
- if(m_fCarGunLR < 0.0f)
- m_fCarGunLR += TWOPI;
- if(m_fCarGunLR > TWOPI)
- m_fCarGunLR -= TWOPI;
- if(m_fCarGunLR != prevAngle)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_TANK_TURRET_ROTATE, Abs(m_fCarGunLR - prevAngle));
-
- // Shoot
- if(CPad::GetPad(0)->CarGunJustDown() &&
- CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeTankShotGun + 800){
- CWorld::Players[CWorld::PlayerInFocus].m_nTimeTankShotGun = CTimer::GetTimeInMilliseconds();
-
- // more like -sin(angle), cos(angle), i.e. rotated (0,1,0)
- CVector turretDir = CVector(Sin(-m_fCarGunLR), Cos(-m_fCarGunLR), 0.0f);
- turretDir = Multiply3x3(GetMatrix(), turretDir);
-
- float c = Cos(m_fCarGunLR);
- float s = Sin(m_fCarGunLR);
- CVector rotatedEnd(
- c*baseToEnd.x - s*baseToEnd.y,
- s*baseToEnd.x + c*baseToEnd.y,
- baseToEnd.z - 1.0f); // correct offset here
- rotatedEnd += turrentBase;
-
- CVector point1 = GetMatrix() * rotatedEnd;
- CVector point2 = point1 + 60.0f*turretDir;
- m_vecMoveSpeed -= 0.06f*turretDir;
- m_vecMoveSpeed.z += 0.05f;
-
- CWeapon::DoTankDoomAiming(FindPlayerVehicle(), FindPlayerPed(), &point1, &point2);
- CColPoint colpoint;
- CEntity *entity = nil;
- CWorld::ProcessLineOfSight(point1, point2, colpoint, entity, true, true, true, true, true, true, false);
- if(entity)
- point2 = colpoint.point - 0.04f*(colpoint.point - point1);
-
- CExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_TANK_GRENADE, point2, 0);
-
- // Add particles on the way to the explosion;
- float shotDist = (point2 - point1).Magnitude();
- int n = shotDist/4.0f;
- RwRGBA black = { 0, 0, 0, 0 };
- for(i = 0; i < n; i++){
- float f = (float)i/n;
- CParticle::AddParticle(PARTICLE_HELI_DUST,
- point1 + f*(point2 - point1),
- CVector(0.0f, 0.0f, 0.0f),
- nil, 0.1f, black);
- }
-
- // More particles
- CVector shotDir = point2 - point1;
- shotDir.Normalise();
- for(i = 0; i < 15; i++){
- float f = i/15.0f;
- CParticle::AddParticle(PARTICLE_GUNSMOKE2, point1,
- shotDir*CGeneral::GetRandomNumberInRange(0.3f, 1.0f)*f,
- nil, CGeneral::GetRandomNumberInRange(0.5f, 1.0f)*f, black);
- }
-
- // And some gun flashes near the gun
- CVector flashPos = point1;
- CVector nullDir(0.0f, 0.0f, 0.0f);
- int lifeSpan = 250;
- if(m_vecMoveSpeed.Magnitude() > 0.08f){
- lifeSpan = 125;
- flashPos.x += 0.5f*m_vecMoveSpeed.x;
- flashPos.y += 0.5f*m_vecMoveSpeed.y;
- }
- CParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.4f, black, 0, 0, 0, lifeSpan);
- flashPos += 0.3f*shotDir;
- CParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.2f, black, 0, 0, 0, lifeSpan);
- flashPos += 0.1f*shotDir;
- CParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.15f, black, 0, 0, 0, lifeSpan);
- }
-
- // Actually update turret node
- if(m_aCarNodes[CAR_WINDSCREEN]){
- CMatrix mat;
- CVector pos;
-
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WINDSCREEN]));
- pos = mat.GetPosition();
- mat.SetRotateZ(m_fCarGunLR);
- mat.Translate(pos);
- mat.UpdateRW();
- }
-}
-
-void
-CAutomobile::HydraulicControl(void)
-{
- int i;
- float wheelPositions[4];
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
- CColModel *normalColModel = mi->GetColModel();
- float wheelRadius = 0.5f*mi->m_wheelScale;
- CPlayerInfo *playerInfo = &CWorld::Players[CWorld::PlayerInFocus];
- CColModel *specialColModel = &playerInfo->m_ColModel;
-
- if(m_status != STATUS_PLAYER){
- // reset hydraulics for non-player cars
-
- if(!bUsingSpecialColModel)
- return;
- if(specialColModel != nil) // this is always true
- for(i = 0; i < 4; i++)
- wheelPositions[i] = specialColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];
- for(i = 0; i < 4; i++){
- m_aSuspensionSpringLength[i] = pHandling->fSuspensionUpperLimit - pHandling->fSuspensionLowerLimit;
- m_aSuspensionLineLength[i] = normalColModel->lines[i].p0.z - normalColModel->lines[i].p1.z;
- m_aSuspensionSpringRatio[i] = (normalColModel->lines[i].p0.z - wheelPositions[i]) / m_aSuspensionLineLength[i];
- if(m_aSuspensionSpringRatio[i] > 1.0f)
- m_aSuspensionSpringRatio[i] = 1.0f;
- }
-
- if(m_hydraulicState == 0)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_1, 0.0f);
- else if(m_hydraulicState >= 100)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);
-
- if(playerInfo->m_pVehicleEx == this)
- playerInfo->m_pVehicleEx = nil;
- bUsingSpecialColModel = false;
- m_hydraulicState = 0;
- return;
- }
-
- // Player car
-
- float normalUpperLimit = pHandling->fSuspensionUpperLimit;
- float normalLowerLimit = pHandling->fSuspensionLowerLimit;
- float normalSpringLength = normalUpperLimit - normalLowerLimit;
- float extendedUpperLimit = normalUpperLimit - 0.2f;
- float extendedLowerLimit = normalLowerLimit - 0.2f;
- float extendedSpringLength = extendedUpperLimit - extendedLowerLimit;
-
- if(!bUsingSpecialColModel){
- // Init special col model
-
- if(playerInfo->m_pVehicleEx && playerInfo->m_pVehicleEx == this)
- playerInfo->m_pVehicleEx->bUsingSpecialColModel = false;
- playerInfo->m_pVehicleEx = this;
- playerInfo->m_ColModel = *normalColModel;
- bUsingSpecialColModel = true;
- specialColModel = &playerInfo->m_ColModel;
-
- if(m_fVelocityChangeForAudio > 0.1f)
- m_hydraulicState = 20;
- else{
- m_hydraulicState = 0;
- normalUpperLimit += -0.12f;
- normalSpringLength = normalUpperLimit - (normalLowerLimit+0.14f);
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);
- }
-
- // Setup suspension
- float normalLineLength = normalSpringLength + wheelRadius;
- CVector pos;
- for(i = 0; i < 4; i++){
- wheelPositions[i] = normalColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];
- mi->GetWheelPosn(i, pos);
- pos.z += normalUpperLimit;
- specialColModel->lines[i].p0 = pos;
- pos.z -= normalLineLength;
- specialColModel->lines[i].p1 = pos;
- m_aSuspensionSpringLength[i] = normalSpringLength;
- m_aSuspensionLineLength[i] = normalLineLength;
-
- if(m_aSuspensionSpringRatio[i] < 1.0f){
- m_aSuspensionSpringRatio[i] = (specialColModel->lines[i].p0.z - wheelPositions[i])/m_aSuspensionLineLength[i];
- if(m_aSuspensionSpringRatio[i] > 1.0f)
- m_aSuspensionSpringRatio[i] = 1.0f;
- }
- }
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);
-
- // Adjust col model
- mi->GetWheelPosn(0, pos);
- float minz = pos.z + extendedLowerLimit - wheelRadius;
- if(minz < specialColModel->boundingBox.min.z)
- specialColModel->boundingBox.min.z = minz;
- float radius = Max(specialColModel->boundingBox.min.Magnitude(), specialColModel->boundingBox.max.Magnitude());
- if(specialColModel->boundingSphere.radius < radius)
- specialColModel->boundingSphere.radius = radius;
-
- }
-
- if(playerInfo->m_WBState != WBSTATE_PLAYING)
- return;
-
- bool setPrevRatio = false;
- if(m_hydraulicState < 20 && m_fVelocityChangeForAudio > 0.2f){
- if(m_hydraulicState == 0){
- m_hydraulicState = 20;
- for(i = 0; i < 4; i++)
- m_aWheelPosition[i] -= 0.06f;
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_1, 0.0f);
- setPrevRatio = true;
- }else{
- m_hydraulicState++;
- }
- }else if(m_hydraulicState != 0){ // must always be true
- if(m_hydraulicState < 21 && m_fVelocityChangeForAudio < 0.1f){
- m_hydraulicState--;
- if(m_hydraulicState == 0)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);
- }
- }
-
- if(CPad::GetPad(0)->HornJustDown()){
- // Switch between normal and extended
-
- if(m_hydraulicState < 100)
- m_hydraulicState = 100;
- else{
- if(m_fVelocityChangeForAudio > 0.1f)
- m_hydraulicState = 20;
- else
- m_hydraulicState = 0;
- }
-
- if(m_hydraulicState < 100){
- if(m_hydraulicState == 0){
- normalUpperLimit += -0.12f;
- normalLowerLimit += 0.14f;
- normalSpringLength = normalUpperLimit - normalLowerLimit;
- }
-
- // Reset suspension to normal
- float normalLineLength = normalSpringLength + wheelRadius;
- CVector pos;
- for(i = 0; i < 4; i++){
- wheelPositions[i] = specialColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];
- mi->GetWheelPosn(i, pos);
- pos.z += normalUpperLimit;
- specialColModel->lines[i].p0 = pos;
- pos.z -= normalLineLength;
- specialColModel->lines[i].p1 = pos;
- m_aSuspensionSpringLength[i] = normalSpringLength;
- m_aSuspensionLineLength[i] = normalLineLength;
-
- if(m_aSuspensionSpringRatio[i] < 1.0f){
- m_aSuspensionSpringRatio[i] = (specialColModel->lines[i].p0.z - wheelPositions[i])/m_aSuspensionLineLength[i];
- if(m_aSuspensionSpringRatio[i] > 1.0f)
- m_aSuspensionSpringRatio[i] = 1.0f;
- }
- }
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);
- }else{
- // Reset suspension to extended
- float extendedLineLength = extendedSpringLength + wheelRadius;
- CVector pos;
- for(i = 0; i < 4; i++){
- wheelPositions[i] = specialColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];
- mi->GetWheelPosn(i, pos);
- pos.z += extendedUpperLimit;
- specialColModel->lines[i].p0 = pos;
- pos.z -= extendedLineLength;
- specialColModel->lines[i].p1 = pos;
- m_aSuspensionSpringLength[i] = extendedSpringLength;
- m_aSuspensionLineLength[i] = extendedLineLength;
-
- if(m_aSuspensionSpringRatio[i] < 1.0f){
- m_aSuspensionSpringRatio[i] = (specialColModel->lines[i].p0.z - wheelPositions[i])/m_aSuspensionLineLength[i];
- if(m_aSuspensionSpringRatio[i] > 1.0f)
- m_aSuspensionSpringRatio[i] = 1.0f;
- }
-
- setPrevRatio = true;
- m_aWheelPosition[i] -= 0.05f;
- }
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);
- }
- }else{
- float suspChange[4];
- float maxDelta = 0.0f;
- float rear = CPad::GetPad(0)->GetCarGunUpDown()/128.0f;
- float front = -rear;
- float right = CPad::GetPad(0)->GetCarGunLeftRight()/128.0f;
- float left = -right;
- suspChange[CARWHEEL_FRONT_LEFT] = Max(front+left, 0.0f);
- suspChange[CARWHEEL_REAR_LEFT] = Max(rear+left, 0.0f);
- suspChange[CARWHEEL_FRONT_RIGHT] = Max(front+right, 0.0f);
- suspChange[CARWHEEL_REAR_RIGHT] = Max(rear+right, 0.0f);
-
- if(m_hydraulicState < 100){
- // Lowered, move wheels up
-
- if(m_hydraulicState == 0){
- normalUpperLimit += -0.12f;
- normalLowerLimit += 0.14f;
- normalSpringLength = normalUpperLimit - normalLowerLimit;
- }
-
- // Set suspension
- CVector pos;
- for(i = 0; i < 4; i++){
- if(suspChange[i] > 1.0f)
- suspChange[i] = 1.0f;
-
- float oldZ = specialColModel->lines[i].p1.z;
- float upperLimit = suspChange[i]*(extendedUpperLimit-normalUpperLimit) + normalUpperLimit;
- float springLength = suspChange[i]*(extendedSpringLength-normalSpringLength) + normalSpringLength;
- float lineLength = springLength + wheelRadius;
-
- wheelPositions[i] = specialColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];
- mi->GetWheelPosn(i, pos);
- pos.z += upperLimit;
- specialColModel->lines[i].p0 = pos;
- pos.z -= lineLength;
- if(Abs(pos.z - specialColModel->lines[i].p1.z) > Abs(maxDelta))
- maxDelta = pos.z - specialColModel->lines[i].p1.z;
- specialColModel->lines[i].p1 = pos;
- m_aSuspensionSpringLength[i] = springLength;
- m_aSuspensionLineLength[i] = lineLength;
-
- if(m_aSuspensionSpringRatio[i] < 1.0f){
- m_aSuspensionSpringRatio[i] = (specialColModel->lines[i].p0.z - wheelPositions[i])/m_aSuspensionLineLength[i];
- if(m_aSuspensionSpringRatio[i] > 1.0f)
- m_aSuspensionSpringRatio[i] = 1.0f;
- m_aWheelPosition[i] -= (oldZ - specialColModel->lines[i].p1.z)*0.3f;
- }
- }
- }else{
- if(m_hydraulicState < 104){
- m_hydraulicState++;
- for(i = 0; i < 4; i++)
- m_aWheelPosition[i] -= 0.1f;
- }
-
- if(m_fVelocityChangeForAudio < 0.1f){
- normalUpperLimit += -0.12f;
- normalLowerLimit += 0.14f;
- normalSpringLength = normalUpperLimit - normalLowerLimit;
- }
-
- // Set suspension
- CVector pos;
- for(i = 0; i < 4; i++){
- if(suspChange[i] > 1.0f)
- suspChange[i] = 1.0f;
-
- float upperLimit = suspChange[i]*(normalUpperLimit-extendedUpperLimit) + extendedUpperLimit;
- float springLength = suspChange[i]*(normalSpringLength-extendedSpringLength) + extendedSpringLength;
- float lineLength = springLength + wheelRadius;
-
- wheelPositions[i] = specialColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];
- mi->GetWheelPosn(i, pos);
- pos.z += upperLimit;
- specialColModel->lines[i].p0 = pos;
- pos.z -= lineLength;
- if(Abs(pos.z - specialColModel->lines[i].p1.z) > Abs(maxDelta))
- maxDelta = pos.z - specialColModel->lines[i].p1.z;
- specialColModel->lines[i].p1 = pos;
- m_aSuspensionSpringLength[i] = springLength;
- m_aSuspensionLineLength[i] = lineLength;
-
- if(m_aSuspensionSpringRatio[i] < 1.0f){
- m_aSuspensionSpringRatio[i] = (specialColModel->lines[i].p0.z - wheelPositions[i])/m_aSuspensionLineLength[i];
- if(m_aSuspensionSpringRatio[i] > 1.0f)
- m_aSuspensionSpringRatio[i] = 1.0f;
- }
- }
- }
-
- float limitDiff = extendedLowerLimit - normalLowerLimit;
- if(limitDiff != 0.0f && Abs(maxDelta/limitDiff) > 0.01f){
- float f = (maxDelta + limitDiff)/2.0f/limitDiff;
- f = clamp(f, 0.0f, 1.0f);
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_3, f);
- if(f < 0.4f || f > 0.6f)
- setPrevRatio = true;
- if(f < 0.25f)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);
- else if(f > 0.75f)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_1, 0.0f);
- }
- }
-
- if(setPrevRatio)
- for(i = 0; i < 4; i++){
- // wheel radius in relation to suspension line
- float wheelRadius = 1.0f - m_aSuspensionSpringLength[i]/m_aSuspensionLineLength[i];
- m_aSuspensionSpringRatioPrev[i] = (m_aSuspensionSpringRatio[i]-wheelRadius)/(1.0f-wheelRadius);
- }
-}
-
-void
-CAutomobile::ProcessBuoyancy(void)
-{
- int i;
- CVector impulse, point;
-
- if(mod_Buoyancy.ProcessBuoyancy(this, m_fBuoyancy, &point, &impulse)){
- m_flagD8 = true;
- ApplyMoveForce(impulse);
- ApplyTurnForce(impulse, point);
-
- CVector initialSpeed = m_vecMoveSpeed;
- float timeStep = Max(CTimer::GetTimeStep(), 0.01f);
- float impulseRatio = impulse.z / (GRAVITY * m_fMass * timeStep);
- float waterResistance = Pow(1.0f - 0.05f*impulseRatio, CTimer::GetTimeStep());
- m_vecMoveSpeed *= waterResistance;
- m_vecTurnSpeed *= waterResistance;
-
- if(impulseRatio > 0.5f){
- bIsInWater = true;
- if(m_vecMoveSpeed.z < -0.1f)
- m_vecMoveSpeed.z = -0.1f;
-
- if(pDriver){
- pDriver->bIsInWater = true;
- if(pDriver->IsPlayer() || !bWaterTight)
- pDriver->InflictDamage(nil, WEAPONTYPE_WATER, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
- }
- for(i = 0; i < m_nNumMaxPassengers; i++)
- if(pPassengers[i]){
- pPassengers[i]->bIsInWater = true;
- if(pPassengers[i]->IsPlayer() || !bWaterTight)
- pPassengers[i]->InflictDamage(nil, WEAPONTYPE_WATER, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
- }
- }else
- bIsInWater = false;
-
- static uint32 nGenerateRaindrops = 0;
- static uint32 nGenerateWaterCircles = 0;
-
- if(initialSpeed.z < -0.3f && impulse.z > 0.3f){
- RwRGBA color;
- color.red = (0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed())*0.45f*255;
- color.green = (0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen())*0.45f*255;
- color.blue = (0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue())*0.45f*255;
- color.alpha = CGeneral::GetRandomNumberInRange(0, 32) + 128;
- CParticleObject::AddObject(POBJECT_CAR_WATER_SPLASH, GetPosition(),
- CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.15f, 0.3f)),
- 0.0f, 75, color, true);
-
- nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300;
- nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60;
- if(m_vecMoveSpeed.z < -0.2f)
- m_vecMoveSpeed.z = -0.2f;
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WATER_FALL, 0.0f);
- }
-
- if(nGenerateWaterCircles > 0 && nGenerateWaterCircles < CTimer::GetTimeInMilliseconds()){
- CVector pos = GetPosition();
- float waterLevel = 0.0f;
- if(CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &waterLevel, false))
- pos.z = waterLevel;
- static RwRGBA black;
- if(pos.z != 0.0f){
- nGenerateWaterCircles = 0;
- pos.z += 1.0f;
- for(i = 0; i < 4; i++){
- CVector p = pos;
- p.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);
- p.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);
- CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW,
- p, CVector(0.0f, 0.0f, 0.0f),
- nil, 0.0f, black, 0, 0, 0, 0);
- }
- }
- }
-
- if(nGenerateRaindrops > 0 && nGenerateRaindrops < CTimer::GetTimeInMilliseconds()){
- CVector pos = GetPosition();
- float waterLevel = 0.0f;
- if(CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &waterLevel, false))
- pos.z = waterLevel;
- static RwRGBA black;
- if(pos.z >= 0.0f){
- nGenerateRaindrops = 0;
- pos.z += 0.5;
- CParticleObject::AddObject(POBJECT_SPLASHES_AROUND,
- pos, CVector(0.0f, 0.0f, 0.0f), 6.5f, 2500, black, true);
- }
- }
- }else{
- bIsInWater = false;
- m_flagD8 = false;
-
- static RwRGBA splashCol = {155, 155, 185, 196};
- static RwRGBA smokeCol = {255, 255, 255, 255};
-
- for(i = 0; i < 4; i++){
- if(m_aSuspensionSpringRatio[i] < 1.0f && m_aWheelColPoints[i].surfaceB == SURFACE_PUDDLE){
- CVector pos = m_aWheelColPoints[i].point + 0.3f*GetUp() - GetPosition();
- CVector vSpeed = GetSpeed(pos);
- vSpeed.z = 0.0f;
- float fSpeed = vSpeed.MagnitudeSqr();
- if(fSpeed > sq(0.05f)){
- fSpeed = Sqrt(fSpeed);
- float size = Min((fSpeed < 0.15f ? 0.25f : 0.75f)*fSpeed, 0.6f);
- CVector right = 0.2f*fSpeed*GetRight() + 0.2f*vSpeed;
-
- CParticle::AddParticle(PARTICLE_PED_SPLASH,
- pos + GetPosition(), -0.5f*right,
- nil, size, splashCol,
- CGeneral::GetRandomNumberInRange(0.0f, 10.0f),
- CGeneral::GetRandomNumberInRange(0.0f, 90.0f), 1, 0);
-
- CParticle::AddParticle(PARTICLE_RUBBER_SMOKE,
- pos + GetPosition(), -0.6f*right,
- nil, size, smokeCol, 0, 0, 0, 0);
-
- if((CTimer::GetFrameCounter() & 0xF) == 0)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_SPLASH, 2000.0f*fSpeed);
- }
- }
- }
- }
-}
-
-void
-CAutomobile::DoDriveByShootings(void)
-{
- CAnimBlendAssociation *anim;
- CWeapon *weapon = pDriver->GetWeapon();
- if(weapon->m_eWeaponType != WEAPONTYPE_UZI)
- return;
-
- weapon->Update(pDriver->m_audioEntityId);
-
- bool lookingLeft = false;
- bool lookingRight = false;
- if(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1){
- if(CPad::GetPad(0)->GetLookLeft())
- lookingLeft = true;
- if(CPad::GetPad(0)->GetLookRight())
- lookingRight = true;
- }else{
- if(TheCamera.Cams[TheCamera.ActiveCam].LookingLeft)
- lookingLeft = true;
- if(TheCamera.Cams[TheCamera.ActiveCam].LookingRight)
- lookingRight = true;
- }
-
- if(lookingLeft || lookingRight){
- if(lookingLeft){
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R);
- if(anim)
- anim->blendDelta = -1000.0f;
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L);
- if(anim == nil || anim->blendDelta < 0.0f)
- CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_DRIVEBY_L);
- else
- anim->SetRun();
- }else if(pDriver->m_pMyVehicle->pPassengers[0] == nil || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIRSTPERSON){
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L);
- if(anim)
- anim->blendDelta = -1000.0f;
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R);
- if(anim == nil || anim->blendDelta < 0.0f)
- CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_DRIVEBY_R);
- else
- anim->SetRun();
- }
-
- if(CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer){
- weapon->FireFromCar(this, lookingLeft);
- weapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70;
- }
- }else{
- weapon->Reload();
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_L);
- if(anim)
- anim->blendDelta = -1000.0f;
- anim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_DRIVEBY_R);
- if(anim)
- anim->blendDelta = -1000.0f;
- }
-
- // TODO: what is this?
- if(!lookingLeft && m_weaponDoorTimerLeft > 0.0f){
- m_weaponDoorTimerLeft = Max(m_weaponDoorTimerLeft - CTimer::GetTimeStep()*0.1f, 0.0f);
- ProcessOpenDoor(CAR_DOOR_LF, NUM_ANIMS, m_weaponDoorTimerLeft);
- }
- if(!lookingRight && m_weaponDoorTimerRight > 0.0f){
- m_weaponDoorTimerRight = Max(m_weaponDoorTimerRight - CTimer::GetTimeStep()*0.1f, 0.0f);
- ProcessOpenDoor(CAR_DOOR_RF, NUM_ANIMS, m_weaponDoorTimerRight);
- }
-}
-
-int32
-CAutomobile::RcbanditCheckHitWheels(void)
-{
- int x, xmin, xmax;
- int y, ymin, ymax;
-
- xmin = CWorld::GetSectorIndexX(GetPosition().x - 2.0f);
- if(xmin < 0) xmin = 0;
- xmax = CWorld::GetSectorIndexX(GetPosition().x + 2.0f);
- if(xmax > NUMSECTORS_X-1) xmax = NUMSECTORS_X-1;
- ymin = CWorld::GetSectorIndexX(GetPosition().y - 2.0f);
- if(ymin < 0) ymin = 0;
- ymax = CWorld::GetSectorIndexX(GetPosition().y + 2.0f);
- if(ymax > NUMSECTORS_Y-1) ymax = NUMSECTORS_X-1;
-
- CWorld::AdvanceCurrentScanCode();
-
- for(y = ymin; y <= ymax; y++)
- for(x = xmin; x <= xmax; x++){
- CSector *s = CWorld::GetSector(x, y);
- if(RcbanditCheck1CarWheels(s->m_lists[ENTITYLIST_VEHICLES]) ||
- RcbanditCheck1CarWheels(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP]))
- return 1;
- }
- return 0;
-}
-
-int32
-CAutomobile::RcbanditCheck1CarWheels(CPtrList &list)
-{
- static CMatrix matW2B;
- int i;
- CPtrNode *node;
- CAutomobile *car;
- CColModel *colModel = GetColModel();
- CVehicleModelInfo *mi;
-
- for(node = list.first; node; node = node->next){
- car = (CAutomobile*)node->item;
- if(this != car && car->IsCar() && car->m_scanCode != CWorld::GetCurrentScanCode()){
- car->m_scanCode = CWorld::GetCurrentScanCode();
-
- if(Abs(this->GetPosition().x - car->GetPosition().x) < 10.0f &&
- Abs(this->GetPosition().y - car->GetPosition().y) < 10.0f){
- mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(car->GetModelIndex());
-
- for(i = 0; i < 4; i++){
- if(car->m_aSuspensionSpringRatioPrev[i] < 1.0f || car->m_status == STATUS_SIMPLE){
- CVector wheelPos;
- CColSphere sph;
- mi->GetWheelPosn(i, wheelPos);
- matW2B = Invert(GetMatrix());
- sph.center = matW2B * (car->GetMatrix() * wheelPos);
- sph.radius = mi->m_wheelScale*0.25f;
- if(CCollision::TestSphereBox(sph, colModel->boundingBox))
- return 1;
- }
- }
- }
- }
- }
- return 0;
-}
-
-void
-CAutomobile::PlaceOnRoadProperly(void)
-{
- CColPoint point;
- CEntity *entity;
- CColModel *colModel = GetColModel();
- float lenFwd, lenBack;
- float frontZ, rearZ;
-
- lenFwd = colModel->boundingBox.max.y;
- lenBack = -colModel->boundingBox.min.y;
-
- CVector front(GetPosition().x + GetForward().x*lenFwd,
- GetPosition().y + GetForward().y*lenFwd,
- GetPosition().z + 5.0f);
- if(CWorld::ProcessVerticalLine(front, GetPosition().z - 5.0f, point, entity,
- true, false, false, false, false, false, nil)){
- frontZ = point.point.z;
- m_pCurGroundEntity = entity;
- }else{
- frontZ = field_21C;
- }
-
- CVector rear(GetPosition().x - GetForward().x*lenBack,
- GetPosition().y - GetForward().y*lenBack,
- GetPosition().z + 5.0f);
- if(CWorld::ProcessVerticalLine(rear, GetPosition().z - 5.0f, point, entity,
- true, false, false, false, false, false, nil)){
- rearZ = point.point.z;
- m_pCurGroundEntity = entity;
- }else{
- rearZ = field_220;
- }
-
- float len = lenFwd + lenBack;
- float angle = Atan((frontZ - rearZ)/len);
- float c = Cos(angle);
- float s = Sin(angle);
-
- GetRight() = CVector((front.y - rear.y)/len, -(front.x - rear.x)/len, 0.0f);
- GetForward() = CVector(-c*GetRight().y, c*GetRight().x, s);
- GetUp() = CrossProduct(GetRight(), GetForward());
- GetPosition() = CVector((front.x + rear.x)/2.0f, (front.y + rear.y)/2.0f, (frontZ + rearZ)/2.0f + GetHeightAboveRoad());
-}
-
-void
-CAutomobile::VehicleDamage(float impulse, uint16 damagedPiece)
-{
- int i;
- float damageMultiplier = 0.2f;
- bool doubleMoney = false;
-
- if(impulse == 0.0f){
- impulse = m_fDamageImpulse;
- damagedPiece = m_nDamagePieceType;
- damageMultiplier = 1.0f;
- }
-
- CVector pos(0.0f, 0.0f, 0.0f);
-
- if(!bCanBeDamaged)
- return;
-
- // damage flipped over car
- if(GetUp().z < 0.0f && this != FindPlayerVehicle()){
- if(bNotDamagedUpsideDown || m_status == STATUS_PLAYER_REMOTE || bIsInWater)
- return;
- m_fHealth -= 4.0f*CTimer::GetTimeStep();
- }
-
- if(impulse > 25.0f && m_status != STATUS_WRECKED){
- if(bIsLawEnforcer &&
- FindPlayerVehicle() && FindPlayerVehicle() == m_pDamageEntity &&
- m_status != STATUS_ABANDONED &&
- FindPlayerVehicle()->m_vecMoveSpeed.Magnitude() >= m_vecMoveSpeed.Magnitude() &&
- FindPlayerVehicle()->m_vecMoveSpeed.Magnitude() > 0.1f)
- FindPlayerPed()->SetWantedLevelNoDrop(1);
-
- if(m_status == STATUS_PLAYER && impulse > 50.0f){
- uint8 freq = Min(0.4f*impulse*2000.0f/m_fMass + 100.0f, 250.0f);
- CPad::GetPad(0)->StartShake(40000/freq, freq);
- }
-
- if(bOnlyDamagedByPlayer){
- if(m_pDamageEntity != FindPlayerPed() &&
- m_pDamageEntity != FindPlayerVehicle())
- return;
- }
-
- if(bCollisionProof)
- return;
-
- if(m_pDamageEntity){
- if(m_pDamageEntity->IsBuilding() &&
- DotProduct(m_vecDamageNormal, GetUp()) > 0.6f)
- return;
- }
-
- int oldLightStatus[4];
- for(i = 0; i < 4; i++)
- oldLightStatus[i] = Damage.GetLightStatus((eLights)i);
-
- if(GetUp().z > 0.0f || m_vecMoveSpeed.MagnitudeSqr() > 0.1f){
- float impulseMult = bMoreResistantToDamage ? 0.5f : 4.0f;
-
- switch(damagedPiece){
- case CAR_PIECE_BUMP_FRONT:
- GetComponentWorldPosition(CAR_BUMP_FRONT, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if(Damage.ApplyDamage(COMPONENT_BUMPER_FRONT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetBumperDamage(CAR_BUMP_FRONT, VEHBUMPER_FRONT);
- doubleMoney = true;
- }
- if(m_aCarNodes[CAR_BONNET] && Damage.GetPanelStatus(VEHBUMPER_FRONT) == PANEL_STATUS_MISSING){
- case CAR_PIECE_BONNET:
- GetComponentWorldPosition(CAR_BONNET, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if(Damage.ApplyDamage(COMPONENT_DOOR_BONNET, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetDoorDamage(CAR_BONNET, DOOR_BONNET);
- doubleMoney = true;
- }
- }
- break;
-
- case CAR_PIECE_BUMP_REAR:
- GetComponentWorldPosition(CAR_BUMP_REAR, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if(Damage.ApplyDamage(COMPONENT_BUMPER_FRONT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetBumperDamage(CAR_BUMP_REAR, VEHBUMPER_REAR);
- doubleMoney = true;
- }
- if(m_aCarNodes[CAR_BOOT] && Damage.GetPanelStatus(VEHBUMPER_REAR) == PANEL_STATUS_MISSING){
- case CAR_PIECE_BOOT:
- GetComponentWorldPosition(CAR_BOOT, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if(Damage.ApplyDamage(COMPONENT_DOOR_BOOT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetDoorDamage(CAR_BOOT, DOOR_BOOT);
- doubleMoney = true;
- }
- }
- break;
-
- case CAR_PIECE_DOOR_LF:
- GetComponentWorldPosition(CAR_DOOR_LF, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if((m_nDoorLock == CARLOCK_NOT_USED || m_nDoorLock == CARLOCK_UNLOCKED) &&
- Damage.ApplyDamage(COMPONENT_DOOR_FRONT_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT);
- doubleMoney = true;
- }
- break;
- case CAR_PIECE_DOOR_RF:
- GetComponentWorldPosition(CAR_DOOR_RF, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if((m_nDoorLock == CARLOCK_NOT_USED || m_nDoorLock == CARLOCK_UNLOCKED) &&
- Damage.ApplyDamage(COMPONENT_DOOR_FRONT_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT);
- doubleMoney = true;
- }
- break;
- case CAR_PIECE_DOOR_LR:
- GetComponentWorldPosition(CAR_DOOR_LR, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if((m_nDoorLock == CARLOCK_NOT_USED || m_nDoorLock == CARLOCK_UNLOCKED) &&
- Damage.ApplyDamage(COMPONENT_DOOR_REAR_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT);
- doubleMoney = true;
- }
- break;
- case CAR_PIECE_DOOR_RR:
- GetComponentWorldPosition(CAR_DOOR_RR, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if((m_nDoorLock == CARLOCK_NOT_USED || m_nDoorLock == CARLOCK_UNLOCKED) &&
- Damage.ApplyDamage(COMPONENT_DOOR_REAR_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT);
- doubleMoney = true;
- }
- break;
-
- case CAR_PIECE_WING_LF:
- GetComponentWorldPosition(CAR_WING_LF, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetPanelDamage(CAR_WING_LF, VEHPANEL_FRONT_LEFT);
- doubleMoney = true;
- }
- break;
- case CAR_PIECE_WING_RF:
- GetComponentWorldPosition(CAR_WING_RF, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetPanelDamage(CAR_WING_RF, VEHPANEL_FRONT_RIGHT);
- doubleMoney = true;
- }
- break;
- case CAR_PIECE_WING_LR:
- GetComponentWorldPosition(CAR_WING_LR, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if(Damage.ApplyDamage(COMPONENT_PANEL_REAR_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetPanelDamage(CAR_WING_LR, VEHPANEL_REAR_LEFT);
- doubleMoney = true;
- }
- break;
- case CAR_PIECE_WING_RR:
- GetComponentWorldPosition(CAR_WING_RR, pos);
- dmgDrawCarCollidingParticles(pos, impulse);
- if(Damage.ApplyDamage(COMPONENT_PANEL_REAR_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- SetPanelDamage(CAR_WING_RR, VEHPANEL_REAR_RIGHT);
- doubleMoney = true;
- }
- break;
-
- case CAR_PIECE_WHEEL_LF:
- case CAR_PIECE_WHEEL_LR:
- case CAR_PIECE_WHEEL_RF:
- case CAR_PIECE_WHEEL_RR:
- break;
-
- case CAR_PIECE_WINDSCREEN:
- if(Damage.ApplyDamage(COMPONENT_PANEL_WINDSCREEN, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){
- uint8 oldStatus = Damage.GetPanelStatus(VEHPANEL_WINDSCREEN);
- SetPanelDamage(CAR_WINDSCREEN, VEHPANEL_WINDSCREEN);
- if(oldStatus != Damage.GetPanelStatus(VEHPANEL_WINDSCREEN)){
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.0f);
- doubleMoney = true;
- }
- }
- break;
- }
-
- if(m_pDamageEntity && m_pDamageEntity == FindPlayerVehicle() && impulse > 10.0f){
- int money = (doubleMoney ? 2 : 1) * impulse*pHandling->nMonetaryValue/1000000.0f;
- money = Min(money, 40);
- if(money > 2){
- sprintf(gString, "$%d", money);
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += money;
- }
- }
- }
-
- float damage = (impulse-25.0f)*pHandling->fCollisionDamageMultiplier*0.6f*damageMultiplier;
-
- if(GetModelIndex() == MI_SECURICA && m_pDamageEntity && m_pDamageEntity->m_status == STATUS_PLAYER)
- damage *= 7.0f;
-
- if(damage > 0.0f){
- int oldHealth = m_fHealth;
- if(this == FindPlayerVehicle()){
- m_fHealth -= bTakeLessDamage ? damage/6.0f : damage/2.0f;
- }else{
- if(damage > 35.0f && pDriver)
- pDriver->Say(SOUND_PED_CAR_COLLISION);
- m_fHealth -= bTakeLessDamage ? damage/12.0f : damage/4.0f;
- }
- if(m_fHealth <= 0.0f && oldHealth > 0)
- m_fHealth = 1.0f;
- }
-
- // play sound if a light broke
- for(i = 0; i < 4; i++)
- if(oldLightStatus[i] != 1 && Damage.GetLightStatus((eLights)i) == 1){
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_LIGHT_BREAK, i); // BUG? i?
- break;
- }
- }
-
- if(m_fHealth < 250.0f){
- // Car is on fire
- if(Damage.GetEngineStatus() < ENGINE_STATUS_ON_FIRE){
- // Set engine on fire and remember who did this
- Damage.SetEngineStatus(ENGINE_STATUS_ON_FIRE);
- m_fFireBlowUpTimer = 0.0f;
- m_pSetOnFireEntity = m_pDamageEntity;
- if(m_pSetOnFireEntity)
- m_pSetOnFireEntity->RegisterReference(&m_pSetOnFireEntity);
- }
- }else{
- if(GetModelIndex() == MI_BFINJECT){
- if(m_fHealth < 400.0f)
- Damage.SetEngineStatus(200);
- else if(m_fHealth < 600.0f)
- Damage.SetEngineStatus(100);
- }
- }
-}
-
-void
-CAutomobile::dmgDrawCarCollidingParticles(const CVector &pos, float amount)
-{
- int i, n;
-
- if(!GetIsOnScreen())
- return;
-
- // FindPlayerSpeed() unused
-
- n = (int)amount/20;
-
- for(i = 0; i < ((n+4)&0x1F); i++)
- CParticle::AddParticle(PARTICLE_SPARK_SMALL, pos,
- CVector(CGeneral::GetRandomNumberInRange(-0.1f, 0.1f),
- CGeneral::GetRandomNumberInRange(-0.1f, 0.1f),
- 0.006f));
-
- for(i = 0; i < n+2; i++)
- CParticle::AddParticle(PARTICLE_CARCOLLISION_DUST,
- CVector(CGeneral::GetRandomNumberInRange(-1.2f, 1.2f) + pos.x,
- CGeneral::GetRandomNumberInRange(-1.2f, 1.2f) + pos.y,
- pos.z),
- CVector(0.0f, 0.0f, 0.0f), nil, 0.5f);
-
- n = (int)amount/50 + 1;
- for(i = 0; i < n; i++)
- CParticle::AddParticle(PARTICLE_CAR_DEBRIS, pos,
- CVector(CGeneral::GetRandomNumberInRange(-0.25f, 0.25f),
- CGeneral::GetRandomNumberInRange(-0.25f, 0.25f),
- CGeneral::GetRandomNumberInRange(0.1f, 0.25f)),
- nil,
- CGeneral::GetRandomNumberInRange(0.02f, 0.08f),
- CVehicleModelInfo::ms_vehicleColourTable[m_currentColour1],
- CGeneral::GetRandomNumberInRange(-40.0f, 40.0f),
- 0,
- CGeneral::GetRandomNumberInRange(0.0f, 4.0f));
-}
-
-void
-CAutomobile::AddDamagedVehicleParticles(void)
-{
- if(this == FindPlayerVehicle() && TheCamera.GetLookingForwardFirstPerson())
- return;
-
- uint8 engineStatus = Damage.GetEngineStatus();
- if(engineStatus < ENGINE_STATUS_STEAM1)
- return;
-
- float fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward()) * 180.0f;
- CVector direction = 0.5f*m_vecMoveSpeed;
- CVector damagePos = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->m_positions[CAR_POS_HEADLIGHTS];
-
- switch(Damage.GetDoorStatus(DOOR_BONNET)){
- case DOOR_STATUS_OK:
- case DOOR_STATUS_SMASHED:
- // Bonnet is still there, smoke comes out at the edge
- damagePos += vecDAMAGE_ENGINE_POS_SMALL;
- break;
- case DOOR_STATUS_SWINGING:
- case DOOR_STATUS_MISSING:
- // Bonnet is gone, smoke comes out at the engine
- damagePos += vecDAMAGE_ENGINE_POS_BIG;
- break;
- }
-
- if(GetModelIndex() == MI_BFINJECT)
- damagePos = CVector(0.3f, -1.5f, -0.1f);
-
- damagePos = GetMatrix()*damagePos;
- damagePos.z += 0.15f;
-
- if(engineStatus < ENGINE_STATUS_STEAM2){
- if(fwdSpeed < 90.0f){
- direction.z += 0.05f;
- CParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, direction, nil, 0.1f);
- }
- }else if(engineStatus < ENGINE_STATUS_SMOKE){
- if(fwdSpeed < 90.0f)
- CParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, direction, nil, 0.0f);
- }else if(engineStatus < ENGINE_STATUS_ON_FIRE){
- if(fwdSpeed < 90.0f){
- CParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, direction, nil, 0.0f);
- CParticle::AddParticle(PARTICLE_ENGINE_SMOKE, damagePos, 0.3f*direction, nil, 0.0f);
- }
- }else if(m_fHealth > 250.0f){
- if(fwdSpeed < 90.0f)
- CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, damagePos, 0.2f*direction, nil, 0.0f);
- }
-}
-
-int32
-CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed)
-{
- int i;
- CVector dir;
- static RwRGBA grassCol = { 8, 24, 8, 255 };
- static RwRGBA dirtCol = { 64, 64, 64, 255 };
- static RwRGBA dirttrackCol = { 64, 32, 16, 255 };
- static RwRGBA waterCol = { 48, 48, 64, 0 };
-
- if(!belowEffectSpeed)
- return 0;
-
- switch(colpoint->surfaceB){
- case SURFACE_GRASS:
- dir.x = -0.05f*m_vecMoveSpeed.x;
- dir.y = -0.05f*m_vecMoveSpeed.y;
- for(i = 0; i < 4; i++){
- dir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f);
- CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,
- CGeneral::GetRandomNumberInRange(0.02f, 0.1f), grassCol);
- }
- return 0;
- case SURFACE_DIRT:
- dir.x = -0.05f*m_vecMoveSpeed.x;
- dir.y = -0.05f*m_vecMoveSpeed.y;
- for(i = 0; i < 4; i++){
- dir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f);
- CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,
- CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirtCol);
- }
- return 1;
- case SURFACE_DIRTTRACK:
- dir.x = -0.05f*m_vecMoveSpeed.x;
- dir.y = -0.05f*m_vecMoveSpeed.y;
- for(i = 0; i < 4; i++){
- dir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f);
- CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,
- CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirttrackCol);
- }
- return 0;
- default:
- // Is this even visible?
- if(CWeather::WetRoads > 0.01f && CTimer::GetFrameCounter() & 1){
- CParticle::AddParticle(PARTICLE_WATERSPRAY,
- colpoint->point + CVector(0.0f, 0.0f, 0.25f+0.25f),
- CVector(0.0f, 0.0f, 1.0f), nil,
- CGeneral::GetRandomNumberInRange(0.1f, 0.5f), waterCol);
- return 0;
- }
- return 1;
- }
-}
-
-void
-CAutomobile::GetComponentWorldPosition(int32 component, CVector &pos)
-{
- if(m_aCarNodes[component] == nil){
- printf("CarNode missing: %d %d\n", GetModelIndex(), component);
- return;
- }
- RwMatrix *ltm = RwFrameGetLTM(m_aCarNodes[component]);
- pos = *RwMatrixGetPos(ltm);
-}
-
-bool
-CAutomobile::IsComponentPresent(int32 comp)
-{
- return m_aCarNodes[comp] != nil;
-}
-
-void
-CAutomobile::SetComponentRotation(int32 component, CVector rotation)
-{
- CMatrix mat(RwFrameGetMatrix(m_aCarNodes[component]));
- CVector pos = mat.GetPosition();
- // BUG: all these set the whole matrix
- mat.SetRotateX(DEGTORAD(rotation.x));
- mat.SetRotateY(DEGTORAD(rotation.y));
- mat.SetRotateZ(DEGTORAD(rotation.z));
- mat.Translate(pos);
- mat.UpdateRW();
-}
-
-void
-CAutomobile::OpenDoor(int32 component, eDoors door, float openRatio)
-{
- CMatrix mat(RwFrameGetMatrix(m_aCarNodes[component]));
- CVector pos = mat.GetPosition();
- float axes[3] = { 0.0f, 0.0f, 0.0f };
- float wasClosed = false;
-
- if(Doors[door].IsClosed()){
- // enable angle cull for closed doors
- RwFrameForAllObjects(m_aCarNodes[component], CVehicleModelInfo::ClearAtomicFlagCB, (void*)ATOMIC_FLAG_NOCULL);
- wasClosed = true;
- }
-
- Doors[door].Open(openRatio);
-
- if(wasClosed && Doors[door].RetAngleWhenClosed() != Doors[door].m_fAngle){
- // door opened
- HideAllComps();
- // turn off angle cull for swinging door
- RwFrameForAllObjects(m_aCarNodes[component], CVehicleModelInfo::SetAtomicFlagCB, (void*)ATOMIC_FLAG_NOCULL);
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_DOOR_OPEN_BONNET + door, 0.0f);
- }
-
- if(!wasClosed && openRatio == 0.0f){
- // door closed
- 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);
- }
-
- axes[Doors[door].m_nAxis] = Doors[door].m_fAngle;
- mat.SetRotate(axes[0], axes[1], axes[2]);
- mat.Translate(pos);
- mat.UpdateRW();
-}
-
-inline void ProcessDoorOpenAnimation(CAutomobile *car, uint32 component, eDoors door, float time, float start, float end)
-{
- if(time > start && time < end){
- float ratio = (time - start)/(end - start);
- if(car->Doors[door].GetAngleOpenRatio() < ratio)
- car->OpenDoor(component, door, ratio);
- }else if(time > end){
- car->OpenDoor(component, door, 1.0f);
- }
-}
-
-inline void ProcessDoorCloseAnimation(CAutomobile *car, uint32 component, eDoors door, float time, float start, float end)
-{
- if(time > start && time < end){
- float ratio = 1.0f - (time - start)/(end - start);
- if(car->Doors[door].GetAngleOpenRatio() > ratio)
- car->OpenDoor(component, door, ratio);
- }else if(time > end){
- car->OpenDoor(component, door, 0.0f);
- }
-}
-
-inline void ProcessDoorOpenCloseAnimation(CAutomobile *car, uint32 component, eDoors door, float time, float start, float mid, float end)
-{
- if(time > start && time < mid){
- // open
- float ratio = (time - start)/(mid - start);
- if(car->Doors[door].GetAngleOpenRatio() < ratio)
- car->OpenDoor(component, door, ratio);
- }else if(time > mid && time < end){
- // close
- float ratio = 1.0f - (time - mid)/(end - mid);
- if(car->Doors[door].GetAngleOpenRatio() > ratio)
- car->OpenDoor(component, door, ratio);
- }else if(time > end){
- car->OpenDoor(component, door, 0.0f);
- }
-}
-void
-CAutomobile::ProcessOpenDoor(uint32 component, uint32 anim, float time)
-{
- eDoors door;
-
- switch(component){
- case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break;
- case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break;
- case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; break;
- case CAR_DOOR_LR: door = DOOR_REAR_LEFT; break;
- default: assert(0);
- }
-
- if(IsDoorMissing(door))
- return;
-
- switch(anim){
- case ANIM_CAR_QJACK:
- case ANIM_CAR_OPEN_LHS:
- case ANIM_CAR_OPEN_RHS:
- ProcessDoorOpenAnimation(this, component, door, time, 0.66f, 0.8f);
- break;
- case ANIM_CAR_CLOSEDOOR_LHS:
- case ANIM_CAR_CLOSEDOOR_LOW_LHS:
- case ANIM_CAR_CLOSEDOOR_RHS:
- case ANIM_CAR_CLOSEDOOR_LOW_RHS:
- ProcessDoorCloseAnimation(this, component, door, time, 0.2f, 0.63f);
- break;
- case ANIM_CAR_ROLLDOOR:
- case ANIM_CAR_ROLLDOOR_LOW:
- ProcessDoorOpenCloseAnimation(this, component, door, time, 0.1f, 0.6f, 0.95f);
- break;
- break;
- case ANIM_CAR_GETOUT_LHS:
- case ANIM_CAR_GETOUT_LOW_LHS:
- case ANIM_CAR_GETOUT_RHS:
- case ANIM_CAR_GETOUT_LOW_RHS:
- ProcessDoorOpenAnimation(this, component, door, time, 0.06f, 0.43f);
- break;
- case ANIM_CAR_CLOSE_LHS:
- case ANIM_CAR_CLOSE_RHS:
- ProcessDoorCloseAnimation(this, component, door, time, 0.1f, 0.23f);
- break;
- case ANIM_CAR_PULLOUT_RHS:
- case ANIM_CAR_PULLOUT_LOW_RHS:
- OpenDoor(component, door, 1.0f);
- case ANIM_COACH_OPEN_L:
- case ANIM_COACH_OPEN_R:
- ProcessDoorOpenAnimation(this, component, door, time, 0.66f, 0.8f);
- break;
- case ANIM_COACH_OUT_L:
- ProcessDoorOpenAnimation(this, component, door, time, 0.0f, 0.3f);
- break;
- case ANIM_VAN_OPEN_L:
- case ANIM_VAN_OPEN:
- ProcessDoorOpenAnimation(this, component, door, time, 0.37f, 0.55f);
- break;
- case ANIM_VAN_CLOSE_L:
- case ANIM_VAN_CLOSE:
- ProcessDoorCloseAnimation(this, component, door, time, 0.5f, 0.8f);
- break;
- case ANIM_VAN_GETOUT_L:
- case ANIM_VAN_GETOUT:
- ProcessDoorOpenAnimation(this, component, door, time, 0.5f, 0.6f);
- break;
- case NUM_ANIMS:
- OpenDoor(component, door, time);
- break;
- }
-}
-
-bool
-CAutomobile::IsDoorReady(eDoors door)
-{
- if(Doors[door].IsClosed() || IsDoorMissing(door))
- return true;
- int doorflag = 0;
- // TODO: enum?
- switch(door){
- case DOOR_FRONT_LEFT: doorflag = 1; break;
- case DOOR_FRONT_RIGHT: doorflag = 4; break;
- case DOOR_REAR_LEFT: doorflag = 2; break;
- case DOOR_REAR_RIGHT: doorflag = 8; break;
- }
- return (doorflag & m_nGettingInFlags) == 0;
-}
-
-bool
-CAutomobile::IsDoorFullyOpen(eDoors door)
-{
- return Doors[door].IsFullyOpen() || IsDoorMissing(door);
-}
-
-bool
-CAutomobile::IsDoorClosed(eDoors door)
-{
- return !!Doors[door].IsClosed();
-}
-
-bool
-CAutomobile::IsDoorMissing(eDoors door)
-{
- return Damage.GetDoorStatus(door) == DOOR_STATUS_MISSING;
-}
-
-void
-CAutomobile::RemoveRefsToVehicle(CEntity *ent)
-{
- int i;
- for(i = 0; i < 4; i++)
- if(m_aGroundPhysical[i] == ent)
- m_aGroundPhysical[i] = nil;
-}
-
-void
-CAutomobile::BlowUpCar(CEntity *culprit)
-{
- int i;
- RpAtomic *atomic;
-
- if(!bCanBeDamaged)
- return;
-
- // explosion pushes vehicle up
- m_vecMoveSpeed.z += 0.13f;
- m_status = STATUS_WRECKED;
- bRenderScorched = true;
- m_nTimeOfDeath = CTimer::GetTimeInMilliseconds();
- Damage.FuckCarCompletely();
-
- if(GetModelIndex() != MI_RCBANDIT){
- SetBumperDamage(CAR_BUMP_FRONT, VEHBUMPER_FRONT);
- SetBumperDamage(CAR_BUMP_REAR, VEHBUMPER_REAR);
- SetDoorDamage(CAR_BONNET, DOOR_BONNET);
- SetDoorDamage(CAR_BOOT, DOOR_BOOT);
- SetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT);
- SetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT);
- SetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT);
- SetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT);
- SpawnFlyingComponent(CAR_WHEEL_LF, COMPGROUP_WHEEL);
- atomic = nil;
- RwFrameForAllObjects(m_aCarNodes[CAR_WHEEL_LF], GetCurrentAtomicObjectCB, &atomic);
- if(atomic)
- RpAtomicSetFlags(atomic, 0);
- }
-
- m_fHealth = 0.0f;
- m_nBombTimer = 0;
- m_bombType = CARBOMB_NONE;
-
- TheCamera.CamShake(0.7f, GetPosition().x, GetPosition().y, GetPosition().z);
-
- // kill driver and passengers
- if(pDriver){
- CDarkel::RegisterKillByPlayer(pDriver, WEAPONTYPE_EXPLOSION);
- if(pDriver->GetPedState() == PED_DRIVING){
- pDriver->SetDead();
- if(!pDriver->IsPlayer())
- pDriver->FlagToDestroyWhenNextProcessed();
- }else
- pDriver->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
- }
- for(i = 0; i < m_nNumMaxPassengers; i++){
- if(pPassengers[i]){
- CDarkel::RegisterKillByPlayer(pPassengers[i], WEAPONTYPE_EXPLOSION);
- if(pPassengers[i]->GetPedState() == PED_DRIVING){
- pPassengers[i]->SetDead();
- if(!pPassengers[i]->IsPlayer())
- pPassengers[i]->FlagToDestroyWhenNextProcessed();
- }else
- pPassengers[i]->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
- }
- }
-
- bEngineOn = false;
- bLightsOn = false;
- m_bSirenOrAlarm = false;
- bTaxiLight = false;
- if(bIsAmbulanceOnDuty){
- bIsAmbulanceOnDuty = false;
- CCarCtrl::NumAmbulancesOnDuty--;
- }
- if(bIsFireTruckOnDuty){
- bIsFireTruckOnDuty = false;
- CCarCtrl::NumFiretrucksOnDuty--;
- }
- ChangeLawEnforcerState(false);
-
- gFireManager.StartFire(this, culprit, 0.8f, 1); // TODO
- CDarkel::RegisterCarBlownUpByPlayer(this);
- if(GetModelIndex() == MI_RCBANDIT)
- CExplosion::AddExplosion(this, culprit, EXPLOSION_CAR_QUICK, GetPosition(), 0);
- else
- CExplosion::AddExplosion(this, culprit, EXPLOSION_CAR, GetPosition(), 0);
-}
-
-bool
-CAutomobile::SetUpWheelColModel(CColModel *colModel)
-{
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
- CColModel *vehColModel = mi->GetColModel();
-
- colModel->boundingSphere = vehColModel->boundingSphere;
- colModel->boundingBox = vehColModel->boundingBox;
-
- CMatrix mat;
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
- colModel->spheres[0].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LF);
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LB]));
- colModel->spheres[1].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LR);
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
- colModel->spheres[2].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RF);
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RB]));
- colModel->spheres[3].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RR);
-
- if(m_aCarNodes[CAR_WHEEL_LM] != nil && m_aCarNodes[CAR_WHEEL_RM] != nil){
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LM]));
- colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RF);
- mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RM]));
- colModel->spheres[5].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_RR);
- colModel->numSpheres = 6;
- }else
- colModel->numSpheres = 4;
-
- return true;
-}
-
-// this probably isn't used in III yet
-void
-CAutomobile::BurstTyre(uint8 wheel)
-{
- switch(wheel){
- case CAR_PIECE_WHEEL_LF: wheel = VEHWHEEL_FRONT_LEFT; break;
- case CAR_PIECE_WHEEL_LR: wheel = VEHWHEEL_REAR_LEFT; break;
- case CAR_PIECE_WHEEL_RF: wheel = VEHWHEEL_FRONT_RIGHT; break;
- case CAR_PIECE_WHEEL_RR: wheel = VEHWHEEL_REAR_RIGHT; break;
- }
-
- int status = Damage.GetWheelStatus(wheel);
- if(status == WHEEL_STATUS_OK){
- Damage.SetWheelStatus(wheel, WHEEL_STATUS_BURST);
-
- if(m_status == STATUS_SIMPLE){
- m_status = STATUS_PHYSICS;
- CCarCtrl::SwitchVehicleToRealPhysics(this);
- }
-
- ApplyMoveForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f));
- ApplyTurnForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f), GetForward());
- }
-}
-
-bool
-CAutomobile::IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset)
-{
- CColPoint colpoint;
- CEntity *ent;
- colpoint.point = CVector(0.0f, 0.0f, 0.0f);
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
-
- CVector seatPos;
- switch(component){
- case CAR_DOOR_RF:
- seatPos = mi->m_positions[mi->m_vehicleType == VEHICLE_TYPE_BOAT ? BOAT_POS_FRONTSEAT : CAR_POS_FRONTSEAT];
- break;
- case CAR_DOOR_LF:
- seatPos = mi->m_positions[mi->m_vehicleType == VEHICLE_TYPE_BOAT ? BOAT_POS_FRONTSEAT : CAR_POS_FRONTSEAT];
- seatPos.x = -seatPos.x;
- break;
- case CAR_DOOR_RR:
- seatPos = mi->m_positions[CAR_POS_BACKSEAT];
- break;
- case CAR_DOOR_LR:
- seatPos = mi->m_positions[CAR_POS_BACKSEAT];
- seatPos.x = -seatPos.x;
- break;
- }
- seatPos = GetMatrix() * seatPos;
-
- CVector doorPos = CPed::GetPositionToOpenCarDoor(this, component);
- if(doorOffset){
- CVector off = *doorOffset;
- if(component == CAR_DOOR_RF || component == CAR_DOOR_RR)
- off.x = -off.x;
- doorPos += Multiply3x3(GetMatrix(), off);
- }
-
- if(GetUp().z < 0.0f){
- seatPos.z += 0.5f;
- doorPos.z += 0.5f;
- }
-
- CVector dist = doorPos - seatPos;
- float length = dist.Magnitude();
- CVector pedPos = seatPos + dist*((length+0.6f)/length);
-
- if(!CWorld::GetIsLineOfSightClear(seatPos, pedPos, true, false, false, true, false, false))
- return false;
- if(CWorld::TestSphereAgainstWorld(doorPos, 0.6f, this, true, true, false, true, false, false))
- return false;
- if(CWorld::ProcessVerticalLine(doorPos, 1000.0f, colpoint, ent, true, false, false, true, false, false, nil))
- if(colpoint.point.z > doorPos.z && colpoint.point.z < doorPos.z + 0.6f)
- return false;
- float upperZ = colpoint.point.z;
- if(!CWorld::ProcessVerticalLine(doorPos, -1000.0f, colpoint, ent, true, false, false, true, false, false, nil))
- return false;
- if(upperZ != 0.0f && upperZ < colpoint.point.z)
- return false;
- return true;
-}
-
-float
-CAutomobile::GetHeightAboveRoad(void)
-{
- return m_fHeightAboveRoad;
-}
-
-void
-CAutomobile::PlayCarHorn(void)
-{
- int r;
-
- if(m_nCarHornTimer != 0)
- return;
-
- r = CGeneral::GetRandomNumber() & 7;
- if(r < 2){
- m_nCarHornTimer = 45;
- }else if(r < 4){
- if(pDriver)
- pDriver->Say(SOUND_PED_CAR_COLLISION);
- m_nCarHornTimer = 45;
- }else{
- if(pDriver)
- pDriver->Say(SOUND_PED_CAR_COLLISION);
- }
-}
-
-void
-CAutomobile::PlayHornIfNecessary(void)
-{
- if(AutoPilot.m_bSlowedDownBecauseOfPeds ||
- AutoPilot.m_bSlowedDownBecauseOfCars)
- if(!HasCarStoppedBecauseOfLight())
- PlayCarHorn();
-}
-
-
-void
-CAutomobile::ResetSuspension(void)
-{
- int i;
- for(i = 0; i < 4; i++){
- m_aSuspensionSpringRatio[i] = 1.0f;
- m_aWheelTimer[i] = 0.0f;
- m_aWheelRotation[i] = 0.0f;
- m_aWheelState[i] = WHEEL_STATE_NORMAL;
- }
-}
-
-void
-CAutomobile::SetupSuspensionLines(void)
-{
- int i;
- CVector posn;
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
- CColModel *colModel = mi->GetColModel();
-
- // 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++){
- mi->GetWheelPosn(i, posn);
- m_aWheelPosition[i] = posn.z;
-
- // uppermost wheel position
- posn.z += pHandling->fSuspensionUpperLimit;
- colModel->lines[i].p0 = posn;
-
- // lowermost wheel position
- posn.z += pHandling->fSuspensionLowerLimit - pHandling->fSuspensionUpperLimit;
- // lowest point on tyre
- posn.z -= mi->m_wheelScale*0.5f;
- colModel->lines[i].p1 = posn;
-
- // this is length of the spring at rest
- m_aSuspensionSpringLength[i] = pHandling->fSuspensionUpperLimit - pHandling->fSuspensionLowerLimit;
- m_aSuspensionLineLength[i] = colModel->lines[i].p0.z - colModel->lines[i].p1.z;
- }
-
- // Compress spring somewhat to get normal height on road
- m_fHeightAboveRoad = -(colModel->lines[0].p0.z + (colModel->lines[0].p1.z - colModel->lines[0].p0.z)*
- (1.0f - 1.0f/(8.0f*pHandling->fSuspensionForceLevel)));
- for(i = 0; i < 4; i++)
- m_aWheelPosition[i] = mi->m_wheelScale*0.5f - m_fHeightAboveRoad;
-
- // adjust col model to include suspension lines
- if(colModel->boundingBox.min.z > colModel->lines[0].p1.z)
- colModel->boundingBox.min.z = colModel->lines[0].p1.z;
- float radius = Max(colModel->boundingBox.min.Magnitude(), colModel->boundingBox.max.Magnitude());
- if(colModel->boundingSphere.radius < radius)
- colModel->boundingSphere.radius = radius;
-
- if(GetModelIndex() == MI_RCBANDIT){
- colModel->boundingSphere.radius = 2.0f;
- for(i = 0; i < colModel->numSpheres; i++)
- colModel->spheres[i].radius = 0.3f;
- }
-}
-
-// called on police cars
-void
-CAutomobile::ScanForCrimes(void)
-{
- if(FindPlayerVehicle() && FindPlayerVehicle()->IsCar())
- if(FindPlayerVehicle()->IsAlarmOn())
- // if player's alarm is on, increase wanted level
- if((FindPlayerVehicle()->GetPosition() - GetPosition()).MagnitudeSqr() < sq(20.0f))
- CWorld::Players[CWorld::PlayerInFocus].m_pPed->SetWantedLevelNoDrop(1);
-}
-
-void
-CAutomobile::BlowUpCarsInPath(void)
-{
- int i;
-
- if(m_vecMoveSpeed.Magnitude() > 0.1f)
- for(i = 0; i < m_nCollisionRecords; i++)
- if(m_aCollisionRecords[i] &&
- m_aCollisionRecords[i]->IsVehicle() &&
- m_aCollisionRecords[i]->GetModelIndex() != MI_RHINO &&
- !m_aCollisionRecords[i]->bRenderScorched)
- ((CVehicle*)m_aCollisionRecords[i])->BlowUpCar(this);
-}
-
-bool
-CAutomobile::HasCarStoppedBecauseOfLight(void)
-{
- int i;
-
- if(m_status != STATUS_SIMPLE && m_status != STATUS_PHYSICS)
- return false;
-
- if(AutoPilot.m_nCurrentRouteNode && AutoPilot.m_nNextRouteNode){
- CPathNode *curnode = &ThePaths.m_pathNodes[AutoPilot.m_nCurrentRouteNode];
- for(i = 0; i < curnode->numLinks; i++)
- if(ThePaths.m_connections[curnode->firstLink + i] == AutoPilot.m_nNextRouteNode)
- break;
- if(i < curnode->numLinks &&
- ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3) // TODO
- return true;
- }
-
- if(AutoPilot.m_nCurrentRouteNode && AutoPilot.m_nPrevRouteNode){
- CPathNode *curnode = &ThePaths.m_pathNodes[AutoPilot.m_nCurrentRouteNode];
- for(i = 0; i < curnode->numLinks; i++)
- if(ThePaths.m_connections[curnode->firstLink + i] == AutoPilot.m_nPrevRouteNode)
- break;
- if(i < curnode->numLinks &&
- ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3) // TODO
- return true;
- }
-
- return false;
-}
-
-void
-CAutomobile::SetBusDoorTimer(uint32 timer, uint8 type)
-{
- if(timer < 1000)
- timer = 1000;
- if(type == 0)
- // open and close
- m_nBusDoorTimerStart = CTimer::GetTimeInMilliseconds();
- else
- // only close
- m_nBusDoorTimerStart = CTimer::GetTimeInMilliseconds() - 500;
- m_nBusDoorTimerEnd = m_nBusDoorTimerStart + timer;
-}
-
-void
-CAutomobile::ProcessAutoBusDoors(void)
-{
- if(CTimer::GetTimeInMilliseconds() < m_nBusDoorTimerEnd){
- if(m_nBusDoorTimerEnd != 0 && CTimer::GetTimeInMilliseconds() > m_nBusDoorTimerEnd-500){
- // close door
- if(!IsDoorMissing(DOOR_FRONT_LEFT) && (m_nGettingInFlags & 1) == 0){
- if(IsDoorClosed(DOOR_FRONT_LEFT)){
- m_nBusDoorTimerEnd = CTimer::GetTimeInMilliseconds();
- OpenDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT, 0.0f);
- }else{
- OpenDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT,
- 1.0f - (CTimer::GetTimeInMilliseconds() - (m_nBusDoorTimerEnd-500))/500.0f);
- }
- }
-
- if(!IsDoorMissing(DOOR_FRONT_RIGHT) && (m_nGettingInFlags & 4) == 0){
- if(IsDoorClosed(DOOR_FRONT_RIGHT)){
- m_nBusDoorTimerEnd = CTimer::GetTimeInMilliseconds();
- OpenDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT, 0.0f);
- }else{
- OpenDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT,
- 1.0f - (CTimer::GetTimeInMilliseconds() - (m_nBusDoorTimerEnd-500))/500.0f);
- }
- }
- }
- }else{
- // ended
- if(m_nBusDoorTimerStart){
- if(!IsDoorMissing(DOOR_FRONT_LEFT) && (m_nGettingInFlags & 1) == 0)
- OpenDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT, 0.0f);
- if(!IsDoorMissing(DOOR_FRONT_RIGHT) && (m_nGettingInFlags & 4) == 0)
- OpenDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT, 0.0f);
- m_nBusDoorTimerStart = 0;
- m_nBusDoorTimerEnd = 0;
- }
- }
-}
-
-void
-CAutomobile::ProcessSwingingDoor(int32 component, eDoors door)
-{
- if(Damage.GetDoorStatus(door) != DOOR_STATUS_SWINGING)
- return;
-
- CMatrix mat(RwFrameGetMatrix(m_aCarNodes[component]));
- CVector pos = mat.GetPosition();
- float axes[3] = { 0.0f, 0.0f, 0.0f };
-
- Doors[door].Process(this);
- axes[Doors[door].m_nAxis] = Doors[door].m_fAngle;
- mat.SetRotate(axes[0], axes[1], axes[2]);
- mat.Translate(pos);
- mat.UpdateRW();
-}
-
-void
-CAutomobile::Fix(void)
-{
- int component;
-
- Damage.ResetDamageStatus();
-
- if(pHandling->Flags & HANDLING_NO_DOORS){
- Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_MISSING);
- Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_MISSING);
- Damage.SetDoorStatus(DOOR_REAR_LEFT, DOOR_STATUS_MISSING);
- Damage.SetDoorStatus(DOOR_REAR_RIGHT, DOOR_STATUS_MISSING);
- }
-
- bIsDamaged = false;
- RpClumpForAllAtomics((RpClump*)m_rwObject, CVehicleModelInfo::HideAllComponentsAtomicCB, (void*)ATOMIC_FLAG_DAM);
-
- for(component = CAR_BUMP_FRONT; component < NUM_CAR_NODES; component++){
- if(m_aCarNodes[component]){
- CMatrix mat(RwFrameGetMatrix(m_aCarNodes[component]));
- mat.SetTranslate(mat.GetPosition());
- mat.UpdateRW();
- }
- }
-}
-
-void
-CAutomobile::SetupDamageAfterLoad(void)
-{
- if(m_aCarNodes[CAR_BUMP_FRONT])
- SetBumperDamage(CAR_BUMP_FRONT, VEHBUMPER_FRONT);
- if(m_aCarNodes[CAR_BONNET])
- SetDoorDamage(CAR_BONNET, DOOR_BONNET);
- if(m_aCarNodes[CAR_BUMP_REAR])
- SetBumperDamage(CAR_BUMP_REAR, VEHBUMPER_REAR);
- if(m_aCarNodes[CAR_BOOT])
- SetDoorDamage(CAR_BOOT, DOOR_BOOT);
- if(m_aCarNodes[CAR_DOOR_LF])
- SetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT);
- if(m_aCarNodes[CAR_DOOR_RF])
- SetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT);
- if(m_aCarNodes[CAR_DOOR_LR])
- SetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT);
- if(m_aCarNodes[CAR_DOOR_RR])
- SetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT);
- if(m_aCarNodes[CAR_WING_LF])
- SetPanelDamage(CAR_WING_LF, VEHPANEL_FRONT_LEFT);
- if(m_aCarNodes[CAR_WING_RF])
- SetPanelDamage(CAR_WING_RF, VEHPANEL_FRONT_RIGHT);
- if(m_aCarNodes[CAR_WING_LR])
- SetPanelDamage(CAR_WING_LR, VEHPANEL_REAR_LEFT);
- if(m_aCarNodes[CAR_WING_RR])
- SetPanelDamage(CAR_WING_RR, VEHPANEL_REAR_RIGHT);
-}
-
-RwObject*
-GetCurrentAtomicObjectCB(RwObject *object, void *data)
-{
- RpAtomic *atomic = (RpAtomic*)object;
- assert(RwObjectGetType(object) == rpATOMIC);
- if(RpAtomicGetFlags(atomic) & rpATOMICRENDER)
- *(RpAtomic**)data = atomic;
- return object;
-}
-
-CColPoint aTempPedColPts[32]; // this name doesn't make any sense
-
-CObject*
-CAutomobile::SpawnFlyingComponent(int32 component, uint32 type)
-{
- RpAtomic *atomic;
- RwFrame *frame;
- RwMatrix *matrix;
- CObject *obj;
-
- if(CObject::nNoTempObjects >= NUMTEMPOBJECTS)
- return nil;
-
- atomic = nil;
- RwFrameForAllObjects(m_aCarNodes[component], GetCurrentAtomicObjectCB, &atomic);
- if(atomic == nil)
- return nil;
-
- obj = new CObject;
- if(obj == nil)
- return nil;
-
- if(component == CAR_WINDSCREEN){
- obj->SetModelIndexNoCreate(MI_CAR_BONNET);
- }else switch(type){
- case COMPGROUP_BUMPER:
- obj->SetModelIndexNoCreate(MI_CAR_BUMPER);
- break;
- case COMPGROUP_WHEEL:
- obj->SetModelIndexNoCreate(MI_CAR_WHEEL);
- break;
- case COMPGROUP_DOOR:
- obj->SetModelIndexNoCreate(MI_CAR_DOOR);
- obj->SetCenterOfMass(0.0f, -0.5f, 0.0f);
- break;
- case COMPGROUP_BONNET:
- obj->SetModelIndexNoCreate(MI_CAR_BONNET);
- obj->SetCenterOfMass(0.0f, 0.4f, 0.0f);
- break;
- case COMPGROUP_BOOT:
- obj->SetModelIndexNoCreate(MI_CAR_BOOT);
- obj->SetCenterOfMass(0.0f, -0.3f, 0.0f);
- break;
- case COMPGROUP_PANEL:
- default:
- obj->SetModelIndexNoCreate(MI_CAR_PANEL);
- break;
- }
-
- // object needs base model
- obj->RefModelInfo(GetModelIndex());
-
- // create new atomic
- matrix = RwFrameGetLTM(m_aCarNodes[component]);
- frame = RwFrameCreate();
- atomic = RpAtomicClone(atomic);
- *RwFrameGetMatrix(frame) = *matrix;
- RpAtomicSetFrame(atomic, frame);
- CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
- obj->AttachToRwObject((RwObject*)atomic);
-
- // init object
- obj->m_fMass = 10.0f;
- obj->m_fTurnMass = 25.0f;
- obj->m_fAirResistance = 0.97f;
- obj->m_fElasticity = 0.1f;
- obj->m_fBuoyancy = obj->m_fMass*GRAVITY/0.75f;
- obj->ObjectCreatedBy = TEMP_OBJECT;
- obj->bIsStatic = false;
- obj->bIsPickup = false;
- obj->bUseVehicleColours = true;
- obj->m_colour1 = m_currentColour1;
- obj->m_colour2 = m_currentColour2;
-
- // life time - the more objects the are, the shorter this one will live
- CObject::nNoTempObjects++;
- if(CObject::nNoTempObjects > 20)
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000/5.0f;
- else if(CObject::nNoTempObjects > 10)
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000/2.0f;
- else
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000;
-
- obj->m_vecMoveSpeed = m_vecMoveSpeed;
- if(obj->m_vecMoveSpeed.z > 0.0f){
- obj->m_vecMoveSpeed.z *= 1.5f;
- }else if(GetUp().z > 0.0f &&
- (component == COMPGROUP_BONNET || component == COMPGROUP_BOOT || component == CAR_WINDSCREEN)){
- obj->m_vecMoveSpeed.z *= -1.5f;
- obj->m_vecMoveSpeed.z += 0.04f;
- }else{
- obj->m_vecMoveSpeed.z *= 0.25f;
- }
- obj->m_vecMoveSpeed.x *= 0.75f;
- obj->m_vecMoveSpeed.y *= 0.75f;
-
- obj->m_vecTurnSpeed = m_vecTurnSpeed*2.0f;
-
- // push component away from car
- CVector dist = obj->GetPosition() - GetPosition();
- dist.Normalise();
- if(component == COMPGROUP_BONNET || component == COMPGROUP_BOOT || component == CAR_WINDSCREEN){
- // push these up some
- dist += GetUp();
- if(GetUp().z > 0.0f){
- // simulate fast upward movement if going fast
- float speed = CVector2D(m_vecMoveSpeed).MagnitudeSqr();
- obj->GetPosition() += GetUp()*speed;
- }
- }
- obj->ApplyMoveForce(dist);
-
- if(type == COMPGROUP_WHEEL){
- obj->m_fTurnMass = 5.0f;
- obj->m_vecTurnSpeed.x = 0.5f;
- obj->m_fAirResistance = 0.99f;
- }
-
- if(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(),
- this->GetMatrix(), *this->GetColModel(),
- aTempPedColPts, nil, nil) > 0)
- obj->m_pCollidingEntity = this;
-
- if(bRenderScorched)
- obj->bRenderScorched = true;
-
- CWorld::Add(obj);
-
- return obj;
-}
-
-CObject*
-CAutomobile::RemoveBonnetInPedCollision(void)
-{
- CObject *obj;
-
- if(Damage.GetDoorStatus(DOOR_BONNET) != DOOR_STATUS_SWINGING &&
- Doors[DOOR_BONNET].RetAngleWhenOpen()*0.4f < Doors[DOOR_BONNET].m_fAngle){
- // BUG? why not COMPGROUP_BONNET?
- obj = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_DOOR);
- // make both doors invisible on car
- SetComponentVisibility(m_aCarNodes[CAR_BONNET], ATOMIC_FLAG_NONE);
- Damage.SetDoorStatus(DOOR_BONNET, DOOR_STATUS_MISSING);
- return obj;
- }
- return nil;
-}
-
-void
-CAutomobile::SetPanelDamage(int32 component, ePanels panel, bool noFlyingComponents)
-{
- int status = Damage.GetPanelStatus(panel);
- if(m_aCarNodes[component] == nil)
- return;
- if(status == PANEL_STATUS_SMASHED1){
- // show damaged part
- SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_DAM);
- }else if(status == PANEL_STATUS_MISSING){
- if(!noFlyingComponents)
- SpawnFlyingComponent(component, COMPGROUP_PANEL);
- // hide both
- SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_NONE);
- }
-}
-
-void
-CAutomobile::SetBumperDamage(int32 component, ePanels panel, bool noFlyingComponents)
-{
- int status = Damage.GetPanelStatus(panel);
- if(m_aCarNodes[component] == nil){
- printf("Trying to damage component %d of %s\n",
- component, CModelInfo::GetModelInfo(GetModelIndex())->GetName());
- return;
- }
- if(status == PANEL_STATUS_SMASHED1){
- // show damaged part
- SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_DAM);
- }else if(status == PANEL_STATUS_MISSING){
- if(!noFlyingComponents)
- SpawnFlyingComponent(component, COMPGROUP_BUMPER);
- // hide both
- SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_NONE);
- }
-}
-
-void
-CAutomobile::SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents)
-{
- int status = Damage.GetDoorStatus(door);
- if(m_aCarNodes[component] == nil){
- printf("Trying to damage component %d of %s\n",
- component, CModelInfo::GetModelInfo(GetModelIndex())->GetName());
- return;
- }
-
- if(door == DOOR_BOOT && status == DOOR_STATUS_SWINGING && pHandling->Flags & HANDLING_NOSWING_BOOT){
- Damage.SetDoorStatus(DOOR_BOOT, DOOR_STATUS_MISSING);
- status = DOOR_STATUS_MISSING;
- }
-
- if(status == DOOR_STATUS_SMASHED){
- // show damaged part
- SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_DAM);
- }else if(status == DOOR_STATUS_SWINGING){
- // turn off angle cull for swinging doors
- RwFrameForAllObjects(m_aCarNodes[component], CVehicleModelInfo::SetAtomicFlagCB, (void*)ATOMIC_FLAG_NOCULL);
- }else if(status == DOOR_STATUS_MISSING){
- if(!noFlyingComponents){
- if(door == DOOR_BONNET)
- SpawnFlyingComponent(component, COMPGROUP_BONNET);
- else if(door == DOOR_BOOT)
- SpawnFlyingComponent(component, COMPGROUP_BOOT);
- else
- SpawnFlyingComponent(component, COMPGROUP_DOOR);
- }
- // hide both
- SetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_NONE);
- }
-}
-
-
-static RwObject*
-SetVehicleAtomicVisibilityCB(RwObject *object, void *data)
-{
- uint32 flags = (uint32)(uintptr)data;
- RpAtomic *atomic = (RpAtomic*)object;
- if((CVisibilityPlugins::GetAtomicId(atomic) & (ATOMIC_FLAG_OK|ATOMIC_FLAG_DAM)) == flags)
- RpAtomicSetFlags(atomic, rpATOMICRENDER);
- else
- RpAtomicSetFlags(atomic, 0);
- return object;
-}
-
-void
-CAutomobile::SetComponentVisibility(RwFrame *frame, uint32 flags)
-{
- HideAllComps();
- bIsDamaged = true;
- RwFrameForAllObjects(frame, SetVehicleAtomicVisibilityCB, (void*)flags);
-}
-
-void
-CAutomobile::SetupModelNodes(void)
-{
- int i;
- for(i = 0; i < NUM_CAR_NODES; i++)
- m_aCarNodes[i] = nil;
- CClumpModelInfo::FillFrameArray((RpClump*)m_rwObject, m_aCarNodes);
-}
-
-void
-CAutomobile::SetTaxiLight(bool light)
-{
- bTaxiLight = light;
-}
-
-bool
-CAutomobile::GetAllWheelsOffGround(void)
-{
- return m_nDriveWheelsOnGround == 0;
-}
-
-void
-CAutomobile::HideAllComps(void)
-{
- // empty
-}
-
-void
-CAutomobile::ShowAllComps(void)
-{
- // empty
-}
-
-void
-CAutomobile::ReduceHornCounter(void)
-{
- if(m_nCarHornTimer != 0)
- m_nCarHornTimer--;
-}
-
-void
-CAutomobile::SetAllTaxiLights(bool set)
-{
- m_sAllTaxiLights = set;
-}
-
-class CAutomobile_ : public CAutomobile
-{
-public:
- void ctor(int32 id, uint8 CreatedBy) { ::new (this) CAutomobile(id, CreatedBy); }
- void dtor() { CAutomobile::~CAutomobile(); }
- void SetModelIndex_(uint32 id) { CAutomobile::SetModelIndex(id); }
- void ProcessControl_(void) { CAutomobile::ProcessControl(); }
- void Teleport_(CVector v) { CAutomobile::Teleport(v); }
- void PreRender_(void) { CAutomobile::PreRender(); }
- void Render_(void) { CAutomobile::Render(); }
-
- int32 ProcessEntityCollision_(CEntity *ent, CColPoint *colpoints){ return CAutomobile::ProcessEntityCollision(ent, colpoints); }
-
- void ProcessControlInputs_(uint8 pad) { CAutomobile::ProcessControlInputs(pad); }
- void GetComponentWorldPosition_(int32 component, CVector &pos) { CAutomobile::GetComponentWorldPosition(component, pos); }
- bool IsComponentPresent_(int32 component) { return CAutomobile::IsComponentPresent(component); }
- void SetComponentRotation_(int32 component, CVector rotation) { CAutomobile::SetComponentRotation(component, rotation); }
- void OpenDoor_(int32 component, eDoors door, float ratio) { CAutomobile::OpenDoor(component, door, ratio); }
- void ProcessOpenDoor_(uint32 component, uint32 anim, float time) { CAutomobile::ProcessOpenDoor(component, anim, time); }
- bool IsDoorReady_(eDoors door) { return CAutomobile::IsDoorReady(door); }
- bool IsDoorFullyOpen_(eDoors door) { return CAutomobile::IsDoorFullyOpen(door); }
- bool IsDoorClosed_(eDoors door) { return CAutomobile::IsDoorClosed(door); }
- bool IsDoorMissing_(eDoors door) { return CAutomobile::IsDoorMissing(door); }
- void RemoveRefsToVehicle_(CEntity *ent) { CAutomobile::RemoveRefsToVehicle(ent); }
- void BlowUpCar_(CEntity *ent) { CAutomobile::BlowUpCar(ent); }
- bool SetUpWheelColModel_(CColModel *colModel) { return CAutomobile::SetUpWheelColModel(colModel); }
- void BurstTyre_(uint8 tyre) { CAutomobile::BurstTyre(tyre); }
- bool IsRoomForPedToLeaveCar_(uint32 door, CVector *pos) { return CAutomobile::IsRoomForPedToLeaveCar(door, pos); }
- float GetHeightAboveRoad_(void) { return CAutomobile::GetHeightAboveRoad(); }
- void PlayCarHorn_(void) { CAutomobile::PlayCarHorn(); }
-};
-
-STARTPATCHES
- InjectHook(0x52C6B0, &CAutomobile_::ctor, PATCH_JUMP);
- InjectHook(0x52D170, &CAutomobile_::dtor, PATCH_JUMP);
- InjectHook(0x52D190, &CAutomobile_::SetModelIndex_, PATCH_JUMP);
- InjectHook(0x531470, &CAutomobile_::ProcessControl_, PATCH_JUMP);
- InjectHook(0x535180, &CAutomobile_::Teleport_, PATCH_JUMP);
- InjectHook(0x539EA0, &CAutomobile_::Render_, PATCH_JUMP);
- InjectHook(0x535B40, &CAutomobile_::PreRender_, PATCH_JUMP);
- InjectHook(0x53B270, &CAutomobile_::ProcessEntityCollision_, PATCH_JUMP);
- InjectHook(0x53B660, &CAutomobile_::ProcessControlInputs_, PATCH_JUMP);
- InjectHook(0x52E5F0, &CAutomobile_::GetComponentWorldPosition_, PATCH_JUMP);
- InjectHook(0x52E660, &CAutomobile_::IsComponentPresent_, PATCH_JUMP);
- InjectHook(0x52E680, &CAutomobile_::SetComponentRotation_, PATCH_JUMP);
- InjectHook(0x52E750, &CAutomobile_::OpenDoor_, PATCH_JUMP);
- InjectHook(0x52EF10, &CAutomobile_::IsDoorReady_, PATCH_JUMP);
- InjectHook(0x52EF90, &CAutomobile_::IsDoorFullyOpen_, PATCH_JUMP);
- InjectHook(0x52EFD0, &CAutomobile_::IsDoorClosed_, PATCH_JUMP);
- InjectHook(0x52F000, &CAutomobile_::IsDoorMissing_, PATCH_JUMP);
- InjectHook(0x53BF40, &CAutomobile_::RemoveRefsToVehicle_, PATCH_JUMP);
- InjectHook(0x53BC60, &CAutomobile_::BlowUpCar_, PATCH_JUMP);
- InjectHook(0x53BF70, &CAutomobile_::SetUpWheelColModel_, PATCH_JUMP);
- InjectHook(0x53C0E0, &CAutomobile_::BurstTyre_, PATCH_JUMP);
- InjectHook(0x53C5B0, &CAutomobile_::IsRoomForPedToLeaveCar_, PATCH_JUMP);
- InjectHook(0x437690, &CAutomobile_::GetHeightAboveRoad_, PATCH_JUMP);
- InjectHook(0x53C450, &CAutomobile_::PlayCarHorn_, PATCH_JUMP);
- InjectHook(0x53E090, &CAutomobile::PlaceOnRoadProperly, PATCH_JUMP);
- InjectHook(0x52F030, &CAutomobile::dmgDrawCarCollidingParticles, PATCH_JUMP);
- InjectHook(0x535450, &CAutomobile::AddDamagedVehicleParticles, PATCH_JUMP);
- InjectHook(0x5357D0, &CAutomobile::AddWheelDirtAndWater, PATCH_JUMP);
- InjectHook(0x5353A0, &CAutomobile::ResetSuspension, PATCH_JUMP);
- InjectHook(0x52D210, &CAutomobile::SetupSuspensionLines, PATCH_JUMP);
- InjectHook(0x53E000, &CAutomobile::BlowUpCarsInPath, PATCH_JUMP);
- InjectHook(0x42E220, &CAutomobile::HasCarStoppedBecauseOfLight, PATCH_JUMP);
- InjectHook(0x53D320, &CAutomobile::SetBusDoorTimer, PATCH_JUMP);
- InjectHook(0x53D370, &CAutomobile::ProcessAutoBusDoors, PATCH_JUMP);
- InjectHook(0x535250, &CAutomobile::ProcessSwingingDoor, PATCH_JUMP);
- InjectHook(0x53C240, &CAutomobile::Fix, PATCH_JUMP);
- InjectHook(0x53C310, &CAutomobile::SetupDamageAfterLoad, PATCH_JUMP);
- InjectHook(0x530300, &CAutomobile::SpawnFlyingComponent, PATCH_JUMP);
- InjectHook(0x535320, &CAutomobile::RemoveBonnetInPedCollision, PATCH_JUMP);
- InjectHook(0x5301A0, &CAutomobile::SetPanelDamage, PATCH_JUMP);
- InjectHook(0x530120, &CAutomobile::SetBumperDamage, PATCH_JUMP);
- InjectHook(0x530200, &CAutomobile::SetDoorDamage, PATCH_JUMP);
- InjectHook(0x5300E0, &CAutomobile::SetComponentVisibility, PATCH_JUMP);
- InjectHook(0x52D1B0, &CAutomobile::SetupModelNodes, PATCH_JUMP);
- InjectHook(0x53C420, &CAutomobile::SetTaxiLight, PATCH_JUMP);
- InjectHook(0x53BC40, &CAutomobile::GetAllWheelsOffGround, PATCH_JUMP);
- InjectHook(0x5308C0, &CAutomobile::ReduceHornCounter, PATCH_JUMP);
- InjectHook(0x53C440, &CAutomobile::SetAllTaxiLights, PATCH_JUMP);
-ENDPATCHES
diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h
index 4dd3a087..6203957d 100644
--- a/src/vehicles/Automobile.h
+++ b/src/vehicles/Automobile.h
@@ -117,7 +117,7 @@ public:
uint8 m_nWheelsOnGround;
uint8 m_nDriveWheelsOnGround;
uint8 m_nDriveWheelsOnGroundPrev;
- int32 field_594;
+ int32 m_fGasPedalAudio;
tWheelState m_aWheelState[4];
static bool &m_sAllTaxiLights;
diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp
index 2b5ff567..f614b78f 100644
--- a/src/vehicles/Boat.cpp
+++ b/src/vehicles/Boat.cpp
@@ -61,7 +61,7 @@ float CBoat::IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat)
float fDist = vecDist.MagnitudeSqr();
if ( fDist < SQR(fMaxDist) )
- return 1.0f - Min(fRangeMult * Sqrt(fDist / SQR(fMaxDist)) + (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[i]) * fTimeMult, 1.0f);
+ return 1.0f - min(fRangeMult * Sqrt(fDist / SQR(fMaxDist)) + (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[i]) * fTimeMult, 1.0f);
}
return 0.0f;
diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp
index 1c242f0e..9b1a651d 100644
--- a/src/vehicles/Heli.cpp
+++ b/src/vehicles/Heli.cpp
@@ -1038,16 +1038,8 @@ void CHeli::ActivateHeli(bool activate) { ScriptHeliOn = activate; }
class CHeli_ : public CHeli
{
public:
-<<<<<<< HEAD
-<<<<<<< HEAD
void ctor(int32 id, uint8 CreatedBy) { ::new (this) CHeli(id, CreatedBy); }
void dtor(void) { CHeli::~CHeli(); }
-=======
- void dtor(void) { this->~CHeli(); }
->>>>>>> More audio ped
-=======
- void dtor(void) { CHeli::~CHeli(); }
->>>>>>> fix
};
STARTPATCHES
diff --git a/src/vehicles/Heli.cpp.autosave b/src/vehicles/Heli.cpp.autosave
deleted file mode 100644
index 9b1a651d..00000000
--- a/src/vehicles/Heli.cpp.autosave
+++ /dev/null
@@ -1,1055 +0,0 @@
-#include "common.h"
-#include "main.h"
-#include "patcher.h"
-#include "General.h"
-#include "Darkel.h"
-#include "Stats.h"
-#include "SurfaceTable.h"
-#include "ModelIndices.h"
-#include "Streaming.h"
-#include "Camera.h"
-#include "VisibilityPlugins.h"
-#include "ZoneCull.h"
-#include "Particle.h"
-#include "Shadows.h"
-#include "Coronas.h"
-#include "Explosion.h"
-#include "TimeCycle.h"
-#include "TempColModels.h"
-#include "World.h"
-#include "WaterLevel.h"
-#include "PlayerPed.h"
-#include "Object.h"
-#include "HandlingMgr.h"
-#include "Heli.h"
-
-enum
-{
- HELI_STATUS_HOVER,
- HELI_STATUS_CHASE_PLAYER,
- HELI_STATUS_FLY_AWAY,
- HELI_STATUS_SHOT_DOWN,
- HELI_STATUS_HOVER2,
-};
-
-CHeli **CHeli::pHelis = (CHeli**)0x72CF50;
-int16 &CHeli::NumRandomHelis = *(int16*)0x95CCAA;
-uint32 &CHeli::TestForNewRandomHelisTimer = *(uint32*)0x8F1A7C;
-int16 CHeli::NumScriptHelis; // unused
-bool &CHeli::CatalinaHeliOn = *(bool*)0x95CD85;
-bool &CHeli::CatalinaHasBeenShotDown = *(bool*)0x95CD56;
-bool &CHeli::ScriptHeliOn = *(bool*)0x95CD43;
-
-CHeli::CHeli(int32 id, uint8 CreatedBy)
- : CVehicle(CreatedBy)
-{
- int i;
-
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
- m_vehType = VEHICLE_TYPE_HELI;
- pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId);
- SetModelIndex(id);
- m_heliStatus = HELI_STATUS_HOVER;
- m_pathState = 0;
-
- m_fMass = 100000000.0f;
- m_fTurnMass = 100000000.0f;
- m_fAirResistance = 0.9994f;
- m_fElasticity = 0.05f;
-
- m_nHeliId = 0;
- m_fRotorRotation = 0.0f;
- m_nBulletDamage = 0;
- m_fAngularSpeed = 0.0f;
- m_fRotation = 0.0f;
- m_nSearchLightTimer = CTimer::GetTimeInMilliseconds();
- for(i = 0; i < 6; i++){
- m_aSearchLightHistoryX[i] = 0.0f;
- m_aSearchLightHistoryY[i] = 0.0f;
- }
-
- for(i = 0; i < 8; i++)
- m_fHeliDustZ[i] = -50.0f;
-
- m_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds();
- m_status = STATUS_HELI;
- m_bTestRight = true;
- m_fTargetOffset = 0.0f;
- m_fSearchLightX = m_fSearchLightY = 0.0f;
-}
-
-void
-CHeli::SetModelIndex(uint32 id)
-{
- int i;
-
- CVehicle::SetModelIndex(id);
- for(i = 0; i < NUM_HELI_NODES; i++)
- m_aHeliNodes[i] = nil;
- CClumpModelInfo::FillFrameArray(GetClump(), m_aHeliNodes);
-}
-
-static float CatalinaTargetX[7] = { -478.0, -677.0, -907.0, -1095.0, -1152.0, -1161.0, -1161.0 };
-static float CatalinaTargetY[7] = { 227.0, 206.0, 210.0, 242.0, 278.0, 341.0, 341.0 };
-static float CatalinaTargetZ[7] = { 77.0, 66.0, 60.0, 53.0, 51.0, 46.0, 30.0 };
-static float DamPathX[6] = { -1191.0, -1176.0, -1128.0, -1072.0, -1007.0, -971.0 };
-static float DamPathY[6] = { 350.0, 388.0, 429.0, 447.0, 449.0, 416.0 };
-static float DamPathZ[6] = { 42.0, 37.0, 28.0, 28.0, 31.0, 33.0 };
-static float ShortPathX[4] = { -974.0, -1036.0, -1112.0, -1173.0 };
-static float ShortPathY[4] = { 340.0, 312.0, 317.0, 294.0 };
-static float ShortPathZ[4] = { 41.0, 38.0, 32.0, 39.0 };
-static float LongPathX[7] = { -934.0, -905.0, -906.0, -1063.0, -1204.0, -1233.0, -1207.0 };
-static float LongPathY[7] = { 371.0, 362.0, 488.0, 548.0, 451.0, 346.0, 308.0 };
-static float LongPathZ[7] = { 57.0, 90.0, 105.0, 100.0, 81.0, 79.0, 70.0 };
-
-static int PathPoint;
-
-void
-CHeli::ProcessControl(void)
-{
- int i;
-
- if(gbModelViewer)
- return;
-
- // Find target
- CVector target(0.0f, 0.0f, 0.0f);
- CVector2D vTargetDist;
- if(m_heliType == HELI_TYPE_CATALINA && m_heliStatus != HELI_STATUS_SHOT_DOWN){
- switch(m_pathState){
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- target.x = CatalinaTargetX[m_pathState];
- target.y = CatalinaTargetY[m_pathState];
- target.z = CatalinaTargetZ[m_pathState];
- if((target - GetPosition()).Magnitude() < 9.0f)
- m_pathState++;
- break;
- case 6:
- target.x = CatalinaTargetX[m_pathState];
- target.y = CatalinaTargetY[m_pathState];
- target.z = CatalinaTargetZ[m_pathState];
- if(GetPosition().z > 31.55f)
- break;
- m_pathState = 7;
- GetPosition().z = 31.55f;
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- break;
- case 7:
- GetPosition().z = 31.55f;
- target = GetPosition();
- break;
-
-
- // Take off
- case 8:
- target.x = GetPosition().x;
- target.y = GetPosition().y;
- target.z = 74.0f;
- if(GetPosition().z < 40.0f)
- break;
- PathPoint = 2;
- m_pathState = 9;
- break;
- // Circle around dam
- case 9:
- target.x = DamPathX[PathPoint];
- target.y = DamPathY[PathPoint];
- target.z = DamPathZ[PathPoint];
- if((target - GetPosition()).Magnitude() < 9.0f){
- PathPoint++;
- if(PathPoint >= 6){
- m_pathState = 10;
- PathPoint = 0;
- }
- }
- break;
- case 10:
- target.x = ShortPathX[PathPoint];
- target.y = ShortPathY[PathPoint];
- target.z = ShortPathZ[PathPoint];
- if((target - GetPosition()).Magnitude() < 9.0f){
- PathPoint++;
- if(PathPoint >= 3){
- m_pathState = 9;
- PathPoint = 1;
- }
- }
- break;
- // how do we get here?
- case 11:
- target.x = LongPathX[PathPoint];
- target.y = LongPathY[PathPoint];
- target.z = LongPathZ[PathPoint];
- if((target - GetPosition()).Magnitude() < 9.0f){
- PathPoint++;
- if(PathPoint >= 7){
- m_pathState = 9;
- PathPoint = 0;
- }
- }
- break;
-
-
- // Fly away
- case 12:
- target.x = GetPosition().x;
- target.y = GetPosition().y;
- target.z = 200.0f;
- break;
- }
-
- vTargetDist = target - GetPosition();
- m_fTargetZ = target.z;
- if(m_pathState == 6){
- GetPosition().x = GetPosition().x*0.99f + target.x*0.01f;
- GetPosition().y = GetPosition().y*0.99f + target.y*0.01f;
- }
- }else{
- vTargetDist = FindPlayerCoors() - GetPosition();
- m_fTargetZ = FindPlayerCoors().z;
-
- // Heli flies away to (0, 0)
- if(m_heliStatus == HELI_STATUS_FLY_AWAY && GetPosition().z > 20.0f){
- vTargetDist.x = 0.0f - GetPosition().x;
- vTargetDist.y = 0.0f - GetPosition().y;
- }
-
- float groundZ;
- switch(m_heliStatus){
- case HELI_STATUS_HOVER:
- groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil);
- m_fTargetZ = max(groundZ, m_fTargetZ) + 8.0f;
- break;
- case HELI_STATUS_SHOT_DOWN:
- groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil);
- m_fTargetZ = max(groundZ, m_fTargetZ) + 8.0f + m_fTargetOffset;
- break;
- case HELI_STATUS_HOVER2:
- groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil);
- m_fTargetZ = max(groundZ, m_fTargetZ) + 8.0f + m_fTargetOffset;
- break;
- default:
- groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil);
- m_fTargetZ = max(groundZ, m_fTargetZ) + 12.0f;
- break;
- }
-
- // Move up if too low
- if(GetPosition().z - 2.0f < groundZ && m_heliStatus != HELI_STATUS_SHOT_DOWN)
- m_vecMoveSpeed.z += CTimer::GetTimeStep()*0.01f;
- m_vecMoveSpeed.z = clamp(m_vecMoveSpeed.z, -0.3f, 0.3f);
- }
-
- float fTargetDist = vTargetDist.Magnitude();
-
- switch(m_heliStatus){
- case HELI_STATUS_HOVER:
- case HELI_STATUS_HOVER2:{
- float targetHeight;
- if(m_heliType == HELI_TYPE_CATALINA)
- targetHeight = 8.0f;
- else
- targetHeight = 40.0f - m_nHeliId*10.0f;
- if(fTargetDist > targetHeight)
- m_heliStatus = HELI_STATUS_CHASE_PLAYER;
- }
- // fall through, BUG?
- case HELI_STATUS_CHASE_PLAYER:{
- float targetHeight;
- if(m_heliType == HELI_TYPE_CATALINA)
- targetHeight = 4.0f;
- else
- targetHeight = 30.0f - m_nHeliId*7.5f;
- if(fTargetDist < 1.0f ||
- fTargetDist < targetHeight && CWorld::GetIsLineOfSightClear(GetPosition(), FindPlayerCoors(), true, false, false, false, false, false))
- m_heliStatus = HELI_STATUS_HOVER;
- }
- }
-
- // Find xy speed
- float speed;
- if(fTargetDist > 100.0f)
- speed = 1.0f;
- else if(fTargetDist > 75.0f)
- speed = 0.7f;
- else
- speed = 0.4f;
- if(m_heliStatus == HELI_STATUS_HOVER || m_heliStatus == HELI_STATUS_HOVER2 || m_heliStatus == HELI_STATUS_SHOT_DOWN)
- speed = 0.0f;
-
- if(fTargetDist != 0.0f)
- vTargetDist /= fTargetDist;
- else
- vTargetDist.x = 1.0f;
- CVector2D targetSpeed = vTargetDist * speed;
-
- if(m_heliStatus == HELI_STATUS_HOVER2 || m_heliStatus == HELI_STATUS_SHOT_DOWN){
- bool force = !!((CTimer::GetFrameCounter() + m_randomSeed) & 8);
- if(m_bTestRight){
- if(force || CWorld::TestSphereAgainstWorld(GetPosition() + 4.0f*GetRight(), 2.0f, this, true, false, false, false, false, false) == nil){
- if(m_heliStatus == HELI_STATUS_SHOT_DOWN){
- m_fTargetOffset -= CTimer::GetTimeStep()*0.05f;
- targetSpeed.x -= -vTargetDist.x*0.15f;
- targetSpeed.y -= vTargetDist.y*0.15f;
- }else{
- targetSpeed.x -= -vTargetDist.x*0.05f;
- targetSpeed.y -= vTargetDist.y*0.05f;
- }
- }else{
- m_bTestRight = false;
- if(m_heliStatus == HELI_STATUS_HOVER2)
- m_fTargetOffset += 5.0f;
- else
- m_fTargetOffset -= 5.0f;
- }
- }else{
- if(force || CWorld::TestSphereAgainstWorld(GetPosition() - 4.0f*GetRight(), 2.0f, this, true, false, false, false, false, false) == nil){
- if(m_heliStatus == HELI_STATUS_SHOT_DOWN){
- m_fTargetOffset -= CTimer::GetTimeStep()*0.05f;
- targetSpeed.x += -vTargetDist.x*0.15f;
- targetSpeed.y += vTargetDist.y*0.15f;
- }else{
- targetSpeed.x += -vTargetDist.x*0.05f;
- targetSpeed.y += vTargetDist.y*0.05f;
- }
- }else{
- m_bTestRight = true;
- if(m_heliStatus == HELI_STATUS_HOVER2)
- m_fTargetOffset += 5.0f;
- else
- m_fTargetOffset -= 5.0f;
- }
- }
-
- if(m_fTargetOffset > 30.0f)
- m_fTargetOffset = 30.0f;
-
- if(m_heliStatus == HELI_STATUS_SHOT_DOWN && force){
- if(CWorld::TestSphereAgainstWorld(GetPosition() + 1.5f*GetForward(), 2.0f, this, true, false, false, false, false, false) ||
- CWorld::TestSphereAgainstWorld(GetPosition() - 1.5f*GetForward(), 2.0f, this, true, false, false, false, false, false))
- m_nExplosionTimer = CTimer::GetPreviousTimeInMilliseconds();
- }
- }else
- if(m_fTargetOffset >= 2.0f)
- m_fTargetOffset -= 2.0f;
-
- if(m_heliType == HELI_TYPE_CATALINA)
- if(m_pathState == 9 || m_pathState == 11 || m_pathState == 10){
- float f = Pow(0.997f, CTimer::GetTimeStep());
- m_vecMoveSpeed.x *= f;
- m_vecMoveSpeed.y *= f;
- }
-
- CVector2D speedDir = targetSpeed - m_vecMoveSpeed;
- float speedDiff = speedDir.Magnitude();
- if(speedDiff != 0.0f)
- speedDir /= speedDiff;
- else
- speedDir.x = 1.0f;
- float speedInc = CTimer::GetTimeStep()*0.002f;
- if(speedDiff < speedInc){
- m_vecMoveSpeed.x = targetSpeed.x;
- m_vecMoveSpeed.y = targetSpeed.y;
- }else{
- m_vecMoveSpeed.x += speedDir.x*speedInc;
- m_vecMoveSpeed.y += speedDir.y*speedInc;
- }
- GetPosition().x += m_vecMoveSpeed.x*CTimer::GetTimeStep();
- GetPosition().y += m_vecMoveSpeed.y*CTimer::GetTimeStep();
-
- // Find z target
- if(m_heliStatus == HELI_STATUS_FLY_AWAY)
- m_fTargetZ = 1000.0f;
- if((CTimer::GetTimeInMilliseconds() + 800*m_nHeliId) & 0x800)
- m_fTargetZ += 2.0f;
- m_fTargetZ += m_nHeliId*5.0f;
-
- // Find z speed
- float targetSpeedZ = (m_fTargetZ - GetPosition().z)*0.01f;
- float speedDiffZ = targetSpeedZ - m_vecMoveSpeed.z;
- float speedIncZ = CTimer::GetTimeStep()*0.001f;
- if(m_heliStatus == HELI_STATUS_FLY_AWAY)
- speedIncZ *= 1.5f;
- if(Abs(speedDiffZ) < speedIncZ)
- m_vecMoveSpeed.z = targetSpeedZ;
- else if(speedDiffZ < 0.0f)
- m_vecMoveSpeed.z -= speedIncZ;
- else
- m_vecMoveSpeed.z += speedIncZ*1.5f;
- GetPosition().z += m_vecMoveSpeed.z*CTimer::GetTimeStep();
-
- // Find angular speed
- float targetAngularSpeed;
- m_fAngularSpeed *= Pow(0.995f, CTimer::GetTimeStep());
- if(fTargetDist < 8.0f)
- targetAngularSpeed = 0.0f;
- else{
- float rotationDiff = CGeneral::GetATanOfXY(vTargetDist.x, vTargetDist.y) - m_fRotation;
- while(rotationDiff < -3.14f) rotationDiff += 6.28f;
- while(rotationDiff > 3.14f) rotationDiff -= 6.28f;
- if(Abs(rotationDiff) > 0.4f){
- if(rotationDiff < 0.0f)
- targetAngularSpeed = -0.2f;
- else
- targetAngularSpeed = 0.2f;
- }else
- targetAngularSpeed = 0.0f;
- }
- float angularSpeedDiff = targetAngularSpeed - m_fAngularSpeed;
- float angularSpeedInc = CTimer::GetTimeStep()*0.0001f;
- if(Abs(angularSpeedDiff) < angularSpeedInc)
- m_fAngularSpeed = targetAngularSpeed;
- else if(angularSpeedDiff < 0.0f)
- m_fAngularSpeed -= angularSpeedInc;
- else
- m_fAngularSpeed += angularSpeedInc;
- m_fRotation += m_fAngularSpeed * CTimer::GetTimeStep();
-
- // Set matrix
- CVector up(3.0f*m_vecMoveSpeed.x, 3.0f*m_vecMoveSpeed.y, 1.0f);
- up.Normalise();
- CVector fwd(-Cos(m_fRotation), -Sin(m_fRotation), 0.0f); // not really forward
- CVector right = CrossProduct(up, fwd);
- fwd = CrossProduct(up, right);
- GetRight() = right;
- GetForward() = fwd;
- GetUp() = up;
-
- // Search light and shooting
- if(m_heliStatus == HELI_STATUS_FLY_AWAY || m_heliType == HELI_TYPE_CATALINA || CCullZones::PlayerNoRain())
- m_fSearchLightIntensity = 0.0f;
- else{
- // Update search light history once every 1000ms
- int timeDiff = CTimer::GetTimeInMilliseconds() - m_nSearchLightTimer;
- while(timeDiff > 1000){
- for(i = 5; i > 0; i--){
- m_aSearchLightHistoryX[i] = m_aSearchLightHistoryX[i-1];
- m_aSearchLightHistoryY[i] = m_aSearchLightHistoryY[i-1];
- }
- m_aSearchLightHistoryX[0] = FindPlayerCoors().x + FindPlayerSpeed().x*50.0f*(m_nHeliId+2);
- m_aSearchLightHistoryY[0] = FindPlayerCoors().y + FindPlayerSpeed().y*50.0f*(m_nHeliId+2);
-
- timeDiff -= 1000;
- m_nSearchLightTimer += 1000;
- }
- assert(timeDiff <= 1000);
- float f1 = timeDiff/1000.0f;
- float f2 = 1.0f - f1;
- m_fSearchLightX = m_aSearchLightHistoryX[m_nHeliId+2]*f2 + m_aSearchLightHistoryX[m_nHeliId+2-1]*f1;
- m_fSearchLightY = m_aSearchLightHistoryY[m_nHeliId+2]*f2 + m_aSearchLightHistoryY[m_nHeliId+2-1]*f1;
-
- float searchLightDist = (CVector2D(m_fSearchLightX, m_fSearchLightY) - GetPosition()).Magnitude();
- if(searchLightDist > 60.0f)
- m_fSearchLightIntensity = 0.0f;
- else if(searchLightDist < 40.0f)
- m_fSearchLightIntensity = 1.0f;
- else
- m_fSearchLightIntensity = 1.0f - (40.0f-searchLightDist)/40.0f;
-
- if(m_fSearchLightIntensity < 0.9f || sq(FindPlayerCoors().x-m_fSearchLightX) + sq(FindPlayerCoors().y-m_fSearchLightY) > sq(7.0f))
- m_nShootTimer = CTimer::GetTimeInMilliseconds();
- else if(CTimer::GetTimeInMilliseconds() > m_nPoliceShoutTimer){
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_PED_HELI_PLAYER_FOUND, 0.0f);
- m_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds() + 4500 + (CGeneral::GetRandomNumber()&0xFFF);
- }
-
- // Shoot
- int shootTimeout;
- if(m_heliType == HELI_TYPE_RANDOM){
- switch(FindPlayerPed()->m_pWanted->m_nWantedLevel){
- case 0:
- case 1:
- case 2: shootTimeout = 999999; break;
- case 3: shootTimeout = 10000; break;
- case 4: shootTimeout = 5000; break;
- case 5: shootTimeout = 3500; break;
- case 6: shootTimeout = 2000; break;
- }
- if(CCullZones::NoPolice())
- shootTimeout /= 2;
- }else
- shootTimeout = 1500;
-
- if(FindPlayerPed()->m_pWanted->IsIgnored())
- m_nShootTimer = CTimer::GetTimeInMilliseconds();
- else{
- // Check if line of sight is clear
- if(CTimer::GetTimeInMilliseconds() > m_nShootTimer + shootTimeout &&
- CTimer::GetPreviousTimeInMilliseconds() <= m_nShootTimer + shootTimeout){
- if(CWorld::GetIsLineOfSightClear(GetPosition(), FindPlayerCoors(), true, false, false, false, false, false)){
- if(m_heliStatus == HELI_STATUS_HOVER2)
- m_heliStatus = HELI_STATUS_HOVER;
- }else{
- m_nShootTimer = CTimer::GetTimeInMilliseconds();
- if(m_heliStatus == HELI_STATUS_HOVER)
- m_heliStatus = HELI_STATUS_HOVER2;
- }
- }
-
- // Shoot!
- if(CTimer::GetTimeInMilliseconds() > m_nShootTimer + shootTimeout &&
- CTimer::GetTimeInMilliseconds() > m_nLastShotTime + 200){
- CVector shotTarget = FindPlayerCoors();
- // some inaccuracy
- shotTarget.x += ((CGeneral::GetRandomNumber()&0xFF)-128)/50.0f;
- shotTarget.y += ((CGeneral::GetRandomNumber()&0xFF)-128)/50.0f;
- CVector direction = FindPlayerCoors() - GetPosition();
- direction.Normalise();
- shotTarget += 3.0f*direction;
- CVector shotSource = GetPosition();
- shotSource += 3.0f*direction;
- FireOneInstantHitRound(&shotSource, &shotTarget, 20);
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);
- m_nLastShotTime = CTimer::GetTimeInMilliseconds();
- }
- }
- }
-
- // Drop Catalina's bombs
- if(m_heliType == HELI_TYPE_CATALINA && m_pathState > 8 && (CTimer::GetTimeInMilliseconds()>>9) != (CTimer::GetPreviousTimeInMilliseconds()>>9)){
- CVector bombPos = GetPosition() - 60.0f*m_vecMoveSpeed;
- if(sq(FindPlayerCoors().x-bombPos.x) + sq(FindPlayerCoors().y-bombPos.y) < sq(35.0f)){
- bool found;
- float groundZ = CWorld::FindGroundZFor3DCoord(bombPos.x, bombPos.y, bombPos.z, &found);
- float waterZ;
- if(!CWaterLevel::GetWaterLevelNoWaves(bombPos.x, bombPos.y, bombPos.z, &waterZ))
- waterZ = 0.0f;
- if(groundZ > waterZ){
- bombPos.z = groundZ + 2.0f;
- CExplosion::AddExplosion(nil, this, EXPLOSION_HELI_BOMB, bombPos, 0);
- }else{
- bombPos.z = waterZ;
- CVector dir;
- for(i = 0; i < 16; i++){
- dir.x = ((CGeneral::GetRandomNumber()&0xFF)-127)*0.001f;
- dir.y = ((CGeneral::GetRandomNumber()&0xFF)-127)*0.001f;
- dir.z = 0.5f;
- CParticle::AddParticle(PARTICLE_BOAT_SPLASH, bombPos, dir, nil, 0.2f);
- }
- }
- }
- }
-
- RemoveAndAdd();
- bIsInSafePosition = true;
- GetMatrix().UpdateRW();
- UpdateRwFrame();
-}
-
-void
-CHeli::PreRender(void)
-{
- float angle;
- uint8 i;
- CColPoint point;
- CEntity *entity;
- uint8 r, g, b;
- float testLowZ = FindPlayerCoors().z - 10.0f;
- float radius = (GetPosition().z - FindPlayerCoors().z - 10.0f - 1.0f) * 0.3f + 10.0f;
- int frm = CTimer::GetFrameCounter() & 7;
-
- i = 0;
- for(angle = 0.0f; angle < TWOPI; angle += TWOPI/32){
- CVector pos(radius*Cos(angle), radius*Sin(angle), 0.0f);
- CVector dir = pos*0.01f;
- pos += GetPosition();
-
- if(CWorld::ProcessVerticalLine(pos, testLowZ, point, entity, true, false, false, false, true, false, nil))
- m_fHeliDustZ[frm] = point.point.z;
- else
- m_fHeliDustZ[frm] = -101.0f;
-
- switch(point.surfaceB){
- default:
- case SURFACE_TARMAC:
- r = 10;
- g = 10;
- b = 10;
- break;
- case SURFACE_GRASS:
- r = 10;
- g = 6;
- b = 3;
- break;
- case SURFACE_DIRT:
- r = 10;
- g = 8;
- b = 7;
- break;
- case SURFACE_DIRTTRACK:
- r = 10;
- g = 6;
- b = 3;
- break;
- }
- RwRGBA col = { r, g, b, 32 };
- pos.z = m_fHeliDustZ[(i - (i&3))/4]; // advance every 4 iterations, why not just /4?
- if(pos.z > -200.0f && GetPosition().z - pos.z < 20.0f)
- CParticle::AddParticle(PARTICLE_HELI_DUST, pos, dir, nil, 0.0f, col);
- i++;
- }
-}
-
-void
-CHeli::Render(void)
-{
- CMatrix mat;
- CVector pos;
-
- mat.Attach(RwFrameGetMatrix(m_aHeliNodes[HELI_TOPROTOR]));
- pos = mat.GetPosition();
- mat.SetRotateZ(m_fRotorRotation);
- mat.Translate(pos);
- mat.UpdateRW();
-
- m_fRotorRotation += 3.14f/6.5f;
- if(m_fRotorRotation > 6.28f)
- m_fRotorRotation -= 6.28f;
-
- mat.Attach(RwFrameGetMatrix(m_aHeliNodes[HELI_BACKROTOR]));
- pos = mat.GetPosition();
- mat.SetRotateX(m_fRotorRotation);
- mat.Translate(pos);
- mat.UpdateRW();
-
- CEntity::Render();
-}
-
-void
-CHeli::PreRenderAlways(void)
-{
- CVector shadowPos(m_fSearchLightX, m_fSearchLightY, GetPosition().z);
- if(m_fSearchLightIntensity > 0.0f){
- CShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &shadowPos,
- 6.0f, 0.0f, 0.0f, -6.0f,
- 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity,
- 50.0f, true, 1.0f);
-
- CVector front = GetMatrix() * CVector(0.0f, 7.0f, 0.0f);
- CVector toPlayer = FindPlayerCoors() - front;
- toPlayer.Normalise();
- float intensity = m_fSearchLightIntensity*sq(CTimeCycle::GetSpriteBrightness());
- if(DotProduct(toPlayer, TheCamera.GetForward()) < -0.8f)
- CCoronas::RegisterCorona((uintptr)this, 255*intensity, 255*intensity, 255*intensity, 255,
- front, 10.0f, 60.0f, CCoronas::TYPE_STAR,
- CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- else
- CCoronas::RegisterCorona((uintptr)this, 200*intensity, 200*intensity, 200*intensity, 255,
- front, 8.0f, 60.0f, CCoronas::TYPE_STAR,
- CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- }
-
- CVector back = GetMatrix() * CVector(0.0f, -9.0f, 0.0f);
- if(CTimer::GetTimeInMilliseconds() & 0x100)
- CCoronas::RegisterCorona((uintptr)this + 2, 255, 0, 0, 255,
- back, 1.0f, 60.0f, CCoronas::TYPE_STAR,
- CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
- else
- CCoronas::RegisterCorona((uintptr)this + 2, 0, 0, 0, 255,
- back, 1.0f, 60.0f, CCoronas::TYPE_STAR,
- CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
-}
-
-RwObject*
-GetHeliAtomicObjectCB(RwObject *object, void *data)
-{
- RpAtomic *atomic = (RpAtomic*)object;
- assert(RwObjectGetType(object) == rpATOMIC);
- if(RpAtomicGetFlags(atomic) & rpATOMICRENDER)
- *(RpAtomic**)data = atomic;
- return object;
-}
-
-CObject*
-CHeli::SpawnFlyingComponent(int32 component)
-{
- RpAtomic *atomic;
- RwFrame *frame;
- RwMatrix *matrix;
- CObject *obj;
-
- if(m_aHeliNodes[component] == nil)
- return nil;
-
- atomic = nil;
- RwFrameForAllObjects(m_aHeliNodes[component], GetHeliAtomicObjectCB, &atomic);
- if(atomic == nil)
- return nil;
-
- obj = new CObject;
- if(obj == nil)
- return nil;
-
- obj->SetModelIndexNoCreate(MI_CAR_WHEEL);
- // object needs base model
- obj->RefModelInfo(GetModelIndex());
-
- // create new atomic
- matrix = RwFrameGetLTM(m_aHeliNodes[component]);
- frame = RwFrameCreate();
- atomic = RpAtomicClone(atomic);
- *RwFrameGetMatrix(frame) = *matrix;
- RpAtomicSetFrame(atomic, frame);
- CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
- obj->AttachToRwObject((RwObject*)atomic);
-
- // init object
- obj->m_fMass = 10.0f;
- obj->m_fTurnMass = 25.0f;
- obj->m_fAirResistance = 0.99f;
- obj->m_fElasticity = 0.1f;
- obj->m_fBuoyancy = obj->m_fMass*GRAVITY/0.75f;
- obj->ObjectCreatedBy = TEMP_OBJECT;
- obj->bIsStatic = false;
- obj->bIsPickup = false;
-
- // life time
- CObject::nNoTempObjects++;
- if(component == HELI_TOPROTOR)
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 1000;
- else
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 3000;
-
- obj->m_vecMoveSpeed = m_vecMoveSpeed;
- if(obj->m_vecMoveSpeed.z > 0.0f)
- obj->m_vecMoveSpeed.z = 0.3f;
- else
- obj->m_vecMoveSpeed.z = 0.0f;
-
- obj->m_vecTurnSpeed = m_vecTurnSpeed*2.0f;
-
- if(component == HELI_BACKROTOR)
- obj->m_vecTurnSpeed.x = 0.5f;
- else if(component == HELI_TOPROTOR || component == HELI_TOPKNOT)
- obj->m_vecTurnSpeed.z = 0.5f;
- else
- obj->m_vecTurnSpeed.y = 0.5f;
-
- obj->bRenderScorched = true;
-
- CWorld::Add(obj);
-
- atomic = nil;
- RwFrameForAllObjects(m_aHeliNodes[component], GetHeliAtomicObjectCB, &atomic);
- if(atomic)
- RpAtomicSetFlags(atomic, 0);
-
- return obj;
-}
-
-
-
-void
-CHeli::InitHelis(void)
-{
- int i;
-
- NumRandomHelis = 0;
- TestForNewRandomHelisTimer = 0;
- NumScriptHelis = 0;
- CatalinaHeliOn = false;
- ScriptHeliOn = false;
- for(i = 0; i < NUM_HELIS; i++)
- pHelis[i] = nil;
-
- ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_ESCAPE))->SetColModel(&CTempColModels::ms_colModelPed1);
- ((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1);
-}
-
-CHeli*
-GenerateHeli(bool catalina)
-{
- CHeli *heli;
- CVector heliPos;
- int i;
-
- if(catalina)
- heli = new CHeli(MI_ESCAPE, PERMANENT_VEHICLE);
- else
- heli = new CHeli(MI_CHOPPER, PERMANENT_VEHICLE);
-
- if(catalina)
- heliPos = CVector(-224.0f, 201.0f, 83.0f);
- else{
- heliPos = FindPlayerCoors();
- float angle = (float)(CGeneral::GetRandomNumber() & 0xFF)/0xFF * 6.28f;
- heliPos.x += 250.0f*Sin(angle);
- heliPos.y += 250.0f*Cos(angle);
- if(heliPos.x < -2000.0f || heliPos.x > 2000.0f || heliPos.y < -2000.0f || heliPos.y > 2000.0f){
- // directly above player
- heliPos.x -= 250.0f*Sin(angle);
- heliPos.y -= 250.0f*Cos(angle);
- }
- heliPos.z += 50.0f;
- }
- heli->GetMatrix().SetTranslate(heliPos);
- if(catalina)
- heli->GetMatrix().SetRotateZOnly(DEGTORAD(270.0f)); // game actually uses 3.14 here
-
- heli->m_status = STATUS_ABANDONED;
-
- int id = -1;
- bool found = false;
- while(!found){
- id++;
- found = true;
- for(i = 0; i < 4; i++)
- if(CHeli::pHelis[i] && CHeli::pHelis[i]->m_nHeliId == id)
- found = false;
- }
- heli->m_nHeliId = id;
-
- CWorld::Add(heli);
-
- return heli;
-}
-
-void
-CHeli::UpdateHelis(void)
-{
- int i, j;
-
- // Spawn new police helis
- int numHelisRequired = FindPlayerPed()->m_pWanted->NumOfHelisRequired();
- if(CStreaming::HasModelLoaded(MI_CHOPPER) && CTimer::GetTimeInMilliseconds() > TestForNewRandomHelisTimer){
- // Spawn a police heli
- TestForNewRandomHelisTimer = CTimer::GetTimeInMilliseconds() + 15000;
- if(NumRandomHelis < numHelisRequired){
- NumRandomHelis++;
- CHeli *heli = GenerateHeli(false);
- heli->m_heliType = HELI_TYPE_RANDOM;
- if(pHelis[HELI_RANDOM0] == nil)
- pHelis[HELI_RANDOM0] = heli;
- else if(pHelis[HELI_RANDOM1] == nil)
- pHelis[HELI_RANDOM1] = heli;
- else
- assert(0 && "too many helis");
- }
- }
-
- // Handle script heli
- if(ScriptHeliOn){
- if(CStreaming::HasModelLoaded(MI_CHOPPER) && pHelis[HELI_SCRIPT] == nil){
- pHelis[HELI_SCRIPT] = GenerateHeli(false);
- pHelis[HELI_SCRIPT]->m_heliType = HELI_TYPE_SCRIPT;
- }else
- CStreaming::RequestModel(MI_CHOPPER, 0);
- }else{
- if(pHelis[HELI_SCRIPT])
- pHelis[HELI_SCRIPT]->m_heliStatus = HELI_STATUS_FLY_AWAY;
- }
-
- // Handle Catalina's heli
- if(CatalinaHeliOn){
- if(CStreaming::HasModelLoaded(MI_ESCAPE) && pHelis[HELI_CATALINA] == nil){
- pHelis[HELI_CATALINA] = GenerateHeli(true);
- pHelis[HELI_CATALINA]->m_heliType = HELI_TYPE_CATALINA;
- }else
- CStreaming::RequestModel(MI_ESCAPE, STREAMFLAGS_DONT_REMOVE);
- }else{
- if(pHelis[HELI_CATALINA])
- pHelis[HELI_CATALINA]->m_heliStatus = HELI_STATUS_FLY_AWAY;
- }
-
- // Delete helis that we no longer need
- for(i = 0; i < NUM_HELIS; i++)
- if(pHelis[i] && pHelis[i]->m_heliStatus == HELI_STATUS_FLY_AWAY && pHelis[i]->GetPosition().z > 150.0f){
- CWorld::Remove(pHelis[i]);
- delete pHelis[i];
- pHelis[i] = nil;
- if(i != HELI_SCRIPT && i != HELI_CATALINA)
- NumRandomHelis--;
- }
-
- // Handle explosions
- for(i = 0; i < NUM_HELIS; i++){
- if(pHelis[i] && pHelis[i]->m_heliStatus == HELI_STATUS_SHOT_DOWN && CTimer::GetTimeInMilliseconds() > pHelis[i]->m_nExplosionTimer){
- // Second part of explosion
- static int nFrameGen;
- CRGBA colors[8];
-
- TheCamera.CamShake(0.7f, pHelis[i]->GetPosition().x, pHelis[i]->GetPosition().y, pHelis[i]->GetPosition().z);
-
- colors[0] = CRGBA(0, 0, 0, 255);
- colors[1] = CRGBA(224, 230, 238, 255);
- colors[2] = CRGBA(0, 0, 0, 255);
- colors[3] = CRGBA(0, 0, 0, 255);
- colors[4] = CRGBA(66, 162, 252, 255);
- colors[5] = CRGBA(0, 0, 0, 255);
- colors[6] = CRGBA(0, 0, 0, 255);
- colors[7] = CRGBA(0, 0, 0, 255);
-
- CVector pos = pHelis[i]->GetPosition();
- CVector dir;
- for(j = 0; j < 40; j++){
- dir.x = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f);
- dir.y = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f);
- dir.z = CGeneral::GetRandomNumberInRange(0.0f, 2.0f);
- int rotSpeed = CGeneral::GetRandomNumberInRange(10, 30);
- if(CGeneral::GetRandomNumber() & 1)
- rotSpeed = -rotSpeed;
- int f = ++nFrameGen & 3;
- CParticle::AddParticle(PARTICLE_HELI_DEBRIS, pos, dir,
- nil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f),
- colors[nFrameGen], rotSpeed, 0, f, 0);
- }
-
- CExplosion::AddExplosion(nil, nil, EXPLOSION_HELI, pos, 0);
-
- pHelis[i]->SpawnFlyingComponent(HELI_SKID_LEFT);
- pHelis[i]->SpawnFlyingComponent(HELI_SKID_RIGHT);
- pHelis[i]->SpawnFlyingComponent(HELI_TOPROTOR);
-
- CDarkel::RegisterCarBlownUpByPlayer(pHelis[i]);
- CWorld::Remove(pHelis[i]);
- delete pHelis[i];
- pHelis[i] = nil;
- if(i != HELI_SCRIPT && i != HELI_CATALINA)
- NumRandomHelis--;
- if(i == HELI_CATALINA)
- CatalinaHasBeenShotDown = true;
-
- CStats::HelisDestroyed++;
- CStats::PeopleKilledByOthers += 2;
- CStats::PedsKilledOfThisType[PEDTYPE_COP] += 2;
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 250;
- pos = CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetPosition();
- CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->RegisterCrime_Immediately(CRIME_SHOOT_HELI,
- pos, i + 19843, false);
-
- TestForNewRandomHelisTimer = CTimer::GetTimeInMilliseconds() + 50000;
- }else if(pHelis[i] && pHelis[i]->m_heliStatus == HELI_STATUS_SHOT_DOWN && CTimer::GetTimeInMilliseconds()+7000 > pHelis[i]->m_nExplosionTimer){
- // First part of explosion
- if(CTimer::GetPreviousTimeInMilliseconds()+7000 < pHelis[i]->m_nExplosionTimer){
- pHelis[i]->SpawnFlyingComponent(HELI_BACKROTOR);
- pHelis[i]->SpawnFlyingComponent(HELI_TAIL);
- pHelis[i]->m_fAngularSpeed *= -2.5f;
- pHelis[i]->bRenderScorched = true;
-
- TheCamera.CamShake(0.4f, pHelis[i]->GetPosition().x, pHelis[i]->GetPosition().y, pHelis[i]->GetPosition().z);
-
- CVector pos = pHelis[i]->GetPosition() - 2.5f*pHelis[i]->GetUp();
- CExplosion::AddExplosion(nil, nil, EXPLOSION_HELI, pos, 0);
- }else
- pHelis[i]->m_fAngularSpeed *= 1.03f;
- }
- }
-
- // Find police helis to remove
- for(i = 0; i < 2; i++)
- if(pHelis[i] && pHelis[i]->m_heliStatus != HELI_STATUS_FLY_AWAY){
- if(numHelisRequired > 0)
- numHelisRequired--;
- else
- pHelis[i]->m_heliStatus = HELI_STATUS_FLY_AWAY;
- }
-
- // Remove all helis if in a tunnel
- if(FindPlayerCoors().z < - 2.0f)
- for(i = 0; i < NUM_HELIS; i++)
- if(pHelis[i] && pHelis[i]->m_heliStatus != HELI_STATUS_SHOT_DOWN)
- pHelis[i]->m_heliStatus = HELI_STATUS_FLY_AWAY;
-}
-
-void
-CHeli::SpecialHeliPreRender(void)
-{
- int i;
- for(i = 0; i < NUM_HELIS; i++)
- if(pHelis[i])
- pHelis[i]->PreRenderAlways();
-}
-
-bool
-CHeli::TestRocketCollision(CVector *rocketPos)
-{
- int i;
- bool hit = false;
-
- for(i = 0; i < NUM_HELIS; i++){
- if(pHelis[i] && !pHelis[i]->bExplosionProof && (*rocketPos - pHelis[i]->GetPosition()).MagnitudeSqr() < sq(8.0f)){
- pHelis[i]->m_fAngularSpeed = (CGeneral::GetRandomNumber() < RAND_MAX/2) ? 0.05f : -0.05f;
- pHelis[i]->m_heliStatus = HELI_STATUS_SHOT_DOWN;
- pHelis[i]->m_nExplosionTimer = CTimer::GetTimeInMilliseconds() + 10000;
- hit = true;
- }
- }
- return hit;
-}
-
-bool
-CHeli::TestBulletCollision(CVector *line0, CVector *line1, CVector *bulletPos, int32 damage)
-{
- int i;
- bool hit = false;
-
- for(i = 0; i < NUM_HELIS; i++)
- if(pHelis[i] && !pHelis[i]->bBulletProof && CCollision::DistToLine(line0, line1, &pHelis[i]->GetPosition()) < 5.0f){
- // Find bullet position
- float distToHeli = (pHelis[i]->GetPosition() - *line0).Magnitude();
- CVector line = (*line1 - *line0);
- float lineLength = line.Magnitude();
- *bulletPos = *line0 + line*max(1.0f, distToHeli-5.0f);
-
- pHelis[i]->m_nBulletDamage += damage;
-
- if(pHelis[i]->m_heliType == HELI_CATALINA && pHelis[i]->m_nBulletDamage > 400 ||
- pHelis[i]->m_heliType != HELI_CATALINA && pHelis[i]->m_nBulletDamage > 700){
- pHelis[i]->m_fAngularSpeed = (CGeneral::GetRandomNumber() < RAND_MAX/2) ? 0.05f : -0.05f;
- pHelis[i]->m_heliStatus = HELI_STATUS_SHOT_DOWN;
- pHelis[i]->m_nExplosionTimer = CTimer::GetTimeInMilliseconds() + 10000;
- }
-
- hit = true;
- }
- return hit;
-}
-
-void CHeli::StartCatalinaFlyBy(void)
-{
- CatalinaHeliOn = true;
- CatalinaHasBeenShotDown = false;
-}
-
-void
-CHeli::RemoveCatalinaHeli(void)
-{
- CatalinaHeliOn = false;
- if(pHelis[HELI_CATALINA]){
- CWorld::Remove(pHelis[HELI_CATALINA]);
- delete pHelis[HELI_CATALINA];
- pHelis[HELI_CATALINA] = nil;
- }
-}
-
-CHeli *CHeli::FindPointerToCatalinasHeli(void) { return pHelis[HELI_CATALINA]; }
-void CHeli::CatalinaTakeOff(void) { pHelis[HELI_CATALINA]->m_pathState = 8; }
-void CHeli::MakeCatalinaHeliFlyAway(void) { pHelis[HELI_CATALINA]->m_pathState = 12; }
-bool CHeli::HasCatalinaBeenShotDown(void) { return CatalinaHasBeenShotDown; }
-
-void CHeli::ActivateHeli(bool activate) { ScriptHeliOn = activate; }
-
-
-class CHeli_ : public CHeli
-{
-public:
- void ctor(int32 id, uint8 CreatedBy) { ::new (this) CHeli(id, CreatedBy); }
- void dtor(void) { CHeli::~CHeli(); }
-};
-
-STARTPATCHES
- InjectHook(0x547220, &CHeli_::ctor, PATCH_JUMP);
- InjectHook(0x5474A0, &CHeli_::dtor, PATCH_JUMP);
- InjectHook(0x54AE50, &CHeli::SpawnFlyingComponent, PATCH_JUMP);
- InjectHook(0x549970, CHeli::InitHelis, PATCH_JUMP);
- InjectHook(0x5499F0, CHeli::UpdateHelis, PATCH_JUMP);
- InjectHook(0x54AE10, CHeli::SpecialHeliPreRender, PATCH_JUMP);
- InjectHook(0x54AA30, CHeli::TestRocketCollision, PATCH_JUMP);
- InjectHook(0x54AB30, CHeli::TestBulletCollision, PATCH_JUMP);
- InjectHook(0x54A640, GenerateHeli, PATCH_JUMP);
-ENDPATCHES
diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp
index 771f36e1..775cf572 100644
--- a/src/vehicles/Plane.cpp
+++ b/src/vehicles/Plane.cpp
@@ -968,16 +968,8 @@ bool CPlane::HasDropOffCesnaBeenShotDown(void) { return DropOffCesnaMissionStatu
class CPlane_ : public CPlane
{
public:
-<<<<<<< HEAD
-<<<<<<< HEAD
void ctor(int32 id, uint8 CreatedBy) { ::new (this) CPlane(id, CreatedBy); }
void dtor(void) { CPlane::~CPlane(); }
-=======
- void dtor(void) { this->~CPlane(); }
->>>>>>> More audio ped
-=======
- void dtor(void) { CPlane::~CPlane(); }
->>>>>>> fix
};
STARTPATCHES
diff --git a/src/vehicles/Plane.cpp.autosave b/src/vehicles/Plane.cpp.autosave
deleted file mode 100644
index 775cf572..00000000
--- a/src/vehicles/Plane.cpp.autosave
+++ /dev/null
@@ -1,985 +0,0 @@
-#include "common.h"
-#include "main.h"
-#include "patcher.h"
-#include "General.h"
-#include "ModelIndices.h"
-#include "FileMgr.h"
-#include "Streaming.h"
-#include "Replay.h"
-#include "Camera.h"
-#include "Coronas.h"
-#include "Particle.h"
-#include "Explosion.h"
-#include "World.h"
-#include "HandlingMgr.h"
-#include "Plane.h"
-
-CPlaneNode *&pPathNodes = *(CPlaneNode**)0x8F1B68;
-CPlaneNode *&pPath2Nodes = *(CPlaneNode**)0x885B8C;
-CPlaneNode *&pPath3Nodes = *(CPlaneNode**)0x885B78;
-CPlaneNode *&pPath4Nodes = *(CPlaneNode**)0x885AD8;
-int32 &NumPathNodes = *(int32*)0x8F2BE4;
-int32 &NumPath2Nodes = *(int32*)0x941498;
-int32 &NumPath3Nodes = *(int32*)0x9414D8;
-int32 &NumPath4Nodes = *(int32*)0x9412C8;
-float &TotalLengthOfFlightPath = *(float*)0x8F2C6C;
-float &TotalLengthOfFlightPath2 = *(float*)0x64CFBC;
-float &TotalLengthOfFlightPath3 = *(float*)0x64CFD0;
-float &TotalLengthOfFlightPath4 = *(float*)0x64CFDC;
-float &TotalDurationOfFlightPath = *(float*)0x64CFB8;
-float &TotalDurationOfFlightPath2 = *(float*)0x64CFC0;
-float &TotalDurationOfFlightPath3 = *(float*)0x64CFD4;
-float &TotalDurationOfFlightPath4 = *(float*)0x64CFE0;
-float &LandingPoint = *(float*)0x8F2C7C;
-float &TakeOffPoint = *(float*)0x8E28A4;
-CPlaneInterpolationLine *aPlaneLineBits = (CPlaneInterpolationLine*)0x734168; //[6]
-
-float *PlanePathPosition = (float*)0x8F5FC8; //[3]
-float *OldPlanePathPosition = (float*)0x8F5FBC; //[3]
-float *PlanePathSpeed = (float*)0x941538; //[3]
-float *PlanePath2Position = (float*)0x64CFC4; //[3]
-float &PlanePath3Position = *(float*)0x64CFD8;
-float &PlanePath4Position = *(float*)0x64CFE4;
-float *PlanePath2Speed = (float*)0x8F1A54; //[3]
-float &PlanePath3Speed = *(float*)0x8F1A94;
-float &PlanePath4Speed = *(float*)0x8F1AFC;
-
-
-enum
-{
- CESNA_STATUS_NONE, // doesn't even exist
- CESNA_STATUS_FLYING,
- CESNA_STATUS_DESTROYED,
- CESNA_STATUS_LANDED,
-};
-
-int32 &CesnaMissionStatus = *(int32*)0x64CFE8;
-int32 &CesnaMissionStartTime = *(int32*)0x64CFEC;
-CPlane *&pDrugRunCesna = *(CPlane**)0x8F5F80;
-int32 &DropOffCesnaMissionStatus = *(int32*)0x64CFF0;
-int32 &DropOffCesnaMissionStartTime = *(int32*)0x64CFF4;
-CPlane *&pDropOffCesna = *(CPlane**)0x8E2A38;
-
-
-CPlane::CPlane(int32 id, uint8 CreatedBy)
- : CVehicle(CreatedBy)
-{
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);
- m_vehType = VEHICLE_TYPE_PLANE;
- pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId);
- SetModelIndex(id);
-
- m_fMass = 100000000.0f;
- m_fTurnMass = 100000000.0f;
- m_fAirResistance = 0.9994f;
- m_fElasticity = 0.05f;
-
- bUsesCollision = false;
- m_bHasBeenHit = false;
- m_bIsDrugRunCesna = false;
- m_bIsDropOffCesna = false;
-
- m_status = STATUS_PLANE;
- bIsBIGBuilding = true;
- m_level = LEVEL_NONE;
-}
-
-CPlane::~CPlane()
-{
- DeleteRwObject();
-}
-
-void
-CPlane::SetModelIndex(uint32 id)
-{
- CVehicle::SetModelIndex(id);
-}
-
-void
-CPlane::DeleteRwObject(void)
-{
- if(m_rwObject && RwObjectGetType(m_rwObject) == rpATOMIC){
- m_matrix.Detach();
- if(RwObjectGetType(m_rwObject) == rpATOMIC){ // useless check
- RwFrame *f = RpAtomicGetFrame((RpAtomic*)m_rwObject);
- RpAtomicDestroy((RpAtomic*)m_rwObject);
- RwFrameDestroy(f);
- }
- m_rwObject = nil;
- }
- CEntity::DeleteRwObject();
-}
-
-// There's a LOT of copy and paste in here. Maybe this could be refactored somehow
-void
-CPlane::ProcessControl(void)
-{
- int i;
- CVector pos;
-
- // Explosion
- if(m_bHasBeenHit){
- // BUG: since this is all based on frames, you can skip the explosion processing when you go into the menu
- if(GetModelIndex() == MI_AIRTRAIN){
- int frm = CTimer::GetFrameCounter() - m_nFrameWhenHit;
- if(frm == 20){
- static int nFrameGen;
- CRGBA colors[8];
-
- CExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_HELI, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), 0);
-
- colors[0] = CRGBA(0, 0, 0, 255);
- colors[1] = CRGBA(224, 230, 238, 255);
- colors[2] = CRGBA(224, 230, 238, 255);
- colors[3] = CRGBA(0, 0, 0, 255);
- colors[4] = CRGBA(224, 230, 238, 255);
- colors[5] = CRGBA(0, 0, 0, 255);
- colors[6] = CRGBA(0, 0, 0, 255);
- colors[7] = CRGBA(224, 230, 238, 255);
-
- CVector dir;
- for(i = 0; i < 40; i++){
- dir.x = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f);
- dir.y = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f);
- dir.z = CGeneral::GetRandomNumberInRange(0.0f, 2.0f);
- int rotSpeed = CGeneral::GetRandomNumberInRange(10, 30);
- if(CGeneral::GetRandomNumber() & 1)
- rotSpeed = -rotSpeed;
- int f = ++nFrameGen & 3;
- CParticle::AddParticle(PARTICLE_HELI_DEBRIS, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), dir,
- nil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f),
- colors[nFrameGen], rotSpeed, 0, f, 0);
- }
- }
- if(frm >= 40 && frm <= 80 && frm & 1){
- if(frm & 1){
- pos.x = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.2f;
- pos.z = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.2f;
- pos.y = frm - 40;
- pos = GetMatrix() * pos;
- }else{
- pos.x = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.2f;
- pos.z = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.2f;
- pos.y = 40 - frm;
- pos = GetMatrix() * pos;
- }
- CExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_HELI, pos, 0);
- }
- if(frm == 60)
- bRenderScorched = true;
- if(frm == 82){
- TheCamera.SetFadeColour(255, 255, 255);
- TheCamera.Fade(0.0f, FADE_OUT);
- TheCamera.ProcessFade();
- TheCamera.Fade(1.0f, FADE_IN);
- FlagToDestroyWhenNextProcessed();
- }
- }else{
- int frm = CTimer::GetFrameCounter() - m_nFrameWhenHit;
- if(frm == 20){
- static int nFrameGen;
- CRGBA colors[8];
-
- CExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_HELI, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), 0);
-
- colors[0] = CRGBA(0, 0, 0, 255);
- colors[1] = CRGBA(224, 230, 238, 255);
- colors[2] = CRGBA(224, 230, 238, 255);
- colors[3] = CRGBA(0, 0, 0, 255);
- colors[4] = CRGBA(252, 66, 66, 255);
- colors[5] = CRGBA(0, 0, 0, 255);
- colors[6] = CRGBA(0, 0, 0, 255);
- colors[7] = CRGBA(252, 66, 66, 255);
-
- for(i = 0; i < 40; i++){
- int rotSpeed = CGeneral::GetRandomNumberInRange(30.0f, 20.0f);
- if(CGeneral::GetRandomNumber() & 1)
- rotSpeed = -rotSpeed;
- int f = ++nFrameGen & 3;
- CParticle::AddParticle(PARTICLE_HELI_DEBRIS, GetMatrix() * CVector(0.0f, 0.0f, 0.0f),
- CVector(CGeneral::GetRandomNumberInRange(-2.0f, 2.0f),
- CGeneral::GetRandomNumberInRange(-2.0f, 2.0f),
- CGeneral::GetRandomNumberInRange(0.0f, 2.0f)),
- nil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f),
- colors[nFrameGen], rotSpeed, 0, f, 0);
- }
- }
- if(frm >= 40 && frm <= 60 && frm & 1){
- if(frm & 1){
- pos.x = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.1f;
- pos.z = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.1f;
- pos.y = (frm - 40)*0.3f;
- pos = GetMatrix() * pos;
- }else{
- pos.x = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.1f;
- pos.z = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.1f;
- pos.y = (40 - frm)*0.3f;
- pos = GetMatrix() * pos;
- }
- CExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_HELI, pos, 0);
- }
- if(frm == 30)
- bRenderScorched = true;
- if(frm == 61){
- TheCamera.SetFadeColour(200, 200, 200);
- TheCamera.Fade(0.0f, FADE_OUT);
- TheCamera.ProcessFade();
- TheCamera.Fade(1.0f, FADE_IN);
- if(m_bIsDrugRunCesna){
- CesnaMissionStatus = CESNA_STATUS_DESTROYED;
- pDrugRunCesna = nil;
- }
- if(m_bIsDropOffCesna){
- DropOffCesnaMissionStatus = CESNA_STATUS_DESTROYED;
- pDropOffCesna = nil;
- }
- FlagToDestroyWhenNextProcessed();
- }
- }
- }
-
- // Update plane position and speed
- if(GetModelIndex() == MI_AIRTRAIN || !m_isFarAway || ((CTimer::GetFrameCounter() + m_randomSeed) & 7) == 0){
- if(GetModelIndex() == MI_AIRTRAIN){
- float pathPositionRear = PlanePathPosition[m_nPlaneId] - 30.0f;
- if(pathPositionRear < 0.0f)
- pathPositionRear += TotalLengthOfFlightPath;
- float pathPosition = pathPositionRear + 30.0f;
-
- float pitch = 0.0f;
- float distSinceTakeOff = pathPosition - TakeOffPoint;
- if(distSinceTakeOff <= 0.0f && distSinceTakeOff > -70.0f){
- // shortly before take off
- pitch = 1.0f - distSinceTakeOff/-70.0f;
- }else if(distSinceTakeOff >= 0.0f && distSinceTakeOff < 100.0f){
- // shortly after take off
- pitch = 1.0f - distSinceTakeOff/100.0f;
- }
-
- float distSinceLanding = pathPosition - LandingPoint;
- if(distSinceLanding <= 0.0f && distSinceLanding > -200.0f){
- // shortly before landing
- pitch = 1.0f - distSinceLanding/-200.0f;
- }else if(distSinceLanding >= 0.0f && distSinceLanding < 70.0f){
- // shortly after landing
- pitch = 1.0f - distSinceLanding/70.0f;
- }
-
-
- // Advance current node to appropriate position
- float pos1, pos2;
- int nextTrackNode = m_nCurPathNode + 1;
- pos1 = pPathNodes[m_nCurPathNode].t;
- if(nextTrackNode < NumPathNodes)
- pos2 = pPathNodes[nextTrackNode].t;
- else{
- nextTrackNode = 0;
- pos2 = TotalLengthOfFlightPath;
- }
- while(pathPositionRear < pos1 || pathPositionRear > pos2){
- m_nCurPathNode = (m_nCurPathNode+1) % NumPathNodes;
- nextTrackNode = m_nCurPathNode + 1;
- pos1 = pPathNodes[m_nCurPathNode].t;
- if(nextTrackNode < NumPathNodes)
- pos2 = pPathNodes[nextTrackNode].t;
- else{
- nextTrackNode = 0;
- pos2 = TotalLengthOfFlightPath;
- }
- }
- bool bothOnGround = pPathNodes[m_nCurPathNode].bOnGround && pPathNodes[nextTrackNode].bOnGround;
- if(PlanePathPosition[m_nPlaneId] >= LandingPoint && OldPlanePathPosition[m_nPlaneId] < LandingPoint)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_PLANE_ON_GROUND, 0.0f);
- float dist = pPathNodes[nextTrackNode].t - pPathNodes[m_nCurPathNode].t;
- if(dist < 0.0f)
- dist += TotalLengthOfFlightPath;
- float f = (pathPositionRear - pPathNodes[m_nCurPathNode].t)/dist;
- CVector posRear = (1.0f - f)*pPathNodes[m_nCurPathNode].p + f*pPathNodes[nextTrackNode].p;
-
- // Same for the front
- float pathPositionFront = pathPositionRear + 60.0f;
- if(pathPositionFront > TotalLengthOfFlightPath)
- pathPositionFront -= TotalLengthOfFlightPath;
- int curPathNodeFront = m_nCurPathNode;
- int nextPathNodeFront = curPathNodeFront + 1;
- pos1 = pPathNodes[curPathNodeFront].t;
- if(nextPathNodeFront < NumPathNodes)
- pos2 = pPathNodes[nextPathNodeFront].t;
- else{
- nextPathNodeFront = 0;
- pos2 = TotalLengthOfFlightPath;
- }
- while(pathPositionFront < pos1 || pathPositionFront > pos2){
- curPathNodeFront = (curPathNodeFront+1) % NumPathNodes;
- nextPathNodeFront = curPathNodeFront + 1;
- pos1 = pPathNodes[curPathNodeFront].t;
- if(nextPathNodeFront < NumPathNodes)
- pos2 = pPathNodes[nextPathNodeFront].t;
- else{
- nextPathNodeFront = 0;
- pos2 = TotalLengthOfFlightPath;
- }
- }
- dist = pPathNodes[nextPathNodeFront].t - pPathNodes[curPathNodeFront].t;
- if(dist < 0.0f)
- dist += TotalLengthOfFlightPath;
- f = (pathPositionFront - pPathNodes[curPathNodeFront].t)/dist;
- CVector posFront = (1.0f - f)*pPathNodes[curPathNodeFront].p + f*pPathNodes[nextPathNodeFront].p;
-
- // And for another point 60 units in front of the plane, used to calculate roll
- float pathPositionFront2 = pathPositionFront + 60.0f;
- if(pathPositionFront2 > TotalLengthOfFlightPath)
- pathPositionFront2 -= TotalLengthOfFlightPath;
- int curPathNodeFront2 = m_nCurPathNode;
- int nextPathNodeFront2 = curPathNodeFront2 + 1;
- pos1 = pPathNodes[curPathNodeFront2].t;
- if(nextPathNodeFront2 < NumPathNodes)
- pos2 = pPathNodes[nextPathNodeFront2].t;
- else{
- nextPathNodeFront2 = 0;
- pos2 = TotalLengthOfFlightPath;
- }
- while(pathPositionFront2 < pos1 || pathPositionFront2 > pos2){
- curPathNodeFront2 = (curPathNodeFront2+1) % NumPathNodes;
- nextPathNodeFront2 = curPathNodeFront2 + 1;
- pos1 = pPathNodes[curPathNodeFront2].t;
- if(nextPathNodeFront2 < NumPathNodes)
- pos2 = pPathNodes[nextPathNodeFront2].t;
- else{
- nextPathNodeFront2 = 0;
- pos2 = TotalLengthOfFlightPath;
- }
- }
- dist = pPathNodes[nextPathNodeFront2].t - pPathNodes[curPathNodeFront2].t;
- if(dist < 0.0f)
- dist += TotalLengthOfFlightPath;
- f = (pathPositionFront2 - pPathNodes[curPathNodeFront2].t)/dist;
- CVector posFront2 = (1.0f - f)*pPathNodes[curPathNodeFront2].p + f*pPathNodes[nextPathNodeFront2].p;
-
- // Now set matrix
- GetPosition() = (posRear + posFront)/2.0f;
- GetPosition().z += 4.3f;
- CVector fwd = posFront - posRear;
- fwd.Normalise();
- if(pitch != 0.0f){
- fwd.z += 0.4f*pitch;
- fwd.Normalise();
- }
- CVector fwd2 = posFront2 - posRear;
- fwd2.Normalise();
- CVector roll = CrossProduct(fwd, fwd2);
- CVector right = CrossProduct(fwd, CVector(0.0f, 0.0f, 1.0f));
- if(!bothOnGround)
- right.z += 3.0f*roll.z;
- right.Normalise();
- CVector up = CrossProduct(right, fwd);
- GetRight() = right;
- GetUp() = up;
- GetForward() = fwd;
-
- // Set speed
- m_vecMoveSpeed = fwd*PlanePathSpeed[m_nPlaneId]/60.0f;
- m_fSpeed = PlanePathSpeed[m_nPlaneId]/60.0f;
- m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
-
- m_isFarAway = !((posFront - TheCamera.GetPosition()).Magnitude2D() < sq(300.0f));
- }else{
- float planePathPosition;
- float totalLengthOfFlightPath;
- CPlaneNode *pathNodes;
- float planePathSpeed;
- int numPathNodes;
-
- if(m_bIsDrugRunCesna){
- planePathPosition = PlanePath3Position;
- totalLengthOfFlightPath = TotalLengthOfFlightPath3;
- pathNodes = pPath3Nodes;
- planePathSpeed = PlanePath3Speed;
- numPathNodes = NumPath3Nodes;
- if(CesnaMissionStatus == CESNA_STATUS_LANDED){
- pDrugRunCesna = false;
- FlagToDestroyWhenNextProcessed();
- }
- }else if(m_bIsDropOffCesna){
- planePathPosition = PlanePath4Position;
- totalLengthOfFlightPath = TotalLengthOfFlightPath4;
- pathNodes = pPath4Nodes;
- planePathSpeed = PlanePath4Speed;
- numPathNodes = NumPath4Nodes;
- if(DropOffCesnaMissionStatus == CESNA_STATUS_LANDED){
- pDropOffCesna = false;
- FlagToDestroyWhenNextProcessed();
- }
- }else{
- planePathPosition = PlanePath2Position[m_nPlaneId];
- totalLengthOfFlightPath = TotalLengthOfFlightPath2;
- pathNodes = pPath2Nodes;
- planePathSpeed = PlanePath2Speed[m_nPlaneId];
- numPathNodes = NumPath2Nodes;
- }
-
- // Advance current node to appropriate position
- float pathPositionRear = planePathPosition - 10.0f;
- if(pathPositionRear < 0.0f)
- pathPositionRear += totalLengthOfFlightPath;
- float pos1, pos2;
- int nextTrackNode = m_nCurPathNode + 1;
- pos1 = pathNodes[m_nCurPathNode].t;
- if(nextTrackNode < numPathNodes)
- pos2 = pathNodes[nextTrackNode].t;
- else{
- nextTrackNode = 0;
- pos2 = totalLengthOfFlightPath;
- }
- while(pathPositionRear < pos1 || pathPositionRear > pos2){
- m_nCurPathNode = (m_nCurPathNode+1) % numPathNodes;
- nextTrackNode = m_nCurPathNode + 1;
- pos1 = pathNodes[m_nCurPathNode].t;
- if(nextTrackNode < numPathNodes)
- pos2 = pathNodes[nextTrackNode].t;
- else{
- nextTrackNode = 0;
- pos2 = totalLengthOfFlightPath;
- }
- }
- float dist = pathNodes[nextTrackNode].t - pathNodes[m_nCurPathNode].t;
- if(dist < 0.0f)
- dist += totalLengthOfFlightPath;
- float f = (pathPositionRear - pathNodes[m_nCurPathNode].t)/dist;
- CVector posRear = (1.0f - f)*pathNodes[m_nCurPathNode].p + f*pathNodes[nextTrackNode].p;
-
- // Same for the front
- float pathPositionFront = pathPositionRear + 20.0f;
- if(pathPositionFront > totalLengthOfFlightPath)
- pathPositionFront -= totalLengthOfFlightPath;
- int curPathNodeFront = m_nCurPathNode;
- int nextPathNodeFront = curPathNodeFront + 1;
- pos1 = pathNodes[curPathNodeFront].t;
- if(nextPathNodeFront < numPathNodes)
- pos2 = pathNodes[nextPathNodeFront].t;
- else{
- nextPathNodeFront = 0;
- pos2 = totalLengthOfFlightPath;
- }
- while(pathPositionFront < pos1 || pathPositionFront > pos2){
- curPathNodeFront = (curPathNodeFront+1) % numPathNodes;
- nextPathNodeFront = curPathNodeFront + 1;
- pos1 = pathNodes[curPathNodeFront].t;
- if(nextPathNodeFront < numPathNodes)
- pos2 = pathNodes[nextPathNodeFront].t;
- else{
- nextPathNodeFront = 0;
- pos2 = totalLengthOfFlightPath;
- }
- }
- dist = pathNodes[nextPathNodeFront].t - pathNodes[curPathNodeFront].t;
- if(dist < 0.0f)
- dist += totalLengthOfFlightPath;
- f = (pathPositionFront - pathNodes[curPathNodeFront].t)/dist;
- CVector posFront = (1.0f - f)*pathNodes[curPathNodeFront].p + f*pathNodes[nextPathNodeFront].p;
-
- // And for another point 60 units in front of the plane, used to calculate roll
- float pathPositionFront2 = pathPositionFront + 30.0f;
- if(pathPositionFront2 > totalLengthOfFlightPath)
- pathPositionFront2 -= totalLengthOfFlightPath;
- int curPathNodeFront2 = m_nCurPathNode;
- int nextPathNodeFront2 = curPathNodeFront2 + 1;
- pos1 = pathNodes[curPathNodeFront2].t;
- if(nextPathNodeFront2 < numPathNodes)
- pos2 = pathNodes[nextPathNodeFront2].t;
- else{
- nextPathNodeFront2 = 0;
- pos2 = totalLengthOfFlightPath;
- }
- while(pathPositionFront2 < pos1 || pathPositionFront2 > pos2){
- curPathNodeFront2 = (curPathNodeFront2+1) % numPathNodes;
- nextPathNodeFront2 = curPathNodeFront2 + 1;
- pos1 = pathNodes[curPathNodeFront2].t;
- if(nextPathNodeFront2 < numPathNodes)
- pos2 = pathNodes[nextPathNodeFront2].t;
- else{
- nextPathNodeFront2 = 0;
- pos2 = totalLengthOfFlightPath;
- }
- }
- dist = pathNodes[nextPathNodeFront2].t - pathNodes[curPathNodeFront2].t;
- if(dist < 0.0f)
- dist += totalLengthOfFlightPath;
- f = (pathPositionFront2 - pathNodes[curPathNodeFront2].t)/dist;
- CVector posFront2 = (1.0f - f)*pathNodes[curPathNodeFront2].p + f*pathNodes[nextPathNodeFront2].p;
-
- // Now set matrix
- GetPosition() = (posRear + posFront)/2.0f;
- GetPosition().z += 1.0f;
- CVector fwd = posFront - posRear;
- fwd.Normalise();
- CVector fwd2 = posFront2 - posRear;
- fwd2.Normalise();
- CVector roll = CrossProduct(fwd, fwd2);
- CVector right = CrossProduct(fwd, CVector(0.0f, 0.0f, 1.0f));
- right.z += 3.0f*roll.z;
- right.Normalise();
- CVector up = CrossProduct(right, fwd);
- GetRight() = right;
- GetUp() = up;
- GetForward() = fwd;
-
- // Set speed
- m_vecMoveSpeed = fwd*planePathSpeed/60.0f;
- m_fSpeed = planePathSpeed/60.0f;
- m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
-
- m_isFarAway = !((posFront - TheCamera.GetPosition()).Magnitude2D() < sq(300.0f));
- }
- }
-
- bIsInSafePosition = true;
- GetMatrix().UpdateRW();
- UpdateRwFrame();
-
- // Handle streaming and such
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
- if(m_isFarAway){
- // Switch to LOD model
- if(m_rwObject && RwObjectGetType(m_rwObject) == rpCLUMP){
- DeleteRwObject();
- if(mi->m_planeLodId != -1){
- m_rwObject = CModelInfo::GetModelInfo(mi->m_planeLodId)->CreateInstance();
- if(m_rwObject)
- m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)));
- }
- }
- }else if(CStreaming::HasModelLoaded(GetModelIndex())){
- if(m_rwObject && RwObjectGetType(m_rwObject) == rpATOMIC){
- // Get rid of LOD model
- m_matrix.Detach();
- if(m_rwObject){ // useless check
- if(RwObjectGetType(m_rwObject) == rpATOMIC){ // useless check
- RwFrame *f = RpAtomicGetFrame((RpAtomic*)m_rwObject);
- RpAtomicDestroy((RpAtomic*)m_rwObject);
- RwFrameDestroy(f);
- }
- m_rwObject = nil;
- }
- }
- // Set high detail model
- if(m_rwObject == nil){
- int id = GetModelIndex();
- m_modelIndex = -1;
- SetModelIndex(id);
- }
- }else{
- CStreaming::RequestModel(GetModelIndex(), STREAMFLAGS_DEPENDENCY);
- }
-}
-
-void
-CPlane::PreRender(void)
-{
- CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
-
- CVector lookVector = GetPosition() - TheCamera.GetPosition();
- float camDist = lookVector.Magnitude();
- if(camDist != 0.0f)
- lookVector *= 1.0f/camDist;
- else
- lookVector = CVector(1.0f, 0.0f, 0.0f);
- float behindness = DotProduct(lookVector, GetForward());
-
- // Wing lights
- if(behindness < 0.0f){
- // in front of plane
- CVector lightPos = mi->m_positions[PLANE_POS_LIGHT_RIGHT];
- CVector lightR = GetMatrix() * lightPos;
- CVector lightL = lightR;
- lightL -= GetRight()*2.0f*lightPos.x;
-
- float intensity = -0.6f*behindness + 0.4f;
- float size = 1.0f - behindness;
-
- if(behindness < -0.9f && camDist < 50.0f){
- // directly in front
- CCoronas::RegisterCorona((uintptr)this + 10, 255*intensity, 255*intensity, 255*intensity, 255,
- lightL, size, 240.0f,
- CCoronas::TYPE_NORMAL, CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
- CCoronas::RegisterCorona((uintptr)this + 11, 255*intensity, 255*intensity, 255*intensity, 255,
- lightR, size, 240.0f,
- CCoronas::TYPE_NORMAL, CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
- }else{
- CCoronas::RegisterCorona((uintptr)this + 10, 255*intensity, 255*intensity, 255*intensity, 255,
- lightL, size, 240.0f,
- CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
- CCoronas::RegisterCorona((uintptr)this + 11, 255*intensity, 255*intensity, 255*intensity, 255,
- lightR, size, 240.0f,
- CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
- }
- }
-
- // Tail light
- if(CTimer::GetTimeInMilliseconds() & 0x200){
- CVector pos = GetMatrix() * mi->m_positions[PLANE_POS_LIGHT_TAIL];
-
- CCoronas::RegisterCorona((uintptr)this + 12, 255, 0, 0, 255,
- pos, 1.0f, 120.0f,
- CCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
- CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);
- }
-}
-
-void
-CPlane::Render(void)
-{
- CEntity::Render();
-}
-
-#define CRUISE_SPEED (50.0f)
-#define TAXI_SPEED (5.0f)
-
-void
-CPlane::InitPlanes(void)
-{
- int i;
-
- CesnaMissionStatus = CESNA_STATUS_NONE;
-
- // Jumbo
- if(pPathNodes == nil){
- pPathNodes = LoadPath("data\\paths\\flight.dat", NumPathNodes, TotalLengthOfFlightPath, true);
-
- // Figure out which nodes are on ground
- CColPoint colpoint;
- CEntity *entity;
- for(i = 0; i < NumPathNodes; i++){
- if(CWorld::ProcessVerticalLine(pPathNodes[i].p, 1000.0f, colpoint, entity, true, false, false, false, true, false, nil)){
- pPathNodes[i].p.z = colpoint.point.z;
- pPathNodes[i].bOnGround = true;
- }else
- pPathNodes[i].bOnGround = false;
- }
-
- // Find lading and takeoff points
- LandingPoint = -1.0f;
- TakeOffPoint = -1.0f;
- bool lastOnGround = pPathNodes[NumPathNodes-1].bOnGround;
- for(i = 0; i < NumPathNodes; i++){
- if(pPathNodes[i].bOnGround && !lastOnGround)
- LandingPoint = pPathNodes[i].t;
- else if(!pPathNodes[i].bOnGround && lastOnGround)
- TakeOffPoint = pPathNodes[i].t;
- lastOnGround = pPathNodes[i].bOnGround;
- }
-
- // Animation
- float time = 0.0f;
- float position = 0.0f;
- // Start on ground with slow speed
- aPlaneLineBits[0].type = 1;
- aPlaneLineBits[0].time = time;
- aPlaneLineBits[0].position = position;
- aPlaneLineBits[0].speed = TAXI_SPEED;
- aPlaneLineBits[0].acceleration = 0.0f;
- float dist = (TakeOffPoint-600.0f) - position;
- time += dist/TAXI_SPEED;
- position += dist;
-
- // Accelerate to take off
- aPlaneLineBits[1].type = 2;
- aPlaneLineBits[1].time = time;
- aPlaneLineBits[1].position = position;
- aPlaneLineBits[1].speed = TAXI_SPEED;
- aPlaneLineBits[1].acceleration = 33.0f/32.0f;
- time += 600.0f/((CRUISE_SPEED+TAXI_SPEED)/2.0f);
- position += 600.0f;
-
- // Fly at cruise speed
- aPlaneLineBits[2].type = 1;
- aPlaneLineBits[2].time = time;
- aPlaneLineBits[2].position = position;
- aPlaneLineBits[2].speed = CRUISE_SPEED;
- aPlaneLineBits[2].acceleration = 0.0f;
- dist = LandingPoint - TakeOffPoint;
- time += dist/CRUISE_SPEED;
- position += dist;
-
- // Brake after landing
- aPlaneLineBits[3].type = 2;
- aPlaneLineBits[3].time = time;
- aPlaneLineBits[3].position = position;
- aPlaneLineBits[3].speed = CRUISE_SPEED;
- aPlaneLineBits[3].acceleration = -33.0f/32.0f;
- time += 600.0f/((CRUISE_SPEED+TAXI_SPEED)/2.0f);
- position += 600.0f;
-
- // Taxi
- aPlaneLineBits[4].type = 1;
- aPlaneLineBits[4].time = time;
- aPlaneLineBits[4].position = position;
- aPlaneLineBits[4].speed = TAXI_SPEED;
- aPlaneLineBits[4].acceleration = 0.0f;
- time += (TotalLengthOfFlightPath - position)/TAXI_SPEED;
-
- // end
- aPlaneLineBits[5].time = time;
- TotalDurationOfFlightPath = time;
- }
-
- // Dodo
- if(pPath2Nodes == nil){
- pPath2Nodes = LoadPath("data\\paths\\flight2.dat", NumPath2Nodes, TotalLengthOfFlightPath2, true);
- TotalDurationOfFlightPath2 = TotalLengthOfFlightPath2/CRUISE_SPEED;
- }
-
- // Mission Cesna
- if(pPath3Nodes == nil){
- pPath3Nodes = LoadPath("data\\paths\\flight3.dat", NumPath3Nodes, TotalLengthOfFlightPath3, false);
- TotalDurationOfFlightPath3 = TotalLengthOfFlightPath3/CRUISE_SPEED;
- }
-
- // Mission Cesna
- if(pPath4Nodes == nil){
- pPath4Nodes = LoadPath("data\\paths\\flight4.dat", NumPath4Nodes, TotalLengthOfFlightPath4, false);
- TotalDurationOfFlightPath4 = TotalLengthOfFlightPath4/CRUISE_SPEED;
- }
-
- CStreaming::LoadAllRequestedModels(false);
- CStreaming::RequestModel(MI_AIRTRAIN, 0);
- CStreaming::LoadAllRequestedModels(false);
-
- for(i = 0; i < 3; i++){
- CPlane *plane = new CPlane(MI_AIRTRAIN, PERMANENT_VEHICLE);
- plane->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);
- plane->m_status = STATUS_ABANDONED;
- plane->bIsLocked = true;
- plane->m_nPlaneId = i;
- plane->m_nCurPathNode = 0;
- CWorld::Add(plane);
- }
-
-
- CStreaming::RequestModel(MI_DEADDODO, 0);
- CStreaming::LoadAllRequestedModels(false);
-
- for(i = 0; i < 3; i++){
- CPlane *plane = new CPlane(MI_DEADDODO, PERMANENT_VEHICLE);
- plane->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);
- plane->m_status = STATUS_ABANDONED;
- plane->bIsLocked = true;
- plane->m_nPlaneId = i;
- plane->m_nCurPathNode = 0;
- CWorld::Add(plane);
- }
-}
-
-void
-CPlane::Shutdown(void)
-{
- delete[] pPathNodes;
- delete[] pPath2Nodes;
- delete[] pPath3Nodes;
- delete[] pPath4Nodes;
- pPathNodes = nil;
- pPath2Nodes = nil;
- pPath3Nodes = nil;
- pPath4Nodes = nil;
-}
-
-CPlaneNode*
-CPlane::LoadPath(char const *filename, int32 &numNodes, float &totalLength, bool loop)
-{
- int bp, lp;
- int i;
-
- CFileMgr::LoadFile(filename, work_buff, sizeof(work_buff), "r");
- *gString = '\0';
- for(bp = 0, lp = 0; work_buff[bp] != '\n'; bp++, lp++)
- gString[lp] = work_buff[bp];
- bp++;
- gString[lp] = '\0';
- sscanf(gString, "%d", &numNodes);
- CPlaneNode *nodes = new CPlaneNode[numNodes];
-
- for(i = 0; i < numNodes; i++){
- *gString = '\0';
- for(lp = 0; work_buff[bp] != '\n'; bp++, lp++)
- gString[lp] = work_buff[bp];
- bp++;
- // BUG: game doesn't terminate string
- gString[lp] = '\0';
- sscanf(gString, "%f %f %f", &nodes[i].p.x, &nodes[i].p.y, &nodes[i].p.z);
- }
-
- // Calculate length of segments and path
- totalLength = 0.0f;
- for(i = 0; i < numNodes; i++){
- nodes[i].t = totalLength;
- float l = (nodes[(i+1) % numNodes].p - nodes[i].p).Magnitude2D();
- if(!loop && i == numNodes-1)
- l = 0.0f;
- totalLength += l;
- }
-
- return nodes;
-}
-
-void
-CPlane::UpdatePlanes(void)
-{
- int i, j;
- uint32 time;
- float t, deltaT;
-
- if(CReplay::IsPlayingBack())
- return;
-
- // Jumbo jets
- time = CTimer::GetTimeInMilliseconds();
- for(i = 0; i < 3; i++){
- t = TotalDurationOfFlightPath * (float)(time & 0x7FFFF)/0x80000;
- // find current frame
- for(j = 0; t > aPlaneLineBits[j+1].time; j++);
-
- OldPlanePathPosition[i] = PlanePathPosition[i];
- deltaT = t - aPlaneLineBits[j].time;
- switch(aPlaneLineBits[j].type){
- case 0: // standing still
- PlanePathPosition[i] = aPlaneLineBits[j].position;
- PlanePathSpeed[i] = 0.0f;
- break;
- case 1: // moving with constant speed
- PlanePathPosition[i] = aPlaneLineBits[j].position + aPlaneLineBits[j].speed*deltaT;
- PlanePathSpeed[i] = (TotalDurationOfFlightPath*1000.0f/0x80000) * aPlaneLineBits[j].speed;
- break;
- case 2: // accelerating/braking
- PlanePathPosition[i] = aPlaneLineBits[j].position + (aPlaneLineBits[j].speed + aPlaneLineBits[j].acceleration*deltaT)*deltaT;
- PlanePathSpeed[i] = (TotalDurationOfFlightPath*1000.0f/0x80000)*aPlaneLineBits[j].speed + 2.0f*aPlaneLineBits[j].acceleration*deltaT;
- break;
- }
-
- // time offset for each plane
- time += 0x80000/3;
- }
-
- time = CTimer::GetTimeInMilliseconds();
-
- t = TotalDurationOfFlightPath2/0x80000;
- PlanePath2Position[0] = CRUISE_SPEED * (time & 0x7FFFF)*t;
- PlanePath2Position[1] = CRUISE_SPEED * ((time + 0x80000/3) & 0x7FFFF)*t;
- PlanePath2Position[2] = CRUISE_SPEED * ((time + 0x80000/3*2) & 0x7FFFF)*t;
- PlanePath2Speed[0] = CRUISE_SPEED*t;
- PlanePath2Speed[1] = CRUISE_SPEED*t;
- PlanePath2Speed[2] = CRUISE_SPEED*t;
-
- if(CesnaMissionStatus == CESNA_STATUS_FLYING){
- PlanePath3Speed = CRUISE_SPEED*TotalDurationOfFlightPath3/0x20000;
- PlanePath3Position = PlanePath3Speed * ((time - CesnaMissionStartTime) & 0x1FFFF);
- if(time - CesnaMissionStartTime >= 128072)
- CesnaMissionStatus = CESNA_STATUS_LANDED;
- }
-
- if(DropOffCesnaMissionStatus == CESNA_STATUS_FLYING){
- PlanePath4Speed = CRUISE_SPEED*TotalDurationOfFlightPath4/0x80000;
- PlanePath4Position = PlanePath4Speed * ((time - DropOffCesnaMissionStartTime) & 0x7FFFF);
- if(time - DropOffCesnaMissionStartTime >= 521288)
- DropOffCesnaMissionStatus = CESNA_STATUS_LANDED;
- }
-}
-
-bool
-CPlane::TestRocketCollision(CVector *rocketPos)
-{
- int i;
-
- i = CPools::GetVehiclePool()->GetSize();
- while(--i >= 0){
- CPlane *plane = (CPlane*)CPools::GetVehiclePool()->GetSlot(i);
- if(plane &&
-#ifdef EXPLODING_AIRTRAIN
- (plane->GetModelIndex() == MI_AIRTRAIN || plane->GetModelIndex() == MI_DODO) &&
-#else
- plane->GetModelIndex() != MI_AIRTRAIN && plane->GetModelIndex() == MI_DODO && // strange check
-#endif
- !plane->m_bHasBeenHit && (*rocketPos - plane->GetPosition()).Magnitude() < 25.0f){
- plane->m_nFrameWhenHit = CTimer::GetFrameCounter();
- plane->m_bHasBeenHit = true;
- CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->RegisterCrime_Immediately(CRIME_DESTROYED_CESSNA,
- plane->GetPosition(), i+1983, false);
- return true;
- }
- }
- return false;
-}
-
-// BUG: not in CPlane in the game
-void
-CPlane::CreateIncomingCesna(void)
-{
- if(CesnaMissionStatus == CESNA_STATUS_FLYING){
- CWorld::Remove(pDrugRunCesna);
- delete pDrugRunCesna;
- pDrugRunCesna = nil;
- }
- pDrugRunCesna = new CPlane(MI_DEADDODO, PERMANENT_VEHICLE);
- pDrugRunCesna->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);
- pDrugRunCesna->m_status = STATUS_ABANDONED;
- pDrugRunCesna->bIsLocked = true;
- pDrugRunCesna->m_nPlaneId = 0;
- pDrugRunCesna->m_nCurPathNode = 0;
- pDrugRunCesna->m_bIsDrugRunCesna = true;
- CWorld::Add(pDrugRunCesna);
-
- CesnaMissionStatus = CESNA_STATUS_FLYING;
- CesnaMissionStartTime = CTimer::GetTimeInMilliseconds();
- printf("CPlane::CreateIncomingCesna(void)\n");
-}
-
-void
-CPlane::CreateDropOffCesna(void)
-{
- if(DropOffCesnaMissionStatus == CESNA_STATUS_FLYING){
- CWorld::Remove(pDropOffCesna);
- delete pDropOffCesna;
- pDropOffCesna = nil;
- }
- pDropOffCesna = new CPlane(MI_DEADDODO, PERMANENT_VEHICLE);
- pDropOffCesna->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);
- pDropOffCesna->m_status = STATUS_ABANDONED;
- pDropOffCesna->bIsLocked = true;
- pDropOffCesna->m_nPlaneId = 0;
- pDropOffCesna->m_nCurPathNode = 0;
- pDropOffCesna->m_bIsDropOffCesna = true;
- CWorld::Add(pDropOffCesna);
-
- DropOffCesnaMissionStatus = CESNA_STATUS_FLYING;
- DropOffCesnaMissionStartTime = CTimer::GetTimeInMilliseconds();
- printf("CPlane::CreateDropOffCesna(void)\n");
-}
-
-CVector CPlane::FindDrugPlaneCoordinates(void) { return pDrugRunCesna->GetPosition(); }
-CVector CPlane::FindDropOffCesnaCoordinates(void) { return pDrugRunCesna->GetPosition(); }
-bool CPlane::HasCesnaLanded(void) { return CesnaMissionStatus == CESNA_STATUS_LANDED; }
-bool CPlane::HasCesnaBeenDestroyed(void) { return CesnaMissionStatus == CESNA_STATUS_DESTROYED; }
-bool CPlane::HasDropOffCesnaBeenShotDown(void) { return DropOffCesnaMissionStatus == CESNA_STATUS_DESTROYED; }
-
-
-class CPlane_ : public CPlane
-{
-public:
- void ctor(int32 id, uint8 CreatedBy) { ::new (this) CPlane(id, CreatedBy); }
- void dtor(void) { CPlane::~CPlane(); }
-};
-
-STARTPATCHES
- InjectHook(0x54B170, &CPlane_::ctor, PATCH_JUMP);
- InjectHook(0x54B270, &CPlane_::dtor, PATCH_JUMP);
- InjectHook(0x54B820, CPlane::InitPlanes, PATCH_JUMP);
- InjectHook(0x54BCD0, CPlane::Shutdown, PATCH_JUMP);
- InjectHook(0x54BD50, CPlane::LoadPath, PATCH_JUMP);
- InjectHook(0x54BEC0, CPlane::UpdatePlanes, PATCH_JUMP);
- InjectHook(0x54DE90, CPlane::TestRocketCollision, PATCH_JUMP);
- InjectHook(0x54E000, CPlane::CreateIncomingCesna, PATCH_JUMP);
- InjectHook(0x54E160, CPlane::CreateDropOffCesna, PATCH_JUMP);
-ENDPATCHES
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index dd15d910..4795a29f 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -97,8 +97,8 @@ CVehicle::CVehicle(uint8 CreatedBy)
DMAudio.SetEntityStatus(m_audioEntityId, true);
m_nRadioStation = CGeneral::GetRandomNumber() % USERTRACK;
m_pCurGroundEntity = nil;
- field_22A = 0;
- field_22B = 0;
+ m_bRainAudioCounter = 0;
+ m_bRainSamplesCounter = 0;
m_comedyControlState = 0;
m_aCollPolys[0].valid = false;
m_aCollPolys[1].valid = false;
@@ -273,7 +273,7 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
right = -contactSpeedRight/wheelsOnGround;
if(wheelStatus == WHEEL_STATUS_BURST){
- float fwdspeed = Min(contactSpeedFwd, 0.3f);
+ float fwdspeed = min(contactSpeedFwd, 0.3f);
right += fwdspeed * CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
}
}
@@ -363,7 +363,7 @@ CVehicle::ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVec
void
CVehicle::ExtinguishCarFire(void)
{
- m_fHealth = Max(m_fHealth, 300.0f);
+ m_fHealth = max(m_fHealth, 300.0f);
if(m_pCarFire)
m_pCarFire->Extinguish();
if(IsCar()){
@@ -638,13 +638,13 @@ CVehicle::SetDriver(CPed *driver)
if(bFreebies && driver == FindPlayerPed()){
if(GetModelIndex() == MI_AMBULAN)
- FindPlayerPed()->m_fHealth = Min(FindPlayerPed()->m_fHealth + 20.0f, 100.0f);
+ FindPlayerPed()->m_fHealth = min(FindPlayerPed()->m_fHealth + 20.0f, 100.0f);
else if(GetModelIndex() == MI_TAXI)
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
else if(GetModelIndex() == MI_POLICE)
driver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5);
else if(GetModelIndex() == MI_ENFORCER)
- driver->m_fArmour = Max(driver->m_fArmour, 100.0f);
+ driver->m_fArmour = max(driver->m_fArmour, 100.0f);
else if(GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE)
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
bFreebies = false;
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index accc6936..96f57e06 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -191,8 +191,8 @@ public:
eCarLock m_nDoorLock;
int8 m_nLastWeaponDamage; // see eWeaponType, -1 if no damage
int8 m_nRadioStation;
- int8 field_22A;
- int8 field_22B;
+ uint8 m_bRainAudioCounter;
+ uint8 m_bRainSamplesCounter;
uint8 m_nCarHornTimer;
int8 field_22D;
bool m_bSirenOrAlarm;