- significantly reduce code with use of GetSurfaceRoadInfo

- refactoring progress on GetNextRoadInfo
This commit is contained in:
Ilya Shurumov 2020-10-01 00:20:03 +06:00
parent b24df3aae9
commit ebce60cba6
3 changed files with 184 additions and 366 deletions

View File

@ -621,6 +621,8 @@ int GetNextRoadInfo(_CAR_DATA* cp, int randomExit, int* turnAngle, int* startDis
{ {
int currentLaneDir; int currentLaneDir;
int widthInLanes; int widthInLanes;
int laneNo;
int count;
_st = GET_STRAIGHT(currentRoadId); _st = GET_STRAIGHT(currentRoadId);
@ -636,34 +638,34 @@ int GetNextRoadInfo(_CAR_DATA* cp, int randomExit, int* turnAngle, int* startDis
else else
tmpNewRoad[1] = _st->ConnectIdx[1]; tmpNewRoad[1] = _st->ConnectIdx[1];
uVar9 = widthInLanes; // counter count = widthInLanes; // counter
uVar29 = widthInLanes; // bestLane laneNo = widthInLanes; // bestLane
do do
{ {
uVar9--; count--;
if(ROAD_IS_AI_LANE(_st, uVar9) && !ROAD_IS_PARKING_ALLOWED_AT(_st, uVar9)) if(ROAD_IS_AI_LANE(_st, count) && !ROAD_IS_PARKING_ALLOWED_AT(_st, count))
{ {
test42 = ROAD_LANE_DIR(_st, uVar9); test42 = ROAD_LANE_DIR(_st, count);
uVar29 = uVar9; laneNo = count;
} }
} while (uVar9 >= 0); } while (count >= 0);
if (currentLaneDir == 0) if (currentLaneDir == 0)
leftLane = uVar29 & 0xff; leftLane = laneNo & 0xff;
else else
rightLane = uVar29 & 0xff; rightLane = laneNo & 0xff;
// if speed lane, use other first lane. WTF idk why
uVar17 = ROAD_HAS_FAST_LANES(_st); // counter count = ROAD_HAS_FAST_LANES(_st); // counter
uVar29 = widthInLanes; // bestLane laneNo = widthInLanes; // bestLane
while (uVar17 < widthInLanes) while (count < widthInLanes)
{ {
if(ROAD_IS_AI_LANE(_st, uVar17) && !ROAD_IS_PARKING_ALLOWED_AT(_st, uVar17)) if(ROAD_IS_AI_LANE(_st, count) && !ROAD_IS_PARKING_ALLOWED_AT(_st, count))
{ {
test555 = ROAD_LANE_DIR(_st, uVar17) ^ 1; test555 = ROAD_LANE_DIR(_st, count) ^ 1;
uVar29 = uVar17; laneNo = count;
if (test555 == 0) if (test555 == 0)
{ {
@ -676,133 +678,84 @@ int GetNextRoadInfo(_CAR_DATA* cp, int randomExit, int* turnAngle, int* startDis
break; break;
} }
} }
uVar29 = widthInLanes; laneNo = widthInLanes;
uVar17++; count++;
} }
if (currentLaneDir != 0) if (currentLaneDir != 0)
leftLane = uVar29 & 0xff; leftLane = laneNo & 0xff;
else else
rightLane = uVar29 & 0xff; rightLane = laneNo & 0xff;
} }
else if(IS_CURVED_SURFACE(currentRoadId)) else if(IS_CURVED_SURFACE(currentRoadId))
{ {
int currentLaneDir;
int widthInLanes;
int laneNo;
int count;
____cv = GET_CURVE(currentRoadId); ____cv = GET_CURVE(currentRoadId);
if (*(short*)&____cv->NumLanes == -0xff) widthInLanes = ROAD_WIDTH_IN_LANES(____cv);
{
uVar9 = (uint)cp->ai.c.currentLane; currentLaneDir = ROAD_LANE_DIR(____cv, cp->ai.c.currentLane);
} oldOppDir = currentLaneDir << 0xb;
tmpNewRoad[0] = ____cv->ConnectIdx[currentLaneDir * 2];
if (currentLaneDir != 0)
tmpNewRoad[1] = ____cv->ConnectIdx[3];
else else
tmpNewRoad[1] = ____cv->ConnectIdx[1];
count = widthInLanes; // counter
laneNo = widthInLanes; // bestLane
do
{ {
uVar9 = (int)(u_char)____cv->LaneDirs >> ((uint)(cp->ai.c.currentLane >> 1) & 0x1f); count--;
} if(ROAD_IS_AI_LANE(____cv, count) && !ROAD_IS_PARKING_ALLOWED_AT(____cv, count))
uVar9 = uVar9 & 1;
oldOppDir = uVar9 << 0xb;
if (*(short*)&____cv->NumLanes == -0xff)
{
uVar29 = (uint)cp->ai.c.currentLane;
}
else
{
uVar29 = (int)(u_char)____cv->LaneDirs >> ((uint)(cp->ai.c.currentLane >> 1) & 0x1f);
}
tmpNewRoad[0] = (int)____cv->ConnectIdx[(uVar29 & 1) * 2];
if (*(short*)&____cv->NumLanes == -0xff)
{
uVar29 = (uint)cp->ai.c.currentLane;
}
else
{
uVar29 = (int)(u_char)____cv->LaneDirs >> ((uint)(cp->ai.c.currentLane >> 1) & 0x1f);
}
iVar22 = 2;
if ((uVar29 & 1) != 0)
iVar22 = 6;
tmpNewRoad[1] = (int)*(short*)((int)____cv->ConnectIdx + iVar22);
uVar25 = ((u_char)____cv->NumLanes & 0xf) * 2;
uVar29 = uVar25;
do {
do {
uVar29 = uVar29 - 1;
uVar16 = uVar25;
if ((int)uVar29 < 0)
{
goto LAB_000245c0_break;
}
} while (((int)(u_char)____cv->AILanes >> ((int)uVar29 / 2 & 0x1fU) & 1U) == 0 ||
uVar29 == 0 && (____cv->NumLanes & 0x40U) != 0 ||
((u_char)____cv->NumLanes & 0xffffff0f) * 2 - 1 == uVar29 &&
(____cv->NumLanes & 0x80U) != 0);
uVar16 = uVar29;
if (*(short*)&____cv->NumLanes != -0xff)
{ {
uVar16 = (int)(u_char)____cv->LaneDirs >> ((int)uVar29 / 2 & 0x1fU); test42 = ROAD_LANE_DIR(____cv, count);
laneNo = count;
} }
} while (count >= 0);
test42 = (uVar16 ^ 1) & 1; if (currentLaneDir == 0)
uVar16 = uVar29; leftLane = laneNo & 0xff;
} while (uVar9 == 0);
LAB_000245c0_break:
if (uVar9 == 0)
leftLane = uVar16 & 0xff;
else else
rightLane = uVar16 & 0xff; rightLane = laneNo & 0xff;
uVar25 = (u_char)____cv->NumLanes; // if speed lane, use other first lane. WTF idk why
uVar20 = (uVar25 & 0xf) << 1; count = ROAD_HAS_FAST_LANES(____cv); // counter
uVar16 = (u_char)(____cv->NumLanes >> 6) & 1; laneNo = widthInLanes; // bestLane
uVar29 = uVar20;
if (uVar16 < uVar20) while (count < widthInLanes)
{ {
do { if(ROAD_IS_AI_LANE(____cv, count) && !ROAD_IS_PARKING_ALLOWED_AT(____cv, count))
if (((int)(u_char)____cv->AILanes >> ((int)uVar16 / 2 & 0x1fU) & 1U) != 0 && (uVar16 != 0 || (____cv->NumLanes & 0x40U) == 0) && {
((uVar25 & 0xffffff0f) * 2 - 1 != uVar16 || (uVar25 & 0x80) == 0)) test555 = ROAD_LANE_DIR(____cv, count) ^ 1;
laneNo = count;
if (test555 == 0)
{ {
uVar29 = uVar16; if (currentLaneDir != 0)
break;
if (*(short*)&____cv->NumLanes != -0xff)
{
uVar29 = (int)(u_char)____cv->LaneDirs >> ((int)uVar16 / 2 & 0x1fU);
}
test555 = (uVar29 ^ 1) & 1;
uVar29 = uVar16;
if (test555 == 0)
{
if (uVar9 != 0)
break;
}
else
{
if (uVar9 == 0)
break;
}
} }
uVar25 = (u_char)____cv->NumLanes; else
uVar16 = uVar16 + 1; {
uVar29 = uVar20; if (currentLaneDir == 0)
} while ((int)uVar16 < (int)((uVar25 & 0xffffff0f) << 1)); break;
}
}
laneNo = widthInLanes;
count++;
} }
if (uVar9 == 0) if (currentLaneDir != 0)
rightLane = uVar29 & 0xff; leftLane = laneNo & 0xff;
else else
leftLane = uVar29 & 0xff; rightLane = laneNo & 0xff;
} }
iVar22 = tmpNewRoad[0]; iVar22 = tmpNewRoad[0];
@ -3430,10 +3383,6 @@ int CreateNewNode(_CAR_DATA * cp)
// [D] [T] // [D] [T]
int InitCivState(_CAR_DATA * cp, EXTRA_CIV_DATA * extraData) int InitCivState(_CAR_DATA * cp, EXTRA_CIV_DATA * extraData)
{ {
int uVar1;
long lVar2;
int iVar3;
CIV_STATE* cs = &cp->ai.c; CIV_STATE* cs = &cp->ai.c;
cp->controlType = CONTROL_TYPE_CIV_AI; cp->controlType = CONTROL_TYPE_CIV_AI;
@ -3462,27 +3411,17 @@ int InitCivState(_CAR_DATA * cp, EXTRA_CIV_DATA * extraData)
// init road and nodes // init road and nodes
if (cs->currentRoad > -1) if (cs->currentRoad > -1)
{ {
DRIVER2_CURVE* crv; DRIVER2_ROAD_INFO roadInfo;
DRIVER2_STRAIGHT* str;
cp->ai.c.currentNode = 0; cp->ai.c.currentNode = 0;
cp->ai.c.pnode = NULL; cp->ai.c.pnode = NULL;
cp->ai.c.ctrlNode = NULL; cp->ai.c.ctrlNode = NULL;
cp->ai.c.turnNode = -1; cp->ai.c.turnNode = -1;
if (IS_CURVED_SURFACE(cs->currentRoad) || IS_STRAIGHT_SURFACE(cs->currentRoad)) if(GetSurfaceRoadInfo(&roadInfo, cs->currentRoad))
{ {
if (IS_STRAIGHT_SURFACE(cs->currentRoad)) cp->ai.c.maxSpeed = speedLimits[ROAD_SPEED_LIMIT(&roadInfo)];
{
str = GET_STRAIGHT(cs->currentRoad);
cp->ai.c.maxSpeed = speedLimits[ROAD_SPEED_LIMIT(str)];
}
else
{
crv = GET_CURVE(cs->currentRoad);
cp->ai.c.maxSpeed = speedLimits[ROAD_SPEED_LIMIT(crv)];
}
InitNodeList(cp, extraData); InitNodeList(cp, extraData);
cp->ai.c.pnode = &cp->ai.c.targetRoute[0]; cp->ai.c.pnode = &cp->ai.c.targetRoute[0];
@ -4344,8 +4283,12 @@ int PingInCivCar(int minPingInDist)
int model; int model;
_CAR_DATA* carCnt; _CAR_DATA* carCnt;
_CAR_DATA* newCar; _CAR_DATA* newCar;
DRIVER2_CURVE* curve;
DRIVER2_STRAIGHT* straight; //DRIVER2_CURVE* curve;
//DRIVER2_STRAIGHT* straight;
DRIVER2_ROAD_INFO roadInfo;
_EXTRA_CIV_DATA civDat; _EXTRA_CIV_DATA civDat;
unsigned char possibleLanes[12]; unsigned char possibleLanes[12];
// carDistLanes removed as it's unused // carDistLanes removed as it's unused
@ -4361,10 +4304,11 @@ int PingInCivCar(int minPingInDist)
int oldCookieCount; int oldCookieCount;
uint retDistSq; uint retDistSq;
//straight = NULL;
//curve = NULL;
civDat.distAlongSegment = -5; civDat.distAlongSegment = -5;
lane = -1; lane = -1;
straight = NULL;
curve = NULL;
dir = 0xffffff; dir = 0xffffff;
tryPingInParkedCars = 0; tryPingInParkedCars = 0;
@ -4517,31 +4461,27 @@ int PingInCivCar(int minPingInDist)
roadSeg = RoadInCell(&randomLoc); roadSeg = RoadInCell(&randomLoc);
} }
// wtf there were before? car wasn't set to 'confused' state // wtf there were before? car wasn't set to 'confused' state
if (!IS_STRAIGHT_SURFACE(roadSeg) && !IS_CURVED_SURFACE(roadSeg)) if (!GetSurfaceRoadInfo(&roadInfo, roadSeg))
{ {
civPingTest.OffRoad++; civPingTest.OffRoad++;
CIV_STATE_SET_CONFUSED(newCar); CIV_STATE_SET_CONFUSED(newCar);
return 0; return 0;
} }
// I wonder if next code was sort of a BIG-BIG inline or MACRO also used in other functions
if (IS_STRAIGHT_SURFACE(roadSeg))
{ {
int numPossibleLanes; int numPossibleLanes;
int numLanes; int numLanes;
int allowedToPark; int allowedToPark;
straight = GET_STRAIGHT(roadSeg); if (ROAD_LANES_COUNT(&roadInfo) == 0) // BAD ROAD
if (ROAD_LANES_COUNT(straight) == 0) // BAD ROAD
{ {
CIV_STATE_SET_CONFUSED(newCar); CIV_STATE_SET_CONFUSED(newCar);
return 0; return 0;
} }
numLanes = ROAD_WIDTH_IN_LANES(straight); numLanes = ROAD_WIDTH_IN_LANES(&roadInfo);
numPossibleLanes = 0; numPossibleLanes = 0;
@ -4556,7 +4496,7 @@ int PingInCivCar(int minPingInDist)
while (i < numLanes) while (i < numLanes)
{ {
// collect the lanes. // collect the lanes.
allowedToPark = ROAD_IS_PARKING_ALLOWED_AT(straight, i); allowedToPark = ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, i);
// this is closest to OG decompiled. Works different! // this is closest to OG decompiled. Works different!
//if (( //if ((
@ -4564,7 +4504,7 @@ int PingInCivCar(int minPingInDist)
// ((ROAD_IS_AI_LANE(straight, i) && (((i != 0 || ((straight->NumLanes & 0x40U) == 0)) && (((straight->NumLanes & 0xffffff0f) * 2 - 1 != i || ((straight->NumLanes & 0x80U) == 0)))))))) // ((ROAD_IS_AI_LANE(straight, i) && (((i != 0 || ((straight->NumLanes & 0x40U) == 0)) && (((straight->NumLanes & 0xffffff0f) * 2 - 1 != i || ((straight->NumLanes & 0x80U) == 0))))))))
// pick only non-parkable driveable lanes if parked cars not requested // pick only non-parkable driveable lanes if parked cars not requested
if (tryPingInParkedCars && allowedToPark || ROAD_IS_AI_LANE(straight, i) && !allowedToPark) if (tryPingInParkedCars && allowedToPark || ROAD_IS_AI_LANE(&roadInfo, i) && !allowedToPark)
possibleLanes[numPossibleLanes++] = i; possibleLanes[numPossibleLanes++] = i;
i++; i++;
@ -4577,89 +4517,19 @@ int PingInCivCar(int minPingInDist)
} }
// check if need to make a parked car // check if need to make a parked car
if (ROAD_IS_PARKING_ALLOWED_AT(straight, lane)) if (ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, lane))
{ {
civDat.thrustState = 3; civDat.thrustState = 3;
civDat.ctrlState = 7; civDat.ctrlState = 7;
// set to drive off // set to drive off
if (ROAD_IS_AI_LANE(straight, lane)) if (ROAD_IS_AI_LANE(&roadInfo, lane))
civDat.ctrlState = 5; civDat.ctrlState = 5;
} }
else else
{ {
// Car is not active. Permanently parked // Car is not active. Permanently parked
if (ROAD_IS_AI_LANE(straight, lane) == 0) if (ROAD_IS_AI_LANE(&roadInfo, lane) == 0)
{
civPingTest.NotDrivable++;
return 0;
}
civDat.thrustState = 0;
civDat.ctrlState = 0;
}
}
else if (IS_CURVED_SURFACE(roadSeg))
{
int numPossibleLanes;
int numLanes;
int allowedToPark;
curve = GET_CURVE(roadSeg);
if (ROAD_LANES_COUNT(curve) == 0) // BAD ROAD
{
CIV_STATE_SET_CONFUSED(newCar);
return 0;
}
numLanes = ROAD_WIDTH_IN_LANES(curve);
numPossibleLanes = 0;
i = 0;
while (i < numLanes)
{
// collect the lanes.
allowedToPark = ROAD_IS_PARKING_ALLOWED_AT(curve, i);
// this is closest to OG decompiled. Works different!
//if ((
// ((tryPingInParkedCars && allowedToPark))) ||
// ((ROAD_IS_AI_LANE(curve, i) && (((i != 0 || ((curve->NumLanes & 0x40U) == 0)) && (((curve->NumLanes & 0xffffff0f) * 2 - 1 != i || ((curve->NumLanes & 0x80U) == 0))))))))
// pick only non-parkable driveable lanes if parked cars not requested
if (tryPingInParkedCars && allowedToPark || ROAD_IS_AI_LANE(curve, i) && !allowedToPark)
possibleLanes[numPossibleLanes++] = i;
i++;
}
if (numPossibleLanes == 0)
return 0;
lane = possibleLanes[(Random2(0) >> 8) % numPossibleLanes];
if (lane > ROAD_WIDTH_IN_LANES(curve))
{
CIV_STATE_SET_CONFUSED(newCar);
return 0;
}
// check if need to make a parked car
if (ROAD_IS_PARKING_ALLOWED_AT(curve, lane))
{
civDat.thrustState = 3;
civDat.ctrlState = 7;
// set to drive off
if (ROAD_IS_AI_LANE(curve, lane))
civDat.ctrlState = 5;
}
else
{
// Car is not active. Permanently parked
if (ROAD_IS_AI_LANE(curve, lane) == 0)
{ {
civPingTest.NotDrivable++; civPingTest.NotDrivable++;
return 0; return 0;
@ -4773,69 +4643,69 @@ int PingInCivCar(int minPingInDist)
minDistAlong = 0; minDistAlong = 0;
} }
if (straight->length <= (scDist + lbody) * 2) // don't spawn outside straight if (roadInfo.straight->length <= (scDist + lbody) * 2) // don't spawn outside straight
return 0; return 0;
dx = randomLoc.vx - straight->Midx; dx = randomLoc.vx - roadInfo.straight->Midx;
dz = randomLoc.vz - straight->Midz; dz = randomLoc.vz - roadInfo.straight->Midz;
theta = (straight->angle - ratan2(dx, dz) & 0xfffU); theta = (roadInfo.straight->angle - ratan2(dx, dz) & 0xfffU);
civDat.distAlongSegment = (straight->length / 2) + FIXEDH(rcossin_tbl[theta * 2 + 1] * SquareRoot0(dx * dx + dz * dz)); civDat.distAlongSegment = (roadInfo.straight->length / 2) + FIXEDH(rcossin_tbl[theta * 2 + 1] * SquareRoot0(dx * dx + dz * dz));
if (requestCopCar == 0) if (requestCopCar == 0)
{ {
if (civDat.distAlongSegment < minDistAlong) if (civDat.distAlongSegment < minDistAlong)
civDat.distAlongSegment = minDistAlong; civDat.distAlongSegment = minDistAlong;
if (straight->length - civDat.distAlongSegment < minDistAlong) if (roadInfo.straight->length - civDat.distAlongSegment < minDistAlong)
civDat.distAlongSegment = straight->length - minDistAlong; civDat.distAlongSegment = roadInfo.straight->length - minDistAlong;
} }
if (ROAD_LANE_DIR(straight, lane) == 0) if (ROAD_LANE_DIR(roadInfo.straight, lane) == 0)
dir = straight->angle; dir = roadInfo.straight->angle;
else else
dir = straight->angle + 0x800U & 0xfff; dir = roadInfo.straight->angle + 0x800U & 0xfff;
} }
else if (IS_CURVED_SURFACE(roadSeg)) else if (IS_CURVED_SURFACE(roadSeg))
{ {
int minDistAlong; int minDistAlong;
int segmentLen; int segmentLen;
currentAngle = ratan2(randomLoc.vx - curve->Midx, randomLoc.vz - curve->Midz); currentAngle = ratan2(randomLoc.vx - roadInfo.curve->Midx, randomLoc.vz - roadInfo.curve->Midz);
minDistAlong = 0; minDistAlong = 0;
if (requestCopCar == 0) if (requestCopCar == 0)
{ {
if (curve->inside > 9) if (roadInfo.curve->inside > 9)
minDistAlong = 32; minDistAlong = 32;
else if (curve->inside < 20) else if (roadInfo.curve->inside < 20)
minDistAlong = 64; minDistAlong = 64;
else else
minDistAlong = 128; minDistAlong = 128;
} }
if (curve->inside > 9) if (roadInfo.curve->inside > 9)
civDat.distAlongSegment = (currentAngle & 0xfffU) - curve->start & 0xfe0; civDat.distAlongSegment = (currentAngle & 0xfffU) - roadInfo.curve->start & 0xfe0;
else if (curve->inside < 20) else if (roadInfo.curve->inside < 20)
civDat.distAlongSegment = (currentAngle & 0xfffU) - curve->start & 0xfc0; civDat.distAlongSegment = (currentAngle & 0xfffU) - roadInfo.curve->start & 0xfc0;
else else
civDat.distAlongSegment = (currentAngle & 0xfffU) - curve->start & 0xf80; civDat.distAlongSegment = (currentAngle & 0xfffU) - roadInfo.curve->start & 0xf80;
if (civDat.distAlongSegment <= minDistAlong) if (civDat.distAlongSegment <= minDistAlong)
civDat.distAlongSegment = minDistAlong; civDat.distAlongSegment = minDistAlong;
segmentLen = (curve->end - curve->start) - segmentLen & 0xfff; segmentLen = (roadInfo.curve->end - roadInfo.curve->start) - segmentLen & 0xfff;
if (civDat.distAlongSegment >= segmentLen) if (civDat.distAlongSegment >= segmentLen)
civDat.distAlongSegment = segmentLen; civDat.distAlongSegment = segmentLen;
if (ROAD_LANE_DIR(curve, lane) == 0) if (ROAD_LANE_DIR(roadInfo.curve, lane) == 0)
dir = civDat.distAlongSegment + curve->start + 0x400; dir = civDat.distAlongSegment + roadInfo.curve->start + 0x400;
else else
dir = civDat.distAlongSegment + curve->start - 0x400; dir = civDat.distAlongSegment + roadInfo.curve->start - 0x400;
curveLength = ((curve->end - curve->start & 0xfffU) * curve->inside * 11) / 7; curveLength = ((roadInfo.curve->end - roadInfo.curve->start & 0xfffU) * roadInfo.curve->inside * 11) / 7;
if (lbody * 6 > curveLength) // don't spawn outside curve if (lbody * 6 > curveLength) // don't spawn outside curve
return 0; return 0;
@ -4853,7 +4723,7 @@ int PingInCivCar(int minPingInDist)
return 0; return 0;
} }
GetNodePos(straight, NULL, curve, civDat.distAlongSegment, newCar, &newCar->ai.c.targetRoute[0].x, &newCar->ai.c.targetRoute[0].z, lane); GetNodePos(roadInfo.straight, NULL, roadInfo.curve, civDat.distAlongSegment, newCar, &newCar->ai.c.targetRoute[0].x, &newCar->ai.c.targetRoute[0].z, lane);
retDistSq = 0x7fffffff; // INT_MAX retDistSq = 0x7fffffff; // INT_MAX
pos[0] = newCar->ai.c.targetRoute[0].x; pos[0] = newCar->ai.c.targetRoute[0].x;
@ -4983,29 +4853,17 @@ int PingInCivCar(int minPingInDist)
void AttemptUnPark(_CAR_DATA * cp) void AttemptUnPark(_CAR_DATA * cp)
{ {
unsigned char oldLane; unsigned char oldLane;
int curRoad; DRIVER2_ROAD_INFO roadInfo;
DRIVER2_STRAIGHT* straight;
DRIVER2_CURVE* curve;
straight = NULL;
curve = NULL;
InitCivState(cp, NULL); InitCivState(cp, NULL);
curRoad = cp->ai.c.currentRoad;
if (IS_STRAIGHT_SURFACE(curRoad))
straight = GET_STRAIGHT(curRoad);
else // actually there might be a bug - it might need additional IS_CURVED_SURFACE check
curve = GET_CURVE(curRoad);
oldLane = cp->ai.c.currentLane; oldLane = cp->ai.c.currentLane;
if (straight && curve) if(GetSurfaceRoadInfo(&roadInfo, cp->ai.c.currentRoad))
{ {
cp->ai.c.currentLane = CheckChangeLanes(straight, curve, cp->ai.c.targetRoute[0].distAlongSegment, cp, 0); cp->ai.c.currentLane = CheckChangeLanes(roadInfo.straight, roadInfo.curve, cp->ai.c.targetRoute[0].distAlongSegment, cp, 0);
if (oldLane == cp->ai.c.currentLane || if (oldLane == cp->ai.c.currentLane || ROAD_IS_AI_LANE(&roadInfo, cp->ai.c.currentLane) == 0)
(straight != NULL && ROAD_IS_AI_LANE(straight, cp->ai.c.currentLane) == 0) ||
(curve != NULL && ROAD_IS_AI_LANE(curve, cp->ai.c.currentLane) == 0))
{ {
// shut off. Unknown intention // shut off. Unknown intention
CIV_STATE_SET_CONFUSED(cp); CIV_STATE_SET_CONFUSED(cp);
@ -6890,10 +6748,13 @@ void CreateRoadblock(void)
CAR_COSMETICS* car_cos; CAR_COSMETICS* car_cos;
_CAR_DATA* cp; _CAR_DATA* cp;
int distAlongSegment; int distAlongSegment;
DRIVER2_CURVE* crv; DRIVER2_CURVE* crv;
DRIVER2_STRAIGHT* str;
VECTOR startPos; VECTOR startPos;
VECTOR endPos; VECTOR endPos;
DRIVER2_STRAIGHT* str;
VECTOR currentPos; VECTOR currentPos;
int numLanes; int numLanes;
int externalCopModel; int externalCopModel;

View File

@ -28,7 +28,7 @@
#define ROAD_LANE_DIR(rd, lane) \ #define ROAD_LANE_DIR(rd, lane) \
(((u_char)rd->LaneDirs == 0xFF && rd->NumLanes == 1) ? (lane & 1) : ROAD_LANE_DIRECTION_BIT(rd, lane)) (((u_char)(rd)->LaneDirs == 0xFF && (rd)->NumLanes == 1) ? ((lane) & 1) : ROAD_LANE_DIRECTION_BIT(rd, lane))
#define ROAD_IS_PARKING_ALLOWED_AT(rd, lane)\ #define ROAD_IS_PARKING_ALLOWED_AT(rd, lane)\
((ROAD_IS_LEFTMOST_LANE_PARKING(rd) && (lane) == 0) || (ROAD_IS_RIGHTMOST_LANE_PARKING(rd) && (lane) == ROAD_WIDTH_IN_LANES(rd) - 1)) ((ROAD_IS_LEFTMOST_LANE_PARKING(rd) && (lane) == 0) || (ROAD_IS_RIGHTMOST_LANE_PARKING(rd) && (lane) == ROAD_WIDTH_IN_LANES(rd) - 1))

View File

@ -569,14 +569,10 @@ void CheckPlayerMiscFelonies(void)
int exitId; int exitId;
int _exitId; int _exitId;
VECTOR *carPos; VECTOR *carPos;
DRIVER2_CURVE *cv; DRIVER2_ROAD_INFO roadInfo;
DRIVER2_STRAIGHT *st;
DRIVER2_JUNCTION *jn; DRIVER2_JUNCTION *jn;
_CAR_DATA* cp; _CAR_DATA* cp;
cv = NULL;
st = NULL;
if (player[0].playerType == 2 || player[0].playerCarId < 0 || FelonyBar.active == 0) if (player[0].playerType == 2 || player[0].playerCarId < 0 || FelonyBar.active == 0)
return; return;
@ -613,36 +609,50 @@ void CheckPlayerMiscFelonies(void)
playerLastRoad = surfInd; playerLastRoad = surfInd;
goingWrongWay = false; goingWrongWay = false;
// straight or curve if(GetSurfaceRoadInfo(&roadInfo, surfInd))
if (IS_STRAIGHT_SURFACE(surfInd))
{ {
int lane_count; int lane_count;
int lane; // $s0 int lane;
int dx; // $v1 int dx;
int dz; // $a0 int dz;
int crd;
st = GET_STRAIGHT(surfInd); lane_count = ROAD_WIDTH_IN_LANES(&roadInfo);
dx = carPos->vx - st->Midx; if(roadInfo.straight)
dz = carPos->vz - st->Midz;
lane = ROAD_LANES_COUNT(st) - (FIXEDH(dx * rcossin_tbl[(st->angle & 0xfff) * 2 + 1] - dz * rcossin_tbl[(st->angle & 0xfff) * 2]) + 512 >> 9);
lane_count = ROAD_WIDTH_IN_LANES(st);
if (lane < 0)
lane = 0;
if (lane_count <= lane)
lane = lane_count - 1;
// check if on correct lane
if (ROAD_IS_AI_LANE(st, lane))
{ {
int crd; dx = carPos->vx - roadInfo.straight->Midx;
crd = (st->angle - cp->hd.direction) + 0x400U >> 0xb & 1; dz = carPos->vz - roadInfo.straight->Midz;
if (ROAD_LANE_DIR(st, lane) == 0) lane = ROAD_LANES_COUNT(&roadInfo) - (FIXEDH(dx * rcossin_tbl[(roadInfo.straight->angle & 0xfff) * 2 + 1] - dz * rcossin_tbl[(roadInfo.straight->angle & 0xfff) * 2]) + 512 >> 9);
if (lane < 0)
lane = 0;
if (lane_count <= lane)
lane = lane_count - 1;
crd = (roadInfo.straight->angle - cp->hd.direction) + 0x400U >> 0xb & 1;
}
else
{
dx = carPos->vx - roadInfo.curve->Midx;
dz = carPos->vz - roadInfo.curve->Midz;
lane = (SquareRoot0(dx * dx + dz * dz) >> 9) - roadInfo.curve->inside * 2;
if (lane < 0)
lane = 0;
if (lane >= lane_count)
lane = lane_count - 1;
crd = NotTravellingAlongCurve(carPos->vx, carPos->vz, cp->hd.direction, roadInfo.curve);
}
// check if on correct lane
if (ROAD_IS_AI_LANE(&roadInfo, lane))
{
if (ROAD_LANE_DIR(&roadInfo, lane) == 0)
{ {
if (crd == 1) if (crd == 1)
goingWrongWay = true; goingWrongWay = true;
@ -654,72 +664,26 @@ void CheckPlayerMiscFelonies(void)
} }
} }
#if 0 #if 1
printInfo("str lane: %d / %d (%d). AI drive: %d, flg: %d%d%d, dir: %d, spd: %d (wrong way: %d)\n", printInfo("ROAD lane: %d / %d, (%d). AI drive: %d, flg: %d%d%d, dir: %d, spd: %d (wrong way: %d)\n",
lane + 1, lane + 1,
((u_char)st->NumLanes & 0xF) * 2, // lane count. * 2 for both sides as roads are symmetric ((u_char)roadInfo.NumLanes & 0xF) * 2, // lane count. * 2 for both sides as roads are symmetric
IS_NARROW_ROAD(st), IS_NARROW_ROAD(&roadInfo),
((u_char)st->AILanes >> (lane / 2) & 1U), // lane AI driveable flag ((u_char)roadInfo.AILanes >> (lane / 2) & 1U), // lane AI driveable flag
(st->NumLanes & 0x20) > 0, // flag 0 - first lane? (roadInfo.NumLanes & 0x20) > 0, // flag 0 - first lane?
(st->NumLanes & 0x40) > 0, // flag 1 - leftmost park (roadInfo.NumLanes & 0x40) > 0, // flag 1 - leftmost park
(st->NumLanes & 0x80) > 0, // flag 2 - rightmost park (roadInfo.NumLanes & 0x80) > 0, // flag 2 - rightmost park
((u_char)st->LaneDirs >> (lane / 2) & 1U), // direction bit ((u_char)roadInfo.LaneDirs >> (lane / 2) & 1U), // direction bit
((u_char)st->NumLanes >> 4) & 3, // speed limit id ((u_char)roadInfo.NumLanes >> 4) & 3, // speed limit id
goingWrongWay); goingWrongWay);
#endif #endif
// get road speed limit
maxSpeed = speedLimits[ROAD_SPEED_LIMIT(&roadInfo)];
} }
else if(IS_CURVED_SURFACE(surfInd)) else
{ {
int lane_count; maxSpeed = speedLimits[2];
int lane; // $s0
int dx; // $v1
int dz; // $a0
cv = GET_CURVE(surfInd);
dx = carPos->vx - cv->Midx;
dz = carPos->vz - cv->Midz;
lane = (SquareRoot0(dx * dx + dz * dz) >> 9) - cv->inside * 2;
if (lane < 0)
lane = 0;
lane_count = ROAD_WIDTH_IN_LANES(cv);
if (lane >= lane_count)
lane = lane_count - 1;
// check if on correct lane
if (ROAD_IS_AI_LANE(cv, lane))
{
int crd;
crd = NotTravellingAlongCurve(carPos->vx, carPos->vz, cp->hd.direction, cv);
if (ROAD_LANE_DIR(cv, lane) == 0)
{
if (crd != 0)
goingWrongWay = true;
}
else
{
if (crd == 0)
goingWrongWay = true;
}
}
#if 0
printInfo("crv lane: %d / %d, (%d). AI drive: %d, flg: %d%d%d, dir: %d, spd: %d (wrong way: %d)\n",
lane + 1,
((u_char)cv->NumLanes & 0xF) * 2, // lane count. * 2 for both sides as roads are symmetric
IS_NARROW_ROAD(cv),
((u_char)cv->AILanes >> (lane / 2) & 1U), // lane AI driveable flag
(cv->NumLanes & 0x20) > 0, // flag 0 - first lane?
(cv->NumLanes & 0x40) > 0, // flag 1 - leftmost park
(cv->NumLanes & 0x80) > 0, // flag 2 - rightmost park
((u_char)cv->LaneDirs >> (lane / 2) & 1U), // direction bit
((u_char)cv->NumLanes >> 4) & 3, // speed limit id
goingWrongWay);
#endif
} }
// wrong way // wrong way
@ -751,13 +715,6 @@ void CheckPlayerMiscFelonies(void)
NoteFelony(&felonyData, 10, 0x1000); NoteFelony(&felonyData, 10, 0x1000);
// check the speed limit // check the speed limit
if (st != NULL)
maxSpeed = speedLimits[ROAD_SPEED_LIMIT(st)];
else if (cv != NULL)
maxSpeed = speedLimits[ROAD_SPEED_LIMIT(cv)];
else
maxSpeed = speedLimits[2];
if (speedLimits[2] == maxSpeed) if (speedLimits[2] == maxSpeed)
limit = (maxSpeed * 19) >> 4; limit = (maxSpeed * 19) >> 4;
else else