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 "DMAudio.h"
#include "Fire.h" #include "Fire.h"
#include "Pools.h" #include "Pools.h"
#include "Population.h"
#include "Timer.h" #include "Timer.h"
#include "TrafficLights.h" #include "TrafficLights.h"
#include "Vehicle.h" #include "Vehicle.h"
@ -560,18 +561,15 @@ void CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)
case MI_PREDATOR: case MI_PREDATOR:
pVehicle->SetUpDriver(); pVehicle->SetUpDriver();
return; return;
//TODO(MIAMI) uncomment this when we have MI_VICECHEE
/*
case MI_VICECHEE: case MI_VICECHEE:
{ {
pVehicle->SetUpDriver()->bIsMiamiViceCop = true; pVehicle->SetUpDriver()->bMiamiViceCop = true;
pVehicle->SetUpPassenger(0)->bIsMiamiViceCop = true; pVehicle->SetupPassenger(0)->bMiamiViceCop = true;
CPopulation::NumMiamiViceCops += 2; CPopulation::NumMiamiViceCops += 2;
CCarCtrl::MiamiViceCycle = (CCarCtrl::MiamiViceCycle + 1) % 4; CCarCtrl::MiamiViceCycle = (CCarCtrl::MiamiViceCycle + 1) % 4;
CCarCtrl::LastTimeMiamiViceGenerated = CTimer::GetTimeInMilliseconds(); CCarCtrl::LastTimeMiamiViceGenerated = CTimer::GetTimeInMilliseconds();
return; return;
} }
*/
default: default:
return; return;
} }

View File

