From 702da55ec9d0e8e02df25a26390a113e452676e3 Mon Sep 17 00:00:00 2001
From: aap <aap@papnet.eu>
Date: Sun, 3 May 2020 15:57:57 +0200
Subject: [PATCH] implemented most of vice city path system

---
 src/control/AutoPilot.cpp     |  16 +-
 src/control/CarCtrl.cpp       | 209 ++++----
 src/control/PathFind.cpp      | 899 ++++++++++++++++++++++++++++------
 src/control/PathFind.h        | 194 ++++++--
 src/control/Restart.cpp       |   4 +-
 src/control/RoadBlocks.cpp    |  59 ++-
 src/control/RoadBlocks.h      |   4 +
 src/control/Script.cpp        |  10 +-
 src/control/TrafficLights.cpp |  28 +-
 src/core/Pad.cpp              |   2 +-
 src/core/World.cpp            |   4 +-
 src/core/config.h             |  11 +
 src/core/re3.cpp              |   2 +-
 src/entities/Physical.cpp     |   2 +
 src/entities/Treadable.h      |   4 +
 src/peds/CopPed.cpp           |  20 +-
 src/peds/CopPed.h             |   2 +-
 src/peds/Ped.cpp              |  40 +-
 src/render/Renderer.cpp       |   2 +
 src/vehicles/Automobile.cpp   |   4 +-
 20 files changed, 1149 insertions(+), 367 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, 50);
+		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, 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;
diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp
index c4c4a69e..da86d15e 100644
--- a/src/core/Pad.cpp
+++ b/src/core/Pad.cpp
@@ -106,7 +106,7 @@ void TankCheat()
 		CAutomobile *tank = new CAutomobile(MI_RHINO, MISSION_VEHICLE);
 #endif
 		if (tank != nil) {
-			CVector pos = ThePaths.m_pathNodes[node].pos;
+			CVector pos = ThePaths.m_pathNodes[node].GetPosition();
 			pos.z += 4.0f;
 			tank->SetPosition(pos);
 			tank->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f));
