summaryrefslogtreecommitdiffstats
path: root/src/control
diff options
context:
space:
mode:
Diffstat (limited to 'src/control')
-rw-r--r--src/control/CarCtrl.cpp180
-rw-r--r--src/control/CarCtrl.h20
2 files changed, 166 insertions, 34 deletions
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index cd116f11..3d82fc1a 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -96,6 +96,15 @@
#define MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN (40.0f)
#define EXTENDED_RANGE_DESPAWN_MULTIPLIER (1.5f)
+#ifdef GTA_NETWORK
+const int32 CCarCtrl::MultiplayerCarBanks[TOTAL_MULTIPLAYER_CAR_BANKS][CARS_IN_MULTIPLAYER_BANK] =
+{
+ MI_SANCHEZ, MI_KURUMA, MI_ESPRIT, MI_MULE, MI_DIABLOS, MI_KURUMA, MI_PEREN, MI_STINGER,
+ MI_PCJ600, MI_BOBCAT, MI_BLISTA, MI_LANDSTAL,MI_SENTINEL,MI_MOONBEAM,MI_MANANA, MI_PEREN,
+ MI_SANCHEZ2,MI_PCJ600, MI_STALLION,MI_MANANA, MI_LINERUN, MI_RCBANDIT,MI_MRWONGS, MI_STINGER
+};
+#endif
+
bool CCarCtrl::bMadDriversCheat;
int CCarCtrl::NumLawEnforcerCars;
int CCarCtrl::NumAmbulancesOnDuty;
@@ -121,9 +130,16 @@ 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];
+uint32 CCarCtrl::maxRandomMpCars = 20;
+bool CCarCtrl::scriptControlsMpCarLimit = false;
bool gbEmergencyVehiclesEnabled = true;
+#ifdef GTA_NETWORK // TMP
+extern bool gIsMultiplayerGame;
+extern int8 nAmbientCarBank; // actually gMultiGame.nAmbientCarBank (TODO)
+#endif
+
void
CCarCtrl::GenerateRandomCars()
{
@@ -158,7 +174,12 @@ CCarCtrl::GenerateOneRandomCar()
pPlayer->m_nTrafficMultiplier = pPlayer->m_fRoadDensity * zone.carDensity;
#ifdef GTA_NETWORK
if (gIsMultiplayerGame) {
- // TODO
+ // TODO (count number of players within 250 meters from spawn position
+ int numPlayersClose = 1;
+ if (NumRandomCars >= pPlayer->m_nTrafficMultiplier * CarDensityMultiplier * CIniFile::CarNumberMultiplier * numPlayersClose)
+ return;
+ if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars + NumLawEnforcerCars + NumRandomCars >= MaxNumberOfCarsInUse)
+ return;
}
else
#endif
@@ -178,7 +199,7 @@ CCarCtrl::GenerateOneRandomCar()
return;
}
else
-#else
+#endif
{
if (pWanted->GetWantedLevel() > 1 && NumLawEnforcerCars < pWanted->m_MaximumLawEnforcerVehicles &&
pWanted->m_CurrentCops < pWanted->m_MaxCops && !CGame::IsInInterior() && (
@@ -202,7 +223,6 @@ CCarCtrl::GenerateOneRandomCar()
}
}
}
-#endif
float frontX, frontY;
float preferredDistance, angleLimit;
float requestMultiplier = 1.0f;
@@ -821,6 +841,22 @@ int32
CCarCtrl::ChooseModel(CZoneInfo* pZone, int* pClass) {
int32 model = -1;
int32 i;
+#ifdef GTA_NETWORK
+ if (gIsMultiplayerGame) {
+ for (i = 10; i > 0 && (model == -1 || !CStreaming::HasModelLoaded(model)); i--) {
+ *pClass = ChooseCarRating(pZone);
+ model = ChooseCarModel(*pClass);
+ bool found = false;
+ for (int j = 0; j < 8; j++) {
+ if (model == MultiplayerCarBanks[nAmbientCarBank][j])
+ found = true;
+ }
+ if (!found)
+ model = -1;
+ }
+ return model;
+ }
+#endif
for (i = 10; i > 0 && (model == -1 || !CStreaming::HasModelLoaded(model)); i--) {
int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
@@ -847,7 +883,8 @@ CCarCtrl::ChooseModel(CZoneInfo* pZone, int* pClass) {
}
if (i == 0)
return -1;
- if (CModelInfo::GetColModel(model)->boundingSphere.radius > 20.0f)
+ CColModel* pColModel = CModelInfo::GetColModel(model);
+ if (!pColModel || pColModel->boundingSphere.radius > 20.0f)
return -1;
return model;
}
@@ -1033,7 +1070,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
}
float distanceToPlayer = (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D();
float despawnMultiplier = 1.0f;
-#ifndef EXTENDED_OFFSCREEN_DESPAWN_RANGE
+#if !defined EXTENDED_OFFSCREEN_DESPAWN_RANGE || defined GTA_PSP
if (FindPlayerVehicle() && TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON && !FrontEndMenuManager.m_PrefsUseWideScreen)
despawnMultiplier = 0.75f;
#endif
@@ -1065,6 +1102,14 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
if (pVehicle->GetIsOnScreen()){
pVehicle->bFadeOut = true;
}else{
+#ifdef GTA_NETWORK
+ if (gIsMultiplayerGame) {
+ // TODO
+ if (false)
+ MultiPlayerRemoveVehicleAndDriver(pVehicle);
+ return;
+ }
+#endif
CWorld::Remove(pVehicle);
delete pVehicle;
}
@@ -1082,10 +1127,33 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
!CTrafficLights::ShouldCarStopForLight(pVehicle, true) &&
!CTrafficLights::ShouldCarStopForBridge(pVehicle) &&
!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
- CWorld::Remove(pVehicle);
- delete pVehicle;
+#ifdef GTA_NETWORK
+ if (!gIsMultiplayerGame)
+#endif
+ {
+ CWorld::Remove(pVehicle);
+ delete pVehicle;
+ return;
+ }
+#ifdef GTA_NETWORK
+ if (false) // TODO(LCS): figure out condition for mp
+ MultiPlayerRemoveVehicleAndDriver(pVehicle);
+#endif
+ }
+#ifdef GTA_NETWORK
+ if (gIsMultiplayerGame) {
+ if (pVehicle->GetStatus() == STATUS_WRECKED && CTimer::GetLogicalFrameCounter() == pVehicle->m_randomSeed) {
+ if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(6.5f)) {
+ if (pVehicle->GetMoveSpeed().MagnitudeSqr() <= SQR(0.01f)) {
+ printf("viciously removing dead vehicle");
+ CWorld::Remove(pVehicle);
+ delete pVehicle;
+ }
+ }
+ }
return;
}
+#endif
if (pVehicle->GetStatus() == STATUS_WRECKED) {
if (pVehicle->m_nTimeOfDeath != 0) {
if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 &&
@@ -1421,6 +1489,10 @@ void CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle,
pVehicle->AutoPilot.m_bSlowedDownBecauseOfCars = true;
*pSpeed = Min(*pSpeed, minProximity * curSpeed);
}
+#ifdef GTA_NETWORK
+ if (gIsMultiplayerGame)
+ return;
+#endif
if (minProximity >= 0.0f && minProximity < 0.5f && pOtherEntity->IsVehicle() &&
CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 15000 &&
CTimer::GetTimeInMilliseconds() - pOtherVehicle->AutoPilot.m_nTimeToStartMission > 15000){
@@ -1649,7 +1721,7 @@ void CCarCtrl::WeaveForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMCAR_CLOSE && pOtherEntity == pVehicle->AutoPilot.m_pTargetCar)
return;
CVector2D vecDiff = pOtherCar->GetPosition() - pVehicle->GetPosition();
- float angleBetweenVehicles = GetATanOfXY(vecDiff.x, vecDiff.y);
+ float angleBetweenVehicles = CGeneral::GetATanOfXY(vecDiff.x, vecDiff.y);
float distance = vecDiff.Magnitude();
if (distance < 1.0f)
return;
@@ -1659,7 +1731,7 @@ void CCarCtrl::WeaveForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float
return;
CVector2D forward = pVehicle->GetForward();
forward.Normalise();
- float forwardAngle = GetATanOfXY(forward.x, forward.y);
+ float forwardAngle = CGeneral::GetATanOfXY(forward.x, forward.y);
float angleDiff = angleBetweenVehicles - forwardAngle;
float lenProjection = ABS(pOtherCar->GetColModel()->boundingBox.max.y * Sin(angleDiff));
float widthProjection = ABS(pOtherCar->GetColModel()->boundingBox.max.x * Cos(angleDiff));
@@ -1705,7 +1777,7 @@ void CCarCtrl::WeaveForPed(CEntity* pOtherEntity, CVehicle* pVehicle, float* pAn
return;
CPed* pPed = (CPed*)pOtherEntity;
CVector2D vecDiff = pPed->GetPosition() - pVehicle->GetPosition();
- float angleBetweenVehicleAndPed = GetATanOfXY(vecDiff.x, vecDiff.y);
+ float angleBetweenVehicleAndPed = CGeneral::GetATanOfXY(vecDiff.x, vecDiff.y);
float distance = vecDiff.Magnitude();
float lengthToEvade = (WIDTH_COEF_TO_WEAVE_SAFELY * 2 * pVehicle->GetColModel()->boundingBox.max.x + PED_WIDTH_TO_WEAVE) / distance;
float diffToLeftAngle = LimitRadianAngle(angleBetweenVehicleAndPed - *pAngleToWeaveLeft);
@@ -1773,7 +1845,7 @@ void CCarCtrl::WeaveForObject(CEntity* pOtherEntity, CVehicle* pVehicle, float*
rightCoef * pObject->GetRight() +
forwardCoef * pObject->GetForward() -
pVehicle->GetPosition();
- float angleBetweenVehicleAndObject = GetATanOfXY(vecDiff.x, vecDiff.y);
+ float angleBetweenVehicleAndObject = CGeneral::GetATanOfXY(vecDiff.x, vecDiff.y);
float distance = vecDiff.Magnitude();
float lengthToEvade = (WIDTH_COEF_TO_WEAVE_SAFELY * 2 * pVehicle->GetColModel()->boundingBox.max.x + OBJECT_WIDTH_TO_WEAVE) / distance;
float diffToLeftAngle = LimitRadianAngle(angleBetweenVehicleAndObject - *pAngleToWeaveLeft);
@@ -2048,13 +2120,13 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
#else
CVector(targetX, targetY, 0.0f),
#endif
- pTargetNode, &numNodes, 2, pVehicle, &distanceToTargetNode, 999999.9f, -1);
+ pTargetNode, &numNodes, 2, pVehicle, &distanceToTargetNode, 100.0f, -1);
int newNextNode;
int nextLink;
if (numNodes != 1 && numNodes != 2 || pTargetNode[0] == pCurNode){
if (numNodes != 2 || pTargetNode[1] == pCurNode) {
- float currentAngle = GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
+ float currentAngle = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
nextLink = 0;
float lowestAngleChange = 10.0f;
int numLinks = pCurNode->numLinks;
@@ -2064,7 +2136,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
if (conNode == prevNode && i > 1)
continue;
CPathNode* pTestNode = &ThePaths.m_pathNodes[conNode];
- float angle = GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY());
+ float angle = CGeneral::GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY());
angle = LimitRadianAngle(angle - currentAngle);
angle = ABS(angle);
if (angle < lowestAngleChange) {
@@ -2163,14 +2235,14 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
{
if (pVehicle->m_nRouteSeed)
- CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
+ CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed++);
int curNode = pVehicle->AutoPilot.m_nNextRouteNode;
CPathNode* pCurNode = &ThePaths.m_pathNodes[curNode];
if (pVehicle->AutoPilot.m_nPathFindNodesCount == 0){
ThePaths.DoPathSearch(0, pVehicle->GetPosition(), curNode,
pVehicle->AutoPilot.m_vecDestinationCoors, pVehicle->AutoPilot.m_aPathFindNodesInfo,
&pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT,
- pVehicle, nil, 999999.9f, -1);
+ pVehicle, nil, 100.0f, -1);
if (pVehicle->AutoPilot.m_nPathFindNodesCount < 2)
return true;
pVehicle->AutoPilot.RemoveOnePathNode();
@@ -2663,8 +2735,8 @@ void CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CVehicle* pVehicle, float
{
CVector2D forward = pVehicle->GetForward();
forward.Normalise();
- float angleToTarget = GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
- float angleForward = GetATanOfXY(forward.x, forward.y);
+ float angleToTarget = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
+ float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
float steerAngle = LimitRadianAngle(angleToTarget - angleForward);
steerAngle = Clamp(steerAngle, -DEFAULT_MAX_STEER_ANGLE, DEFAULT_MAX_STEER_ANGLE);
#ifdef FIX_BUGS
@@ -2695,8 +2767,8 @@ void CCarCtrl::SteerAIBoatWithPhysicsAttackingPlayer(CVehicle* pVehicle, float*
CVector2D forward = pVehicle->GetForward();
forward.Normalise();
CVector2D vecToProjection = FindPlayerCoors() + FindPlayerSpeed() * projection * GAME_SPEED_TO_CARAI_SPEED;
- float angleToTarget = GetATanOfXY(vecToProjection.x - pVehicle->GetPosition().x, vecToProjection.y - pVehicle->GetPosition().y);
- float angleForward = GetATanOfXY(forward.x, forward.y);
+ float angleToTarget = CGeneral::GetATanOfXY(vecToProjection.x - pVehicle->GetPosition().x, vecToProjection.y - pVehicle->GetPosition().y);
+ float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
float steerAngle = LimitRadianAngle(angleToTarget - angleForward);
#ifdef FIX_BUGS
float speedTarget = pVehicle->AutoPilot.GetCruiseSpeed();
@@ -2784,7 +2856,7 @@ void CCarCtrl::SteerAIHeliTowardsTargetCoors(CAutomobile* pHeli)
if (distanceToTarget < 8.0f && pHeli->m_fHeliOrientation < 0.0f)
ZTurnSpeedTarget = 0.0f;
else {
- float fAngleTarget = GetATanOfXY(vecToTarget.x, vecToTarget.y) + PI;
+ float fAngleTarget = CGeneral::GetATanOfXY(vecToTarget.x, vecToTarget.y) + PI;
if (pHeli->m_fHeliOrientation >= 0.0f)
fAngleTarget = pHeli->m_fHeliOrientation;
fAngleTarget -= pHeli->m_fOrientation;
@@ -2827,7 +2899,7 @@ void CCarCtrl::SteerAIPlaneTowardsTargetCoors(CAutomobile* pPlane)
CVector2D vecToTarget = pPlane->AutoPilot.m_vecDestinationCoors - pPlane->GetPosition();
float fForwardZ = (pPlane->AutoPilot.m_vecDestinationCoors.z - pPlane->GetPosition().z) / vecToTarget.Magnitude();
fForwardZ = Clamp(fForwardZ, -0.3f, 0.3f);
- float angle = GetATanOfXY(vecToTarget.x, vecToTarget.y);
+ float angle = CGeneral::GetATanOfXY(vecToTarget.x, vecToTarget.y);
while (angle > TWOPI)
angle -= TWOPI;
float difference = LimitRadianAngle(angle - pPlane->m_fOrientation);
@@ -2924,8 +2996,8 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
projectedPosition.y = positionOnCurrentLinkIncludingLane.y;
}
CVector2D distanceToProjectedPosition = projectedPosition - pVehicle->GetPosition();
- float angleCurrentLink = GetATanOfXY(distanceToProjectedPosition.x, distanceToProjectedPosition.y);
- float angleForward = GetATanOfXY(forward.x, forward.y);
+ float angleCurrentLink = CGeneral::GetATanOfXY(distanceToProjectedPosition.x, distanceToProjectedPosition.y);
+ float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS)
angleCurrentLink = FindAngleToWeaveThroughTraffic(pVehicle, nil, angleCurrentLink, angleForward);
float steerAngle = LimitRadianAngle(angleCurrentLink - angleForward);
@@ -2970,11 +3042,11 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
trajectory -= pVehicle->GetPosition();
float speedAngleMultiplier = FindSpeedMultiplier(
- GetATanOfXY(trajectory.x, trajectory.y) - angleForward,
+ CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward,
MIN_ANGLE_FOR_SPEED_LIMITING, MAX_ANGLE_FOR_SPEED_LIMITING, MIN_LOWERING_SPEED_COEFFICIENT);
float tmpWideMultiplier = FindSpeedMultiplier(
- GetATanOfXY(currentPathLinkForward.x, currentPathLinkForward.y) -
- GetATanOfXY(nextPathLinkForwardX, nextPathLinkForwardY),
+ CGeneral::GetATanOfXY(currentPathLinkForward.x, currentPathLinkForward.y) -
+ CGeneral::GetATanOfXY(nextPathLinkForwardX, nextPathLinkForwardY),
MIN_ANGLE_FOR_SPEED_LIMITING_BETWEEN_NODES, MAX_ANGLE_FOR_SPEED_LIMITING, MIN_LOWERING_SPEED_COEFFICIENT);
float speedNodesMultiplier;
if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN || pVehicle->AutoPilot.m_nCruiseSpeed < 12)
@@ -3008,8 +3080,8 @@ void CCarCtrl::SteerAICarWithPhysicsHeadingForTarget(CVehicle* pVehicle, CPhysic
*pHandbrake = false;
CVector2D forward = pVehicle->GetForward();
forward.Normalise();
- float angleToTarget = GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
- float angleForward = GetATanOfXY(forward.x, forward.y);
+ float angleToTarget = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
+ float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
if (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS)
angleToTarget = FindAngleToWeaveThroughTraffic(pVehicle, pTarget, angleToTarget, angleForward);
float steerAngle = LimitRadianAngle(angleToTarget - angleForward);
@@ -3194,7 +3266,7 @@ bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTar
{
pVehicle->AutoPilot.m_vecDestinationCoors = vecTarget;
ThePaths.DoPathSearch(0, pVehicle->GetPosition(), -1, vecTarget, pVehicle->AutoPilot.m_aPathFindNodesInfo,
- &pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT, pVehicle, nil, 999999.9f, -1);
+ &pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT, pVehicle, nil, 100.0f, -1);
ThePaths.RemoveBadStartNode(pVehicle->GetPosition(),
pVehicle->AutoPilot.m_aPathFindNodesInfo, &pVehicle->AutoPilot.m_nPathFindNodesCount);
if (pVehicle->AutoPilot.m_nPathFindNodesCount < 2){
@@ -3253,12 +3325,18 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
void CCarCtrl::GenerateEmergencyServicesCar(void)
{
+#ifdef GTA_NETWORK
+ if (gIsMultiplayerGame)
+ return;
+#endif
if (FindPlayerPed()->m_pWanted->GetWantedLevel() > 3)
return;
if (CGame::IsInInterior())
return;
- if (TheCamera.m_WideScreenOn) // TODO(LCS): verify
+#ifndef GTA_PSP
+ if (TheCamera.m_WideScreenOn)
return;
+#endif
if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars +
NumLawEnforcerCars + NumRandomCars > MaxNumberOfCarsInUse)
return;
@@ -3312,6 +3390,10 @@ void CCarCtrl::GenerateEmergencyServicesCar(void)
bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos)
{
+#ifdef GTA_NETWORK
+ if (gIsMultiplayerGame)
+ return;
+#endif
CVector pPlayerPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
bool created = false;
int attempts = 0;
@@ -3377,6 +3459,11 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos)
pVehicle->m_bSirenOrAlarm = true;
CWorld::Add(pVehicle);
printf("CREATED EMERGENCY VEHICLE\n");
+#ifdef GTA_NETWORK
+ if (gIsMultiplayerGame) {
+ // TODO (register car for network)
+ }
+#endif
return true;
}
@@ -3458,9 +3545,8 @@ bool CCarCtrl::OkToCreateVehicleAtThisPosition(const CVector& pos)
if (gIsMultiplayerGame) {
// TODO
}
-#else
- return true;
#endif
+ return true;
}
float CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(int8 type)
@@ -3505,3 +3591,31 @@ void CCarCtrl::RenderDebugInfo(CVehicle* pVehicle)
DefinedState();
}
}
+
+void CCarCtrl::SetMultiplayerAmbientCarLimit(uint32 limit)
+{
+ maxRandomMpCars = limit;
+}
+
+void CCarCtrl::ToggleScriptControlsMpCarLimit(bool toggle)
+{
+ scriptControlsMpCarLimit = toggle;
+}
+
+void CCarCtrl::MultiPlayerRemoveVehicleAndDriver(CVehicle* pVehicle)
+{
+ CPed* pDriver = pVehicle->pDriver;
+ CWorld::Remove(pVehicle);
+ delete pVehicle;
+ if (pDriver) {
+ CWorld::Remove(pDriver);
+ delete pDriver;
+ }
+}
+
+void CCarCtrl::Write(base::cRelocatableChunkWriter& writer)
+{
+ writer.AllocateRaw(CarArrays, sizeof(CarArrays), 4);
+ writer.AllocateRaw(TotalNumOfCarsOfRating, sizeof(TotalNumOfCarsOfRating), 4, false, true);
+}
+
diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h
index edf1f41e..c6796504 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -17,6 +17,13 @@ enum{
MAX_CAR_MODELS_IN_ARRAY = 25,
};
+#ifdef GTA_NETWORK
+enum {
+ TOTAL_MULTIPLAYER_CAR_BANKS = 3,
+ CARS_IN_MULTIPLAYER_BANK = 8
+};
+#endif
+
#ifdef FIX_BUGS
#define FIX_PATHFIND_BUG
#endif
@@ -133,7 +140,10 @@ public:
static bool OkToCreateVehicleAtThisPosition(const CVector&);
static void RenderDebugInfo(CVehicle*);
- static float GetATanOfXY(float x, float y) { float t = CGeneral::GetATanOfXY(x, y); if (t < 0.0f) t += TWOPI; return t; }
+ static void SetMultiplayerAmbientCarLimit(uint32);
+ static void ToggleScriptControlsMpCarLimit(bool);
+ static void MultiPlayerRemoveVehicleAndDriver(CVehicle*);
+ static void Write(base::cRelocatableChunkWriter&);
static float GetPositionAlongCurrentCurve(CVehicle* pVehicle)
{
@@ -170,6 +180,14 @@ public:
static int32 NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
static int32 CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
static int32 LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
+
+#ifdef GTA_NETWORK
+ static const int32 MultiplayerCarBanks[TOTAL_MULTIPLAYER_CAR_BANKS][CARS_IN_MULTIPLAYER_BANK];
+#endif
+
+ static uint32 maxRandomMpCars;
+ static bool scriptControlsMpCarLimit;
+
};
extern CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP];