CCarCtrl::GenerateOneRandomCar

This commit is contained in:
Nikolay Korolev 2020-05-08 23:29:43 +03:00
parent f902136b6a
commit 7e753c2596
19 changed files with 275 additions and 41 deletions

View File

@ -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;
}

View File

@ -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))

View File

@ -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];

View File

@ -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){

View File

@ -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;

View File

@ -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);

View File

@ -1292,6 +1292,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){

View File

@ -39,6 +39,12 @@ CWanted::Initialise()
ClearQdCrimes();
}
bool
CWanted::AreMiamiViceRequired()
{
return m_nWantedLevel >= 3;
}
bool
CWanted::AreSwatRequired()
{

View File

@ -31,6 +31,7 @@ public:
public:
void Initialise();
bool AreMiamiViceRequired();
bool AreSwatRequired();
bool AreFbiRequired();
bool AreArmyRequired();

View File

@ -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()
{

View File

@ -39,5 +39,6 @@ public:
static bool IsBoatModel(int32 id);
static bool IsBikeModel(int32 id);
static bool IsCarModel(int32 id);
static void ReInit2dEffects();
};

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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;

View File

@ -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;