implemented CTrafficLights

This commit is contained in:
aap 2020-04-10 18:36:39 +02:00
parent 3a4442eca4
commit c5d61392ea
10 changed files with 577 additions and 116 deletions

View File

@ -43,7 +43,6 @@ CPools - save/loading
CRecordDataForChase CRecordDataForChase
CRecordDataForGame CRecordDataForGame
CRoadBlocks CRoadBlocks
CTrafficLights
CWeapon CWeapon
CWorld CWorld
GenericLoad GenericLoad

View File

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

View File

@ -393,25 +393,25 @@ CCarCtrl::GenerateOneRandomCar()
pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f); pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f);
pCar->GetUp() = CVector(0.0f, 0.0f, 1.0f); pCar->GetUp() = CVector(0.0f, 0.0f, 1.0f);
float currentPathLinkForwardX = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dirX; 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].dirY; 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].dirX; 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].dirY; float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.y;
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo];
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurrentLink->posX + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurrentLink->pos.x + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurrentLink->posY - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurrentLink->pos.y - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurrentLink->dirX * pCar->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurrentLink->dir.x * pCar->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurrentLink->dirY * pCar->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurrentLink->dir.y * pCar->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dirX * pCar->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->dir.x * pCar->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dirY * pCar->AutoPilot.m_nNextDirection; float directionNextLinkY = pNextLink->dir.y * pCar->AutoPilot.m_nNextDirection;
/* We want to make a path between two links that may not have the same forward directions a curve. */ /* We want to make a path between two links that may not have the same forward directions a curve. */
pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -763,17 +763,17 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
return; return;
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
float currentPathLinkForwardX = pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; float currentPathLinkForwardX = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
float currentPathLinkForwardY = pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; float currentPathLinkForwardY = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
float nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
float nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f); CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f); CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
@ -1553,8 +1553,8 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nNextDirection = -1; pVehicle->AutoPilot.m_nNextDirection = -1;
lanesOnNextNode = pNextLink->numRightLanes; lanesOnNextNode = pNextLink->numRightLanes;
} }
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX; float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x;
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX; float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x;
if (lanesOnNextNode >= 0){ if (lanesOnNextNode >= 0){
if ((CGeneral::GetRandomNumber() & 0x600) == 0){ if ((CGeneral::GetRandomNumber() & 0x600) == 0){
/* 25% chance vehicle will try to switch lane */ /* 25% chance vehicle will try to switch lane */
@ -1574,17 +1574,17 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
if (pVehicle->AutoPilot.m_bStayInFastLane) if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0; pVehicle->AutoPilot.m_nNextLane = 0;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */ pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */
pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH), pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH),
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
/* We want to make a path between two links that may not have the same forward directions a curve. */ /* We want to make a path between two links that may not have the same forward directions a curve. */
pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -1725,10 +1725,10 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
pVehicle->AutoPilot.m_nNextDirection = -1; pVehicle->AutoPilot.m_nNextDirection = -1;
lanesOnNextNode = pNextLink->numRightLanes; lanesOnNextNode = pNextLink->numRightLanes;
} }
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX; float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x;
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirY; float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y;
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX; float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x;
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirY; float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y;
if (lanesOnNextNode >= 0) { if (lanesOnNextNode >= 0) {
CVector2D dist = pNextPathNode->pos - pCurNode->pos; CVector2D dist = pNextPathNode->pos - pCurNode->pos;
if (dist.MagnitudeSqr() >= SQR(7.0f)){ if (dist.MagnitudeSqr() >= SQR(7.0f)){
@ -1755,17 +1755,17 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
if (pVehicle->AutoPilot.m_bStayInFastLane) if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0; pVehicle->AutoPilot.m_nNextLane = 0;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
/* We want to make a path between two links that may not have the same forward directions a curve. */ /* We want to make a path between two links that may not have the same forward directions a curve. */
pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -1814,10 +1814,10 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
pVehicle->AutoPilot.m_nNextDirection = -1; pVehicle->AutoPilot.m_nNextDirection = -1;
lanesOnNextNode = pNextLink->numRightLanes; lanesOnNextNode = pNextLink->numRightLanes;
} }
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX; float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x;
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirY; float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y;
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX; float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x;
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirY; float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y;
if (lanesOnNextNode >= 0) { if (lanesOnNextNode >= 0) {
CVector2D dist = pNextPathNode->pos - pCurNode->pos; CVector2D dist = pNextPathNode->pos - pCurNode->pos;
if (dist.MagnitudeSqr() >= SQR(7.0f) && (CGeneral::GetRandomNumber() & 0x600) == 0) { if (dist.MagnitudeSqr() >= SQR(7.0f) && (CGeneral::GetRandomNumber() & 0x600) == 0) {
@ -1835,17 +1835,17 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
if (pVehicle->AutoPilot.m_bStayInFastLane) if (pVehicle->AutoPilot.m_bStayInFastLane)
pVehicle->AutoPilot.m_nNextLane = 0; pVehicle->AutoPilot.m_nNextLane = 0;
CVector positionOnCurrentLinkIncludingLane( CVector positionOnCurrentLinkIncludingLane(
pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY, pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX, pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
0.0f); 0.0f);
CVector positionOnNextLinkIncludingLane( CVector positionOnNextLinkIncludingLane(
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX, pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
0.0f); 0.0f);
float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
/* We want to make a path between two links that may not have the same forward directions a curve. */ /* We want to make a path between two links that may not have the same forward directions a curve. */
pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor( pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
&positionOnCurrentLinkIncludingLane, &positionOnCurrentLinkIncludingLane,
@ -2192,16 +2192,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
forward.Normalise(); forward.Normalise();
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
CVector2D currentPathLinkForward(pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection, CVector2D currentPathLinkForward(pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection,
pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection); pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection);
float nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
float nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
CVector2D positionOnCurrentLinkIncludingLane( CVector2D positionOnCurrentLinkIncludingLane(
pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
CVector2D positionOnNextLinkIncludingLane( CVector2D positionOnNextLinkIncludingLane(
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY, pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX); pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX);
CVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane; CVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane;
float scalarDistanceToNextNode = distanceToNextNode.Magnitude(); float scalarDistanceToNextNode = distanceToNextNode.Magnitude();
CVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane; CVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane;
@ -2230,16 +2230,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
} }
pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo]; pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
scalarDistanceToNextNode = CVector2D( scalarDistanceToNextNode = CVector2D(
pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x, pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x,
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude(); pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude();
pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo]; pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
currentPathLinkForward.x = pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection; currentPathLinkForward.x = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
currentPathLinkForward.y = pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection; currentPathLinkForward.y = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection; nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection; nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
} }
positionOnCurrentLinkIncludingLane.x = pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y; positionOnCurrentLinkIncludingLane.x = pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y;
positionOnCurrentLinkIncludingLane.y = pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x; positionOnCurrentLinkIncludingLane.y = pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x;
CVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f; CVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f;
if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){ if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){
projectedPosition.x = positionOnCurrentLinkIncludingLane.x; projectedPosition.x = positionOnCurrentLinkIncludingLane.x;
@ -2281,8 +2281,8 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
CCarAI::CarHasReasonToStop(pVehicle); CCarAI::CarHasReasonToStop(pVehicle);
speedStyleMultiplier = 0.0f; speedStyleMultiplier = 0.0f;
} }
CVector2D trajectory(pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y, CVector2D trajectory(pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x); pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
trajectory -= pVehicle->GetPosition(); trajectory -= pVehicle->GetPosition();
float speedAngleMultiplier = FindSpeedMultiplier( float speedAngleMultiplier = FindSpeedMultiplier(
CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward, CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward,

View File

@ -5,8 +5,13 @@
#include "Camera.h" #include "Camera.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "World.h" #include "World.h"
#include "Lines.h" // for debug
#include "PathFind.h" #include "PathFind.h"
bool gbShowPedPaths;
bool gbShowCarPaths;
bool gbShowCarPathsLinks;
CPathFind &ThePaths = *(CPathFind*)0x8F6754; CPathFind &ThePaths = *(CPathFind*)0x8F6754;
WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); } WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); }
@ -466,20 +471,20 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
// IMPROVE: use a goto here // IMPROVE: use a goto here
// Find existing car path link // Find existing car path link
for(k = 0; k < m_numCarPathLinks; k++){ for(k = 0; k < m_numCarPathLinks; k++){
if(m_carPathLinks[k].dirX == tempnodes[j].dirX && if(m_carPathLinks[k].dir.x == tempnodes[j].dirX &&
m_carPathLinks[k].dirY == tempnodes[j].dirY && m_carPathLinks[k].dir.y == tempnodes[j].dirY &&
m_carPathLinks[k].posX == tempnodes[j].pos.x && m_carPathLinks[k].pos.x == tempnodes[j].pos.x &&
m_carPathLinks[k].posY == tempnodes[j].pos.y){ m_carPathLinks[k].pos.y == tempnodes[j].pos.y){
m_carPathConnections[m_numConnections] = k; m_carPathConnections[m_numConnections] = k;
k = m_numCarPathLinks; k = m_numCarPathLinks;
} }
} }
// k is m_numCarPathLinks+1 if we found one // k is m_numCarPathLinks+1 if we found one
if(k == m_numCarPathLinks){ if(k == m_numCarPathLinks){
m_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX; m_carPathLinks[m_numCarPathLinks].dir.x = tempnodes[j].dirX;
m_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY; m_carPathLinks[m_numCarPathLinks].dir.y = tempnodes[j].dirY;
m_carPathLinks[m_numCarPathLinks].posX = tempnodes[j].pos.x; m_carPathLinks[m_numCarPathLinks].pos.x = tempnodes[j].pos.x;
m_carPathLinks[m_numCarPathLinks].posY = tempnodes[j].pos.y; m_carPathLinks[m_numCarPathLinks].pos.y = tempnodes[j].pos.y;
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes; m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes;
m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes; m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes;
@ -529,20 +534,20 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
// IMPROVE: use a goto here // IMPROVE: use a goto here
// Find existing car path link // Find existing car path link
for(k = 0; k < m_numCarPathLinks; k++){ for(k = 0; k < m_numCarPathLinks; k++){
if(m_carPathLinks[k].dirX == dx && if(m_carPathLinks[k].dir.x == dx &&
m_carPathLinks[k].dirY == dy && m_carPathLinks[k].dir.y == dy &&
m_carPathLinks[k].posX == posx && m_carPathLinks[k].pos.x == posx &&
m_carPathLinks[k].posY == posy){ m_carPathLinks[k].pos.y == posy){
m_carPathConnections[m_numConnections] = k; m_carPathConnections[m_numConnections] = k;
k = m_numCarPathLinks; k = m_numCarPathLinks;
} }
} }
// k is m_numCarPathLinks+1 if we found one // k is m_numCarPathLinks+1 if we found one
if(k == m_numCarPathLinks){ if(k == m_numCarPathLinks){
m_carPathLinks[m_numCarPathLinks].dirX = dx; m_carPathLinks[m_numCarPathLinks].dir.x = dx;
m_carPathLinks[m_numCarPathLinks].dirY = dy; m_carPathLinks[m_numCarPathLinks].dir.y = dy;
m_carPathLinks[m_numCarPathLinks].posX = posx; m_carPathLinks[m_numCarPathLinks].pos.x = posx;
m_carPathLinks[m_numCarPathLinks].posY = posy; m_carPathLinks[m_numCarPathLinks].pos.y = posy;
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i; m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1; m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1;
m_carPathLinks[m_numCarPathLinks].numRightLanes = -1; m_carPathLinks[m_numCarPathLinks].numRightLanes = -1;
@ -760,8 +765,8 @@ CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool ena
{ {
int i; int i;
for(i = 0; i < m_numCarPathLinks; i++) for(i = 0; i < m_numCarPathLinks; i++)
if(x1 < m_carPathLinks[i].posX && m_carPathLinks[i].posX < x2 && if(x1 < m_carPathLinks[i].pos.x && m_carPathLinks[i].pos.x < x2 &&
y1 < m_carPathLinks[i].posY && m_carPathLinks[i].posY < y2) y1 < m_carPathLinks[i].pos.y && m_carPathLinks[i].pos.y < y2)
m_carPathLinks[i].bBridgeLights = enable; m_carPathLinks[i].bBridgeLights = enable;
} }
@ -1444,6 +1449,132 @@ CPathFind::Load(uint8 *buf, uint32 size)
m_pathNodes[i].bBetweenLevels = false; m_pathNodes[i].bBetweenLevels = false;
} }
void
CPathFind::DisplayPathData(void)
{
// Not the function from mobm_carPathLinksile but my own!
int i, j, k;
// Draw 50 units around camera
CVector pos = TheCamera.GetPosition();
const float maxDist = 50.0f;
// Render car path nodes
if(gbShowCarPaths)
for(i = 0; i < m_numCarPathNodes; i++){
if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist))
continue;
CVector n1 = m_pathNodes[i].pos;
n1.z += 0.3f;
// Draw node itself
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n1.x, n1.y, n1.z + 1.0f,
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;
n2.z += 0.3f;
// Draw links to neighbours
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n2.x, n2.y, n2.z,
0xFFFFFFFF, 0xFFFFFFFF);
}
}
// Render car path nodes
if(gbShowCarPathsLinks)
for(i = 0; i < m_numCarPathLinks; i++){
CVector2D n1_2d = m_carPathLinks[i].pos;
if((n1_2d - pos).MagnitudeSqr() > SQR(maxDist))
continue;
int ni = m_carPathLinks[i].pathNodeIndex;
CVector pn1 = m_pathNodes[ni].pos;
pn1.z += 0.3f;
CVector n1(n1_2d.x, n1_2d.y, pn1.z);
n1.z += 0.3f;
// Draw car node itself
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
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,
0xFFFFFFFF, 0xFFFFFFFF);
// Draw connection to car path node
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
pn1.x, pn1.y, pn1.z,
0xFF0000FF, 0xFFFFFFFF);
// traffic light type
uint32 col = 0xFF;
if((m_carPathLinks[i].trafficLightType&0x7F) == 1)
col += 0xFF000000;
if((m_carPathLinks[i].trafficLightType&0x7F) == 2)
col += 0x00FF0000;
if(m_carPathLinks[i].trafficLightType & 0x80)
col += 0x0000FF00;
CLines::RenderLineWithClipping(n1.x+0.2f, n1.y, n1.z,
n1.x+0.2f, n1.y, n1.z + 1.0f,
col, col);
for(j = 0; j < m_pathNodes[ni].numLinks; j++){
k = m_carPathConnections[m_pathNodes[ni].firstLink + j];
CVector2D n2_2d = m_carPathLinks[k].pos;
int nk = m_carPathLinks[k].pathNodeIndex;
CVector pn2 = m_pathNodes[nk].pos;
pn2.z += 0.3f;
CVector n2(n2_2d.x, n2_2d.y, pn2.z);
n2.z += 0.3f;
// Draw links to neighbours
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n2.x, n2.y, n2.z,
0xFF00FFFF, 0xFF00FFFF);
}
}
// Render ped path nodes
if(gbShowPedPaths)
for(i = m_numCarPathNodes; i < m_numPathNodes; i++){
if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist))
continue;
CVector n1 = m_pathNodes[i].pos;
n1.z += 0.3f;
// Draw node itself
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n1.x, n1.y, n1.z + 1.0f,
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;
n2.z += 0.3f;
// Draw links to neighbours
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
n2.x, n2.y, n2.z,
0xFFFFFFFF, 0xFFFFFFFF);
// Draw connection flags
CVector mid = (n1+n2)/2.0f;
uint32 col = 0xFF;
if(m_connectionFlags[m_pathNodes[i].firstLink + j].bCrossesRoad)
col += 0x00FF0000;
if(m_connectionFlags[m_pathNodes[i].firstLink + j].bTrafficLight)
col += 0xFF000000;
CLines::RenderLineWithClipping(mid.x, mid.y, mid.z,
mid.x, mid.y, mid.z + 1.0f,
col, col);
}
}
}
STARTPATCHES STARTPATCHES
InjectHook(0x4294A0, &CPathFind::Init, PATCH_JUMP); InjectHook(0x4294A0, &CPathFind::Init, PATCH_JUMP);
InjectHook(0x42D580, &CPathFind::AllocatePathFindInfoMem, PATCH_JUMP); InjectHook(0x42D580, &CPathFind::AllocatePathFindInfoMem, PATCH_JUMP);

View File

@ -84,10 +84,8 @@ union CConnectionFlags
struct CCarPathLink struct CCarPathLink
{ {
float posX; CVector2D pos;
float posY; CVector2D dir;
float dirX;
float dirY;
int16 pathNodeIndex; int16 pathNodeIndex;
int8 numLeftLanes; int8 numLeftLanes;
int8 numRightLanes; int8 numRightLanes;
@ -208,7 +206,13 @@ public:
bool TestCoorsCloseness(CVector target, uint8 type, CVector start); bool TestCoorsCloseness(CVector target, uint8 type, CVector start);
void Save(uint8 *buf, uint32 *size); void Save(uint8 *buf, uint32 *size);
void Load(uint8 *buf, uint32 size); void Load(uint8 *buf, uint32 size);
void DisplayPathData(void);
}; };
static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error"); static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error");
extern CPathFind &ThePaths; extern CPathFind &ThePaths;
extern bool gbShowPedPaths;
extern bool gbShowCarPaths;
extern bool gbShowCarPathsLinks;

View File

@ -1,23 +1,335 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "TrafficLights.h" #include "General.h"
#include "Camera.h"
#include "World.h"
#include "PathFind.h"
#include "Timer.h" #include "Timer.h"
#include "Clock.h"
#include "Weather.h"
#include "Timecycle.h"
#include "Pointlights.h"
#include "Shadows.h"
#include "Coronas.h"
#include "SpecialFX.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "TrafficLights.h"
WRAPPER void CTrafficLights::DisplayActualLight(CEntity *ent) { EAXJMP(0x455800); } // TODO: figure out the meaning of this
WRAPPER void CTrafficLights::ScanForLightsOnMap(void) { EAXJMP(0x454F40); } enum { SOME_FLAG = 0x80 };
WRAPPER bool CTrafficLights::ShouldCarStopForLight(CVehicle*, bool) { EAXJMP(0x455350); }
WRAPPER bool CTrafficLights::ShouldCarStopForBridge(CVehicle*) { EAXJMP(0x456460); } void
CTrafficLights::DisplayActualLight(CEntity *ent)
{
if(ent->GetUp().z < 0.96f || ent->bRenderDamaged)
return;
int phase;
if(FindTrafficLightType(ent) == 1)
phase = LightForCars1();
else
phase = LightForCars2();
int i;
CBaseModelInfo *mi = CModelInfo::GetModelInfo(ent->GetModelIndex());
float x = mi->Get2dEffect(0)->pos.x;
float yMin = mi->Get2dEffect(0)->pos.y;
float yMax = mi->Get2dEffect(0)->pos.y;
float zMin = mi->Get2dEffect(0)->pos.z;
float zMax = mi->Get2dEffect(0)->pos.z;
for(i = 1; i < 6; i++){
assert(mi->Get2dEffect(i));
yMin = min(yMin, mi->Get2dEffect(i)->pos.y);
yMax = min(yMax, mi->Get2dEffect(i)->pos.y);
zMin = min(zMin, mi->Get2dEffect(i)->pos.z);
zMax = min(zMax, mi->Get2dEffect(i)->pos.z);
}
CVector pos1, pos2;
uint8 r, g;
int id;
switch(phase){
case CAR_LIGHTS_GREEN:
r = 0;
g = 255;
pos1 = ent->GetMatrix() * CVector(x, yMax, zMin);
pos2 = ent->GetMatrix() * CVector(x, yMin, zMin);
id = 0;
break;
case CAR_LIGHTS_YELLOW:
r = 255;
g = 128;
pos1 = ent->GetMatrix() * CVector(x, yMax, (zMin+zMax)/2.0f);
pos2 = ent->GetMatrix() * CVector(x, yMin, (zMin+zMax)/2.0f);
id = 1;
break;
case CAR_LIGHTS_RED:
default:
r = 255;
g = 0;
pos1 = ent->GetMatrix() * CVector(x, yMax, zMax);
pos2 = ent->GetMatrix() * CVector(x, yMin, zMax);
id = 2;
break;
}
if(CClock::GetHours() > 19 || CClock::GetHours() < 6 || CWeather::Foggyness > 0.05f)
CPointLights::AddLight(CPointLights::LIGHT_POINT,
pos1, CVector(0.0f, 0.0f, 0.0f), 8.0f,
r/255.0f, g/255.0f, 0/255.0f, CPointLights::FOG_NORMAL, true);
CShadows::StoreStaticShadow((uintptr)ent,
SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos1,
8.0f, 0.0f, 0.0f, -8.0f, 128,
r*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
g*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
0*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
12.0f, 1.0f, 40.0f, false, 0.0f);
if(DotProduct(TheCamera.GetForward(), ent->GetForward()) < 0.0f)
CCoronas::RegisterCorona((uintptr)ent + id,
r*CTimeCycle::GetSpriteBrightness()*0.7f,
g*CTimeCycle::GetSpriteBrightness()*0.7f,
0*CTimeCycle::GetSpriteBrightness()*0.7f,
255,
pos1, 1.75f*CTimeCycle::GetSpriteSize(), 50.0f,
CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
else
CCoronas::RegisterCorona((uintptr)ent + id + 3,
r*CTimeCycle::GetSpriteBrightness()*0.7f,
g*CTimeCycle::GetSpriteBrightness()*0.7f,
0*CTimeCycle::GetSpriteBrightness()*0.7f,
255,
pos2, 1.75f*CTimeCycle::GetSpriteSize(), 50.0f,
CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
CBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
CBrightLights::RegisterOne(pos2, ent->GetUp(), -ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
static const float top = -0.127f;
static const float bot = -0.539f;
static const float mid = bot + (top-bot)/3.0f;
static const float left = 1.256f;
static const float right = 0.706f;
phase = CTrafficLights::LightForPeds();
if(phase == PED_LIGHTS_DONT_WALK){
CVector p0(2.7f, right, top);
CVector p1(2.7f, left, top);
CVector p2(2.7f, right, mid);
CVector p3(2.7f, left, mid);
CShinyTexts::RegisterOne(ent->GetMatrix()*p0, ent->GetMatrix()*p1, ent->GetMatrix()*p2, ent->GetMatrix()*p3,
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
SHINYTEXT_WALK, 255, 0, 0, 60.0f);
}else if(phase == PED_LIGHTS_WALK || CTimer::GetTimeInMilliseconds() & 0x100){
CVector p0(2.7f, right, mid);
CVector p1(2.7f, left, mid);
CVector p2(2.7f, right, bot);
CVector p3(2.7f, left, bot);
CShinyTexts::RegisterOne(ent->GetMatrix()*p0, ent->GetMatrix()*p1, ent->GetMatrix()*p2, ent->GetMatrix()*p3,
1.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f,
SHINYTEXT_WALK, 255, 255, 255, 60.0f);
}
}
void
CTrafficLights::ScanForLightsOnMap(void)
{
int x, y;
int i, j, l;
CPtrNode *node;
for(x = 0; x < NUMSECTORS_X; x++)
for(y = 0; y < NUMSECTORS_Y; y++){
CPtrList &list = CWorld::GetSector(x, y)->m_lists[ENTITYLIST_DUMMIES];
for(node = list.first; node; node = node->next){
CEntity *light = (CEntity*)node->item;
if(light->GetModelIndex() != MI_TRAFFICLIGHTS)
continue;
// Check cars
for(i = 0; i < ThePaths.m_numCarPathLinks; i++){
CVector2D dist = ThePaths.m_carPathLinks[i].pos - 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 -
light->GetPosition().z;
if(dz < 15.0f){
ThePaths.m_carPathLinks[i].trafficLightType = FindTrafficLightType(light);
// Find two neighbour nodes of this one
int n1 = -1;
int n2 = -1;
for(j = 0; j < ThePaths.m_numPathNodes; j++)
for(l = 0; l < ThePaths.m_pathNodes[j].numLinks; l++)
if(ThePaths.m_carPathConnections[ThePaths.m_pathNodes[j].firstLink + l] == i){
if(n1 == -1)
n1 = j;
else
n2 = j;
}
// What's going on here?
if(ThePaths.m_pathNodes[n1].numLinks <= ThePaths.m_pathNodes[n2].numLinks)
n1 = n2;
if(ThePaths.m_carPathLinks[i].pathNodeIndex != n1)
ThePaths.m_carPathLinks[i].trafficLightType |= SOME_FLAG;
}
}
}
// 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);
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(dist1 < 15.0f || dist2 < 15.0f)
ThePaths.m_connectionFlags[j].bTrafficLight = true;
}
}
}
}
}
}
}
bool
CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
{
int node, type;
node = vehicle->AutoPilot.m_nNextPathNodeInfo;
type = ThePaths.m_carPathLinks[node].trafficLightType;
if(type){
if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nNextRouteNode) &&
(!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nNextRouteNode))
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);
if(vehicle->AutoPilot.m_nNextDirection == -1){
if(dist > 0.0f && dist < 8.0f)
return true;
}else{
if(dist < 0.0f && dist > -8.0f)
return true;
}
}
}
node = vehicle->AutoPilot.m_nCurrentPathNodeInfo;
type = ThePaths.m_carPathLinks[node].trafficLightType;
if(type){
if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nCurrentRouteNode) &&
(!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nCurrentRouteNode))
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);
if(vehicle->AutoPilot.m_nCurrentDirection == -1){
if(dist > 0.0f && dist < 8.0f)
return true;
}else{
if(dist < 0.0f && dist > -8.0f)
return true;
}
}
}
if(vehicle->m_status == STATUS_PHYSICS){
node = vehicle->AutoPilot.m_nPreviousPathNodeInfo;
type = ThePaths.m_carPathLinks[node].trafficLightType;
if(type){
if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nPrevRouteNode) &&
(!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nPrevRouteNode))
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);
if(vehicle->AutoPilot.m_nPreviousDirection == -1){
if(dist > 0.0f && dist < 6.0f)
return true;
}else{
if(dist < 0.0f && dist > -6.0f)
return true;
}
}
}
}
return false;
}
bool
CTrafficLights::ShouldCarStopForBridge(CVehicle *vehicle)
{
return ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nNextPathNodeInfo].bBridgeLights &&
!ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nCurrentPathNodeInfo].bBridgeLights;
}
int
CTrafficLights::FindTrafficLightType(CEntity *light)
{
float orientation = RADTODEG(CGeneral::GetATanOfXY(light->GetForward().x, light->GetForward().y));
if((orientation > 60.0f && orientation < 60.0f + 90.0f) ||
(orientation > 240.0f && orientation < 240.0f + 90.0f))
return 1;
return 2;
}
uint8 uint8
CTrafficLights::LightForPeds(void) CTrafficLights::LightForPeds(void)
{ {
uint32 period = CTimer::GetTimeInMilliseconds() & 0x3FFF; // Equals to % 16384 uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
if (period >= 15384) if(period < 12000)
return PED_LIGHTS_WALK_BLINK; return PED_LIGHTS_DONT_WALK;
else if (period >= 12000) else if(period < 16384 - 1000)
return PED_LIGHTS_WALK; return PED_LIGHTS_WALK;
else else
return PED_LIGHTS_DONT_WALK; return PED_LIGHTS_WALK_BLINK;
} }
uint8
CTrafficLights::LightForCars1(void)
{
uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
if(period < 5000)
return CAR_LIGHTS_GREEN;
else if(period < 5000 + 1000)
return CAR_LIGHTS_YELLOW;
else
return CAR_LIGHTS_RED;
}
uint8
CTrafficLights::LightForCars2(void)
{
uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
if(period < 6000)
return CAR_LIGHTS_RED;
else if(period < 12000 - 1000)
return CAR_LIGHTS_GREEN;
else if(period < 12000)
return CAR_LIGHTS_YELLOW;
else
return CAR_LIGHTS_RED;
}
STARTPATCHES
InjectHook(0x455760, &CTrafficLights::LightForCars1, PATCH_JUMP);
InjectHook(0x455790, &CTrafficLights::LightForCars2, PATCH_JUMP);
InjectHook(0x4557D0, &CTrafficLights::LightForPeds, PATCH_JUMP);
ENDPATCHES

