From 7e753c259680a13c656bdc6c86d99a4891616474 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 8 May 2020 23:29:43 +0300 Subject: CCarCtrl::GenerateOneRandomCar --- src/control/CarAI.cpp | 8 +-- src/control/CarCtrl.cpp | 163 +++++++++++++++++++++++++++++++++++++++++------ src/control/CarCtrl.h | 5 +- src/control/PathFind.cpp | 14 ++-- src/control/PathFind.h | 4 +- src/control/Script.cpp | 6 +- 6 files changed, 163 insertions(+), 37 deletions(-) (limited to 'src/control') 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); -- cgit v1.2.3