summaryrefslogtreecommitdiffstats
path: root/src/vehicles
diff options
context:
space:
mode:
Diffstat (limited to 'src/vehicles')
-rw-r--r--src/vehicles/Automobile.cpp23
-rw-r--r--src/vehicles/Boat.cpp2
-rw-r--r--src/vehicles/Heli.cpp3
-rw-r--r--src/vehicles/Plane.cpp3
-rw-r--r--src/vehicles/Train.cpp3
-rw-r--r--src/vehicles/Vehicle.cpp212
-rw-r--r--src/vehicles/Vehicle.h4
7 files changed, 242 insertions, 8 deletions
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index a05a1236..e6b936f6 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -39,6 +39,7 @@
#include "PathFind.h"
#include "AnimManager.h"
#include "RpAnimBlend.h"
+#include "AnimBlendAssociation.h"
#include "Ped.h"
#include "PlayerPed.h"
#include "Object.h"
@@ -2338,10 +2339,16 @@ 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();
+#ifdef FREE_CAM
+ if (!CCamera::bFreeCam)
+#endif
+ {
+ m_fCarGunLR += CPad::GetPad(0)->GetCarGunLeftRight() * 0.00025f * CTimer::GetTimeStep();
+ m_fCarGunUD += CPad::GetPad(0)->GetCarGunUpDown() * 0.0001f * CTimer::GetTimeStep();
+ }
m_fCarGunUD = clamp(m_fCarGunUD, 0.05f, 0.3f);
+
CVector cannonPos(0.0f, 1.5f, 1.9f);
cannonPos = GetMatrix() * cannonPos;
CVector cannonDir(
@@ -2407,7 +2414,11 @@ CAutomobile::TankControl(void)
// Rotate turret
float prevAngle = m_fCarGunLR;
- m_fCarGunLR -= CPad::GetPad(0)->GetCarGunLeftRight() * 0.00015f * CTimer::GetTimeStep();
+#ifdef FREE_CAM
+ if(!CCamera::bFreeCam)
+#endif
+ m_fCarGunLR -= CPad::GetPad(0)->GetCarGunLeftRight() * 0.00015f * CTimer::GetTimeStep();
+
if(m_fCarGunLR < 0.0f)
m_fCarGunLR += TWOPI;
if(m_fCarGunLR > TWOPI)
@@ -2822,13 +2833,13 @@ CAutomobile::ProcessBuoyancy(void)
if(pDriver){
pDriver->bIsInWater = true;
if(pDriver->IsPlayer() || !bWaterTight)
- pDriver->InflictDamage(nil, WEAPONTYPE_WATER, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
+ pDriver->InflictDamage(nil, WEAPONTYPE_DROWNING, 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);
+ pPassengers[i]->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
}
}else
bIsInWater = false;
@@ -4483,6 +4494,8 @@ CAutomobile::SetAllTaxiLights(bool set)
m_sAllTaxiLights = set;
}
+#include <new>
+
class CAutomobile_ : public CAutomobile
{
public:
diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp
index 7dbd7080..6d584017 100644
--- a/src/vehicles/Boat.cpp
+++ b/src/vehicles/Boat.cpp
@@ -299,6 +299,8 @@ CBoat::FillBoatList()
}
}
+#include <new>
+
class CBoat_ : public CBoat
{
public:
diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp
index aab9dd0d..3dc1deeb 100644
--- a/src/vehicles/Heli.cpp
+++ b/src/vehicles/Heli.cpp
@@ -19,6 +19,8 @@
#include "World.h"
#include "WaterLevel.h"
#include "PlayerPed.h"
+#include "Wanted.h"
+#include "DMAudio.h"
#include "Object.h"
#include "HandlingMgr.h"
#include "Heli.h"
@@ -1034,6 +1036,7 @@ bool CHeli::HasCatalinaBeenShotDown(void) { return CatalinaHasBeenShotDown; }
void CHeli::ActivateHeli(bool activate) { ScriptHeliOn = activate; }
+#include <new>
class CHeli_ : public CHeli
{
diff --git a/src/vehicles/Plane.cpp b/src/vehicles/Plane.cpp
index b4d80581..c2b9e493 100644
--- a/src/vehicles/Plane.cpp
+++ b/src/vehicles/Plane.cpp
@@ -7,6 +7,8 @@
#include "Streaming.h"
#include "Replay.h"
#include "Camera.h"
+#include "DMAudio.h"
+#include "Wanted.h"
#include "Coronas.h"
#include "Particle.h"
#include "Explosion.h"
@@ -964,6 +966,7 @@ bool CPlane::HasCesnaLanded(void) { return CesnaMissionStatus == CESNA_STATUS_LA
bool CPlane::HasCesnaBeenDestroyed(void) { return CesnaMissionStatus == CESNA_STATUS_DESTROYED; }
bool CPlane::HasDropOffCesnaBeenShotDown(void) { return DropOffCesnaMissionStatus == CESNA_STATUS_DESTROYED; }
+#include <new>
class CPlane_ : public CPlane
{
diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp
index 1c73ed05..7d81fd57 100644
--- a/src/vehicles/Train.cpp
+++ b/src/vehicles/Train.cpp
@@ -10,6 +10,7 @@
#include "Coronas.h"
#include "World.h"
#include "Ped.h"
+#include "DMAudio.h"
#include "HandlingMgr.h"
#include "Train.h"
@@ -691,6 +692,8 @@ CTrain::UpdateTrains(void)
}
}
+#include <new>
+
class CTrain_ : public CTrain
{
public:
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index 90848d6c..adeba19e 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -16,6 +16,8 @@
#include "Renderer.h"
#include "DMAudio.h"
#include "Radar.h"
+#include "Fire.h"
+#include "Darkel.h"
bool &CVehicle::bWheelsOnlyCheat = *(bool *)0x95CD78;
bool &CVehicle::bAllDodosCheat = *(bool *)0x95CD75;
@@ -29,9 +31,17 @@ void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehicleP
void CVehicle::operator delete(void *p, size_t sz) { CPools::GetVehiclePool()->Delete((CVehicle*)p); }
void CVehicle::operator delete(void *p, int handle) { CPools::GetVehiclePool()->Delete((CVehicle*)p); }
-WRAPPER bool CVehicle::ShufflePassengersToMakeSpace(void) { EAXJMP(0x5528A0); }
-// or Weapon.cpp?
-WRAPPER void FireOneInstantHitRound(CVector *shotSource, CVector *shotTarget, int32 damage) { EAXJMP(0x563B00); }
+#ifdef FIX_BUGS
+// I think they meant that
+#define DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE (MYRAND_MAX * 35 / 100)
+#define DAMAGE_FLEE_ON_FOOT_PROBABILITY_VALUE (MYRAND_MAX * 70 / 100)
+#else
+#define DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE (35000)
+#define DAMAGE_FLEE_ON_FOOT_PROBABILITY_VALUE (70000)
+#endif
+#define DAMAGE_HEALTH_TO_FLEE_ALWAYS (200.0f)
+#define DAMAGE_HEALTH_TO_CATCH_FIRE (250.0f)
+
CVehicle::CVehicle(uint8 CreatedBy)
{
@@ -359,6 +369,119 @@ CVehicle::ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVec
}
void
+CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage)
+{
+ if (!bCanBeDamaged)
+ return;
+ if (bOnlyDamagedByPlayer && (damagedBy != FindPlayerPed() && damagedBy != FindPlayerVehicle()))
+ return;
+ bool bFrightensDriver = false;
+ switch (weaponType) {
+ case WEAPONTYPE_UNARMED:
+ case WEAPONTYPE_BASEBALLBAT:
+ if (bMeleeProof)
+ return;
+ break;
+ case WEAPONTYPE_COLT45:
+ case WEAPONTYPE_UZI:
+ case WEAPONTYPE_SHOTGUN:
+ case WEAPONTYPE_AK47:
+ case WEAPONTYPE_M16:
+ case WEAPONTYPE_SNIPERRIFLE:
+ case WEAPONTYPE_TOTAL_INVENTORY_WEAPONS:
+ case WEAPONTYPE_UZI_DRIVEBY:
+ if (bBulletProof)
+ return;
+ bFrightensDriver = true;
+ break;
+ case WEAPONTYPE_ROCKETLAUNCHER:
+ case WEAPONTYPE_MOLOTOV:
+ case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_EXPLOSION:
+ if (bExplosionProof)
+ return;
+ bFrightensDriver = true;
+ break;
+ case WEAPONTYPE_FLAMETHROWER:
+ if (bFireProof)
+ return;
+ break;
+ case WEAPONTYPE_RAMMEDBYCAR:
+ if (bCollisionProof)
+ return;
+ break;
+ default:
+ break;
+ }
+ if (m_fHealth > 0.0f) {
+ if (VehicleCreatedBy == RANDOM_VEHICLE && pDriver &&
+ (m_status == STATUS_SIMPLE || m_status == STATUS_PHYSICS) &&
+ AutoPilot.m_nCarMission == MISSION_CRUISE) {
+ if (m_randomSeed < DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE) {
+ CCarCtrl::SwitchVehicleToRealPhysics(this);
+ AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * pHandling->Transmission.fUnkMaxVelocity;
+ m_status = STATUS_PHYSICS;
+ }
+ }
+ m_nLastWeaponDamage = weaponType;
+ float oldHealth = m_fHealth;
+ if (m_fHealth > damage) {
+ m_fHealth -= damage;
+ if (VehicleCreatedBy == RANDOM_VEHICLE &&
+ (m_fHealth < DAMAGE_HEALTH_TO_FLEE_ALWAYS ||
+ bFrightensDriver && m_randomSeed > DAMAGE_FLEE_ON_FOOT_PROBABILITY_VALUE)) {
+ switch (m_status) {
+ case STATUS_SIMPLE:
+ case STATUS_PHYSICS:
+ if (pDriver) {
+ m_status = STATUS_ABANDONED;
+ pDriver->bFleeAfterExitingCar = true;
+ pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this);
+ }
+ for (int i = 0; i < m_nNumMaxPassengers; i++) {
+ if (pPassengers[i]) {
+ pPassengers[i]->bFleeAfterExitingCar = true;
+ pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (oldHealth > DAMAGE_HEALTH_TO_CATCH_FIRE && m_fHealth < DAMAGE_HEALTH_TO_CATCH_FIRE) {
+ if (IsCar()) {
+ CAutomobile* pThisCar = (CAutomobile*)this;
+ pThisCar->Damage.SetEngineStatus(ENGINE_STATUS_ON_FIRE);
+ pThisCar->m_pSetOnFireEntity = damagedBy;
+ if (damagedBy)
+ damagedBy->RegisterReference((CEntity**)&pThisCar->m_pSetOnFireEntity);
+ }
+ }
+ }
+ else {
+ m_fHealth = 0.0f;
+ if (weaponType == WEAPONTYPE_EXPLOSION) {
+ // between 1000 and 3047. Also not very nice: can't be saved by respray or cheat
+ m_nBombTimer = 1000 + CGeneral::GetRandomNumber() & 0x7FF;
+ m_pBlowUpEntity = damagedBy;
+ if (damagedBy)
+ damagedBy->RegisterReference((CEntity**)&m_pBlowUpEntity);
+ }
+ else
+ BlowUpCar(damagedBy);
+ }
+ }
+#ifdef FIX_BUGS // removing dumb case when shooting police car in player's own garage gives wanted level
+ if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed() && !bHasBeenOwnedByPlayer)
+#else
+ if (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed())
+#endif
+ FindPlayerPed()->SetWantedLevelNoDrop(1);
+}
+
+void
CVehicle::ExtinguishCarFire(void)
{
m_fHealth = max(m_fHealth, 300.0f);
@@ -372,6 +495,65 @@ CVehicle::ExtinguishCarFire(void)
}
}
+bool
+CVehicle::ShufflePassengersToMakeSpace(void)
+{
+ if (m_nNumPassengers >= m_nNumMaxPassengers)
+ return false;
+ if (pPassengers[1] &&
+ !(m_nGettingInFlags & CAR_DOOR_FLAG_LR) &&
+ IsRoomForPedToLeaveCar(COMPONENT_DOOR_REAR_LEFT, nil)) {
+ if (!pPassengers[2] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RR)) {
+ pPassengers[2] = pPassengers[1];
+ pPassengers[1] = nil;
+ pPassengers[2]->m_vehEnterType = CAR_DOOR_RR;
+ return true;
+ }
+ if (!pPassengers[0] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RF)) {
+ pPassengers[0] = pPassengers[1];
+ pPassengers[1] = nil;
+ pPassengers[0]->m_vehEnterType = CAR_DOOR_RF;
+ return true;
+ }
+ return false;
+ }
+ if (pPassengers[2] &&
+ !(m_nGettingInFlags & CAR_DOOR_FLAG_RR) &&
+ IsRoomForPedToLeaveCar(COMPONENT_DOOR_REAR_RIGHT, nil)) {
+ if (!pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR)) {
+ pPassengers[1] = pPassengers[2];
+ pPassengers[2] = nil;
+ pPassengers[1]->m_vehEnterType = CAR_DOOR_LR;
+ return true;
+ }
+ if (!pPassengers[0] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RF)) {
+ pPassengers[0] = pPassengers[2];
+ pPassengers[2] = nil;
+ pPassengers[0]->m_vehEnterType = CAR_DOOR_RF;
+ return true;
+ }
+ return false;
+ }
+ if (pPassengers[0] &&
+ !(m_nGettingInFlags & CAR_DOOR_FLAG_RF) &&
+ IsRoomForPedToLeaveCar(COMPONENT_DOOR_FRONT_RIGHT, nil)) {
+ if (!pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR)) {
+ pPassengers[1] = pPassengers[0];
+ pPassengers[0] = nil;
+ pPassengers[1]->m_vehEnterType = CAR_DOOR_LR;
+ return true;
+ }
+ if (!pPassengers[2] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RR)) {
+ pPassengers[2] = pPassengers[0];
+ pPassengers[0] = nil;
+ pPassengers[2]->m_vehEnterType = CAR_DOOR_RR;
+ return true;
+ }
+ return false;
+ }
+ return false;
+}
+
void
CVehicle::ProcessDelayedExplosion(void)
{
@@ -763,6 +945,29 @@ CVehicle::IsSphereTouchingVehicle(float sx, float sy, float sz, float radius)
return true;
}
+void
+DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle)
+{
+ if (pVehicle->pDriver) {
+#ifndef FIX_BUGS
+ // this just isn't fair
+ CDarkel::RegisterKillByPlayer(pVehicle->pDriver, WEAPONTYPE_UNIDENTIFIED);
+#endif
+ pVehicle->pDriver->FlagToDestroyWhenNextProcessed();
+ }
+ for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {
+ if (pVehicle->pPassengers[i]) {
+#ifndef FIX_BUGS
+ // this just isn't fair
+ CDarkel::RegisterKillByPlayer(pVehicle->pPassengers[i], WEAPONTYPE_UNIDENTIFIED);
+#endif
+ pVehicle->pPassengers[i]->FlagToDestroyWhenNextProcessed();
+ }
+ }
+ CWorld::Remove(pVehicle);
+ delete pVehicle;
+}
+
class CVehicle_ : public CVehicle
{
@@ -805,4 +1010,5 @@ STARTPATCHES
InjectHook(0x551EB0, &CVehicle::RemovePassenger, PATCH_JUMP);
InjectHook(0x5525A0, &CVehicle::ProcessCarAlarm, PATCH_JUMP);
InjectHook(0x552620, &CVehicle::IsSphereTouchingVehicle, PATCH_JUMP);
+ InjectHook(0x551950, &CVehicle::InflictDamage, PATCH_JUMP);
ENDPATCHES
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index bd8df694..4639f3e1 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -4,6 +4,7 @@
#include "AutoPilot.h"
#include "ModelIndices.h"
#include "AnimManager.h"
+#include "Weapon.h"
class CPed;
class CFire;
@@ -266,6 +267,7 @@ public:
void ProcessCarAlarm(void);
bool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius);
bool ShufflePassengersToMakeSpace(void);
+ void InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage);
bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; }
CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); }
@@ -300,3 +302,5 @@ public:
};
static_assert(sizeof(cVehicleParams) == 0x18, "cVehicleParams: error");
+
+void DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle);