implemented most of vice city path system

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

View file

@ -12,17 +12,17 @@ void CAutoPilot::ModifySpeed(float speed)
float positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve;
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,

View file

@ -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;

File diff suppressed because it is too large Load diff

View file

@ -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;

View file

@ -108,7 +108,7 @@ CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, f
// if we still didn't find anything, find closest path node
if (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];

View file

@ -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
}

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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));

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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
}
}

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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.

View file

@ -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

View file

@ -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)