summaryrefslogtreecommitdiffstats
path: root/src/vehicles
diff options
context:
space:
mode:
Diffstat (limited to 'src/vehicles')
-rw-r--r--src/vehicles/Automobile.cpp223
-rw-r--r--src/vehicles/Automobile.h2
-rw-r--r--src/vehicles/Vehicle.cpp2
-rw-r--r--src/vehicles/Vehicle.h6
4 files changed, 223 insertions, 10 deletions
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 5580ee6d..ecf3bde3 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -10,6 +10,7 @@
#include "Rubbish.h"
#include "Fire.h"
#include "Explosion.h"
+#include "Particle.h"
#include "World.h"
#include "SurfaceTable.h"
#include "HandlingMgr.h"
@@ -46,6 +47,9 @@ CAutomobile::SetModelIndex(uint32 id)
SetupModelNodes();
}
+CVector vecDAMAGE_ENGINE_POS_SMALL(-0.1f, -0.1f, 0.0f);
+CVector vecDAMAGE_ENGINE_POS_BIG(-0.5f, -0.3f, 0.0f);
+
//WRAPPER void CAutomobile::ProcessControl(void) { EAXJMP(0x531470); }
void
CAutomobile::ProcessControl(void)
@@ -330,12 +334,51 @@ CAutomobile::ProcessControl(void)
break;
default:
if(CVehicle::bCheat3){
- // strong grip cheat
- // TODO: make cars jump when horn key is pressed
+ // 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_HYDRALIC_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;
@@ -473,7 +516,7 @@ CAutomobile::ProcessControl(void)
GetModelIndex() == MI_MIAMI_SPARROW)
acceleration = 0.0f;
- float brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep();
+ 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);
@@ -766,7 +809,7 @@ CAutomobile::ProcessControl(void)
for(i = 0; i < 4; i++){
float wheelPos = colModel->lines[i].p0.z;
if(m_aSuspensionSpringRatio[i] > 0.0f)
- wheelPos -= m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];
+ wheelPos -= m_aSuspensionSpringRatio[i]*m_aSuspensionSpringLength[i];
m_aWheelPosition[i] += (wheelPos - m_aWheelPosition[i])*0.75f;
}
for(i = 0; i < 4; i++)
@@ -824,7 +867,174 @@ CAutomobile::ProcessControl(void)
}
}
- assert(0 && "misc stuff");
+
+
+ // 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 > 225 && 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
@@ -1557,7 +1767,7 @@ void
CAutomobile::ScanForCrimes(void)
{
if(FindPlayerVehicle() && FindPlayerVehicle()->IsCar())
- if(FindPlayerVehicle()->m_nAlarmState != -1)
+ 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);
@@ -2064,6 +2274,7 @@ public:
STARTPATCHES
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(0x53B270, &CAutomobile_::ProcessEntityCollision_, PATCH_JUMP);
InjectHook(0x53B660, &CAutomobile_::ProcessControlInputs_, PATCH_JUMP);
diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h
index 69df9bb3..5ff39fed 100644
--- a/src/vehicles/Automobile.h
+++ b/src/vehicles/Automobile.h
@@ -59,7 +59,7 @@ public:
float m_fHeightAboveRoad;
float m_fTraction;
uint8 stuff6[28];
- float field_530;
+ float m_fFireBlowUpTimer;
CPhysical *m_aGroundPhysical[4]; // physicals touching wheels
CVector m_aGroundOffset[4]; // from ground object to colpoint
CEntity *m_pSetOnFireEntity;
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index e521a699..b91e4268 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -364,7 +364,7 @@ CVehicle::ExtinguishCarFire(void)
CAutomobile *car = (CAutomobile*)this;
if(car->Damage.GetEngineStatus() >= 225)
car->Damage.SetEngineStatus(215);
- car->field_530 = 0.0f;
+ car->m_fFireBlowUpTimer = 0.0f;
}
}
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index de74264b..7513c0da 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -130,7 +130,7 @@ public:
uint8 m_currentColour1;
uint8 m_currentColour2;
uint8 m_aExtras[2];
- int16 m_nAlarmState; // m_nWantedStarsOnEnter on DK22
+ int16 m_nAlarmState;
int16 m_nMissionValue;
CPed *pDriver;
CPed *pPassengers[8];
@@ -188,7 +188,7 @@ public:
uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default)
int8 field_1FB;
int8 field_1FC[4];
- float m_fHealth; // 1000.0f = full health. 0 -> explode
+ float m_fHealth; // 1000.0f = full health. 250.0f = fire. 0 -> explode
uint8 m_nCurrentGear;
int8 field_205[3];
float m_fChangeGearTime;
@@ -277,6 +277,8 @@ public:
void RemoveDriver(void);
void ProcessCarAlarm(void);
bool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius);
+
+ bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; }
static bool &bWheelsOnlyCheat;
static bool &bAllDodosCheat;