summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraap <aap@papnet.eu>2020-05-24 15:14:27 +0200
committeraap <aap@papnet.eu>2020-05-25 18:33:34 +0200
commit7bf833785411955c2bcf35ed55e9d206facbc575 (patch)
treea69383e116ca35a5c6ac14e40a462d29b8b46c87
parenthow did saving even work in original III? (diff)
downloadre3-7bf833785411955c2bcf35ed55e9d206facbc575.tar
re3-7bf833785411955c2bcf35ed55e9d206facbc575.tar.gz
re3-7bf833785411955c2bcf35ed55e9d206facbc575.tar.bz2
re3-7bf833785411955c2bcf35ed55e9d206facbc575.tar.lz
re3-7bf833785411955c2bcf35ed55e9d206facbc575.tar.xz
re3-7bf833785411955c2bcf35ed55e9d206facbc575.tar.zst
re3-7bf833785411955c2bcf35ed55e9d206facbc575.zip
-rw-r--r--src/control/CarCtrl.cpp2
-rw-r--r--src/control/RoadBlocks.cpp4
-rw-r--r--src/control/RoadBlocks.h2
-rw-r--r--src/control/Script.cpp4
-rw-r--r--src/control/TrafficLights.cpp2
-rw-r--r--src/core/Camera.cpp12
-rw-r--r--src/core/Camera.h5
-rw-r--r--src/core/Collision.cpp9
-rw-r--r--src/core/Collision.h6
-rw-r--r--src/core/PlayerInfo.h1
-rw-r--r--src/core/World.cpp62
-rw-r--r--src/core/World.h7
-rw-r--r--src/core/re3.cpp10
-rw-r--r--src/entities/Entity.cpp2
-rw-r--r--src/math/Vector2D.h4
-rw-r--r--src/math/math.cpp13
-rw-r--r--src/modelinfo/ModelIndices.h3
-rw-r--r--src/peds/Ped.cpp15
-rw-r--r--src/peds/Ped.h3
-rw-r--r--src/render/Coronas.cpp6
-rw-r--r--src/render/Shadows.cpp8
-rw-r--r--src/render/Skidmarks.cpp4
-rw-r--r--src/render/SpecialFX.cpp1
-rw-r--r--src/render/SpecialFX.h2
-rw-r--r--src/render/Timecycle.cpp2
-rw-r--r--src/render/Timecycle.h2
-rw-r--r--src/render/Weather.cpp6
-rw-r--r--src/vehicles/Automobile.cpp73
-rw-r--r--src/vehicles/Automobile.h5
-rw-r--r--src/vehicles/Heli.cpp54
-rw-r--r--src/vehicles/Vehicle.cpp1481
-rw-r--r--src/vehicles/Vehicle.h72
-rw-r--r--src/weapons/Weapon.cpp4
33 files changed, 1448 insertions, 438 deletions
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index 073195a4..1004e5de 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -913,7 +913,7 @@ CCarCtrl::RemoveDistantCars()
PossiblyRemoveVehicle(pVehicle);
if (pVehicle->bCreateRoadBlockPeds){
if ((pVehicle->GetPosition() - FindPlayerCentreOfWorld(CWorld::PlayerInFocus)).Magnitude2D() < DISTANCE_TO_SPAWN_ROADBLOCK_PEDS) {
- CRoadBlocks::GenerateRoadBlockCopsForCar(pVehicle, pVehicle->m_nRoadblockType, pVehicle->m_nRoadblockNode);
+ CRoadBlocks::GenerateRoadBlockCopsForCar(pVehicle, pVehicle->m_nRoadblockType);
pVehicle->bCreateRoadBlockPeds = false;
}
}
diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp
index 0261cd4a..a26e19f5 100644
--- a/src/control/RoadBlocks.cpp
+++ b/src/control/RoadBlocks.cpp
@@ -47,7 +47,7 @@ CRoadBlocks::Init(void)
}
void
-CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode)
+CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType)
{
static const CVector vecRoadBlockOffets[6] = { {-1.5, 1.8f, 0.0f}, {-1.5f, -1.8f, 0.0f}, {1.5f, 1.8f, 0.0f},
{1.5f, -1.8f, 0.0f}, {-1.5f, 0.0f, 0.0f}, {1.5, 0.0, 0.0} };
@@ -90,7 +90,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType
pCopPed->SetIdle();
pCopPed->bKindaStayInSamePlace = true;
pCopPed->bNotAllowedToDuck = false;
- pCopPed->m_nRoadblockNode = roadBlockNode;
+// pCopPed->m_nRoadblockNode = roadBlockNode;
pCopPed->bCrouchWhenShooting = roadBlockType != 2;
if (pEntityToAttack) {
pCopPed->m_pPointGunAt = pEntityToAttack;
diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h
index 439fd6e7..c8469ba5 100644
--- a/src/control/RoadBlocks.h
+++ b/src/control/RoadBlocks.h
@@ -15,6 +15,6 @@ public:
static bool InOrOut[NUMROADBLOCKS];
static void Init(void);
- static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode);
+ static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType);
static void GenerateRoadBlocks(void);
};
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index cf2545c0..abcb29bc 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -10943,10 +10943,10 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
ScriptParams[1] = 0;
else if (ScriptParams[1] == 3)
ScriptParams[1] = 1;
- pVehicle->BurstTyre(ScriptParams[1]); // TODO(MIAMI): second param is true
+ pVehicle->BurstTyre(ScriptParams[1], true);
}
else {
- pVehicle->BurstTyre(ScriptParams[1]); // TODO(MIAMI): second param is true
+ pVehicle->BurstTyre(ScriptParams[1], true);
}
return 0;
}
diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp
index 8487847f..54c97d06 100644
--- a/src/control/TrafficLights.cpp
+++ b/src/control/TrafficLights.cpp
@@ -108,6 +108,7 @@ CTrafficLights::DisplayActualLight(CEntity *ent)
CBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
CBrightLights::RegisterOne(pos2, ent->GetUp(), -ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
+/*
static const float top = -0.127f;
static const float bot = -0.539f;
static const float mid = bot + (top-bot)/3.0f;
@@ -131,6 +132,7 @@ CTrafficLights::DisplayActualLight(CEntity *ent)
1.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f,
SHINYTEXT_WALK, 255, 255, 255, 60.0f);
}
+*/
}
void
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 3b7bdbaf..f618c652 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -3281,6 +3281,18 @@ CCamera::Find3rdPersonQuickAimPitch(void)
return -(DEGTORAD(((0.5f - m_f3rdPersonCHairMultY) * 1.8f * 0.5f * Cams[ActiveCam].FOV)) + rot);
}
+bool
+CCamera::Using1stPersonWeaponMode(void)
+{
+ switch(PlayerWeaponMode.Mode)
+ case CCam::MODE_SNIPER:
+ case CCam::MODE_M16_1STPERSON:
+ case CCam::MODE_ROCKETLAUNCHER:
+ case CCam::MODE_HELICANNON_1STPERSON:
+ case CCam::MODE_CAMERA:
+ return true;
+ return false;
+}
void
diff --git a/src/core/Camera.h b/src/core/Camera.h
index 135f9d8f..4e90855b 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -91,7 +91,9 @@ public:
MODE_M16_1STPERSON_RUNABOUT,
MODE_FIGHT_CAM_RUNABOUT,
MODE_EDITOR,
- MODE_HELICANNON_1STPERSON, // vice city leftover
+ MODE_HELICANNON_1STPERSON,
+ MODE_45,
+ MODE_CAMERA,
};
bool bBelowMinDist; //used for follow ped mode
@@ -625,6 +627,7 @@ public:
void UpdateAimingCoors(CVector const &coors);
void Find3rdPersonCamTargetVector(float dist, CVector pos, CVector &source, CVector &target);
float Find3rdPersonQuickAimPitch(void);
+ bool Using1stPersonWeaponMode(void);
// Physical camera
void SetRwCamera(RwCamera *cam);
diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp
index c29c1d28..d2e08f7c 100644
--- a/src/core/Collision.cpp
+++ b/src/core/Collision.cpp
@@ -414,8 +414,9 @@ CCollision::TestSphereTriangle(const CColSphere &sphere,
return dist < sphere.radius;
}
+//--MIAMI: TODO
bool
-CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough)
+CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough)
{
static CMatrix matTransform;
int i;
@@ -1042,10 +1043,11 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere,
return true;
}
+//--MIAMI: TODO
bool
CCollision::ProcessLineOfSight(const CColLine &line,
const CMatrix &matrix, CColModel &model,
- CColPoint &point, float &mindist, bool ignoreSeeThrough)
+ CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough)
{
static CMatrix matTransform;
int i;
@@ -1081,10 +1083,11 @@ CCollision::ProcessLineOfSight(const CColLine &line,
return false;
}
+//--MIAMI: TODO
bool
CCollision::ProcessVerticalLine(const CColLine &line,
const CMatrix &matrix, CColModel &model,
- CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly)
+ CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly)
{
static CStoredCollPoly TempStoredPoly;
int i;
diff --git a/src/core/Collision.h b/src/core/Collision.h
index 4b0c2fb9..12af5225 100644
--- a/src/core/Collision.h
+++ b/src/core/Collision.h
@@ -151,7 +151,7 @@ public:
static bool TestLineTriangle(const CColLine &line, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
static bool TestSphereTriangle(const CColSphere &sphere, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
- static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough);
+ static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough);
static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq);
static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq);
@@ -160,8 +160,8 @@ public:
static bool ProcessLineTriangle(const CColLine &line , const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist);
static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);
static bool ProcessSphereTriangle(const CColSphere &sph, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
- static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough);
- static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly);
+ static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough);
+ static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly);
static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);
static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);
diff --git a/src/core/PlayerInfo.h b/src/core/PlayerInfo.h
index 119f0b2c..e2e874e6 100644
--- a/src/core/PlayerInfo.h
+++ b/src/core/PlayerInfo.h
@@ -51,6 +51,7 @@ public:
int32 field_268;
int32 field_272;
uint32 m_nHavocLevel;
+ float m_fMediaAttention;
bool m_bInfiniteSprint;
bool m_bFastReload;
bool m_bFireproof;
diff --git a/src/core/World.cpp b/src/core/World.cpp
index 433f9745..06108c5c 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -33,22 +33,24 @@
CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS];
-CPtrList CWorld::ms_bigBuildingsList[4];// = (CPtrList*)0x6FAB60;
-CPtrList CWorld::ms_listMovingEntityPtrs;// = *(CPtrList*)0x8F433C;
-CSector CWorld::ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X];// = (CSector (*)[NUMSECTORS_Y])0x665608;
-uint16 CWorld::ms_nCurrentScanCode;// = *(uint16*)0x95CC64;
+CPtrList CWorld::ms_bigBuildingsList[4];
+CPtrList CWorld::ms_listMovingEntityPtrs;
+CSector CWorld::ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X];
+uint16 CWorld::ms_nCurrentScanCode;
-uint8 CWorld::PlayerInFocus;// = *(uint8 *)0x95CD61;
+uint8 CWorld::PlayerInFocus;
CPlayerInfo CWorld::Players[NUMPLAYERS];
-bool CWorld::bNoMoreCollisionTorque;// = *(bool*)0x95CDCC;
-CEntity *CWorld::pIgnoreEntity;// = *(CEntity**)0x8F6494;
-bool CWorld::bIncludeDeadPeds;// = *(bool*)0x95CD8F;
-bool CWorld::bSecondShift;// = *(bool*)0x95CD54;
-bool CWorld::bForceProcessControl;// = *(bool*)0x95CD6C;
-bool CWorld::bProcessCutsceneOnly;// = *(bool*)0x95CD8B;
+bool CWorld::bNoMoreCollisionTorque;
+CEntity *CWorld::pIgnoreEntity;
+bool CWorld::bIncludeDeadPeds;
+bool CWorld::bSecondShift;
+bool CWorld::bForceProcessControl;
+bool CWorld::bProcessCutsceneOnly;
-bool CWorld::bDoingCarCollisions;// = *(bool*)0x95CD8C;
-bool CWorld::bIncludeCarTyres;// = *(bool*)0x95CDAA;
+bool CWorld::bDoingCarCollisions;
+bool CWorld::bIncludeCarTyres;
+
+CColPoint CWorld::m_aTempColPts[MAX_COLLISION_POINTS];
void
CWorld::Initialise()
@@ -165,7 +167,7 @@ CWorld::CameraToIgnoreThisObject(CEntity *ent)
bool
CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity,
bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects,
- bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
+ bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough)
{
int x, xstart, xend;
int y, ystart, yend;
@@ -184,7 +186,7 @@ CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoi
#define LOSARGS \
CColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, \
- checkDummies, ignoreSeeThrough, ignoreSomeObjects
+ checkDummies, ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough
if(xstart == xend && ystart == yend) {
// Only one sector
@@ -266,7 +268,7 @@ CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoi
bool
CWorld::ProcessLineOfSightSector(CSector &sector, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity,
bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects,
- bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
+ bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough)
{
float mindist = dist;
bool deadPeds = !!bIncludeDeadPeds;
@@ -274,39 +276,39 @@ CWorld::ProcessLineOfSightSector(CSector &sector, const CColLine &line, CColPoin
if(checkBuildings) {
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity,
- ignoreSeeThrough);
+ ignoreSeeThrough, false, ignoreShootThrough);
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity,
- ignoreSeeThrough);
+ ignoreSeeThrough, false, ignoreShootThrough);
}
if(checkVehicles) {
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity,
- ignoreSeeThrough);
+ ignoreSeeThrough, false, ignoreShootThrough);
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity,
- ignoreSeeThrough);
+ ignoreSeeThrough, false, ignoreShootThrough);
}
if(checkPeds) {
if(deadPeds) bIncludeDeadPeds = true;
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity,
- ignoreSeeThrough);
+ ignoreSeeThrough, false, ignoreShootThrough);
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity,
- ignoreSeeThrough);
+ ignoreSeeThrough, false, ignoreShootThrough);
bIncludeDeadPeds = false;
}
if(checkObjects) {
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity,
- ignoreSeeThrough, ignoreSomeObjects);
+ ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough);
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity,
- ignoreSeeThrough, ignoreSomeObjects);
+ ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough);
}
if(checkDummies) {
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity,
- ignoreSeeThrough);
+ ignoreSeeThrough, false, ignoreShootThrough);
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity,
- ignoreSeeThrough);
+ ignoreSeeThrough, false, ignoreShootThrough);
}
bIncludeDeadPeds = deadPeds;
@@ -320,7 +322,7 @@ CWorld::ProcessLineOfSightSector(CSector &sector, const CColLine &line, CColPoin
bool
CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist,
- CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects)
+ CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough)
{
bool deadPeds = false;
float mindist = dist;
@@ -347,7 +349,7 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
if(colmodel && CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, dist,
- ignoreSeeThrough))
+ ignoreSeeThrough, ignoreShootThrough))
entity = e;
}
}
@@ -436,7 +438,7 @@ CWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CCol
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, dist,
- ignoreSeeThrough, poly))
+ ignoreSeeThrough, false, poly))
entity = e;
}
}
@@ -637,7 +639,7 @@ CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bo
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
- if(CCollision::TestLineOfSight(line, e->GetMatrix(), *colmodel, ignoreSeeThrough))
+ if(CCollision::TestLineOfSight(line, e->GetMatrix(), *colmodel, ignoreSeeThrough, false))
return false;
}
}
diff --git a/src/core/World.h b/src/core/World.h
index 89f05cfd..3da774ba 100644
--- a/src/core/World.h
+++ b/src/core/World.h
@@ -71,6 +71,7 @@ public:
static bool bProcessCutsceneOnly;
static bool bDoingCarCollisions;
static bool bIncludeCarTyres;
+ static CColPoint m_aTempColPts[MAX_COLLISION_POINTS];
static void Remove(CEntity *entity);
static void Add(CEntity *entity);
@@ -90,9 +91,9 @@ public:
static bool CameraToIgnoreThisObject(CEntity *ent);
- static bool ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
- static bool ProcessLineOfSightSector(CSector &sector, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
- static bool ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
+ static bool ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false, bool ignoreShootThrough = false);
+ static bool ProcessLineOfSightSector(CSector &sector, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough);
+ static bool ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough);
static bool ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly);
static bool ProcessVerticalLineSector(CSector &sector, const CColLine &line, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly);
static bool ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly);
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index 8f808b61..a74e5ffa 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -273,7 +273,7 @@ DebugMenuPopulate(void)
{
if(1){
static const char *weathers[] = {
- "Sunny", "Cloudy", "Rainy", "Foggy"
+ "Sunny", "Cloudy", "Rainy", "Foggy", "Extrasunny", "Stormy"
};
DebugMenuEntry *e;
e = DebugMenuAddVar("Time & Weather", "Current Hour", &CClock::GetHoursRef(), nil, 1, 0, 23, nil);
@@ -281,9 +281,9 @@ DebugMenuPopulate(void)
e = DebugMenuAddVar("Time & Weather", "Current Minute", &CClock::GetMinutesRef(),
[](){ CWeather::InterpolationValue = CClock::GetMinutes()/60.0f; }, 1, 0, 59, nil);
DebugMenuEntrySetWrap(e, true);
- e = DebugMenuAddVar("Time & Weather", "Old Weather", (int16*)&CWeather::OldWeatherType, nil, 1, 0, 3, weathers);
+ e = DebugMenuAddVar("Time & Weather", "Old Weather", (int16*)&CWeather::OldWeatherType, nil, 1, 0, 5, weathers);
DebugMenuEntrySetWrap(e, true);
- e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 3, weathers);
+ e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 5, weathers);
DebugMenuEntrySetWrap(e, true);
DebugMenuAddVar("Time & Weather", "Wind", (float*)&CWeather::Wind, nil, 0.1f, 0.0f, 1.0f);
DebugMenuAddVar("Time & Weather", "Time scale", (float*)&CTimer::GetTimeScale(), nil, 0.1f, 0.0f, 10.0f);
@@ -337,7 +337,11 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Spawn", "Spawn Banshee", [](){ SpawnCar(MI_BANSHEE); });
DebugMenuAddCmd("Spawn", "Spawn Cuban", [](){ SpawnCar(MI_CUBAN); });
DebugMenuAddCmd("Spawn", "Spawn Voodoo", [](){ SpawnCar(MI_VOODOO); });
+ DebugMenuAddCmd("Spawn", "Spawn Maverick", [](){ SpawnCar(MI_MAVERICK); });
+ DebugMenuAddCmd("Spawn", "Spawn VCN Maverick", [](){ SpawnCar(MI_VCNMAV); });
DebugMenuAddCmd("Spawn", "Spawn Sparrow", [](){ SpawnCar(MI_SPARROW); });
+ DebugMenuAddCmd("Spawn", "Spawn Sea Sparrow", [](){ SpawnCar(MI_SEASPAR); });
+ DebugMenuAddCmd("Spawn", "Spawn Hunter", [](){ SpawnCar(MI_HUNTER); });
DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); });
DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); });
DebugMenuAddCmd("Spawn", "Spawn Predator", [](){ SpawnCar(MI_PREDATOR); });
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index a0c5c484..68486a3c 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -910,7 +910,7 @@ CEntity::ProcessLightsForEntity(void)
camDir *= 2.0f/dist;
glareDir += camDir;
glareDir.Normalise();
- float camAngle = -DotProduct(glareDir, CTimeCycle::GetSunPosition());
+ float camAngle = -DotProduct(glareDir, CTimeCycle::GetSunDirection());
if(camAngle > 0.0f){
float intens = Sqrt(camAngle) * CWeather::SunGlare;
pos += camDir;
diff --git a/src/math/Vector2D.h b/src/math/Vector2D.h
index 0885a5d2..7bfccae6 100644
--- a/src/math/Vector2D.h
+++ b/src/math/Vector2D.h
@@ -11,9 +11,7 @@ public:
float Magnitude(void) const { return Sqrt(x*x + y*y); }
float MagnitudeSqr(void) const { return x*x + y*y; }
- void Normalise(void);
-
- void NormaliseSafe(void) {
+ void Normalise(void) {
float sq = MagnitudeSqr();
if(sq > 0.0f){
float invsqrt = RecipSqrt(sq);
diff --git a/src/math/math.cpp b/src/math/math.cpp
index eeb9d3fa..e11d048c 100644
--- a/src/math/math.cpp
+++ b/src/math/math.cpp
@@ -5,19 +5,6 @@
// TODO: move more stuff into here
void
-CVector2D::Normalise(void)
-{
- float sq = MagnitudeSqr();
- assert(sq != 0.0f); // just be safe here
- //if(sq > 0.0f){
- float invsqrt = RecipSqrt(sq);
- x *= invsqrt;
- y *= invsqrt;
- //}else
- // x = 1.0f;
-}
-
-void
CMatrix::SetRotate(float xAngle, float yAngle, float zAngle)
{
float cX = Cos(xAngle);
diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h
index 91ba650e..e7285b2f 100644
--- a/src/modelinfo/ModelIndices.h
+++ b/src/modelinfo/ModelIndices.h
@@ -302,7 +302,8 @@ enum
MI_TRAIN = -1,
MI_DODO = -2,
- MI_NIGHTSTICK = 262,
+ MI_GOLFCLUB = 261,
+ MI_NIGHTSTICK,
MI_KNIFE,
MI_BASEBALL_BAT,
MI_GRENADE = 270,
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 7eb2491b..647ecef6 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -66,7 +66,7 @@
CPed *gapTempPedList[50];
uint16 gnNumTempPedList;
-CColPoint aTempPedColPts[MAX_COLLISION_POINTS];
+static CColPoint aTempPedColPts[MAX_COLLISION_POINTS];
// TODO(Miami)
#define AUDIO_NOT_READY
@@ -4558,7 +4558,8 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi
m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;
m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;
}
- if (m_pMyVehicle->CanPedExitCar()) {
+// TODO(MIAMI): argument
+ if (m_pMyVehicle->CanPedExitCar(false)) {
SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle);
} else {
m_fHealth = 0.0f;
@@ -13372,7 +13373,8 @@ CPed::ProcessObjective(void)
} else {
bool targetHasVeh = m_pedInObjective->bInVehicle;
if (!targetHasVeh
- || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar()) {
+// TODO(MIAMI): argument
+ || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar(false)) {
m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
SetObjective(OBJECTIVE_LEAVE_VEHICLE, m_pMyVehicle);
@@ -15427,13 +15429,13 @@ CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
}
float minDist = 1.0f;
belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,
- intersectionPoint, minDist, false, &m_collPoly);
+ intersectionPoint, minDist, false, false, &m_collPoly);
if (collidedWithBoat && bWasStanding && !belowTorsoCollided) {
ourLine.p0.z = ourLine.p1.z;
ourLine.p1.z = ourLine.p1.z + gravityEffect;
belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,
- intersectionPoint, minDist, false, &m_collPoly);
+ intersectionPoint, minDist, false, false, &m_collPoly);
}
if (belowTorsoCollided) {
#ifndef VC_PED_PORTS
@@ -16151,7 +16153,8 @@ CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)
uint32 optedDoorNode = wantedDoorNode;
bool teleportNeeded = false;
bool isLow = !!veh->bLowVehicle;
- if (!veh->CanPedExitCar()) {
+// TODO(MIAMI): argument
+ if (!veh->CanPedExitCar(false)) {
if (veh->pDriver && !veh->pDriver->IsPlayer()) {
veh->AutoPilot.m_nCruiseSpeed = 0;
veh->AutoPilot.m_nCarMission = MISSION_NONE;
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 776aa1dd..155e6cea 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -447,7 +447,7 @@ public:
uint32 bIsDrowning : 1;
uint32 bDrownsInWater : 1;
//uint32 b156_4
- //uint32 b156_8
+ uint32 b156_8 : 1;
uint32 bIsPlayerFriend : 1;
#ifdef VC_PED_PORTS
uint32 bHeadStuckInCollision : 1;
@@ -864,6 +864,7 @@ public:
static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg);
bool IsPlayer(void);
+ bool IsFemale(void) { return m_nPedType == PEDTYPE_CIVFEMALE || m_nPedType == PEDTYPE_PROSTITUTE; }
bool UseGroundColModel(void);
bool CanSetPedState(void);
bool IsPedInControl(void);
diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp
index 8e832ab1..efe486fe 100644
--- a/src/render/Coronas.cpp
+++ b/src/render/Coronas.cpp
@@ -509,18 +509,18 @@ CCoronas::DoSunAndMoon(void)
{
// yeah, moon is done somewhere else....
- CVector sunCoors = CTimeCycle::GetSunPosition();
+ CVector sunCoors = CTimeCycle::GetSunDirection();
sunCoors *= 150.0f;
sunCoors += TheCamera.GetPosition();
- if(CTimeCycle::GetSunPosition().z > -0.2f){
+ if(CTimeCycle::GetSunDirection().z > -0.2f){
float size = ((CGeneral::GetRandomNumber()&0xFF) * 0.005f + 10.0f) * CTimeCycle::GetSunSize();
RegisterCorona(SUN_CORE,
CTimeCycle::GetSunCoreRed(), CTimeCycle::GetSunCoreGreen(), CTimeCycle::GetSunCoreBlue(),
255, sunCoors, size,
999999.88f, TYPE_STAR, FLARE_NONE, REFLECTION_OFF, LOSCHECK_OFF, STREAK_OFF, 0.0f);
- if(CTimeCycle::GetSunPosition().z > 0.0f)
+ if(CTimeCycle::GetSunDirection().z > 0.0f)
RegisterCorona(SUN_CORONA,
CTimeCycle::GetSunCoronaRed(), CTimeCycle::GetSunCoronaGreen(), CTimeCycle::GetSunCoronaBlue(),
255, sunCoors, 25.0f * CTimeCycle::GetSunSize(),
diff --git a/src/render/Shadows.cpp b/src/render/Shadows.cpp
index c512f35c..fac35aeb 100644
--- a/src/render/Shadows.cpp
+++ b/src/render/Shadows.cpp
@@ -643,12 +643,12 @@ CShadows::StoreShadowForPole(CEntity *pPole, float fOffsetX, float fOffsetY, flo
PolePos.y += fOffsetX * pPole->GetRight().y + fOffsetY * pPole->GetForward().y;
PolePos.z += fOffsetZ;
- PolePos.x += -CTimeCycle::GetSunPosition().x * (fPoleHeight / 2);
- PolePos.y += -CTimeCycle::GetSunPosition().y * (fPoleHeight / 2);
+ PolePos.x += -CTimeCycle::GetSunDirection().x * (fPoleHeight / 2);
+ PolePos.y += -CTimeCycle::GetSunDirection().y * (fPoleHeight / 2);
StoreStaticShadow((uintptr)pPole + nID + _TODOCONST(51), SHADOWTYPE_DARK, gpPostShadowTex, &PolePos,
- -CTimeCycle::GetSunPosition().x * (fPoleHeight / 2),
- -CTimeCycle::GetSunPosition().y * (fPoleHeight / 2),
+ -CTimeCycle::GetSunDirection().x * (fPoleHeight / 2),
+ -CTimeCycle::GetSunDirection().y * (fPoleHeight / 2),
CTimeCycle::GetShadowSideX() * fPoleWidth,
CTimeCycle::GetShadowSideY() * fPoleWidth,
2 * (int32)((pPole->GetUp().z - 0.5f) * CTimeCycle::GetShadowStrength() * 2.0f) / 3,
diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp
index 7f057319..961c38a6 100644
--- a/src/render/Skidmarks.cpp
+++ b/src/render/Skidmarks.cpp
@@ -199,8 +199,8 @@ CSkidmarks::RegisterOne(uintptr id, CVector pos, float fwdX, float fwdY, bool *i
aSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos;
CVector2D dist = aSkidmarks[i].m_pos[aSkidmarks[i].m_last] - aSkidmarks[i].m_pos[aSkidmarks[i].m_last-1];
- dist.NormaliseSafe();
- fwd.NormaliseSafe();
+ dist.Normalise();
+ fwd.Normalise();
CVector2D right(dist.y, -dist.x);
float turn = DotProduct2D(fwd, right);
turn = Abs(turn) + 1.0f;
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index 7e08fbad..79ae21a5 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -28,6 +28,7 @@ RwImVertexIndex StreakIndexList[12];
RwIm3DVertex TraceVertices[6];
RwImVertexIndex TraceIndexList[12];
+bool CSpecialFX::bSnapShotActive;
void
CSpecialFX::Init(void)
diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h
index 2d9f18b1..7bc3750a 100644
--- a/src/render/SpecialFX.h
+++ b/src/render/SpecialFX.h
@@ -3,6 +3,8 @@
class CSpecialFX
{
public:
+ static bool bSnapShotActive;
+
static void Render(void);
static void Update(void);
static void Init(void);
diff --git a/src/render/Timecycle.cpp b/src/render/Timecycle.cpp
index c120c003..ab94f874 100644
--- a/src/render/Timecycle.cpp
+++ b/src/render/Timecycle.cpp
@@ -350,7 +350,7 @@ CTimeCycle::Update(void)
m_CurrentStoredValue = (m_CurrentStoredValue+1)&0xF;
float sunAngle = 2*PI*(CClock::GetSeconds()/60.0f + CClock::GetMinutes() + CClock::GetHours()*60)/(24*60);
- CVector &sunPos = GetSunPosition();
+ CVector &sunPos = GetSunDirection();
sunPos.x = Sin(sunAngle);
sunPos.y = 1.0f;
sunPos.z = 0.2f - Cos(sunAngle);
diff --git a/src/render/Timecycle.h b/src/render/Timecycle.h
index 2d873e6d..60c9e29f 100644
--- a/src/render/Timecycle.h
+++ b/src/render/Timecycle.h
@@ -180,7 +180,7 @@ public:
static void Initialise(void);
static void Update(void);
- static CVector &GetSunPosition(void) { return m_VectorToSun[m_CurrentStoredValue]; }
+ static CVector &GetSunDirection(void) { return m_VectorToSun[m_CurrentStoredValue]; }
static float GetShadowFrontX(void) { return m_fShadowFrontX[m_CurrentStoredValue]; }
static float GetShadowFrontY(void) { return m_fShadowFrontY[m_CurrentStoredValue]; }
static float GetShadowSideX(void) { return m_fShadowSideX[m_CurrentStoredValue]; }
diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp
index fc3e0d61..324c63ea 100644
--- a/src/render/Weather.cpp
+++ b/src/render/Weather.cpp
@@ -18,6 +18,7 @@
#include "Vehicle.h"
#include "World.h"
#include "ZoneCull.h"
+#include "SpecialFX.h"
int32 CWeather::SoundHandle = -1;
@@ -271,9 +272,10 @@ void CWeather::Update(void)
SunGlare += InterpolationValue;
if (SunGlare > 0.0f) {
- SunGlare *= Min(1.0f, 7.0 * CTimeCycle::GetSunPosition().z);
+ SunGlare *= Min(1.0f, 7.0 * CTimeCycle::GetSunDirection().z);
SunGlare = clamp(SunGlare, 0.0f, 1.0f);
- // TODO(MIAMI): if (CSpecialFX::bSnapShotActive)...
+ if (!CSpecialFX::bSnapShotActive)
+ SunGlare *= (1.0f - (CGeneral::GetRandomNumber()&0x1F)*0.007f);
}
Wind = InterpolationValue * Windiness[NewWeatherType] + (1.0f - InterpolationValue) * Windiness[OldWeatherType];
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index dc406237..364415e9 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -77,6 +77,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
SetModelIndex(id);
pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)mi->m_handlingId);
+ pFlyingHandling = mod_HandlingManager.GetFlyingPointer((eHandlingId)mi->m_handlingId);
field_49C = 20.0f;
field_4D8 = 0;
@@ -176,7 +177,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
m_nNumPassengers = 0;
m_bombType = CARBOMB_NONE;
- bHadDriver = false;
+ bDriverLastFrame = false;
m_pBombRigger = nil;
if(m_nDoorLock == CARLOCK_UNLOCKED &&
@@ -272,25 +273,14 @@ CAutomobile::ProcessControl(void)
}
// 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);
+ }
- 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;
+ ActivateBombWhenEntered();
// Process passengers
if(m_nNumPassengers != 0 && IsUpsideDown() && CanPedEnterCar()){
@@ -304,18 +294,7 @@ CAutomobile::ProcessControl(void)
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);
+ UpdateClumpAlpha();
AutoPilot.m_bSlowedDownBecauseOfCars = false;
AutoPilot.m_bSlowedDownBecauseOfPeds = false;
@@ -726,19 +705,8 @@ CAutomobile::ProcessControl(void)
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);
- }
- }
+ if(CPad::GetPad(0)->WeaponJustDown())
+ ActivateBomb();
}else if(strongGrip1 || CVehicle::bCheat3){
traction *= 1.2f;
acceleration *= 1.4f;
@@ -1934,6 +1902,8 @@ CAutomobile::PreRender(void)
}
CShadows::StoreShadowForCar(this);
+
+ DoSunGlare();
}
void
@@ -3939,7 +3909,7 @@ CAutomobile::SetUpWheelColModel(CColModel *colModel)
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);
+ colModel->spheres[4].Set(mi->m_wheelScale, mat.GetPosition(), SURFACE_TIRE, CAR_PIECE_WHEEL_LR);
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;
@@ -3949,9 +3919,8 @@ CAutomobile::SetUpWheelColModel(CColModel *colModel)
return true;
}
-// this probably isn't used in III yet
void
-CAutomobile::BurstTyre(uint8 wheel)
+CAutomobile::BurstTyre(uint8 wheel, bool applyForces)
{
switch(wheel){
case CAR_PIECE_WHEEL_LF: wheel = VEHWHEEL_FRONT_LEFT; break;
@@ -3969,8 +3938,10 @@ CAutomobile::BurstTyre(uint8 wheel)
CCarCtrl::SwitchVehicleToRealPhysics(this);
}
- ApplyMoveForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f));
- ApplyTurnForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f), GetForward());
+ if(applyForces){
+ ApplyMoveForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f));
+ ApplyTurnForce(GetRight() * CGeneral::GetRandomNumberInRange(-0.3f, 0.3f), GetForward());
+ }
}
}
@@ -4337,7 +4308,7 @@ GetCurrentAtomicObjectCB(RwObject *object, void *data)
return object;
}
-CColPoint spherepoints[MAX_COLLISION_POINTS];
+static CColPoint aTempPedColPts[MAX_COLLISION_POINTS];
CObject*
CAutomobile::SpawnFlyingComponent(int32 component, uint32 type)
@@ -4457,7 +4428,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type)
if(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(),
this->GetMatrix(), *this->GetColModel(),
- spherepoints, nil, nil) > 0)
+ aTempPedColPts, nil, nil) > 0)
obj->m_pCollidingEntity = this;
if(bRenderScorched)
diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h
index e096465e..883177aa 100644
--- a/src/vehicles/Automobile.h
+++ b/src/vehicles/Automobile.h
@@ -83,9 +83,10 @@ public:
float m_aWheelRotation[4];
float m_aWheelPosition[4];
float m_aWheelSpeed[4];
+ float m_fRotorSpeed;
uint8 field_4D8;
uint8 bTaxiLight : 1;
- uint8 bHadDriver : 1; // for bombs
+ //uint8 bHadDriver : 1; // for bombs
uint8 bFixedColour : 1;
uint8 bBigWheels : 1;
uint8 bWaterTight : 1; // no damage for non-player peds
@@ -146,7 +147,7 @@ public:
void RemoveRefsToVehicle(CEntity *ent);
void BlowUpCar(CEntity *ent);
bool SetUpWheelColModel(CColModel *colModel);
- void BurstTyre(uint8 tyre);
+ void BurstTyre(uint8 tyre, bool applyForces);
bool IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset);
float GetHeightAboveRoad(void);
void PlayCarHorn(void);
diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp
index 5cd6488a..1e0a8c27 100644
--- a/src/vehicles/Heli.cpp
+++ b/src/vehicles/Heli.cpp
@@ -558,60 +558,8 @@ CHeli::ProcessControl(void)
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 };
-#ifdef FIX_BUGS
- pos.z = m_fHeliDustZ[frm];
-#else
- // What the hell is the point of this?
- pos.z = m_fHeliDustZ[(i - (i&3))/4]; // advance every 4 iterations, why not just /4?
-#endif
- if(pos.z > -200.0f && GetPosition().z - pos.z < 20.0f)
- CParticle::AddParticle(PARTICLE_HELI_DUST, pos, dir, nil, 0.0f, col);
- i++;
- }
+ HeliDustGenerate(this, radius, FindPlayerCoors().z, Max(16.0f - 4.0f*CTimer::GetTimeStep(), 2.0f));
}
void
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index f07b633c..c988bf3d 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -14,11 +14,22 @@
#include "Lights.h"
#include "PointLights.h"
#include "Renderer.h"
+#include "VisibilityPlugins.h"
#include "DMAudio.h"
#include "Radar.h"
#include "Fire.h"
#include "Darkel.h"
#include "Streaming.h"
+#include "Camera.h"
+#include "Stats.h"
+#include "Garages.h"
+#include "Wanted.h"
+#include "SurfaceTable.h"
+#include "Particle.h"
+#include "WaterLevel.h"
+#include "TimeCycle.h"
+#include "Weather.h"
+#include "Coronas.h"
bool CVehicle::bWheelsOnlyCheat;
bool CVehicle::bAllDodosCheat;
@@ -53,8 +64,8 @@ CVehicle::CVehicle(uint8 CreatedBy)
{
int i;
- m_nCurrentGear = 0;
- m_fChangeGearTime = 0;
+ m_nCurrentGear = 1;
+ m_fChangeGearTime = 0.0f;
m_fSteerRatio = 0.0f;
m_type = ENTITY_TYPE_VEHICLE;
VehicleCreatedBy = CreatedBy;
@@ -106,10 +117,22 @@ CVehicle::CVehicle(uint8 CreatedBy)
m_nCarHornDelay = 0;
bPartOfConvoy = false;
bHeliMinimumTilt = false;
+ bAudioChangingGear = false;
bIsDrowning = false;
bTyresDontBurst = false;
bCreatedAsPoliceVehicle = false;
+ bRestingOnPhysical = false;
bParking = false;
+ bCanPark = CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.0f; // BUG? this makes no sense
+ bIsVan = false;
+ bIsBus = false;
+ bIsBig = false;
+ bLowVehicle = false;
+
+ m_bombType = CARBOMB_NONE;
+ bDriverLastFrame = false;
+ m_pBombRigger = nil;
+
m_nSetPieceExtendedRangeTime = 0;
m_nAlarmState = 0;
m_nDoorLock = CARLOCK_UNLOCKED;
@@ -118,6 +141,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, this);
if(m_audioEntityId >= 0)
DMAudio.SetEntityStatus(m_audioEntityId, true);
+// TODO(MIAMI):
m_nRadioStation = CGeneral::GetRandomNumber() % USERTRACK;
m_pCurGroundEntity = nil;
m_bRainAudioCounter = 0;
@@ -131,9 +155,6 @@ CVehicle::CVehicle(uint8 CreatedBy)
AutoPilot.m_bStayInCurrentLevel = false;
AutoPilot.m_bIgnorePathfinding = false;
AutoPilot.m_nSwitchDistance = 20;
-
-// TODO(MIAMI)
- bRestingOnPhysical = false;
}
CVehicle::~CVehicle()
@@ -198,57 +219,30 @@ CVehicle::RemoveLighting(bool reset)
CRenderer::RemoveVehiclePedLights(this, reset);
}
+bool
+CVehicle::IsClearToDriveAway(void)
+{
+ CColPoint point;
+ float length = GetColModel()->boundingBox.GetSize().y;
+ CEntity *ent = nil;
+ CVector front = GetForward() * (length*0.5f + 3.0f);
+ return !CWorld::ProcessLineOfSight(GetPosition() + front, GetPosition(),
+ point, ent, true, true, false, false, false, true, true) ||
+ ent == this;
+}
+
float
CVehicle::GetHeightAboveRoad(void)
{
return -1.0f * GetColModel()->boundingBox.min.z;
}
-const float fRCPropFallOff = 3.0f;
-const float fRCAeroThrust = 0.003f;
-const float fRCSideSlipMult = 0.1f;
-const float fRCRudderMult = 0.2f;
-const float fRCYawMult = -0.01f;
-const float fRCRollMult = 0.02f;
-const float fRCRollStabilise = -0.08f;
-const float fRCPitchMult = 0.005f;
-const float fRCTailMult = 0.3f;
-const float fRCFormLiftMult = 0.02f;
-const float fRCAttackLiftMult = 0.25f;
-const CVector vecRCAeroResistance(0.998f, 0.998f, 0.9f);
-
-const float fSeaPropFallOff = 2.3f;
-const float fSeaThrust = 0.002f;
-const float fSeaSideSlipMult = 0.1f;
-const float fSeaRudderMult = 0.01f;
-const float fSeaYawMult = -0.0003f;
-const float fSeaRollMult = 0.0015f;
-const float fSeaRollStabilise = -0.01f;
-const float fSeaPitchMult = 0.0002f;
-const float fSeaTailMult = 0.01f;
-const float fSeaFormLiftMult = 0.012f;
-const float fSeaAttackLiftMult = 0.1f;
-const CVector vecSeaAeroResistance(0.995f, 0.995f, 0.85f);
-
-const float fSpeedResistanceY = 500.0f;
-const float fSpeedResistanceZ = 500.0f;
-
-const CVector vecHeliMoveRes(0.995f, 0.995f, 0.99f);
-const CVector vecRCHeliMoveRes(0.99f, 0.99f, 0.99f);
-const float fThrustVar = 0.3f;
-const float fRotorFallOff = 0.75f;
-const float fStabiliseVar = 0.015f;
-const float fPitchBrake = 10.0f;
-const float fPitchVar = 0.006f;
-const float fRollVar = 0.006f;
-const float fYawVar = -0.001f;
-const CVector vecHeliResistance(0.81f, 0.85f, 0.99f);
-const CVector vecRCHeliResistance(0.92f, 0.92f, 0.998f);
-const float fSpinSpeedRes = 20.0f;
-
void
CVehicle::FlyingControl(eFlightModel flightModel)
{
+ if(pFlyingHandling == nil)
+ return;
+
switch(flightModel){
case FLIGHT_MODEL_DODO:
{
@@ -289,6 +283,8 @@ CVehicle::FlyingControl(eFlightModel flightModel)
m_vecTurnSpeed.y *= Pow(0.9f, CTimer::GetTimeStep());
+
+
moveSpeed = m_vecMoveSpeed.MagnitudeSqr();
if(moveSpeed > SQR(1.5f))
m_vecMoveSpeed *= 1.5f/Sqrt(moveSpeed);
@@ -296,172 +292,199 @@ CVehicle::FlyingControl(eFlightModel flightModel)
float turnSpeed = m_vecTurnSpeed.MagnitudeSqr();
if(turnSpeed > SQR(0.2f))
m_vecTurnSpeed *= 0.2f/Sqrt(turnSpeed);
- }
break;
+ }
case FLIGHT_MODEL_RCPLANE:
case FLIGHT_MODEL_SEAPLANE:
+ case FLIGHT_MODEL_PLANE_UNUSED:
+ case FLIGHT_MODEL_PLANE:
{
+ float fSteerLR = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;
+ float fSteerUD = -CPad::GetPad(0)->GetSteeringUpDown() / 128.0f;
+ float fGunUD = Abs(CPad::GetPad(0)->GetCarGunUpDown());
+ if(fGunUD > 1.0f)
+ fSteerUD = -CPad::GetPad(0)->GetCarGunUpDown() / 128.0f;
+
+ float fSteerAngle = Atan2(fSteerUD, fSteerLR);
+ float fSteerMult = 1.0f;
+ if(fSteerAngle > -PI/4.0f && fSteerAngle <= PI/4.0f)
+ fSteerMult = 1.0f/Cos(fSteerAngle);
+ else if(fSteerAngle > PI/4.0f && fSteerAngle <= PI*3.0f/4.0f)
+ fSteerMult = 1.0f/Cos(fSteerAngle - HALFPI);
+ else if(fSteerAngle > PI*3.0f/4.0f)
+ fSteerMult = 1.0f/Cos(fSteerAngle - PI);
+ else if(fSteerAngle <= -PI*3.0f/4.0f)
+ fSteerMult = 1.0f/Cos(fSteerAngle + PI);
+ else if(fSteerAngle > -PI*3.0f/4.0f && fSteerAngle < -PI/4.0f)
+ fSteerMult = 1.0f/Cos(fSteerAngle + HALFPI);
+
+ fSteerLR *= fSteerMult;
+ fSteerUD *= -fSteerMult;
+
// thrust
float fForwSpeed = DotProduct(GetMoveSpeed(), GetForward());
CVector vecWidthForward = GetColModel()->boundingBox.min.y * GetForward();
float fThrust = (CPad::GetPad(0)->GetAccelerate() - CPad::GetPad(0)->GetBrake()) / 255.0f;
- if (fForwSpeed > 0.1f || (flightModel == FLIGHT_MODEL_RCPLANE && fForwSpeed > 0.02f))
- fThrust += 1.0f;
- else if (fForwSpeed > 0.0f && fThrust < 0.0f)
- fThrust = 0.0f;
- float fThrustImpulse;
- if (flightModel == FLIGHT_MODEL_RCPLANE)
- fThrustImpulse = (fThrust - fRCPropFallOff * fForwSpeed) * fRCAeroThrust;
+ float fThrustAccel;
+ if(fForwSpeed > 0.0f || fThrust > 0.0f)
+ fThrustAccel = (fThrust - pFlyingHandling->fThrustFallOff * fForwSpeed) * pFlyingHandling->fThrust;
else
- fThrustImpulse = (fThrust - fSeaPropFallOff * fForwSpeed) * fSeaThrust;
- ApplyMoveForce(fThrustImpulse * GetForward() * m_fMass * CTimer::GetTimeStep());
+ fThrustAccel = Min(fThrust - 8.0f * pFlyingHandling->fThrustFallOff * fForwSpeed, 0.0f) * pFlyingHandling->fThrust;
+ if(flightModel == FLIGHT_MODEL_PLANE_UNUSED)
+ fThrustAccel *= 0.3f;
+ else if(flightModel == FLIGHT_MODEL_PLANE)
+ fThrustAccel *= 0.1f;
+ ApplyMoveForce(fThrustAccel * GetForward() * m_fMass * CTimer::GetTimeStep());
// left/right
float fSideSpeed = -DotProduct(GetMoveSpeed(), GetRight());
- float fSteerLR = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;
- float fSideSlipImpulse;
- if (flightModel == FLIGHT_MODEL_RCPLANE)
- fSideSlipImpulse = Abs(fSideSpeed) * fSideSpeed * fRCSideSlipMult;
- else
- fSideSlipImpulse = Abs(fSideSpeed) * fSideSpeed * fSeaSideSlipMult;
- ApplyMoveForce(m_fMass * GetRight() * fSideSlipImpulse * CTimer::GetTimeStep());
+ float fSideSlipAccel = pFlyingHandling->fSideSlip * fSideSpeed * Abs(fSideSpeed);
+ ApplyMoveForce(m_fMass * GetRight() * fSideSlipAccel * CTimer::GetTimeStep());
- float fYaw = -DotProduct(CrossProduct(m_vecTurnSpeed + m_vecTurnFriction, vecWidthForward) + m_vecMoveSpeed + m_vecMoveFriction, GetRight());
- float fYawImpulse;
- if (flightModel == FLIGHT_MODEL_RCPLANE)
- fYawImpulse = fRCRudderMult * fYaw * Abs(fYaw) + fRCYawMult * fSteerLR * fForwSpeed;
- else
- fYawImpulse = fSeaRudderMult * fYaw * Abs(fYaw) + fSeaYawMult * fSteerLR * fForwSpeed;
- ApplyTurnForce(fYawImpulse * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), vecWidthForward);
+ float fYaw = -DotProduct(GetSpeed(vecWidthForward), GetRight());
+ float fYawAccel = pFlyingHandling->fYawStab * fYaw * Abs(fYaw) + pFlyingHandling->fYaw * fSteerLR * fForwSpeed;
+ ApplyTurnForce(fYawAccel * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), vecWidthForward);
- float fRollImpulse;
+ float fRollAccel;
if (flightModel == FLIGHT_MODEL_RCPLANE) {
float fDirectionMultiplier = CPad::GetPad(0)->GetLookRight();
if (CPad::GetPad(0)->GetLookLeft())
fDirectionMultiplier = -1;
- fRollImpulse = (0.5f * fDirectionMultiplier + fSteerLR) * fRCRollMult;
+ fRollAccel = (0.5f * fDirectionMultiplier + fSteerLR) * pFlyingHandling->fRoll;
}
else
- fRollImpulse = fSteerLR * fSeaRollMult;
- ApplyTurnForce(GetRight() * fRollImpulse * fForwSpeed * m_fTurnMass * CTimer::GetTimeStep(), GetUp());
+ fRollAccel = fSteerLR * pFlyingHandling->fRoll;
+ ApplyTurnForce(GetRight() * fRollAccel * fForwSpeed * m_fTurnMass * CTimer::GetTimeStep(), GetUp());
CVector vecFRight = CrossProduct(GetForward(), CVector(0.0f, 0.0f, 1.0f));
CVector vecStabilise = (GetUp().z > 0.0f) ? vecFRight : -vecFRight;
float fStabiliseDirection = (GetRight().z > 0.0f) ? -1.0f : 1.0f;
- float fStabiliseImpulse;
- if (flightModel == FLIGHT_MODEL_RCPLANE)
- fStabiliseImpulse = fRCRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z));
- else
- fStabiliseImpulse = fSeaRollStabilise * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z));
- ApplyTurnForce(fStabiliseImpulse * m_fTurnMass * GetRight(), GetUp()); // no CTimer::GetTimeStep(), is it right? VC doesn't have it too
+ float fStabiliseSpeed = pFlyingHandling->fRollStab * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z));
+ ApplyTurnForce(fStabiliseSpeed * m_fTurnMass * GetRight(), GetUp()); // no CTimer::GetTimeStep(), is it right?
// up/down
- float fTail = -DotProduct(CrossProduct(m_vecTurnSpeed + m_vecTurnFriction, vecWidthForward) + m_vecMoveSpeed + m_vecMoveFriction, GetUp());
- float fSteerUD = -CPad::GetPad(0)->GetSteeringUpDown() / 128.0f;
- float fPitchImpulse;
- if (flightModel == FLIGHT_MODEL_RCPLANE)
- fPitchImpulse = fRCTailMult * fTail * Abs(fTail) + fRCPitchMult * fSteerUD * fForwSpeed;
- else
- fPitchImpulse = fSeaTailMult * fTail * Abs(fTail) + fSeaPitchMult * fSteerUD * fForwSpeed;
- ApplyTurnForce(fPitchImpulse * m_fTurnMass * GetUp() * CTimer::GetTimeStep(), vecWidthForward);
+ float fTail = -DotProduct(GetSpeed(vecWidthForward), GetUp());
+ float fPitchAccel = pFlyingHandling->fPitchStab * fTail * Abs(fTail) + pFlyingHandling->fPitch * fSteerUD * fForwSpeed;
+ ApplyTurnForce(fPitchAccel * m_fTurnMass * GetUp() * CTimer::GetTimeStep(), vecWidthForward);
float fLift = -DotProduct(GetMoveSpeed(), GetUp()) / Max(0.01f, GetMoveSpeed().Magnitude());
- float fLiftImpluse;
- if (flightModel == FLIGHT_MODEL_RCPLANE)
- fLiftImpluse = (fRCAttackLiftMult * fLift + fRCFormLiftMult) * fForwSpeed * fForwSpeed;
- else
- fLiftImpluse = (fSeaAttackLiftMult * fLift + fSeaFormLiftMult) * fForwSpeed * fForwSpeed;
- float fLiftForce = fLiftImpluse * m_fMass * CTimer::GetTimeStep();
- if (GRAVITY * CTimer::GetTimeStep() * m_fMass < fLiftImpluse) {
+ float fLiftAccel = (pFlyingHandling->fAttackLift * fLift + pFlyingHandling->fFormLift) * fForwSpeed * fForwSpeed;
+ float fLiftImpulse = fLiftAccel * m_fMass * CTimer::GetTimeStep();
+ if (GRAVITY * CTimer::GetTimeStep() * m_fMass < fLiftImpulse) {
if (flightModel == FLIGHT_MODEL_RCPLANE && GetPosition().z > 50.0f)
- fLiftForce = CTimer::GetTimeStep() * 0.0072 * m_fMass;
+ fLiftImpulse = CTimer::GetTimeStep() * 0.9f*GRAVITY * m_fMass;
else if (flightModel == FLIGHT_MODEL_SEAPLANE && GetPosition().z > 80.0f)
- fLiftForce = CTimer::GetTimeStep() * 0.0072 * m_fMass;
+ fLiftImpulse = CTimer::GetTimeStep() * 0.9f*GRAVITY * m_fMass;
}
- ApplyMoveForce(fLiftForce * GetUp());
+ ApplyMoveForce(fLiftImpulse * GetUp());
+
CVector vecResistance;
- if (flightModel == FLIGHT_MODEL_RCPLANE)
- vecResistance = vecRCAeroResistance;
- else
- vecResistance = vecSeaAeroResistance;
+ vecResistance = pFlyingHandling->vecTurnRes;
float rX = Pow(vecResistance.x, CTimer::GetTimeStep());
float rY = Pow(vecResistance.y, CTimer::GetTimeStep());
float rZ = Pow(vecResistance.z, CTimer::GetTimeStep());
CVector vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix());
vecTurnSpeed.x *= rX;
- float fResistance = vecTurnSpeed.y * (1.0f / (fSpeedResistanceY * SQR(vecTurnSpeed.y) + 1.0f)) * rY - vecTurnSpeed.y;
+ float fResistance = vecTurnSpeed.y * (1.0f / (pFlyingHandling->vecSpeedRes.y * SQR(vecTurnSpeed.y) + 1.0f)) * rY - vecTurnSpeed.y;
vecTurnSpeed.z *= rZ;
m_vecTurnSpeed = Multiply3x3(GetMatrix(), vecTurnSpeed);
ApplyTurnForce(-GetUp() * fResistance * m_fTurnMass, GetRight() + Multiply3x3(GetMatrix(), m_vecCentreOfMass));
+
+
+ float fMoveSpeed = m_vecMoveSpeed.MagnitudeSqr();
+ if(fMoveSpeed > SQR(1.5f))
+ m_vecMoveSpeed *= 1.5f/Sqrt(fMoveSpeed);
+
+ float fTurnSpeed = m_vecTurnSpeed.MagnitudeSqr();
+ if(fTurnSpeed > SQR(0.2f))
+ m_vecTurnSpeed *= 0.2f/Sqrt(fTurnSpeed);
break;
}
+ case FLIGHT_MODEL_RCHELI:
case FLIGHT_MODEL_HELI:
{
- CVector vecMoveResistance;
- if (GetModelIndex() == MI_SPARROW)
- vecMoveResistance = vecHeliMoveRes;
- else
- vecMoveResistance = vecRCHeliMoveRes;
- float rmX = Pow(vecMoveResistance.x, CTimer::GetTimeStep());
- float rmY = Pow(vecMoveResistance.y, CTimer::GetTimeStep());
- float rmZ = Pow(vecMoveResistance.z, CTimer::GetTimeStep());
- m_vecMoveSpeed.x *= rmX;
- m_vecMoveSpeed.y *= rmY;
- m_vecMoveSpeed.z *= rmZ;
+ float rm = Pow(pFlyingHandling->fMoveRes, CTimer::GetTimeStep());
+ m_vecMoveSpeed *= rm;
if (GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE)
return;
- float fThrust;
- if (bCheat5)
- fThrust = CPad::GetPad(0)->GetSteeringUpDown() * fThrustVar / 128.0f + 0.95f;
- else
- fThrust = fThrustVar * (CPad::GetPad(0)->GetAccelerate() - 2 * CPad::GetPad(0)->GetBrake()) / 255.0f + 0.95f;
- fThrust -= fRotorFallOff * DotProduct(m_vecMoveSpeed, GetUp());
-#ifdef GTA3_1_1_PATCH
- if (fThrust > 0.9f && GetPosition().z > 80.0f)
- fThrust = 0.9f;
-#endif
+ float fUpSpeed = DotProduct(m_vecMoveSpeed, GetUp());
+ float fThrust = (CPad::GetPad(0)->GetAccelerate() - CPad::GetPad(0)->GetBrake()) / 255.0f;
+ if(fThrust < 0.0f)
+ fThrust *= 2.0f;
+ if(flightModel == FLIGHT_MODEL_RCHELI){
+ fThrust = pFlyingHandling->fThrust * fThrust + 0.45f;
+ ApplyMoveForce(GRAVITY * CVector(0.0f, 0.0f, 0.5f) * m_fMass * CTimer::GetTimeStep());
+ }else
+ fThrust = pFlyingHandling->fThrust * fThrust + 0.95f;
+ fThrust -= pFlyingHandling->fThrustFallOff * fUpSpeed;
+ if(flightModel == FLIGHT_MODEL_RCHELI && GetPosition().z > 40.0f)
+ fThrust *= 10.0f/(GetPosition().z - 30.0f);
+ else if(GetPosition().z > 80.0f)
+ fThrust *= 10.0f/(GetPosition().z - 70.0f);
ApplyMoveForce(GRAVITY * GetUp() * fThrust * m_fMass * CTimer::GetTimeStep());
- if (GetUp().z > 0.0f)
- ApplyTurnForce(-CVector(GetUp().x, GetUp().y, 0.0f) * fStabiliseVar * m_fTurnMass * CTimer::GetTimeStep(), GetUp());
+ if (GetUp().z > 0.0f){
+ float upRight = clamp(GetRight().z, -pFlyingHandling->fFormLift, pFlyingHandling->fFormLift);
+ float upImpulseRight = -upRight * pFlyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep();
+ ApplyTurnForce(upImpulseRight * GetUp(), GetRight());
+
+ float upFwd = clamp(GetForward().z, -pFlyingHandling->fFormLift, pFlyingHandling->fFormLift);
+ float upImpulseFwd = -upFwd * pFlyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep();
+ ApplyTurnForce(upImpulseFwd * GetUp(), GetForward());
+ }else{
+ float upRight = GetRight().z < 0.0f ? -pFlyingHandling->fFormLift : pFlyingHandling->fFormLift;
+ float upImpulseRight = -upRight * pFlyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep();
+ ApplyTurnForce(upImpulseRight * GetUp(), GetRight());
+
+ float upFwd = GetForward().z < 0.0f ? -pFlyingHandling->fFormLift : pFlyingHandling->fFormLift;
+ float upImpulseFwd = -upFwd * pFlyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep();
+ ApplyTurnForce(upImpulseFwd * GetUp(), GetForward());
+ }
float fRoll, fPitch, fYaw;
if (bCheat5) {
- fPitch = CPad::GetPad(0)->GetCarGunUpDown() / 128.0f;
- fRoll = -CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;
- fYaw = CPad::GetPad(0)->GetCarGunLeftRight() / 128.0f;
- }
- else {
fPitch = CPad::GetPad(0)->GetSteeringUpDown() / 128.0f;
+ fRoll = CPad::GetPad(0)->GetLookLeft();
+ if (CPad::GetPad(0)->GetLookRight())
+ fRoll = -1.0f;
+ fYaw = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;
+ } else {
+ fPitch = CPad::GetPad(0)->GetSteeringUpDown() / 128.0f;
+ fRoll = -CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;
fYaw = CPad::GetPad(0)->GetLookRight();
if (CPad::GetPad(0)->GetLookLeft())
fYaw = -1.0f;
- fRoll = -CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;
+ if(Abs(CPad::GetPad(0)->GetCarGunLeftRight()) > 1.0f)
+ fYaw = CPad::GetPad(0)->GetCarGunLeftRight() / 128.0f;
}
+ if(Abs(CPad::GetPad(0)->GetCarGunUpDown()) > 1.0f)
+ fPitch = -CPad::GetPad(0)->GetCarGunUpDown() / 128.0f;
if (CPad::GetPad(0)->GetHorn()) {
fYaw = 0.0f;
- fPitch = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetUp()), -200.0f, 1.3f);
- fRoll = clamp(10.0f * DotProduct(m_vecMoveSpeed, GetRight()), -200.0f, 1.3f);
+ fPitch = clamp(pFlyingHandling->fPitchStab * DotProduct(m_vecMoveSpeed, GetForward()), -200.0f, 1.3f);
+ fRoll = clamp(pFlyingHandling->fRollStab * DotProduct(m_vecMoveSpeed, GetRight()), -200.0f, 1.3f);
}
- ApplyTurnForce(fPitch * GetUp() * fPitchVar * m_fTurnMass * CTimer::GetTimeStep(), GetForward());
- ApplyTurnForce(fRoll * GetUp() * fRollVar * m_fTurnMass * CTimer::GetTimeStep(), GetRight());
- ApplyTurnForce(fYaw * GetForward() * fYawVar * m_fTurnMass * CTimer::GetTimeStep(), GetRight());
+ ApplyTurnForce(fPitch * GetUp() * pFlyingHandling->fPitch * m_fTurnMass * CTimer::GetTimeStep(), GetForward());
+ ApplyTurnForce(fRoll * GetUp() * pFlyingHandling->fRoll * m_fTurnMass * CTimer::GetTimeStep(), GetRight());
- CVector vecResistance;
- if (GetModelIndex() == MI_SPARROW)
- vecResistance = vecHeliResistance;
- else
- vecResistance = vecRCHeliResistance;
- float rX = Pow(vecResistance.x, CTimer::GetTimeStep());
- float rY = Pow(vecResistance.y, CTimer::GetTimeStep());
- float rZ = Pow(vecResistance.z, CTimer::GetTimeStep());
+ float fSideSpeed = -DotProduct(GetMoveSpeed(), GetRight());
+ float fSideSlipAccel = pFlyingHandling->fSideSlip * fSideSpeed * Abs(fSideSpeed);
+ ApplyMoveForce(m_fMass * GetRight() * fSideSlipAccel * CTimer::GetTimeStep());
+ float fYawAccel = pFlyingHandling->fYawStab * fSideSpeed * Abs(fSideSpeed) + pFlyingHandling->fYaw * fYaw;
+ ApplyTurnForce(fYawAccel * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), -GetForward());
+
+ ApplyTurnForce(fYaw * GetForward() * pFlyingHandling->fYaw * m_fTurnMass * CTimer::GetTimeStep(), GetRight());
+
+ float rX = Pow(pFlyingHandling->vecTurnRes.x, CTimer::GetTimeStep());
+ float rY = Pow(pFlyingHandling->vecTurnRes.y, CTimer::GetTimeStep());
+ float rZ = Pow(pFlyingHandling->vecTurnRes.z, CTimer::GetTimeStep());
CVector vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix());
- float fResistanceMultiplier = Pow(1.0f / (fSpinSpeedRes * SQR(vecTurnSpeed.z) + 1.0f), CTimer::GetTimeStep());
+ float fResistanceMultiplier = Pow(1.0f / (pFlyingHandling->vecSpeedRes.z * SQR(vecTurnSpeed.z) + 1.0f) * rZ, CTimer::GetTimeStep());
float fResistance = vecTurnSpeed.z * fResistanceMultiplier - vecTurnSpeed.z;
vecTurnSpeed.x *= rX;
vecTurnSpeed.y *= rY;
- vecTurnSpeed.z *= rZ;
+ vecTurnSpeed.z *= fResistanceMultiplier;
m_vecTurnSpeed = Multiply3x3(GetMatrix(), vecTurnSpeed);
ApplyTurnForce(-GetRight() * fResistance * m_fTurnMass, GetForward() + Multiply3x3(GetMatrix(), m_vecCentreOfMass));
break;
@@ -469,6 +492,228 @@ CVehicle::FlyingControl(eFlightModel flightModel)
}
}
+static CColModel rotorColModel;
+static CColSphere rotorColSphere;
+float ROTOR_SEMI_THICKNESS = 0.05f;
+float ROTOR_TURN_SPEED = 0.2f;
+float ROTOR_DISGUARD_MULT = 0.3f;
+float ROTOR_COL_ELASTICITY = 1.0f;
+float ROTOR_COL_TURNMULT = -0.001f;
+float ROTOR_DEFAULT_DAMAGE = 100.0f;
+
+bool
+CVehicle::DoBladeCollision(CVector pos, CMatrix &matrix, int16 rotorType, float radius, float damageMult)
+{
+ CVector max(radius, radius, radius);
+ CVector min(-radius, -radius, -radius);
+
+ switch(rotorType){
+ case ROTOR_TOP:
+ case ROTOR_BOTTOM:
+ min.z = -ROTOR_SEMI_THICKNESS;
+ max.z = ROTOR_SEMI_THICKNESS;
+ break;
+ case ROTOR_FRONT:
+ case ROTOR_BACK:
+ min.y = -ROTOR_SEMI_THICKNESS;
+ max.y = ROTOR_SEMI_THICKNESS;
+ break;
+ case ROTOR_RIGHT:
+ case ROTOR_LEFT:
+ min.x = -ROTOR_SEMI_THICKNESS;
+ max.x = ROTOR_SEMI_THICKNESS;
+ break;
+ }
+
+ min += pos;
+ max += pos;
+ rotorColModel.boundingBox.Set(min, max);
+ rotorColModel.boundingSphere.Set(radius, pos);
+ rotorColSphere.Set(radius, pos, 0, 0);
+ rotorColModel.spheres = &rotorColSphere;
+ rotorColModel.numSpheres = 1;
+
+ pos = matrix * pos;
+ bool hadCollision;
+ int minX = CWorld::GetSectorIndexX(pos.x - radius);
+ if(minX <= 0) minX = 0;
+
+ int minY = CWorld::GetSectorIndexY(pos.y - radius);
+ if(minY <= 0) minY = 0;
+
+ int maxX = CWorld::GetSectorIndexX(pos.x + radius);
+#ifdef FIX_BUGS
+ if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
+#else
+ if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
+#endif
+
+ int maxY = CWorld::GetSectorIndexY(pos.y + radius);
+#ifdef FIX_BUGS
+ if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
+#else
+ if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
+#endif
+
+ CWorld::AdvanceCurrentScanCode();
+ for(int curY = minY; curY <= maxY; curY++) {
+ for(int curX = minX; curX <= maxX; curX++) {
+ CSector *sector = CWorld::GetSector(curX, curY);
+ if(BladeColSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], rotorColModel, matrix, rotorType, damageMult))
+ hadCollision = true;
+ if(BladeColSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], rotorColModel, matrix, rotorType, damageMult))
+ hadCollision = true;
+ if(BladeColSectorList(sector->m_lists[ENTITYLIST_VEHICLES], rotorColModel, matrix, rotorType, damageMult))
+ hadCollision = true;
+ if(BladeColSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], rotorColModel, matrix, rotorType, damageMult))
+ hadCollision = true;
+ if(BladeColSectorList(sector->m_lists[ENTITYLIST_PEDS], rotorColModel, matrix, rotorType, 0.0f))
+ hadCollision = true;
+ if(BladeColSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], rotorColModel, matrix, rotorType, 0.0f))
+ hadCollision = true;
+ if(BladeColSectorList(sector->m_lists[ENTITYLIST_OBJECTS], rotorColModel, matrix, rotorType, damageMult))
+ hadCollision = true;
+ if(BladeColSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], rotorColModel, matrix, rotorType, damageMult))
+ hadCollision = true;
+ }
+ }
+ rotorColModel.spheres = nil;
+ rotorColModel.numSpheres = 0;
+
+ return hadCollision;
+}
+
+bool
+CVehicle::BladeColSectorList(CPtrList &list, CColModel &rotorColModel, CMatrix &matrix, int16 rotorType, float damageMult)
+{
+ int i;
+ CVector axis;
+ CVector turnSpeed(0.0f, 0.0f, 0.0f);
+ switch(rotorType){
+ case ROTOR_TOP:
+ turnSpeed.z = -ROTOR_TURN_SPEED;
+ axis = -matrix.GetUp();
+ break;
+ case ROTOR_BOTTOM:
+ turnSpeed.z = ROTOR_TURN_SPEED;
+ axis = matrix.GetUp();
+ break;
+
+ case ROTOR_FRONT:
+ turnSpeed.y = -ROTOR_TURN_SPEED;
+ axis = -matrix.GetForward();
+ break;
+ case ROTOR_BACK:
+ turnSpeed.y = ROTOR_TURN_SPEED;
+ axis = matrix.GetForward();
+ break;
+
+ case ROTOR_RIGHT:
+ turnSpeed.x = -ROTOR_TURN_SPEED;
+ axis = -matrix.GetRight();
+ break;
+ case ROTOR_LEFT:
+ turnSpeed.x = ROTOR_TURN_SPEED;
+ axis = matrix.GetRight();
+ break;
+ }
+ turnSpeed = Multiply3x3(matrix, turnSpeed);
+ CVector center = rotorColModel.boundingSphere.center;
+ center = matrix*center;
+
+ for(CPtrNode *node = list.first; node; node = node->next) {
+ CEntity *entity = (CEntity *)node->item;
+ if(entity == (CEntity*)this ||
+ !entity->bUsesCollision ||
+ entity->m_scanCode == CWorld::GetCurrentScanCode())
+ continue;
+
+ entity->m_scanCode = CWorld::GetCurrentScanCode();
+
+ int numCollisions;
+ CColModel *entityCol;
+ if(entity->IsPed())
+ entityCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(entity->GetModelIndex()))->AnimatePedColModelSkinned(entity->GetClump());
+ else
+ entityCol = CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel();
+ if(entityCol)
+ numCollisions = CCollision::ProcessColModels(matrix, rotorColModel, entity->GetMatrix(), *entityCol,
+ CWorld::m_aTempColPts, nil, nil);
+ else
+ numCollisions = 0;
+
+ if(numCollisions > 0 && entity->IsPed()){
+ CPed *ped = (CPed*)entity;
+ CVector2D dirToRotor = GetPosition() - entity->GetPosition();
+ dirToRotor.Normalise();
+ int localDir = ped->GetLocalDirection(dirToRotor);
+ if(ped->m_attachedTo == nil){
+ ped->bIsStanding = false;
+ ped->ApplyMoveForce(-5.0f*dirToRotor.x, -5.0f*dirToRotor.y, 5.0f);
+ }
+ ped->InflictDamage(this, WEAPONTYPE_RUNOVERBYCAR, 1000.0f, PEDPIECE_TORSO, localDir);
+
+ if(CGame::nastyGame && ped->GetIsOnScreen()){
+ for(i = 0; i < 16; i++)
+ CParticle::AddParticle(PARTICLE_BLOOD_SMALL, ped->GetPosition(), CVector(dirToRotor.x, dirToRotor.y, 1.0f) * 0.01f);
+ CParticle::AddParticle(PARTICLE_TEST, ped->GetPosition(), CVector(0.0f, 0.0f, 0.02f), nil, 0.1f);
+ CParticle::AddParticle(PARTICLE_TEST, ped->GetPosition()+CVector(0.0f, 0.0f, 0.2f), CVector(0.0f, 0.0f, -0.01f), nil, 0.1f);
+ }
+ }else if(numCollisions > 0 && entity->GetModelIndex() != MI_MISSILE){
+ float impulse = 0.0f;
+ bool hadCollision = false;
+ float savedElasticity = m_fElasticity;
+ m_fElasticity = ROTOR_COL_ELASTICITY;
+
+ for(i = 0; i < numCollisions; i++){
+ CVector colpos = CWorld::m_aTempColPts[i].point;
+ CVector localColpos = colpos - center;
+ float axisDir = DotProduct(axis, localColpos);
+ float colDir = DotProduct(CWorld::m_aTempColPts[i].normal, localColpos);
+ if(2.0f*ROTOR_SEMI_THICKNESS < Abs(axisDir) &&
+ ROTOR_DISGUARD_MULT*Abs(colDir) < Abs(axisDir))
+ continue;
+
+ colpos -= axisDir*axis; // get rid of axis component
+
+ CVector tangentSpeed = CrossProduct(turnSpeed, colpos - center);
+
+ // Particles
+ for(int j = 0; j < 4; j++){
+ CParticle::AddParticle(PARTICLE_SPARK_SMALL, colpos, (tangentSpeed+m_vecMoveSpeed)/2.0f);
+ CParticle::AddParticle(PARTICLE_SPARK, colpos, 0.1f*CWorld::m_aTempColPts[i].normal);
+ }
+
+ // Apply Collision
+ if(IsCar()){
+ CAutomobile *heli = (CAutomobile*)this;
+ if(heli->m_fRotorSpeed > 0.15f){
+ ApplyCollision(CWorld::m_aTempColPts[i], impulse);
+ ApplyTurnForce(m_fTurnMass*ROTOR_COL_TURNMULT*tangentSpeed, colpos - center);
+ heli->m_fRotorSpeed = 0.15f;
+ }else if(heli->m_fRotorSpeed < 0.075f && heli->m_fRotorSpeed > 0.0f)
+ heli->m_fRotorSpeed *= -1.0f;
+ }
+
+ float damageImpulse = damageMult * Max(impulse, ROTOR_DEFAULT_DAMAGE*m_fMass/3000.0f);
+ if(damageImpulse > m_fDamageImpulse)
+ SetDamagedPieceRecord(0, damageImpulse, entity, CWorld::m_aTempColPts[i].normal);
+
+ hadCollision = true;
+ }
+
+ if(hadCollision && !entity->IsPed())
+ DMAudio.ReportCollision(this, entity, SURFACE_BILLBOARD, SURFACE_TARMAC, 50.0f, 0.09f);
+ m_fElasticity = savedElasticity;
+ }
+ }
+ return false;
+}
+
+
+float fBurstSpeedMax = 0.3f;
+float fBurstTyreMod = 0.13f;
+
void
CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,
int32 wheelsOnGround, float thrust, float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, uint16 wheelStatus)
@@ -478,6 +723,10 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
static bool bBraking;
static bool bDriving;
+#ifdef FIX_BUGS
+ bAlreadySkidding = false;
+#endif
+
// how much force we want to apply in these axes
float fwd = 0.0f;
float right = 0.0f;
@@ -509,8 +758,169 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
#endif
if(wheelStatus == WHEEL_STATUS_BURST){
- float fwdspeed = Min(contactSpeedFwd, 0.3f);
- right += fwdspeed * CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
+ float fwdspeed = Min(contactSpeedFwd, fBurstSpeedMax);
+ right += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstTyreMod, fBurstTyreMod);
+ }
+ }
+
+ if(bDriving){
+ fwd = thrust;
+
+ // limit sideways force (why?)
+ if(right > 0.0f){
+ if(right > adhesion)
+ right = adhesion;
+ }else{
+ if(right < -adhesion)
+ right = -adhesion;
+ }
+ }else if(contactSpeedFwd != 0.0f){
+ fwd = -contactSpeedFwd/wheelsOnGround;
+#ifdef FIX_BUGS
+ // contactSpeedFwd is independent of framerate but fwd has timestep as a factor
+ // so we probably have to fix this
+ fwd *= CTimer::GetTimeStepFix();
+#endif
+
+ if(!bBraking){
+ if(m_fGasPedal < 0.01f){
+ if(IsBike())
+ brake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->fMass + 200.0f);
+ else if(pHandling->fMass < 500.0f)
+ brake = mod_HandlingManager.fWheelFriction / m_fMass;
+ else if(GetModelIndex() == MI_RCBANDIT)
+ brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass;
+ else
+ brake = mod_HandlingManager.fWheelFriction / m_fMass;
+#ifdef FIX_BUGS
+ brake *= CTimer::GetTimeStepFix();
+#endif
+ }
+ }
+
+ if(brake > adhesion){
+ if(Abs(contactSpeedFwd) > 0.005f)
+ *wheelState = WHEEL_STATE_FIXED;
+ }else {
+ if(fwd > 0.0f){
+ if(fwd > brake)
+ fwd = brake;
+ }else{
+ if(fwd < -brake)
+ fwd = -brake;
+ }
+ }
+ }
+
+ float speedSq = sq(right) + sq(fwd);
+ if(sq(adhesion) < speedSq){
+ if(*wheelState != WHEEL_STATE_FIXED){
+ if(bDriving && contactSpeedFwd < 0.2f)
+ *wheelState = WHEEL_STATE_SPINNING;
+ else
+ *wheelState = WHEEL_STATE_SKIDDING;
+ }
+
+ float l = Sqrt(speedSq);
+ float tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss;
+ right *= adhesion * tractionLoss / l;
+ fwd *= adhesion * tractionLoss / l;
+ }
+
+ if(fwd != 0.0f || right != 0.0f){
+ CVector totalSpeed = fwd*wheelFwd + right*wheelRight;
+
+ CVector turnDirection = totalSpeed;
+ bool separateTurnForce = false; // BUG: not initialized on PC
+ if(pHandling->fSuspensionAntidiveMultiplier > 0.0f){
+ if(bBraking){
+ separateTurnForce = true;
+ turnDirection = totalSpeed - pHandling->fSuspensionAntidiveMultiplier*fwd*wheelFwd;
+ }else if(bDriving){
+ separateTurnForce = true;
+ turnDirection = totalSpeed - 0.5f*pHandling->fSuspensionAntidiveMultiplier*fwd*wheelFwd;
+ }
+ }
+
+ CVector direction = totalSpeed;
+
+ float speed = totalSpeed.Magnitude();
+ float turnSpeed;
+ if(separateTurnForce)
+ turnSpeed = turnDirection.Magnitude();
+ else
+ turnSpeed = speed;
+ direction.Normalise();
+ if(separateTurnForce)
+ turnDirection.Normalise();
+ else
+ turnDirection = direction;
+
+ float impulse = speed*m_fMass;
+ float turnImpulse = turnSpeed*GetMass(wheelContactPoint, turnDirection);
+
+ ApplyMoveForce(impulse * direction);
+ ApplyTurnForce(turnImpulse * direction, wheelContactPoint);
+ }
+}
+
+float fBurstBikeSpeedMax = 0.12f;
+float fBurstBikeTyreMod = 0.05f;
+float fTweakBikeWheelTurnForce = 2.0f;
+
+void
+CVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,
+ int32 wheelsOnGround, float thrust, float brake, float adhesion, float unk, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus)
+{
+ // BUG: using statics here is probably a bad idea
+ static bool bAlreadySkidding = false; // this is never reset
+ static bool bBraking;
+ static bool bDriving;
+ static bool bReversing;
+
+#ifdef FIX_BUGS
+ bAlreadySkidding = false;
+#endif
+
+ // how much force we want to apply in these axes
+ float fwd = 0.0f;
+ float right = 0.0f;
+
+ bBraking = brake != 0.0f;
+ if(bBraking)
+ thrust = 0.0f;
+ bDriving = thrust != 0.0f;
+ bReversing = thrust < 0.0f;
+
+ float contactSpeedFwd = DotProduct(wheelContactSpeed, wheelFwd);
+ float contactSpeedRight;
+
+ if(*wheelState != WHEEL_STATE_NORMAL)
+ bAlreadySkidding = true;
+ *wheelState = WHEEL_STATE_NORMAL;
+
+ adhesion *= CTimer::GetTimeStep();
+ if(bAlreadySkidding)
+ adhesion *= pHandling->fTractionLoss;
+
+ if(special == BIKE_WHEEL_2 || special == BIKE_WHEEL_3)
+ contactSpeedRight = 0.0f;
+ else
+ contactSpeedRight = DotProduct(wheelContactSpeed, wheelRight);
+
+ // moving sideways
+ if(contactSpeedRight != 0.0f){
+ // exert opposing force
+ right = -contactSpeedRight/wheelsOnGround;
+#ifdef FIX_BUGS
+ // contactSpeedRight is independent of framerate but right has timestep as a factor
+ // so we probably have to fix this
+ right *= CTimer::GetTimeStepFix();
+#endif
+
+ if(wheelStatus == WHEEL_STATUS_BURST){
+ float fwdspeed = Min(contactSpeedFwd, fBurstBikeSpeedMax);
+ right += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstBikeTyreMod, fBurstBikeTyreMod);
}
}
@@ -535,7 +945,11 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
if(!bBraking){
if(m_fGasPedal < 0.01f){
- if(GetModelIndex() == MI_RCBANDIT)
+ if(IsBike())
+ brake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->fMass + 200.0f);
+ else if(pHandling->fMass < 500.0f)
+ brake = mod_HandlingManager.fWheelFriction / m_fMass;
+ else if(GetModelIndex() == MI_RCBANDIT)
brake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass;
else
brake = mod_HandlingManager.fWheelFriction / m_fMass;
@@ -559,7 +973,8 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
}
}
- if(sq(adhesion) < sq(right) + sq(fwd)){
+ float speedSq = sq(right) + sq(fwd);
+ if(sq(adhesion) < speedSq){
if(*wheelState != WHEEL_STATE_FIXED){
if(bDriving && contactSpeedFwd < 0.2f)
*wheelState = WHEEL_STATE_SPINNING;
@@ -567,22 +982,44 @@ CVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelCon
*wheelState = WHEEL_STATE_SKIDDING;
}
- float l = Sqrt(sq(right) + sq(fwd));
+ float l = Sqrt(speedSq);
float tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss;
right *= adhesion * tractionLoss / l;
fwd *= adhesion * tractionLoss / l;
+
+ if(unk < 1.0f)
+ right *= unk;
+ }else if(unk < 1.0f){
+ if(!bAlreadySkidding)
+ unk *= pHandling->fTractionLoss;
+ if(sq(adhesion*unk) < speedSq){
+ float l = Sqrt(speedSq);
+ right *= adhesion * unk / l;
+ }
}
if(fwd != 0.0f || right != 0.0f){
CVector direction = fwd*wheelFwd + right*wheelRight;
+
float speed = direction.Magnitude();
direction.Normalise();
float impulse = speed*m_fMass;
float turnImpulse = speed*GetMass(wheelContactPoint, direction);
+ CVector vTurnImpulse = turnImpulse * direction;
+ float turnRight = DotProduct(vTurnImpulse, GetRight());
ApplyMoveForce(impulse * direction);
- ApplyTurnForce(turnImpulse * direction, wheelContactPoint);
+
+ float contactRight = DotProduct(wheelContactPoint, GetRight());
+ float contactFwd = DotProduct(wheelContactPoint, GetForward());
+
+ if(wheelId != CARWHEEL_REAR_LEFT ||
+ !bBraking && !bReversing)
+ ApplyTurnForce((vTurnImpulse - turnRight*GetRight()) * fTweakBikeWheelTurnForce,
+ wheelContactPoint - contactRight*GetRight());
+
+ ApplyTurnForce(turnRight*GetRight(), contactFwd*GetForward());
}
}
@@ -604,40 +1041,81 @@ CVehicle::ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVec
return angularVelocity * CTimer::GetTimeStep();
}
+int
+CVehicle::FindTyreNearestPoint(float x, float y)
+{
+ CVector pos = CVector(x - GetPosition().x, y - GetPosition().y, 0.0f);
+ float fwd = DotProduct(GetForward(), pos);
+ float right = DotProduct(GetRight(), pos);
+
+ int piece;
+ if(IsBike()){
+ piece = fwd > 0.0f ? CAR_PIECE_WHEEL_LF : CAR_PIECE_WHEEL_LR;
+ }else{
+ piece = fwd > 0.0f ?
+ right > 0.0f ? CAR_PIECE_WHEEL_RF : CAR_PIECE_WHEEL_LF :
+ right > 0.0f ? CAR_PIECE_WHEEL_RR : CAR_PIECE_WHEEL_LR;
+ }
+ return piece - CAR_PIECE_WHEEL_LF;
+}
+
void
-CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage)
+CVehicle::InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage, CVector pos)
{
if (!bCanBeDamaged)
return;
- if (bOnlyDamagedByPlayer && (damagedBy != FindPlayerPed() && damagedBy != FindPlayerVehicle()))
+ if(GetStatus() == STATUS_PLAYER && CStats::GetPercentageProgress() >= 100.0f)
+ damage *= 0.5f;
+ if (GetStatus() != STATUS_PLAYER && bOnlyDamagedByPlayer && (damagedBy != FindPlayerPed() && damagedBy != FindPlayerVehicle()))
return;
+
+ if(damage > 10.0f && (damagedBy == FindPlayerPed() || damagedBy == FindPlayerVehicle()) && GetStatus() != STATUS_WRECKED){
+ CWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 2;
+ CWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention += 1.0f;
+ CStats::PropertyDestroyed += CGeneral::GetRandomNumberInRange(5, 25);
+ }
+
bool bFrightensDriver = false;
switch (weaponType) {
case WEAPONTYPE_UNARMED:
+ case WEAPONTYPE_BRASSKNUCKLE:
+ case WEAPONTYPE_SCREWDRIVER:
+ case WEAPONTYPE_GOLFCLUB:
+ case WEAPONTYPE_NIGHTSTICK:
+ case WEAPONTYPE_KNIFE:
case WEAPONTYPE_BASEBALLBAT:
+ case WEAPONTYPE_HAMMER:
+ case WEAPONTYPE_CLEAVER:
+ case WEAPONTYPE_MACHETE:
+ case WEAPONTYPE_KATANA:
+ case WEAPONTYPE_CHAINSAW:
if (bMeleeProof)
return;
break;
case WEAPONTYPE_COLT45:
- case WEAPONTYPE_UZI:
- case WEAPONTYPE_TEC9:
- case WEAPONTYPE_SILENCED_INGRAM:
- case WEAPONTYPE_MP5:
+ case WEAPONTYPE_PYTHON:
case WEAPONTYPE_SHOTGUN:
case WEAPONTYPE_SPAS12_SHOTGUN:
case WEAPONTYPE_STUBBY_SHOTGUN:
- case WEAPONTYPE_RUGER:
+ case WEAPONTYPE_TEC9:
+ case WEAPONTYPE_UZI:
+ case WEAPONTYPE_SILENCED_INGRAM:
+ case WEAPONTYPE_MP5:
case WEAPONTYPE_M4:
+ case WEAPONTYPE_RUGER:
case WEAPONTYPE_SNIPERRIFLE:
+ case WEAPONTYPE_LASERSCOPE:
+ case WEAPONTYPE_M60:
+ case WEAPONTYPE_MINIGUN:
case WEAPONTYPE_HELICANNON:
case WEAPONTYPE_UZI_DRIVEBY:
if (bBulletProof)
return;
bFrightensDriver = true;
break;
- case WEAPONTYPE_ROCKETLAUNCHER:
- case WEAPONTYPE_MOLOTOV:
case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_MOLOTOV:
+ case WEAPONTYPE_ROCKET:
case WEAPONTYPE_EXPLOSION:
if (bExplosionProof)
return;
@@ -654,6 +1132,52 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage
default:
break;
}
+
+ if(bFrightensDriver && GetStatus() == STATUS_PLAYER && m_fHealth < 250.0f)
+ return;
+
+ // Pop tires
+ if(damagedBy && damagedBy->IsPed() && (IsCar() || IsBike())){
+ int accuracy = 0;
+ switch(weaponType){
+ case WEAPONTYPE_COLT45:
+ accuracy = 10;
+ break;
+ case WEAPONTYPE_PYTHON:
+ if(!((CPed*)damagedBy)->IsPlayer())
+ accuracy = 64;
+ break;
+ case WEAPONTYPE_SHOTGUN:
+ case WEAPONTYPE_STUBBY_SHOTGUN:
+ case WEAPONTYPE_M60:
+ case WEAPONTYPE_HELICANNON:
+ accuracy = 25;
+ break;
+ case WEAPONTYPE_TEC9:
+ case WEAPONTYPE_UZI:
+ case WEAPONTYPE_SILENCED_INGRAM:
+ case WEAPONTYPE_MP5:
+ case WEAPONTYPE_UZI_DRIVEBY:
+ accuracy = 15;
+ break;
+ case WEAPONTYPE_M4:
+ case WEAPONTYPE_RUGER:
+ if(!((CPed*)damagedBy)->IsPlayer())
+ accuracy = 15;
+ break;
+ }
+
+ if(((CPed*)damagedBy)->IsPlayer() && (CCamera::m_bUseMouse3rdPerson || TheCamera.Using1stPersonWeaponMode()))
+ accuracy = 0;
+
+ if(accuracy != 0 && !bTyresDontBurst && (CGeneral::GetRandomNumber()&0x7F) < accuracy){
+ if(IsBike())
+ BurstTyre(FindTyreNearestPoint(pos.x, pos.y) + CAR_PIECE_WHEEL_LF, false);
+ else if(GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR)
+ BurstTyre(FindTyreNearestPoint(pos.x, pos.y) + CAR_PIECE_WHEEL_LF, true);
+ }
+ }
+
if (m_fHealth > 0.0f) {
if (VehicleCreatedBy == RANDOM_VEHICLE && pDriver &&
(GetStatus() == STATUS_SIMPLE || GetStatus() == STATUS_PHYSICS) &&
@@ -666,24 +1190,43 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage
}
}
m_nLastWeaponDamage = weaponType;
+ m_pLastDamageEntity = damagedBy;
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)) {
+ if (VehicleCreatedBy == RANDOM_VEHICLE && !IsBoat()){
switch (GetStatus()) {
case STATUS_SIMPLE:
case STATUS_PHYSICS:
- if (pDriver) {
- SetStatus(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);
+ if(AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_PLOUGH_THROUGH ||
+ CGeneral::GetRandomNumberInRange(0.0f, 1.0f) > 0.5f && AutoPilot.m_nCarMission == MISSION_CRUISE){
+ // Drive away like a maniac
+ if(pDriver && pDriver->m_objective != OBJECTIVE_LEAVE_VEHICLE){
+ if(AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH)
+ AutoPilot.m_nCruiseSpeed *= 1.5f;
+ AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH;
+ }
+ }else{
+ // Leave vehicle
+ if (pDriver && pDriver->CharCreatedBy != MISSION_CHAR) {
+ SetStatus(STATUS_ABANDONED);
+ pDriver->bFleeAfterExitingCar = true;
+ pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this);
+// TODO(MIAMI):
+// pDriver->Say(120);
+ }
+ int time = 200;
+ for (int i = 0; i < m_nNumMaxPassengers; i++) {
+ if (pPassengers[i] &&
+ pPassengers[i]->m_objective != OBJECTIVE_LEAVE_VEHICLE &&
+ pPassengers[i]->CharCreatedBy != MISSION_CHAR) {
+ pPassengers[i]->bFleeAfterExitingCar = true;
+ pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this);
+ pPassengers[i]->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + time;
+// TODO(MIAMI):
+// pPassengers[i]->Say(120);
+ time += 200;
+ }
}
}
break;
@@ -691,7 +1234,7 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage
break;
}
}
- if (oldHealth > DAMAGE_HEALTH_TO_CATCH_FIRE && m_fHealth < DAMAGE_HEALTH_TO_CATCH_FIRE) {
+ 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);
@@ -725,11 +1268,13 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage
void
CVehicle::DoFixedMachineGuns(void)
{
- if(CPad::GetPad(0)->GetCarGunFired() && !bGunSwitchedOff){
- FireFixedMachineGuns();
- }else{
- if(CTimer::GetTimeInMilliseconds() > m_nGunFiringTime + 1400)
- m_nAmmoInClip = 20;
+ if(TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_FORWARD){
+ if(CPad::GetPad(0)->GetCarGunFired() && !bGunSwitchedOff){
+ FireFixedMachineGuns();
+ }else{
+ if(CTimer::GetTimeInMilliseconds() > m_nGunFiringTime + 1400)
+ m_nAmmoInClip = 20;
+ }
}
}
@@ -778,9 +1323,43 @@ CVehicle::FireFixedMachineGuns(void)
}
void
+CVehicle::ActivateBomb(void)
+{
+ 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);
+ }
+}
+
+void
+CVehicle::ActivateBombWhenEntered(void)
+{
+ if(pDriver){
+ if(!bDriverLastFrame && 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);
+ }
+ bDriverLastFrame = true;
+ }else
+ bDriverLastFrame = false;
+}
+
+void
CVehicle::ExtinguishCarFire(void)
{
- m_fHealth = Max(m_fHealth, 300.0f);
+ if(GetStatus() != STATUS_WRECKED)
+ m_fHealth = Max(m_fHealth, 300.0f);
if(m_pCarFire)
m_pCarFire->Extinguish();
if(IsCar()){
@@ -851,6 +1430,69 @@ CVehicle::ShufflePassengersToMakeSpace(void)
}
void
+CVehicle::MakeNonDraggedPedsLeaveVehicle(CPed *ped1, CPed *ped2, CPlayerPed *&player, CCopPed *&cop)
+{
+ int i;
+ player = nil;
+ cop = nil;
+
+ if(ped1->IsPlayer() && ped2->m_nPedType == PEDTYPE_COP &&
+ ((CPlayerPed*)ped1)->m_pWanted->m_nWantedLevel > 0 &&
+ ped2->m_pedInObjective == ped1){
+ player = (CPlayerPed*)ped1;
+ cop = (CCopPed*)ped2;
+ return;
+ }
+
+ bool ped1IsDriver = ped1 == pDriver;
+
+ // Just what the hell is this weird code?
+ CPed *peds[9];
+ CPed *peds2[9];
+ int numPeds = 0;
+ int numPeds2 = 0;
+ for(i = 0; i < m_nNumMaxPassengers; i++){
+ CPed *p = pPassengers[i];
+ if(p && p != ped1 && !p->bStayInCarOnJack){
+ peds[numPeds++] = p;
+ // uhh what?
+ if(i < 1 && !ped1IsDriver)
+ continue;
+ peds2[numPeds2++] = p;
+ }
+ }
+
+ // So we're copying this array for no reason...
+ CPed *peds3[9];
+ int numPeds3 = 0;
+ for(i = 0; i < numPeds; i++){
+ if(peds[i]->IsPlayer() && ped2->m_nPedType == PEDTYPE_COP &&
+ ((CPlayerPed*)peds[i])->m_pWanted->m_nWantedLevel > 0 &&
+ ped2->m_pedInObjective == peds[i]){
+ player = (CPlayerPed*)peds[i];
+ cop = (CCopPed*)ped2;
+ return;
+ }
+ peds3[numPeds3++] = peds[i];
+ }
+
+ int time = 1800;
+ for(i = 0; i < numPeds3; i++){
+ peds3[i]->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + time;
+ peds3[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, this);
+ time += CGeneral::GetRandomNumberInRange(300.0f, 600.0f);
+ }
+
+ if(IsCar() && numPeds2 > 0 && CGeneral::GetRandomTrueFalse())
+ for(i = 0; i < numPeds2; i++)
+ if(peds2[i]->IsFemale() || CGeneral::GetRandomTrueFalse()){
+ peds2[i]->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ peds2[i]->b156_8 = true;
+ peds2[i]->bFleeAfterExitingCar = true;
+ }
+}
+
+void
CVehicle::ProcessDelayedExplosion(void)
{
if(m_nBombTimer == 0)
@@ -869,8 +1511,6 @@ CVehicle::ProcessDelayedExplosion(void)
if (m_nBombTimer != 0)
return;
- if(FindPlayerVehicle() != this && m_pBlowUpEntity == FindPlayerPed())
- CWorld::Players[CWorld::PlayerInFocus].AwardMoneyForExplosion(this);
BlowUpCar(m_pBlowUpEntity);
}
@@ -878,12 +1518,13 @@ bool
CVehicle::IsLawEnforcementVehicle(void)
{
switch(GetModelIndex()){
- case MI_FBICAR:
case MI_POLICE:
case MI_ENFORCER:
case MI_PREDATOR:
case MI_RHINO:
case MI_BARRACKS:
+ case MI_FBIRANCH:
+ case MI_VICECHEE:
return true;
default:
return false;
@@ -901,6 +1542,8 @@ CVehicle::UsesSiren(uint32 id)
case MI_POLICE:
case MI_ENFORCER:
case MI_PREDATOR:
+ case MI_FBIRANCH:
+ case MI_VICECHEE:
return true;
default:
return false;
@@ -989,7 +1632,8 @@ CVehicle::CanPedOpenLocks(CPed *ped)
{
if(m_nDoorLock == CARLOCK_LOCKED ||
m_nDoorLock == CARLOCK_LOCKED_INITIALLY ||
- m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE)
+ m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE ||
+ m_nDoorLock == CARLOCK_SKIP_SHUT_DOORS)
return false;
if(ped->IsPlayer() && m_nDoorLock == CARLOCK_LOCKOUT_PLAYER_ONLY)
return false;
@@ -997,11 +1641,18 @@ CVehicle::CanPedOpenLocks(CPed *ped)
}
bool
+CVehicle::CanDoorsBeDamaged(void)
+{
+ return m_nDoorLock == CARLOCK_NOT_USED ||
+ m_nDoorLock == CARLOCK_UNLOCKED ||
+ m_nDoorLock == CARLOCK_SKIP_SHUT_DOORS;
+}
+
+bool
CVehicle::CanPedEnterCar(void)
{
- CVector up = GetUp();
// can't enter when car is on side
- if(up.z > 0.1f || up.z < -0.1f){
+ if(IsBike() || GetUp().z > 0.1f || GetUp().z < -0.1f){
// also when car is moving too fast
if(m_vecMoveSpeed.MagnitudeSqr() > sq(0.2f))
return false;
@@ -1013,16 +1664,14 @@ CVehicle::CanPedEnterCar(void)
}
bool
-CVehicle::CanPedExitCar(void)
+CVehicle::CanPedExitCar(bool jumpExit)
{
CVector up = GetUp();
if(up.z > 0.1f || up.z < -0.1f){
-#ifdef VC_PED_PORTS
if (IsBoat())
return true;
-#endif
// can't exit when car is moving too fast
- if(m_vecMoveSpeed.MagnitudeSqr() > 0.005f)
+ if(m_vecMoveSpeed.MagnitudeSqr() > 0.005f && !jumpExit)
return false;
// if car is slow enough, check turn speed
if(Abs(m_vecTurnSpeed.x) > 0.01f ||
@@ -1045,6 +1694,14 @@ CVehicle::CanPedExitCar(void)
}
}
+bool
+CVehicle::CanPedJumpOffBike(void)
+{
+ if(pPassengers[0])
+ return false;
+ return m_vecMoveSpeed.MagnitudeSqr() < 0.07f ? false : true;
+}
+
void
CVehicle::ChangeLawEnforcerState(uint8 enable)
{
@@ -1082,14 +1739,30 @@ CVehicle::SetUpDriver(void)
CPed*
CVehicle::SetupPassenger(int n)
{
+ int i;
+
if(pPassengers[n])
return pPassengers[n];
- pPassengers[n] = CPopulation::AddPedInCar(this, false);
- pPassengers[n]->m_pMyVehicle = this;
- pPassengers[n]->m_pMyVehicle->RegisterReference((CEntity**)&pPassengers[n]->m_pMyVehicle);
- pPassengers[n]->bInVehicle = true;
- pPassengers[n]->SetPedState(PED_DRIVING);
+ if((IsTaxi() || IsLimo()) && n == 0)
+ pPassengers[0] = nil;
+ else{
+ CPed *passenger = CPopulation::AddPedInCar(this, false);
+ pPassengers[n] = passenger;
+ passenger->m_pMyVehicle = this;
+ passenger->m_pMyVehicle->RegisterReference((CEntity**)&pPassengers[n]->m_pMyVehicle);
+ passenger->bInVehicle = true;
+ passenger->SetPedState(PED_DRIVING);
+
+ if(passenger->m_nPedType == PEDTYPE_CIVMALE || passenger->m_nPedType == PEDTYPE_CIVFEMALE)
+ for(i = 0; i < n; i++)
+ if(pPassengers[i] && pPassengers[n] &&
+ pPassengers[i]->m_nPedType == PEDTYPE_CIVMALE || pPassengers[i]->m_nPedType == PEDTYPE_CIVFEMALE &&
+ passenger->GetModelIndex() == pPassengers[i]->GetModelIndex()){
+ pPassengers[n] = nil;
+ CPopulation::RemovePed(passenger);
+ }
+ }
if(bIsBus)
pPassengers[n]->bRenderPedInCar = false;
++m_nNumPassengers;
@@ -1103,24 +1776,42 @@ CVehicle::SetDriver(CPed *driver)
pDriver->RegisterReference((CEntity**)&pDriver);
if(bFreebies && driver == FindPlayerPed()){
- if(GetModelIndex() == MI_AMBULAN)
- FindPlayerPed()->m_fHealth = Min(FindPlayerPed()->m_fHealth + 20.0f, CWorld::Players[0].m_nMaxHealth);
- else if(GetModelIndex() == MI_TAXI)
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
- else if (GetModelIndex() == MI_POLICE) {
- CStreaming::RequestModel(WEAPONTYPE_SHOTGUN, STREAMFLAGS_DONT_REMOVE);
- driver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5);
- } else if (GetModelIndex() == MI_ENFORCER)
- driver->m_fArmour = Max(driver->m_fArmour, CWorld::Players[0].m_nMaxArmour);
- else if(GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA) // TODO(MIAMI): check zebra
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 25;
bFreebies = false;
+ switch(GetModelIndex()){
+ case MI_AMBULAN:
+ FindPlayerPed()->m_fHealth = Max(FindPlayerPed()->m_fHealth, Min(FindPlayerPed()->m_fHealth + 20.0f, CWorld::Players[0].m_nMaxHealth));
+ break;
+
+ case MI_TAXI:
+ case MI_CABBIE:
+ case MI_ZEBRA:
+ case MI_KAUFMAN:
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 12;
+ break;
+
+ case MI_POLICE:
+ CStreaming::RequestModel(MI_SHOTGUN, STREAMFLAGS_DONT_REMOVE);
+ bFreebies = true;
+ break;
+
+ case MI_ENFORCER:
+ driver->m_fArmour = Max(driver->m_fArmour, CWorld::Players[0].m_nMaxArmour);
+ break;
+
+ case MI_CADDY:
+ if(!(driver->IsPlayer() && ((CPlayerPed*)driver)->DoesPlayerWantNewWeapon(WEAPONTYPE_GOLFCLUB, true)))
+ CStreaming::RequestModel(MI_GOLFCLUB, STREAMFLAGS_DONT_REMOVE);
+ break;
+ }
}
- ApplyTurnForce(0.0f, 0.0f, -0.2f*driver->m_fMass,
- driver->GetPosition().x - GetPosition().x,
- driver->GetPosition().y - GetPosition().y,
- 0.0f);
+ if(IsBike())
+ ApplyMoveForce(-0.2f*driver->m_fMass * GetUp());
+ else
+ ApplyTurnForce(0.0f, 0.0f, -0.2f*driver->m_fMass,
+ driver->GetPosition().x - GetPosition().x,
+ driver->GetPosition().y - GetPosition().y,
+ 0.0f);
}
bool
@@ -1128,10 +1819,13 @@ CVehicle::AddPassenger(CPed *passenger)
{
int i;
- ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,
- passenger->GetPosition().x - GetPosition().x,
- passenger->GetPosition().y - GetPosition().y,
- 0.0f);
+ if(IsBike())
+ ApplyTurnForce(-0.2f*passenger->m_fMass * GetUp(), -0.1f*GetForward());
+ else
+ ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,
+ passenger->GetPosition().x - GetPosition().x,
+ passenger->GetPosition().y - GetPosition().y,
+ 0.0f);
for(i = 0; i < m_nNumMaxPassengers; i++)
if(pPassengers[i] == nil){
@@ -1148,10 +1842,13 @@ CVehicle::AddPassenger(CPed *passenger, uint8 n)
if(bIsBus)
return AddPassenger(passenger);
- ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,
- passenger->GetPosition().x - GetPosition().x,
- passenger->GetPosition().y - GetPosition().y,
- 0.0f);
+ if(IsBike())
+ ApplyTurnForce(-0.2f*passenger->m_fMass * GetUp(), -0.1f*GetForward());
+ else
+ ApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,
+ passenger->GetPosition().x - GetPosition().x,
+ passenger->GetPosition().y - GetPosition().y,
+ 0.0f);
if(n < m_nNumMaxPassengers && pPassengers[n] == nil){
pPassengers[n] = passenger;
@@ -1165,6 +1862,22 @@ void
CVehicle::RemoveDriver(void)
{
SetStatus(STATUS_ABANDONED);
+ if(pDriver == FindPlayerPed()){
+ if(GetModelIndex() == MI_POLICE && CStreaming::HasModelLoaded(MI_SHOTGUN)){
+ if(bFreebies){
+ if(((CPlayerPed*)pDriver)->DoesPlayerWantNewWeapon(WEAPONTYPE_SHOTGUN, true))
+ pDriver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5, true);
+ else
+ pDriver->GrantAmmo(WEAPONTYPE_SHOTGUN, 5);
+ bFreebies = false;
+ }
+ CStreaming::SetModelIsDeletable(MI_SHOTGUN);
+ }else if(GetModelIndex() == MI_CADDY && CStreaming::HasModelLoaded(MI_GOLFCLUB)){
+ if(((CPlayerPed*)pDriver)->DoesPlayerWantNewWeapon(WEAPONTYPE_GOLFCLUB, true))
+ pDriver->GiveWeapon(WEAPONTYPE_GOLFCLUB, 1, true);
+ CStreaming::SetModelIsDeletable(MI_GOLFCLUB);
+ }
+ }
pDriver = nil;
}
@@ -1190,6 +1903,57 @@ CVehicle::RemovePassenger(CPed *p)
}
}
+bool
+CVehicle::IsDriver(CPed *ped)
+{
+ if(ped == nil)
+ return false;
+ return ped == pDriver;
+}
+
+bool
+CVehicle::IsDriver(int32 model)
+{
+ return pDriver && pDriver->GetModelIndex() == model;
+}
+
+bool
+CVehicle::IsPassenger(CPed *ped)
+{
+ int i;
+ if(ped == nil)
+ return false;
+ for(i = 0; i < 8; i++)
+ if(pPassengers[i] == ped)
+ return true;
+ return false;
+}
+
+bool
+CVehicle::IsPassenger(int32 model)
+{
+ int i;
+ for(i = 0; i < 8; i++)
+ if(pPassengers[i] && pPassengers[i]->GetModelIndex() == model)
+ return true;
+ return false;
+}
+
+void
+CVehicle::UpdatePassengerList(void)
+{
+ int i;
+ bool hasPassenger = false;
+ if(m_nNumPassengers)
+ for(i = 0; i < 8; i++)
+ if(pPassengers[i]){
+ hasPassenger = true;
+ break;
+ }
+ if(!hasPassenger)
+ m_nNumPassengers = 0;
+}
+
void
CVehicle::ProcessCarAlarm(void)
{
@@ -1199,9 +1963,10 @@ CVehicle::ProcessCarAlarm(void)
return;
step = CTimer::GetTimeStepInMilliseconds();
- if((uint16)m_nAlarmState < step)
+ if((uint16)m_nAlarmState < step){
m_nAlarmState = 0;
- else
+ m_nCarHornTimer = 0;
+ }else
m_nAlarmState -= step;
}
@@ -1229,6 +1994,261 @@ CVehicle::IsSphereTouchingVehicle(float sx, float sy, float sz, float radius)
return true;
}
+RpMaterial*
+SetCompAlphaCB(RpMaterial *material, void *data)
+{
+ uint32 alpha = (uint32)(uintptr)data;
+ RwRGBA *col = (RwRGBA*)RpMaterialGetColor(material); // get rid of const
+ col->alpha = alpha;
+ return material;
+}
+
+void
+CVehicle::SetComponentAtomicAlpha(RpAtomic *atomic, int32 alpha)
+{
+ RpGeometry *geo = RpAtomicGetGeometry(atomic);
+ RpGeometrySetFlags(geo, RpGeometryGetFlags(geo) | rpGEOMETRYMODULATEMATERIALCOLOR);
+ RpGeometryForAllMaterials(geo, SetCompAlphaCB, (void*)alpha);
+}
+
+void
+CVehicle::UpdateClumpAlpha(void)
+{
+ 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);
+}
+
+void
+CVehicle::HeliDustGenerate(CEntity *heli, float radius, float ground, int rnd)
+{
+ int i;
+ float angle;
+ CColPoint point;
+ CEntity *entity;
+ uint8 r, g, b;
+
+ if(heli == nil)
+ return;
+
+ uint8 surface = SURFACE_TARMAC;
+ int frm = CTimer::GetFrameCounter() & 7;
+ float testLowZ = ground - 10.0f;
+ float dustSize = 0.0f;
+ float baseSize = 1.0f;
+ float offset = 1.0f; // when heli is tilted
+ float particleZ = -101.0f;
+ int n = 0;
+
+ if(heli->GetModelIndex() == MI_RCGOBLIN || heli->GetModelIndex() == MI_RCRAIDER){
+ radius = 3.0f;
+ dustSize = 0.04f;
+ baseSize = 0.07f;
+ offset = 0.3f;
+ }
+
+ CVector heliPos = heli->GetPosition();
+
+ if(heli->IsVehicle() && ((CVehicle*)heli)->IsCar()){
+ heliPos.x -= (heliPos.z - ground)*heli->GetUp().x*offset*0.5f;
+ heliPos.y -= (heliPos.z - ground)*heli->GetUp().y*offset*0.5f;
+ }
+
+ float steamSize = 0.25f * radius * baseSize;
+ float splashSize = 0.3f * radius * baseSize;
+
+ i = 0;
+ for(i = 0; i < 32+rnd; i++){
+ angle = i * TWOPI/32.0f;
+ CVector pos(radius*Cos(angle), radius*Sin(angle), 0.0f);
+ CVector dir = CVector(pos.x, pos.y, 1.0f)*0.01f;
+ pos += heliPos;
+
+ if(i < 32 && i == 4*frm){
+ if(CWorld::ProcessVerticalLine(pos, testLowZ, point, entity, true, false, false, false, true, false, nil)){
+ n = rnd;
+ particleZ = point.point.z;
+ surface = point.surfaceB;
+ }else
+ n = 0;
+
+ float waterLevel = 0.0f;
+ if(CWaterLevel::GetWaterLevel(pos, &waterLevel, false) && waterLevel > particleZ){
+ surface = SURFACE_PUDDLE;
+ n = rnd;
+ particleZ = waterLevel;
+ }
+ }
+
+ if(n){
+ pos.z = particleZ;
+ if(surface == SURFACE_PUDDLE){
+ float red = (0.3*CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed_Obj())*255.0f/4.0f;
+ float green = (0.3*CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen_Obj())*255.0f/4.0f;
+ float blue = (0.3*CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue_Obj())*255.0f/4.0f;
+ r = clamp(red, 0.0f, 255.0f);
+ g = clamp(green, 0.0f, 255.0f);
+ b = clamp(blue, 0.0f, 255.0f);
+ RwRGBA col1 = { r, g, b, CGeneral::GetRandomNumberInRange(8, 32) };
+ RwRGBA col2 = { 255, 255, 255, 32 };
+
+ if(n&1)
+ CParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, pos, dir, nil, steamSize, col2);
+ else
+ CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, dir, nil, splashSize, col1,
+ CGeneral::GetRandomNumberInRange(0.0f, 10.0f),
+ CGeneral::GetRandomNumberInRange(0.0f, 90.0f), 1);
+ }else{
+ switch(surface){
+ default:
+ case SURFACE_TARMAC:
+ r = 10;
+ g = 10;
+ b = 10;
+ break;
+ case SURFACE_GRASS:
+ r = 10;
+ g = 10;
+ b = 3;
+ break;
+ case SURFACE_DIRT:
+ r = 10;
+ g = 8;
+ b = 7;
+ break;
+ case SURFACE_DIRTTRACK:
+ r = 10;
+ g = 6;
+ b = 3;
+ break;
+ case SURFACE_SAND:
+ case SURFACE_SAND33:
+ r = 10;
+ g = 10;
+ b = 7;
+ break;
+ }
+ RwRGBA col = { r, g, b, 32 };
+ if(heliPos.z - pos.z < 20.0f)
+ CParticle::AddParticle(PARTICLE_HELI_DUST, pos, dir, nil, dustSize, col);
+ }
+
+ n--;
+ }
+ }
+}
+
+#define GLARE_MIN_DIST (13.0f)
+#define GLARE_FULL_DIST (30.0f)
+#define GLARE_MIN_ANGLE (0.99f)
+#define GLARE_FULL_ANGLE (0.995f)
+
+void
+CVehicle::DoSunGlare(void)
+{
+ if(bRenderScorched || GetPosition().z < 0.0f ||
+ GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR || CWeather::SunGlare <= 0.0f)
+ return;
+
+ CVector camDir = TheCamera.GetPosition() - GetPosition();
+ float dist = camDir.Magnitude();
+ camDir *= 2.0f/dist;
+ CVector glareVec = camDir + CTimeCycle::GetSunDirection();
+ CVector localGlareVec;
+ localGlareVec.x = DotProduct(glareVec, GetRight());
+ localGlareVec.y = DotProduct(glareVec, GetForward());
+ localGlareVec.z = 0.0;
+ localGlareVec.Normalise();
+
+ CVector2D fwd2D = GetForward();
+ fwd2D.Normalise();
+ CVector2D camDir2D = camDir;
+ camDir2D.Normalise();
+ float fwdness = Abs(DotProduct2D(fwd2D, camDir2D));
+
+ // check angle
+ float strength;
+ if(fwdness > GLARE_FULL_ANGLE)
+ strength = 1.0f;
+ else if(fwdness > GLARE_MIN_ANGLE)
+ strength = (fwdness - GLARE_MIN_ANGLE)/(GLARE_FULL_ANGLE-GLARE_MIN_ANGLE);
+ else
+ return;
+ // check distance
+ if(dist > GLARE_FULL_DIST){
+ // no max distance
+ }else if(dist > GLARE_MIN_DIST)
+ strength *= (dist - GLARE_MIN_DIST)/(GLARE_FULL_DIST - GLARE_MIN_DIST);
+ else
+ return;
+
+ float intens = 0.8f * strength * CWeather::SunGlare;
+ int r = intens * (CTimeCycle::GetSunCoreRed() + 2*255)/3.0f;
+ int g = intens * (CTimeCycle::GetSunCoreGreen() + 2*255)/3.0f;
+ int b = intens * (CTimeCycle::GetSunCoreBlue() + 2*255)/3.0f;
+
+ CColModel *colmodel = GetColModel();
+ CCollision::CalculateTrianglePlanes(colmodel);
+
+ int i;
+ for(i = 0; i < colmodel->numTriangles-2; i += 2){
+ int a1 = colmodel->triangles[i].a;
+ int b1 = colmodel->triangles[i].b;
+ int c1 = colmodel->triangles[i].c;
+ int a2 = colmodel->triangles[i+1].a;
+ int b2 = colmodel->triangles[i+1].b;
+ int c2 = colmodel->triangles[i+1].c;
+ CVector vert1 = colmodel->vertices[a1];
+ CVector vert4;
+ // Need an upward surface
+ if(vert1.z <= 0.0f)
+ continue;
+
+ // trying to find a quad here
+ int numTri2Verts = 0;
+ if(a2 != a1 && a2 != b1 && a2 != c1){
+ // a2 is not in tri1
+ numTri2Verts++;
+ vert4 = colmodel->vertices[a2];
+ }
+ if(b2 != a1 && b2 != b1 && b2 != c1){
+ // b2 is not in tri1
+ numTri2Verts++;
+ vert4 = colmodel->vertices[b2];
+ }
+ if(c2 != a1 && c2 != b1 && c2 != c1){
+ // c2 is not in tri1
+ numTri2Verts++;
+ vert4 = colmodel->vertices[c2];
+ }
+ // Need exactly one vertex from tri2 for a quad with tri1
+ if(numTri2Verts != 1)
+ continue;
+
+ CVector mid = (vert1 + colmodel->vertices[b1] + colmodel->vertices[c1] + vert4)/4.0f;
+ float dy = mid.y - vert1.y;
+ float dx = mid.x - vert1.x;
+ float dist = 1.4f * Min(Abs(dx), Abs(dy));
+ if(dist > 0.6f){
+ CVector pos = GetMatrix() * (dist * localGlareVec + mid) + camDir;
+ CCoronas::RegisterCorona((uintptr)this + 27 + i,
+ r, g, b, 255,
+ pos, 0.9f*CWeather::SunGlare, 90.0f,
+ CCoronas::TYPE_STAR, CCoronas::FLARE_NONE,
+ CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF,
+ CCoronas::STREAK_OFF, 0.0f);
+ }
+ }
+}
+
void
DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle)
{
@@ -1372,20 +2392,19 @@ CVehicle::Load(uint8*& buf)
#endif
eVehicleAppearance
-//--MIAMI: TODO, implement VC version, appearance != type
-// This would work for cars, boats and bikes but not for planes and helis
CVehicle::GetVehicleAppearance(void)
{
- if (IsCar())
+ uint32 flags = pHandling->Flags & 0xF0000;
+ if (flags == 0)
return VEHICLE_APPEARANCE_CAR;
- if (IsBoat())
- return VEHICLE_APPEARANCE_BOAT;
- if (IsBike())
+ if (flags == HANDLING_IS_BIKE)
return VEHICLE_APPEARANCE_BIKE;
- if (IsPlane())
- return VEHICLE_APPEARANCE_PLANE;
- if (IsHeli())
+ if (flags == HANDLING_IS_HELI)
return VEHICLE_APPEARANCE_HELI;
+ if (flags == HANDLING_IS_PLANE)
+ return VEHICLE_APPEARANCE_PLANE;
+ if (flags == HANDLING_IS_BOAT)
+ return VEHICLE_APPEARANCE_BOAT;
return VEHICLE_APPEARANCE_NONE;
}
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index 7b5a1e11..083a8a15 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -8,6 +8,8 @@
#include "HandlingMgr.h"
class CPed;
+class CPlayerPed;
+class CCopPed;
class CFire;
struct tHandlingData;
@@ -87,8 +89,8 @@ enum
CAR_PIECE_WING_LR,
CAR_PIECE_WING_RR,
CAR_PIECE_WHEEL_LF,
- CAR_PIECE_WHEEL_LR,
CAR_PIECE_WHEEL_RF,
+ CAR_PIECE_WHEEL_LR,
CAR_PIECE_WHEEL_RR,
CAR_PIECE_WINDSCREEN,
};
@@ -104,10 +106,12 @@ enum tWheelState
enum eFlightModel
{
FLIGHT_MODEL_DODO,
- // not used in III
FLIGHT_MODEL_RCPLANE,
- FLIGHT_MODEL_HELI,
- FLIGHT_MODEL_SEAPLANE
+ FLIGHT_MODEL_RCHELI,
+ FLIGHT_MODEL_SEAPLANE,
+ FLIGHT_MODEL_PLANE_UNUSED,
+ FLIGHT_MODEL_PLANE,
+ FLIGHT_MODEL_HELI
};
enum eVehicleAppearance
@@ -120,10 +124,28 @@ enum eVehicleAppearance
VEHICLE_APPEARANCE_PLANE,
};
+// TODO
+enum eBikeWheelSpecial
+{
+ BIKE_WHEEL_2 = 2,
+ BIKE_WHEEL_3,
+};
+
+enum
+{
+ ROTOR_TOP = 3,
+ ROTOR_FRONT = 4,
+ ROTOR_RIGHT = 5,
+ ROTOR_LEFT = 7,
+ ROTOR_BACK = 8,
+ ROTOR_BOTTOM = 9,
+};
+
class CVehicle : public CPhysical
{
public:
tHandlingData *pHandling;
+ tFlyingHandlingData *pFlyingHandling;
CAutoPilot AutoPilot;
uint8 m_currentColour1;
uint8 m_currentColour2;
@@ -180,28 +202,28 @@ public:
uint8 bHasAlreadyBeenRecorded : 1; // Used for replays
uint8 bPartOfConvoy : 1;
uint8 bHeliMinimumTilt : 1; // This heli should have almost no tilt really
- //uint8 bAudioChangingGear : 1; // sounds like vehicle is changing gear
+ uint8 bAudioChangingGear : 1; // sounds like vehicle is changing gear
uint8 bIsDrowning : 1; // is vehicle occupants taking damage in water (i.e. vehicle is dead in water)
uint8 bTyresDontBurst : 1; // If this is set the tyres are invincible
uint8 bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc)
uint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed
uint8 bParking : 1;
- //uint8 bCanPark : 1;
+ uint8 bCanPark : 1;
uint8 m_bombType : 3;
+ uint8 bDriverLastFrame : 1;
int8 m_numPedsUseItAsCover;
uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default)
int8 m_nPacManPickupsCarried;
uint8 m_nRoadblockType;
- int16 m_nRoadblockNode;
float m_fHealth; // 1000.0f = full health. 250.0f = fire. 0 -> explode
uint8 m_nCurrentGear;
float m_fChangeGearTime;
CEntity* m_pBombRigger;
- uint32 m_nGunFiringTime; // last time when gun on vehicle was fired (used on boats)
uint32 m_nSetPieceExtendedRangeTime;
+ uint32 m_nGunFiringTime; // last time when gun on vehicle was fired (used on boats)
uint32 m_nTimeOfDeath;
uint16 m_nTimeBlocked;
int16 m_nBombTimer; // goes down with each frame
@@ -214,7 +236,7 @@ public:
int8 m_nRadioStation;
uint8 m_bRainAudioCounter;
uint8 m_bRainSamplesCounter;
- uint8 m_nCarHornTimer;
+ uint32 m_nCarHornTimer;
uint8 m_nCarHornPattern;
bool m_bSirenOrAlarm;
uint8 m_nCarHornDelay;
@@ -247,11 +269,15 @@ public:
virtual bool IsDoorFullyOpen(eDoors door) { return false; }
virtual bool IsDoorClosed(eDoors door) { return false; }
virtual bool IsDoorMissing(eDoors door) { return false; }
+ virtual bool IsDoorReady(uint32 door) { return false; }
+ virtual bool IsDoorMissing(uint32 door) { return false; }
+ virtual bool IsOpenTopCar(void) { return false; }
virtual void RemoveRefsToVehicle(CEntity *ent) {}
virtual void BlowUpCar(CEntity *ent) {}
virtual bool SetUpWheelColModel(CColModel *colModel) { return false; }
- virtual void BurstTyre(uint8 tyre) {}
+ virtual void BurstTyre(uint8 tyre, bool applyForces) {}
virtual bool IsRoomForPedToLeaveCar(uint32 component, CVector *forcedDoorPos) { return false;}
+ virtual bool IsClearToDriveAway(void);
virtual float GetHeightAboveRoad(void);
virtual void PlayCarHorn(void) {}
#ifdef COMPATIBLE_SAVES
@@ -268,11 +294,17 @@ public:
bool IsBike(void) { return m_vehType == VEHICLE_TYPE_BIKE; }
void FlyingControl(eFlightModel flightModel);
+ bool DoBladeCollision(CVector pos, CMatrix &matrix, int16 rotorType, float radius, float damageMult);
+ bool BladeColSectorList(CPtrList &list, CColModel &rotorColModel, CMatrix &matrix, int16 rotorType, float damageMult);
+
void ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,
int32 wheelsOnGround, float thrust, float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, uint16 wheelStatus);
+ void ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,
+ int32 wheelsOnGround, float thrust, float brake, float adhesion, float unk, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus);
void ExtinguishCarFire(void);
void ProcessDelayedExplosion(void);
float ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVector &speed, float radius);
+ int FindTyreNearestPoint(float x, float y);
bool IsLawEnforcementVehicle(void);
void ChangeLawEnforcerState(uint8 enable);
bool UsesSiren(uint32 id);
@@ -282,8 +314,10 @@ public:
bool IsOnItsSide(void);
bool CanBeDeleted(void);
bool CanPedOpenLocks(CPed *ped);
+ bool CanDoorsBeDamaged(void);
bool CanPedEnterCar(void);
- bool CanPedExitCar(void);
+ bool CanPedExitCar(bool jumpExit);
+ bool CanPedJumpOffBike(void);
// do these two actually return something?
CPed *SetUpDriver(void);
CPed *SetupPassenger(int n);
@@ -292,17 +326,31 @@ public:
bool AddPassenger(CPed *passenger, uint8 n);
void RemovePassenger(CPed *passenger);
void RemoveDriver(void);
+ bool IsDriver(CPed *ped);
+ bool IsDriver(int32 model);
+ bool IsPassenger(CPed *ped);
+ bool IsPassenger(int32 model);
+ void UpdatePassengerList(void);
void ProcessCarAlarm(void);
bool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius);
bool ShufflePassengersToMakeSpace(void);
- void InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage);
+ void MakeNonDraggedPedsLeaveVehicle(CPed *ped1, CPed *ped2, CPlayerPed *&player, CCopPed *&cop);
+ void InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage, CVector pos = CVector(0.0f, 0.0f, 0.0f));
void DoFixedMachineGuns(void);
void FireFixedMachineGuns(void);
+ void ActivateBomb(void);
+ void ActivateBombWhenEntered(void);
+
+ void SetComponentAtomicAlpha(RpAtomic *atomic, int32 alpha);
+ void UpdateClumpAlpha(void);
+ static void HeliDustGenerate(CEntity *heli, float radius, float ground, int rnd);
+ void DoSunGlare(void);
bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; }
CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); }
bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA || GetModelIndex() == MI_KAUFMAN; }
+ bool IsLimo(void) { return GetModelIndex() == MI_STRETCH || GetModelIndex() == MI_LOVEFIST; }
bool IsRealHeli(void) { return !!(pHandling->Flags & HANDLING_IS_HELI); }
static bool bWheelsOnlyCheat;
diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp
index ebdeb38b..a6217d70 100644
--- a/src/weapons/Weapon.cpp
+++ b/src/weapons/Weapon.cpp
@@ -1271,7 +1271,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim,
}
case ENTITY_TYPE_VEHICLE:
{
- ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage);
+ ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, point->point);
for ( int32 i = 0; i < 16; i++ )
CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f);
@@ -1648,7 +1648,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource)
case ENTITY_TYPE_VEHICLE:
{
if (point.pieceB >= SURFACE_STREET_LIGHT && point.pieceB <= SURFACE_METAL_FENCE) {
- ((CVehicle*)victim)->BurstTyre(point.pieceB); // TODO(Miami): New parameter: ,true);
+ ((CVehicle*)victim)->BurstTyre(point.pieceB, true);
for (int32 i = 0; i < 4; i++)
CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, point.point, point.normal * 0.05f);