diff options
-rw-r--r-- | src/control/CarCtrl.cpp | 228 | ||||
-rw-r--r-- | src/control/CarCtrl.h | 3 |
2 files changed, 131 insertions, 100 deletions
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 781c8799..93e9aa44 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -11,6 +11,7 @@ #include "Cranes.h" #include "Curves.h" #include "CutsceneMgr.h" +#include "Frontend.h" #include "Gangs.h" #include "Game.h" #include "Garages.h" @@ -76,10 +77,11 @@ #define DISTANCE_BETWEEN_CAR_AND_DEAD_PED (6.0f) #define PROBABILITY_OF_PASSENGER_IN_VEHICLE (0.125f) -#define ONSCREEN_DESPAWN_RANGE (120.0f) -#define MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN (100.0f) -#define REQUEST_ONSCREEN_DISTANCE ((ONSCREEN_DESPAWN_RANGE + MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) / 2) -#define OFFSCREEN_DESPAWN_RANGE (40.0f) +#define ONSCREEN_DESPAWN_RANGE (190.0f) +#define MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN (130.0f) +#define REQUEST_ONSCREEN_DISTANCE (140.0f) +#define OFFSCREEN_DESPAWN_RANGE (60.0f) +#define MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN (40.0f) #define EXTENDED_RANGE_DESPAWN_MULTIPLIER (1.5f) //--MIAMI: file done @@ -95,7 +97,7 @@ int32 CCarCtrl::NumRandomCars; int32 CCarCtrl::NumParkedCars; int32 CCarCtrl::NumPermanentCars; int8 CCarCtrl::CountDownToCarsAtStart; -int32 CCarCtrl::MaxNumberOfCarsInUse = 12; +int32 CCarCtrl::MaxNumberOfCarsInUse = 30; uint32 CCarCtrl::LastTimeLawEnforcerCreated; uint32 CCarCtrl::LastTimeFireTruckCreated; uint32 CCarCtrl::LastTimeAmbulanceCreated; @@ -161,14 +163,19 @@ CCarCtrl::GenerateOneRandomCar() carClass = COPS; carModel = ChoosePoliceCarModel(); }else{ - carModel = ChooseModel(&zone, &carClass); - if (carModel == -1 || (carClass == COPS && pWanted->m_nWantedLevel >= 1)) - /* 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; + for (int i = 0; i < 5; i++) { + carModel = ChooseModel(&zone, &carClass); + if (carModel == -1) + return; + if (!(carClass == COPS && pWanted->m_nWantedLevel >= 1)) + /* 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. */ + break; + } } float frontX, frontY; float preferredDistance, angleLimit; + float requestMultiplier; bool invertAngleLimitTest; CVector spawnPosition; int32 curNodeId, nextNodeId; @@ -188,11 +195,14 @@ CCarCtrl::GenerateOneRandomCar() angleLimit = -1.0f; bTopDownCamera = true; invertAngleLimitTest = true; - preferredDistance = OFFSCREEN_DESPAWN_RANGE + 15.0f; + preferredDistance = MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN + 15.0f; /* BUG: testForCollision not initialized in original game. */ testForCollision = false; }else if (!pPlayerVehicle){ /* Player is not in vehicle. */ + requestMultiplier = 13.0f / 20.0f; + if (FrontEndMenuManager.m_PrefsUseWideScreen) // TODO(LCS): static + requestMultiplier *= 4.0f / 3.0f; testForCollision = true; frontX = TheCamera.CamFrontXNorm; frontY = TheCamera.CamFrontYNorm; @@ -202,95 +212,105 @@ CCarCtrl::GenerateOneRandomCar() /* Forward to his current direction (camera direction). */ angleLimit = 0.707f; /* 45 degrees */ invertAngleLimitTest = true; - preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier; + preferredDistance = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * TheCamera.GenerationDistMultiplier; break; case 1: /* Spawn a vehicle close to player to his side. */ /* Kinda not within camera angle. */ angleLimit = 0.707f; /* 45 degrees */ invertAngleLimitTest = false; - preferredDistance = OFFSCREEN_DESPAWN_RANGE; + preferredDistance = MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN; break; } - }else if (fPlayerVehicleSpeed > 0.4f){ /* 72 km/h */ + } + else { + requestMultiplier = 13.0f / 20.0f; + if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON && !FrontEndMenuManager.m_PrefsUseWideScreen) + requestMultiplier *= 0.9f; + if (FrontEndMenuManager.m_PrefsUseWideScreen) // TODO(LCS): static + requestMultiplier *= 4.0f / 3.0f; + if (fPlayerVehicleSpeed > 0.4f) { /* 72 km/h */ /* Player is moving fast in vehicle */ /* Prefer spawning vehicles very far away from him. */ - frontX = vecPlayerVehicleSpeed.x / fPlayerVehicleSpeed; - frontY = vecPlayerVehicleSpeed.y / fPlayerVehicleSpeed; - testForCollision = false; - switch (CTimer::GetFrameCounter() & 3) { - case 0: - case 1: - /* Spawn a vehicle in a very narrow gap in front of a player */ - angleLimit = 0.85f; /* approx 30 degrees */ - invertAngleLimitTest = true; - preferredDistance = REQUEST_ONSCREEN_DISTANCE * 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 = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier; - break; - case 3: - /* Spawn a vehicle close to player to his side. */ - /* Kinda not within camera angle. */ - angleLimit = 0.707f; /* 45 degrees */ - invertAngleLimitTest = false; - preferredDistance = OFFSCREEN_DESPAWN_RANGE; - break; + frontX = vecPlayerVehicleSpeed.x / fPlayerVehicleSpeed; + frontY = vecPlayerVehicleSpeed.y / fPlayerVehicleSpeed; + testForCollision = false; + switch (CTimer::GetFrameCounter() & 3) { + case 0: + case 1: + /* Spawn a vehicle in a very narrow gap in front of a player */ + angleLimit = 0.85f; /* approx 30 degrees */ + invertAngleLimitTest = true; + preferredDistance = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * 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 = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * TheCamera.GenerationDistMultiplier; + break; + case 3: + /* Spawn a vehicle close to player to his side. */ + /* Kinda not within camera angle. */ + angleLimit = 0.707f; /* 45 degrees */ + invertAngleLimitTest = false; + preferredDistance = MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN; + break; + } } - }else if (fPlayerVehicleSpeed > 0.1f){ /* 18 km/h */ - /* Player is moving moderately fast in vehicle */ - /* Spawn more vehicles to player's side. */ - frontX = vecPlayerVehicleSpeed.x / fPlayerVehicleSpeed; - frontY = vecPlayerVehicleSpeed.y / fPlayerVehicleSpeed; - testForCollision = false; - switch (CTimer::GetFrameCounter() & 3) { - case 0: - /* Spawn a vehicle in a very narrow gap in front of a player */ - angleLimit = 0.85f; /* approx 30 degrees */ - invertAngleLimitTest = true; - preferredDistance = REQUEST_ONSCREEN_DISTANCE * 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 = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier; - break; - case 2: - case 3: - /* Spawn a vehicle close to player to his side. */ - /* Kinda not within camera angle. */ - angleLimit = 0.707f; /* 45 degrees */ - invertAngleLimitTest = false; - preferredDistance = OFFSCREEN_DESPAWN_RANGE; - break; + else if (fPlayerVehicleSpeed > 0.1f) { /* 18 km/h */ + /* Player is moving moderately fast in vehicle */ + /* Spawn more vehicles to player's side. */ + frontX = vecPlayerVehicleSpeed.x / fPlayerVehicleSpeed; + frontY = vecPlayerVehicleSpeed.y / fPlayerVehicleSpeed; + testForCollision = false; + switch (CTimer::GetFrameCounter() & 3) { + case 0: + /* Spawn a vehicle in a very narrow gap in front of a player */ + angleLimit = 0.85f; /* approx 30 degrees */ + invertAngleLimitTest = true; + preferredDistance = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * 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 = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * TheCamera.GenerationDistMultiplier; + break; + case 2: + case 3: + /* Spawn a vehicle close to player to his side. */ + /* Kinda not within camera angle. */ + angleLimit = 0.707f; /* 45 degrees */ + invertAngleLimitTest = false; + preferredDistance = MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN; + break; + } } - }else{ - /* Player is in vehicle but moving very slow. */ - /* Then use camera direction instead of vehicle direction. */ - testForCollision = true; - frontX = TheCamera.CamFrontXNorm; - frontY = TheCamera.CamFrontYNorm; - switch (CTimer::GetFrameCounter() & 1) { - case 0: - /* Spawn a vehicle relatively far away from player. */ - /* Forward to his current direction (camera direction). */ - angleLimit = 0.707f; /* 45 degrees */ - invertAngleLimitTest = true; - preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier; - break; - case 1: - /* Spawn a vehicle close to player to his side. */ - /* Kinda not within camera angle. */ - angleLimit = 0.707f; /* 45 degrees */ - invertAngleLimitTest = false; - preferredDistance = OFFSCREEN_DESPAWN_RANGE; - break; + else { + /* Player is in vehicle but moving very slow. */ + /* Then use camera direction instead of vehicle direction. */ + testForCollision = true; + frontX = TheCamera.CamFrontXNorm; + frontY = TheCamera.CamFrontYNorm; + switch (CTimer::GetFrameCounter() & 1) { + case 0: + /* Spawn a vehicle relatively far away from player. */ + /* Forward to his current direction (camera direction). */ + angleLimit = 0.707f; /* 45 degrees */ + invertAngleLimitTest = true; + preferredDistance = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * TheCamera.GenerationDistMultiplier; + break; + case 1: + /* Spawn a vehicle close to player to his side. */ + /* Kinda not within camera angle. */ + angleLimit = 0.707f; /* 45 degrees */ + invertAngleLimitTest = false; + preferredDistance = MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN; + break; + } } } if (!ThePaths.GenerateCarCreationCoors(vecTargetPos.x, vecTargetPos.y, frontX, frontY, @@ -300,6 +320,8 @@ CCarCtrl::GenerateOneRandomCar() CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId]; CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId]; bool bBoatGenerated = false; + if (!OkToCreateVehicleAtThisPosition(spawnPosition)) + return; if ((CGeneral::GetRandomNumber() & 0xF) > Min(pCurNode->spawnRate, pNextNode->spawnRate)) return; if (pCurNode->bWaterPath) { @@ -604,12 +626,12 @@ CCarCtrl::GenerateOneRandomCar() return; } }else{ - if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f) * ONSCREEN_DESPAWN_RANGE || - (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) { + if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * requestMultiplier * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f) * ONSCREEN_DESPAWN_RANGE || + (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * requestMultiplier * MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) { delete pVehicle; return; } - if ((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera) { + if ((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 105.0f * requestMultiplier * TheCamera.GenerationDistMultiplier || bTopDownCamera) { delete pVehicle; return; } @@ -659,13 +681,13 @@ CCarCtrl::GenerateOneRandomCar() int nMadDrivers; switch (pVehicle->GetVehicleAppearance()) { case VEHICLE_APPEARANCE_BIKE: - nMadDrivers = 30; + nMadDrivers = 20; break; case VEHICLE_APPEARANCE_BOAT: nMadDrivers = 40; break; default: - nMadDrivers = 6; + nMadDrivers = 3; break; } if ((CGeneral::GetRandomNumber() & 0x7F) < nMadDrivers || bMadDriversCheat) { @@ -949,6 +971,7 @@ CCarCtrl::RemoveCarsIfThePoolGetsFull(void) } } if (pClosestVehicle) { + debug(":::::::::::\'Nearest removed\' cause pools was full -> NumRandomCars %d\n", NumRandomCars); CWorld::Remove(pClosestVehicle); delete pClosestVehicle; } @@ -971,7 +994,10 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) return; } float distanceToPlayer = (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D(); - float threshold = OFFSCREEN_DESPAWN_RANGE; + float despawnMultiplier = 1.0f; + if (FindPlayerVehicle() && TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON && !FrontEndMenuManager.m_PrefsUseWideScreen) + despawnMultiplier = 0.75f; + float threshold = OFFSCREEN_DESPAWN_RANGE * despawnMultiplier; if (pVehicle->GetIsOnScreen() || TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight || @@ -984,7 +1010,7 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle) pVehicle->bIsCarParkVehicle || CTimer::GetTimeInMilliseconds() < pVehicle->m_nSetPieceExtendedRangeTime ){ - threshold = ONSCREEN_DESPAWN_RANGE * TheCamera.GenerationDistMultiplier; + threshold = ONSCREEN_DESPAWN_RANGE * despawnMultiplier * TheCamera.GenerationDistMultiplier; } if (TheCamera.GetForward().z < -0.9f) threshold = 70.0f; @@ -1767,7 +1793,7 @@ bool CCarCtrl::PickNextNodeAccordingStrategy(CVehicle* pVehicle) void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) { if (pVehicle->m_nRouteSeed) - CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed); + CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed++); int32 prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode; int32 curNode = pVehicle->AutoPilot.m_nNextRouteNode; uint8 totalLinks = ThePaths.m_pathNodes[curNode].numLinks; @@ -1853,13 +1879,15 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode]; if ((!pNextPathNode->bDisabled || pPrevPathNode->bDisabled) && (!pNextPathNode->bBetweenLevels || pPrevPathNode->bBetweenLevels || !pVehicle->AutoPilot.m_bStayInCurrentLevel)) - /* Nice way to exit loop but this will fail because this is used for indexing! */ - nextLink = 1000; + break; } } - if (nextLink < 999) + if (nextLink >= totalLinks) { /* If everything else failed, turn vehicle around */ + nextLink = 0; + debug("Couldn\'t find ANYTHING. Just go back from where we came.\n"); pVehicle->AutoPilot.m_nNextRouteNode = prevNode; + } } pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode]; pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]]; @@ -1983,7 +2011,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t #endif { if (pVehicle->m_nRouteSeed) - CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed); + CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed++); int prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode; int curNode = pVehicle->AutoPilot.m_nNextRouteNode; CPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNode]; diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 5efbe275..61ebb35c 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -130,6 +130,9 @@ public: static void SteerAIBoatWithPhysicsAttackingPlayer(CVehicle*, float*, float*, float*, bool*); static void SteerAICarBlockingPlayerForwardAndBack(CVehicle*, float*, float*, float*, bool*); + static bool OkToCreateVehicleAtThisPosition(const CVector&) { return true; } + static float GetATanOfXY(float x, float y) { float t = CGeneral::GetATanOfXY(x, y); if (t < 0.0f) t += TWOPI; return t; } // TODO(LCS): replace where required + static float GetPositionAlongCurrentCurve(CVehicle* pVehicle) { uint32 timeInCurve = CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeEnteredCurve; |