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