summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/control/CarAI.cpp8
-rw-r--r--src/control/CarCtrl.cpp163
-rw-r--r--src/control/CarCtrl.h5
-rw-r--r--src/control/PathFind.cpp14
-rw-r--r--src/control/PathFind.h4
-rw-r--r--src/control/Script.cpp6
-rw-r--r--src/core/Streaming.cpp9
-rw-r--r--src/core/Wanted.cpp6
-rw-r--r--src/core/Wanted.h1
-rw-r--r--src/modelinfo/ModelInfo.cpp7
-rw-r--r--src/modelinfo/ModelInfo.h1
-rw-r--r--src/peds/Ped.cpp8
-rw-r--r--src/peds/Ped.h7
-rw-r--r--src/peds/PedPlacement.cpp8
-rw-r--r--src/peds/PedPlacement.h2
-rw-r--r--src/peds/Population.cpp60
-rw-r--r--src/peds/Population.h5
-rw-r--r--src/vehicles/Vehicle.cpp1
-rw-r--r--src/vehicles/Vehicle.h1
19 files changed, 275 insertions, 41 deletions
diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp
index 0330d80d..c233178f 100644
--- a/src/control/CarAI.cpp
+++ b/src/control/CarAI.cpp
@@ -13,6 +13,7 @@
#include "DMAudio.h"
#include "Fire.h"
#include "Pools.h"
+#include "Population.h"
#include "Timer.h"
#include "TrafficLights.h"
#include "Vehicle.h"
@@ -560,18 +561,15 @@ void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
case MI_PREDATOR:
pVehicle->SetUpDriver();
return;
-//TODO(MIAMI) uncomment this when we have MI_VICECHEE
-/*
case MI_VICECHEE:
{
- pVehicle->SetUpDriver()->bIsMiamiViceCop = true;
- pVehicle->SetUpPassenger(0)->bIsMiamiViceCop = true;
+ pVehicle->SetUpDriver()->bMiamiViceCop = true;
+ pVehicle->SetupPassenger(0)->bMiamiViceCop = true;
CPopulation::NumMiamiViceCops += 2;
CCarCtrl::MiamiViceCycle = (CCarCtrl::MiamiViceCycle + 1) % 4;
CCarCtrl::LastTimeMiamiViceGenerated = CTimer::GetTimeInMilliseconds();
return;
}
-*/
default:
return;
}
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index 66e29b6c..699ccc20 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -20,6 +20,7 @@
#include "Ped.h"
#include "PlayerInfo.h"
#include "PlayerPed.h"
+#include "Population.h"
#include "Wanted.h"
#include "Pools.h"
#include "Renderer.h"
@@ -69,6 +70,10 @@
#define MIN_ANGLE_TO_APPLY_HANDBRAKE 0.7f
#define MIN_SPEED_TO_APPLY_HANDBRAKE 0.3f
+#define PROBABILITY_OF_DEAD_PED_ACCIDENT 0.005f
+#define DISTANCE_BETWEEN_CAR_AND_DEAD_PED 6.0f
+#define PROBABILITY_OF_PASSENGER_IN_VEHICLE 0.125f
+
int CCarCtrl::NumLawEnforcerCars;
int CCarCtrl::NumAmbulancesOnDuty;
int CCarCtrl::NumFiretrucksOnDuty;
@@ -83,6 +88,8 @@ int32 CCarCtrl::MaxNumberOfCarsInUse = 12;
uint32 CCarCtrl::LastTimeLawEnforcerCreated;
uint32 CCarCtrl::LastTimeFireTruckCreated;
uint32 CCarCtrl::LastTimeAmbulanceCreated;
+int32 CCarCtrl::MiamiViceCycle;
+uint32 CCarCtrl::LastTimeMiamiViceGenerated;
int32 CCarCtrl::TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
int32 CCarCtrl::CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
int32 CCarCtrl::NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
@@ -292,8 +299,17 @@ CCarCtrl::GenerateOneRandomCar()
return;
}
else {
- return;
- // TODO: normal boats
+ int i;
+ carModel = -1;
+ for (i = 10; i > 0 && (carModel == -1 || CStreaming::HasModelLoaded(carModel)); i--) {
+ carModel = ChooseBoatModel(ChooseBoatRating(&zone));
+ }
+ if (i == 0)
+ return;
+ }
+ if (pCurNode->bOnlySmallBoats || pNextNode->bOnlySmallBoats) {
+ if (BoatWithTallMast(carModel))
+ return;
}
}
}
@@ -320,8 +336,8 @@ CCarCtrl::GenerateOneRandomCar()
CVehicle* pVehicle;
if (CModelInfo::IsBoatModel(carModel))
pVehicle = new CBoat(carModel, RANDOM_VEHICLE);
- //else if (CModelInfo::IsBikeModel(carModel))
- // pVehicle = new CBike(carModel, RANDOM_VEHICLE);
+ else if (CModelInfo::IsBikeModel(carModel))
+ return; // TODO(MIAMI): spawn bikes
else
pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
pVehicle->AutoPilot.m_nPrevRouteNode = 0;
@@ -344,15 +360,15 @@ CCarCtrl::GenerateOneRandomCar()
if (carModel == MI_FBICAR){
pVehicle->m_currentColour1 = 0;
pVehicle->m_currentColour2 = 0;
- /* FBI cars are gray in carcols, but we want them black if they going after player. */
}
- // TODO(MIAMI): check the flag
+ pVehicle->bCreatedAsPoliceVehicle = true;
break;
case COPS_BOAT:
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(4.0f, 16.0f);
pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
pVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceBoatMissionForWantedLevel();
+ pVehicle->bCreatedAsPoliceVehicle = true;
break;
default:
pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14);
@@ -445,6 +461,8 @@ CCarCtrl::GenerateOneRandomCar()
/* Second fix: adding 0.5f is a mistake. It should be between 0 and 1. It was fixed in SA.*/
/* It is also correct in CAutoPilot::ModifySpeed. */
+
+ /* It seems like design decisions in VC were made based on this 0.5f addition. Can't remove it anymore. */
pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
(uint32)((0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve);
#else
@@ -520,15 +538,21 @@ CCarCtrl::GenerateOneRandomCar()
delete pVehicle;
return;
}
- }else if((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? 1.5f : 1.0f) * 120.0f ||
- (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 100.0f){
- delete pVehicle;
- return;
- }else if((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera ){
- delete pVehicle;
- return;
+ }else{
+ if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? 1.5f : 1.0f) * 120.0f ||
+ (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 100.0f) {
+ delete pVehicle;
+ return;
+ }
+ if ((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera) {
+ delete pVehicle;
+ return;
+ }
+ if (pVehicle->GetModelIndex() == MI_MARQUIS) { // so marquis can only spawn if player doesn't see it?
+ delete pVehicle;
+ return;
+ }
}
- // TODO(MIAMI): if MARQUIS then delete
CVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo();
float radiusToTest = pVehicleModel->GetColModel()->boundingSphere.radius;
if (testForCollision){
@@ -552,17 +576,93 @@ CCarCtrl::GenerateOneRandomCar()
CWorld::Add(pVehicle);
if (carClass == COPS || carClass == COPS_BOAT)
CCarAI::AddPoliceCarOccupants(pVehicle);
- else
- pVehicle->SetUpDriver(); //TODO(MIAMI): FIX!
- if ((CGeneral::GetRandomNumber() & 0x3F) == 0){ /* 1/64 probability */ /* TODO(MIAMI): FIX!*/
+ else {
+ pVehicle->SetUpDriver();
+ int32 passengers = 0;
+ for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++)
+ passengers += (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < PROBABILITY_OF_PASSENGER_IN_VEHICLE) ? 1 : 0;
+ if (CModelInfo::IsCarModel(carModel) && (CModelInfo::GetModelInfo(carModel)->GetAnimFileIndex() == CAnimManager::GetAnimationBlockIndex("van") && passengers >= 1))
+ passengers = 1;
+ for (int i = 0; i < passengers; i++) {
+ CPed* pPassenger = pVehicle->SetupPassenger(i);
+ if (pPassenger) {
+ ++CPopulation::ms_nTotalCarPassengerPeds;
+ pPassenger->bCarPassenger = true;
+ }
+ }
+ }
+ int nMadDrivers;
+ switch (pVehicle->GetVehicleAppearance()) {
+ case VEHICLE_BIKE:
+ nMadDrivers = 30;
+ break;
+ case VEHICLE_BOAT:
+ nMadDrivers = 40;
+ break;
+ default:
+ nMadDrivers = 6;
+ break;
+ }
+ if ((CGeneral::GetRandomNumber() & 0x7F) < nMadDrivers /* TODO(MIAMI): || mad drivers cheat */) {
pVehicle->SetStatus(STATUS_PHYSICS);
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
pVehicle->AutoPilot.m_nCruiseSpeed += 10;
}
if (carClass == COPS)
LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds();
- /* TODO(MIAMI): CADDY, VICECHEE, dead ped code*/
- return;
+ if (pVehicle->GetModelIndex() == MI_CADDY) {
+ pVehicle->SetStatus(STATUS_PHYSICS);
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ }
+ if (carClass == COPS && pVehicle->GetModelIndex() == MI_VICECHEE) {
+ CVehicleModelInfo* pVehicleModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_VICECHEE);
+ switch (MiamiViceCycle) {
+ case 0:
+ pVehicleModel->SetVehicleColour(53, 77);
+ break;
+ case 1:
+ pVehicleModel->SetVehicleColour(15, 77);
+ break;
+ case 2:
+ pVehicleModel->SetVehicleColour(41, 77);
+ break;
+ case 3:
+ pVehicleModel->SetVehicleColour(61, 77);
+ break;
+ default:
+ break;
+ }
+ }
+ if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) >= (1 - PROBABILITY_OF_DEAD_PED_ACCIDENT)) {
+ if (CModelInfo::IsCarModel(pVehicle->GetModelIndex()) && !pVehicle->bIsLawEnforcer) {
+ if (CPopulation::AddDeadPedInFrontOfCar(pVehicle->GetPosition() + pVehicle->GetForward() * DISTANCE_BETWEEN_CAR_AND_DEAD_PED, pVehicle)) {
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ pVehicle->SetMoveSpeed(0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < pVehicle->m_nNumPassengers; i++) {
+ if (pVehicle->pPassengers[i]) {
+ pVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
+ pVehicle->pPassengers[i]->m_nLastPedState = PED_WANDER_PATH;
+ pVehicle->pPassengers[i]->m_vehicleInAccident = pVehicle;
+ pVehicle->pPassengers[i]->bDeadPedInFrontOfCar = true;
+ pVehicle->RegisterReference((CEntity**)&pVehicle->pPassengers[i]->m_vehicleInAccident);
+ }
+ }
+ if (pVehicle->pDriver) {
+ pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, pVehicle);
+ pVehicle->pDriver->m_nLastPedState = PED_WANDER_PATH;
+ pVehicle->pDriver->m_vehicleInAccident = pVehicle;
+ pVehicle->pDriver->bDeadPedInFrontOfCar = true;
+ pVehicle->RegisterReference((CEntity**)&pVehicle->pDriver->m_vehicleInAccident);
+ }
+ }
+ }
+ }
+}
+
+bool
+CCarCtrl::BoatWithTallMast(int32 mi)
+{
+ return mi == MI_RIO || mi == MI_TROPIC || mi == MI_MARQUIS;
}
int32
@@ -680,6 +780,31 @@ CCarCtrl::ChooseCarModelToLoad(int rating)
int32
CCarCtrl::ChoosePoliceCarModel(void)
{
+ if (FindPlayerPed()->m_pWanted->AreMiamiViceRequired() &&
+ CTimer::GetTimeInMilliseconds() > LastTimeMiamiViceGenerated + 120000 &&
+ CStreaming::HasModelLoaded(MI_VICECHEE)) {
+ // TODO(MIAMI): setup correct models!
+ switch (MiamiViceCycle) {
+ case 0:
+ if (CStreaming::HasModelLoaded(MI_COP) && CStreaming::HasModelLoaded(MI_COP))
+ return MI_VICECHEE;
+ break;
+ case 1:
+ if (CStreaming::HasModelLoaded(MI_COP) && CStreaming::HasModelLoaded(MI_COP))
+ return MI_VICECHEE;
+ break;
+ case 2:
+ if (CStreaming::HasModelLoaded(MI_COP) && CStreaming::HasModelLoaded(MI_COP))
+ return MI_VICECHEE;
+ break;
+ case 3:
+ if (CStreaming::HasModelLoaded(MI_COP) && CStreaming::HasModelLoaded(MI_COP))
+ return MI_VICECHEE;
+ break;
+ default:
+ break;
+ }
+ }
if (FindPlayerPed()->m_pWanted->AreSwatRequired() &&
CStreaming::HasModelLoaded(MI_ENFORCER) &&
CStreaming::HasModelLoaded(MI_POLICE))
diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h
index ce25c206..f66b9232 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -124,7 +124,8 @@ public:
static int32 ChooseCarRating(CZoneInfo* pZoneInfo);
static void AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq);
static void RemoveFromLoadedVehicleArray(int32 mi, int32 rating);
- static int32 ChooseCarModelToLoad(int rating);
+ static int32 ChooseCarModelToLoad(int32 rating);
+ static bool BoatWithTallMast(int32 mi);
static float GetPositionAlongCurrentCurve(CVehicle* pVehicle)
{
@@ -158,6 +159,8 @@ public:
static int32 TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
static int32 CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+ static int32 MiamiViceCycle;
+ static uint32 LastTimeMiamiViceGenerated;
static int32 NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
static int32 NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
static int32 CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp
index 20c4aa69..4a948032 100644
--- a/src/control/PathFind.cpp
+++ b/src/control/PathFind.cpp
@@ -322,7 +322,7 @@ CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x,
InfoForTilePeds[i].roadBlock = false;
InfoForTilePeds[i].disabled = false;
InfoForTilePeds[i].waterPath = false;
- InfoForTilePeds[i].flag02 = false;
+ InfoForTilePeds[i].onlySmallBoats = false;
InfoForTilePeds[i].betweenLevels = false;
InfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
@@ -351,7 +351,7 @@ CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x,
InfoForTilePeds[i].roadBlock = false;
InfoForTilePeds[i].disabled = false;
InfoForTilePeds[i].waterPath = false;
- InfoForTilePeds[i].flag02 = false;
+ InfoForTilePeds[i].onlySmallBoats = false;
InfoForTilePeds[i].betweenLevels = false;
InfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
@@ -383,7 +383,7 @@ CPathFind::StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x,
DetachedInfoForTilePeds[i].roadBlock = false;
DetachedInfoForTilePeds[i].disabled = disabled;
DetachedInfoForTilePeds[i].waterPath = false;
- DetachedInfoForTilePeds[i].flag02 = false;
+ DetachedInfoForTilePeds[i].onlySmallBoats = false;
DetachedInfoForTilePeds[i].betweenLevels = betweenLevels;
DetachedInfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
@@ -396,7 +396,7 @@ CPathFind::StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x,
//--MIAMI: done
void
CPathFind::StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight,
- bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool unk)
+ bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool onlySmallBoats)
{
int i;
@@ -417,7 +417,7 @@ CPathFind::StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x,
DetachedInfoForTileCars[i].roadBlock = roadBlock;
DetachedInfoForTileCars[i].disabled = disabled;
DetachedInfoForTileCars[i].waterPath = waterPath;
- DetachedInfoForTileCars[i].flag02 = unk;
+ DetachedInfoForTileCars[i].onlySmallBoats = onlySmallBoats;
DetachedInfoForTileCars[i].betweenLevels = betweenLevels;
DetachedInfoForTileCars[i].spawnRate = Min(spawnRate, 15);
@@ -655,7 +655,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
m_pathNodes[m_numPathNodes].bUseInRoadBlock = objectpathinfo[start + j].roadBlock;
m_pathNodes[m_numPathNodes].bDisabled = objectpathinfo[start + j].disabled;
m_pathNodes[m_numPathNodes].bWaterPath = objectpathinfo[start + j].waterPath;
- m_pathNodes[m_numPathNodes].flagB2 = objectpathinfo[start + j].flag02;
+ m_pathNodes[m_numPathNodes].bOnlySmallBoats = objectpathinfo[start + j].onlySmallBoats;
m_pathNodes[m_numPathNodes].bBetweenLevels = objectpathinfo[start + j].betweenLevels;
m_numPathNodes++;
}
@@ -696,7 +696,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
m_pathNodes[m_numPathNodes].bUseInRoadBlock = detachednodes[start + j].roadBlock;
m_pathNodes[m_numPathNodes].bDisabled = detachednodes[start + j].disabled;
m_pathNodes[m_numPathNodes].bWaterPath = detachednodes[start + j].waterPath;
- m_pathNodes[m_numPathNodes].flagB2 = detachednodes[start + j].flag02;
+ m_pathNodes[m_numPathNodes].bOnlySmallBoats = detachednodes[start + j].onlySmallBoats;
m_pathNodes[m_numPathNodes].bBetweenLevels = detachednodes[start + j].betweenLevels;
m_numPathNodes++;
}else if(detachednodes[start + j].type == NodeTypeExtern){
diff --git a/src/control/PathFind.h b/src/control/PathFind.h
index 51bdbd7f..5f5de3e1 100644
--- a/src/control/PathFind.h
+++ b/src/control/PathFind.h
@@ -69,7 +69,7 @@ struct CPathNode
uint8 bUseInRoadBlock : 1;
uint8 bWaterPath : 1;
- uint8 flagB2 : 1; // flag 2 in node info, always zero
+ uint8 bOnlySmallBoats : 1;
uint8 flagB4 : 1; // where is this set?
uint8 speedLimit : 2;
//uint8 flagB20 : 1;
@@ -145,7 +145,7 @@ struct CPathInfoForObject
int8 width;
uint8 crossing : 1;
- uint8 flag02 : 1; // always zero
+ uint8 onlySmallBoats : 1;
uint8 roadBlock : 1;
uint8 disabled : 1;
uint8 waterPath : 1;
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index dabb0571..b6729486 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -3089,7 +3089,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
case COMMAND_SET_ZONE_CAR_INFO:
{
char label[12];
- int16 gangDensities[NUM_GANGS];
+ int16 gangDensities[NUM_GANGS] = { 0 };
int i;
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
@@ -9849,8 +9849,8 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
case COMMAND_SET_ZONE_CIVILIAN_CAR_INFO:
{
char label[12];
- int16 carDensities[CCarCtrl::NUM_CAR_CLASSES];
- int16 boatDensities[CCarCtrl::NUM_BOAT_CLASSES];
+ int16 carDensities[CCarCtrl::NUM_CAR_CLASSES] = { 0 };
+ int16 boatDensities[CCarCtrl::NUM_BOAT_CLASSES] = { 0 };
int i;
CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp
index b1a73607..eb7fc8f5 100644
--- a/src/core/Streaming.cpp
+++ b/src/core/Streaming.cpp
@@ -1396,6 +1396,15 @@ CStreaming::StreamVehiclesAndPeds(void)
else
SetModelIsDeletable(MI_CHOPPER);
+ if (FindPlayerPed()->m_pWanted->AreMiamiViceRequired()) {
+ //TODO(MIAMI): miami vice peds
+ RequestModel(MI_VICECHEE, STREAMFLAGS_DONT_REMOVE);
+ }
+ else {
+ SetModelIsDeletable(MI_VICECHEE);
+ //TODO(MIAMI): miami vice peds
+ }
+
if(timeBeforeNextLoad >= 0)
timeBeforeNextLoad--;
else if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){
diff --git a/src/core/Wanted.cpp b/src/core/Wanted.cpp
index 7508c9f4..ff82edad 100644
--- a/src/core/Wanted.cpp
+++ b/src/core/Wanted.cpp
@@ -40,6 +40,12 @@ CWanted::Initialise()
}
bool
+CWanted::AreMiamiViceRequired()
+{
+ return m_nWantedLevel >= 3;
+}
+
+bool
CWanted::AreSwatRequired()
{
return m_nWantedLevel == 4 || m_bSwatRequired;
diff --git a/src/core/Wanted.h b/src/core/Wanted.h
index e3e407b0..0e0e70c3 100644
--- a/src/core/Wanted.h
+++ b/src/core/Wanted.h
@@ -31,6 +31,7 @@ public:
public:
void Initialise();
+ bool AreMiamiViceRequired();
bool AreSwatRequired();
bool AreFbiRequired();
bool AreArmyRequired();
diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp
index 79353b1b..29466777 100644
--- a/src/modelinfo/ModelInfo.cpp
+++ b/src/modelinfo/ModelInfo.cpp
@@ -199,6 +199,13 @@ CModelInfo::IsBikeModel(int32 id)
((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_BIKE;
}
+bool
+CModelInfo::IsCarModel(int32 id)
+{
+ return GetModelInfo(id)->GetModelType() == MITYPE_VEHICLE &&
+ ((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_CAR;
+}
+
void
CModelInfo::ReInit2dEffects()
{
diff --git a/src/modelinfo/ModelInfo.h b/src/modelinfo/ModelInfo.h
index 46f8c117..fd545e3d 100644
--- a/src/modelinfo/ModelInfo.h
+++ b/src/modelinfo/ModelInfo.h
@@ -39,5 +39,6 @@ public:
static bool IsBoatModel(int32 id);
static bool IsBikeModel(int32 id);
+ static bool IsCarModel(int32 id);
static void ReInit2dEffects();
};
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 3b95dfdd..8a86360b 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -402,6 +402,10 @@ CPed::~CPed(void)
}
if (m_pFire)
m_pFire->Extinguish();
+ if (bCarPassenger)
+ CPopulation::ms_nTotalCarPassengerPeds--;
+ if (bMiamiViceCop)
+ CPopulation::NumMiamiViceCops--;
CPopulation::UpdatePedCount((ePedType)m_nPedType, true);
DMAudio.DestroyEntity(m_audioEntityId);
}
@@ -605,6 +609,10 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
bSomeVCflag1 = false;
#endif
+ bCarPassenger = false;
+ bMiamiViceCop = false;
+ bDeadPedInFrontOfCar = false;
+
if ((CGeneral::GetRandomNumber() & 3) == 0)
bHasACamera = true;
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 9f105e7a..209aeb40 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -389,6 +389,10 @@ public:
uint32 m_ped_flagI40 : 1; // bMakePedsRunToPhonesToReportCrimes makes use of this as runover by car indicator
uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle
+ uint32 bCarPassenger : 1;
+ uint32 bMiamiViceCop : 1; //
+ uint32 bDeadPedInFrontOfCar : 1;
+
uint8 CharCreatedBy;
eObjective m_objective;
eObjective m_prevObjective;
@@ -452,6 +456,9 @@ public:
CVehicle *m_pMyVehicle;
bool bInVehicle;
float m_distanceToCountSeekDone;
+
+ CVehicle* m_vehicleInAccident;
+
bool bRunningToPhone;
int16 m_phoneId;
eCrimeType m_crimeToReportOnPhone;
diff --git a/src/peds/PedPlacement.cpp b/src/peds/PedPlacement.cpp
index 2d4a92fa..6011ce44 100644
--- a/src/peds/PedPlacement.cpp
+++ b/src/peds/PedPlacement.cpp
@@ -43,9 +43,13 @@ CPedPlacement::IsPositionClearOfCars(Const CVector *pos)
}
bool
-CPedPlacement::IsPositionClearForPed(CVector* pos)
+CPedPlacement::IsPositionClearForPed(const CVector& pos, float radius, int total, CEntity** entities)
{
int16 count;
- CWorld::FindObjectsKindaColliding(*pos, 0.75f, true, &count, 2, nil, false, true, true, false, false);
+ if (radius == -1.0f)
+ radius = 0.75f;
+ if (total == -1)
+ total = 2;
+ CWorld::FindObjectsKindaColliding(pos, radius, true, &count, total, entities, false, true, true, false, false);
return count == 0;
}
diff --git a/src/peds/PedPlacement.h b/src/peds/PedPlacement.h
index b51e2aad..5b8354d4 100644
--- a/src/peds/PedPlacement.h
+++ b/src/peds/PedPlacement.h
@@ -4,5 +4,5 @@ class CPedPlacement {
public:
static void FindZCoorForPed(CVector* pos);
static CEntity* IsPositionClearOfCars(Const CVector*);
- static bool IsPositionClearForPed(CVector*);
+ static bool IsPositionClearForPed(const CVector& pos, float radius = -1.0f, int total = -1, CEntity** entities = nil);
}; \ No newline at end of file
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp
index ba8e1a74..1d8c7f5d 100644
--- a/src/peds/Population.cpp
+++ b/src/peds/Population.cpp
@@ -83,6 +83,9 @@ CVector CPopulation::RegenerationPoint_a;
CVector CPopulation::RegenerationPoint_b;
CVector CPopulation::RegenerationForward;
+uint32 CPopulation::ms_nTotalCarPassengerPeds;
+uint32 CPopulation::NumMiamiViceCops;
+
void
CPopulation::Initialise()
{
@@ -103,6 +106,8 @@ CPopulation::Initialise()
ms_nNumGang9 = 0;
ms_nNumDummy = 0;
+ ms_nTotalCarPassengerPeds = 0;
+
m_AllRandomPedsThisType = -1;
PedDensityMultiplier = 1.0f;
bZoneChangeHasHappened = false;
@@ -398,6 +403,7 @@ CPopulation::Update()
+ ms_nNumGang2 + ms_nNumGang1;
ms_nTotalPeds = ms_nNumDummy + ms_nNumEmergency + ms_nNumCop
+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;
+ ms_nTotalPeds -= ms_nTotalCarPassengerPeds;
if (!CCutsceneMgr::IsRunning()) {
float pcdm = PedCreationDistMultiplier();
AddToPopulation(pcdm * (MIN_CREATION_DIST * TheCamera.GenerationDistMultiplier),
@@ -419,6 +425,7 @@ CPopulation::GeneratePedsAtStartOfGame()
+ ms_nNumGang3 + ms_nNumGang2 + ms_nNumGang1;
ms_nTotalPeds = ms_nNumDummy + ms_nNumEmergency + ms_nNumCop
+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;
+ ms_nTotalPeds -= ms_nTotalCarPassengerPeds;
// Min dist is 10.0f only for start of the game (naturally)
AddToPopulation(10.0f, PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE),
@@ -656,7 +663,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
generatedCoors.y = yOffset + gangLeader->GetPosition().y;
}
}
- if (!CPedPlacement::IsPositionClearForPed(&generatedCoors))
+ if (!CPedPlacement::IsPositionClearForPed(generatedCoors))
break;
// Why no love for last gang member?!
@@ -733,6 +740,7 @@ CPopulation::AddPedInCar(CVehicle* car)
break;
case MI_POLICE:
case MI_PREDATOR:
+ case MI_VICECHEE: // TODO(MIAMI): proper model
preferredModel = COP_STREET;
pedType = PEDTYPE_COP;
break;
@@ -1016,6 +1024,10 @@ CPopulation::ManagePopulation(void)
}
float dist = (ped->GetPosition() - playerPos).Magnitude2D();
+
+ if (ped->IsGangMember() || (ped->bDeadPedInFrontOfCar && ped->m_vehicleInAccident))
+ dist -= 30.0f;
+
bool pedIsFarAway = false;
if (PedCreationDistMultiplier() * (PED_REMOVE_DIST_SPECIAL * TheCamera.GenerationDistMultiplier) < dist
|| (!ped->bCullExtraFarAway && PedCreationDistMultiplier() * PED_REMOVE_DIST * TheCamera.GenerationDistMultiplier < dist)
@@ -1062,3 +1074,49 @@ CPopulation::ManagePopulation(void)
}
}
}
+
+CPed*
+CPopulation::AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit)
+{
+ if (TheCamera.IsSphereVisible(pos, 2.0f)) {
+ float fDistanceToPlayer = (pos - FindPlayerPed()->GetPosition()).Magnitude2D();
+ float fDistanceMultiplier;
+ if (FindPlayerVehicle())
+ fDistanceMultiplier = clamp(FindPlayerVehicle()->GetMoveSpeed().Magnitude2D() - 0.1f + 1.0f, 1.0f, 1.5f);
+ else
+ fDistanceMultiplier = 1.0f;
+ if (40.0f * fDistanceMultiplier > fDistanceToPlayer)
+ return nil;
+ }
+ bool found;
+ float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &found) + 1.0f;
+ if (!found)
+ return nil;
+ z = Max(z, pos.z);
+ if (!CModelInfo::GetModelInfo(MI_MALE01)->GetRwObject()) // strange way to check it
+ return nil;
+ CPed* pPed = CPopulation::AddPed(PEDTYPE_CIVMALE, MI_MALE01, pos); // TODO(MIAMI): 4th parameter
+ pPed->SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+ //TODO(MIAMI): set money == 0
+ pPed->bDeadPedInFrontOfCar = true;
+ pPed->m_vehicleInAccident = pCulprit;
+ pCulprit->RegisterReference((CEntity**)&pPed->m_vehicleInAccident);
+ CEntity* pEntities[3] = { 0 };
+ if (!CPedPlacement::IsPositionClearForPed(pos, 2.0f, 3, pEntities)) {
+ for (int i = 0; i < 3; i++) {
+ if (pEntities[i] && pEntities[i] != pCulprit && pEntities[i] != pPed) {
+ CWorld::Remove(pPed);
+ delete pPed;
+ return nil;
+ }
+ }
+ }
+ CColPoint colpts[32];
+ if (CCollision::ProcessColModels(pCulprit->GetMatrix(), *pCulprit->GetColModel(), pPed->GetMatrix(), *pPed->GetColModel(), colpts, nil, nil)) {
+ CWorld::Remove(pPed);
+ delete pPed;
+ return nil;
+ }
+ CVisibilityPlugins::SetClumpAlpha(pPed->GetClump(), 0);
+ return pPed;
+}
diff --git a/src/peds/Population.h b/src/peds/Population.h
index aa8129c0..181c5809 100644
--- a/src/peds/Population.h
+++ b/src/peds/Population.h
@@ -62,6 +62,9 @@ public:
static CVector RegenerationPoint_b;
static CVector RegenerationForward;
+ static uint32 ms_nTotalCarPassengerPeds;
+ static uint32 NumMiamiViceCops;
+
static void Initialise();
static void Update(void);
static void LoadPedGroups();
@@ -86,4 +89,6 @@ public:
static void ConvertAllObjectsToDummyObjects(void);
static bool TestRoomForDummyObject(CObject*);
static bool TestSafeForRealObject(CDummyObject*);
+
+ static CPed* AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit);
};
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index 5fdbde06..1cf41435 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -99,6 +99,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
m_bSirenOrAlarm = 0;
m_nCarHornTimer = 0;
m_nCarHornPattern = 0;
+ bCreatedAsPoliceVehicle = false;
bParking = false;
m_nAlarmState = 0;
m_nDoorLock = CARLOCK_UNLOCKED;
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index 66dfebb1..7711e445 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -182,6 +182,7 @@ public:
uint8 bIsCarParkVehicle : 1; // Car has been created using the special CAR_PARK script command
uint8 bHasAlreadyBeenRecorded : 1; // Used for replays
+ uint8 bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc)
uint8 bParking : 1;
int8 m_numPedsUseItAsCover;