From 40888e9486f00aa852c531209bbfe55f24e2e04f Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 7 May 2020 16:57:49 +0300 Subject: [PATCH 1/5] car control and friends --- src/control/CarCtrl.cpp | 285 +++++++++++++++++++++++--------------- src/control/CarCtrl.h | 12 +- src/control/PathFind.cpp | 6 +- src/core/FileLoader.cpp | 4 +- src/core/Game.h | 2 + src/entities/Building.h | 1 - src/entities/Dummy.h | 1 - src/entities/Entity.h | 1 - src/entities/Physical.h | 1 - src/objects/DummyObject.h | 1 - src/objects/Object.h | 1 - src/peds/DummyPed.h | 1 - src/peds/Population.cpp | 1 + 13 files changed, 189 insertions(+), 128 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index a4769d56..6818cd19 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" @@ -113,6 +115,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(); @@ -127,7 +130,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)) { @@ -161,8 +164,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){ @@ -176,7 +180,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. */ @@ -198,14 +202,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. */ @@ -226,14 +230,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: @@ -256,7 +260,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. */ @@ -271,17 +275,35 @@ 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 { + // 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++; @@ -289,14 +311,19 @@ 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: @@ -315,48 +342,55 @@ CCarCtrl::GenerateOneRandomCar() case GANG8: case GANG9: { - pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14); + pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14); if (carClass == EXEC) - pCar->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18); + pVehicle->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; + pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10); + CVehicleModelInfo* pVehicleInfo = pVehicle->GetModelInfo(); + if (pVehicleInfo->GetColModel()->boundingBox.max.y - pVehicle->GetModelInfo()->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) { + pVehicle->AutoPilot.m_nCruiseSpeed *= 3; + pVehicle->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; + 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; } 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 + 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: 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; - CBox* 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. */ @@ -365,20 +399,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(); @@ -391,47 +425,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)(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); @@ -442,8 +476,8 @@ CCarCtrl::GenerateOneRandomCar() &positionOnNextLinkIncludingLane, &directionCurrentLink, &directionNextLink, - GetPositionAlongCurrentCurve(pCar), - pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve, + GetPositionAlongCurrentCurve(pVehicle), + pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve, &positionIncludingCurve, &directionIncludingCurve ); @@ -454,21 +488,34 @@ 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: @@ -487,62 +534,67 @@ CCarCtrl::GenerateOneRandomCar() case NINES: case GANG8: case GANG9: - pCar->SetStatus(STATUS_SIMPLE); + pVehicle->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: 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*/ } int32 @@ -681,7 +733,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 || @@ -693,8 +745,10 @@ 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())){ @@ -707,7 +761,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 && diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 4f92bdcf..53ada8ca 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -41,7 +41,17 @@ class CCarCtrl NINES, GANG8, GANG9, - COPS + COPS, + CLASS12, + CLASS13, + CLASS14, + CLASS15, + CLASS16, + CLASS17, + CLASS18, + CLASS19, + CLASS20, + COPS_BOAT }; public: static void SwitchVehicleToRealPhysics(CVehicle*); diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 08eadb25..20c4aa69 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -1419,14 +1419,14 @@ CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, if(m_pathNodes[node1].bDisabled && !ignoreDisabled) continue; dist1 = Distance2D(m_pathNodes[node1].GetPosition(), x, y); - if(dist1 < spawnDist + 60.0f){ - d1 = dist1 - spawnDist; + if(dist1 < Max(spawnDist + 70.0f, spawnDist * 1.7f)){ + d1 = m_pathNodes[node1].bWaterPath ? (dist1 - spawnDist * 1.5f) : (dist1 - spawnDist); for(j = 0; j < m_pathNodes[node1].numLinks; j++){ node2 = ConnectedNode(m_pathNodes[node1].firstLink + j); if(m_pathNodes[node2].bDisabled && !ignoreDisabled) continue; dist2 = Distance2D(m_pathNodes[node2].GetPosition(), x, y); - d2 = dist2 - spawnDist; + d2 = m_pathNodes[node2].bWaterPath ? (dist2 - spawnDist * 1.5f) : (dist2 - spawnDist); if(d1*d2 < 0.0f){ // nodes are on different sides of spawn distance float f2 = Abs(d1)/(Abs(d1) + Abs(d2)); diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp index 21fd8a70..b42cd0a2 100644 --- a/src/core/FileLoader.cpp +++ b/src/core/FileLoader.cpp @@ -927,10 +927,10 @@ CFileLoader::LoadCarPathNode(const char *line, int id, int node, bool waterPath) if(id == -1) ThePaths.StoreDetachedNodeInfoCar(node, type, next, x, y, z, width, numLeft, numRight, - !!(flags&1), !!(flags&4), speed, !!(flags&2), waterPath, spawnRate, false); + !!(flags&1), !!(flags&4), speed, !!(flags&2), waterPath, spawnRate * 15, false); else ThePaths.StoreNodeInfoCar(id, node, type, next, x, y, z, 0, numLeft, numRight, - !!(flags&1), !!(flags&4), speed, !!(flags&2), waterPath, spawnRate); + !!(flags&1), !!(flags&4), speed, !!(flags&2), waterPath, spawnRate * 15); } diff --git a/src/core/Game.h b/src/core/Game.h index 1b8fcb0a..ed9ded4f 100644 --- a/src/core/Game.h +++ b/src/core/Game.h @@ -58,6 +58,8 @@ public: static void ShutDownForRestart(void); static void InitialiseWhenRestarting(void); static void Process(void); + + static bool IsInInterior(void) { return currArea != AREA_MAIN_MAP; } // NB: these do something on PS2 static void TidyUpMemory(bool, bool); diff --git a/src/entities/Building.h b/src/entities/Building.h index 7b837f46..29608c10 100644 --- a/src/entities/Building.h +++ b/src/entities/Building.h @@ -16,4 +16,3 @@ public: virtual bool GetIsATreadable(void) { return false; } }; -static_assert(sizeof(CBuilding) == 0x64, "CBuilding: error"); diff --git a/src/entities/Dummy.h b/src/entities/Dummy.h index fcfd23fb..7998a748 100644 --- a/src/entities/Dummy.h +++ b/src/entities/Dummy.h @@ -15,4 +15,3 @@ public: static void *operator new(size_t); static void operator delete(void*, size_t); }; -static_assert(sizeof(CDummy) == 0x68, "CDummy: error"); diff --git a/src/entities/Entity.h b/src/entities/Entity.h index e85e40f7..2e2c64c0 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -174,4 +174,3 @@ public: static void AddSteamsFromGround(CPtrList& list); }; -static_assert(sizeof(CEntity) == 0x64, "CEntity: error"); diff --git a/src/entities/Physical.h b/src/entities/Physical.h index b47d556e..c801ae72 100644 --- a/src/entities/Physical.h +++ b/src/entities/Physical.h @@ -160,4 +160,3 @@ public: bool CheckCollision(void); bool CheckCollision_SimpleCar(void); }; -static_assert(sizeof(CPhysical) == 0x128, "CPhysical: error"); diff --git a/src/objects/DummyObject.h b/src/objects/DummyObject.h index d4dce609..680df685 100644 --- a/src/objects/DummyObject.h +++ b/src/objects/DummyObject.h @@ -10,4 +10,3 @@ public: CDummyObject(void) {} CDummyObject(CObject *obj); }; -static_assert(sizeof(CDummyObject) == 0x68, "CDummyObject: error"); diff --git a/src/objects/Object.h b/src/objects/Object.h index 2afb621c..20c99b1b 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -113,4 +113,3 @@ public: static void DeleteAllTempObjects(); static void DeleteAllTempObjectsInArea(CVector point, float fRadius); }; -static_assert(sizeof(CObject) == 0x198, "CObject: error"); diff --git a/src/peds/DummyPed.h b/src/peds/DummyPed.h index af633dc4..cace4ead 100644 --- a/src/peds/DummyPed.h +++ b/src/peds/DummyPed.h @@ -8,4 +8,3 @@ class CDummyPed : CDummy int32 pedType; int32 unknown; }; -static_assert(sizeof(CDummyPed) == 0x70, "CDummyPed: error"); diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index d81648fa..53cf334f 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -734,6 +734,7 @@ CPopulation::AddPedInCar(CVehicle* car) pedType = PEDTYPE_COP; break; case MI_POLICE: + case MI_PREDATOR: preferredModel = COP_STREET; pedType = PEDTYPE_COP; break; From 2dc818e4d239b96e4f762531a9858a15de36a30f Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Thu, 7 May 2020 23:21:36 +0300 Subject: [PATCH 2/5] intermediate changes --- src/control/CarCtrl.cpp | 123 +++++++++++++++++++--------------------- src/control/CarCtrl.h | 26 +++++---- 2 files changed, 73 insertions(+), 76 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index e8bc977c..66a41fcb 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -86,6 +86,7 @@ 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]; CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP]; uint32 aCarsToKeepTime[MAX_CARS_TO_KEEP]; @@ -350,7 +351,7 @@ CCarCtrl::GenerateOneRandomCar() pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14); if (carClass == EXEC) pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18); - else if (carClass == POOR || carClass == SPECIAL) + else if (carClass == POOR) pVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10); CVehicleModelInfo* pVehicleInfo = pVehicle->GetModelInfo(); if (pVehicleInfo->GetColModel()->boundingBox.max.y - pVehicle->GetModelInfo()->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) { @@ -607,46 +608,57 @@ CCarCtrl::GenerateOneRandomCar() /* TODO(MIAMI): CADDY, VICECHEE, dead ped code*/ } +int32 +CCarCtrl::ChooseBoatModel(int32 rating) +{ + ++NumRequestsOfCarRating[rating]; + return ChooseCarModel(rating); +} + +int32 +CCarCtrl::ChooseBoatRating(CZoneInfo* pZoneInfo) +{ + int rnd = CGeneral::GetRandomNumberInRange(0, 1000); + for (int i = FIRST_BOAT_RATING; i < FIRST_BOAT_RATING + NUM_BOAT_CLASSES - 1; i++) { + if (rnd < pZoneInfo->carThreshold[i]) + return i; + } + return FIRST_BOAT_RATING + NUM_BOAT_CLASSES - 1; +} + +int32 +CCarCtrl::ChooseCarRating(CZoneInfo* pZoneInfo) +{ + int rnd = CGeneral::GetRandomNumberInRange(0, 1000); + for (int i = FIRST_CAR_RATING; i < FIRST_CAR_RATING + 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); - // TODO(MIAMI): new car classes - if (rnd < pZone->carThreshold[0]) - model = CCarCtrl::ChooseCarModel((*pClass = NORMAL)); - else if (rnd < pZone->carThreshold[1]) - model = CCarCtrl::ChooseCarModel((*pClass = POOR)); - else if (rnd < pZone->carThreshold[2]) - model = CCarCtrl::ChooseCarModel((*pClass = RICH)); - else if (rnd < pZone->carThreshold[3]) - model = CCarCtrl::ChooseCarModel((*pClass = EXEC)); - else if (rnd < pZone->carThreshold[4]) - model = CCarCtrl::ChooseCarModel((*pClass = WORKER)); - 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 = FIRST_GANG_CAR_RATING; i < FIRST_GANG_CAR_RATING + NUM_GANG_CAR_CLASSES; i++) { + if (rnd < pZone->carThreshold[i]) { + *pClass = i; + model = ChooseGangCarModel(i - FIRST_GANG_CAR_RATING); + continue; + } + } + + *pClass = ChooseCarRating(pZone); + model = ChooseCarModel(*pClass); } return model; } @@ -655,33 +667,16 @@ int32 CCarCtrl::ChooseCarModel(int32 vehclass) { int32 model = -1; - switch (vehclass) { - case POOR: - case RICH: - case EXEC: - case WORKER: - // TODO(MIAMI): check this - case MOPED: - case MOTORBIKE: - case LEISUREBOAT: - case WORKERBOAT: - // - 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; - } + ++NumRequestsOfCarRating[vehclass]; + if (TotalNumOfCarsOfRating[vehclass] == 0) + return -1; + 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... */ return model; } diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 1ef2fed7..f71fc26f 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -36,7 +36,7 @@ public: MOTORBIKE, LEISUREBOAT, WORKERBOAT, - TOTAL_CUSTOM_CLASSES, + COPS, MAFIA, TRIAD, DIABLO, @@ -46,17 +46,14 @@ public: NINES, GANG8, GANG9, - COPS, - CLASS12, - CLASS13, - CLASS14, - CLASS15, - CLASS16, - CLASS17, - CLASS18, - CLASS19, - CLASS20, - COPS_BOAT + COPS_BOAT, + FIRST_CAR_RATING = NORMAL, + FIRST_BOAT_RATING = LEISUREBOAT, + FIRST_GANG_CAR_RATING = MAFIA, + NUM_CAR_CLASSES = MOTORBIKE - FIRST_CAR_RATING + 1, + NUM_BOAT_CLASSES = WORKERBOAT - FIRST_BOAT_RATING + 1, + NUM_GANG_CAR_CLASSES = GANG9 - FIRST_GANG_CAR_RATING + 1, + TOTAL_CUSTOM_CLASSES = NUM_CAR_CLASSES + NUM_BOAT_CLASSES }; static void SwitchVehicleToRealPhysics(CVehicle*); @@ -120,6 +117,9 @@ public: static void FindLinksToGoWithTheseNodes(CVehicle*); static bool GenerateOneEmergencyServicesCar(uint32, CVector); static float FindSpeedMultiplierWithSpeedFromNodes(int8); + static int32 ChooseBoatModel(int32); + static int32 ChooseBoatRating(CZoneInfo* pZoneInfo); + static int32 ChooseCarRating(CZoneInfo* pZoneInfo); static float GetPositionAlongCurrentCurve(CVehicle* pVehicle) { @@ -153,6 +153,8 @@ public: static int32 TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES]; static int32 NextCarOfRating[TOTAL_CUSTOM_CLASSES]; static int32 CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY]; + + static int32 NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES]; }; extern CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP]; \ No newline at end of file From 44c5cdf453f1b49ce07f7f1b526e2e5808ac245c Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 8 May 2020 11:11:09 +0300 Subject: [PATCH 3/5] tmp stuff --- src/control/CarCtrl.cpp | 153 ++++++++++++++++++++++++++++------------ src/control/CarCtrl.h | 9 ++- src/core/Streaming.cpp | 54 +++++++++----- 3 files changed, 148 insertions(+), 68 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 808a3769..8be92ede 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -84,26 +84,37 @@ 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() { + static int vals[20]; + static uint32 old = CTimer::GetTimeInMilliseconds(); + if (CTimer::GetTimeInMilliseconds() - old > 1000) { + char str[512]; + sprintf(str, "%8d: %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n", old, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8], vals[9], vals[10], vals[11], vals[12], vals[13], vals[14], vals[15], vals[16], vals[17], vals[18], vals[19]); + debug("%s", str); + for (int i = 0; i < 20; i++) + vals[i] = 0; + old = CTimer::GetTimeInMilliseconds(); + } if (CCutsceneMgr::IsRunning()) { CountDownToCarsAtStart = 2; return; } if (NumRandomCars < 30){ - if (CountDownToCarsAtStart == 0){ - GenerateOneRandomCar(); - } + if (CountDownToCarsAtStart == 0) + vals[GenerateOneRandomCar()]++; else if (--CountDownToCarsAtStart == 0) { for (int i = 0; i < 100; i++) - GenerateOneRandomCar(); + vals[GenerateOneRandomCar()]++; CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = 20; } } @@ -112,7 +123,7 @@ CCarCtrl::GenerateRandomCars() GenerateEmergencyServicesCar(); } -void +int CCarCtrl::GenerateOneRandomCar() { static int32 unk = 0; @@ -124,9 +135,9 @@ CCarCtrl::GenerateOneRandomCar() CTheZones::GetZoneInfoForTimeOfDay(&vecTargetPos, &zone); pPlayer->m_nTrafficMultiplier = pPlayer->m_fRoadDensity * zone.carDensity; if (NumRandomCars >= pPlayer->m_nTrafficMultiplier * CarDensityMultiplier * CIniFile::CarNumberMultiplier) - return; + return 1; if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars + NumLawEnforcerCars + NumRandomCars >= MaxNumberOfCarsInUse) - return; + return 2; CWanted* pWanted = pPlayer->m_pPed->m_pWanted; int carClass; int carModel; @@ -141,10 +152,10 @@ 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; + return 3; } float frontX, frontY; float preferredDistance, angleLimit; @@ -275,12 +286,12 @@ CCarCtrl::GenerateOneRandomCar() if (!ThePaths.NewGenerateCarCreationCoors(vecTargetPos.x, vecTargetPos.y, frontX, frontY, preferredDistance, angleLimit, invertAngleLimitTest, &spawnPosition, &curNodeId, &nextNodeId, &positionBetweenNodes, carClass == COPS && pWanted->m_nWantedLevel >= 1)) - return; + return 4; 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; + return 5; if (pCurNode->bWaterPath) { bBoatGenerated = true; if (carClass == COPS) { @@ -288,9 +299,10 @@ CCarCtrl::GenerateOneRandomCar() carClass = COPS_BOAT; if (!CStreaming::HasModelLoaded(MI_PREDATOR)) { CStreaming::RequestModel(MI_PREDATOR, STREAMFLAGS_DEPENDENCY); - return; + return 6; } else { + return 7; // TODO: normal boats } } @@ -299,10 +311,10 @@ CCarCtrl::GenerateOneRandomCar() 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; + return 8; if (!bBoatGenerated && !ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition)) /* Testing if spawn position can reach target position via valid path. */ - return; + return 9; int16 idInNode = 0; while (idInNode < pCurNode->numLinks && @@ -314,7 +326,7 @@ CCarCtrl::GenerateOneRandomCar() CVehicleModelInfo* pModelInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(carModel); if (lanesOnCurrentRoad == 0) /* Not spawning vehicle if road is one way and intended direction is opposide to that way. */ - return; + return 10; CVehicle* pVehicle; if (CModelInfo::IsBoatModel(carModel)) pVehicle = new CBoat(carModel, RANDOM_VEHICLE); @@ -409,7 +421,7 @@ CCarCtrl::GenerateOneRandomCar() if (pCurNode->numLinks == 1){ /* Do not create vehicle if there is nowhere to go. */ delete pVehicle; - return; + return 11; } int16 nextConnection = pVehicle->AutoPilot.m_nNextPathNodeInfo; int16 newLink; @@ -489,6 +501,15 @@ CCarCtrl::GenerateOneRandomCar() ); CVector vectorBetweenNodes = pCurNode->GetPosition() - pNextNode->GetPosition(); CVector finalPosition = positionIncludingCurve + vectorBetweenNodes * 2.0f / vectorBetweenNodes.Magnitude(); + debug("initialPositionDist: %f\n", (spawnPosition - vecTargetPos).Magnitude()); + debug("pCurNode: %f\n", (CVector2D(pCurNode->GetX(), pCurNode->GetY()) - vecTargetPos).Magnitude()); + debug("pNextNode: %f\n", (CVector2D(pNextNode->GetX(), pNextNode->GetY()) - vecTargetPos).Magnitude()); + debug("pCurrentLink: %f\n", (CVector2D(pCurrentLink->GetX(), pCurrentLink->GetY()) - vecTargetPos).Magnitude()); + debug("pNextLink: %f\n", (CVector2D(pNextLink->GetX(), pNextLink->GetY()) - vecTargetPos).Magnitude()); + debug("positionOnCurrentLinkIncludingLane: %f\n", (positionOnCurrentLinkIncludingLane - vecTargetPos).Magnitude()); + debug("positionOnNextLinkIncludingLane: %f\n", (positionOnNextLinkIncludingLane - vecTargetPos).Magnitude()); + debug("positionIncludingCurve: %f\n", (finalPosition - vecTargetPos).Magnitude()); + debug("finalPositionDist: %f\n", (finalPosition - vecTargetPos).Magnitude()); finalPosition.z = positionBetweenNodes * pNextNode->GetZ() + (1.0f - positionBetweenNodes) * pCurNode->GetZ(); float groundZ = INFINITE_Z; @@ -497,7 +518,7 @@ CCarCtrl::GenerateOneRandomCar() if (bBoatGenerated) { if (!CWaterLevel::GetWaterLevel(finalPosition, &groundZ, true)) { delete pVehicle; - return; + return 12; } } else { @@ -511,7 +532,7 @@ CCarCtrl::GenerateOneRandomCar() if (groundZ == INFINITE_Z || ABS(groundZ - finalPosition.z) > 7.0f) { /* Failed to find ground or too far from expected position. */ delete pVehicle; - return; + return 13; } if (CModelInfo::IsBoatModel(carModel)) { finalPosition.z = groundZ; @@ -562,15 +583,17 @@ CCarCtrl::GenerateOneRandomCar() 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 pVehicle; - return; + return 14; } }else if((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? 1.5f : 1.0f) * 120.0f || (vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * 100.0f){ + debug("not spawning because %f\n", (vecTargetPos - pVehicle->GetPosition()).Magnitude2D()); delete pVehicle; - return; - }else if((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera){ + return 15; + }else if((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera ){ + debug("despite %f got %f\n", (vecTargetPos - pVehicle->GetPosition()).Magnitude2D(), (TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D()); delete pVehicle; - return; + return 16; } // TODO(MIAMI): if MARQUIS then delete CVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo(); @@ -579,18 +602,18 @@ CCarCtrl::GenerateOneRandomCar() CWorld::FindObjectsKindaColliding(pVehicle->GetPosition(), radiusToTest + 20.0f, true, &colliding, 2, nil, false, true, false, false, false); if (colliding){ delete pVehicle; - return; + return 17; } } CWorld::FindObjectsKindaColliding(pVehicle->GetPosition(), radiusToTest, true, &colliding, 2, nil, false, true, false, false, false); if (colliding){ delete pVehicle; - return; + return 18; } if (speedDifferenceWithTarget.x * distanceToTarget.x + speedDifferenceWithTarget.y * distanceToTarget.y >= 0.0f){ delete pVehicle; - return; + return 19; } pVehicleModel->AvoidSameVehicleColour(&pVehicle->m_currentColour1, &pVehicle->m_currentColour2); CWorld::Add(pVehicle); @@ -606,6 +629,7 @@ CCarCtrl::GenerateOneRandomCar() if (carClass == COPS) LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds(); /* TODO(MIAMI): CADDY, VICECHEE, dead ped code*/ + return 0; } int32 @@ -619,9 +643,9 @@ int32 CCarCtrl::ChooseBoatRating(CZoneInfo* pZoneInfo) { int rnd = CGeneral::GetRandomNumberInRange(0, 1000); - for (int i = FIRST_BOAT_RATING; i < FIRST_BOAT_RATING + NUM_BOAT_CLASSES - 1; i++) { - if (rnd < pZoneInfo->carThreshold[i]) - return i; + 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; } @@ -630,7 +654,7 @@ int32 CCarCtrl::ChooseCarRating(CZoneInfo* pZoneInfo) { int rnd = CGeneral::GetRandomNumberInRange(0, 1000); - for (int i = FIRST_CAR_RATING; i < FIRST_CAR_RATING + NUM_CAR_CLASSES - 1; i++) { + for (int i = 0; i < NUM_CAR_CLASSES - 1; i++) { if (rnd < pZoneInfo->carThreshold[i]) return i; } @@ -649,10 +673,10 @@ CCarCtrl::ChooseModel(CZoneInfo* pZone, CVector* pPos, int* pClass) { continue; } - for (int i = FIRST_GANG_CAR_RATING; i < FIRST_GANG_CAR_RATING + NUM_GANG_CAR_CLASSES; i++) { - if (rnd < pZone->carThreshold[i]) { - *pClass = i; - model = ChooseGangCarModel(i - FIRST_GANG_CAR_RATING); + 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; } } @@ -668,16 +692,49 @@ CCarCtrl::ChooseCarModel(int32 vehclass) { int32 model = -1; ++NumRequestsOfCarRating[vehclass]; - if (TotalNumOfCarsOfRating[vehclass] == 0) + if (NumOfLoadedCarsOfRating[vehclass] == 0) return -1; - 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... */ - return model; + 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; + } + 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; + } + --NumOfLoadedCarsOfRating[rating]; +} + +int32 +CCarCtrl::ChooseCarModelToLoad(int rating) +{ + return CarArrays[rating][CGeneral::GetRandomNumberInRange(0, TotalNumOfCarsOfRating[rating])]; } int32 @@ -1920,9 +1977,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; } } @@ -1946,7 +2005,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) diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 9f5deebe..cd7383b2 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -69,7 +69,7 @@ public: static void ScanForPedDanger(CVehicle *veh); static void RemoveFromInterestingVehicleList(CVehicle*); static void GenerateRandomCars(void); - static void GenerateOneRandomCar(void); + static int GenerateOneRandomCar(void); static void GenerateEmergencyServicesCar(void); static int32 ChooseModel(CZoneInfo*, CVector*, int*); static int32 ChoosePoliceCarModel(void); @@ -122,6 +122,9 @@ public: static int32 ChooseBoatModel(int32); static int32 ChooseBoatRating(CZoneInfo* pZoneInfo); 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 float GetPositionAlongCurrentCurve(CVehicle* pVehicle) { @@ -153,10 +156,12 @@ public: static uint32 LastTimeFireTruckCreated; static uint32 LastTimeAmbulanceCreated; static int32 TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES]; - static int32 NextCarOfRating[TOTAL_CUSTOM_CLASSES]; static int32 CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY]; static int32 NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES]; + 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]; }; extern CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP]; \ No newline at end of file diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp index b2c3b84d..83a70f14 100644 --- a/src/core/Streaming.cpp +++ b/src/core/Streaming.cpp @@ -1025,7 +1025,9 @@ found: RemoveModel(ms_vehiclesLoaded[ms_lastVehicleDeleted]); ms_numVehiclesLoaded--; ms_vehiclesLoaded[ms_lastVehicleDeleted] = -1; - // TODO(MIAMI): CCarCtrl::RemoveFromLoadedVehicleArray + CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id); + if (pVehicleInfo->m_vehicleClass != -1) + CCarCtrl::RemoveFromLoadedVehicleArray(id, pVehicleInfo->m_vehicleClass); return true; } @@ -1159,13 +1161,21 @@ found: ms_lastVehicleDeleted = id; // this is more that we wanted actually ms_numVehiclesLoaded++; - }else + } + else{ RemoveModel(id); + CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(modelId); + if (pVehicleInfo->m_vehicleClass != -1) + CCarCtrl::RemoveFromLoadedVehicleArray(modelId, pVehicleInfo->m_vehicleClass); + } } ms_vehiclesLoaded[ms_lastVehicleDeleted++] = modelId; if(ms_lastVehicleDeleted == MAXVEHICLESLOADED) ms_lastVehicleDeleted = 0; + CVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(modelId); + if (pVehicleInfo->m_vehicleClass != -1) + CCarCtrl::AddToLoadedVehicleArray(modelId, pVehicleInfo->m_vehicleClass, pVehicleInfo->m_frequency); return true; } @@ -1283,25 +1293,24 @@ CStreaming::StreamVehiclesAndPeds(void) if(timeBeforeNextLoad >= 0) timeBeforeNextLoad--; else if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){ - for(i = 1; i <= 10; i++){ - model = CCarCtrl::ChooseCarModel(modelQualityClass); -// TODO(MIAMI): check this -if(model < 0) - continue; - modelQualityClass++; - if(modelQualityClass >= CCarCtrl::TOTAL_CUSTOM_CLASSES) - modelQualityClass = 0; - - // check if we want to load this model - if(ms_aInfoForModel[model].m_loadState == STREAMSTATE_NOTLOADED && - ((CVehicleModelInfo*)CModelInfo::GetModelInfo(model))->m_level & (1 << (CGame::currLevel-1))) - break; + CZoneInfo zone; + CTheZones::GetZoneInfoForTimeOfDay(&FindPlayerCoors(), &zone); + int32 maxReq = -1; + int32 mostRequestedRating = 0; + for(i = 0; i < CCarCtrl::TOTAL_CUSTOM_CLASSES; i++){ + if(CCarCtrl::NumRequestsOfCarRating[i] > maxReq && + (i == 0 && zone.carThreshold[0] != 0) || + (i != 0 && zone.carThreshold[i] != zone.carThreshold[i-1])) { + maxReq = CCarCtrl::NumRequestsOfCarRating[i]; + mostRequestedRating = i; + } } - - if(i <= 10){ + model = CCarCtrl::ChooseCarModelToLoad(mostRequestedRating); + if(!HasModelLoaded(model)){ RequestModel(model, STREAMFLAGS_DEPENDENCY); - timeBeforeNextLoad = 500; + timeBeforeNextLoad = 350; } + CCarCtrl::NumRequestsOfCarRating[mostRequestedRating] = 0; } } @@ -2435,7 +2444,14 @@ CStreaming::LoadScene(const CVector &pos) AddModelsToRequestList(pos); CRadar::StreamRadarSections(pos); - // TODO(MIAMI): stream zone vehicles + if (!CGame::IsInInterior()) { + for (int i = 0; i < 5; i++) { + CZoneInfo zone; + CTheZones::GetZoneInfoForTimeOfDay(&pos, &zone); + int32 model = CCarCtrl::ChooseCarModelToLoad(CCarCtrl::ChooseCarRating(&zone)); + CStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY); + } + } LoadAllRequestedModels(false); // TODO(MIAMI): InstanceLoadedModels From 49cf53644a1d328dba35cb6674fb14aa44dcbdf6 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 8 May 2020 11:43:27 +0300 Subject: [PATCH 4/5] reasonable spawns --- src/control/CarCtrl.cpp | 69 ++++++++++++++--------------------------- src/control/CarCtrl.h | 2 +- 2 files changed, 25 insertions(+), 46 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 8be92ede..8b1c5887 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -95,26 +95,16 @@ uint32 aCarsToKeepTime[MAX_CARS_TO_KEEP]; void CCarCtrl::GenerateRandomCars() { - static int vals[20]; - static uint32 old = CTimer::GetTimeInMilliseconds(); - if (CTimer::GetTimeInMilliseconds() - old > 1000) { - char str[512]; - sprintf(str, "%8d: %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n", old, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8], vals[9], vals[10], vals[11], vals[12], vals[13], vals[14], vals[15], vals[16], vals[17], vals[18], vals[19]); - debug("%s", str); - for (int i = 0; i < 20; i++) - vals[i] = 0; - old = CTimer::GetTimeInMilliseconds(); - } if (CCutsceneMgr::IsRunning()) { CountDownToCarsAtStart = 2; return; } if (NumRandomCars < 30){ if (CountDownToCarsAtStart == 0) - vals[GenerateOneRandomCar()]++; + GenerateOneRandomCar(); else if (--CountDownToCarsAtStart == 0) { for (int i = 0; i < 100; i++) - vals[GenerateOneRandomCar()]++; + GenerateOneRandomCar(); CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = 20; } } @@ -123,7 +113,7 @@ CCarCtrl::GenerateRandomCars() GenerateEmergencyServicesCar(); } -int +void CCarCtrl::GenerateOneRandomCar() { static int32 unk = 0; @@ -135,9 +125,9 @@ CCarCtrl::GenerateOneRandomCar() CTheZones::GetZoneInfoForTimeOfDay(&vecTargetPos, &zone); pPlayer->m_nTrafficMultiplier = pPlayer->m_fRoadDensity * zone.carDensity; if (NumRandomCars >= pPlayer->m_nTrafficMultiplier * CarDensityMultiplier * CIniFile::CarNumberMultiplier) - return 1; + return; if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars + NumLawEnforcerCars + NumRandomCars >= MaxNumberOfCarsInUse) - return 2; + return; CWanted* pWanted = pPlayer->m_pPed->m_pWanted; int carClass; int carModel; @@ -155,7 +145,7 @@ CCarCtrl::GenerateOneRandomCar() 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 3; + return; } float frontX, frontY; float preferredDistance, angleLimit; @@ -286,12 +276,12 @@ CCarCtrl::GenerateOneRandomCar() if (!ThePaths.NewGenerateCarCreationCoors(vecTargetPos.x, vecTargetPos.y, frontX, frontY, preferredDistance, angleLimit, invertAngleLimitTest, &spawnPosition, &curNodeId, &nextNodeId, &positionBetweenNodes, carClass == COPS && pWanted->m_nWantedLevel >= 1)) - return 4; + 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 5; + return; if (pCurNode->bWaterPath) { bBoatGenerated = true; if (carClass == COPS) { @@ -299,10 +289,10 @@ CCarCtrl::GenerateOneRandomCar() carClass = COPS_BOAT; if (!CStreaming::HasModelLoaded(MI_PREDATOR)) { CStreaming::RequestModel(MI_PREDATOR, STREAMFLAGS_DEPENDENCY); - return 6; + return; } else { - return 7; + return; // TODO: normal boats } } @@ -311,10 +301,10 @@ CCarCtrl::GenerateOneRandomCar() 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 8; + return; if (!bBoatGenerated && !ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition)) /* Testing if spawn position can reach target position via valid path. */ - return 9; + return; int16 idInNode = 0; while (idInNode < pCurNode->numLinks && @@ -326,7 +316,7 @@ CCarCtrl::GenerateOneRandomCar() CVehicleModelInfo* pModelInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(carModel); if (lanesOnCurrentRoad == 0) /* Not spawning vehicle if road is one way and intended direction is opposide to that way. */ - return 10; + return; CVehicle* pVehicle; if (CModelInfo::IsBoatModel(carModel)) pVehicle = new CBoat(carModel, RANDOM_VEHICLE); @@ -421,7 +411,7 @@ CCarCtrl::GenerateOneRandomCar() if (pCurNode->numLinks == 1){ /* Do not create vehicle if there is nowhere to go. */ delete pVehicle; - return 11; + return; } int16 nextConnection = pVehicle->AutoPilot.m_nNextPathNodeInfo; int16 newLink; @@ -480,7 +470,7 @@ 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. */ pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - - (uint32)(positionBetweenNodes * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); + (uint32)((0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve); #else pVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - (0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve; @@ -501,15 +491,6 @@ CCarCtrl::GenerateOneRandomCar() ); CVector vectorBetweenNodes = pCurNode->GetPosition() - pNextNode->GetPosition(); CVector finalPosition = positionIncludingCurve + vectorBetweenNodes * 2.0f / vectorBetweenNodes.Magnitude(); - debug("initialPositionDist: %f\n", (spawnPosition - vecTargetPos).Magnitude()); - debug("pCurNode: %f\n", (CVector2D(pCurNode->GetX(), pCurNode->GetY()) - vecTargetPos).Magnitude()); - debug("pNextNode: %f\n", (CVector2D(pNextNode->GetX(), pNextNode->GetY()) - vecTargetPos).Magnitude()); - debug("pCurrentLink: %f\n", (CVector2D(pCurrentLink->GetX(), pCurrentLink->GetY()) - vecTargetPos).Magnitude()); - debug("pNextLink: %f\n", (CVector2D(pNextLink->GetX(), pNextLink->GetY()) - vecTargetPos).Magnitude()); - debug("positionOnCurrentLinkIncludingLane: %f\n", (positionOnCurrentLinkIncludingLane - vecTargetPos).Magnitude()); - debug("positionOnNextLinkIncludingLane: %f\n", (positionOnNextLinkIncludingLane - vecTargetPos).Magnitude()); - debug("positionIncludingCurve: %f\n", (finalPosition - vecTargetPos).Magnitude()); - debug("finalPositionDist: %f\n", (finalPosition - vecTargetPos).Magnitude()); finalPosition.z = positionBetweenNodes * pNextNode->GetZ() + (1.0f - positionBetweenNodes) * pCurNode->GetZ(); float groundZ = INFINITE_Z; @@ -518,7 +499,7 @@ CCarCtrl::GenerateOneRandomCar() if (bBoatGenerated) { if (!CWaterLevel::GetWaterLevel(finalPosition, &groundZ, true)) { delete pVehicle; - return 12; + return; } } else { @@ -532,7 +513,7 @@ CCarCtrl::GenerateOneRandomCar() if (groundZ == INFINITE_Z || ABS(groundZ - finalPosition.z) > 7.0f) { /* Failed to find ground or too far from expected position. */ delete pVehicle; - return 13; + return; } if (CModelInfo::IsBoatModel(carModel)) { finalPosition.z = groundZ; @@ -583,17 +564,15 @@ CCarCtrl::GenerateOneRandomCar() 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 pVehicle; - return 14; + 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){ - debug("not spawning because %f\n", (vecTargetPos - pVehicle->GetPosition()).Magnitude2D()); delete pVehicle; - return 15; + return; }else if((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera ){ - debug("despite %f got %f\n", (vecTargetPos - pVehicle->GetPosition()).Magnitude2D(), (TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D()); delete pVehicle; - return 16; + return; } // TODO(MIAMI): if MARQUIS then delete CVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo(); @@ -602,18 +581,18 @@ CCarCtrl::GenerateOneRandomCar() CWorld::FindObjectsKindaColliding(pVehicle->GetPosition(), radiusToTest + 20.0f, true, &colliding, 2, nil, false, true, false, false, false); if (colliding){ delete pVehicle; - return 17; + return; } } CWorld::FindObjectsKindaColliding(pVehicle->GetPosition(), radiusToTest, true, &colliding, 2, nil, false, true, false, false, false); if (colliding){ delete pVehicle; - return 18; + return; } if (speedDifferenceWithTarget.x * distanceToTarget.x + speedDifferenceWithTarget.y * distanceToTarget.y >= 0.0f){ delete pVehicle; - return 19; + return; } pVehicleModel->AvoidSameVehicleColour(&pVehicle->m_currentColour1, &pVehicle->m_currentColour2); CWorld::Add(pVehicle); @@ -629,7 +608,7 @@ CCarCtrl::GenerateOneRandomCar() if (carClass == COPS) LastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds(); /* TODO(MIAMI): CADDY, VICECHEE, dead ped code*/ - return 0; + return; } int32 diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index cd7383b2..ce25c206 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -69,7 +69,7 @@ public: static void ScanForPedDanger(CVehicle *veh); static void RemoveFromInterestingVehicleList(CVehicle*); static void GenerateRandomCars(void); - static int GenerateOneRandomCar(void); + static void GenerateOneRandomCar(void); static void GenerateEmergencyServicesCar(void); static int32 ChooseModel(CZoneInfo*, CVector*, int*); static int32 ChoosePoliceCarModel(void); From db267003522c76cc16520afa5a178d370e6be030 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Fri, 8 May 2020 11:49:40 +0300 Subject: [PATCH 5/5] final fix --- src/control/CarCtrl.cpp | 75 ++++++++--------------------------------- 1 file changed, 14 insertions(+), 61 deletions(-) diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 8b1c5887..ffa419c1 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -328,44 +328,6 @@ CCarCtrl::GenerateOneRandomCar() pVehicle->AutoPilot.m_nCurrentRouteNode = curNodeId; pVehicle->AutoPilot.m_nNextRouteNode = nextNodeId; switch (carClass) { - case POOR: - case RICH: - case EXEC: - case WORKER: - case BIG: - case TAXI: - // TODO(MIAMI): check this - case MOPED: - case MOTORBIKE: - case LEISUREBOAT: - case WORKERBOAT: - // - case MAFIA: - case TRIAD: - case DIABLO: - case YAKUZA: - case YARDIE: - case COLOMB: - case NINES: - case GANG8: - case GANG9: - { - 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); - CVehicleModelInfo* pVehicleInfo = pVehicle->GetModelInfo(); - if (pVehicleInfo->GetColModel()->boundingBox.max.y - pVehicle->GetModelInfo()->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; - } case COPS: pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE; if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->m_nWantedLevel != 0){ @@ -392,6 +354,19 @@ CCarCtrl::GenerateOneRandomCar() 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 (pVehicle && pVehicle->GetModelIndex() == MI_MRWHOOP) @@ -526,29 +501,6 @@ CCarCtrl::GenerateOneRandomCar() CVector2D speedDifferenceWithTarget = (CVector2D)pVehicle->GetMoveSpeed() - vecPlayerSpeed; CVector2D distanceToTarget = positionIncludingCurve - vecTargetPos; switch (carClass) { - case POOR: - case RICH: - case EXEC: - case WORKER: - // TODO(MIAMI): check this - case MOPED: - case MOTORBIKE: - case LEISUREBOAT: - case WORKERBOAT: - // - case BIG: - case TAXI: - case MAFIA: - case TRIAD: - case DIABLO: - case YAKUZA: - case YARDIE: - case COLOMB: - case NINES: - case GANG8: - case GANG9: - pVehicle->SetStatus(STATUS_SIMPLE); - break; case COPS: pVehicle->SetStatus((pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) ? STATUS_SIMPLE : STATUS_PHYSICS); pVehicle->ChangeLawEnforcerState(1); @@ -557,6 +509,7 @@ CCarCtrl::GenerateOneRandomCar() pVehicle->ChangeLawEnforcerState(1); pVehicle->SetStatus(STATUS_PHYSICS); default: + pVehicle->SetStatus(STATUS_SIMPLE); break; } CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);