summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNikolay Korolev <nickvnuk@gmail.com>2019-07-28 14:52:39 +0200
committerNikolay Korolev <nickvnuk@gmail.com>2019-07-28 14:52:39 +0200
commitf7c93fc15c9b9b45a3022433379ff967443a2c74 (patch)
tree9db8a9057d0b96fac16bdb9f76796c87e5283706 /src
parentfixed phones (diff)
parentMerge branch 'master' of github.com:GTAmodding/re3 (diff)
downloadre3-f7c93fc15c9b9b45a3022433379ff967443a2c74.tar
re3-f7c93fc15c9b9b45a3022433379ff967443a2c74.tar.gz
re3-f7c93fc15c9b9b45a3022433379ff967443a2c74.tar.bz2
re3-f7c93fc15c9b9b45a3022433379ff967443a2c74.tar.lz
re3-f7c93fc15c9b9b45a3022433379ff967443a2c74.tar.xz
re3-f7c93fc15c9b9b45a3022433379ff967443a2c74.tar.zst
re3-f7c93fc15c9b9b45a3022433379ff967443a2c74.zip
Diffstat (limited to 'src')
-rw-r--r--src/entities/Entity.cpp2
-rw-r--r--src/entities/Entity.h2
-rw-r--r--src/math/Vector.h6
-rw-r--r--src/math/Vector2D.h2
-rw-r--r--src/peds/Ped.cpp4
-rw-r--r--src/render/Coronas.cpp2
-rw-r--r--src/render/Coronas.h2
-rw-r--r--src/render/Renderer.cpp4
-rw-r--r--src/render/Shadows.h1
-rw-r--r--src/render/Skidmarks.cpp1
-rw-r--r--src/render/Skidmarks.h1
-rw-r--r--src/render/SpecialFX.cpp1
-rw-r--r--src/render/SpecialFX.h9
-rw-r--r--src/vehicles/Automobile.cpp733
-rw-r--r--src/vehicles/Automobile.h2
-rw-r--r--src/vehicles/DamageManager.h6
-rw-r--r--src/vehicles/Vehicle.cpp16
-rw-r--r--src/vehicles/Vehicle.h8
18 files changed, 764 insertions, 38 deletions
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index b795931f..04a93420 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -65,7 +65,7 @@ CEntity::CEntity(void)
m_flagD8 = false;
bIsSubway = false;
bDrawLast = false;
- m_flagD40 = false;
+ bNoBrightHeadLights = false;
m_flagD80 = false;
bDistanceFade = false;
diff --git a/src/entities/Entity.h b/src/entities/Entity.h
index cdc9a173..11d3e8cd 100644
--- a/src/entities/Entity.h
+++ b/src/entities/Entity.h
@@ -76,7 +76,7 @@ public:
uint32 m_flagD8 : 1; // used by cBuoyancy::ProcessBuoyancy
uint32 bIsSubway : 1; // set when subway, but maybe different meaning?
uint32 bDrawLast : 1;
- uint32 m_flagD40 : 1;
+ uint32 bNoBrightHeadLights : 1;
uint32 m_flagD80 : 1; // CObject visibility?
// flagsE
diff --git a/src/math/Vector.h b/src/math/Vector.h
index f794a57f..42087339 100644
--- a/src/math/Vector.h
+++ b/src/math/Vector.h
@@ -31,7 +31,7 @@ public:
void Normalise(void) {
float sq = MagnitudeSqr();
if(sq > 0.0f){
- float invsqrt = 1.0f/Sqrt(sq); // CMaths::RecipSqrt
+ float invsqrt = RecipSqrt(sq);
x *= invsqrt;
y *= invsqrt;
z *= invsqrt;
@@ -71,6 +71,10 @@ public:
return CVector(-x, -y, -z);
}
+ const bool operator==(CVector const &right) {
+ return x == right.x && y == right.y && z == right.z;
+ }
+
bool IsZero(void) { return x == 0.0f && y == 0.0f && z == 0.0f; }
};
diff --git a/src/math/Vector2D.h b/src/math/Vector2D.h
index caba9146..c8835ec0 100644
--- a/src/math/Vector2D.h
+++ b/src/math/Vector2D.h
@@ -14,7 +14,7 @@ public:
void Normalise(void){
float sq = MagnitudeSqr();
if(sq > 0.0f){
- float invsqrt = 1.0f/Sqrt(sq);
+ float invsqrt = RecipSqrt(sq);
x *= invsqrt;
y *= invsqrt;
}else
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index c95068d0..51174da8 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -1489,7 +1489,7 @@ CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatP
break;
case CAR_DOOR_RR:
- vehDoorPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
+ vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
vehDoorPos.x += seatOffset;
vehDoorOffset.x = -vehDoorOffset.x;
break;
@@ -1504,7 +1504,7 @@ CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatP
break;
case CAR_DOOR_LR:
- vehDoorPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
+ vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
vehDoorPos.x = -(vehDoorPos.x + seatOffset);
break;
diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp
index 5ac9b149..1a6cfea3 100644
--- a/src/render/Coronas.cpp
+++ b/src/render/Coronas.cpp
@@ -203,7 +203,7 @@ CCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 al
}
void
-CCoronas::UpdateCoronaCoors(int id, const CVector &coors, float drawDist, float someAngle)
+CCoronas::UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, float someAngle)
{
int i;
diff --git a/src/render/Coronas.h b/src/render/Coronas.h
index ed69b1e6..359a34ed 100644
--- a/src/render/Coronas.h
+++ b/src/render/Coronas.h
@@ -93,7 +93,7 @@ public:
static void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,
const CVector &coors, float size, float drawDist, uint8 type,
int8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle);
- static void UpdateCoronaCoors(int id, const CVector &coors, float drawDist, float someAngle);
+ static void UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, float someAngle);
static void Render(void);
static void RenderReflections(void);
static void DoSunAndMoon(void);
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 7bf4593f..77489e60 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -359,10 +359,10 @@ CRenderer::SetupEntityVisibility(CEntity *ent)
ent->GetModelIndex() == MI_RHINO ||
ent->GetModelIndex() == MI_COACH ||
TheCamera.m_bInATunnelAndABigVehicle){
- ent->m_flagD40 = true;
+ ent->bNoBrightHeadLights = true;
}else{
m_pFirstPersonVehicle = (CVehicle*)ent;
- ent->m_flagD40 = false;
+ ent->bNoBrightHeadLights = false;
}
return VIS_OFFSCREEN;
}else{
diff --git a/src/render/Shadows.h b/src/render/Shadows.h
index 585518ee..c12327b1 100644
--- a/src/render/Shadows.h
+++ b/src/render/Shadows.h
@@ -177,3 +177,4 @@ public:
extern RwTexture *&gpBloodPoolTex;
extern RwTexture *&gpShadowExplosionTex;
+extern RwTexture *&gpShadowHeadLightsTex;
diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp
index fd5e7d2b..bbadd54c 100644
--- a/src/render/Skidmarks.cpp
+++ b/src/render/Skidmarks.cpp
@@ -5,3 +5,4 @@
WRAPPER void CSkidmarks::Clear(void) { EAXJMP(0x518130); }
WRAPPER void CSkidmarks::Render(void) { EAXJMP(0x5182E0); }
+WRAPPER void CSkidmarks::RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy) { EAXJMP(0x5185C0); }
diff --git a/src/render/Skidmarks.h b/src/render/Skidmarks.h
index d1e1d996..280150a7 100644
--- a/src/render/Skidmarks.h
+++ b/src/render/Skidmarks.h
@@ -5,4 +5,5 @@ class CSkidmarks
public:
static void Clear(void);
static void Render(void);
+ static void RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy);
};
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index 4fa2677a..bed5af50 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -11,5 +11,6 @@ CBulletTrace (&CBulletTraces::aTraces)[16] = *(CBulletTrace(*)[16])*(uintptr*)0x
WRAPPER void CBulletTraces::Init(void) { EAXJMP(0x518DE0); }
+WRAPPER void CBrightLights::RegisterOne(CVector pos, CVector up, CVector right, CVector fwd, uint8 type, uint8 unk1, uint8 unk2, uint8 unk3) { EAXJMP(0x51A410); }
WRAPPER void C3dMarkers::PlaceMarkerSet(uint32 id, uint16 type, CVector& pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate) { EAXJMP(0x51BB80); } \ No newline at end of file
diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h
index 08f0f08a..9c61c0fb 100644
--- a/src/render/SpecialFX.h
+++ b/src/render/SpecialFX.h
@@ -29,8 +29,15 @@ public:
static void Init(void);
};
+class CBrightLights
+{
+public:
+ static void RegisterOne(CVector pos, CVector up, CVector right, CVector fwd, uint8 type, uint8 unk1 = 0, uint8 unk2 = 0, uint8 unk3 = 0);
+};
+
class C3dMarkers
{
public:
static void PlaceMarkerSet(uint32 id, uint16 type, CVector& pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
-}; \ No newline at end of file
+};
+
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 50010d3c..28ede4cd 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -7,7 +7,9 @@
#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"
@@ -15,6 +17,12 @@
#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"
@@ -134,7 +142,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
m_aWheelTimer[i] = 0.0f;
m_aWheelRotation[i] = 0.0f;
m_aWheelSpeed[i] = 0.0f;
- m_aWheelState[i] = WHEEL_STATE_0;
+ m_aWheelState[i] = WHEEL_STATE_NORMAL;
m_aWheelSkidmarkMuddy[i] = false;
m_aWheelSkidmarkBloody[i] = false;
}
@@ -364,7 +372,7 @@ CAutomobile::ProcessControl(void)
pHandling->Transmission.CalculateGearForSimpleCar(AutoPilot.m_fMaxTrafficSpeed/50.0f, m_nCurrentGear);
{
- float wheelRot = ProcessWheelRotation(WHEEL_STATE_0, GetForward(), m_vecMoveSpeed, 0.35f);
+ float wheelRot = ProcessWheelRotation(WHEEL_STATE_NORMAL, GetForward(), m_vecMoveSpeed, 0.35f);
for(i = 0; i < 4; i++)
m_aWheelRotation[i] += wheelRot;
}
@@ -1202,7 +1210,702 @@ CAutomobile::Teleport(CVector pos)
CWorld::Add(this);
}
-WRAPPER void CAutomobile::PreRender(void) { EAXJMP(0x535B40); }
+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)
@@ -1409,7 +2112,6 @@ CAutomobile::Render(void)
mi->SetVehicleColour(m_currentColour1, m_currentColour2);
}
-
if(!CVehicle::bWheelsOnlyCheat)
CEntity::Render();
}
@@ -2727,7 +3429,7 @@ CAutomobile::AddDamagedVehicleParticles(void)
}
}
-void
+int32
CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed)
{
int i;
@@ -2738,7 +3440,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed)
static RwRGBA waterCol = { 48, 48, 64, 0 };
if(!belowEffectSpeed)
- return;
+ return 0;
switch(colpoint->surfaceB){
case SURFACE_GRASS:
@@ -2749,7 +3451,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed)
CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,
CGeneral::GetRandomNumberInRange(0.02f, 0.1f), grassCol);
}
- break;
+ return 0;
case SURFACE_DIRT:
dir.x = -0.05f*m_vecMoveSpeed.x;
dir.y = -0.05f*m_vecMoveSpeed.y;
@@ -2758,7 +3460,7 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed)
CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,
CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirtCol);
}
- break;
+ return 1;
case SURFACE_DIRTTRACK:
dir.x = -0.05f*m_vecMoveSpeed.x;
dir.y = -0.05f*m_vecMoveSpeed.y;
@@ -2767,15 +3469,17 @@ CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed)
CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,
CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirttrackCol);
}
- break;
+ return 0;
default:
// Is this even visible?
- if(CWeather::WetRoads > 0.01f && CTimer::GetFrameCounter() & 1)
+ 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);
- break;
+ return 0;
+ }
+ return 1;
}
}
@@ -3148,10 +3852,10 @@ CAutomobile::IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset)
CVector seatPos;
switch(component){
case CAR_DOOR_RF:
- seatPos = mi->m_positions[IsBoat() ? BOAT_POS_FRONTSEAT : CAR_POS_FRONTSEAT];
+ 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[IsBoat() ? BOAT_POS_FRONTSEAT : CAR_POS_FRONTSEAT];
+ 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:
@@ -3241,7 +3945,7 @@ CAutomobile::ResetSuspension(void)
m_aSuspensionSpringRatio[i] = 1.0f;
m_aWheelTimer[i] = 0.0f;
m_aWheelRotation[i] = 0.0f;
- m_aWheelState[i] = WHEEL_STATE_0;
+ m_aWheelState[i] = WHEEL_STATE_NORMAL;
}
}
@@ -3809,6 +4513,7 @@ STARTPATCHES
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);
diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h
index 618ad079..6226b555 100644
--- a/src/vehicles/Automobile.h
+++ b/src/vehicles/Automobile.h
@@ -123,7 +123,7 @@ public:
void PlaceOnRoadProperly(void);
void dmgDrawCarCollidingParticles(const CVector &pos, float amount);
void AddDamagedVehicleParticles(void);
- void AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed);
+ int32 AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed);
void PlayHornIfNecessary(void);
void ResetSuspension(void);
void SetupSuspensionLines(void);
diff --git a/src/vehicles/DamageManager.h b/src/vehicles/DamageManager.h
index 388fbae9..bf0c59a1 100644
--- a/src/vehicles/DamageManager.h
+++ b/src/vehicles/DamageManager.h
@@ -35,6 +35,12 @@ enum eWheelStatus
WHEEL_STATUS_MISSING
};
+enum eLightStatus
+{
+ LIGHT_STATUS_OK,
+ LIGHT_STATUS_BROKEN
+};
+
enum tComponent
{
COMPONENT_DEFAULT,
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index 194d4e14..36675c8b 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -255,9 +255,9 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
float contactSpeedFwd = DotProduct(wheelContactSpeed, wheelFwd);
float contactSpeedRight = DotProduct(wheelContactSpeed, wheelRight);
- if(*wheelState != WHEEL_STATE_0)
+ if(*wheelState != WHEEL_STATE_NORMAL)
bAlreadySkidding = true;
- *wheelState = WHEEL_STATE_0;
+ *wheelState = WHEEL_STATE_NORMAL;
adhesion *= CTimer::GetTimeStep();
if(bAlreadySkidding)
@@ -299,7 +299,7 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
if(brake > adhesion){
if(Abs(contactSpeedFwd) > 0.005f)
- *wheelState = WHEEL_STATE_STATIC;
+ *wheelState = WHEEL_STATE_FIXED;
}else {
if(fwd > 0.0f){
if(fwd > brake)
@@ -312,11 +312,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
}
if(sq(adhesion) < sq(right) + sq(fwd)){
- if(*wheelState != WHEEL_STATE_STATIC){
+ if(*wheelState != WHEEL_STATE_FIXED){
if(bDriving && contactSpeedFwd < 0.2f)
- *wheelState = WHEEL_STATE_1;
+ *wheelState = WHEEL_STATE_SPINNING;
else
- *wheelState = WHEEL_STATE_2;
+ *wheelState = WHEEL_STATE_SKIDDING;
}
float l = Sqrt(sq(right) + sq(fwd));
@@ -343,10 +343,10 @@ CVehicle::ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVec
{
float angularVelocity;
switch(state){
- case WHEEL_STATE_1:
+ case WHEEL_STATE_SPINNING:
angularVelocity = -1.1f; // constant speed forward
break;
- case WHEEL_STATE_STATIC:
+ case WHEEL_STATE_FIXED:
angularVelocity = 0.0f; // not moving
break;
default:
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index 1e77a3c5..262bd62c 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -124,10 +124,10 @@ enum
enum tWheelState
{
- WHEEL_STATE_0 = 0,
- WHEEL_STATE_1 = 1, // constant velocity
- WHEEL_STATE_2 = 2, // normal
- WHEEL_STATE_STATIC = 3, // not moving
+ WHEEL_STATE_NORMAL, // standing still or rolling normally
+ WHEEL_STATE_SPINNING, // rotating but not moving
+ WHEEL_STATE_SKIDDING,
+ WHEEL_STATE_FIXED, // not rotating
};
enum eFlightModel