implemented most of vice city path system

This commit is contained in:
aap 2020-05-03 15:57:57 +02:00
parent ff4af35292
commit 702da55ec9
20 changed files with 1149 additions and 367 deletions

View File

@ -12,17 +12,17 @@ void CAutoPilot::ModifySpeed(float speed)
float positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve; float positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve;
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[m_nNextPathNodeInfo];
float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.x; float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].GetDirX();
float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.y; float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].GetDirY();
float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.x; float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].GetDirX();
float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.y; float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].GetDirY();
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurrentLink->pos.x + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY, pCurrentLink->GetX() + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY,
pCurrentLink->pos.y - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX, pCurrentLink->GetY() - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->pos.x + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->GetX() + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->pos.y - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->GetY() - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,

View File

@ -281,7 +281,7 @@ CCarCtrl::GenerateOneRandomCar()
CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId]; CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];
CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId]; CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];
while (idInNode < pCurNode->numLinks && while (idInNode < pCurNode->numLinks &&
ThePaths.m_connections[idInNode + pCurNode->firstLink] != nextNodeId) ThePaths.ConnectedNode(idInNode + pCurNode->firstLink) != nextNodeId)
idInNode++; idInNode++;
int16 connectionId = ThePaths.m_carPathConnections[idInNode + pCurNode->firstLink]; int16 connectionId = ThePaths.m_carPathConnections[idInNode + pCurNode->firstLink];
CCarPathLink* pPathLink = &ThePaths.m_carPathLinks[connectionId]; CCarPathLink* pPathLink = &ThePaths.m_carPathLinks[connectionId];
@ -356,7 +356,7 @@ CCarCtrl::GenerateOneRandomCar()
pCar->AutoPilot.m_nNextLane = pCar->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad; pCar->AutoPilot.m_nNextLane = pCar->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad;
CColBox* boundingBox = &CModelInfo::GetModelInfo(pCar->GetModelIndex())->GetColModel()->boundingBox; CColBox* boundingBox = &CModelInfo::GetModelInfo(pCar->GetModelIndex())->GetColModel()->boundingBox;
float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2; 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. */ /* 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. */ /* Otherwise put it at least in a way that full vehicle length fits between two nodes. */
if (distanceBetweenNodes / 2 < carLength) if (distanceBetweenNodes / 2 < carLength)
@ -376,8 +376,8 @@ CCarCtrl::GenerateOneRandomCar()
nextConnection = ThePaths.m_carPathConnections[newLink + pCurNode->firstLink]; nextConnection = ThePaths.m_carPathConnections[newLink + pCurNode->firstLink];
} }
pCar->AutoPilot.m_nCurrentPathNodeInfo = nextConnection; pCar->AutoPilot.m_nCurrentPathNodeInfo = nextConnection;
pCar->AutoPilot.m_nCurrentDirection = (ThePaths.m_connections[newLink + pCurNode->firstLink] >= curNodeId) ? 1 : -1; pCar->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(newLink + pCurNode->firstLink) >= curNodeId) ? 1 : -1;
CVector2D vecBetweenNodes = pNextNode->pos - pCurNode->pos; CVector2D vecBetweenNodes = pNextNode->GetPosition() - pCurNode->GetPosition();
float forwardX, forwardY; float forwardX, forwardY;
float distBetweenNodes = vecBetweenNodes.Magnitude(); float distBetweenNodes = vecBetweenNodes.Magnitude();
if (distanceBetweenNodes == 0.0f){ if (distanceBetweenNodes == 0.0f){
@ -393,25 +393,25 @@ CCarCtrl::GenerateOneRandomCar()
pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f); pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f);
pCar->GetUp() = CVector(0.0f, 0.0f, 1.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 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].dir.y; 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].dir.x; 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].dir.y; float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].GetDirY();
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo];
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurrentLink->pos.x + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurrentLink->GetX() + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurrentLink->pos.y - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurrentLink->GetY() - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->pos.x + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->GetX() + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->pos.y - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->GetY() - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurrentLink->dir.x * pCar->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurrentLink->GetDirX() * pCar->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurrentLink->dir.y * pCar->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurrentLink->GetDirY() * pCar->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dir.x * pCar->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->GetDirX() * pCar->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dir.y * 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. */ /* 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( pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -442,10 +442,10 @@ CCarCtrl::GenerateOneRandomCar()
&positionIncludingCurve, &positionIncludingCurve,
&directionIncludingCurve &directionIncludingCurve
); );
CVector vectorBetweenNodes = pCurNode->pos - pNextNode->pos; CVector vectorBetweenNodes = pCurNode->GetPosition() - pNextNode->GetPosition();
CVector finalPosition = positionIncludingCurve + vectorBetweenNodes * 2.0f / vectorBetweenNodes.Magnitude(); CVector finalPosition = positionIncludingCurve + vectorBetweenNodes * 2.0f / vectorBetweenNodes.Magnitude();
finalPosition.z = positionBetweenNodes * pNextNode->pos.z + finalPosition.z = positionBetweenNodes * pNextNode->GetZ() +
(1.0f - positionBetweenNodes) * pCurNode->pos.z; (1.0f - positionBetweenNodes) * pCurNode->GetZ();
float groundZ = INFINITE_Z; float groundZ = INFINITE_Z;
CColPoint colPoint; CColPoint colPoint;
CEntity* pEntity; CEntity* pEntity;
@ -763,17 +763,17 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
return; return;
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
float currentPathLinkForwardX = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; float currentPathLinkForwardX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;
float currentPathLinkForwardY = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; float currentPathLinkForwardY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;
float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;
float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f); CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f); CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
@ -1490,7 +1490,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
} }
} }
nextLink = CGeneral::GetRandomNumber() % totalLinks; 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); direction = FindPathDirection(prevNode, curNode, pVehicle->AutoPilot.m_nNextRouteNode);
pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]]; pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];
goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0; goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0;
@ -1508,7 +1508,7 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
} }
} }
nextLink = CGeneral::GetRandomNumber() % totalLinks; 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]]; pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];
goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0; 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 (attempt >= ATTEMPTS_TO_FIND_NEXT_NODE) {
/* If we failed again, remove no U-turn limitation and remove randomness */ /* If we failed again, remove no U-turn limitation and remove randomness */
for (nextLink = 0; nextLink < totalLinks; nextLink++) { 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]]; pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];
goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0; goingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0;
if (!goingAgainstOneWayRoad) { if (!goingAgainstOneWayRoad) {
@ -1553,12 +1553,12 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nNextDirection = -1; pVehicle->AutoPilot.m_nNextDirection = -1;
lanesOnNextNode = pNextLink->numRightLanes; lanesOnNextNode = pNextLink->numRightLanes;
} }
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX();
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX();
if (lanesOnNextNode >= 0){ if (lanesOnNextNode >= 0){
if ((CGeneral::GetRandomNumber() & 0x600) == 0){ if ((CGeneral::GetRandomNumber() & 0x600) == 0){
/* 25% chance vehicle will try to switch lane */ /* 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 (dist.MagnitudeSqr() >= SQR(14.0f)){
if (CGeneral::GetRandomTrueFalse()) if (CGeneral::GetRandomTrueFalse())
pVehicle->AutoPilot.m_nNextLane += 1; pVehicle->AutoPilot.m_nNextLane += 1;
@ -1574,17 +1574,17 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
if (pVehicle->AutoPilot.m_bStayInFastLane) if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0; pVehicle->AutoPilot.m_nNextLane = 0;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */ pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */
pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH), pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH),
pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dir.y * 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. */ /* 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( pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -1600,8 +1600,8 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
uint8 CCarCtrl::FindPathDirection(int32 prevNode, int32 curNode, int32 nextNode) uint8 CCarCtrl::FindPathDirection(int32 prevNode, int32 curNode, int32 nextNode)
{ {
CVector2D prevToCur = ThePaths.m_pathNodes[curNode].pos - ThePaths.m_pathNodes[prevNode].pos; CVector2D prevToCur = ThePaths.m_pathNodes[curNode].GetPosition() - ThePaths.m_pathNodes[prevNode].GetPosition();
CVector2D curToNext = ThePaths.m_pathNodes[nextNode].pos - ThePaths.m_pathNodes[curNode].pos; CVector2D curToNext = ThePaths.m_pathNodes[nextNode].GetPosition() - ThePaths.m_pathNodes[curNode].GetPosition();
float distPrevToCur = prevToCur.Magnitude(); float distPrevToCur = prevToCur.Magnitude();
if (distPrevToCur == 0.0f) if (distPrevToCur == 0.0f)
return PATH_DIRECTION_NONE; return PATH_DIRECTION_NONE;
@ -1638,7 +1638,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
CPathNode* pTargetNode; CPathNode* pTargetNode;
int16 numNodes; int16 numNodes;
float distanceToTargetNode; float distanceToTargetNode;
#ifndef REMOVE_TREADABLE_PATHFIND #ifndef MIAMI
if (pTarget && pTarget->m_pCurGroundEntity && if (pTarget && pTarget->m_pCurGroundEntity &&
pTarget->m_pCurGroundEntity->IsBuilding() && pTarget->m_pCurGroundEntity->IsBuilding() &&
((CBuilding*)pTarget->m_pCurGroundEntity)->GetIsATreadable() && ((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]; int node = pCurrentMapObject->m_nodeIndices[0][i];
if (node < 0) if (node < 0)
break; break;
float dist = (ThePaths.m_pathNodes[node].pos - pTarget->GetPosition()).Magnitude(); float dist = (ThePaths.m_pathNodes[node].GetPosition() - pTarget->GetPosition()).Magnitude();
if (dist < minDist){ if (dist < minDist){
minDist = dist; minDist = dist;
closestNode = node; closestNode = node;
} }
} }
ThePaths.DoPathSearch(0, pCurNode->pos, curNode, ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
#ifdef FIX_PATHFIND_BUG #ifdef FIX_PATHFIND_BUG
CVector(targetX, targetY, targetZ), CVector(targetX, targetY, targetZ),
#else #else
CVector(targetX, targetY, 0.0f), CVector(targetX, targetY, 0.0f),
#endif #endif
&pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, closestNode); &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, closestNode);
}else{ }else
#endif #endif
ThePaths.DoPathSearch(0, pCurNode->pos, curNode, {
ThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,
#ifdef FIX_PATHFIND_BUG #ifdef FIX_PATHFIND_BUG
CVector(targetX, targetY, targetZ), CVector(targetX, targetY, targetZ),
#else #else
CVector(targetX, targetY, 0.0f), CVector(targetX, targetY, 0.0f),
#endif #endif
&pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1); &pTargetNode, &numNodes, 1, pVehicle, &distanceToTargetNode, 999999.9f, -1);
#ifndef REMOVE_TREADABLE_PATHFIND
} }
#endif
int newNextNode; int newNextNode;
int nextLink; int nextLink;
if (numNodes != 1 || pTargetNode == pCurNode){ if (numNodes != 1 || pTargetNode == pCurNode){
@ -1684,11 +1685,11 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
int numLinks = pCurNode->numLinks; int numLinks = pCurNode->numLinks;
newNextNode = 0; newNextNode = 0;
for (int i = 0; i < numLinks; i++){ 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) if (conNode == prevNode && i > 1)
continue; continue;
CPathNode* pTestNode = &ThePaths.m_pathNodes[conNode]; 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 = LimitRadianAngle(angle - currentAngle);
angle = ABS(angle); angle = ABS(angle);
if (angle < lowestAngleChange){ if (angle < lowestAngleChange){
@ -1700,7 +1701,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
}else{ }else{
nextLink = 0; nextLink = 0;
newNextNode = pTargetNode - ThePaths.m_pathNodes; 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]; 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; pVehicle->AutoPilot.m_nNextDirection = -1;
lanesOnNextNode = pNextLink->numRightLanes; lanesOnNextNode = pNextLink->numRightLanes;
} }
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX();
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y; float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY();
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX();
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y; float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirY();
if (lanesOnNextNode >= 0) { if (lanesOnNextNode >= 0) {
CVector2D dist = pNextPathNode->pos - pCurNode->pos; CVector2D dist = pNextPathNode->GetPosition() - pCurNode->GetPosition();
if (dist.MagnitudeSqr() >= SQR(7.0f)){ if (dist.MagnitudeSqr() >= SQR(7.0f)){
/* 25% chance vehicle will try to switch lane */ /* 25% chance vehicle will try to switch lane */
/* No lane switching if following car from far away */ /* 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) if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0; pVehicle->AutoPilot.m_nNextLane = 0;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dir.y * 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. */ /* 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( pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -1801,7 +1802,7 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nCurrentDirection = pVehicle->AutoPilot.m_nNextDirection; pVehicle->AutoPilot.m_nCurrentDirection = pVehicle->AutoPilot.m_nNextDirection;
pVehicle->AutoPilot.m_nCurrentLane = pVehicle->AutoPilot.m_nNextLane; pVehicle->AutoPilot.m_nCurrentLane = pVehicle->AutoPilot.m_nNextLane;
int nextLink = 0; 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]]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink]];
pVehicle->AutoPilot.m_nNextPathNodeInfo = 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; pVehicle->AutoPilot.m_nNextDirection = -1;
lanesOnNextNode = pNextLink->numRightLanes; lanesOnNextNode = pNextLink->numRightLanes;
} }
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x; float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX();
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y; float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY();
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x; float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX();
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y; float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirY();
if (lanesOnNextNode >= 0) { 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 (dist.MagnitudeSqr() >= SQR(7.0f) && (CGeneral::GetRandomNumber() & 0x600) == 0) {
if (CGeneral::GetRandomTrueFalse()) if (CGeneral::GetRandomTrueFalse())
pVehicle->AutoPilot.m_nNextLane += 1; pVehicle->AutoPilot.m_nNextLane += 1;
@ -1835,17 +1836,17 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
if (pVehicle->AutoPilot.m_bStayInFastLane) if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0; pVehicle->AutoPilot.m_nNextLane = 0;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dir.y * 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. */ /* 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( pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -2199,16 +2200,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
forward.Normalise(); forward.Normalise();
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
CVector2D currentPathLinkForward(pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection, CVector2D currentPathLinkForward(pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection,
pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection); pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection);
float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;
float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;
CVector2D positionOnCurrentLinkIncludingLane( CVector2D positionOnCurrentLinkIncludingLane(
pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,
pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
CVector2D positionOnNextLinkIncludingLane( CVector2D positionOnNextLinkIncludingLane(
pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX); pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX);
CVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane; CVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane;
float scalarDistanceToNextNode = distanceToNextNode.Magnitude(); float scalarDistanceToNextNode = distanceToNextNode.Magnitude();
CVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane; CVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane;
@ -2237,16 +2238,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
} }
pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
scalarDistanceToNextNode = CVector2D( scalarDistanceToNextNode = CVector2D(
pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x, pCurrentLink->GetX() + ((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->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude();
pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
currentPathLinkForward.x = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection; currentPathLinkForward.x = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;
currentPathLinkForward.y = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection; currentPathLinkForward.y = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;
nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection; nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;
nextPathLinkForwardY = pNextLink->dir.y * 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.x = pCurrentLink->GetX() + ((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.y = pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x;
CVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f; CVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f;
if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){ if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){
projectedPosition.x = positionOnCurrentLinkIncludingLane.x; projectedPosition.x = positionOnCurrentLinkIncludingLane.x;
@ -2288,8 +2289,8 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
CCarAI::CarHasReasonToStop(pVehicle); CCarAI::CarHasReasonToStop(pVehicle);
speedStyleMultiplier = 0.0f; speedStyleMultiplier = 0.0f;
} }
CVector2D trajectory(pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, CVector2D trajectory(pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,
pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
trajectory -= pVehicle->GetPosition(); trajectory -= pVehicle->GetPosition();
float speedAngleMultiplier = FindSpeedMultiplier( float speedAngleMultiplier = FindSpeedMultiplier(
CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward, CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward,
@ -2503,9 +2504,9 @@ void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle)
int prevNodeId = -1; int prevNodeId = -1;
float minDistance = 999999.9f; float minDistance = 999999.9f;
for (int i = 0; i < pNode->numLinks; i++){ 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]; CPathNode* pCandidateNode = &ThePaths.m_pathNodes[candidateId];
float distance = (pCandidateNode->pos - pNode->pos).Magnitude2D(); float distance = (pCandidateNode->GetPosition() - pNode->GetPosition()).Magnitude2D();
if (distance < minDistance){ if (distance < minDistance){
minDistance = distance; minDistance = distance;
prevNodeId = candidateId; prevNodeId = candidateId;
@ -2517,7 +2518,7 @@ void CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle)
CPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNodeId]; CPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNodeId];
if (forward.x == 0.0f && forward.y == 0.0f) if (forward.x == 0.0f && forward.y == 0.0f)
forward.x = 1.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; int tmp;
tmp = prevNodeId; tmp = prevNodeId;
prevNodeId = nodeId; prevNodeId = nodeId;
@ -2557,7 +2558,7 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
int nextLink; int nextLink;
CPathNode* pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode]; CPathNode* pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode];
for (nextLink = 0; nextLink < 12; nextLink++) 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; break;
pVehicle->AutoPilot.m_nNextPathNodeInfo = ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink]; pVehicle->AutoPilot.m_nNextPathNodeInfo = ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink];
pVehicle->AutoPilot.m_nNextDirection = (pVehicle->AutoPilot.m_nCurrentRouteNode >= pVehicle->AutoPilot.m_nNextRouteNode) ? 1 : -1; 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_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) 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->GetForward() = CVector(direction.x, direction.y, 0.0f);
pVehicle->GetRight() = CVector(direction.y, -direction.x, 0.0f); pVehicle->GetRight() = CVector(direction.y, -direction.x, 0.0f);
pVehicle->GetUp() = CVector(0.0f, 0.0f, 1.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; float groundZ = INFINITE_Z;
CColPoint colPoint; CColPoint colPoint;
CEntity* pEntity; CEntity* pEntity;

File diff suppressed because it is too large Load Diff

View File

@ -55,6 +55,7 @@ public:
struct CPathNode struct CPathNode
{ {
#ifndef MIAMI
CVector pos; CVector pos;
CPathNode *prev; CPathNode *prev;
CPathNode *next; CPathNode *next;
@ -69,31 +70,55 @@ struct CPathNode
uint8 bBetweenLevels : 1; uint8 bBetweenLevels : 1;
int8 group; 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 prevIndex;
int16 nextIndex; int16 nextIndex;
int16 x; int16 x;
int16 y; int16 y;
int16 z; int16 z;
int16 distance; int16 distance; // in path search
int16 firstLink; int16 firstLink;
int8 width; int8 width;
int8 group; int8 group;
int8 numLinks : 4;
int8 bDeadEnd : 1; uint8 numLinks : 4;
int8 bTurnedOff : 1; // flag 8 in node info uint8 bDeadEnd : 1;
int8 flagA40 : 1; // flag 20 in node info uint8 bDisabled : 1;
int8 flagA80 : 1; // flag 4 in node info uint8 bBetweenLevels : 1;
int8 flagB1 : 1; // flag 10 in node info uint8 bUseInRoadBlock : 1;
int8 flagB2 : 1; // flag 2 in node info
int8 flagB4 : 1; uint8 bWaterPath : 1;
int8 speedLimit : 2; // speed limit uint8 flagB2 : 1; // flag 2 in node info, always zero
int8 flagB20 : 1; uint8 flagB4 : 1; // where is this set?
int8 flagB40 : 1; uint8 speedLimit : 2;
int8 flagB80 : 1; //uint8 flagB20 : 1;
int8 spawnRate : 4; //uint8 flagB40 : 1;
int8 flagsC : 4; //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 union CConnectionFlags
@ -107,6 +132,7 @@ union CConnectionFlags
struct CCarPathLink struct CCarPathLink
{ {
#ifndef MIAMI
CVector2D pos; CVector2D pos;
CVector2D dir; CVector2D dir;
int16 pathNodeIndex; int16 pathNodeIndex;
@ -117,6 +143,33 @@ struct CCarPathLink
uint8 bBridgeLights : 1; uint8 bBridgeLights : 1;
// more? // 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() float OneWayLaneOffset()
{ {
if (numLeftLanes == 0) if (numLeftLanes == 0)
@ -127,8 +180,10 @@ struct CCarPathLink
} }
}; };
// This is what we're reading from the files, only temporary
struct CPathInfoForObject struct CPathInfoForObject
{ {
#ifndef MIAMI
int16 x; int16 x;
int16 y; int16 y;
int16 z; int16 z;
@ -137,6 +192,28 @@ struct CPathInfoForObject
int8 numLeftLanes; int8 numLeftLanes;
int8 numRightLanes; int8 numRightLanes;
uint8 crossing : 1; 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 *InfoForTileCars;
extern CPathInfoForObject *InfoForTilePeds; extern CPathInfoForObject *InfoForTilePeds;
@ -144,6 +221,7 @@ extern CPathInfoForObject *InfoForTilePeds;
struct CTempNode struct CTempNode
{ {
CVector pos; CVector pos;
#ifndef MIAMI
float dirX; float dirX;
float dirY; float dirY;
int16 link1; int16 link1;
@ -151,34 +229,55 @@ struct CTempNode
int8 numLeftLanes; int8 numLeftLanes;
int8 numRightLanes; int8 numRightLanes;
int8 linkState; 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 struct CTempDetachedNode // unused
{ {
uint8 foo[20]; uint8 foo[20];
}; };
#endif
class CPathFind class CPathFind
{ {
public: 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]; CPathNode m_pathNodes[NUM_PATHNODES];
CCarPathLink m_carPathLinks[NUM_CARPATHLINKS]; CCarPathLink m_carPathLinks[NUM_CARPATHLINKS];
CTreadable *m_mapObjects[NUM_MAPOBJECTS]; CTreadable *m_mapObjects[NUM_MAPOBJECTS];
#ifndef MIAMI
uint8 m_objectFlags[NUM_MAPOBJECTS]; uint8 m_objectFlags[NUM_MAPOBJECTS];
int16 m_connections[NUM_PATHCONNECTIONS]; int16 m_connections[NUM_PATHCONNECTIONS];
int16 m_distances[NUM_PATHCONNECTIONS]; int16 m_distances[NUM_PATHCONNECTIONS];
CConnectionFlags m_connectionFlags[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]; int16 m_carPathConnections[NUM_PATHCONNECTIONS];
int32 m_numPathNodes; int32 m_numPathNodes;
int32 m_numCarPathNodes; int32 m_numCarPathNodes;
int32 m_numPedPathNodes; int32 m_numPedPathNodes;
@ -194,12 +293,20 @@ public:
void RegisterMapObject(CTreadable *mapObject); 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 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); 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); 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); bool LoadPathFindData(void);
void PreparePathData(void); void PreparePathData(void);
void CountFloodFillGroups(uint8 type); void CountFloodFillGroups(uint8 type);
void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo, 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); } 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 MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId);
void MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2); 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); 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); 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); int32 FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY);
float FindNodeOrientationForCarPlacement(int32 nodeId); float FindNodeOrientationForCarPlacement(int32 nodeId);
float FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards); 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 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); 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); CTreadable *FindRoadObjectClosestToCoors(CVector coors, uint8 type);
#endif
void FindNextNodeWandering(uint8, CVector, CPathNode**, CPathNode**, uint8, uint8*); 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); 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); bool TestCoorsCloseness(CVector target, uint8 type, CVector start);
void Save(uint8 *buf, uint32 *size); void Save(uint8 *buf, uint32 *size);
void Load(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); void DisplayPathData(void);
}; };
#ifndef MIAMI
static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error"); static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error");
#endif
extern CPathFind ThePaths; 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 gbShowPedPaths;
extern bool gbShowCarPaths; extern bool gbShowCarPaths;
extern bool gbShowCarPathsLinks; extern bool gbShowCarPathsLinks;

View File

@ -108,7 +108,7 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f
// if we still didn't find anything, find closest path node // if we still didn't find anything, find closest path node
if (closestPoint == NUM_RESTART_POINTS) { 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; *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); 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 { } 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 we still didn't find anything, find closest path node
if (closestPoint == NUM_RESTART_POINTS) { if (closestPoint == NUM_RESTART_POINTS) {
printf("Couldn't find a police restart zone near the player\n"); 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; *outHeading = 0.0f;
} else { } else {
*outPos = PoliceRestartPoints[closestPoint]; *outPos = PoliceRestartPoints[closestPoint];

View File

@ -15,19 +15,40 @@
#include "CarCtrl.h" #include "CarCtrl.h"
#include "General.h" #include "General.h"
#ifndef MIAMI
#define ROADBLOCKDIST (80.0f)
#else
#define ROADBLOCKDIST (90.0f)
#endif
int16 CRoadBlocks::NumRoadBlocks; int16 CRoadBlocks::NumRoadBlocks;
#ifndef MIAMI
int16 CRoadBlocks::RoadBlockObjects[NUMROADBLOCKS]; int16 CRoadBlocks::RoadBlockObjects[NUMROADBLOCKS];
#else
int16 CRoadBlocks::RoadBlockNodes[NUMROADBLOCKS];
#endif
bool CRoadBlocks::InOrOut[NUMROADBLOCKS]; bool CRoadBlocks::InOrOut[NUMROADBLOCKS];
//--MIAMI: TODO: script roadblocks
void void
CRoadBlocks::Init(void) CRoadBlocks::Init(void)
{ {
int i;
NumRoadBlocks = 0; NumRoadBlocks = 0;
for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) { #ifndef MIAMI
if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) { 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) { if (NumRoadBlocks < NUMROADBLOCKS) {
InOrOut[NumRoadBlocks] = true; InOrOut[NumRoadBlocks] = true;
RoadBlockObjects[NumRoadBlocks] = objId; #ifndef MIAMI
RoadBlockObjects[NumRoadBlocks] = i;
#else
RoadBlockNodes[NumRoadBlocks] = i;
#endif
NumRoadBlocks++; NumRoadBlocks++;
} else { } else {
#ifndef MASTER #ifndef MASTER
@ -38,7 +59,6 @@ CRoadBlocks::Init(void)
} }
} }
} }
} }
void void
@ -85,7 +105,7 @@ CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType
pCopPed->SetIdle(); pCopPed->SetIdle();
pCopPed->bKindaStayInSamePlace = true; pCopPed->bKindaStayInSamePlace = true;
pCopPed->bNotAllowedToDuck = false; pCopPed->bNotAllowedToDuck = false;
pCopPed->m_wRoadblockNode = roadBlockNode; pCopPed->m_nRoadblockNode = roadBlockNode;
pCopPed->bCrouchWhenShooting = roadBlockType != 2; pCopPed->bCrouchWhenShooting = roadBlockType != 2;
if (pEntityToAttack) { if (pEntityToAttack) {
pCopPed->m_pPointGunAt = pEntityToAttack; pCopPed->m_pPointGunAt = pEntityToAttack;
@ -107,18 +127,20 @@ CRoadBlocks::GenerateRoadBlocks(void)
uint32 frame = CTimer::GetFrameCounter() & 0xF; uint32 frame = CTimer::GetFrameCounter() & 0xF;
int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16; int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16; const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
int16 numRoadBlocks = CRoadBlocks::NumRoadBlocks; for (; nRoadblockNode < Min(NumRoadBlocks, maxRoadBlocks); nRoadblockNode++) {
if (CRoadBlocks::NumRoadBlocks >= maxRoadBlocks) #ifndef MIAMI
numRoadBlocks = maxRoadBlocks; CTreadable *mapObject = ThePaths.m_mapObjects[RoadBlockObjects[nRoadblockNode]];
for (; nRoadblockNode < numRoadBlocks; nRoadblockNode++) {
CTreadable *mapObject = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[nRoadblockNode]];
CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition(); CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition();
if (vecDistance.x > -80.0f && vecDistance.x < 80.0f && #else
vecDistance.y > -80.0f && vecDistance.y < 80.0f && CVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[nRoadblockNode].GetPosition();
vecDistance.Magnitude() < 80.0f) { #endif
if (!CRoadBlocks::InOrOut[nRoadblockNode]) { if (vecDistance.x > -ROADBLOCKDIST && vecDistance.x < ROADBLOCKDIST &&
CRoadBlocks::InOrOut[nRoadblockNode] = true; 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) { if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) {
#ifndef MIAMI
CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted; CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted;
float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x; float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x;
int32 vehicleId = MI_POLICE; int32 vehicleId = MI_POLICE;
@ -146,7 +168,7 @@ CRoadBlocks::GenerateRoadBlocks(void)
nRoadblockType = !nRoadblockType; nRoadblockType = !nRoadblockType;
offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI); 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); offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f);
else else
offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f); offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f);
@ -188,10 +210,13 @@ CRoadBlocks::GenerateRoadBlocks(void)
} }
} }
} }
#endif
} }
} }
} else { } else {
CRoadBlocks::InOrOut[nRoadblockNode] = false; InOrOut[nRoadblockNode] = false;
} }
} }
//--MIAMI: TODO script roadblocks
} }

View File

@ -7,7 +7,11 @@ class CRoadBlocks
{ {
public: public:
static int16 NumRoadBlocks; static int16 NumRoadBlocks;
#ifndef MIAMI
static int16 RoadBlockObjects[NUMROADBLOCKS]; static int16 RoadBlockObjects[NUMROADBLOCKS];
#else
static int16 RoadBlockNodes[NUMROADBLOCKS];
#endif
static bool InOrOut[NUMROADBLOCKS]; static bool InOrOut[NUMROADBLOCKS];
static void Init(void); static void Init(void);

View File

@ -5559,7 +5559,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
if (pos.z <= MAP_Z_LOW_LIMIT) if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f)]; 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); StoreParameters(&m_nIp, 3);
return 0; return 0;
} }
@ -5570,7 +5570,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
if (pos.z <= MAP_Z_LOW_LIMIT) if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
CPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f)]; 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); StoreParameters(&m_nIp, 3);
return 0; return 0;
} }
@ -8247,7 +8247,7 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
if (pos.z <= MAP_Z_LOW_LIMIT) if (pos.z <= MAP_Z_LOW_LIMIT)
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
int node = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); 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); *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacement(node);
StoreParameters(&m_nIp, 4); StoreParameters(&m_nIp, 4);
return 0; return 0;
@ -9329,7 +9329,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
float destY = *(float*)&ScriptParams[4]; float destY = *(float*)&ScriptParams[4];
int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);
CPathNode* pNode = &ThePaths.m_pathNodes[nid]; 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); *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, true);
StoreParameters(&m_nIp, 4); StoreParameters(&m_nIp, 4);
return 0; return 0;
@ -9344,7 +9344,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
float destY = *(float*)&ScriptParams[4]; float destY = *(float*)&ScriptParams[4];
int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true); int32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);
CPathNode* pNode = &ThePaths.m_pathNodes[nid]; 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); *(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, false);
StoreParameters(&m_nIp, 4); StoreParameters(&m_nIp, 4);
return 0; return 0;

View File

@ -150,12 +150,12 @@ CTrafficLights::ScanForLightsOnMap(void)
// Check cars // Check cars
for(i = 0; i < ThePaths.m_numCarPathLinks; i++){ 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 dotY = Abs(DotProduct2D(dist, light->GetForward())); // forward is direction of car light
float dotX = DotProduct2D(dist, light->GetRight()); // towards base of 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 // 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){ 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; light->GetPosition().z;
if(dz < 15.0f){ if(dz < 15.0f){
ThePaths.m_carPathLinks[i].trafficLightType = FindTrafficLightType(light); ThePaths.m_carPathLinks[i].trafficLightType = FindTrafficLightType(light);
@ -182,16 +182,16 @@ CTrafficLights::ScanForLightsOnMap(void)
// Check peds // Check peds
for(i = ThePaths.m_numCarPathNodes; i < ThePaths.m_numPathNodes; i++){ for(i = ThePaths.m_numCarPathNodes; i < ThePaths.m_numPathNodes; i++){
float dist1, dist2; float dist1, dist2;
dist1 = Abs(ThePaths.m_pathNodes[i].pos.x - light->GetPosition().x) + dist1 = Abs(ThePaths.m_pathNodes[i].GetX() - light->GetPosition().x) +
Abs(ThePaths.m_pathNodes[i].pos.y - light->GetPosition().y); Abs(ThePaths.m_pathNodes[i].GetY() - light->GetPosition().y);
if(dist1 < 50.0f){ if(dist1 < 50.0f){
for(l = 0; l < ThePaths.m_pathNodes[i].numLinks; l++){ for(l = 0; l < ThePaths.m_pathNodes[i].numLinks; l++){
j = ThePaths.m_pathNodes[i].firstLink + l; j = ThePaths.m_pathNodes[i].firstLink + l;
if(ThePaths.m_connectionFlags[j].bCrossesRoad){ if(ThePaths.ConnectionCrossesRoad(j)){
dist2 = Abs(ThePaths.m_pathNodes[j].pos.x - light->GetPosition().x) + dist2 = Abs(ThePaths.m_pathNodes[j].GetX() - light->GetPosition().x) +
Abs(ThePaths.m_pathNodes[j].pos.y - light->GetPosition().y); Abs(ThePaths.m_pathNodes[j].GetY() - light->GetPosition().y);
if(dist1 < 15.0f || dist2 < 15.0f) 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 || if(alwaysStop ||
(type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
(type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(),
ThePaths.m_carPathLinks[node].dir); ThePaths.m_carPathLinks[node].GetDirection());
if(vehicle->AutoPilot.m_nNextDirection == -1){ if(vehicle->AutoPilot.m_nNextDirection == -1){
if(dist > 0.0f && dist < 8.0f) if(dist > 0.0f && dist < 8.0f)
return true; return true;
@ -233,8 +233,8 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
if(alwaysStop || if(alwaysStop ||
(type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
(type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(),
ThePaths.m_carPathLinks[node].dir); ThePaths.m_carPathLinks[node].GetDirection());
if(vehicle->AutoPilot.m_nCurrentDirection == -1){ if(vehicle->AutoPilot.m_nCurrentDirection == -1){
if(dist > 0.0f && dist < 8.0f) if(dist > 0.0f && dist < 8.0f)
return true; return true;
@ -254,8 +254,8 @@ CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
if(alwaysStop || if(alwaysStop ||
(type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN || (type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
(type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){ (type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos, float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(),
ThePaths.m_carPathLinks[node].dir); ThePaths.m_carPathLinks[node].GetDirection());
if(vehicle->AutoPilot.m_nPreviousDirection == -1){ if(vehicle->AutoPilot.m_nPreviousDirection == -1){
if(dist > 0.0f && dist < 6.0f) if(dist > 0.0f && dist < 6.0f)
return true; return true;

View File

@ -106,7 +106,7 @@ void TankCheat()
CAutomobile *tank = new CAutomobile(MI_RHINO, MISSION_VEHICLE); CAutomobile *tank = new CAutomobile(MI_RHINO, MISSION_VEHICLE);
#endif #endif
if (tank != nil) { if (tank != nil) {
CVector pos = ThePaths.m_pathNodes[node].pos; CVector pos = ThePaths.m_pathNodes[node].GetPosition();
pos.z += 4.0f; pos.z += 4.0f;
tank->SetPosition(pos); tank->SetPosition(pos);
tank->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f)); tank->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f));

View File

@ -1618,7 +1618,7 @@ CWorld::RemoveFallenPeds(void)
if(ped->CharCreatedBy != RANDOM_CHAR || ped->IsPlayer()) { if(ped->CharCreatedBy != RANDOM_CHAR || ped->IsPlayer()) {
int closestNode = ThePaths.FindNodeClosestToCoors(ped->GetPosition(), PATH_PED, int closestNode = ThePaths.FindNodeClosestToCoors(ped->GetPosition(), PATH_PED,
999999.9f, false, false); 999999.9f, false, false);
CVector newPos = ThePaths.m_pathNodes[closestNode].pos; CVector newPos = ThePaths.m_pathNodes[closestNode].GetPosition();
newPos.z += 2.0f; newPos.z += 2.0f;
ped->Teleport(newPos); ped->Teleport(newPos);
ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
@ -1642,7 +1642,7 @@ CWorld::RemoveFallenCars(void)
(veh->pDriver && veh->pDriver->IsPlayer())) { (veh->pDriver && veh->pDriver->IsPlayer())) {
int closestNode = ThePaths.FindNodeClosestToCoors(veh->GetPosition(), PATH_CAR, int closestNode = ThePaths.FindNodeClosestToCoors(veh->GetPosition(), PATH_CAR,
999999.9f, false, false); 999999.9f, false, false);
CVector newPos = ThePaths.m_pathNodes[closestNode].pos; CVector newPos = ThePaths.m_pathNodes[closestNode].GetPosition();
newPos.z += 3.0f; newPos.z += 3.0f;
veh->Teleport(newPos); veh->Teleport(newPos);
veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);

View File

@ -41,10 +41,17 @@ enum Config {
NUMTEMPOBJECTS = 30, NUMTEMPOBJECTS = 30,
// Path data // Path data
#ifndef MIAMI
NUM_PATHNODES = 4930, NUM_PATHNODES = 4930,
NUM_CARPATHLINKS = 2076, NUM_CARPATHLINKS = 2076,
NUM_MAPOBJECTS = 1250, NUM_MAPOBJECTS = 1250,
NUM_PATHCONNECTIONS = 10260, NUM_PATHCONNECTIONS = 10260,
#else
NUM_PATHNODES = 9650,
NUM_CARPATHLINKS = 3500,
NUM_MAPOBJECTS = 1250,
NUM_PATHCONNECTIONS = 20400,
#endif
// Link list lengths // Link list lengths
NUMALPHALIST = 20, NUMALPHALIST = 20,
@ -110,7 +117,11 @@ enum Config {
NUMMODELSPERPEDGROUP = 8, NUMMODELSPERPEDGROUP = 8,
NUMSHOTINFOS = 100, NUMSHOTINFOS = 100,
#ifndef MIAMI
NUMROADBLOCKS = 600, NUMROADBLOCKS = 600,
#else
NUMROADBLOCKS = 300,
#endif
NUMVISIBLEENTITIES = 2000, NUMVISIBLEENTITIES = 2000,
NUMINVISIBLEENTITIES = 150, NUMINVISIBLEENTITIES = 150,

View File

@ -118,7 +118,7 @@ SpawnCar(int id)
if(CModelInfo::IsBoatModel(id)) if(CModelInfo::IsBoatModel(id))
v->SetPosition(TheCamera.GetPosition() + TheCamera.GetForward()*15.0f); v->SetPosition(TheCamera.GetPosition() + TheCamera.GetForward()*15.0f);
else else
v->SetPosition(ThePaths.m_pathNodes[node].pos); v->SetPosition(ThePaths.m_pathNodes[node].GetPosition());
v->GetMatrix().GetPosition().z += 4.0f; v->GetMatrix().GetPosition().z += 4.0f;
v->SetOrientation(0.0f, 0.0f, 3.49f); v->SetOrientation(0.0f, 0.0f, 3.49f);

View File

@ -267,6 +267,7 @@ void
CPhysical::AddCollisionRecord_Treadable(CEntity *ent) CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
{ {
if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){ if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){
#ifndef MIAMI
CTreadable *t = (CTreadable*)ent; CTreadable *t = (CTreadable*)ent;
if(t->m_nodeIndices[PATH_PED][0] >= 0 || if(t->m_nodeIndices[PATH_PED][0] >= 0 ||
t->m_nodeIndices[PATH_PED][1] >= 0 || t->m_nodeIndices[PATH_PED][1] >= 0 ||
@ -278,6 +279,7 @@ CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
t->m_nodeIndices[PATH_CAR][2] >= 0 || t->m_nodeIndices[PATH_CAR][2] >= 0 ||
t->m_nodeIndices[PATH_CAR][3] >= 0) t->m_nodeIndices[PATH_CAR][3] >= 0)
m_treadable[PATH_CAR] = t; m_treadable[PATH_CAR] = t;
#endif
} }
} }

View File

@ -8,8 +8,12 @@ public:
static void *operator new(size_t); static void *operator new(size_t);
static void operator delete(void*, size_t); static void operator delete(void*, size_t);
#ifndef MIAMI
int16 m_nodeIndices[2][12]; // first car, then ped int16 m_nodeIndices[2][12]; // first car, then ped
#endif
bool GetIsATreadable(void) { return true; } bool GetIsATreadable(void) { return true; }
}; };
#ifndef MIAMI
static_assert(sizeof(CTreadable) == 0x94, "CTreadable: error"); static_assert(sizeof(CTreadable) == 0x94, "CTreadable: error");
#endif

View File

@ -73,7 +73,7 @@ CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
// VC also initializes in here, but as nil // VC also initializes in here, but as nil
#ifdef FIX_BUGS #ifdef FIX_BUGS
m_wRoadblockNode = -1; m_nRoadblockNode = -1;
#endif #endif
} }
@ -305,9 +305,9 @@ CCopPed::CopAI(void)
m_bZoneDisabled = true; m_bZoneDisabled = true;
m_bIsDisabledCop = true; m_bIsDisabledCop = true;
#ifdef FIX_BUGS #ifdef FIX_BUGS
m_wRoadblockNode = -1; m_nRoadblockNode = -1;
#else #else
m_wRoadblockNode = 0; m_nRoadblockNode = 0;
#endif #endif
bKindaStayInSamePlace = true; bKindaStayInSamePlace = true;
bIsRunning = false; bIsRunning = false;
@ -424,9 +424,15 @@ CCopPed::CopAI(void)
// VC checks for != nil compared to buggy behaviour of III. I check for != -1 here. // VC checks for != nil compared to buggy behaviour of III. I check for != -1 here.
#ifdef VC_PED_PORTS #ifdef VC_PED_PORTS
float dotProd; float dotProd;
if (m_wRoadblockNode != -1) { if (m_nRoadblockNode != -1) {
CTreadable *roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_wRoadblockNode]]; #ifndef MIAMI
CTreadable *roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_nRoadblockNode]];
dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), GetPosition() - roadBlockRoad->GetPosition()); dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), GetPosition() - roadBlockRoad->GetPosition());
#else
// TODO: check this, i'm only getting this compile here....
CPathNode *roadBlockNode = &ThePaths.m_pathNodes[CRoadBlocks::RoadBlockNodes[m_nRoadblockNode]];
dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockNode->GetPosition(), GetPosition() - roadBlockNode->GetPosition());
#endif
} else } else
dotProd = -1.0f; dotProd = -1.0f;
@ -437,10 +443,10 @@ CCopPed::CopAI(void)
float copRoadDotProd, targetRoadDotProd; float copRoadDotProd, targetRoadDotProd;
#else #else
float copRoadDotProd = 1.0f, targetRoadDotProd = 1.0f; float copRoadDotProd = 1.0f, targetRoadDotProd = 1.0f;
if (m_wRoadblockNode != -1) if (m_nRoadblockNode != -1)
#endif #endif
{ {
CTreadable* roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_wRoadblockNode]]; CTreadable* roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_nRoadblockNode]];
CVector2D roadFwd = roadBlockRoad->GetForward(); CVector2D roadFwd = roadBlockRoad->GetForward();
copRoadDotProd = DotProduct2D(GetPosition() - roadBlockRoad->GetPosition(), roadFwd); copRoadDotProd = DotProduct2D(GetPosition() - roadBlockRoad->GetPosition(), roadFwd);
targetRoadDotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), roadFwd); targetRoadDotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), roadFwd);

View File

@ -12,7 +12,7 @@ enum eCopType
class CCopPed : public CPed class CCopPed : public CPed
{ {
public: public:
int16 m_wRoadblockNode; int16 m_nRoadblockNode;
float m_fDistanceToTarget; float m_fDistanceToTarget;
bool m_bIsInPursuit; bool m_bIsInPursuit;
bool m_bIsDisabledCop; bool m_bIsDisabledCop;

View File

@ -4504,7 +4504,7 @@ CPed::RestorePreviousState(void)
bIsRunning = false; bIsRunning = false;
if (!bFindNewNodeAfterStateRestore) { if (!bFindNewNodeAfterStateRestore) {
if (m_pNextPathNode) { if (m_pNextPathNode) {
CVector diff = m_pNextPathNode->pos - GetPosition(); CVector diff = m_pNextPathNode->GetPosition() - GetPosition();
if (diff.MagnitudeSqr() < sq(7.0f)) { if (diff.MagnitudeSqr() < sq(7.0f)) {
SetMoveState(PEDMOVE_WALK); SetMoveState(PEDMOVE_WALK);
break; break;
@ -6925,10 +6925,10 @@ SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVecto
{ {
for (int i = 0; i < node->numLinks; i++) { for (int i = 0; i < node->numLinks; i++) {
CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.m_connections[i + node->firstLink]]; CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.ConnectedNode(i + node->firstLink)];
if (testNode && testNode != closeNode && testNode != closeNode2) { if (testNode && testNode != closeNode && testNode != closeNode2) {
CVector2D posDiff(ped->m_vecSeekPos - testNode->pos); CVector2D posDiff(ped->m_vecSeekPos - testNode->GetPosition());
float dist = posDiff.MagnitudeSqr(); float dist = posDiff.MagnitudeSqr();
if (farDist.MagnitudeSqr() > dist) { if (farDist.MagnitudeSqr() > dist) {
@ -6969,16 +6969,16 @@ CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords)
CVector2D seekPosDist (m_vecSeekPos - ourPos); CVector2D seekPosDist (m_vecSeekPos - ourPos);
CPathNode *closestNode = &ThePaths.m_pathNodes[closestNodeId]; CPathNode *closestNode = &ThePaths.m_pathNodes[closestNodeId];
CVector2D closeDist(m_vecSeekPos - closestNode->pos); CVector2D closeDist(m_vecSeekPos - closestNode->GetPosition());
SelectClosestNodeForSeek(this, closestNode, closeDist, seekPosDist, closestNode, nil); SelectClosestNodeForSeek(this, closestNode, closeDist, seekPosDist, closestNode, nil);
// Above function decided that going to the next node is more logical than seeking the object. // Above function decided that going to the next node is more logical than seeking the object.
if (m_pNextPathNode) { if (m_pNextPathNode) {
CVector pathToNextNode = m_pNextPathNode->pos - ourPos; CVector pathToNextNode = m_pNextPathNode->GetPosition() - ourPos;
if (pathToNextNode.MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) { if (pathToNextNode.MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) {
*bestCoords = m_pNextPathNode->pos; *bestCoords = m_pNextPathNode->GetPosition();
return true; return true;
} }
m_pNextPathNode = nil; m_pNextPathNode = nil;
@ -7671,7 +7671,7 @@ CPed::Flee(void)
} }
if (m_pNextPathNode) { if (m_pNextPathNode) {
m_vecSeekPos = m_pNextPathNode->pos; m_vecSeekPos = m_pNextPathNode->GetPosition();
if (m_nMoveState == PEDMOVE_RUN) if (m_nMoveState == PEDMOVE_RUN)
bIsRunning = true; bIsRunning = true;
@ -9653,17 +9653,17 @@ CPed::ProcessControl(void)
if (m_nPedState == PED_WANDER_PATH) { if (m_nPedState == PED_WANDER_PATH) {
m_pNextPathNode = &ThePaths.m_pathNodes[closestNodeId]; m_pNextPathNode = &ThePaths.m_pathNodes[closestNodeId];
angleToFace = CGeneral::GetRadianAngleBetweenPoints( angleToFace = CGeneral::GetRadianAngleBetweenPoints(
m_pNextPathNode->pos.x, m_pNextPathNode->pos.y, m_pNextPathNode->GetX(), m_pNextPathNode->GetY(),
GetPosition().x, GetPosition().y); GetPosition().x, GetPosition().y);
} else { } else {
if (ThePaths.m_pathNodes[closestNodeId].pos.x == 0.0f if (ThePaths.m_pathNodes[closestNodeId].GetX() == 0.0f
|| ThePaths.m_pathNodes[closestNodeId].pos.y == 0.0f) { || ThePaths.m_pathNodes[closestNodeId].GetY() == 0.0f) {
posToHead = (3.0f * m_vecDamageNormal) + GetPosition(); posToHead = (3.0f * m_vecDamageNormal) + GetPosition();
posToHead.x += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f; posToHead.x += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f;
posToHead.y += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f; posToHead.y += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f;
} else { } else {
posToHead.x = ThePaths.m_pathNodes[closestNodeId].pos.x; posToHead.x = ThePaths.m_pathNodes[closestNodeId].GetX();
posToHead.y = ThePaths.m_pathNodes[closestNodeId].pos.y; posToHead.y = ThePaths.m_pathNodes[closestNodeId].GetY();
} }
angleToFace = CGeneral::GetRadianAngleBetweenPoints( angleToFace = CGeneral::GetRadianAngleBetweenPoints(
posToHead.x, posToHead.y, posToHead.x, posToHead.y,
@ -9674,12 +9674,12 @@ CPed::ProcessControl(void)
} }
} else { } else {
angleToFace = CGeneral::GetRadianAngleBetweenPoints( angleToFace = CGeneral::GetRadianAngleBetweenPoints(
ThePaths.m_pathNodes[closestNodeId].pos.x, ThePaths.m_pathNodes[closestNodeId].GetX(),
ThePaths.m_pathNodes[closestNodeId].pos.y, ThePaths.m_pathNodes[closestNodeId].GetY(),
GetPosition().x, GetPosition().x,
GetPosition().y); GetPosition().y);
CVector2D distToNode = ThePaths.m_pathNodes[closestNodeId].pos - GetPosition(); CVector2D distToNode = ThePaths.m_pathNodes[closestNodeId].GetPosition() - GetPosition();
CVector2D distToSeekPos = m_vecSeekPos - GetPosition(); CVector2D distToSeekPos = m_vecSeekPos - GetPosition();
if (DotProduct2D(distToNode, distToSeekPos) < 0.0f) { if (DotProduct2D(distToNode, distToSeekPos) < 0.0f) {
@ -12904,7 +12904,7 @@ CPed::ProcessObjective(void)
if (closestNode >= 0) { if (closestNode >= 0) {
int16 colliding; int16 colliding;
CWorld::FindObjectsKindaColliding( CWorld::FindObjectsKindaColliding(
ThePaths.m_pathNodes[closestNode].pos, 10.0f, true, &colliding, 2, nil, false, true, true, false, false); ThePaths.m_pathNodes[closestNode].GetPosition(), 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
if (!colliding) { if (!colliding) {
CZoneInfo zoneInfo; CZoneInfo zoneInfo;
int chosenCarClass; int chosenCarClass;
@ -12912,7 +12912,7 @@ CPed::ProcessObjective(void)
int chosenModel = CCarCtrl::ChooseModel(&zoneInfo, &ourPos, &chosenCarClass); int chosenModel = CCarCtrl::ChooseModel(&zoneInfo, &ourPos, &chosenCarClass);
CAutomobile *newVeh = new CAutomobile(chosenModel, RANDOM_VEHICLE); CAutomobile *newVeh = new CAutomobile(chosenModel, RANDOM_VEHICLE);
if (newVeh) { if (newVeh) {
newVeh->GetPosition() = ThePaths.m_pathNodes[closestNode].pos; newVeh->GetPosition() = ThePaths.m_pathNodes[closestNode].GetPosition();
newVeh->GetPosition().z += 4.0f; newVeh->GetPosition().z += 4.0f;
newVeh->SetHeading(DEGTORAD(200.0f)); newVeh->SetHeading(DEGTORAD(200.0f));
newVeh->SetStatus(STATUS_ABANDONED); newVeh->SetStatus(STATUS_ABANDONED);
@ -13112,7 +13112,7 @@ CPed::ProcessObjective(void)
FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords); FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
if (m_pNextPathNode) if (m_pNextPathNode)
m_vecSeekPos = m_pNextPathNode->pos; m_vecSeekPos = m_pNextPathNode->GetPosition();
SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
} else { } else {
@ -13666,7 +13666,7 @@ CPed::ProcessObjective(void)
FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords); FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
if (m_pNextPathNode) if (m_pNextPathNode)
m_vecSeekPos = m_pNextPathNode->pos; m_vecSeekPos = m_pNextPathNode->GetPosition();
} }
SetSeek(m_vecSeekPos, m_distanceToCountSeekDone); SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
} }
@ -17324,7 +17324,7 @@ CPed::WanderPath(void)
if (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE) if (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE)
SetMoveState(PEDMOVE_WALK); SetMoveState(PEDMOVE_WALK);
} }
m_vecSeekPos = m_pNextPathNode->pos; m_vecSeekPos = m_pNextPathNode->GetPosition();
m_vecSeekPos.z += 1.0f; m_vecSeekPos.z += 1.0f;
// Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him. // Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him.

View File

@ -198,6 +198,7 @@ CRenderer::RenderRoads(void)
t = (CTreadable*)ms_aVisibleEntityPtrs[i]; t = (CTreadable*)ms_aVisibleEntityPtrs[i];
if(t->IsBuilding() && t->GetIsATreadable()){ if(t->IsBuilding() && t->GetIsATreadable()){
#ifndef MASTER #ifndef MASTER
#ifndef MIAMI
if(gbShowCarRoadGroups || gbShowPedRoadGroups){ if(gbShowCarRoadGroups || gbShowPedRoadGroups){
int ind = 0; int ind = 0;
if(gbShowCarRoadGroups) if(gbShowCarRoadGroups)
@ -206,6 +207,7 @@ CRenderer::RenderRoads(void)
ind += ThePaths.m_pathNodes[t->m_nodeIndices[PATH_PED][0]].group; ind += ThePaths.m_pathNodes[t->m_nodeIndices[PATH_PED][0]].group;
SetAmbientColoursToIndicateRoadGroup(ind); SetAmbientColoursToIndicateRoadGroup(ind);
} }
#endif
#endif #endif
RenderOneRoad(t); RenderOneRoad(t);
#ifndef MASTER #ifndef MASTER

View File

@ -4146,7 +4146,7 @@ CAutomobile::HasCarStoppedBecauseOfLight(void)
if(AutoPilot.m_nCurrentRouteNode && AutoPilot.m_nNextRouteNode){ if(AutoPilot.m_nCurrentRouteNode && AutoPilot.m_nNextRouteNode){
CPathNode *curnode = &ThePaths.m_pathNodes[AutoPilot.m_nCurrentRouteNode]; CPathNode *curnode = &ThePaths.m_pathNodes[AutoPilot.m_nCurrentRouteNode];
for(i = 0; i < curnode->numLinks; i++) for(i = 0; i < curnode->numLinks; i++)
if(ThePaths.m_connections[curnode->firstLink + i] == AutoPilot.m_nNextRouteNode) if(ThePaths.ConnectedNode(curnode->firstLink + i) == AutoPilot.m_nNextRouteNode)
break; break;
if(i < curnode->numLinks && if(i < curnode->numLinks &&
ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3) ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3)
@ -4156,7 +4156,7 @@ CAutomobile::HasCarStoppedBecauseOfLight(void)
if(AutoPilot.m_nCurrentRouteNode && AutoPilot.m_nPrevRouteNode){ if(AutoPilot.m_nCurrentRouteNode && AutoPilot.m_nPrevRouteNode){
CPathNode *curnode = &ThePaths.m_pathNodes[AutoPilot.m_nCurrentRouteNode]; CPathNode *curnode = &ThePaths.m_pathNodes[AutoPilot.m_nCurrentRouteNode];
for(i = 0; i < curnode->numLinks; i++) for(i = 0; i < curnode->numLinks; i++)
if(ThePaths.m_connections[curnode->firstLink + i] == AutoPilot.m_nPrevRouteNode) if(ThePaths.ConnectedNode(curnode->firstLink + i) == AutoPilot.m_nPrevRouteNode)
break; break;
if(i < curnode->numLinks && if(i < curnode->numLinks &&
ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3) ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3)