@ -20,6 +20,7 @@
#include "Ped.h" #include "Ped.h"
#include "PlayerInfo.h" #include "PlayerInfo.h"
#include "PlayerPed.h" #include "PlayerPed.h"
#include "Population.h"
#include "Wanted.h" #include "Wanted.h"
#include "Pools.h" #include "Pools.h"
#include "Renderer.h" #include "Renderer.h"
@ -69,6 +70,10 @@
#define MIN_ANGLE_TO_APPLY_HANDBRAKE 0.7f #define MIN_ANGLE_TO_APPLY_HANDBRAKE 0.7f
#define MIN_SPEED_TO_APPLY_HANDBRAKE 0.3f #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::NumLawEnforcerCars;
int CCarCtrl::NumAmbulancesOnDuty; int CCarCtrl::NumAmbulancesOnDuty;
int CCarCtrl::NumFiretrucksOnDuty; int CCarCtrl::NumFiretrucksOnDuty;
@ -83,6 +88,8 @@ int32 CCarCtrl::MaxNumberOfCarsInUse = 12;
uint32 CCarCtrl::LastTimeLawEnforcerCreated; uint32 CCarCtrl::LastTimeLawEnforcerCreated;
uint32 CCarCtrl::LastTimeFireTruckCreated; uint32 CCarCtrl::LastTimeFireTruckCreated;
uint32 CCarCtrl::LastTimeAmbulanceCreated; uint32 CCarCtrl::LastTimeAmbulanceCreated;
int32 CCarCtrl::MiamiViceCycle;
uint32 CCarCtrl::LastTimeMiamiViceGenerated;
int32 CCarCtrl::TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES]; int32 CCarCtrl::TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
int32 CCarCtrl::CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY]; int32 CCarCtrl::CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
int32 CCarCtrl::NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES]; int32 CCarCtrl::NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
@ -292,8 +299,17 @@ CCarCtrl::GenerateOneRandomCar()
return; return;
} }
else { else {
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; return;
// TODO: normal boats
} }
} }
} }
@ -320,8 +336,8 @@ CCarCtrl::GenerateOneRandomCar()
CVehicle* pVehicle; CVehicle* pVehicle;
if (CModelInfo::IsBoatModel(carModel)) if (CModelInfo::IsBoatModel(carModel))
pVehicle = new CBoat(carModel, RANDOM_VEHICLE); pVehicle = new CBoat(carModel, RANDOM_VEHICLE);
//else if (CModelInfo::IsBikeModel(carModel)) else if (CModelInfo::IsBikeModel(carModel))
// pVehicle = new CBike(carModel, RANDOM_VEHICLE); return; // TODO(MIAMI): spawn bikes
else else
pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE); pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
pVehicle->AutoPilot.m_nPrevRouteNode = 0; pVehicle->AutoPilot.m_nPrevRouteNode = 0;
@ -344,15 +360,15 @@ CCarCtrl::GenerateOneRandomCar()
if (carModel == MI_FBICAR){ if (carModel == MI_FBICAR){
pVehicle->m_currentColour1 = 0; pVehicle->m_currentColour1 = 0;
pVehicle->m_currentColour2 = 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; break;
case COPS_BOAT: case COPS_BOAT:
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(4.0f, 16.0f); pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(4.0f, 16.0f);
pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed; pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
pVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceBoatMissionForWantedLevel(); pVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceBoatMissionForWantedLevel();
pVehicle->bCreatedAsPoliceVehicle = true;
break; break;
default: default:
pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14); 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.*/ /* 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 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() - pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
(uint32)((0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); (uint32)((0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve);
#else #else
@ -520,15 +538,21 @@ CCarCtrl::GenerateOneRandomCar()
delete pVehicle; delete pVehicle;
return; return;
} }
}else if((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? 1.5f : 1.0f) * 120.0f || }else{
if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? 1.5f : 1.0f) * 120.0f ||
(vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 100.0f) { (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 100.0f) {
delete pVehicle; delete pVehicle;
return; return;
}else if((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera ){ }
if ((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera) {
delete pVehicle; delete pVehicle;
return; return;
} }
// TODO(MIAMI): if MARQUIS then delete if (pVehicle->GetModelIndex() == MI_MARQUIS) { // so marquis can only spawn if player doesn't see it?
delete pVehicle;
return;
}
}
CVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo(); CVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo();
float radiusToTest = pVehicleModel->GetColModel()->boundingSphere.radius; float radiusToTest = pVehicleModel->GetColModel()->boundingSphere.radius;
if (testForCollision){ if (testForCollision){
@ -552,17 +576,93 @@ CCarCtrl::GenerateOneRandomCar()
CWorld::Add(pVehicle); CWorld::Add(pVehicle);
if (carClass == COPS || carClass == COPS_BOAT) if (carClass == COPS || carClass == COPS_BOAT)
CCarAI::AddPoliceCarOccupants(pVehicle); CCarAI::AddPoliceCarOccupants(pVehicle);
else else {
pVehicle->SetUpDriver(); //TODO(MIAMI): FIX! pVehicle->SetUpDriver();
if ((CGeneral::GetRandomNumber() & 0x3F) == 0){ /* 1/64 probability */ /* TODO(MIAMI): FIX!*/ 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->SetStatus(STATUS_PHYSICS);
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS; pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
pVehicle->AutoPilot.m_nCruiseSpeed += 10; pVehicle->AutoPilot.m_nCruiseSpeed += 10;
} }
if (carClass == COPS) if (carClass == COPS)
LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds(); LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds();
/* TODO(MIAMI): CADDY, VICECHEE, dead ped code*/ if (pVehicle->GetModelIndex() == MI_CADDY) {
return; 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 int32
@ -680,6 +780,31 @@ CCarCtrl::ChooseCarModelToLoad(int rating)
int32 int32
CCarCtrl::ChoosePoliceCarModel(void) 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() && if (FindPlayerPed()->m_pWanted->AreSwatRequired() &&
CStreaming::HasModelLoaded(MI_ENFORCER) && CStreaming::HasModelLoaded(MI_ENFORCER) &&
CStreaming::HasModelLoaded(MI_POLICE)) CStreaming::HasModelLoaded(MI_POLICE))

View File

