summaryrefslogtreecommitdiffstats
path: root/src/control/CarCtrl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/control/CarCtrl.cpp')
-rw-r--r--src/control/CarCtrl.cpp562
1 files changed, 306 insertions, 256 deletions
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index 9b2bd4f0..2c5751a3 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -11,6 +11,7 @@
#include "Curves.h"
#include "CutsceneMgr.h"
#include "Gangs.h"
+#include "Game.h"
#include "Garages.h"
#include "General.h"
#include "IniFile.h"
@@ -29,6 +30,7 @@
#include "VisibilityPlugins.h"
#include "Vehicle.h"
#include "Fire.h"
+#include "WaterLevel.h"
#include "World.h"
#include "Zones.h"
@@ -82,22 +84,26 @@ uint32 CCarCtrl::LastTimeLawEnforcerCreated;
uint32 CCarCtrl::LastTimeFireTruckCreated;
uint32 CCarCtrl::LastTimeAmbulanceCreated;
int32 CCarCtrl::TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];
-int32 CCarCtrl::NextCarOfRating[TOTAL_CUSTOM_CLASSES];
int32 CCarCtrl::CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+int32 CCarCtrl::NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];
+int32 CCarCtrl::NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
+int32 CCarCtrl::CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+int32 CCarCtrl::LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP];
uint32 aCarsToKeepTime[MAX_CARS_TO_KEEP];
void
CCarCtrl::GenerateRandomCars()
{
- if (CCutsceneMgr::IsRunning())
+ if (CCutsceneMgr::IsRunning()) {
+ CountDownToCarsAtStart = 2;
return;
+ }
if (NumRandomCars < 30){
- if (CountDownToCarsAtStart == 0){
+ if (CountDownToCarsAtStart == 0)
GenerateOneRandomCar();
- }
else if (--CountDownToCarsAtStart == 0) {
- for (int i = 0; i < 50; i++)
+ for (int i = 0; i < 100; i++)
GenerateOneRandomCar();
CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = 20;
}
@@ -111,6 +117,7 @@ void
CCarCtrl::GenerateOneRandomCar()
{
static int32 unk = 0;
+ bool bTopDownCamera = false;
CPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus];
CVector vecTargetPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
CVector2D vecPlayerSpeed = FindPlayerSpeed();
@@ -125,7 +132,7 @@ CCarCtrl::GenerateOneRandomCar()
int carClass;
int carModel;
if (pWanted->m_nWantedLevel > 1 && NumLawEnforcerCars < pWanted->m_MaximumLawEnforcerVehicles &&
- pWanted->m_CurrentCops < pWanted->m_MaxCops && (
+ pWanted->m_CurrentCops < pWanted->m_MaxCops && !CGame::IsInInterior() && (
pWanted->m_nWantedLevel > 3 ||
pWanted->m_nWantedLevel > 2 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 5000 ||
pWanted->m_nWantedLevel > 1 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 8000)) {
@@ -135,7 +142,7 @@ CCarCtrl::GenerateOneRandomCar()
carModel = ChoosePoliceCarModel();
}else{
carModel = ChooseModel(&zone, &vecTargetPos, &carClass);
- if (carClass == COPS && pWanted->m_nWantedLevel >= 1)
+ if (carClass == COPS && pWanted->m_nWantedLevel >= 1 || carModel < 0)
/* All cop spawns with wanted level are handled by condition above. */
/* In particular it means that cop cars never spawn if player has wanted level of 1. */
return;
@@ -159,8 +166,9 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn essentially anywhere. */
frontX = frontY = 0.707f; /* 45 degrees */
angleLimit = -1.0f;
+ bTopDownCamera = true;
invertAngleLimitTest = true;
- preferredDistance = 40.0f;
+ preferredDistance = 55.0f;
/* BUG: testForCollision not initialized in original game. */
testForCollision = false;
}else if (!pPlayerVehicle){
@@ -174,7 +182,7 @@ CCarCtrl::GenerateOneRandomCar()
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = 110.0f * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle close to player to his side. */
@@ -196,14 +204,14 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn a vehicle in a very narrow gap in front of a player */
angleLimit = 0.85f; /* approx 30 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = 110.0f * TheCamera.GenerationDistMultiplier;
break;
case 2:
/* Spawn a vehicle relatively far away from player. */
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = 110.0f * TheCamera.GenerationDistMultiplier;
break;
case 3:
/* Spawn a vehicle close to player to his side. */
@@ -224,14 +232,14 @@ CCarCtrl::GenerateOneRandomCar()
/* Spawn a vehicle in a very narrow gap in front of a player */
angleLimit = 0.85f; /* approx 30 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = 110.0f * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle relatively far away from player. */
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = 110.0f * TheCamera.GenerationDistMultiplier;
break;
case 2:
case 3:
@@ -254,7 +262,7 @@ CCarCtrl::GenerateOneRandomCar()
/* Forward to his current direction (camera direction). */
angleLimit = 0.707f; /* 45 degrees */
invertAngleLimitTest = true;
- preferredDistance = 120.0f * TheCamera.GenerationDistMultiplier;
+ preferredDistance = 110.0f * TheCamera.GenerationDistMultiplier;
break;
case 1:
/* Spawn a vehicle close to player to his side. */
@@ -269,17 +277,36 @@ CCarCtrl::GenerateOneRandomCar()
preferredDistance, angleLimit, invertAngleLimitTest, &spawnPosition, &curNodeId, &nextNodeId,
&positionBetweenNodes, carClass == COPS && pWanted->m_nWantedLevel >= 1))
return;
+ CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];
+ CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];
+ bool bBoatGenerated = false;
+ if ((CGeneral::GetRandomNumber() & 0xF) > Min(pCurNode->spawnRate, pNextNode->spawnRate))
+ return;
+ if (pCurNode->bWaterPath) {
+ bBoatGenerated = true;
+ if (carClass == COPS) {
+ carModel = MI_PREDATOR;
+ carClass = COPS_BOAT;
+ if (!CStreaming::HasModelLoaded(MI_PREDATOR)) {
+ CStreaming::RequestModel(MI_PREDATOR, STREAMFLAGS_DEPENDENCY);
+ return;
+ }
+ else {
+ return;
+ // TODO: normal boats
+ }
+ }
+ }
int16 colliding;
- CWorld::FindObjectsKindaColliding(spawnPosition, 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
+ CWorld::FindObjectsKindaColliding(spawnPosition, bBoatGenerated ? 40.0f : 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
if (colliding)
/* If something is already present in spawn position, do not create vehicle*/
return;
- if (!ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition))
+ if (!bBoatGenerated && !ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition))
/* Testing if spawn position can reach target position via valid path. */
return;
int16 idInNode = 0;
- CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];
- CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];
+
while (idInNode < pCurNode->numLinks &&
ThePaths.ConnectedNode(idInNode + pCurNode->firstLink) != nextNodeId)
idInNode++;
@@ -287,74 +314,67 @@ CCarCtrl::GenerateOneRandomCar()
CCarPathLink* pPathLink = &ThePaths.m_carPathLinks[connectionId];
int16 lanesOnCurrentRoad = pPathLink->pathNodeIndex == nextNodeId ? pPathLink->numLeftLanes : pPathLink->numRightLanes;
CVehicleModelInfo* pModelInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(carModel);
- if (lanesOnCurrentRoad == 0 || pModelInfo->m_vehicleType == VEHICLE_TYPE_BIKE)
+ if (lanesOnCurrentRoad == 0)
/* Not spawning vehicle if road is one way and intended direction is opposide to that way. */
- /* Also not spawning bikes but they don't exist in final game. */
return;
- CAutomobile* pCar = new CAutomobile(carModel, RANDOM_VEHICLE);
- pCar->AutoPilot.m_nPrevRouteNode = 0;
- pCar->AutoPilot.m_nCurrentRouteNode = curNodeId;
- pCar->AutoPilot.m_nNextRouteNode = nextNodeId;
+ CVehicle* pVehicle;
+ if (CModelInfo::IsBoatModel(carModel))
+ pVehicle = new CBoat(carModel, RANDOM_VEHICLE);
+ //else if (CModelInfo::IsBikeModel(carModel))
+ // pVehicle = new CBike(carModel, RANDOM_VEHICLE);
+ else
+ pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
+ pVehicle->AutoPilot.m_nPrevRouteNode = 0;
+ pVehicle->AutoPilot.m_nCurrentRouteNode = curNodeId;
+ pVehicle->AutoPilot.m_nNextRouteNode = nextNodeId;
switch (carClass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- case MAFIA:
- case TRIAD:
- case DIABLO:
- case YAKUZA:
- case YARDIE:
- case COLOMB:
- case NINES:
- case GANG8:
- case GANG9:
- {
- pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14);
- if (carClass == EXEC)
- pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18);
- else if (carClass == POOR || carClass == SPECIAL)
- pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10);
- CVehicleModelInfo* pVehicleInfo = pCar->GetModelInfo();
- if (pVehicleInfo->GetColModel()->boundingBox.max.y - pCar->GetModelInfo()->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) {
- pCar->AutoPilot.m_nCruiseSpeed *= 3;
- pCar->AutoPilot.m_nCruiseSpeed /= 4;
- }
- pCar->AutoPilot.m_fMaxTrafficSpeed = pCar->AutoPilot.m_nCruiseSpeed;
- pCar->AutoPilot.m_nCarMission = MISSION_CRUISE;
- pCar->AutoPilot.m_nTempAction = TEMPACT_NONE;
- pCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- break;
- }
case COPS:
- pCar->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel != 0){
- pCar->AutoPilot.m_nCruiseSpeed = CCarAI::FindPoliceCarSpeedForWantedLevel(pCar);
- pCar->AutoPilot.m_fMaxTrafficSpeed = pCar->AutoPilot.m_nCruiseSpeed / 2;
- pCar->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();
- pCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ pVehicle->AutoPilot.m_nCruiseSpeed = CCarAI::FindPoliceCarSpeedForWantedLevel(pVehicle);
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed / 2;
+ pVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
}else{
- pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 16);
- pCar->AutoPilot.m_fMaxTrafficSpeed = pCar->AutoPilot.m_nCruiseSpeed;
- pCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
- pCar->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 16);
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
}
if (carModel == MI_FBICAR){
- pCar->m_currentColour1 = 0;
- pCar->m_currentColour2 = 0;
+ 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
+ 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();
+ break;
default:
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14);
+ if (carClass == EXEC)
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18);
+ else if (carClass == POOR)
+ pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10);
+ if (pVehicle->GetColModel()->boundingBox.max.y - pVehicle->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) {
+ pVehicle->AutoPilot.m_nCruiseSpeed *= 3;
+ pVehicle->AutoPilot.m_nCruiseSpeed /= 4;
+ }
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
break;
}
- if (pCar && pCar->GetModelIndex() == MI_MRWHOOP)
- pCar->m_bSirenOrAlarm = true;
- pCar->AutoPilot.m_nNextPathNodeInfo = connectionId;
- pCar->AutoPilot.m_nNextLane = pCar->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad;
- CColBox* boundingBox = &CModelInfo::GetModelInfo(pCar->GetModelIndex())->GetColModel()->boundingBox;
+ if (pVehicle && pVehicle->GetModelIndex() == MI_MRWHOOP)
+ pVehicle->m_bSirenOrAlarm = true;
+ pVehicle->AutoPilot.m_nNextPathNodeInfo = connectionId;
+ pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad;
+ CBox* boundingBox = &CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel()->boundingBox;
float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2;
float distanceBetweenNodes = (pCurNode->GetPosition() - pNextNode->GetPosition()).Magnitude2D();
/* If car is so long that it doesn't fit between two car nodes, place it directly in the middle. */
@@ -363,20 +383,20 @@ CCarCtrl::GenerateOneRandomCar()
positionBetweenNodes = 0.5f;
else
positionBetweenNodes = Min(1.0f - carLength / distanceBetweenNodes, Max(carLength / distanceBetweenNodes, positionBetweenNodes));
- pCar->AutoPilot.m_nNextDirection = (curNodeId >= nextNodeId) ? 1 : -1;
+ pVehicle->AutoPilot.m_nNextDirection = (curNodeId >= nextNodeId) ? 1 : -1;
if (pCurNode->numLinks == 1){
/* Do not create vehicle if there is nowhere to go. */
- delete pCar;
+ delete pVehicle;
return;
}
- int16 nextConnection = pCar->AutoPilot.m_nNextPathNodeInfo;
+ int16 nextConnection = pVehicle->AutoPilot.m_nNextPathNodeInfo;
int16 newLink;
- while (nextConnection == pCar->AutoPilot.m_nNextPathNodeInfo){
+ while (nextConnection == pVehicle->AutoPilot.m_nNextPathNodeInfo){
newLink = CGeneral::GetRandomNumber() % pCurNode->numLinks;
nextConnection = ThePaths.m_carPathConnections[newLink + pCurNode->firstLink];
}
- pCar->AutoPilot.m_nCurrentPathNodeInfo = nextConnection;
- pCar->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(newLink + pCurNode->firstLink) >= curNodeId) ? 1 : -1;
+ pVehicle->AutoPilot.m_nCurrentPathNodeInfo = nextConnection;
+ pVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(newLink + pCurNode->firstLink) >= curNodeId) ? 1 : -1;
CVector2D vecBetweenNodes = pNextNode->GetPosition() - pCurNode->GetPosition();
float forwardX, forwardY;
float distBetweenNodes = vecBetweenNodes.Magnitude();
@@ -389,47 +409,47 @@ CCarCtrl::GenerateOneRandomCar()
}
/* I think the following might be some form of SetRotateZOnly. */
/* Setting up direction between two car nodes. */
- pCar->GetForward() = CVector(forwardX, forwardY, 0.0f);
- pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f);
- pCar->GetUp() = CVector(0.0f, 0.0f, 1.0f);
+ pVehicle->GetForward() = CVector(forwardX, forwardY, 0.0f);
+ pVehicle->GetRight() = CVector(forwardY, -forwardX, 0.0f);
+ pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f);
- float currentPathLinkForwardX = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].GetDirX();
- float currentPathLinkForwardY = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].GetDirY();
- float nextPathLinkForwardX = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].GetDirX();
- float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].GetDirY();
+ float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX();
+ float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY();
+ float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX();
+ float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY();
- CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo];
- CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo];
+ CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
+ CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
CVector positionOnCurrentLinkIncludingLane(
- pCurrentLink->GetX() + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
- pCurrentLink->GetY() - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
+ pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
+ pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f);
CVector positionOnNextLinkIncludingLane(
- pNextLink->GetX() + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
- pNextLink->GetY() - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
+ pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
+ pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f);
- float directionCurrentLinkX = pCurrentLink->GetDirX() * pCar->AutoPilot.m_nCurrentDirection;
- float directionCurrentLinkY = pCurrentLink->GetDirY() * pCar->AutoPilot.m_nCurrentDirection;
- float directionNextLinkX = pNextLink->GetDirX() * pCar->AutoPilot.m_nNextDirection;
- float directionNextLinkY = pNextLink->GetDirY() * pCar->AutoPilot.m_nNextDirection;
+ float directionCurrentLinkX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;
+ float directionCurrentLinkY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;
+ float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;
+ float directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;
/* We want to make a path between two links that may not have the same forward directions a curve. */
- pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
+ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane,
&positionOnNextLinkIncludingLane,
directionCurrentLinkX, directionCurrentLinkY,
directionNextLinkX, directionNextLinkY
- ) * (1000.0f / pCar->AutoPilot.m_fMaxTrafficSpeed);
+ ) * (1000.0f / pVehicle->AutoPilot.m_fMaxTrafficSpeed);
#ifdef FIX_BUGS
/* Casting timer to float is very unwanted. In this case it's not awful */
/* but in CAutoPilot::ModifySpeed it can even cause crashes (see SilentPatch). */
/* 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. */
- pCar->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
- (uint32)(positionBetweenNodes * pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve);
+ pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
+ (uint32)((0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve);
#else
- pCar->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
- (0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve;
+ pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -
+ (0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve;
#endif
CVector directionCurrentLink(directionCurrentLinkX, directionCurrentLinkY, 0.0f);
CVector directionNextLink(directionNextLinkX, directionNextLinkY, 0.0f);
@@ -440,8 +460,8 @@ CCarCtrl::GenerateOneRandomCar()
&positionOnNextLinkIncludingLane,
&directionCurrentLink,
&directionNextLink,
- GetPositionAlongCurrentCurve(pCar),
- pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve,
+ GetPositionAlongCurrentCurve(pVehicle),
+ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve,
&positionIncludingCurve,
&directionIncludingCurve
);
@@ -452,136 +472,150 @@ CCarCtrl::GenerateOneRandomCar()
float groundZ = INFINITE_Z;
CColPoint colPoint;
CEntity* pEntity;
- if (CWorld::ProcessVerticalLine(finalPosition, 1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))
- groundZ = colPoint.point.z;
- if (CWorld::ProcessVerticalLine(finalPosition, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil)){
- if (ABS(colPoint.point.z - finalPosition.z) < ABS(groundZ - finalPosition.z))
+ if (bBoatGenerated) {
+ if (!CWaterLevel::GetWaterLevel(finalPosition, &groundZ, true)) {
+ delete pVehicle;
+ return;
+ }
+ }
+ else {
+ if (CWorld::ProcessVerticalLine(finalPosition, 1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))
groundZ = colPoint.point.z;
+ if (CWorld::ProcessVerticalLine(finalPosition, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil)) {
+ if (ABS(colPoint.point.z - finalPosition.z) < ABS(groundZ - finalPosition.z))
+ groundZ = colPoint.point.z;
+ }
}
if (groundZ == INFINITE_Z || ABS(groundZ - finalPosition.z) > 7.0f) {
/* Failed to find ground or too far from expected position. */
- delete pCar;
+ delete pVehicle;
return;
}
- finalPosition.z = groundZ + pCar->GetHeightAboveRoad();
- pCar->SetPosition(finalPosition);
- pCar->SetMoveSpeed(directionIncludingCurve / GAME_SPEED_TO_CARAI_SPEED);
- CVector2D speedDifferenceWithTarget = (CVector2D)pCar->GetMoveSpeed() - vecPlayerSpeed;
+ if (CModelInfo::IsBoatModel(carModel)) {
+ finalPosition.z = groundZ;
+ pVehicle->bExtendedRange = true;
+ }
+ else
+ finalPosition.z = groundZ + pVehicle->GetHeightAboveRoad();
+ pVehicle->SetPosition(finalPosition);
+ pVehicle->SetMoveSpeed(directionIncludingCurve / GAME_SPEED_TO_CARAI_SPEED);
+ CVector2D speedDifferenceWithTarget = (CVector2D)pVehicle->GetMoveSpeed() - vecPlayerSpeed;
CVector2D distanceToTarget = positionIncludingCurve - vecTargetPos;
switch (carClass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- case MAFIA:
- case TRIAD:
- case DIABLO:
- case YAKUZA:
- case YARDIE:
- case COLOMB:
- case NINES:
- case GANG8:
- case GANG9:
- pCar->SetStatus(STATUS_SIMPLE);
- break;
case COPS:
- pCar->SetStatus((pCar->AutoPilot.m_nCarMission == MISSION_CRUISE) ? STATUS_SIMPLE : STATUS_PHYSICS);
- pCar->ChangeLawEnforcerState(1);
+ pVehicle->SetStatus((pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) ? STATUS_SIMPLE : STATUS_PHYSICS);
+ pVehicle->ChangeLawEnforcerState(1);
break;
+ case COPS_BOAT:
+ pVehicle->ChangeLawEnforcerState(1);
+ pVehicle->SetStatus(STATUS_PHYSICS);
default:
+ pVehicle->SetStatus(STATUS_SIMPLE);
break;
}
- CVisibilityPlugins::SetClumpAlpha(pCar->GetClump(), 0);
- if (!pCar->GetIsOnScreen()){
- if ((vecTargetPos - pCar->GetPosition()).Magnitude2D() > 50.0f) {
+ CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
+ if (!pVehicle->GetIsOnScreen()){
+ if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > 40.0f * (pVehicle->bExtendedRange ? 1.5f : 1.0f)) {
/* Too far away cars that are not visible aren't needed. */
- delete pCar;
+ delete pVehicle;
return;
}
- }else if((vecTargetPos - pCar->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * 130.0f ||
- (vecTargetPos - pCar->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 110.0f){
- delete pCar;
+ }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() - pCar->GetPosition()).Magnitude2D() < 90.0f * TheCamera.GenerationDistMultiplier){
- delete pCar;
+ }else if((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera ){
+ delete pVehicle;
return;
}
- CVehicleModelInfo* pVehicleModel = pCar->GetModelInfo();
+ // TODO(MIAMI): if MARQUIS then delete
+ CVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo();
float radiusToTest = pVehicleModel->GetColModel()->boundingSphere.radius;
if (testForCollision){
- CWorld::FindObjectsKindaColliding(pCar->GetPosition(), radiusToTest + 20.0f, true, &colliding, 2, nil, false, true, false, false, false);
+ CWorld::FindObjectsKindaColliding(pVehicle->GetPosition(), radiusToTest + 20.0f, true, &colliding, 2, nil, false, true, false, false, false);
if (colliding){
- delete pCar;
+ delete pVehicle;
return;
}
}
- CWorld::FindObjectsKindaColliding(pCar->GetPosition(), radiusToTest, true, &colliding, 2, nil, false, true, false, false, false);
+ CWorld::FindObjectsKindaColliding(pVehicle->GetPosition(), radiusToTest, true, &colliding, 2, nil, false, true, false, false, false);
if (colliding){
- delete pCar;
+ delete pVehicle;
return;
}
if (speedDifferenceWithTarget.x * distanceToTarget.x +
speedDifferenceWithTarget.y * distanceToTarget.y >= 0.0f){
- delete pCar;
+ delete pVehicle;
return;
}
- pVehicleModel->AvoidSameVehicleColour(&pCar->m_currentColour1, &pCar->m_currentColour2);
- CWorld::Add(pCar);
- if (carClass == COPS)
- CCarAI::AddPoliceCarOccupants(pCar);
+ pVehicleModel->AvoidSameVehicleColour(&pVehicle->m_currentColour1, &pVehicle->m_currentColour2);
+ CWorld::Add(pVehicle);
+ if (carClass == COPS || carClass == COPS_BOAT)
+ CCarAI::AddPoliceCarOccupants(pVehicle);
else
- pCar->SetUpDriver();
- if ((CGeneral::GetRandomNumber() & 0x3F) == 0){ /* 1/64 probability */
- pCar->SetStatus(STATUS_PHYSICS);
- pCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- pCar->AutoPilot.m_nCruiseSpeed += 10;
+ pVehicle->SetUpDriver(); //TODO(MIAMI): FIX!
+ if ((CGeneral::GetRandomNumber() & 0x3F) == 0){ /* 1/64 probability */ /* TODO(MIAMI): FIX!*/
+ 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;
+}
+
+int32
+CCarCtrl::ChooseBoatModel(int32 rating)
+{
+ ++NumRequestsOfCarRating[rating];
+ return ChooseCarModel(rating);
+}
+
+int32
+CCarCtrl::ChooseBoatRating(CZoneInfo* pZoneInfo)
+{
+ int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
+ for (int i = 0; i < NUM_BOAT_CLASSES - 1; i++) {
+ if (rnd < pZoneInfo->boatThreshold[i])
+ return FIRST_BOAT_RATING + i;
+ }
+ return FIRST_BOAT_RATING + NUM_BOAT_CLASSES - 1;
+}
+
+int32
+CCarCtrl::ChooseCarRating(CZoneInfo* pZoneInfo)
+{
+ int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
+ for (int i = 0; i < NUM_CAR_CLASSES - 1; i++) {
+ if (rnd < pZoneInfo->carThreshold[i])
+ return i;
+ }
+ return FIRST_CAR_RATING + NUM_CAR_CLASSES - 1;
}
int32
CCarCtrl::ChooseModel(CZoneInfo* pZone, CVector* pPos, int* pClass) {
int32 model = -1;
- while (model == -1 || !CStreaming::HasModelLoaded(model)){
+ for (int i = 0; i < 10 && (model == -1 || !CStreaming::HasModelLoaded(model)); i++) {
int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
- if (rnd < pZone->carThreshold[0])
- model = CCarCtrl::ChooseCarModel((*pClass = POOR));
- else if (rnd < pZone->carThreshold[1])
- model = CCarCtrl::ChooseCarModel((*pClass = RICH));
- else if (rnd < pZone->carThreshold[2])
- model = CCarCtrl::ChooseCarModel((*pClass = EXEC));
- else if (rnd < pZone->carThreshold[3])
- model = CCarCtrl::ChooseCarModel((*pClass = WORKER));
- else if (rnd < pZone->carThreshold[4])
- model = CCarCtrl::ChooseCarModel((*pClass = SPECIAL));
- else if (rnd < pZone->carThreshold[5])
- model = CCarCtrl::ChooseCarModel((*pClass = BIG));
- else if (rnd < pZone->copThreshold)
- *pClass = COPS, model = CCarCtrl::ChoosePoliceCarModel();
- else if (rnd < pZone->gangThreshold[0])
- model = CCarCtrl::ChooseGangCarModel((*pClass = MAFIA) - MAFIA);
- else if (rnd < pZone->gangThreshold[1])
- model = CCarCtrl::ChooseGangCarModel((*pClass = TRIAD) - MAFIA);
- else if (rnd < pZone->gangThreshold[2])
- model = CCarCtrl::ChooseGangCarModel((*pClass = DIABLO) - MAFIA);
- else if (rnd < pZone->gangThreshold[3])
- model = CCarCtrl::ChooseGangCarModel((*pClass = YAKUZA) - MAFIA);
- else if (rnd < pZone->gangThreshold[4])
- model = CCarCtrl::ChooseGangCarModel((*pClass = YARDIE) - MAFIA);
- else if (rnd < pZone->gangThreshold[5])
- model = CCarCtrl::ChooseGangCarModel((*pClass = COLOMB) - MAFIA);
- else if (rnd < pZone->gangThreshold[6])
- model = CCarCtrl::ChooseGangCarModel((*pClass = NINES) - MAFIA);
- else if (rnd < pZone->gangThreshold[7])
- model = CCarCtrl::ChooseGangCarModel((*pClass = GANG8) - MAFIA);
- else if (rnd < pZone->gangThreshold[8])
- model = CCarCtrl::ChooseGangCarModel((*pClass = GANG9) - MAFIA);
- else
- model = CCarCtrl::ChooseCarModel((*pClass = TAXI));
+
+ if (rnd < pZone->copThreshold) {
+ *pClass = COPS;
+ model = ChoosePoliceCarModel();
+ continue;
+ }
+
+ for (int i = 0; i < NUM_GANG_CAR_CLASSES; i++) {
+ if (rnd < pZone->gangThreshold[i]) {
+ *pClass = i + FIRST_GANG_CAR_RATING;
+ model = ChooseGangCarModel(i);
+ continue;
+ }
+ }
+
+ *pClass = ChooseCarRating(pZone);
+ model = ChooseCarModel(*pClass);
}
return model;
}
@@ -590,29 +624,53 @@ int32
CCarCtrl::ChooseCarModel(int32 vehclass)
{
int32 model = -1;
- switch (vehclass) {
- case POOR:
- case RICH:
- case EXEC:
- case WORKER:
- case SPECIAL:
- case BIG:
- case TAXI:
- {
- if (TotalNumOfCarsOfRating[vehclass] == 0)
- debug("ChooseCarModel : No cars of type %d have been declared\n", vehclass);
- model = CarArrays[vehclass][NextCarOfRating[vehclass]];
- int32 total = TotalNumOfCarsOfRating[vehclass];
- NextCarOfRating[vehclass] += CGeneral::GetRandomNumberInRange(1, total);
- while (NextCarOfRating[vehclass] >= total)
- NextCarOfRating[vehclass] -= total;
- //NextCarOfRating[vehclass] %= total;
- TotalNumOfCarsOfRating[vehclass] = total; /* why... */
- }
- default:
- break;
- }
- return model;
+ ++NumRequestsOfCarRating[vehclass];
+ if (NumOfLoadedCarsOfRating[vehclass] == 0)
+ return -1;
+ int32 rnd = CGeneral::GetRandomNumberInRange(0, CarFreqArrays[vehclass][NumOfLoadedCarsOfRating[vehclass] - 1]);
+ int32 index = 0;
+ while (rnd > CarFreqArrays[vehclass][index])
+ index++;
+ assert(LoadedCarsArray[vehclass][index]);
+ return LoadedCarsArray[vehclass][index];
+}
+
+void
+CCarCtrl::AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq)
+{
+ LoadedCarsArray[rating][NumOfLoadedCarsOfRating[rating]] = mi;
+ assert(mi >= 130);
+ CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating]] = freq;
+ if (NumOfLoadedCarsOfRating[rating])
+ CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating]] += CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating] - 1];
+ NumOfLoadedCarsOfRating[rating]++;
+}
+
+void
+CCarCtrl::RemoveFromLoadedVehicleArray(int mi, int32 rating)
+{
+ int index = 0;
+ while (LoadedCarsArray[rating][index] != -1) {
+ if (LoadedCarsArray[rating][index] == mi)
+ break;
+ index++;
+ }
+ assert(LoadedCarsArray[rating][index] == mi);
+ int32 freq = CarFreqArrays[rating][index];
+ if (index > 0)
+ freq -= CarFreqArrays[rating][index - 1];
+ while (LoadedCarsArray[rating][index + 1] != -1) {
+ LoadedCarsArray[rating][index] = LoadedCarsArray[rating][index + 1];
+ CarFreqArrays[rating][index] = CarFreqArrays[rating][index + 1] - freq;
+ index++;
+ }
+ --NumOfLoadedCarsOfRating[rating];
+}
+
+int32
+CCarCtrl::ChooseCarModelToLoad(int rating)
+{
+ return CarArrays[rating][CGeneral::GetRandomNumberInRange(0, TotalNumOfCarsOfRating[rating])];
}
int32
@@ -646,6 +704,7 @@ CCarCtrl::ChooseGangCarModel(int32 gang)
void
CCarCtrl::AddToCarArray(int32 id, int32 vehclass)
{
+ assert(TotalNumOfCarsOfRating[vehclass] < MAX_CAR_MODELS_IN_ARRAY);
CarArrays[vehclass][TotalNumOfCarsOfRating[vehclass]++] = id;
}
@@ -679,7 +738,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
return;
}
float distanceToPlayer = (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D();
- float threshold = 50.0f;
+ float threshold = 40.0f;
if (pVehicle->GetIsOnScreen() ||
TheCamera.Cams[TheCamera.ActiveCam].LookingLeft ||
TheCamera.Cams[TheCamera.ActiveCam].LookingRight ||
@@ -691,12 +750,14 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
pVehicle->bIsLawEnforcer ||
pVehicle->bIsCarParkVehicle
){
- threshold = 130.0f * TheCamera.GenerationDistMultiplier;
+ threshold = 120.0f * TheCamera.GenerationDistMultiplier;
}
+ if (TheCamera.GetForward().z < -0.9f)
+ threshold = 70.0f;
if (pVehicle->bExtendedRange)
threshold *= 1.5f;
if (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
- if (pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)) {
+ if (pVehicle->GetIsOnScreen()){
pVehicle->bFadeOut = true;
}else{
CWorld::Remove(pVehicle);
@@ -705,7 +766,8 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
return;
}
}
- if ((pVehicle->GetStatus() == STATUS_SIMPLE || pVehicle->GetStatus() == STATUS_PHYSICS && pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS) &&
+ if ((pVehicle->GetStatus() == STATUS_SIMPLE || pVehicle->GetStatus() == STATUS_PHYSICS &&
+ (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS || pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS)) &&
CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 5000 &&
!pVehicle->GetIsOnScreen() &&
(pVehicle->GetPosition() - vecPlayerPos).Magnitude2D() > 25.0f &&
@@ -722,7 +784,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
if (pVehicle->GetStatus() != STATUS_WRECKED || pVehicle->m_nTimeOfDeath == 0)
return;
if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 &&
- !(pVehicle->GetIsOnScreen() && CRenderer::IsEntityCullZoneVisible(pVehicle)) ){
+ !pVehicle->GetIsOnScreen()){
if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(7.5f)){
if (!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
CWorld::Remove(pVehicle);
@@ -1641,41 +1703,13 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
CPathNode* pTargetNode;
int16 numNodes;
float distanceToTargetNode;
- if (pTarget && pTarget->m_pCurGroundEntity &&
- pTarget->m_pCurGroundEntity->IsBuilding() &&
- ((CBuilding*)pTarget->m_pCurGroundEntity)->GetIsATreadable() &&
- ((CTreadable*)pTarget->m_pCurGroundEntity)->m_nodeIndices[0][0] >= 0){
- CTreadable* pCurrentMapObject = (CTreadable*)pTarget->m_pCurGroundEntity;
- int closestNode = -1;
- float minDist = 100000.0f;
- for (int i = 0; i < 12; i++){
- int node = pCurrentMapObject->m_nodeIndices[0][i];
- if (node < 0)
- break;
- float dist = (ThePaths.m_pathNodes[node].GetPosition() - pTarget->GetPosition()).Magnitude();
- if (dist < minDist){
- minDist = dist;
- closestNode = node;
- }
- }
- ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
-#ifdef FIX_PATHFIND_BUG
- CVector(targetX, targetY, targetZ),
-#else
- CVector(targetX, targetY, 0.0f),
-#endif
- &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, closestNode);
- }else
- {
-
- ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
+ ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
#ifdef FIX_PATHFIND_BUG
- CVector(targetX, targetY, targetZ),
+ CVector(targetX, targetY, targetZ),
#else
- CVector(targetX, targetY, 0.0f),
+ CVector(targetX, targetY, 0.0f),
#endif
- &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1);
- }
+ &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1);
int newNextNode;
int nextLink;
@@ -1879,9 +1913,11 @@ void CCarCtrl::Init(void)
for (int i = 0; i < MAX_CARS_TO_KEEP; i++)
apCarsToKeep[i] = nil;
for (int i = 0; i < TOTAL_CUSTOM_CLASSES; i++){
- for (int j = 0; j < MAX_CAR_MODELS_IN_ARRAY; j++)
- CarArrays[i][j] = 0;
- NextCarOfRating[i] = 0;
+ for (int j = 0; j < MAX_CAR_MODELS_IN_ARRAY; j++) {
+ LoadedCarsArray[i][j] = -1;
+ }
+ NumOfLoadedCarsOfRating[i] = 0;
+ NumRequestsOfCarRating[i] = 0;
TotalNumOfCarsOfRating[i] = 0;
}
}
@@ -1905,7 +1941,7 @@ void CCarCtrl::ReInit(void)
for (int i = 0; i < MAX_CARS_TO_KEEP; i++)
apCarsToKeep[i] = nil;
for (int i = 0; i < TOTAL_CUSTOM_CLASSES; i++)
- NextCarOfRating[i] = 0;
+ NumRequestsOfCarRating[i] = 0;
}
void CCarCtrl::DragCarToPoint(CVehicle* pVehicle, CVector* pPoint)
@@ -2741,7 +2777,21 @@ bool CCarCtrl::ThisRoadObjectCouldMove(int16 mi)
bool CCarCtrl::MapCouldMoveInThisArea(float x, float y)
{
+#ifdef GTA_BRIDGE // actually they forgot that in VC...
// bridge moves up and down
return x > -342.0f && x < -219.0f &&
y > -677.0f && y < -580.0f;
+#else
+ return false;
+#endif
+}
+
+float CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(int8 type)
+{
+ switch (type)
+ {
+ case 1: return 1.5f;
+ case 2: return 2.0f;
+ }
+ return 1.0f;
}