View File

@ -7,6 +7,10 @@ enum {
PED_LIGHTS_WALK, PED_LIGHTS_WALK,
PED_LIGHTS_WALK_BLINK, PED_LIGHTS_WALK_BLINK,
PED_LIGHTS_DONT_WALK, PED_LIGHTS_DONT_WALK,
CAR_LIGHTS_GREEN = 0,
CAR_LIGHTS_YELLOW,
CAR_LIGHTS_RED
}; };
class CTrafficLights class CTrafficLights
@ -14,7 +18,10 @@ class CTrafficLights
public: public:
static void DisplayActualLight(CEntity *ent); static void DisplayActualLight(CEntity *ent);
static void ScanForLightsOnMap(void); static void ScanForLightsOnMap(void);
static int FindTrafficLightType(CEntity *light);
static uint8 LightForPeds(void); static uint8 LightForPeds(void);
static uint8 LightForCars1(void);
static uint8 LightForCars2(void);
static bool ShouldCarStopForLight(CVehicle*, bool); static bool ShouldCarStopForLight(CVehicle*, bool);
static bool ShouldCarStopForBridge(CVehicle*); static bool ShouldCarStopForBridge(CVehicle*);
}; };

View File

@ -1,8 +1,7 @@
#include "common.h" #include "common.h"
#include "rpmatfx.h" #include "rpmatfx.h"
#include "rpskin.h"
#include "rphanim.h" #include "rphanim.h"
#include "rtbmp.h" #include "rpskin.h"
#include "patcher.h" #include "patcher.h"
#include "main.h" #include "main.h"
#include "CdStream.h" #include "CdStream.h"
@ -54,6 +53,7 @@
#include "Frontend.h" #include "Frontend.h"
#include "AnimViewer.h" #include "AnimViewer.h"
#include "Script.h" #include "Script.h"
#include "PathFind.h"
#include "Debug.h" #include "Debug.h"
#include "Console.h" #include "Console.h"
#include "timebars.h" #include "timebars.h"
@ -788,8 +788,11 @@ void
RenderDebugShit(void) RenderDebugShit(void)
{ {
CTheScripts::RenderTheScriptDebugLines(); CTheScripts::RenderTheScriptDebugLines();
#ifndef FINAL
if(gbShowCollisionLines) if(gbShowCollisionLines)
CRenderer::RenderCollisionLines(); CRenderer::RenderCollisionLines();
ThePaths.DisplayPathData();
#endif
} }
void void