@ -124,7 +124,8 @@ public:
static int32 ChooseCarRating(CZoneInfo* pZoneInfo); static int32 ChooseCarRating(CZoneInfo* pZoneInfo);
static void AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq); static void AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq);
static void RemoveFromLoadedVehicleArray(int32 mi, int32 rating); 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) static float GetPositionAlongCurrentCurve(CVehicle* pVehicle)
{ {
@ -158,6 +159,8 @@ public:
static int32 TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES]; static int32 TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
static int32 CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY]; 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 NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
static int32 NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES]; static int32 NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
static int32 CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY]; 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].roadBlock = false;
InfoForTilePeds[i].disabled = false; InfoForTilePeds[i].disabled = false;
InfoForTilePeds[i].waterPath = false; InfoForTilePeds[i].waterPath = false;
InfoForTilePeds[i].flag02 = false; InfoForTilePeds[i].onlySmallBoats = false;
InfoForTilePeds[i].betweenLevels = false; InfoForTilePeds[i].betweenLevels = false;
InfoForTilePeds[i].spawnRate = Min(spawnRate, 15); 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].roadBlock = false;
InfoForTilePeds[i].disabled = false; InfoForTilePeds[i].disabled = false;
InfoForTilePeds[i].waterPath = false; InfoForTilePeds[i].waterPath = false;
InfoForTilePeds[i].flag02 = false; InfoForTilePeds[i].onlySmallBoats = false;
InfoForTilePeds[i].betweenLevels = false; InfoForTilePeds[i].betweenLevels = false;
InfoForTilePeds[i].spawnRate = Min(spawnRate, 15); 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].roadBlock = false;
DetachedInfoForTilePeds[i].disabled = disabled; DetachedInfoForTilePeds[i].disabled = disabled;
DetachedInfoForTilePeds[i].waterPath = false; DetachedInfoForTilePeds[i].waterPath = false;
DetachedInfoForTilePeds[i].flag02 = false; DetachedInfoForTilePeds[i].onlySmallBoats = false;
DetachedInfoForTilePeds[i].betweenLevels = betweenLevels; DetachedInfoForTilePeds[i].betweenLevels = betweenLevels;
DetachedInfoForTilePeds[i].spawnRate = Min(spawnRate, 15); DetachedInfoForTilePeds[i].spawnRate = Min(spawnRate, 15);
@ -396,7 +396,7 @@ CPathFind::StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x,
//--MIAMI: done //--MIAMI: done
void void
CPathFind::StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight, 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; int i;
@ -417,7 +417,7 @@ CPathFind::StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x,
DetachedInfoForTileCars[i].roadBlock = roadBlock; DetachedInfoForTileCars[i].roadBlock = roadBlock;
DetachedInfoForTileCars[i].disabled = disabled; DetachedInfoForTileCars[i].disabled = disabled;
DetachedInfoForTileCars[i].waterPath = waterPath; DetachedInfoForTileCars[i].waterPath = waterPath;
DetachedInfoForTileCars[i].flag02 = unk; DetachedInfoForTileCars[i].onlySmallBoats = onlySmallBoats;
DetachedInfoForTileCars[i].betweenLevels = betweenLevels; DetachedInfoForTileCars[i].betweenLevels = betweenLevels;
DetachedInfoForTileCars[i].spawnRate = Min(spawnRate, 15); 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].bUseInRoadBlock = objectpathinfo[start + j].roadBlock;
m_pathNodes[m_numPathNodes].bDisabled = objectpathinfo[start + j].disabled; m_pathNodes[m_numPathNodes].bDisabled = objectpathinfo[start + j].disabled;
m_pathNodes[m_numPathNodes].bWaterPath = objectpathinfo[start + j].waterPath; 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_pathNodes[m_numPathNodes].bBetweenLevels = objectpathinfo[start + j].betweenLevels;
m_numPathNodes++; 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].bUseInRoadBlock = detachednodes[start + j].roadBlock;
m_pathNodes[m_numPathNodes].bDisabled = detachednodes[start + j].disabled; m_pathNodes[m_numPathNodes].bDisabled = detachednodes[start + j].disabled;
m_pathNodes[m_numPathNodes].bWaterPath = detachednodes[start + j].waterPath; 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_pathNodes[m_numPathNodes].bBetweenLevels = detachednodes[start + j].betweenLevels;
m_numPathNodes++; m_numPathNodes++;
}else if(detachednodes[start + j].type == NodeTypeExtern){ }else if(detachednodes[start + j].type == NodeTypeExtern){

View File

@ -69,7 +69,7 @@ struct CPathNode
uint8 bUseInRoadBlock : 1; uint8 bUseInRoadBlock : 1;
uint8 bWaterPath : 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 flagB4 : 1; // where is this set?
uint8 speedLimit : 2; uint8 speedLimit : 2;
//uint8 flagB20 : 1; //uint8 flagB20 : 1;
@ -145,7 +145,7 @@ struct CPathInfoForObject
int8 width; int8 width;
uint8 crossing : 1; uint8 crossing : 1;
uint8 flag02 : 1; // always zero uint8 onlySmallBoats : 1;
uint8 roadBlock : 1; uint8 roadBlock : 1;
uint8 disabled : 1; uint8 disabled : 1;
uint8 waterPath : 1; uint8 waterPath : 1;

View File

@ -3089,7 +3089,7 @@ int8 CRunningScript::ProcessCommands300To399(int32 command)
case COMMAND_SET_ZONE_CAR_INFO: case COMMAND_SET_ZONE_CAR_INFO:
{ {
char label[12]; char label[12];
int16 gangDensities[NUM_GANGS]; int16 gangDensities[NUM_GANGS] = { 0 };
int i; int i;
CTheScripts::ReadTextLabelFromScript(&m_nIp, label); CTheScripts::ReadTextLabelFromScript(&m_nIp, label);
@ -9849,8 +9849,8 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
case COMMAND_SET_ZONE_CIVILIAN_CAR_INFO: case COMMAND_SET_ZONE_CIVILIAN_CAR_INFO:
{ {
char label[12]; char label[12];
int16 carDensities[CCarCtrl::NUM_CAR_CLASSES]; int16 carDensities[CCarCtrl::NUM_CAR_CLASSES] = { 0 };
int16 boatDensities[CCarCtrl::NUM_BOAT_CLASSES]; int16 boatDensities[CCarCtrl::NUM_BOAT_CLASSES] = { 0 };
int i; int i;
CTheScripts::ReadTextLabelFromScript(&m_nIp, label); CTheScripts::ReadTextLabelFromScript(&m_nIp, label);

View File

@ -1292,6 +1292,15 @@ CStreaming::StreamVehiclesAndPeds(void)
else else
SetModelIsDeletable(MI_CHOPPER); 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) if(timeBeforeNextLoad >= 0)
timeBeforeNextLoad--; timeBeforeNextLoad--;
else if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){ else if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){

View File

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

View File

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

View File

@ -199,6 +199,13 @@ CModelInfo::IsBikeModel(int32 id)
((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_BIKE; ((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 void
CModelInfo::ReInit2dEffects() CModelInfo::ReInit2dEffects()
{ {

View File

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

View File

@ -402,6 +402,10 @@ CPed::~CPed(void)
} }
if (m_pFire) if (m_pFire)
m_pFire->Extinguish(); m_pFire->Extinguish();
if (bCarPassenger)
CPopulation::ms_nTotalCarPassengerPeds--;
if (bMiamiViceCop)
CPopulation::NumMiamiViceCops--;
CPopulation::UpdatePedCount((ePedType)m_nPedType, true); CPopulation::UpdatePedCount((ePedType)m_nPedType, true);
DMAudio.DestroyEntity(m_audioEntityId); DMAudio.DestroyEntity(m_audioEntityId);
} }
@ -605,6 +609,10 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
bSomeVCflag1 = false; bSomeVCflag1 = false;
#endif #endif
bCarPassenger = false;
bMiamiViceCop = false;
bDeadPedInFrontOfCar = false;
if ((CGeneral::GetRandomNumber() & 3) == 0) if ((CGeneral::GetRandomNumber() & 3) == 0)
bHasACamera = true; 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_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 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; uint8 CharCreatedBy;
eObjective m_objective; eObjective m_objective;
eObjective m_prevObjective; eObjective m_prevObjective;
@ -452,6 +456,9 @@ public:
CVehicle *m_pMyVehicle; CVehicle *m_pMyVehicle;
bool bInVehicle; bool bInVehicle;
float m_distanceToCountSeekDone; float m_distanceToCountSeekDone;
CVehicle* m_vehicleInAccident;
bool bRunningToPhone; bool bRunningToPhone;
int16 m_phoneId; int16 m_phoneId;
eCrimeType m_crimeToReportOnPhone; eCrimeType m_crimeToReportOnPhone;

View File

@ -43,9 +43,13 @@ CPedPlacement::IsPositionClearOfCars(Const CVector *pos)
} }
bool bool
CPedPlacement::IsPositionClearForPed(CVector* pos) CPedPlacement::IsPositionClearForPed(const CVector& pos, float radius, int total, CEntity** entities)
{ {
int16 count; 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; return count == 0;
} }

View File

@ -4,5 +4,5 @@ class CPedPlacement {
public: public:
static void FindZCoorForPed(CVector* pos); static void FindZCoorForPed(CVector* pos);
static CEntity* IsPositionClearOfCars(Const CVector*); 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::RegenerationPoint_b;
CVector CPopulation::RegenerationForward; CVector CPopulation::RegenerationForward;
uint32 CPopulation::ms_nTotalCarPassengerPeds;
uint32 CPopulation::NumMiamiViceCops;
void void
CPopulation::Initialise() CPopulation::Initialise()
{ {
@ -103,6 +106,8 @@ CPopulation::Initialise()
ms_nNumGang9 = 0; ms_nNumGang9 = 0;
ms_nNumDummy = 0; ms_nNumDummy = 0;
ms_nTotalCarPassengerPeds = 0;
m_AllRandomPedsThisType = -1; m_AllRandomPedsThisType = -1;
PedDensityMultiplier = 1.0f; PedDensityMultiplier = 1.0f;
bZoneChangeHasHappened = false; bZoneChangeHasHappened = false;
@ -398,6 +403,7 @@ CPopulation::Update()
+ ms_nNumGang2 + ms_nNumGang1; + ms_nNumGang2 + ms_nNumGang1;
ms_nTotalPeds = ms_nNumDummy + ms_nNumEmergency + ms_nNumCop ms_nTotalPeds = ms_nNumDummy + ms_nNumEmergency + ms_nNumCop
+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale; + ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;
ms_nTotalPeds -= ms_nTotalCarPassengerPeds;
if (!CCutsceneMgr::IsRunning()) { if (!CCutsceneMgr::IsRunning()) {
float pcdm = PedCreationDistMultiplier(); float pcdm = PedCreationDistMultiplier();
AddToPopulation(pcdm * (MIN_CREATION_DIST * TheCamera.GenerationDistMultiplier), AddToPopulation(pcdm * (MIN_CREATION_DIST * TheCamera.GenerationDistMultiplier),
@ -419,6 +425,7 @@ CPopulation::GeneratePedsAtStartOfGame()
+ ms_nNumGang3 + ms_nNumGang2 + ms_nNumGang1; + ms_nNumGang3 + ms_nNumGang2 + ms_nNumGang1;
ms_nTotalPeds = ms_nNumDummy + ms_nNumEmergency + ms_nNumCop ms_nTotalPeds = ms_nNumDummy + ms_nNumEmergency + ms_nNumCop
+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale; + ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;
ms_nTotalPeds -= ms_nTotalCarPassengerPeds;
// Min dist is 10.0f only for start of the game (naturally) // Min dist is 10.0f only for start of the game (naturally)
AddToPopulation(10.0f, PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE), 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; generatedCoors.y = yOffset + gangLeader->GetPosition().y;
} }
} }
if (!CPedPlacement::IsPositionClearForPed(&generatedCoors)) if (!CPedPlacement::IsPositionClearForPed(generatedCoors))
break; break;
// Why no love for last gang member?! // Why no love for last gang member?!
@ -733,6 +740,7 @@ CPopulation::AddPedInCar(CVehicle* car)
break; break;
case MI_POLICE: case MI_POLICE:
case MI_PREDATOR: case MI_PREDATOR:
case MI_VICECHEE: // TODO(MIAMI): proper model
preferredModel = COP_STREET; preferredModel = COP_STREET;
pedType = PEDTYPE_COP; pedType = PEDTYPE_COP;
break; break;
@ -1016,6 +1024,10 @@ CPopulation::ManagePopulation(void)
} }
float dist = (ped->GetPosition() - playerPos).Magnitude2D(); float dist = (ped->GetPosition() - playerPos).Magnitude2D();
if (ped->IsGangMember() || (ped->bDeadPedInFrontOfCar && ped->m_vehicleInAccident))
dist -= 30.0f;
bool pedIsFarAway = false; bool pedIsFarAway = false;
if (PedCreationDistMultiplier() * (PED_REMOVE_DIST_SPECIAL * TheCamera.GenerationDistMultiplier) < dist if (PedCreationDistMultiplier() * (PED_REMOVE_DIST_SPECIAL * TheCamera.GenerationDistMultiplier) < dist
|| (!ped->bCullExtraFarAway && PedCreationDistMultiplier() * PED_REMOVE_DIST * 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 RegenerationPoint_b;
static CVector RegenerationForward; static CVector RegenerationForward;
static uint32 ms_nTotalCarPassengerPeds;
static uint32 NumMiamiViceCops;
static void Initialise(); static void Initialise();
static void Update(void); static void Update(void);
static void LoadPedGroups(); static void LoadPedGroups();
@ -86,4 +89,6 @@ public:
static void ConvertAllObjectsToDummyObjects(void); static void ConvertAllObjectsToDummyObjects(void);
static bool TestRoomForDummyObject(CObject*); static bool TestRoomForDummyObject(CObject*);
static bool TestSafeForRealObject(CDummyObject*); 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_bSirenOrAlarm = 0;
m_nCarHornTimer = 0; m_nCarHornTimer = 0;
m_nCarHornPattern = 0; m_nCarHornPattern = 0;
bCreatedAsPoliceVehicle = false;
bParking = false; bParking = false;
m_nAlarmState = 0; m_nAlarmState = 0;
m_nDoorLock = CARLOCK_UNLOCKED; 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 bIsCarParkVehicle : 1; // Car has been created using the special CAR_PARK script command
uint8 bHasAlreadyBeenRecorded : 1; // Used for replays 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; uint8 bParking : 1;
int8 m_numPedsUseItAsCover; int8 m_numPedsUseItAsCover;