summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio/DMAudio.h6
-rw-r--r--src/core/Collision.cpp6
-rw-r--r--src/core/Fire.cpp1
-rw-r--r--src/core/Fire.h3
-rw-r--r--src/core/PlayerInfo.h2
-rw-r--r--src/core/re3.cpp1
-rw-r--r--src/render/WaterCannon.cpp1
-rw-r--r--src/render/WaterCannon.h1
-rw-r--r--src/vehicles/Automobile.cpp366
-rw-r--r--src/vehicles/Automobile.h2
-rw-r--r--src/vehicles/Vehicle.cpp2
-rw-r--r--src/vehicles/Vehicle.h2
12 files changed, 373 insertions, 20 deletions
diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h
index da20dc31..4428c958 100644
--- a/src/audio/DMAudio.h
+++ b/src/audio/DMAudio.h
@@ -20,9 +20,9 @@ enum eSound : int16
SOUND_F = 15,
SOUND_CAR_ENGINE_START = 16,
SOUND_CAR_LIGHT_BREAK = 17,
- SOUND_CAR_HYDRALIC_1 = 18,
- SOUND_CAR_HYDRALIC_2 = 19,
- SOUND_CAR_HYDRALIC_3 = 20,
+ SOUND_CAR_HYDRAULIC_1 = 18,
+ SOUND_CAR_HYDRAULIC_2 = 19,
+ SOUND_CAR_HYDRAULIC_3 = 20,
SOUND_CAR_JERK = 21,
SOUND_CAR_SPLASH = 22,
SOUND_17 = 23,
diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp
index 7982e77d..cc360f79 100644
--- a/src/core/Collision.cpp
+++ b/src/core/Collision.cpp
@@ -2023,11 +2023,11 @@ CColModel::operator=(const CColModel &other)
numVerts = 0;
for(i = 0; i < other.numTriangles; i++){
if(other.triangles[i].a > numVerts)
- other.triangles[i].a = numVerts;
+ numVerts = other.triangles[i].a;
if(other.triangles[i].b > numVerts)
- other.triangles[i].b = numVerts;
+ numVerts = other.triangles[i].b;
if(other.triangles[i].c > numVerts)
- other.triangles[i].c = numVerts;
+ numVerts = other.triangles[i].c;
}
numVerts++;
if(vertices)
diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp
index bc59de2f..a2894d43 100644
--- a/src/core/Fire.cpp
+++ b/src/core/Fire.cpp
@@ -7,3 +7,4 @@ CFireManager &gFireManager = *(CFireManager*)0x8F31D0;
WRAPPER void CFire::Extinguish(void) { EAXJMP(0x479D40); }
WRAPPER void CFireManager::StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32) { EAXJMP(0x479590); }
+WRAPPER CFire *CFireManager::FindFurthestFire_NeverMindFireMen(CVector coors, float, float) { EAXJMP(0x479430); }
diff --git a/src/core/Fire.h b/src/core/Fire.h
index 9c9e1dec..040e9a25 100644
--- a/src/core/Fire.h
+++ b/src/core/Fire.h
@@ -4,6 +4,7 @@ class CEntity;
class CFire
{
+public:
bool m_bIsOngoing;
bool m_bExists;
bool m_bPropogationFlag;
@@ -18,7 +19,6 @@ class CFire
int field_28;
float field_2C;
-public:
void Extinguish(void);
};
@@ -26,5 +26,6 @@ class CFireManager
{
public:
void StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32);
+ CFire *FindFurthestFire_NeverMindFireMen(CVector coors, float, float);
};
extern CFireManager &gFireManager;
diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h
index a5f69122..decfb24c 100644
--- a/src/core/PlayerInfo.h
+++ b/src/core/PlayerInfo.h
@@ -20,7 +20,7 @@ public:
CPlayerPed *m_pPed;
CVehicle *m_pRemoteVehicle;
CColModel m_ColModel;
- CVehicle *m_pVehicleEx;
+ CVehicle *m_pVehicleEx; // vehicle using the col model above
char m_aPlayerName[70];
int32 m_nMoney;
int32 m_nVisibleMoney;
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 6566a282..c2787bc3 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -295,6 +295,7 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Spawn", "Spawn Enforcer", [](){ SpawnCar(MI_ENFORCER); });
DebugMenuAddCmd("Spawn", "Spawn Banshee", [](){ SpawnCar(MI_BANSHEE); });
DebugMenuAddCmd("Spawn", "Spawn Yakuza", [](){ SpawnCar(MI_YAKUZA); });
+ DebugMenuAddCmd("Spawn", "Spawn Yardie", [](){ SpawnCar(MI_YARDIE); });
DebugMenuAddCmd("Spawn", "Spawn Dodo", [](){ SpawnCar(MI_DODO); });
DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); });
DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); });
diff --git a/src/render/WaterCannon.cpp b/src/render/WaterCannon.cpp
index afb40f6f..9398c847 100644
--- a/src/render/WaterCannon.cpp
+++ b/src/render/WaterCannon.cpp
@@ -2,4 +2,5 @@
#include "patcher.h"
#include "WaterCannon.h"
+WRAPPER void CWaterCannons::UpdateOne(uint32 id, CVector *pos, CVector *dir) { EAXJMP(0x522470); }
WRAPPER void CWaterCannons::Render(void) { EAXJMP(0x522550); }
diff --git a/src/render/WaterCannon.h b/src/render/WaterCannon.h
index 1a18e75f..55949803 100644
--- a/src/render/WaterCannon.h
+++ b/src/render/WaterCannon.h
@@ -3,5 +3,6 @@
class CWaterCannons
{
public:
+ static void UpdateOne(uint32 id, CVector *pos, CVector *dir);
static void Render(void);
};
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index 0c4d0ff9..e1484fa4 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -15,6 +15,7 @@
#include "Explosion.h"
#include "Particle.h"
#include "ParticleObject.h"
+#include "WaterCannon.h"
#include "WaterLevel.h"
#include "Floater.h"
#include "World.h"
@@ -122,7 +123,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
bNotDamagedUpsideDown = false;
bMoreResistantToDamage = false;
m_fVelocityChangeForAudio = 0.f;
- field_4E2 = 0;
+ m_hydraulicState = 0;
for(i = 0; i < 4; i++){
m_aGroundPhysical[i] = nil;
@@ -205,7 +206,7 @@ CAutomobile::ProcessControl(void)
int i;
CColModel *colModel;
- if(m_veh_flagC80)
+ if(bUseSpecialColModel)
colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;
else
colModel = GetColModel();
@@ -488,7 +489,7 @@ CAutomobile::ProcessControl(void)
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_HYDRAULIC_1, 0.0f);
DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP, 1.0f);
CParticle::AddParticle(PARTICLE_ENGINE_STEAM,
@@ -1213,7 +1214,7 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
if(m_status != STATUS_SIMPLE)
bVehicleColProcessed = true;
- if(m_veh_flagC80)
+ if(bUseSpecialColModel)
colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;
else
colModel = GetColModel();
@@ -1416,9 +1417,62 @@ CAutomobile::ProcessControlInputs(uint8 pad)
}
}
-WRAPPER void
+void
CAutomobile::FireTruckControl(void)
-{ EAXJMP(0x522590);
+{
+ 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
@@ -1528,13 +1582,307 @@ CAutomobile::TankControl(void)
}
}
-WRAPPER void
+void
CAutomobile::HydraulicControl(void)
-{ EAXJMP(0x52D4E0);
+{
+ 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(!bUseSpecialColModel)
+ 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;
+ bUseSpecialColModel = 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(!bUseSpecialColModel){
+ // Init special col model
+
+ if(playerInfo->m_pVehicleEx && playerInfo->m_pVehicleEx == this)
+ playerInfo->m_pVehicleEx->bUseSpecialColModel = false;
+ playerInfo->m_pVehicleEx = this;
+ playerInfo->m_ColModel = *normalColModel;
+ bUseSpecialColModel = 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)
+CAutomobile::ProcessBuoyancy(void)
{
int i;
CVector impulse, point;
diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h
index fd3eb203..81b02634 100644
--- a/src/vehicles/Automobile.h
+++ b/src/vehicles/Automobile.h
@@ -54,7 +54,7 @@ public:
uint8 field_4DB;
CEntity *m_pBombRigger;
int16 field_4E0;
- int16 field_4E2;
+ uint16 m_hydraulicState;
uint32 m_nBusDoorTimerEnd;
uint32 m_nBusDoorTimerStart;
float m_aSuspensionSpringLength[4];
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index 4bcd08db..d8ea6211 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -70,7 +70,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
bHasBeenOwnedByPlayer = false;
m_veh_flagC20 = false;
bCanBeDamaged = true;
- m_veh_flagC80 = false;
+ bUseSpecialColModel = false;
m_veh_flagD1 = false;
m_veh_flagD2 = false;
m_nGunFiringTime = 0;
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index 38d411cd..825c1a6c 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -186,7 +186,7 @@ public:
uint8 m_veh_flagC10 : 1;
uint8 m_veh_flagC20 : 1;
uint8 bCanBeDamaged : 1; // Set to FALSE during cut scenes to avoid explosions
- uint8 m_veh_flagC80 : 1;
+ uint8 bUseSpecialColModel : 1;
uint8 m_veh_flagD1 : 1;
uint8 m_veh_flagD2 : 1;