View File

@ -350,6 +350,9 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway); DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway);
DebugMenuAddVarBool8("Debug", "Script Heli On", (int8*)0x95CD43, nil); DebugMenuAddVarBool8("Debug", "Script Heli On", (int8*)0x95CD43, nil);
DebugMenuAddVarBool8("Debug", "Show Ped Paths", (int8*)&gbShowPedPaths, nil);
DebugMenuAddVarBool8("Debug", "Show Car Paths", (int8*)&gbShowCarPaths, nil);
DebugMenuAddVarBool8("Debug", "Show Car Path Links", (int8*)&gbShowCarPathsLinks, nil);
DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", (int8*)&gbShowPedRoadGroups, nil); DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", (int8*)&gbShowPedRoadGroups, nil);
DebugMenuAddVarBool8("Debug", "Show Car Road Groups", (int8*)&gbShowCarRoadGroups, nil); DebugMenuAddVarBool8("Debug", "Show Car Road Groups", (int8*)&gbShowCarRoadGroups, nil);
DebugMenuAddVarBool8("Debug", "Show Collision Lines", (int8*)&gbShowCollisionLines, nil); DebugMenuAddVarBool8("Debug", "Show Collision Lines", (int8*)&gbShowCollisionLines, nil);

View File

@ -119,8 +119,10 @@ public:
static int GetSunCoronaBlue(void) { return m_nCurrentSunCoronaBlue; } static int GetSunCoronaBlue(void) { return m_nCurrentSunCoronaBlue; }
static float GetSunSize(void) { return m_fCurrentSunSize; } static float GetSunSize(void) { return m_fCurrentSunSize; }
static float GetSpriteBrightness(void) { return m_fCurrentSpriteBrightness; } static float GetSpriteBrightness(void) { return m_fCurrentSpriteBrightness; }
static float GetSpriteSize(void) { return m_fCurrentSpriteSize; }
static int GetShadowStrength(void) { return m_nCurrentShadowStrength; } static int GetShadowStrength(void) { return m_nCurrentShadowStrength; }
static int GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; } static int GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; }
static int GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; }
static float GetFarClip(void) { return m_fCurrentFarClip; } static float GetFarClip(void) { return m_fCurrentFarClip; }
static float GetFogStart(void) { return m_fCurrentFogStart; } static float GetFogStart(void) { return m_fCurrentFogStart; }