diff options
Diffstat (limited to '')
-rw-r--r-- | src/control/AutoPilot.cpp | 16 | ||||
-rw-r--r-- | src/control/Bridge.cpp | 19 | ||||
-rw-r--r-- | src/control/CarCtrl.cpp | 213 | ||||
-rw-r--r-- | src/control/PathFind.cpp | 900 | ||||
-rw-r--r-- | src/control/PathFind.h | 194 | ||||
-rw-r--r-- | src/control/Restart.cpp | 4 | ||||
-rw-r--r-- | src/control/RoadBlocks.cpp | 59 | ||||
-rw-r--r-- | src/control/RoadBlocks.h | 4 | ||||
-rw-r--r-- | src/control/Script.cpp | 10 | ||||
-rw-r--r-- | src/control/TrafficLights.cpp | 32 |
10 files changed, 1117 insertions, 334 deletions
diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp index 96a1fedf..b1fce95f 100644 --- a/src/control/AutoPilot.cpp +++ b/src/control/AutoPilot.cpp @@ -12,17 +12,17 @@ void CAutoPilot::ModifySpeed(float speed) float positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[m_nNextPathNodeInfo]; - float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.x; - float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.y; - float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.x; - float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.y; + float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].GetDirX(); + float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].GetDirY(); + float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].GetDirX(); + float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].GetDirY(); CVector positionOnCurrentLinkIncludingLane( - pCurrentLink->pos.x + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY, - pCurrentLink->pos.y - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX, + pCurrentLink->GetX() + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY, + pCurrentLink->GetY() - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->GetX() + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, diff --git a/src/control/Bridge.cpp b/src/control/Bridge.cpp index 98c74bbe..1e63cf30 100644 --- a/src/control/Bridge.cpp +++ b/src/control/Bridge.cpp @@ -23,6 +23,7 @@ uint32 CBridge::TimeOfBridgeBecomingOperational; void CBridge::Init() { +#ifdef GTA_BRIDGE FindBridgeEntities(); OldLift = -1.0f; if (pLiftPart && pWeight) @@ -35,10 +36,12 @@ void CBridge::Init() ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true); } +#endif } void CBridge::Update() { +#ifdef GTA_BRIDGE if (!pLiftPart || !pWeight) return; @@ -113,12 +116,21 @@ void CBridge::Update() ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true); else if (State == STATE_LIFT_PART_IS_DOWN && OldState == STATE_LIFT_PART_MOVING_DOWN) ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, false); +#endif } -bool CBridge::ShouldLightsBeFlashing() { return State != STATE_LIFT_PART_IS_DOWN; } +bool CBridge::ShouldLightsBeFlashing() +{ +#ifdef GTA_BRIDGE + return State != STATE_LIFT_PART_IS_DOWN; +#else + return false; +#endif +} void CBridge::FindBridgeEntities() { +#ifdef GTA_BRIDGE pWeight = nil; pLiftRoad = nil; pLiftPart = nil; @@ -135,12 +147,17 @@ void CBridge::FindBridgeEntities() pWeight = entry; } } +#endif } bool CBridge::ThisIsABridgeObjectMovingUp(int index) { +#ifdef GTA_BRIDGE if (index != MI_BRIDGEROADSEGMENT && index != MI_BRIDGELIFT) return false; return State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP || State == STATE_LIFT_PART_MOVING_UP; +#else + return false; +#endif } diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 2d946145..c3fb5409 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -281,7 +281,7 @@ CCarCtrl::GenerateOneRandomCar() CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId]; CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId]; while (idInNode < pCurNode->numLinks && - ThePaths.m_connections[idInNode + pCurNode->firstLink] != nextNodeId) + ThePaths.ConnectedNode(idInNode + pCurNode->firstLink) != nextNodeId) idInNode++; int16 connectionId = ThePaths.m_carPathConnections[idInNode + pCurNode->firstLink]; CCarPathLink* pPathLink = &ThePaths.m_carPathLinks[connectionId]; @@ -356,7 +356,7 @@ CCarCtrl::GenerateOneRandomCar() pCar->AutoPilot.m_nNextLane = pCar->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad; CColBox* boundingBox = &CModelInfo::GetModelInfo(pCar->GetModelIndex())->GetColModel()->boundingBox; float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2; - float distanceBetweenNodes = (pCurNode->pos - pNextNode->pos).Magnitude2D(); + 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. */ /* Otherwise put it at least in a way that full vehicle length fits between two nodes. */ if (distanceBetweenNodes / 2 < carLength) @@ -376,8 +376,8 @@ CCarCtrl::GenerateOneRandomCar() nextConnection = ThePaths.m_carPathConnections[newLink + pCurNode->firstLink]; } pCar->AutoPilot.m_nCurrentPathNodeInfo = nextConnection; - pCar->AutoPilot.m_nCurrentDirection = (ThePaths.m_connections[newLink + pCurNode->firstLink] >= curNodeId) ? 1 : -1; - CVector2D vecBetweenNodes = pNextNode->pos - pCurNode->pos; + pCar->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(newLink + pCurNode->firstLink) >= curNodeId) ? 1 : -1; + CVector2D vecBetweenNodes = pNextNode->GetPosition() - pCurNode->GetPosition(); float forwardX, forwardY; float distBetweenNodes = vecBetweenNodes.Magnitude(); if (distanceBetweenNodes == 0.0f){ @@ -393,25 +393,25 @@ CCarCtrl::GenerateOneRandomCar() pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f); pCar->GetUp() = CVector(0.0f, 0.0f, 1.0f); - float currentPathLinkForwardX = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dir.x; - float currentPathLinkForwardY = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dir.y; - float nextPathLinkForwardX = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.x; - float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.y; + 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(); CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo]; CVector positionOnCurrentLinkIncludingLane( - pCurrentLink->pos.x + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurrentLink->pos.y - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurrentLink->GetX() + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurrentLink->GetY() - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->GetX() + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, + pNextLink->GetY() - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); - float directionCurrentLinkX = pCurrentLink->dir.x * pCar->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurrentLink->dir.y * pCar->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dir.x * pCar->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dir.y * pCar->AutoPilot.m_nNextDirection; + 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; /* 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( &positionOnCurrentLinkIncludingLane, @@ -442,10 +442,10 @@ CCarCtrl::GenerateOneRandomCar() &positionIncludingCurve, &directionIncludingCurve ); - CVector vectorBetweenNodes = pCurNode->pos - pNextNode->pos; + CVector vectorBetweenNodes = pCurNode->GetPosition() - pNextNode->GetPosition(); CVector finalPosition = positionIncludingCurve + vectorBetweenNodes * 2.0f / vectorBetweenNodes.Magnitude(); - finalPosition.z = positionBetweenNodes * pNextNode->pos.z + - (1.0f - positionBetweenNodes) * pCurNode->pos.z; + finalPosition.z = positionBetweenNodes * pNextNode->GetZ() + + (1.0f - positionBetweenNodes) * pCurNode->GetZ(); float groundZ = INFINITE_Z; CColPoint colPoint; CEntity* pEntity; @@ -763,17 +763,17 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle) return; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; - float currentPathLinkForwardX = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; - float currentPathLinkForwardY = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; - float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + float currentPathLinkForwardX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + float currentPathLinkForwardY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; + float nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + float nextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; CVector positionOnCurrentLinkIncludingLane( - pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurrentLink->pos.y - ((pVehicle->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->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((pVehicle->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); CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f); CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f); @@ -1490,7 +1490,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) } } nextLink = CGeneral::GetRandomNumber() % totalLinks; - pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.m_connections[nextLink + pCurPathNode->firstLink]; + pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.ConnectedNode(nextLink + pCurPathNode->firstLink); direction = FindPathDirection(prevNode, curNode, pVehicle->AutoPilot.m_nNextRouteNode); pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]]; goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0; @@ -1508,7 +1508,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) } } nextLink = CGeneral::GetRandomNumber() % totalLinks; - pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.m_connections[nextLink + pCurPathNode->firstLink]; + pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.ConnectedNode(nextLink + pCurPathNode->firstLink); pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]]; goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0; } @@ -1516,7 +1516,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) if (attempt >= ATTEMPTS_TO_FIND_NEXT_NODE) { /* If we failed again, remove no U-turn limitation and remove randomness */ for (nextLink = 0; nextLink < totalLinks; nextLink++) { - pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.m_connections[nextLink + pCurPathNode->firstLink]; + pVehicle->AutoPilot.m_nNextRouteNode = ThePaths.ConnectedNode(nextLink + pCurPathNode->firstLink); pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]]; goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0; if (!goingAgainstOneWayRoad) { @@ -1553,12 +1553,12 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) pVehicle->AutoPilot.m_nNextDirection = -1; lanesOnNextNode = pNextLink->numRightLanes; } - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX(); + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX(); if (lanesOnNextNode >= 0){ if ((CGeneral::GetRandomNumber() & 0x600) == 0){ /* 25% chance vehicle will try to switch lane */ - CVector2D dist = pNextPathNode->pos - pCurPathNode->pos; + CVector2D dist = pNextPathNode->GetPosition() - pCurPathNode->GetPosition(); if (dist.MagnitudeSqr() >= SQR(14.0f)){ if (CGeneral::GetRandomTrueFalse()) pVehicle->AutoPilot.m_nNextLane += 1; @@ -1574,17 +1574,17 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; CVector positionOnCurrentLinkIncludingLane( - pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */ - pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */ + pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH), - pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, + pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH), + pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, 0.0f); - float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurLink->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. */ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -1600,8 +1600,8 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle) uint8 CCarCtrl::FindPathDirection(int32 prevNode, int32 curNode, int32 nextNode) { - CVector2D prevToCur = ThePaths.m_pathNodes[curNode].pos - ThePaths.m_pathNodes[prevNode].pos; - CVector2D curToNext = ThePaths.m_pathNodes[nextNode].pos - ThePaths.m_pathNodes[curNode].pos; + CVector2D prevToCur = ThePaths.m_pathNodes[curNode].GetPosition() - ThePaths.m_pathNodes[prevNode].GetPosition(); + CVector2D curToNext = ThePaths.m_pathNodes[nextNode].GetPosition() - ThePaths.m_pathNodes[curNode].GetPosition(); float distPrevToCur = prevToCur.Magnitude(); if (distPrevToCur == 0.0f) return PATH_DIRECTION_NONE; @@ -1638,7 +1638,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t CPathNode* pTargetNode; int16 numNodes; float distanceToTargetNode; -#ifndef REMOVE_TREADABLE_PATHFIND +#ifndef MIAMI if (pTarget && pTarget->m_pCurGroundEntity && pTarget->m_pCurGroundEntity->IsBuilding() && ((CBuilding*)pTarget->m_pCurGroundEntity)->GetIsATreadable() && @@ -1650,31 +1650,32 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t int node = pCurrentMapObject->m_nodeIndices[0][i]; if (node < 0) break; - float dist = (ThePaths.m_pathNodes[node].pos - pTarget->GetPosition()).Magnitude(); + float dist = (ThePaths.m_pathNodes[node].GetPosition() - pTarget->GetPosition()).Magnitude(); if (dist < minDist){ minDist = dist; closestNode = node; } } - ThePaths.DoPathSearch(0, pCurNode->pos, curNode, + ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode, #ifdef FIX_PATHFIND_BUG CVector(targetX, targetY, targetZ), #else CVector(targetX, targetY, 0.0f), #endif &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, closestNode); - }else{ + }else #endif - ThePaths.DoPathSearch(0, pCurNode->pos, curNode, + { + + ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode, #ifdef FIX_PATHFIND_BUG CVector(targetX, targetY, targetZ), #else CVector(targetX, targetY, 0.0f), #endif &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1); -#ifndef REMOVE_TREADABLE_PATHFIND } -#endif + int newNextNode; int nextLink; if (numNodes != 1 || pTargetNode == pCurNode){ @@ -1684,11 +1685,11 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t int numLinks = pCurNode->numLinks; newNextNode = 0; for (int i = 0; i < numLinks; i++){ - int conNode = ThePaths.m_connections[i + pCurNode->firstLink]; + int conNode = ThePaths.ConnectedNode(i + pCurNode->firstLink); if (conNode == prevNode && i > 1) continue; CPathNode* pTestNode = &ThePaths.m_pathNodes[conNode]; - float angle = CGeneral::GetATanOfXY(pTestNode->pos.x - pCurNode->pos.x, pTestNode->pos.y - pCurNode->pos.y); + float angle = CGeneral::GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY()); angle = LimitRadianAngle(angle - currentAngle); angle = ABS(angle); if (angle < lowestAngleChange){ @@ -1700,7 +1701,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t }else{ nextLink = 0; newNextNode = pTargetNode - ThePaths.m_pathNodes; - for (int i = pCurNode->firstLink; ThePaths.m_connections[i] != newNextNode; i++, nextLink++) + for (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != newNextNode; i++, nextLink++) ; } CPathNode* pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode]; @@ -1725,12 +1726,12 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t pVehicle->AutoPilot.m_nNextDirection = -1; lanesOnNextNode = pNextLink->numRightLanes; } - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; - float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y; - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; - float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX(); + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY(); + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX(); + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirY(); if (lanesOnNextNode >= 0) { - CVector2D dist = pNextPathNode->pos - pCurNode->pos; + CVector2D dist = pNextPathNode->GetPosition() - pCurNode->GetPosition(); if (dist.MagnitudeSqr() >= SQR(7.0f)){ /* 25% chance vehicle will try to switch lane */ /* No lane switching if following car from far away */ @@ -1755,17 +1756,17 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; CVector positionOnCurrentLinkIncludingLane( - pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((pVehicle->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 = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurLink->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. */ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -1801,7 +1802,7 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) pVehicle->AutoPilot.m_nCurrentDirection = pVehicle->AutoPilot.m_nNextDirection; pVehicle->AutoPilot.m_nCurrentLane = pVehicle->AutoPilot.m_nNextLane; int nextLink = 0; - for (int i = pCurNode->firstLink; ThePaths.m_connections[i] != pVehicle->AutoPilot.m_nNextRouteNode; i++, nextLink++) + for (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != pVehicle->AutoPilot.m_nNextRouteNode; i++, nextLink++) ; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink]]; pVehicle->AutoPilot.m_nNextPathNodeInfo = ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink]; @@ -1814,12 +1815,12 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) pVehicle->AutoPilot.m_nNextDirection = -1; lanesOnNextNode = pNextLink->numRightLanes; } - float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; - float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y; - float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; - float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y; + float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX(); + float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY(); + float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX(); + float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirY(); if (lanesOnNextNode >= 0) { - CVector2D dist = pNextPathNode->pos - pCurNode->pos; + CVector2D dist = pNextPathNode->GetPosition() - pCurNode->GetPosition(); if (dist.MagnitudeSqr() >= SQR(7.0f) && (CGeneral::GetRandomNumber() & 0x600) == 0) { if (CGeneral::GetRandomTrueFalse()) pVehicle->AutoPilot.m_nNextLane += 1; @@ -1835,17 +1836,17 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle) if (pVehicle->AutoPilot.m_bStayInFastLane) pVehicle->AutoPilot.m_nNextLane = 0; CVector positionOnCurrentLinkIncludingLane( - pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, - pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, + pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, + pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, 0.0f); CVector positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((pVehicle->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 = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; - float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; - float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + float directionCurrentLinkY = pCurLink->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. */ pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( &positionOnCurrentLinkIncludingLane, @@ -2199,16 +2200,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv forward.Normalise(); CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; - CVector2D currentPathLinkForward(pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection, - pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection); - float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + CVector2D currentPathLinkForward(pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection, + pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection); + float nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + float nextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; CVector2D positionOnCurrentLinkIncludingLane( - pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, - pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); + pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, + pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); CVector2D positionOnNextLinkIncludingLane( - pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, - pNextLink->pos.y - ((pVehicle->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); CVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane; float scalarDistanceToNextNode = distanceToNextNode.Magnitude(); CVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane; @@ -2237,16 +2238,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv } pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; scalarDistanceToNextNode = CVector2D( - pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x, - pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude(); + pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x, + pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude(); pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; - currentPathLinkForward.x = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; - currentPathLinkForward.y = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; - nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; - nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; + currentPathLinkForward.x = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection; + currentPathLinkForward.y = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection; + nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection; + nextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection; } - positionOnCurrentLinkIncludingLane.x = pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y; - positionOnCurrentLinkIncludingLane.y = pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x; + positionOnCurrentLinkIncludingLane.x = pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y; + positionOnCurrentLinkIncludingLane.y = pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x; CVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f; if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){ projectedPosition.x = positionOnCurrentLinkIncludingLane.x; @@ -2288,8 +2289,8 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv CCarAI::CarHasReasonToStop(pVehicle); speedStyleMultiplier = 0.0f; } - CVector2D trajectory(pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, - pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); + CVector2D trajectory(pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, + pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); trajectory -= pVehicle->GetPosition(); float speedAngleMultiplier = FindSpeedMultiplier( CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward, @@ -2503,9 +2504,9 @@ void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle) int prevNodeId = -1; float minDistance = 999999.9f; for (int i = 0; i < pNode->numLinks; i++){ - int candidateId = ThePaths.m_connections[i + pNode->firstLink]; + int candidateId = ThePaths.ConnectedNode(i + pNode->firstLink); CPathNode* pCandidateNode = &ThePaths.m_pathNodes[candidateId]; - float distance = (pCandidateNode->pos - pNode->pos).Magnitude2D(); + float distance = (pCandidateNode->GetPosition() - pNode->GetPosition()).Magnitude2D(); if (distance < minDistance){ minDistance = distance; prevNodeId = candidateId; @@ -2517,7 +2518,7 @@ void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle) CPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNodeId]; if (forward.x == 0.0f && forward.y == 0.0f) forward.x = 1.0f; - if (DotProduct2D(pNode->pos - pPrevNode->pos, forward) < 0.0f){ + if (DotProduct2D(pNode->GetPosition() - pPrevNode->GetPosition(), forward) < 0.0f){ int tmp; tmp = prevNodeId; prevNodeId = nodeId; @@ -2557,7 +2558,7 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle) int nextLink; CPathNode* pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode]; for (nextLink = 0; nextLink < 12; nextLink++) - if (ThePaths.m_connections[nextLink + pCurNode->firstLink] == pVehicle->AutoPilot.m_nNextRouteNode) + if (ThePaths.ConnectedNode(nextLink + pCurNode->firstLink) == pVehicle->AutoPilot.m_nNextRouteNode) break; pVehicle->AutoPilot.m_nNextPathNodeInfo = ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink]; pVehicle->AutoPilot.m_nNextDirection = (pVehicle->AutoPilot.m_nCurrentRouteNode >= pVehicle->AutoPilot.m_nNextRouteNode) ? 1 : -1; @@ -2574,7 +2575,7 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle) } } pVehicle->AutoPilot.m_nCurrentPathNodeInfo = curConnection; - pVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.m_connections[curLink + pCurNode->firstLink] >= pVehicle->AutoPilot.m_nCurrentRouteNode) ? 1 : -1; + pVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(curLink + pCurNode->firstLink) >= pVehicle->AutoPilot.m_nCurrentRouteNode) ? 1 : -1; } void CCarCtrl::GenerateEmergencyServicesCar(void) @@ -2656,7 +2657,7 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos) pVehicle->GetForward() = CVector(direction.x, direction.y, 0.0f); pVehicle->GetRight() = CVector(direction.y, -direction.x, 0.0f); pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f); - spawnPos.z = posBetweenNodes * ThePaths.m_pathNodes[curNode].pos.z + (1.0f - posBetweenNodes) * ThePaths.m_pathNodes[nextNode].pos.z; + spawnPos.z = posBetweenNodes * ThePaths.m_pathNodes[curNode].GetZ() + (1.0f - posBetweenNodes) * ThePaths.m_pathNodes[nextNode].GetZ(); float groundZ = INFINITE_Z; CColPoint colPoint; CEntity* pEntity; @@ -2739,7 +2740,11 @@ bool CCarCtrl::ThisRoadObjectCouldMove(int16 mi) bool CCarCtrl::MapCouldMoveInThisArea(float x, float y) { +#ifdef GTA_BRIDGE // actually they forgot that in VC... // bridge moves up and down return x > -342.0f && x < -219.0f && y > -677.0f && y < -580.0f; +#else + return false; +#endif } diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 44062b38..86314d36 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -17,15 +17,38 @@ CPathFind ThePaths; #define MAX_DIST INT16_MAX-1 #define MIN_PED_ROUTE_DISTANCE 23.8f + +#ifdef MIAMI +#define NUMTEMPNODES 5000 +#define NUMDETACHED_CARS 1024 +#define NUMDETACHED_PEDS 1214 +#define NUMTEMPEXTERNALNODES 4600 +#else +#define NUMTEMPNODES 4000 +#define NUMDETACHED_CARS 100 +#define NUMDETACHED_PEDS 50 +#endif + + // object flags: // 1 UseInRoadBlock // 2 east/west road(?) CPathInfoForObject *InfoForTileCars; CPathInfoForObject *InfoForTilePeds; + +#ifndef MIAMI // unused CTempDetachedNode *DetachedNodesCars; CTempDetachedNode *DetachedNodesPeds; +#else +CPathInfoForObject *DetachedInfoForTileCars; +CPathInfoForObject *DetachedInfoForTilePeds; +CTempNodeExternal *TempExternalNodes; +int32 NumTempExternalNodes; +int32 NumDetachedPedNodeGroups; +int32 NumDetachedCarNodeGroups; +#endif bool CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints) @@ -220,6 +243,28 @@ CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *p } } +#ifdef MIAMI +// Make sure all externals link TO an internal +void +CPathInfoForObject::SwapConnectionsToBeRightWayRound(void) +{ + int e, i; + CPathInfoForObject *tile = this; + + for(e = 0; e < 12; e++) + if(tile[e].type == NodeTypeExtern && tile[e].next < 0) + for(i = 0; i < 12; i++) + if(tile[i].type == NodeTypeIntern && tile[i].next == e){ + tile[e].next = i; + tile[i].next = -1; + bool tmp = !!tile[e].crossing; + tile[e].crossing = tile[i].crossing; + tile[i].crossing = tmp; + } +} +#endif + +//--MIAMI: done void CPathFind::Init(void) { @@ -230,11 +275,15 @@ CPathFind::Init(void) m_numConnections = 0; m_numCarPathLinks = 0; unk = 0; +#ifdef MIAMI + NumTempExternalNodes = 0; +#endif for(i = 0; i < NUM_PATHNODES; i++) m_pathNodes[i].distance = MAX_DIST; } +//--MIAMI: done void CPathFind::AllocatePathFindInfoMem(int16 numPathGroups) { @@ -243,28 +292,48 @@ CPathFind::AllocatePathFindInfoMem(int16 numPathGroups) delete[] InfoForTilePeds; InfoForTilePeds = nil; + // NB: MIAMI doesn't use numPathGroups here but hardcodes 4500 InfoForTileCars = new CPathInfoForObject[12*numPathGroups]; memset(InfoForTileCars, 0, 12*numPathGroups*sizeof(CPathInfoForObject)); InfoForTilePeds = new CPathInfoForObject[12*numPathGroups]; memset(InfoForTilePeds, 0, 12*numPathGroups*sizeof(CPathInfoForObject)); +#ifndef MIAMI // unused delete[] DetachedNodesCars; DetachedNodesCars = nil; delete[] DetachedNodesPeds; DetachedNodesPeds = nil; - DetachedNodesCars = new CTempDetachedNode[100]; - memset(DetachedNodesCars, 0, 100*sizeof(CTempDetachedNode)); - DetachedNodesPeds = new CTempDetachedNode[50]; - memset(DetachedNodesPeds, 0, 50*sizeof(CTempDetachedNode)); + DetachedNodesCars = new CTempDetachedNode[NUMDETACHED_CARS]; + memset(DetachedNodesCars, 0, NUMDETACHED_CARS*sizeof(CTempDetachedNode)); + DetachedNodesPeds = new CTempDetachedNode[NUMDETACHED_PEDS]; + memset(DetachedNodesPeds, 0, NUMDETACHED_PEDS*sizeof(CTempDetachedNode)); +#else + delete[] DetachedInfoForTileCars; + DetachedInfoForTileCars = nil; + delete[] DetachedInfoForTilePeds; + DetachedInfoForTilePeds = nil; + DetachedInfoForTileCars = new CPathInfoForObject[12*NUMDETACHED_CARS]; + memset(DetachedInfoForTileCars, 0, 12*NUMDETACHED_CARS*sizeof(CPathInfoForObject)); + DetachedInfoForTilePeds = new CPathInfoForObject[12*NUMDETACHED_PEDS]; + memset(DetachedInfoForTilePeds, 0, 12*NUMDETACHED_PEDS*sizeof(CPathInfoForObject)); + + TempExternalNodes = new CTempNodeExternal[NUMTEMPEXTERNALNODES]; + memset(TempExternalNodes, 0, NUMTEMPEXTERNALNODES*sizeof(CTempNodeExternal)); + NumTempExternalNodes = 0; + NumDetachedPedNodeGroups = 0; + NumDetachedCarNodeGroups = 0; +#endif } +//--MIAMI: done void CPathFind::RegisterMapObject(CTreadable *mapObject) { m_mapObjects[m_numMapObjects++] = mapObject; } +//--MIAMI: TODO: implement all the arguments once we can load the VC map void CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing) { @@ -273,13 +342,27 @@ CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, i = id*12 + node; InfoForTilePeds[i].type = type; InfoForTilePeds[i].next = next; +#ifndef MIAMI InfoForTilePeds[i].x = x; InfoForTilePeds[i].y = y; InfoForTilePeds[i].z = z; +#else + InfoForTilePeds[i].x = x/16.0f; + InfoForTilePeds[i].y = y/16.0f; + InfoForTilePeds[i].z = z/16.0f; +#endif InfoForTilePeds[i].numLeftLanes = 0; InfoForTilePeds[i].numRightLanes = 0; InfoForTilePeds[i].crossing = crossing; +#ifdef MIAMI + InfoForTilePeds[i].flag02 = false; + InfoForTilePeds[i].roadBlock = false; + InfoForTilePeds[i].disabled = false; + InfoForTilePeds[i].waterPath = false; + InfoForTilePeds[i].betweenLevels = false; +#endif +#ifndef MIAMI if(type) for(i = 0; i < node; i++){ j = id*12 + i; @@ -290,8 +373,13 @@ CPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, printf("Modelindex of cullprit: %d\n\n", id); } } +#else + if(node == 11) + InfoForTilePeds[id*12].SwapConnectionsToBeRightWayRound(); +#endif } +//--MIAMI: TODO: implement all the arguments once we can load the VC map void CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight) { @@ -300,12 +388,28 @@ CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, i = id*12 + node; InfoForTileCars[i].type = type; InfoForTileCars[i].next = next; +#ifndef MIAMI InfoForTileCars[i].x = x; InfoForTileCars[i].y = y; InfoForTileCars[i].z = z; +#else + InfoForTileCars[i].x = x/16.0f; + InfoForTileCars[i].y = y/16.0f; + InfoForTileCars[i].z = z/16.0f; +#endif InfoForTileCars[i].numLeftLanes = numLeft; InfoForTileCars[i].numRightLanes = numRight; +#ifdef MIAMI + InfoForTileCars[i].crossing = false; + InfoForTileCars[i].flag02 = false; + InfoForTileCars[i].roadBlock = false; + InfoForTileCars[i].disabled = false; + InfoForTileCars[i].waterPath = false; + InfoForTileCars[i].betweenLevels = false; +#endif + +#ifndef MIAMI if(type) for(i = 0; i < node; i++){ j = id*12 + i; @@ -316,8 +420,13 @@ CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, printf("Modelindex of cullprit: %d\n\n", id); } } +#else + if(node == 11) + InfoForTileCars[id*12].SwapConnectionsToBeRightWayRound(); +#endif } +#ifndef MIAMI void CPathFind::CalcNodeCoors(int16 x, int16 y, int16 z, int id, CVector *out) { @@ -327,7 +436,19 @@ CPathFind::CalcNodeCoors(int16 x, int16 y, int16 z, int id, CVector *out) pos.z = z / 16.0f; *out = m_mapObjects[id]->GetMatrix() * pos; } +#else +void +CPathFind::CalcNodeCoors(float x, float y, float z, int id, CVector *out) +{ + CVector pos; + pos.x = x; + pos.y = y; + pos.z = z; + *out = m_mapObjects[id]->GetMatrix() * pos; +} +#endif +//--MIAMI: done bool CPathFind::LoadPathFindData(void) { @@ -335,6 +456,7 @@ CPathFind::LoadPathFindData(void) return false; } +//--MIAMI: done void CPathFind::PreparePathData(void) { @@ -346,12 +468,20 @@ CPathFind::PreparePathData(void) printf("PreparePathData\n"); if(!CPathFind::LoadPathFindData() && // empty InfoForTileCars && InfoForTilePeds && - DetachedNodesCars && DetachedNodesPeds){ - tempNodes = new CTempNode[4000]; +#ifndef MIAMI + DetachedNodesCars && DetachedNodesPeds +#else + DetachedInfoForTileCars && DetachedInfoForTilePeds && TempExternalNodes +#endif + ){ + tempNodes = new CTempNode[NUMTEMPNODES]; m_numConnections = 0; + +#ifndef MIAMI for(i = 0; i < PATHNODESIZE; i++) m_pathNodes[i].unkBits = 0; +#endif for(i = 0; i < PATHNODESIZE; i++){ numExtern = 0; @@ -366,9 +496,25 @@ CPathFind::PreparePathData(void) printf("ILLEGAL BLOCK. MORE THAN 1 INTERNALS AND NOT 2 EXTERNALS (Modelindex:%d)\n", i); } +#ifdef MIAMI + int numExternDetached, numInternDetached; + for(i = 0; i < NUMDETACHED_CARS; i++){ + numExternDetached = 0; + numInternDetached = 0; + for(j = 0; j < 12; j++){ + if(DetachedInfoForTileCars[i*12 + j].type == NodeTypeExtern) + numExternDetached++; + if(DetachedInfoForTilePeds[i*12 + j].type == NodeTypeIntern) + numInternDetached++; + } + // no diagnostic here + } +#endif + for(i = 0; i < PATHNODESIZE; i++) for(j = 0; j < 12; j++) if(InfoForTileCars[i*12 + j].type == NodeTypeExtern){ + // MIAMI has MI:%d here but no argument for it if(InfoForTileCars[i*12 + j].numLeftLanes < 0) printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i); if(InfoForTileCars[i*12 + j].numRightLanes < 0) @@ -376,13 +522,33 @@ CPathFind::PreparePathData(void) if(InfoForTileCars[i*12 + j].numLeftLanes + InfoForTileCars[i*12 + j].numRightLanes <= 0) printf("ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\n", i); } +#ifdef MIAMI + for(i = 0; i < NUMDETACHED_CARS; i++) + for(j = 0; j < 12; j++) + if(DetachedInfoForTilePeds[i*12 + j].type == NodeTypeExtern){ + // MI:%d here but no argument for it + if(DetachedInfoForTilePeds[i*12 + j].numLeftLanes < 0) + printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i); + if(DetachedInfoForTilePeds[i*12 + j].numRightLanes < 0) + printf("ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\n", i); + if(DetachedInfoForTilePeds[i*12 + j].numLeftLanes + DetachedInfoForTilePeds[i*12 + j].numRightLanes <= 0) + printf("ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\n", i); + } +#endif m_numPathNodes = 0; - PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedNodesCars, 100); +#ifndef MIAMI + PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedNodesCars, NUMDETACHED_CARS); + m_numCarPathNodes = m_numPathNodes; + PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedNodesPeds, NUMDETACHED_PEDS); +#else + PreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedInfoForTileCars, NumDetachedCarNodeGroups); m_numCarPathNodes = m_numPathNodes; - PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedNodesPeds, 50); + PreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedInfoForTilePeds, NumDetachedPedNodeGroups); +#endif m_numPedPathNodes = m_numPathNodes - m_numCarPathNodes; +#ifndef MIAMI // TODO: figure out what exactly is going on here // Some roads seem to get a west/east flag for(i = 0; i < m_numMapObjects; i++){ @@ -421,6 +587,7 @@ CPathFind::PreparePathData(void) } } } +#endif delete[] tempNodes; @@ -431,14 +598,25 @@ CPathFind::PreparePathData(void) InfoForTileCars = nil; delete[] InfoForTilePeds; InfoForTilePeds = nil; + +#ifndef MIAMI delete[] DetachedNodesCars; DetachedNodesCars = nil; delete[] DetachedNodesPeds; DetachedNodesPeds = nil; +#else + delete[] DetachedInfoForTileCars; + DetachedInfoForTileCars = nil; + delete[] DetachedInfoForTilePeds; + DetachedInfoForTilePeds = nil; + delete[] TempExternalNodes; + TempExternalNodes = nil; +#endif } printf("Done with PreparePathData\n"); } +//--MIAMI: done /* String together connected nodes in a list by a flood fill algorithm */ void CPathFind::CountFloodFillGroups(uint8 type) @@ -476,29 +654,34 @@ CPathFind::CountFloodFillGroups(uint8 type) break; node = &m_pathNodes[i]; - node->next = nil; + node->SetNext(nil); node->group = n; if(node->numLinks == 0){ if(type == PATH_CAR) +#ifndef MIAMI printf("Single car node: %f %f %f (%d)\n", - node->pos.x, node->pos.y, node->pos.z, + node->GetX(), node->GetY(), node->GetZ(), m_mapObjects[node->objectIndex]->m_modelIndex); +#else + printf("Single car node: %f %f %f\n", + node->GetX(), node->GetY(), node->GetZ()); +#endif else printf("Single ped node: %f %f %f\n", - node->pos.x, node->pos.y, node->pos.z); + node->GetX(), node->GetY(), node->GetZ()); } while(node){ prev = node; - node = node->next; + node = node->GetNext(); for(i = 0; i < prev->numLinks; i++){ - l = m_connections[prev->firstLink + i]; + l = ConnectedNode(prev->firstLink + i); if(m_pathNodes[l].group == 0){ m_pathNodes[l].group = n; if(m_pathNodes[l].group == 0) m_pathNodes[l].group = INT8_MIN; - m_pathNodes[l].next = node; + m_pathNodes[l].SetNext(node); node = &m_pathNodes[l]; } } @@ -511,9 +694,14 @@ CPathFind::CountFloodFillGroups(uint8 type) int32 TempListLength; +//--MIAMI: done void CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo, - float maxdist, CTempDetachedNode *detachednodes, int unused) +#ifndef MIAMI + float maxdist, CTempDetachedNode *detachednodes, int numDetached) +#else + float maxdist, CPathInfoForObject *detachednodes, int numDetached) +#endif { static CVector CoorsXFormed; int i, j, k, l; @@ -525,43 +713,120 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor int nearestId; int next; int oldNumPathNodes, oldNumLinks; - CVector dist; + float dist; int iseg, jseg; int istart, jstart; int done, cont; + int tileStart; oldNumPathNodes = m_numPathNodes; oldNumLinks = m_numConnections; +#ifndef MIAMI +#define OBJECTINDEX(n) (m_pathNodes[(n)].objectIndex) // Initialize map objects for(i = 0; i < m_numMapObjects; i++) for(j = 0; j < 12; j++) m_mapObjects[i]->m_nodeIndices[type][j] = -1; +#else +#define OBJECTINDEX(n) (mapObjIndices[(n)]) + int16 *mapObjIndices = new int16[NUM_PATHNODES]; + NumTempExternalNodes = 0; +#endif // Calculate internal nodes, store them and connect them to defining object for(i = 0; i < m_numMapObjects; i++){ + tileStart = m_numPathNodes; start = 12*m_mapObjects[i]->m_modelIndex; for(j = 0; j < 12; j++){ - if(objectpathinfo[start + j].type != NodeTypeIntern) - continue; - CalcNodeCoors( - objectpathinfo[start + j].x, - objectpathinfo[start + j].y, - objectpathinfo[start + j].z, - i, - &CoorsXFormed); - m_pathNodes[m_numPathNodes].pos = CoorsXFormed; - m_pathNodes[m_numPathNodes].objectIndex = i; - m_pathNodes[m_numPathNodes].unkBits = 1; - m_mapObjects[i]->m_nodeIndices[type][j] = m_numPathNodes++; + if(objectpathinfo[start + j].type == NodeTypeIntern){ + CalcNodeCoors( + objectpathinfo[start + j].x, + objectpathinfo[start + j].y, + objectpathinfo[start + j].z, + i, + &CoorsXFormed); + m_pathNodes[m_numPathNodes].SetPosition(CoorsXFormed); + OBJECTINDEX(m_numPathNodes) = i; +#ifndef MIAMI + m_pathNodes[m_numPathNodes].unkBits = 1; + m_mapObjects[i]->m_nodeIndices[type][j] = m_numPathNodes; +#else + m_pathNodes[m_numPathNodes].width = objectpathinfo[start + j].width; + m_pathNodes[m_numPathNodes].speedLimit = objectpathinfo[start + j].speedLimit; + m_pathNodes[m_numPathNodes].spawnRate = objectpathinfo[start + j].spawnRate; + m_pathNodes[m_numPathNodes].bUseInRoadBlock = objectpathinfo[start + j].roadBlock; + m_pathNodes[m_numPathNodes].bDisabled = objectpathinfo[start + j].disabled; + m_pathNodes[m_numPathNodes].bWaterPath = objectpathinfo[start + j].waterPath; + m_pathNodes[m_numPathNodes].flagB2 = objectpathinfo[start + j].flag02; + m_pathNodes[m_numPathNodes].bBetweenLevels = objectpathinfo[start + j].betweenLevels; +#endif + m_numPathNodes++; + } +#ifdef MIAMI + else if(objectpathinfo[start + j].type == NodeTypeExtern){ + CalcNodeCoors( + objectpathinfo[start + j].x, + objectpathinfo[start + j].y, + objectpathinfo[start + j].z, + i, + &CoorsXFormed); + TempExternalNodes[NumTempExternalNodes].pos = CoorsXFormed; + assert(objectpathinfo[start + j].next >= 0); + TempExternalNodes[NumTempExternalNodes].next = tileStart + objectpathinfo[start + j].next; + TempExternalNodes[NumTempExternalNodes].numLeftLanes = objectpathinfo[start + j].numLeftLanes; + TempExternalNodes[NumTempExternalNodes].numRightLanes = objectpathinfo[start + j].numRightLanes; + TempExternalNodes[NumTempExternalNodes].width = objectpathinfo[start + j].width; + TempExternalNodes[NumTempExternalNodes].isCross = !!objectpathinfo[start + j].crossing; + NumTempExternalNodes++; + } +#endif } } +#ifdef MIAMI + // Same thing for detached nodes + for(i = 0; i < numDetached; i++){ + tileStart = m_numPathNodes; + start = 12*i; + for(j = 0; j < 12; j++){ + if(detachednodes[start + j].type == NodeTypeIntern){ + CVector pos; + pos.x = detachednodes[start + j].x; + pos.y = detachednodes[start + j].y; + pos.z = detachednodes[start + j].z; + m_pathNodes[m_numPathNodes].SetPosition(pos); + mapObjIndices[m_numPathNodes] = -(i+1); + m_pathNodes[m_numPathNodes].width = detachednodes[start + j].width; + m_pathNodes[m_numPathNodes].speedLimit = detachednodes[start + j].speedLimit; + m_pathNodes[m_numPathNodes].spawnRate = detachednodes[start + j].spawnRate; + m_pathNodes[m_numPathNodes].bUseInRoadBlock = detachednodes[start + j].roadBlock; + m_pathNodes[m_numPathNodes].bDisabled = detachednodes[start + j].disabled; + m_pathNodes[m_numPathNodes].bWaterPath = detachednodes[start + j].waterPath; + m_pathNodes[m_numPathNodes].flagB2 = detachednodes[start + j].flag02; + m_pathNodes[m_numPathNodes].bBetweenLevels = detachednodes[start + j].betweenLevels; + m_numPathNodes++; + }else if(detachednodes[start + j].type == NodeTypeExtern){ + TempExternalNodes[NumTempExternalNodes].pos.x = detachednodes[start + j].x; + TempExternalNodes[NumTempExternalNodes].pos.y = detachednodes[start + j].y; + TempExternalNodes[NumTempExternalNodes].pos.z = detachednodes[start + j].z; + assert(detachednodes[start + j].next >= 0); + TempExternalNodes[NumTempExternalNodes].next = tileStart + detachednodes[start + j].next; + TempExternalNodes[NumTempExternalNodes].numLeftLanes = detachednodes[start + j].numLeftLanes; + TempExternalNodes[NumTempExternalNodes].numRightLanes = detachednodes[start + j].numRightLanes; + TempExternalNodes[NumTempExternalNodes].width = detachednodes[start + j].width; + TempExternalNodes[NumTempExternalNodes].isCross = !!detachednodes[start + j].crossing; + NumTempExternalNodes++; + } + } + } +#endif + // Insert external nodes into TempList TempListLength = 0; +#ifndef MIAMI for(i = 0; i < m_numMapObjects; i++){ start = 12*m_mapObjects[i]->m_modelIndex; - for(j = 0; j < 12; j++){ if(objectpathinfo[start + j].type != NodeTypeExtern) continue; @@ -618,8 +883,8 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor tempnodes[nearestId].linkState = 2; // collapse this node with nearest we found - dx = m_pathNodes[tempnodes[nearestId].link1].pos.x - m_pathNodes[tempnodes[nearestId].link2].pos.x; - dy = m_pathNodes[tempnodes[nearestId].link1].pos.y - m_pathNodes[tempnodes[nearestId].link2].pos.y; + dx = m_pathNodes[tempnodes[nearestId].link1].GetX() - m_pathNodes[tempnodes[nearestId].link2].GetX(); + dy = m_pathNodes[tempnodes[nearestId].link1].GetY() - m_pathNodes[tempnodes[nearestId].link2].GetY(); tempnodes[nearestId].pos = (tempnodes[nearestId].pos + CoorsXFormed)*0.5f; mag = Sqrt(dx*dx + dy*dy); tempnodes[nearestId].dirX = dx/mag; @@ -635,6 +900,62 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor } } } +#else + for(i = 0; i < NumTempExternalNodes; i++){ + // find closest unconnected node + nearestId = -1; + nearestDist = maxdist; + for(k = 0; k < TempListLength; k++){ + if(tempnodes[k].linkState != 1) + continue; + dx = tempnodes[k].pos.x - TempExternalNodes[i].pos.x; + if(Abs(dx) < nearestDist){ + dy = tempnodes[k].pos.y - TempExternalNodes[i].pos.y; + if(Abs(dy) < nearestDist){ + nearestDist = Max(Abs(dx), Abs(dy)); + nearestId = k; + } + } + } + + if(nearestId < 0){ + // None found, add this one to temp list + tempnodes[TempListLength].pos = TempExternalNodes[i].pos; + // link to connecting internal node + tempnodes[TempListLength].link1 = TempExternalNodes[i].next; + if(type == PATH_CAR){ + tempnodes[TempListLength].numLeftLanes = TempExternalNodes[i].numLeftLanes; + tempnodes[TempListLength].numRightLanes = TempExternalNodes[i].numRightLanes; + } + tempnodes[TempListLength].width = TempExternalNodes[i].width; + tempnodes[TempListLength].isCross = TempExternalNodes[i].isCross; + tempnodes[TempListLength++].linkState = 1; + }else{ + // Found nearest, connect it to our neighbour + tempnodes[nearestId].link2 = TempExternalNodes[i].next; + tempnodes[nearestId].linkState = 2; + + // collapse this node with nearest we found + dx = m_pathNodes[tempnodes[nearestId].link1].GetX() - m_pathNodes[tempnodes[nearestId].link2].GetX(); + dy = m_pathNodes[tempnodes[nearestId].link1].GetY() - m_pathNodes[tempnodes[nearestId].link2].GetY(); + tempnodes[nearestId].pos = (tempnodes[nearestId].pos + TempExternalNodes[i].pos)*0.5f; + mag = Sqrt(dx*dx + dy*dy); + tempnodes[nearestId].dirX = dx/mag * 100; + tempnodes[nearestId].dirY = dy/mag * 100; + tempnodes[nearestId].width = Max(tempnodes[nearestId].width, TempExternalNodes[i].width); + if(TempExternalNodes[i].isCross) + tempnodes[nearestId].isCross = true; // TODO: is this guaranteed to be false otherwise? + // do something when number of lanes doesn't agree + if(type == PATH_CAR) + if(tempnodes[nearestId].numLeftLanes != 0 && tempnodes[nearestId].numRightLanes != 0 && + (TempExternalNodes[i].numLeftLanes == 0 || TempExternalNodes[i].numRightLanes == 0)){ + // why switch left and right here? + tempnodes[nearestId].numLeftLanes = TempExternalNodes[i].numRightLanes; + tempnodes[nearestId].numRightLanes = TempExternalNodes[i].numLeftLanes; + } + } + } +#endif // Loop through previously added internal nodes and link them for(i = oldNumPathNodes; i < m_numPathNodes; i++){ @@ -648,6 +969,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor continue; // Add link to other side of the external + // NB this clears the flags in MIAMI if(tempnodes[j].link1 == i) m_connections[m_numConnections] = tempnodes[j].link2; else if(tempnodes[j].link2 == i) @@ -655,32 +977,55 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor else continue; - dist = m_pathNodes[i].pos - m_pathNodes[m_connections[m_numConnections]].pos; - m_distances[m_numConnections] = dist.Magnitude(); + dist = (m_pathNodes[i].GetPosition() - m_pathNodes[ConnectedNode(m_numConnections)].GetPosition()).Magnitude(); +#ifndef MIAMI + m_distances[m_numConnections] = dist; m_connectionFlags[m_numConnections].flags = 0; +#else + m_distances[m_numConnections] = Min(dist, 255); + if(tempnodes[j].isCross) + m_connections[j] |= 0x8000; // crosses road flag +#endif if(type == PATH_CAR){ // IMPROVE: use a goto here // Find existing car path link for(k = 0; k < m_numCarPathLinks; k++){ +#ifndef MIAMI if(m_carPathLinks[k].dir.x == tempnodes[j].dirX && m_carPathLinks[k].dir.y == tempnodes[j].dirY && m_carPathLinks[k].pos.x == tempnodes[j].pos.x && m_carPathLinks[k].pos.y == tempnodes[j].pos.y){ +#else + if(m_carPathLinks[k].dirX == tempnodes[j].dirX && + m_carPathLinks[k].dirY == tempnodes[j].dirY && + m_carPathLinks[k].x == (int)(tempnodes[j].pos.x*8.0f) && + m_carPathLinks[k].y == (int)(tempnodes[j].pos.y*8.0f)){ +#endif m_carPathConnections[m_numConnections] = k; k = m_numCarPathLinks; } } // k is m_numCarPathLinks+1 if we found one if(k == m_numCarPathLinks){ +#ifndef MIAMI m_carPathLinks[m_numCarPathLinks].dir.x = tempnodes[j].dirX; m_carPathLinks[m_numCarPathLinks].dir.y = tempnodes[j].dirY; m_carPathLinks[m_numCarPathLinks].pos.x = tempnodes[j].pos.x; m_carPathLinks[m_numCarPathLinks].pos.y = tempnodes[j].pos.y; +#else + m_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX; + m_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY; + m_carPathLinks[m_numCarPathLinks].x = tempnodes[j].pos.x*8.0f; + m_carPathLinks[m_numCarPathLinks].y = tempnodes[j].pos.y*8.0f; + m_carPathLinks[m_numCarPathLinks].flag1 = false; + m_carPathLinks[m_numCarPathLinks].width = tempnodes[j].width; +#endif m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes; m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes; m_carPathLinks[m_numCarPathLinks].trafficLightType = 0; + assert(m_numCarPathLinks <= NUM_CARPATHLINKS); m_carPathConnections[m_numConnections] = m_numCarPathLinks++; } } @@ -689,36 +1034,66 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor m_numConnections++; } +#ifdef MIAMI + CPathInfoForObject *tile; + if(mapObjIndices[i] < 0){ + if(type == PATH_CAR) + tile = &DetachedInfoForTileCars[12 * (-1 - mapObjIndices[i])]; + else + tile = &DetachedInfoForTilePeds[12 * (-1 - mapObjIndices[i])]; + }else{ + if(type == PATH_CAR) + tile = &InfoForTileCars[12 * m_mapObjects[mapObjIndices[i]]->GetModelIndex()]; + else + tile = &InfoForTilePeds[12 * m_mapObjects[mapObjIndices[i]]->GetModelIndex()]; + } +#endif + // Find i inside path segment iseg = 0; for(j = Max(oldNumPathNodes, i-12); j < i; j++) - if(m_pathNodes[j].objectIndex == m_pathNodes[i].objectIndex) + if(OBJECTINDEX(j) == OBJECTINDEX(i)) iseg++; +#ifndef MIAMI istart = 12*m_mapObjects[m_pathNodes[i].objectIndex]->m_modelIndex; +#endif // Add links to other internal nodes for(j = Max(oldNumPathNodes, i-12); j < Min(m_numPathNodes, i+12); j++){ - if(m_pathNodes[i].objectIndex != m_pathNodes[j].objectIndex || i == j) + if(OBJECTINDEX(i) != OBJECTINDEX(j) || i == j) continue; // N.B.: in every path segment, the externals have to be at the end jseg = j-i + iseg; +#ifndef MIAMI jstart = 12*m_mapObjects[m_pathNodes[j].objectIndex]->m_modelIndex; if(objectpathinfo[istart + iseg].next == jseg || objectpathinfo[jstart + jseg].next == iseg){ - // Found a link between i and j +#else + if(tile[iseg].next == jseg || + tile[jseg].next == iseg){ +#endif + // Found a link between i and jConnectionSetCrossesRoad + // NB this clears the flags in MIAMI m_connections[m_numConnections] = j; - dist = m_pathNodes[i].pos - m_pathNodes[j].pos; - m_distances[m_numConnections] = dist.Magnitude(); + dist = (m_pathNodes[i].GetPosition() - m_pathNodes[j].GetPosition()).Magnitude(); +#ifndef MIAMI + m_distances[m_numConnections] = dist; +#else + m_distances[m_numConnections] = Min(dist, 255); +#endif if(type == PATH_CAR){ - posx = (m_pathNodes[i].pos.x + m_pathNodes[j].pos.x)*0.5f; - posy = (m_pathNodes[i].pos.y + m_pathNodes[j].pos.y)*0.5f; - dx = m_pathNodes[j].pos.x - m_pathNodes[i].pos.x; - dy = m_pathNodes[j].pos.y - m_pathNodes[i].pos.y; + posx = (m_pathNodes[i].GetX() + m_pathNodes[j].GetX())*0.5f; + posy = (m_pathNodes[i].GetY() + m_pathNodes[j].GetY())*0.5f; + dx = m_pathNodes[j].GetX() - m_pathNodes[i].GetX(); + dy = m_pathNodes[j].GetY() - m_pathNodes[i].GetY(); mag = Sqrt(dx*dx + dy*dy); dx /= mag; dy /= mag; +#ifdef MIAMI + int width = Max(m_pathNodes[i].width, m_pathNodes[j].width); +#endif if(i < j){ dx = -dx; dy = -dy; @@ -726,33 +1101,56 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor // IMPROVE: use a goto here // Find existing car path link for(k = 0; k < m_numCarPathLinks; k++){ +#ifndef MIAMI if(m_carPathLinks[k].dir.x == dx && m_carPathLinks[k].dir.y == dy && m_carPathLinks[k].pos.x == posx && m_carPathLinks[k].pos.y == posy){ +#else + if(m_carPathLinks[k].dirX == (int)(dx*100.0f) && + m_carPathLinks[k].dirY == (int)(dy*100.0f) && + m_carPathLinks[k].x == (int)(posx*8.0f) && + m_carPathLinks[k].y == (int)(posy*8.0f)){ +#endif m_carPathConnections[m_numConnections] = k; k = m_numCarPathLinks; } } // k is m_numCarPathLinks+1 if we found one if(k == m_numCarPathLinks){ +#ifndef MIAMI m_carPathLinks[m_numCarPathLinks].dir.x = dx; m_carPathLinks[m_numCarPathLinks].dir.y = dy; m_carPathLinks[m_numCarPathLinks].pos.x = posx; m_carPathLinks[m_numCarPathLinks].pos.y = posy; +#else + m_carPathLinks[m_numCarPathLinks].dirX = dx*100.0f; + m_carPathLinks[m_numCarPathLinks].dirY = dy*100.0f; + m_carPathLinks[m_numCarPathLinks].x = posx*8.0f; + m_carPathLinks[m_numCarPathLinks].y = posy*8.0f; + m_carPathLinks[m_numCarPathLinks].flag1 = false; + m_carPathLinks[m_numCarPathLinks].width = width; +#endif m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1; m_carPathLinks[m_numCarPathLinks].numRightLanes = -1; m_carPathLinks[m_numCarPathLinks].trafficLightType = 0; + assert(m_numCarPathLinks <= NUM_CARPATHLINKS); m_carPathConnections[m_numConnections] = m_numCarPathLinks++; } }else{ // Crosses road +#ifndef MIAMI if(objectpathinfo[istart + iseg].next == jseg && objectpathinfo[istart + iseg].crossing || objectpathinfo[jstart + jseg].next == iseg && objectpathinfo[jstart + jseg].crossing) m_connectionFlags[m_numConnections].bCrossesRoad = true; else m_connectionFlags[m_numConnections].bCrossesRoad = false; +#else + if(tile[iseg].next == jseg && tile[iseg].crossing || + tile[jseg].next == iseg && tile[jseg].crossing) + m_connections[m_numConnections] |= 0x8000; // crosses road flag +#endif } m_pathNodes[i].numLinks++; @@ -765,7 +1163,11 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor done = 0; // Set number of lanes for all nodes somehow // very strange code +#ifndef MIAMI for(k = 0; !done && k < 10; k++){ +#else + for(k = 0; !done && k < 12; k++){ +#endif done = 1; for(i = 0; i < m_numPathNodes; i++){ if(m_pathNodes[i].numLinks != 2) @@ -773,6 +1175,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor l1 = m_carPathConnections[m_pathNodes[i].firstLink]; l2 = m_carPathConnections[m_pathNodes[i].firstLink+1]; +#ifndef MIAMI if(m_carPathLinks[l1].numLeftLanes == -1 && m_carPathLinks[l2].numLeftLanes != -1){ done = 0; @@ -800,6 +1203,52 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor }else if(m_carPathLinks[l1].numLeftLanes == -1 && m_carPathLinks[l2].numLeftLanes == -1) done = 0; +#else + int8 l1Left = m_carPathLinks[l1].numLeftLanes; + int8 l1Right = m_carPathLinks[l1].numRightLanes; + int8 l2Left = m_carPathLinks[l2].numLeftLanes; + int8 l2Right = m_carPathLinks[l2].numRightLanes; + int8 *l1Leftp, *l1Rightp; + int8 *l2Leftp, *l2Rightp; + if(m_carPathLinks[l1].pathNodeIndex == i){ + l1Leftp = &l1Left; + l1Rightp = &l1Right; + }else{ + l1Leftp = &l1Right; + l1Rightp = &l1Left; + } + if(m_carPathLinks[l2].pathNodeIndex == i){ + l2Leftp = &l2Left; + l2Rightp = &l2Right; + }else{ + l2Leftp = &l2Right; + l2Rightp = &l2Left; + } + if(*l1Leftp == -1 && *l2Rightp != -1){ + *l1Leftp = *l2Rightp; + done = 0; + } + if(*l1Rightp == -1 && *l2Leftp != -1){ + *l1Rightp = *l2Leftp; + done = 0; + } + if(*l2Leftp == -1 && *l1Rightp != -1){ + *l2Leftp = *l1Rightp; + done = 0; + } + if(*l2Rightp == -1 && *l1Leftp != -1){ + *l2Rightp = *l1Leftp; + done = 0; + } + if(*l1Leftp == -1 && *l2Rightp == -1) + done = 0; + if(*l2Leftp == -1 && *l1Rightp == -1) + done = 0; + m_carPathLinks[l1].numLeftLanes = l1Left; + m_carPathLinks[l1].numRightLanes = l1Right; + m_carPathLinks[l2].numLeftLanes = l2Left; + m_carPathLinks[l2].numRightLanes = l2Right; +#endif } } @@ -807,10 +1256,17 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor for(i = 0; i < m_numPathNodes; i++) for(j = 0; j < m_pathNodes[i].numLinks; j++){ k = m_carPathConnections[m_pathNodes[i].firstLink + j]; +#ifndef MIAMI if(m_carPathLinks[k].numLeftLanes < 0) m_carPathLinks[k].numLeftLanes = 1; if(m_carPathLinks[k].numRightLanes < 0) m_carPathLinks[k].numRightLanes = 1; +#else + if(m_carPathLinks[k].numLeftLanes == -1) + m_carPathLinks[k].numLeftLanes = 0; + if(m_carPathLinks[k].numRightLanes == -1) + m_carPathLinks[k].numRightLanes = 0; +#endif } } @@ -819,13 +1275,15 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor do{ cont = 0; for(i = 0; i < m_numPathNodes; i++){ +#ifndef MIAMI m_pathNodes[i].bDisabled = false; m_pathNodes[i].bBetweenLevels = false; +#endif // See if node is a dead end, if so, we're not done yet if(!m_pathNodes[i].bDeadEnd){ k = 0; for(j = 0; j < m_pathNodes[i].numLinks; j++) - if(!m_pathNodes[m_connections[m_pathNodes[i].firstLink + j]].bDeadEnd) + if(!m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].bDeadEnd) k++; if(k < 2){ m_pathNodes[i].bDeadEnd = true; @@ -847,10 +1305,13 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor m_pathNodes[j] = m_pathNodes[j+1]; // Fix links - for(j = oldNumLinks; j < m_numConnections; j++) - if(m_connections[j] >= i) - m_connections[j]--; + for(j = oldNumLinks; j < m_numConnections; j++){ + int node = ConnectedNode(j); + if(node >= i) + m_connections[j] = node-1; + } +#ifndef MIAMI // Also in treadables for(j = 0; j < m_numMapObjects; j++) for(k = 0; k < 12; k++){ @@ -862,12 +1323,17 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor }else if(m_mapObjects[j]->m_nodeIndices[PATH_PED][k] > i) m_mapObjects[j]->m_nodeIndices[PATH_PED][k]--; } +#endif i--; m_numPathNodes--; } +#ifdef MIAMI + delete[] mapObjIndices; +#endif } +//--MIAMI: done float CPathFind::CalcRoadDensity(float x, float y) { @@ -875,93 +1341,105 @@ CPathFind::CalcRoadDensity(float x, float y) float density = 0.0f; for(i = 0; i < m_numCarPathNodes; i++){ - if(Abs(m_pathNodes[i].pos.x - x) < 80.0f && - Abs(m_pathNodes[i].pos.y - y) < 80.0f && + if(Abs(m_pathNodes[i].GetX() - x) < 80.0f && + Abs(m_pathNodes[i].GetY() - y) < 80.0f && m_pathNodes[i].numLinks > 0){ for(j = 0; j < m_pathNodes[i].numLinks; j++){ - int next = m_connections[m_pathNodes[i].firstLink + j]; - float dist = (m_pathNodes[i].pos - m_pathNodes[next].pos).Magnitude2D(); + int next = ConnectedNode(m_pathNodes[i].firstLink + j); + float dist = (m_pathNodes[i].GetPosition() - m_pathNodes[next].GetPosition()).Magnitude2D(); next = m_carPathConnections[m_pathNodes[i].firstLink + j]; density += m_carPathLinks[next].numLeftLanes * dist; density += m_carPathLinks[next].numRightLanes * dist; +#ifndef MIAMI if(m_carPathLinks[next].numLeftLanes < 0) printf("Link from object %d to %d (MIs)\n", m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex(), - m_mapObjects[m_pathNodes[m_connections[m_pathNodes[i].firstLink + j]].objectIndex]->GetModelIndex()); + m_mapObjects[m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].objectIndex]->GetModelIndex()); if(m_carPathLinks[next].numRightLanes < 0) printf("Link from object %d to %d (MIs)\n", m_mapObjects[m_pathNodes[i].objectIndex]->GetModelIndex(), - m_mapObjects[m_pathNodes[m_connections[m_pathNodes[i].firstLink + j]].objectIndex]->GetModelIndex()); + m_mapObjects[m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].objectIndex]->GetModelIndex()); +#endif } } } return density/2500.0f; } +//--MIAMI: done bool CPathFind::TestForPedTrafficLight(CPathNode *n1, CPathNode *n2) { int i; for(i = 0; i < n1->numLinks; i++) - if(&m_pathNodes[m_connections[n1->firstLink + i]] == n2) - return m_connectionFlags[n1->firstLink + i].bTrafficLight; + if(&m_pathNodes[ConnectedNode(n1->firstLink + i)] == n2) + return ConnectionHasTrafficLight(n1->firstLink + i); return false; } +//--MIAMI: done bool CPathFind::TestCrossesRoad(CPathNode *n1, CPathNode *n2) { int i; for(i = 0; i < n1->numLinks; i++) - if(&m_pathNodes[m_connections[n1->firstLink + i]] == n2) - return m_connectionFlags[n1->firstLink + i].bCrossesRoad; + if(&m_pathNodes[ConnectedNode(n1->firstLink + i)] == n2) + return ConnectionCrossesRoad(n1->firstLink + i); return false; } +//--MIAMI: done void CPathFind::AddNodeToList(CPathNode *node, int32 listId) { int i = listId & 0x1FF; - node->next = m_searchNodes[i].next; - node->prev = &m_searchNodes[i]; - if(m_searchNodes[i].next) - m_searchNodes[i].next->prev = node; - m_searchNodes[i].next = node; + node->SetNext(m_searchNodes[i].GetNext()); + node->SetPrev(&m_searchNodes[i]); + if(m_searchNodes[i].GetNext()) + m_searchNodes[i].GetNext()->SetPrev(node); + m_searchNodes[i].SetNext(node); node->distance = listId; } +//--MIAMI: done void CPathFind::RemoveNodeFromList(CPathNode *node) { - node->prev->next = node->next; - if(node->next) - node->next->prev = node->prev; + node->GetPrev()->SetNext(node->GetNext()); + if(node->GetNext()) + node->GetNext()->SetPrev(node->GetPrev()); } +//--MIAMI: done void CPathFind::RemoveBadStartNode(CVector pos, CPathNode **nodes, int16 *n) { int i; if(*n < 2) return; - if(DotProduct2D(nodes[1]->pos - pos, nodes[0]->pos - pos) < 0.0f){ + if(DotProduct2D(nodes[1]->GetPosition() - pos, nodes[0]->GetPosition() - pos) < 0.0f){ (*n)--; for(i = 0; i < *n; i++) nodes[i] = nodes[i+1]; } } +#ifdef GTA_BRIDGE void CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool enable) { int i; - for(i = 0; i < m_numCarPathLinks; i++) - if(x1 < m_carPathLinks[i].pos.x && m_carPathLinks[i].pos.x < x2 && - y1 < m_carPathLinks[i].pos.y && m_carPathLinks[i].pos.y < y2) + for(i = 0; i < m_numCarPathLinks; i++){ + CVector2D pos = m_carPathLinks[i].GetPosition(); + if(x1 < pos.x && pos.x < x2 && + y1 < pos.y && pos.y < y2) m_carPathLinks[i].bBridgeLights = enable; + } } +#endif +//--MIAMI: done void CPathFind::SwitchOffNodeAndNeighbours(int32 nodeId, bool disable) { @@ -970,39 +1448,46 @@ CPathFind::SwitchOffNodeAndNeighbours(int32 nodeId, bool disable) m_pathNodes[nodeId].bDisabled = disable; if(m_pathNodes[nodeId].numLinks < 3) for(i = 0; i < m_pathNodes[nodeId].numLinks; i++){ - next = m_connections[m_pathNodes[nodeId].firstLink + i]; + next = ConnectedNode(m_pathNodes[nodeId].firstLink + i); if(m_pathNodes[next].bDisabled != disable && m_pathNodes[next].numLinks < 3) SwitchOffNodeAndNeighbours(next, disable); } } +//--MIAMI: done void CPathFind::SwitchRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable) { int i; - for(i = 0; i < m_numCarPathNodes; i++) - if (x1 <= m_pathNodes[i].pos.x && m_pathNodes[i].pos.x <= x2 && - y1 <= m_pathNodes[i].pos.y && m_pathNodes[i].pos.y <= y2 && - z1 <= m_pathNodes[i].pos.z && m_pathNodes[i].pos.z <= z2 && + for(i = 0; i < m_numCarPathNodes; i++){ + CVector pos = m_pathNodes[i].GetPosition(); + if(x1 <= pos.x && pos.x <= x2 && + y1 <= pos.y && pos.y <= y2 && + z1 <= pos.z && pos.z <= z2 && disable != m_pathNodes[i].bDisabled) SwitchOffNodeAndNeighbours(i, disable); + } } +//--MIAMI: done void CPathFind::SwitchPedRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable) { int i; - for(i = m_numCarPathNodes; i < m_numPathNodes; i++) - if(x1 <= m_pathNodes[i].pos.x && m_pathNodes[i].pos.x <= x2 && - y1 <= m_pathNodes[i].pos.y && m_pathNodes[i].pos.y <= y2 && - z1 <= m_pathNodes[i].pos.z && m_pathNodes[i].pos.z <= z2 && + for(i = m_numCarPathNodes; i < m_numPathNodes; i++){ + CVector pos = m_pathNodes[i].GetPosition(); + if(x1 <= pos.x && pos.x <= x2 && + y1 <= pos.y && pos.y <= y2 && + z1 <= pos.z && pos.z <= z2 && disable != m_pathNodes[i].bDisabled) SwitchOffNodeAndNeighbours(i, disable); + } } +//--MIAMI: unused (still needed for script here) void CPathFind::SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float y2, float z2, float length, uint8 type, uint8 mode) { @@ -1039,9 +1524,10 @@ CPathFind::SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float bool disable = mode == SWITCH_OFF; for(i = firstNode; i < lastNode; i++){ - if(m_pathNodes[i].pos.z < z1 || m_pathNodes[i].pos.z > z2) + CVector pos = m_pathNodes[i].GetPosition(); + if(pos.z < z1 || pos.z > z2) continue; - CVector2D d(m_pathNodes[i].pos.x - x1, m_pathNodes[i].pos.y - y1); + CVector2D d(pos.x - x1, pos.y - y1); float dot = DotProduct2D(d, v12); if(dot < 0.0f || dot > len12) continue; @@ -1053,6 +1539,7 @@ CPathFind::SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float } } +//--MIAMI: unused (still needed for script here) void CPathFind::MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId) { @@ -1061,39 +1548,51 @@ CPathFind::MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId) m_pathNodes[nodeId].bBetweenLevels = true; if(m_pathNodes[nodeId].numLinks < 3) for(i = 0; i < m_pathNodes[nodeId].numLinks; i++){ - next = m_connections[m_pathNodes[nodeId].firstLink + i]; + next = ConnectedNode(m_pathNodes[nodeId].firstLink + i); if(!m_pathNodes[next].bBetweenLevels && m_pathNodes[next].numLinks < 3) MarkRoadsBetweenLevelsNodeAndNeighbours(next); } } +//--MIAMI: unused (still needed for script here) void CPathFind::MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2) { int i; - for(i = 0; i < m_numPathNodes; i++) - if(x1 < m_pathNodes[i].pos.x && m_pathNodes[i].pos.x < x2 && - y1 < m_pathNodes[i].pos.y && m_pathNodes[i].pos.y < y2 && - z1 < m_pathNodes[i].pos.z && m_pathNodes[i].pos.z < z2) + for(i = 0; i < m_numPathNodes; i++){ + CVector pos = m_pathNodes[i].GetPosition(); + if(x1 < pos.x && pos.x < x2 && + y1 < pos.y && pos.y < y2 && + z1 < pos.z && pos.z < z2) MarkRoadsBetweenLevelsNodeAndNeighbours(i); + } } +//--MIAMI: unused (still needed for script here) void CPathFind::PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2) { int i; - for(i = m_numCarPathNodes; i < m_numPathNodes; i++) - if(x1 < m_pathNodes[i].pos.x && m_pathNodes[i].pos.x < x2 && - y1 < m_pathNodes[i].pos.y && m_pathNodes[i].pos.y < y2 && - z1 < m_pathNodes[i].pos.z && m_pathNodes[i].pos.z < z2) + for(i = m_numCarPathNodes; i < m_numPathNodes; i++){ + CVector pos = m_pathNodes[i].GetPosition(); + if(x1 < pos.x && pos.x < x2 && + y1 < pos.y && pos.y < y2 && + z1 < pos.z && pos.z < z2) MarkRoadsBetweenLevelsNodeAndNeighbours(i); + } } +//--MIAMI: done +#ifndef MIAMI int32 CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels) +#else +int32 +CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels, bool ignoreFlagB4, bool bWaterPath) +#endif { int i; int firstNode, lastNode; @@ -1115,22 +1614,30 @@ CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bo for(i = firstNode; i < lastNode; i++){ if(ignoreDisabled && m_pathNodes[i].bDisabled) continue; if(ignoreBetweenLevels && m_pathNodes[i].bBetweenLevels) continue; +#ifndef MIAMI switch(m_pathNodes[i].unkBits){ case 1: case 2: - dist = Abs(m_pathNodes[i].pos.x - coors.x) + - Abs(m_pathNodes[i].pos.y - coors.y) + - 3.0f*Abs(m_pathNodes[i].pos.z - coors.z); +#else + if(ignoreFlagB4 && m_pathNodes[i].flagB4) continue; + if(bWaterPath != m_pathNodes[i].bWaterPath) continue; +#endif + dist = Abs(m_pathNodes[i].GetX() - coors.x) + + Abs(m_pathNodes[i].GetY() - coors.y) + + 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z); if(dist < closestDist){ closestDist = dist; closestNode = i; } +#ifndef MIAMI break; } +#endif } return closestDist < distLimit ? closestNode : -1; } +//--MIAMI: done int32 CPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY) { @@ -1153,13 +1660,15 @@ CPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, floa } for(i = firstNode; i < lastNode; i++){ +#ifndef MIAMI switch(m_pathNodes[i].unkBits){ case 1: case 2: - dX = m_pathNodes[i].pos.x - coors.x; - dY = m_pathNodes[i].pos.y - coors.y; +#endif + dX = m_pathNodes[i].GetX() - coors.x; + dY = m_pathNodes[i].GetY() - coors.y; dist = Abs(dX) + Abs(dY) + - 3.0f*Abs(m_pathNodes[i].pos.z - coors.z); + 3.0f*Abs(m_pathNodes[i].GetZ() - coors.z); if(dist < closestDist){ NormalizeXY(dX, dY); dist -= (dX*dirX + dY*dirY - 1.0f)*20.0f; @@ -1168,37 +1677,40 @@ CPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, floa closestNode = i; } } +#ifndef MIAMI break; } +#endif } return closestNode; } - +//--MIAMI: done float CPathFind::FindNodeOrientationForCarPlacement(int32 nodeId) { if(m_pathNodes[nodeId].numLinks == 0) return 0.0f; - CVector dir = m_pathNodes[m_connections[m_pathNodes[nodeId].firstLink]].pos - m_pathNodes[nodeId].pos; + CVector dir = m_pathNodes[ConnectedNode(m_pathNodes[nodeId].firstLink)].GetPosition() - m_pathNodes[nodeId].GetPosition(); dir.z = 0.0f; dir.Normalise(); return RADTODEG(dir.Heading()); } +//--MIAMI: unused (still needed for script here) float CPathFind::FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards) { int i; - CVector targetDir(x - m_pathNodes[nodeId].pos.x, y - m_pathNodes[nodeId].pos.y, 0.0f); + CVector targetDir(x - m_pathNodes[nodeId].GetX(), y - m_pathNodes[nodeId].GetY(), 0.0f); targetDir.Normalise(); CVector dir; if(m_pathNodes[nodeId].numLinks == 0) return 0.0f; - int bestNode = m_connections[m_pathNodes[nodeId].firstLink]; + int bestNode = ConnectedNode(m_pathNodes[nodeId].firstLink); #ifdef FIX_BUGS float bestDot = towards ? -2.0f : 2.0f; #else @@ -1206,29 +1718,31 @@ CPathFind::FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, flo #endif for(i = 0; i < m_pathNodes[nodeId].numLinks; i++){ - dir = m_pathNodes[m_connections[m_pathNodes[nodeId].firstLink + i]].pos - m_pathNodes[nodeId].pos; + dir = m_pathNodes[ConnectedNode(m_pathNodes[nodeId].firstLink + i)].GetPosition() - m_pathNodes[nodeId].GetPosition(); dir.z = 0.0f; dir.Normalise(); float angle = DotProduct2D(dir, targetDir); if(towards){ if(angle > bestDot){ bestDot = angle; - bestNode = m_connections[m_pathNodes[nodeId].firstLink + i]; + bestNode = ConnectedNode(m_pathNodes[nodeId].firstLink + i); } }else{ if(angle < bestDot){ bestDot = angle; - bestNode = m_connections[m_pathNodes[nodeId].firstLink + i]; + bestNode = ConnectedNode(m_pathNodes[nodeId].firstLink + i); } } } - dir = m_pathNodes[bestNode].pos - m_pathNodes[nodeId].pos; + dir = m_pathNodes[bestNode].GetPosition() - m_pathNodes[nodeId].GetPosition(); dir.z = 0.0f; dir.Normalise(); return RADTODEG(dir.Heading()); } +// no "New" in MIAMI +//--MIAMI: TODO bool CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled) { @@ -1243,21 +1757,21 @@ CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, node1 = (CGeneral::GetRandomNumber()>>3) % m_numCarPathNodes; if(m_pathNodes[node1].bDisabled && !ignoreDisabled) continue; - dist1 = Distance2D(m_pathNodes[node1].pos, x, y); + dist1 = Distance2D(m_pathNodes[node1].GetPosition(), x, y); if(dist1 < spawnDist + 60.0f){ d1 = dist1 - spawnDist; for(j = 0; j < m_pathNodes[node1].numLinks; j++){ - node2 = m_connections[m_pathNodes[node1].firstLink + j]; + node2 = ConnectedNode(m_pathNodes[node1].firstLink + j); if(m_pathNodes[node2].bDisabled && !ignoreDisabled) continue; - dist2 = Distance2D(m_pathNodes[node2].pos, x, y); + dist2 = Distance2D(m_pathNodes[node2].GetPosition(), x, y); d2 = dist2 - spawnDist; if(d1*d2 < 0.0f){ // nodes are on different sides of spawn distance float f2 = Abs(d1)/(Abs(d1) + Abs(d2)); float f1 = 1.0f - f2; *pPositionBetweenNodes = f2; - CVector pos = m_pathNodes[node1].pos*f1 + m_pathNodes[node2].pos*f2; + CVector pos = m_pathNodes[node1].GetPosition()*f1 + m_pathNodes[node2].GetPosition()*f2; CVector2D dist2d(pos.x - x, pos.y - y); dist2d.Normalise(); // done manually in the game float dot = DotProduct2D(dist2d, CVector2D(dirX, dirY)); @@ -1283,6 +1797,7 @@ CPathFind::NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, return false; } +//--MIAMI: TODO bool CPathFind::GeneratePedCreationCoors(float x, float y, float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, CMatrix *camMatrix) { @@ -1294,20 +1809,20 @@ CPathFind::GeneratePedCreationCoors(float x, float y, float minDist, float maxDi for(i = 0; i < 400; i++){ node1 = m_numCarPathNodes + CGeneral::GetRandomNumber() % m_numPedPathNodes; - if(DistanceSqr2D(m_pathNodes[node1].pos, x, y) < sq(maxDist+30.0f)){ + if(DistanceSqr2D(m_pathNodes[node1].GetPosition(), x, y) < sq(maxDist+30.0f)){ if(m_pathNodes[node1].numLinks == 0) continue; int link = m_pathNodes[node1].firstLink + CGeneral::GetRandomNumber() % m_pathNodes[node1].numLinks; - if(m_connectionFlags[link].bCrossesRoad) + if(ConnectionCrossesRoad(link)) continue; - node2 = m_connections[link]; + node2 = ConnectedNode(link); if(m_pathNodes[node1].bDisabled || m_pathNodes[node2].bDisabled) continue; float f2 = (CGeneral::GetRandomNumber()&0xFF)/256.0f; float f1 = 1.0f - f2; *pPositionBetweenNodes = f2; - CVector pos = m_pathNodes[node1].pos*f1 + m_pathNodes[node2].pos*f2; + CVector pos = m_pathNodes[node1].GetPosition()*f1 + m_pathNodes[node2].GetPosition()*f2; if(Distance2D(pos, x, y) < maxDist+20.0f){ pos.x += ((CGeneral::GetRandomNumber()&0xFF)-128)*0.01f; pos.y += ((CGeneral::GetRandomNumber()&0xFF)-128)*0.01f; @@ -1342,6 +1857,7 @@ CPathFind::GeneratePedCreationCoors(float x, float y, float minDist, float maxDi return false; } +#ifndef MIAMI CTreadable* CPathFind::FindRoadObjectClosestToCoors(CVector coors, uint8 type) { @@ -1363,11 +1879,11 @@ CPathFind::FindRoadObjectClosestToCoors(CVector coors, uint8 type) break; // FIX: game uses ThePaths here explicitly for(k = 0; k < m_pathNodes[node1].numLinks; k++){ - node2 = m_connections[m_pathNodes[node1].firstLink + k]; - float lineDist = CCollision::DistToLine(&m_pathNodes[node1].pos, &m_pathNodes[node2].pos, &coors); + node2 = ConnectedNode(m_pathNodes[node1].firstLink + k); + float lineDist = CCollision::DistToLine(&m_pathNodes[node1].GetPosition(), &m_pathNodes[node2].GetPosition(), &coors); if(lineDist < closestDist){ closestDist = lineDist; - if((coors - m_pathNodes[node1].pos).MagnitudeSqr() < (coors - m_pathNodes[node2].pos).MagnitudeSqr()) + if((coors - m_pathNodes[node1].GetPosition()).MagnitudeSqr() < (coors - m_pathNodes[node2].GetPosition()).MagnitudeSqr()) closestMapObj = m_mapObjects[m_pathNodes[node1].objectIndex]; else closestMapObj = m_mapObjects[m_pathNodes[node2].objectIndex]; @@ -1377,14 +1893,17 @@ CPathFind::FindRoadObjectClosestToCoors(CVector coors, uint8 type) } return closestMapObj; } +#endif +//--MIAMI: done void CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode, CPathNode **nextNode, uint8 curDir, uint8 *nextDir) { int i; CPathNode *node; - if(lastNode == nil || (node = *lastNode) == nil || (coors - (*lastNode)->pos).MagnitudeSqr() > 7.0f){ + if(lastNode == nil || (node = *lastNode) == nil || (coors - (*lastNode)->GetPosition()).MagnitudeSqr() > 7.0f){ +#ifndef MIAMI // need to find the node we're coming from node = nil; CTreadable *obj = FindRoadObjectClosestToCoors(coors, type); @@ -1392,28 +1911,32 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode for(i = 0; i < 12; i++){ if(obj->m_nodeIndices[type][i] < 0) break; - float dist = (coors - m_pathNodes[obj->m_nodeIndices[type][i]].pos).MagnitudeSqr(); + float dist = (coors - m_pathNodes[obj->m_nodeIndices[type][i]].GetPosition()).MagnitudeSqr(); if(dist < nodeDist){ nodeDist = dist; node = &m_pathNodes[obj->m_nodeIndices[type][i]]; } } +#else + int32 nodeIdx = FindNodeClosestToCoors(coors, type, 999999.88f); + node = &m_pathNodes[nodeIdx]; +#endif } CVector2D vCurDir(Sin(curDir*PI/4.0f), Cos(curDir * PI / 4.0f)); *nextNode = 0; float bestDot = -999999.0f; for(i = 0; i < node->numLinks; i++){ - int next = m_connections[node->firstLink+i]; + int next = ConnectedNode(node->firstLink+i); if(!node->bDisabled && m_pathNodes[next].bDisabled) continue; CVector pedCoors = coors; pedCoors.z += 1.0f; - CVector nodeCoors = m_pathNodes[next].pos; + CVector nodeCoors = m_pathNodes[next].GetPosition(); nodeCoors.z += 1.0f; if(!CWorld::GetIsLineOfSightClear(pedCoors, nodeCoors, true, false, false, false, false, false)) continue; - CVector2D nodeDir = m_pathNodes[next].pos - node->pos; + CVector2D nodeDir = m_pathNodes[next].GetPosition() - node->GetPosition(); nodeDir.Normalise(); float dot = DotProduct2D(nodeDir, vCurDir); if(dot >= bestDot){ @@ -1421,7 +1944,7 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode bestDot = dot; // direction is 0, 2, 4, 6 for north, east, south, west - // this could be sone simpler... + // this could be done simpler... if(nodeDir.x < 0.0f){ if(2.0f*Abs(nodeDir.y) < -nodeDir.x) *nextDir = 6; // west @@ -1453,26 +1976,29 @@ CPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode } } +#ifndef MIAMI static CPathNode *apNodesToBeCleared[4995]; +#else +static CPathNode *apNodesToBeCleared[6525]; +#endif +//--MIAMI: done void -CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *pNumNodes, int16 maxNumNodes, CVehicle *vehicle, float *pDist, float distLimit, int32 forcedTargetNode) +CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *pNumNodes, int16 maxNumNodes, CVehicle *vehicle, float *pDist, float distLimit, int32 targetNodeId) { int i, j; // Find target - int targetNode; - if(forcedTargetNode < 0) - targetNode = FindNodeClosestToCoors(target, type, distLimit); - else - targetNode = forcedTargetNode; - if(targetNode < 0) { + if(targetNodeId < 0) + targetNodeId = FindNodeClosestToCoors(target, type, distLimit); + if(targetNodeId < 0) { *pNumNodes = 0; if(pDist) *pDist = 100000.0f; return; } // Find start +#ifndef MIAMI int numPathsToTry; CTreadable *startObj; if(startNodeId < 0){ @@ -1482,7 +2008,7 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta for(i = 0; i < 12; i++){ if(startObj->m_nodeIndices[type][i] < 0) break; - if(m_pathNodes[startObj->m_nodeIndices[type][i]].group == m_pathNodes[targetNode].group) + if(m_pathNodes[startObj->m_nodeIndices[type][i]].group == m_pathNodes[targetNodeId].group) numPathsToTry++; } }else{ @@ -1498,39 +2024,67 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta if(startNodeId < 0){ // why only check node 0? if(m_pathNodes[startObj->m_nodeIndices[type][0]].group != - m_pathNodes[targetNode].group) { + m_pathNodes[targetNodeId].group) { *pNumNodes = 0; if(pDist) *pDist = 100000.0f; return; } }else{ - if(m_pathNodes[startNodeId].group != m_pathNodes[targetNode].group) { + if(m_pathNodes[startNodeId].group != m_pathNodes[targetNodeId].group) { *pNumNodes = 0; if(pDist) *pDist = 100000.0f; return; } } +#else + if(startNodeId < 0) + startNodeId = FindNodeClosestToCoors(start, type, 999999.88f); + if(startNodeId < 0) { + *pNumNodes = 0; + if(pDist) *pDist = 100000.0f; + return; + } + if(startNodeId == targetNodeId){ + *pNumNodes = 0; + if(pDist) *pDist = 0.0f; + return; + } + if(m_pathNodes[startNodeId].group != m_pathNodes[targetNodeId].group) { + *pNumNodes = 0; + if(pDist) *pDist = 100000.0f; + return; + } +#endif - for(i = 0; i < 512; i++) - m_searchNodes[i].next = nil; - AddNodeToList(&m_pathNodes[targetNode], 0); + for(i = 0; i < ARRAY_SIZE(m_searchNodes); i++) + m_searchNodes[i].SetNext(nil); + AddNodeToList(&m_pathNodes[targetNodeId], 0); int numNodesToBeCleared = 0; - apNodesToBeCleared[numNodesToBeCleared++] = &m_pathNodes[targetNode]; + apNodesToBeCleared[numNodesToBeCleared++] = &m_pathNodes[targetNodeId]; // Dijkstra's algorithm // Find distances int numPathsFound = 0; - if(startNodeId < 0 && m_mapObjects[m_pathNodes[targetNode].objectIndex] == startObj) +#ifndef MIAMI + if(startNodeId < 0 && m_mapObjects[m_pathNodes[targetNodeId].objectIndex] == startObj) numPathsFound++; for(i = 0; numPathsFound < numPathsToTry; i = (i+1) & 0x1FF){ +#else + for(i = 0; numPathsFound == 0; i = (i+1) & 0x1FF){ +#endif CPathNode *node; - for(node = m_searchNodes[i].next; node; node = node->next){ + for(node = m_searchNodes[i].GetNext(); node; node = node->GetNext()){ +#ifndef MIAMI if(m_mapObjects[node->objectIndex] == startObj && (startNodeId < 0 || node == &m_pathNodes[startNodeId])) numPathsFound++; +#else + if(node == &m_pathNodes[startNodeId]) + numPathsFound = 1; +#endif for(j = 0; j < node->numLinks; j++){ - int next = m_connections[node->firstLink + j]; + int next = ConnectedNode(node->firstLink + j); int dist = node->distance + m_distances[node->firstLink + j]; if(dist < m_pathNodes[next].distance){ if(m_pathNodes[next].distance != MAX_DIST) @@ -1547,13 +2101,14 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta // Find out whence to start tracing back CPathNode *curNode; +#ifndef MIAMI if(startNodeId < 0){ int minDist = MAX_DIST; *pNumNodes = 1; for(i = 0; i < 12; i++){ if(startObj->m_nodeIndices[type][i] < 0) break; - int dist = (m_pathNodes[startObj->m_nodeIndices[type][i]].pos - start).Magnitude(); + int dist = (m_pathNodes[startObj->m_nodeIndices[type][i]].GetPosition() - start).Magnitude(); if(m_pathNodes[startObj->m_nodeIndices[type][i]].distance + dist < minDist){ minDist = m_pathNodes[startObj->m_nodeIndices[type][i]].distance + dist; curNode = &m_pathNodes[startObj->m_nodeIndices[type][i]]; @@ -1567,17 +2122,22 @@ CPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector ta } if(pDist) *pDist = minDist; - }else{ + }else +#endif + { curNode = &m_pathNodes[startNodeId]; *pNumNodes = 0; if(pDist) *pDist = m_pathNodes[startNodeId].distance; } +#ifdef MIAMI + nodes[(*pNumNodes)++] = curNode; +#endif // Trace back to target and update list of nodes - while(*pNumNodes < maxNumNodes && curNode != &m_pathNodes[targetNode]) + while(*pNumNodes < maxNumNodes && curNode != &m_pathNodes[targetNodeId]) for(i = 0; i < curNode->numLinks; i++){ - int next = m_connections[curNode->firstLink + i]; + int next = ConnectedNode(curNode->firstLink + i); if(curNode->distance - m_distances[curNode->firstLink + i] == m_pathNodes[next].distance){ curNode = &m_pathNodes[next]; nodes[(*pNumNodes)++] = curNode; @@ -1594,20 +2154,27 @@ static CPathNode *pNodeList[32]; static int16 DummyResult; static int16 DummyResult2; +//--MIAMI: done bool CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start) { float dist; + if(type == PATH_CAR) DoPathSearch(type, start, -1, target, pNodeList, &DummyResult, 32, nil, &dist, 999999.88f, -1); else DoPathSearch(type, start, -1, target, nil, &DummyResult2, 0, nil, &dist, 50.0f, -1); if(type == PATH_CAR) +#ifndef MIAMI return dist < 160.0f; +#else + return dist < 150.0f; +#endif else return dist < 100.0f; } +//--MIAMI: done void CPathFind::Save(uint8 *buf, uint32 *size) { @@ -1629,6 +2196,7 @@ CPathFind::Save(uint8 *buf, uint32 *size) buf[i/8 + n] &= ~(1 << i%8); } +//--MIAMI: done void CPathFind::Load(uint8 *buf, uint32 size) { @@ -1661,10 +2229,10 @@ CPathFind::DisplayPathData(void) // Render car path nodes if(gbShowCarPaths) for(i = 0; i < m_numCarPathNodes; i++){ - if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist)) + if((m_pathNodes[i].GetPosition() - pos).MagnitudeSqr() > SQR(maxDist)) continue; - CVector n1 = m_pathNodes[i].pos; + CVector n1 = m_pathNodes[i].GetPosition(); n1.z += 0.3f; // Draw node itself @@ -1673,8 +2241,8 @@ CPathFind::DisplayPathData(void) 0xFFFFFFFF, 0xFFFFFFFF); for(j = 0; j < m_pathNodes[i].numLinks; j++){ - k = m_connections[m_pathNodes[i].firstLink + j]; - CVector n2 = m_pathNodes[k].pos; + k = ConnectedNode(m_pathNodes[i].firstLink + j); + CVector n2 = m_pathNodes[k].GetPosition(); n2.z += 0.3f; // Draw links to neighbours CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, @@ -1686,12 +2254,12 @@ CPathFind::DisplayPathData(void) // Render car path nodes if(gbShowCarPathsLinks) for(i = 0; i < m_numCarPathLinks; i++){ - CVector2D n1_2d = m_carPathLinks[i].pos; + CVector2D n1_2d = m_carPathLinks[i].GetPosition(); if((n1_2d - pos).MagnitudeSqr() > SQR(maxDist)) continue; int ni = m_carPathLinks[i].pathNodeIndex; - CVector pn1 = m_pathNodes[ni].pos; + CVector pn1 = m_pathNodes[ni].GetPosition(); pn1.z += 0.3f; CVector n1(n1_2d.x, n1_2d.y, pn1.z); n1.z += 0.3f; @@ -1701,7 +2269,7 @@ CPathFind::DisplayPathData(void) n1.x, n1.y, n1.z + 1.0f, 0xFFFFFFFF, 0xFFFFFFFF); CLines::RenderLineWithClipping(n1.x, n1.y, n1.z + 0.5f, - n1.x+m_carPathLinks[i].dir.x, n1.y+m_carPathLinks[i].dir.y, n1.z + 0.5f, + n1.x+m_carPathLinks[i].GetDirX(), n1.y+m_carPathLinks[i].GetDirY(), n1.z + 0.5f, 0xFFFFFFFF, 0xFFFFFFFF); // Draw connection to car path node @@ -1723,9 +2291,9 @@ CPathFind::DisplayPathData(void) for(j = 0; j < m_pathNodes[ni].numLinks; j++){ k = m_carPathConnections[m_pathNodes[ni].firstLink + j]; - CVector2D n2_2d = m_carPathLinks[k].pos; + CVector2D n2_2d = m_carPathLinks[k].GetPosition(); int nk = m_carPathLinks[k].pathNodeIndex; - CVector pn2 = m_pathNodes[nk].pos; + CVector pn2 = m_pathNodes[nk].GetPosition(); pn2.z += 0.3f; CVector n2(n2_2d.x, n2_2d.y, pn2.z); n2.z += 0.3f; @@ -1740,10 +2308,10 @@ CPathFind::DisplayPathData(void) // Render ped path nodes if(gbShowPedPaths) for(i = m_numCarPathNodes; i < m_numPathNodes; i++){ - if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist)) + if((m_pathNodes[i].GetPosition() - pos).MagnitudeSqr() > SQR(maxDist)) continue; - CVector n1 = m_pathNodes[i].pos; + CVector n1 = m_pathNodes[i].GetPosition(); n1.z += 0.3f; // Draw node itself @@ -1752,8 +2320,8 @@ CPathFind::DisplayPathData(void) 0xFFFFFFFF, 0xFFFFFFFF); for(j = 0; j < m_pathNodes[i].numLinks; j++){ - k = m_connections[m_pathNodes[i].firstLink + j]; - CVector n2 = m_pathNodes[k].pos; + k = ConnectedNode(m_pathNodes[i].firstLink + j); + CVector n2 = m_pathNodes[k].GetPosition(); n2.z += 0.3f; // Draw links to neighbours CLines::RenderLineWithClipping(n1.x, n1.y, n1.z, @@ -1763,9 +2331,9 @@ CPathFind::DisplayPathData(void) // Draw connection flags CVector mid = (n1+n2)/2.0f; uint32 col = 0xFF; - if(m_connectionFlags[m_pathNodes[i].firstLink + j].bCrossesRoad) + if(ConnectionCrossesRoad(m_pathNodes[i].firstLink + j)) col += 0x00FF0000; - if(m_connectionFlags[m_pathNodes[i].firstLink + j].bTrafficLight) + if(ConnectionHasTrafficLight(m_pathNodes[i].firstLink + j)) col += 0xFF000000; CLines::RenderLineWithClipping(mid.x, mid.y, mid.z, mid.x, mid.y, mid.z + 1.0f, @@ -1773,3 +2341,25 @@ CPathFind::DisplayPathData(void) } } } + +#ifdef MIAMI +CPathNode* +CPathFind::GetNode(int16 index) +{ + if(index < 0) + return nil; + if(index < ARRAY_SIZE(ThePaths.m_searchNodes)) + return &ThePaths.m_searchNodes[index]; + return &ThePaths.m_pathNodes[index - ARRAY_SIZE(ThePaths.m_searchNodes)]; +} +int16 +CPathFind::GetIndex(CPathNode *node) +{ + if(node == nil) + return -1; + if(node >= &ThePaths.m_searchNodes[0] && node < &ThePaths.m_searchNodes[ARRAY_SIZE(ThePaths.m_searchNodes)]) + return node - ThePaths.m_searchNodes; + else + return (node - ThePaths.m_pathNodes) + ARRAY_SIZE(ThePaths.m_searchNodes); +} +#endif diff --git a/src/control/PathFind.h b/src/control/PathFind.h index 64c12d5b..a4bb02a2 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -55,6 +55,7 @@ public: struct CPathNode { +#ifndef MIAMI CVector pos; CPathNode *prev; CPathNode *next; @@ -69,31 +70,55 @@ struct CPathNode uint8 bBetweenLevels : 1; int8 group; -/* For reference VC: + + CVector &GetPosition(void) { return pos; } + void SetPosition(const CVector &p) { pos = p; } + float GetX(void) { return pos.x; } + float GetY(void) { return pos.y; } + float GetZ(void) { return pos.z; } + + CPathNode *GetPrev(void) { return prev; } + CPathNode *GetNext(void) { return next; } + void SetPrev(CPathNode *node) { prev = node; } + void SetNext(CPathNode *node) { next = node; } +#else int16 prevIndex; int16 nextIndex; int16 x; int16 y; int16 z; - int16 distance; + int16 distance; // in path search int16 firstLink; int8 width; int8 group; - int8 numLinks : 4; - int8 bDeadEnd : 1; - int8 bTurnedOff : 1; // flag 8 in node info - int8 flagA40 : 1; // flag 20 in node info - int8 flagA80 : 1; // flag 4 in node info - int8 flagB1 : 1; // flag 10 in node info - int8 flagB2 : 1; // flag 2 in node info - int8 flagB4 : 1; - int8 speedLimit : 2; // speed limit - int8 flagB20 : 1; - int8 flagB40 : 1; - int8 flagB80 : 1; - int8 spawnRate : 4; - int8 flagsC : 4; -*/ + + uint8 numLinks : 4; + uint8 bDeadEnd : 1; + uint8 bDisabled : 1; + uint8 bBetweenLevels : 1; + uint8 bUseInRoadBlock : 1; + + uint8 bWaterPath : 1; + uint8 flagB2 : 1; // flag 2 in node info, always zero + uint8 flagB4 : 1; // where is this set? + uint8 speedLimit : 2; + //uint8 flagB20 : 1; + //uint8 flagB40 : 1; + //uint8 flagB80 : 1; + + uint8 spawnRate : 4; + uint8 flagsC : 4; + + CVector GetPosition(void) { return CVector(x/8.0f, y/8.0f, z/8.0f); } + void SetPosition(const CVector &p) { x = p.x*8.0f; y = p.y*8.0f; z = p.z*8.0f; } + float GetX(void) { return x/8.0f; } + float GetY(void) { return y/8.0f; } + float GetZ(void) { return z/8.0f; } + CPathNode *GetPrev(void); + CPathNode *GetNext(void); + void SetPrev(CPathNode *node); + void SetNext(CPathNode *node); +#endif }; union CConnectionFlags @@ -107,6 +132,7 @@ union CConnectionFlags struct CCarPathLink { +#ifndef MIAMI CVector2D pos; CVector2D dir; int16 pathNodeIndex; @@ -117,6 +143,33 @@ struct CCarPathLink uint8 bBridgeLights : 1; // more? + CVector2D &GetPosition(void) { return pos; } + CVector2D &GetDirection(void) { return dir; } + float GetX(void) { return pos.x; } + float GetY(void) { return pos.y; } + float GetDirX(void) { return dir.x; } + float GetDirY(void) { return dir.y; } +#else + int16 x; + int16 y; + int16 pathNodeIndex; + int8 dirX; + int8 dirY; + int8 numLeftLanes : 3; + int8 numRightLanes : 3; + uint8 flag1 : 1; + uint8 trafficLightType : 2; + uint8 bBridgeLights : 1; // at least in LCS... + int8 width; + + CVector2D GetPosition(void) { return CVector2D(x/8.0f, y/8.0f); } + CVector2D GetDirection(void) { return CVector2D(dirX/100.0f, dirY/100.0f); } + float GetX(void) { return x/8.0f; } + float GetY(void) { return y/8.0f; } + float GetDirX(void) { return dirX/100.0f; } + float GetDirY(void) { return dirY/100.0f; } +#endif + float OneWayLaneOffset() { if (numLeftLanes == 0) @@ -127,8 +180,10 @@ struct CCarPathLink } }; +// This is what we're reading from the files, only temporary struct CPathInfoForObject { +#ifndef MIAMI int16 x; int16 y; int16 z; @@ -137,6 +192,28 @@ struct CPathInfoForObject int8 numLeftLanes; int8 numRightLanes; uint8 crossing : 1; +#else + float x; + float y; + float z; + int8 type; + int8 next; + int8 numLeftLanes; + int8 numRightLanes; + int8 speedLimit; + int8 width; + + uint8 crossing : 1; + uint8 flag02 : 1; // always zero + uint8 roadBlock : 1; + uint8 disabled : 1; + uint8 waterPath : 1; + uint8 betweenLevels : 1; + + uint8 spawnRate : 4; + + void SwapConnectionsToBeRightWayRound(void); +#endif }; extern CPathInfoForObject *InfoForTileCars; extern CPathInfoForObject *InfoForTilePeds; @@ -144,6 +221,7 @@ extern CPathInfoForObject *InfoForTilePeds; struct CTempNode { CVector pos; +#ifndef MIAMI float dirX; float dirY; int16 link1; @@ -151,34 +229,55 @@ struct CTempNode int8 numLeftLanes; int8 numRightLanes; int8 linkState; +#else + int8 dirX; // *100 + int8 dirY; + int16 link1; + int16 link2; + int8 numLeftLanes; + int8 numRightLanes; + int8 width; + bool isCross; + int8 linkState; +#endif }; +#ifdef MIAMI +struct CTempNodeExternal // made up name +{ + CVector pos; + int16 next; + int8 numLeftLanes; + int8 numRightLanes; + int8 width; + bool isCross; +}; +#endif + +#ifndef MIAMI struct CTempDetachedNode // unused { uint8 foo[20]; }; +#endif class CPathFind { public: -/* For reference VC: - CPathNode pathNodes[9650]; - CCarPathLink m_carPathLinks[3500]; - CBuilding *m_mapObjects[1250]; - // 0x8000 is cross road flag - // 0x4000 is traffic light flag - uint16 m_connections[20400]; - uint8 m_distances[20400]; - int16 m_carPathConnections[20400]; -*/ CPathNode m_pathNodes[NUM_PATHNODES]; CCarPathLink m_carPathLinks[NUM_CARPATHLINKS]; CTreadable *m_mapObjects[NUM_MAPOBJECTS]; +#ifndef MIAMI uint8 m_objectFlags[NUM_MAPOBJECTS]; int16 m_connections[NUM_PATHCONNECTIONS]; int16 m_distances[NUM_PATHCONNECTIONS]; CConnectionFlags m_connectionFlags[NUM_PATHCONNECTIONS]; +#else + uint16 m_connections[NUM_PATHCONNECTIONS]; // and flags + uint8 m_distances[NUM_PATHCONNECTIONS]; +#endif int16 m_carPathConnections[NUM_PATHCONNECTIONS]; + int32 m_numPathNodes; int32 m_numCarPathNodes; int32 m_numPedPathNodes; @@ -194,12 +293,20 @@ public: void RegisterMapObject(CTreadable *mapObject); void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing); void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight); +#ifndef MIAMI void CalcNodeCoors(int16 x, int16 y, int16 z, int32 id, CVector *out); +#else + void CalcNodeCoors(float x, float y, float z, int32 id, CVector *out); +#endif bool LoadPathFindData(void); void PreparePathData(void); void CountFloodFillGroups(uint8 type); void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo, - float unk, CTempDetachedNode *detachednodes, int unused); +#ifndef MIAMI + float maxdist, CTempDetachedNode *detachednodes, int32 numDetached); +#else + float maxdist, CPathInfoForObject *detachednodes, int32 numDetached); +#endif bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); } @@ -217,25 +324,56 @@ public: void MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId); void MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2); void PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2); +#ifndef MIAMI int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false); +#else +//--MIAMI: TODO: check callers for new arguments + int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false, bool ignoreFlagB4 = false, bool bWaterPath = false); +#endif int32 FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY); float FindNodeOrientationForCarPlacement(int32 nodeId); float FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards); bool NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled = false); bool GeneratePedCreationCoors(float x, float y, float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, CMatrix *camMatrix); +#ifndef MIAMI CTreadable *FindRoadObjectClosestToCoors(CVector coors, uint8 type); +#endif void FindNextNodeWandering(uint8, CVector, CPathNode**, CPathNode**, uint8, uint8*); void DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *numNodes, int16 maxNumNodes, CVehicle *vehicle, float *dist, float distLimit, int32 forcedTargetNode); bool TestCoorsCloseness(CVector target, uint8 type, CVector start); void Save(uint8 *buf, uint32 *size); void Load(uint8 *buf, uint32 size); +#ifdef MIAMI + CPathNode *GetNode(int16 index); + int16 GetIndex(CPathNode *node); + + uint16 ConnectedNode(int id) { return m_connections[id] & 0x3FFF; } + bool ConnectionCrossesRoad(int id) { return !!(m_connections[id] & 0x8000); } + bool ConnectionHasTrafficLight(int id) { return !!(m_connections[id] & 0x4000); } + void ConnectionSetTrafficLight(int id) { m_connections[id] |= 0x4000; } +#else + uint16 ConnectedNode(int id) { return m_connections[id]; } + bool ConnectionCrossesRoad(int id) { return m_connectionFlags[id].bCrossesRoad; } + bool ConnectionHasTrafficLight(int id) { return m_connectionFlags[id].bTrafficLight; } + void ConnectionSetTrafficLight(int id) { m_connectionFlags[id].bTrafficLight = true; } +#endif + void DisplayPathData(void); }; +#ifndef MIAMI static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error"); +#endif extern CPathFind ThePaths; +#ifdef MIAMI +inline CPathNode *CPathNode::GetPrev(void) { return ThePaths.GetNode(prevIndex); } +inline CPathNode *CPathNode::GetNext(void) { return ThePaths.GetNode(nextIndex); } +inline void CPathNode::SetPrev(CPathNode *node) { prevIndex = ThePaths.GetIndex(node); } +inline void CPathNode::SetNext(CPathNode *node) { nextIndex = ThePaths.GetIndex(node); } +#endif + extern bool gbShowPedPaths; extern bool gbShowCarPaths; extern bool gbShowCarPathsLinks; diff --git a/src/control/Restart.cpp b/src/control/Restart.cpp index 2a31f8f1..5a322cdb 100644 --- a/src/control/Restart.cpp +++ b/src/control/Restart.cpp @@ -108,7 +108,7 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f // if we still didn't find anything, find closest path node if (closestPoint == NUM_RESTART_POINTS) { - *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos; + *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].GetPosition(); *outHeading = 0.0f; printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z); } else { @@ -156,7 +156,7 @@ CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, flo // if we still didn't find anything, find closest path node if (closestPoint == NUM_RESTART_POINTS) { printf("Couldn't find a police restart zone near the player\n"); - *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos; + *outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].GetPosition(); *outHeading = 0.0f; } else { *outPos = PoliceRestartPoints[closestPoint]; diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp index 65625d8c..322cc1df 100644 --- a/src/control/RoadBlocks.cpp +++ b/src/control/RoadBlocks.cpp @@ -15,19 +15,40 @@ #include "CarCtrl.h" #include "General.h" +#ifndef MIAMI +#define ROADBLOCKDIST (80.0f) +#else +#define ROADBLOCKDIST (90.0f) +#endif + int16 CRoadBlocks::NumRoadBlocks; +#ifndef MIAMI int16 CRoadBlocks::RoadBlockObjects[NUMROADBLOCKS]; +#else +int16 CRoadBlocks::RoadBlockNodes[NUMROADBLOCKS]; +#endif bool CRoadBlocks::InOrOut[NUMROADBLOCKS]; +//--MIAMI: TODO: script roadblocks void CRoadBlocks::Init(void) { + int i; NumRoadBlocks = 0; - for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) { - if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) { +#ifndef MIAMI + for (i = 0; i < ThePaths.m_numMapObjects; i++) { + if (ThePaths.m_objectFlags[i] & UseInRoadBlock) { +#else + for(i = 0; i < ThePaths.m_numCarPathNodes; i++){ + if(ThePaths.m_pathNodes[i].bUseInRoadBlock && ThePaths.m_pathNodes[i].numLinks == 2){ +#endif if (NumRoadBlocks < NUMROADBLOCKS) { InOrOut[NumRoadBlocks] = true; - RoadBlockObjects[NumRoadBlocks] = objId; +#ifndef MIAMI + RoadBlockObjects[NumRoadBlocks] = i; +#else + RoadBlockNodes[NumRoadBlocks] = i; +#endif NumRoadBlocks++; } else { #ifndef MASTER @@ -38,7 +59,6 @@ CRoadBlocks::Init(void) } } } - } void @@ -85,7 +105,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType pCopPed->SetIdle(); pCopPed->bKindaStayInSamePlace = true; pCopPed->bNotAllowedToDuck = false; - pCopPed->m_wRoadblockNode = roadBlockNode; + pCopPed->m_nRoadblockNode = roadBlockNode; pCopPed->bCrouchWhenShooting = roadBlockType != 2; if (pEntityToAttack) { pCopPed->m_pPointGunAt = pEntityToAttack; @@ -107,18 +127,20 @@ CRoadBlocks::GenerateRoadBlocks(void) uint32 frame = CTimer::GetFrameCounter() & 0xF; int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16; const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16; - int16 numRoadBlocks = CRoadBlocks::NumRoadBlocks; - if (CRoadBlocks::NumRoadBlocks >= maxRoadBlocks) - numRoadBlocks = maxRoadBlocks; - for (; nRoadblockNode < numRoadBlocks; nRoadblockNode++) { - CTreadable *mapObject = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[nRoadblockNode]]; + for (; nRoadblockNode < Min(NumRoadBlocks, maxRoadBlocks); nRoadblockNode++) { +#ifndef MIAMI + CTreadable *mapObject = ThePaths.m_mapObjects[RoadBlockObjects[nRoadblockNode]]; CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition(); - if (vecDistance.x > -80.0f && vecDistance.x < 80.0f && - vecDistance.y > -80.0f && vecDistance.y < 80.0f && - vecDistance.Magnitude() < 80.0f) { - if (!CRoadBlocks::InOrOut[nRoadblockNode]) { - CRoadBlocks::InOrOut[nRoadblockNode] = true; +#else + CVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[nRoadblockNode].GetPosition(); +#endif + if (vecDistance.x > -ROADBLOCKDIST && vecDistance.x < ROADBLOCKDIST && + vecDistance.y > -ROADBLOCKDIST && vecDistance.y < ROADBLOCKDIST && + vecDistance.Magnitude() < ROADBLOCKDIST) { + if (!InOrOut[nRoadblockNode]) { + InOrOut[nRoadblockNode] = true; if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) { +#ifndef MIAMI CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted; float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x; int32 vehicleId = MI_POLICE; @@ -146,7 +168,7 @@ CRoadBlocks::GenerateRoadBlocks(void) nRoadblockType = !nRoadblockType; offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI); } - if (ThePaths.m_objectFlags[CRoadBlocks::RoadBlockObjects[nRoadblockNode]] & ObjectEastWest) + if (ThePaths.m_objectFlags[RoadBlockObjects[nRoadblockNode]] & ObjectEastWest) offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f); else offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f); @@ -188,10 +210,13 @@ CRoadBlocks::GenerateRoadBlocks(void) } } } +#endif } } } else { - CRoadBlocks::InOrOut[nRoadblockNode] = false; + InOrOut[nRoadblockNode] = false; } } + +//--MIAMI: TODO script roadblocks } diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h index 0f0c1882..439fd6e7 100644 --- a/src/control/RoadBlocks.h +++ b/src/control/RoadBlocks.h @@ -7,7 +7,11 @@ class CRoadBlocks { public: static int16 NumRoadBlocks; +#ifndef MIAMI static int16 RoadBlockObjects[NUMROADBLOCKS]; +#else + static int16 RoadBlockNodes[NUMROADBLOCKS]; +#endif static bool InOrOut[NUMROADBLOCKS]; static void Init(void); diff --git a/src/control/Script.cpp b/src/control/Script.cpp index dbae1f21..48269a2b 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -5559,7 +5559,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f)]; - *(CVector*)&ScriptParams[0] = pNode->pos; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); StoreParameters(&m_nIp, 3); return 0; } @@ -5570,7 +5570,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f)]; - *(CVector*)&ScriptParams[0] = pNode->pos; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); StoreParameters(&m_nIp, 3); return 0; } @@ -8247,7 +8247,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); int node = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); - *(CVector*)&ScriptParams[0] = ThePaths.m_pathNodes[node].pos; + *(CVector*)&ScriptParams[0] = ThePaths.m_pathNodes[node].GetPosition(); *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacement(node); StoreParameters(&m_nIp, 4); return 0; @@ -9329,7 +9329,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) float destY = *(float*)&ScriptParams[4]; int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); CPathNode* pNode = &ThePaths.m_pathNodes[nid]; - *(CVector*)&ScriptParams[0] = pNode->pos; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, true); StoreParameters(&m_nIp, 4); return 0; @@ -9344,7 +9344,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) float destY = *(float*)&ScriptParams[4]; int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); CPathNode* pNode = &ThePaths.m_pathNodes[nid]; - *(CVector*)&ScriptParams[0] = pNode->pos; + *(CVector*)&ScriptParams[0] = pNode->GetPosition(); *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, false); StoreParameters(&m_nIp, 4); return 0; diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp index 44e14bdc..f2dd6814 100644 --- a/src/control/TrafficLights.cpp +++ b/src/control/TrafficLights.cpp @@ -150,12 +150,12 @@ CTrafficLights::ScanForLightsOnMap(void) // Check cars for(i = 0; i < ThePaths.m_numCarPathLinks; i++){ - CVector2D dist = ThePaths.m_carPathLinks[i].pos - light->GetPosition(); + CVector2D dist = ThePaths.m_carPathLinks[i].GetPosition() - light->GetPosition(); float dotY = Abs(DotProduct2D(dist, light->GetForward())); // forward is direction of car light float dotX = DotProduct2D(dist, light->GetRight()); // towards base of light // it has to be on the correct side of the node and also not very far away if(dotX < 0.0f && dotX > -15.0f && dotY < 3.0f){ - float dz = ThePaths.m_pathNodes[ThePaths.m_carPathLinks[i].pathNodeIndex].pos.z - + float dz = ThePaths.m_pathNodes[ThePaths.m_carPathLinks[i].pathNodeIndex].GetZ() - light->GetPosition().z; if(dz < 15.0f){ ThePaths.m_carPathLinks[i].trafficLightType = FindTrafficLightType(light); @@ -182,16 +182,16 @@ CTrafficLights::ScanForLightsOnMap(void) // Check peds for(i = ThePaths.m_numCarPathNodes; i < ThePaths.m_numPathNodes; i++){ float dist1, dist2; - dist1 = Abs(ThePaths.m_pathNodes[i].pos.x - light->GetPosition().x) + - Abs(ThePaths.m_pathNodes[i].pos.y - light->GetPosition().y); + dist1 = Abs(ThePaths.m_pathNodes[i].GetX() - light->GetPosition().x) + + Abs(ThePaths.m_pathNodes[i].GetY() - light->GetPosition().y); if(dist1 < 50.0f){ for(l = 0; l < ThePaths.m_pathNodes[i].numLinks; l++){ j = ThePaths.m_pathNodes[i].firstLink + l; - if(ThePaths.m_connectionFlags[j].bCrossesRoad){ - dist2 = Abs(ThePaths.m_pathNodes[j].pos.x - light->GetPosition().x) + - Abs(ThePaths.m_pathNodes[j].pos.y - light->GetPosition().y); + if(ThePaths.ConnectionCrossesRoad(j)){ + dist2 = Abs(ThePaths.m_pathNodes[j].GetX() - light->GetPosition().x) + + Abs(ThePaths.m_pathNodes[j].GetY() - light->GetPosition().y); if(dist1 < 15.0f || dist2 < 15.0f) - ThePaths.m_connectionFlags[j].bTrafficLight = true; + ThePaths.ConnectionSetTrafficLight(j); } } } @@ -213,8 +213,8 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop) if(alwaysStop || (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ - float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, - ThePaths.m_carPathLinks[node].dir); + float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(), + ThePaths.m_carPathLinks[node].GetDirection()); if(vehicle->AutoPilot.m_nNextDirection == -1){ if(dist > 0.0f && dist < 8.0f) return true; @@ -233,8 +233,8 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop) if(alwaysStop || (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ - float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, - ThePaths.m_carPathLinks[node].dir); + float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(), + ThePaths.m_carPathLinks[node].GetDirection()); if(vehicle->AutoPilot.m_nCurrentDirection == -1){ if(dist > 0.0f && dist < 8.0f) return true; @@ -254,8 +254,8 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop) if(alwaysStop || (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ - float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, - ThePaths.m_carPathLinks[node].dir); + float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(), + ThePaths.m_carPathLinks[node].GetDirection()); if(vehicle->AutoPilot.m_nPreviousDirection == -1){ if(dist > 0.0f && dist < 6.0f) return true; @@ -273,8 +273,12 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop) bool CTrafficLights::ShouldCarStopForBridge(CVehicle *vehicle) { +#ifdef GTA_BRIDGE return ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nNextPathNodeInfo].bBridgeLights && !ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nCurrentPathNodeInfo].bBridgeLights; +#else + return false; +#endif } int |