diff --git a/src/core/World.cpp b/src/core/World.cpp
index 30d086df..2833c59c 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -1618,7 +1618,7 @@ CWorld::RemoveFallenPeds(void)
 				if(ped->CharCreatedBy != RANDOM_CHAR || ped->IsPlayer()) {
 					int closestNode = ThePaths.FindNodeClosestToCoors(ped->GetPosition(), PATH_PED,
 					                                                  999999.9f, false, false);
-					CVector newPos = ThePaths.m_pathNodes[closestNode].pos;
+					CVector newPos = ThePaths.m_pathNodes[closestNode].GetPosition();
 					newPos.z += 2.0f;
 					ped->Teleport(newPos);
 					ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
@@ -1642,7 +1642,7 @@ CWorld::RemoveFallenCars(void)
 				   (veh->pDriver && veh->pDriver->IsPlayer())) {
 					int closestNode = ThePaths.FindNodeClosestToCoors(veh->GetPosition(), PATH_CAR,
 					                                                  999999.9f, false, false);
-					CVector newPos = ThePaths.m_pathNodes[closestNode].pos;
+					CVector newPos = ThePaths.m_pathNodes[closestNode].GetPosition();
 					newPos.z += 3.0f;
 					veh->Teleport(newPos);
 					veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
diff --git a/src/core/config.h b/src/core/config.h
index 7c1fab5b..86189920 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -41,10 +41,17 @@ enum Config {
 	NUMTEMPOBJECTS = 30,
 
 	// Path data
+#ifndef MIAMI
 	NUM_PATHNODES = 4930,
 	NUM_CARPATHLINKS = 2076,
 	NUM_MAPOBJECTS = 1250,
 	NUM_PATHCONNECTIONS = 10260,
+#else
+	NUM_PATHNODES = 9650,
+	NUM_CARPATHLINKS = 3500,
+	NUM_MAPOBJECTS = 1250,
+	NUM_PATHCONNECTIONS = 20400,
+#endif
 
 	// Link list lengths
 	NUMALPHALIST = 20,
@@ -110,7 +117,11 @@ enum Config {
 	NUMMODELSPERPEDGROUP = 8,
 	NUMSHOTINFOS = 100,
 
+#ifndef MIAMI
 	NUMROADBLOCKS = 600,
+#else
+	NUMROADBLOCKS = 300,
+#endif
 
 	NUMVISIBLEENTITIES = 2000,
 	NUMINVISIBLEENTITIES = 150,
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index e6409523..44253c14 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -118,7 +118,7 @@ SpawnCar(int id)
 		if(CModelInfo::IsBoatModel(id))
 			v->SetPosition(TheCamera.GetPosition() + TheCamera.GetForward()*15.0f);
 		else
-			v->SetPosition(ThePaths.m_pathNodes[node].pos);
+			v->SetPosition(ThePaths.m_pathNodes[node].GetPosition());
 
 		v->GetMatrix().GetPosition().z += 4.0f;
 		v->SetOrientation(0.0f, 0.0f, 3.49f);
diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp
index 842104a4..af08ced6 100644
--- a/src/entities/Physical.cpp
+++ b/src/entities/Physical.cpp
@@ -267,6 +267,7 @@ void
 CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
 {
 	if(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){
+#ifndef MIAMI
 		CTreadable *t = (CTreadable*)ent;
 		if(t->m_nodeIndices[PATH_PED][0] >= 0 ||
 		   t->m_nodeIndices[PATH_PED][1] >= 0 ||
@@ -278,6 +279,7 @@ CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
 		   t->m_nodeIndices[PATH_CAR][2] >= 0 ||
 		   t->m_nodeIndices[PATH_CAR][3] >= 0)
 			m_treadable[PATH_CAR] = t;
+#endif
 	}
 }
 
diff --git a/src/entities/Treadable.h b/src/entities/Treadable.h
index 9e4de59a..78f69c8a 100644
--- a/src/entities/Treadable.h
+++ b/src/entities/Treadable.h
@@ -8,8 +8,12 @@ public:
 	static void *operator new(size_t);
 	static void operator delete(void*, size_t);
 
+#ifndef MIAMI
 	int16 m_nodeIndices[2][12];	// first car, then ped
+#endif
 
 	bool GetIsATreadable(void) { return true; }
 };
+#ifndef MIAMI
 static_assert(sizeof(CTreadable) == 0x94, "CTreadable: error");
+#endif
diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp
index 7cea902d..8bfd807f 100644
--- a/src/peds/CopPed.cpp
+++ b/src/peds/CopPed.cpp
@@ -73,7 +73,7 @@ CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
 
 	// VC also initializes in here, but as nil
 #ifdef FIX_BUGS
-	m_wRoadblockNode = -1;
+	m_nRoadblockNode = -1;
 #endif
 }
 
@@ -305,9 +305,9 @@ CCopPed::CopAI(void)
 			m_bZoneDisabled = true;
 			m_bIsDisabledCop = true;
 #ifdef FIX_BUGS
-			m_wRoadblockNode = -1;
+			m_nRoadblockNode = -1;
 #else
-			m_wRoadblockNode = 0;
+			m_nRoadblockNode = 0;
 #endif
 			bKindaStayInSamePlace = true;
 			bIsRunning = false;
@@ -424,9 +424,15 @@ CCopPed::CopAI(void)
 						// VC checks for != nil compared to buggy behaviour of III. I check for != -1 here.
 #ifdef VC_PED_PORTS
 						float dotProd;
-						if (m_wRoadblockNode != -1) {
-							CTreadable *roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_wRoadblockNode]];
+						if (m_nRoadblockNode != -1) {
+#ifndef MIAMI
+							CTreadable *roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_nRoadblockNode]];
 							dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), GetPosition() - roadBlockRoad->GetPosition());
+#else
+							// TODO: check this, i'm only getting this compile here....
+							CPathNode *roadBlockNode = &ThePaths.m_pathNodes[CRoadBlocks::RoadBlockNodes[m_nRoadblockNode]];
+							dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockNode->GetPosition(), GetPosition() - roadBlockNode->GetPosition());
+#endif
 						} else
 							dotProd = -1.0f;
 
@@ -437,10 +443,10 @@ CCopPed::CopAI(void)
 						float copRoadDotProd, targetRoadDotProd;
 #else
 						float copRoadDotProd = 1.0f, targetRoadDotProd = 1.0f;
-						if (m_wRoadblockNode != -1)
+						if (m_nRoadblockNode != -1)
 #endif
 						{
-							CTreadable* roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_wRoadblockNode]];
+							CTreadable* roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_nRoadblockNode]];
 							CVector2D roadFwd = roadBlockRoad->GetForward();
 							copRoadDotProd = DotProduct2D(GetPosition() - roadBlockRoad->GetPosition(), roadFwd);
 							targetRoadDotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), roadFwd);
diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h
index e9780035..d63aef06 100644
--- a/src/peds/CopPed.h
+++ b/src/peds/CopPed.h
@@ -12,7 +12,7 @@ enum eCopType
 class CCopPed : public CPed
 {
 public:
-	int16 m_wRoadblockNode;
+	int16 m_nRoadblockNode;
 	float m_fDistanceToTarget;
 	bool m_bIsInPursuit;
 	bool m_bIsDisabledCop;
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index e7972541..cfd50a5d 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -4504,7 +4504,7 @@ CPed::RestorePreviousState(void)
 				bIsRunning = false;
 				if (!bFindNewNodeAfterStateRestore) {
 					if (m_pNextPathNode) {
-						CVector diff = m_pNextPathNode->pos - GetPosition();
+						CVector diff = m_pNextPathNode->GetPosition() - GetPosition();
 						if (diff.MagnitudeSqr() < sq(7.0f)) {
 							SetMoveState(PEDMOVE_WALK);
 							break;
@@ -6925,10 +6925,10 @@ SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVecto
 {
 	for (int i = 0; i < node->numLinks; i++) {
 
-		CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.m_connections[i + node->firstLink]];
+		CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.ConnectedNode(i + node->firstLink)];
 
 		if (testNode && testNode != closeNode && testNode != closeNode2) {
-			CVector2D posDiff(ped->m_vecSeekPos - testNode->pos);
+			CVector2D posDiff(ped->m_vecSeekPos - testNode->GetPosition());
 			float dist = posDiff.MagnitudeSqr();
 
 			if (farDist.MagnitudeSqr() > dist) {
@@ -6969,16 +6969,16 @@ CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords)
 	CVector2D seekPosDist (m_vecSeekPos - ourPos);
 
 	CPathNode *closestNode = &ThePaths.m_pathNodes[closestNodeId];
-	CVector2D closeDist(m_vecSeekPos - closestNode->pos);
+	CVector2D closeDist(m_vecSeekPos - closestNode->GetPosition());
 
 	SelectClosestNodeForSeek(this, closestNode, closeDist, seekPosDist, closestNode, nil);
 
 	// Above function decided that going to the next node is more logical than seeking the object.
 	if (m_pNextPathNode) {
 
-		CVector pathToNextNode = m_pNextPathNode->pos - ourPos;
+		CVector pathToNextNode = m_pNextPathNode->GetPosition() - ourPos;
 		if (pathToNextNode.MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) {
-			*bestCoords = m_pNextPathNode->pos;
+			*bestCoords = m_pNextPathNode->GetPosition();
 			return true;
 		}
 		m_pNextPathNode = nil;
@@ -7671,7 +7671,7 @@ CPed::Flee(void)
 			}
 
 			if (m_pNextPathNode) {
-				m_vecSeekPos = m_pNextPathNode->pos;
+				m_vecSeekPos = m_pNextPathNode->GetPosition();
 				if (m_nMoveState == PEDMOVE_RUN)
 					bIsRunning = true;
 
@@ -9653,17 +9653,17 @@ CPed::ProcessControl(void)
 											if (m_nPedState == PED_WANDER_PATH) {
 												m_pNextPathNode = &ThePaths.m_pathNodes[closestNodeId];
 												angleToFace = CGeneral::GetRadianAngleBetweenPoints(
-													m_pNextPathNode->pos.x, m_pNextPathNode->pos.y,
+													m_pNextPathNode->GetX(), m_pNextPathNode->GetY(),
 													GetPosition().x, GetPosition().y);
 											} else {
-												if (ThePaths.m_pathNodes[closestNodeId].pos.x == 0.0f
-													|| ThePaths.m_pathNodes[closestNodeId].pos.y == 0.0f) {
+												if (ThePaths.m_pathNodes[closestNodeId].GetX() == 0.0f
+													|| ThePaths.m_pathNodes[closestNodeId].GetY() == 0.0f) {
 													posToHead = (3.0f * m_vecDamageNormal) + GetPosition();
 													posToHead.x += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f;
 													posToHead.y += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f;
 												} else {
-													posToHead.x = ThePaths.m_pathNodes[closestNodeId].pos.x;
-													posToHead.y = ThePaths.m_pathNodes[closestNodeId].pos.y;
+													posToHead.x = ThePaths.m_pathNodes[closestNodeId].GetX();
+													posToHead.y = ThePaths.m_pathNodes[closestNodeId].GetY();
 												}
 												angleToFace = CGeneral::GetRadianAngleBetweenPoints(
 													posToHead.x, posToHead.y,
@@ -9674,12 +9674,12 @@ CPed::ProcessControl(void)
 											}
 										} else {
 											angleToFace = CGeneral::GetRadianAngleBetweenPoints(
-												ThePaths.m_pathNodes[closestNodeId].pos.x,
-												ThePaths.m_pathNodes[closestNodeId].pos.y,
+												ThePaths.m_pathNodes[closestNodeId].GetX(),
+												ThePaths.m_pathNodes[closestNodeId].GetY(),
 												GetPosition().x,
 												GetPosition().y);
 
-											CVector2D distToNode = ThePaths.m_pathNodes[closestNodeId].pos - GetPosition();
+											CVector2D distToNode = ThePaths.m_pathNodes[closestNodeId].GetPosition() - GetPosition();
 											CVector2D distToSeekPos = m_vecSeekPos - GetPosition();
 
 											if (DotProduct2D(distToNode, distToSeekPos) < 0.0f) {
@@ -12904,7 +12904,7 @@ CPed::ProcessObjective(void)
 								if (closestNode >= 0) {
 									int16 colliding;
 									CWorld::FindObjectsKindaColliding(
-										ThePaths.m_pathNodes[closestNode].pos, 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
+										ThePaths.m_pathNodes[closestNode].GetPosition(), 10.0f, true, &colliding, 2, nil, false, true, true, false, false);
 									if (!colliding) {
 										CZoneInfo zoneInfo;
 										int chosenCarClass;
@@ -12912,7 +12912,7 @@ CPed::ProcessObjective(void)
 										int chosenModel = CCarCtrl::ChooseModel(&zoneInfo, &ourPos, &chosenCarClass);
 										CAutomobile *newVeh = new CAutomobile(chosenModel, RANDOM_VEHICLE);
 										if (newVeh) {
-											newVeh->GetPosition() = ThePaths.m_pathNodes[closestNode].pos;
+											newVeh->GetPosition() = ThePaths.m_pathNodes[closestNode].GetPosition();
 											newVeh->GetPosition().z += 4.0f;
 											newVeh->SetHeading(DEGTORAD(200.0f));
 											newVeh->SetStatus(STATUS_ABANDONED);
@@ -13112,7 +13112,7 @@ CPed::ProcessObjective(void)
 								FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
 
 							if (m_pNextPathNode)
-								m_vecSeekPos = m_pNextPathNode->pos;
+								m_vecSeekPos = m_pNextPathNode->GetPosition();
 
 							SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
 						} else {
@@ -13666,7 +13666,7 @@ CPed::ProcessObjective(void)
 								FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
 
 							if (m_pNextPathNode)
-								m_vecSeekPos = m_pNextPathNode->pos;
+								m_vecSeekPos = m_pNextPathNode->GetPosition();
 						}
 						SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
 					}
@@ -17324,7 +17324,7 @@ CPed::WanderPath(void)
 		if (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE)
 			SetMoveState(PEDMOVE_WALK);
 	}
-	m_vecSeekPos = m_pNextPathNode->pos;
+	m_vecSeekPos = m_pNextPathNode->GetPosition();
 	m_vecSeekPos.z += 1.0f;
 
 	// Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him.
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 2617e801..cb2cb5b7 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -198,6 +198,7 @@ CRenderer::RenderRoads(void)
 		t = (CTreadable*)ms_aVisibleEntityPtrs[i];
 		if(t->IsBuilding() && t->GetIsATreadable()){
 #ifndef MASTER
+#ifndef MIAMI
 			if(gbShowCarRoadGroups || gbShowPedRoadGroups){
 				int ind = 0;
 				if(gbShowCarRoadGroups)
@@ -206,6 +207,7 @@ CRenderer::RenderRoads(void)
 					ind += ThePaths.m_pathNodes[t->m_nodeIndices[PATH_PED][0]].group;
 				SetAmbientColoursToIndicateRoadGroup(ind);
 			}
+#endif
 #endif
 			RenderOneRoad(t);
 #ifndef MASTER
diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp
index acca4d60..58971786 100644
--- a/src/vehicles/Automobile.cpp
+++ b/src/vehicles/Automobile.cpp
@@ -4146,7 +4146,7 @@ CAutomobile::HasCarStoppedBecauseOfLight(void)
 	if(AutoPilot.m_nCurrentRouteNode && AutoPilot.m_nNextRouteNode){
 		CPathNode *curnode = &ThePaths.m_pathNodes[AutoPilot.m_nCurrentRouteNode];
 		for(i = 0; i < curnode->numLinks; i++)
-			if(ThePaths.m_connections[curnode->firstLink + i] == AutoPilot.m_nNextRouteNode)
+			if(ThePaths.ConnectedNode(curnode->firstLink + i) == AutoPilot.m_nNextRouteNode)
 				break;
 		if(i < curnode->numLinks &&
 		   ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3)
@@ -4156,7 +4156,7 @@ CAutomobile::HasCarStoppedBecauseOfLight(void)
 	if(AutoPilot.m_nCurrentRouteNode && AutoPilot.m_nPrevRouteNode){
 		CPathNode *curnode = &ThePaths.m_pathNodes[AutoPilot.m_nCurrentRouteNode];
 		for(i = 0; i < curnode->numLinks; i++)
-			if(ThePaths.m_connections[curnode->firstLink + i] == AutoPilot.m_nPrevRouteNode)
+			if(ThePaths.ConnectedNode(curnode->firstLink + i) == AutoPilot.m_nPrevRouteNode)
 				break;
 		if(i < curnode->numLinks &&
 		   ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3)