mirror of
https://github.com/OpenDriver2/REDRIVER2.git
synced 2024-11-22 10:22:48 +01:00
Merge branch 'develop-Fireboyd78' of github.com:OpenDriver2/REDRIVER2 into develop-Fireboyd78
This commit is contained in:
commit
0287aa6722
@ -162,13 +162,12 @@ void DrawDebugOverlays()
|
||||
|
||||
int lane = GetLaneByPositionOnRoad(&roadInfo, carPos);
|
||||
|
||||
sprintf(tempBuf, "%s %d flg %d%d%d spd %d len %d",
|
||||
sprintf(tempBuf, "%s %d PRK(%d-%d) SPD(%d) LEN(%d)",
|
||||
roadInfo.straight ? "STR" : "CRV",
|
||||
roadInfo.surfId,
|
||||
(roadInfo.NumLanes & 0x20) > 0, // flag 0 - first lane?
|
||||
(roadInfo.NumLanes & 0x40) > 0, // flag 1 - leftmost park
|
||||
(roadInfo.NumLanes & 0x80) > 0, // flag 2 - rightmost park
|
||||
ROAD_SPEED_LIMIT(&roadInfo), // speed limit id
|
||||
ROAD_IS_LEFTMOST_LANE_PARKING(&roadInfo),
|
||||
ROAD_IS_RIGHTMOST_LANE_PARKING(&roadInfo),
|
||||
ROAD_SPEED_LIMIT(&roadInfo),
|
||||
segLen
|
||||
);
|
||||
|
||||
@ -185,7 +184,7 @@ void DrawDebugOverlays()
|
||||
PrintString(tempBuf, 10, 195);
|
||||
|
||||
sprintf(tempBuf, "c %d %d %d %d",
|
||||
(int)(*roadInfo.ConnectIdx)[0], (int)(*roadInfo.ConnectIdx)[1], (int)(*roadInfo.ConnectIdx)[2], (int)(*roadInfo.ConnectIdx)[3]);
|
||||
(int)roadInfo.ConnectIdx[0], (int)roadInfo.ConnectIdx[1], (int)roadInfo.ConnectIdx[2], (int)roadInfo.ConnectIdx[3]);
|
||||
|
||||
PrintString(tempBuf, 10, 205);
|
||||
}
|
||||
@ -193,10 +192,16 @@ void DrawDebugOverlays()
|
||||
{
|
||||
DRIVER2_JUNCTION* junc = GET_JUNCTION(roadInfo.surfId);
|
||||
|
||||
sprintf(tempBuf, "JUN %d flg %d - c %d %d %d %d",roadInfo.surfId, junc->flags,
|
||||
(int)(*roadInfo.ConnectIdx)[0], (int)(*roadInfo.ConnectIdx)[1], (int)(*roadInfo.ConnectIdx)[2], (int)(*roadInfo.ConnectIdx)[3]);
|
||||
sprintf(tempBuf, "JUN %d TL(%d) YLD(%d)",
|
||||
roadInfo.surfId,
|
||||
(junc->flags & 1), (junc->flags & 2));
|
||||
|
||||
PrintString(tempBuf, 10, 180);
|
||||
|
||||
sprintf(tempBuf, "c %d %d %d %d",
|
||||
(int)roadInfo.ConnectIdx[0], (int)roadInfo.ConnectIdx[1], (int)roadInfo.ConnectIdx[2], (int)roadInfo.ConnectIdx[3]);
|
||||
|
||||
PrintString(tempBuf, 10, 205);
|
||||
}
|
||||
|
||||
|
||||
|
@ -111,8 +111,10 @@ int FrustrumCheck16(PACKED_CELL_OBJECT* pcop, int bounding_sphere)
|
||||
|
||||
ang = FRUSTUM_THRESHOLD - bounding_sphere;
|
||||
|
||||
if (ang <= MIN(result.vx, result.vz))
|
||||
if (ang <= result.vx && ang <= result.vy && ang <= result.vz)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -132,8 +134,10 @@ int FrustrumCheck(VECTOR* pos, int bounding_sphere)
|
||||
|
||||
ang = FRUSTUM_THRESHOLD - bounding_sphere;
|
||||
|
||||
if (ang <= MIN(result.vx, result.vz))
|
||||
if (ang <= result.vx && ang <= result.vy && ang <= result.vz)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -103,6 +103,8 @@ char UglyLowCarLODs[4][10] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
int GetNodePos(DRIVER2_STRAIGHT* straight, DRIVER2_JUNCTION* junction, DRIVER2_CURVE* curve, int distAlongPath, CAR_DATA* cp, int* x, int* z, int laneNo);
|
||||
|
||||
// [D] [T]
|
||||
int InitCar(CAR_DATA* cp, int direction, LONGVECTOR4* startPos, unsigned char control, int model, int palette, char* extraData)
|
||||
{
|
||||
@ -265,6 +267,66 @@ void CivCarFX(CAR_DATA* cp)
|
||||
AddBrakeLight(cp);
|
||||
}
|
||||
|
||||
int GetLeftBoundLane(DRIVER2_ROAD_INFO& roadInfo, int oppDir)
|
||||
{
|
||||
int i, laneCount, laneNo;
|
||||
|
||||
laneCount = ROAD_WIDTH_IN_LANES(&roadInfo);
|
||||
laneNo = laneCount;
|
||||
|
||||
for (i = laneNo - 1; i >= 0; i--)
|
||||
{
|
||||
if (ROAD_IS_AI_LANE(&roadInfo, i) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, i))
|
||||
{
|
||||
test42 = ROAD_LANE_DIR(&roadInfo, i) ^ 1;
|
||||
laneNo = i;
|
||||
|
||||
if (test42 == 0)
|
||||
{
|
||||
if (oppDir != 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oppDir == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return laneNo;
|
||||
};
|
||||
|
||||
int GetRightBoundLane(DRIVER2_ROAD_INFO& roadInfo, int oppDir)
|
||||
{
|
||||
int i, laneCount, laneNo;
|
||||
|
||||
laneCount = ROAD_WIDTH_IN_LANES(&roadInfo);
|
||||
laneNo = ROAD_IS_LEFTMOST_LANE_PARKING(&roadInfo);
|
||||
|
||||
for (i = laneNo; i < laneCount; i++)
|
||||
{
|
||||
if (ROAD_IS_AI_LANE(&roadInfo, i) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, i))
|
||||
{
|
||||
test555 = ROAD_LANE_DIR(&roadInfo, i) ^ 1;
|
||||
laneNo = i;
|
||||
|
||||
if (test555 == 0)
|
||||
{
|
||||
if (oppDir != 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oppDir == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return laneNo;
|
||||
}
|
||||
|
||||
// [D] [T]
|
||||
int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist, CIV_ROUTE_ENTRY* oldNode)
|
||||
{
|
||||
@ -274,34 +336,22 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
DRIVER2_ROAD_INFO currentRoadInfo;
|
||||
DRIVER2_ROAD_INFO roadInfo;
|
||||
|
||||
int currentRoadId = 0;
|
||||
int tmpNewRoad[2];
|
||||
int newExit = 0;
|
||||
int tmpNewLane[2];
|
||||
int laneFit[2];
|
||||
short validExitIdx[4];
|
||||
|
||||
int newLane;
|
||||
int newRoad;
|
||||
int newRoad, newLane, newExit, numExits;
|
||||
int currentRoadId, leftLane, rightLane;
|
||||
|
||||
int numExits;
|
||||
int leftLane;
|
||||
int rightLane;
|
||||
|
||||
int oldOppDir;
|
||||
int oppDir;
|
||||
int turnDir;
|
||||
int currentLaneDir;
|
||||
int oppDir, oldOppDir;
|
||||
int turnDir, currentLaneDir;
|
||||
|
||||
currentRoadId = cp->ai.c.currentRoad;
|
||||
|
||||
if (GetSurfaceRoadInfo(¤tRoadInfo, currentRoadId))
|
||||
{
|
||||
int widthInLanes;
|
||||
int laneNo;
|
||||
int count;
|
||||
|
||||
widthInLanes = ROAD_WIDTH_IN_LANES(¤tRoadInfo);
|
||||
|
||||
currentLaneDir = ROAD_LANE_DIR(¤tRoadInfo, cp->ai.c.currentLane);
|
||||
|
||||
@ -315,76 +365,36 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
dx = oldNode->x - currentRoadInfo.curve->Midx;
|
||||
dz = oldNode->z - currentRoadInfo.curve->Midz;
|
||||
|
||||
oldOppDir = DIFF_ANGLES(ratan2(dx, dz), oldNode->dir); // (((oldNode->dir - ratan2(dx, dz)) + 2048U & 0xfff) - 2048);
|
||||
oldOppDir = DIFF_ANGLES(ratan2(dx, dz), oldNode->dir);
|
||||
oldOppDir = (oldOppDir < 1) * 2048;
|
||||
}
|
||||
|
||||
// first road is picked from road direction
|
||||
tmpNewRoad[0] = ((short*)currentRoadInfo.ConnectIdx)[(oldOppDir > 0) * 2];
|
||||
tmpNewRoad[0] = currentRoadInfo.ConnectIdx[(oldOppDir > 0) * 2];
|
||||
|
||||
// and second picked from lane direction
|
||||
tmpNewRoad[1] = ((short*)currentRoadInfo.ConnectIdx)[(currentLaneDir > 0) ? 3 : 1];
|
||||
tmpNewRoad[1] = currentRoadInfo.ConnectIdx[(currentLaneDir > 0) ? 3 : 1];
|
||||
laneNo = GetLeftBoundLane(currentRoadInfo, currentLaneDir);
|
||||
|
||||
count = widthInLanes; // counter
|
||||
laneNo = widthInLanes; // bestLane
|
||||
|
||||
do
|
||||
{
|
||||
count--;
|
||||
if (ROAD_IS_AI_LANE(¤tRoadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(¤tRoadInfo, count))
|
||||
{
|
||||
test42 = ROAD_LANE_DIR(¤tRoadInfo, count);
|
||||
laneNo = count;
|
||||
}
|
||||
} while (count >= 0);
|
||||
|
||||
if (currentLaneDir == 0)
|
||||
leftLane = laneNo & 0xff;
|
||||
if (oldOppDir == 0)
|
||||
leftLane = laneNo;
|
||||
else
|
||||
rightLane = laneNo & 0xff;
|
||||
rightLane = laneNo;
|
||||
|
||||
// ifhas fast lane, use second lane
|
||||
count = ROAD_HAS_FAST_LANES(¤tRoadInfo);
|
||||
laneNo = widthInLanes;
|
||||
laneNo = GetRightBoundLane(currentRoadInfo, currentLaneDir);
|
||||
|
||||
while (count < widthInLanes)
|
||||
{
|
||||
if (ROAD_IS_AI_LANE(¤tRoadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(¤tRoadInfo, count))
|
||||
{
|
||||
test555 = ROAD_LANE_DIR(¤tRoadInfo, count) ^ 1;
|
||||
laneNo = count;
|
||||
|
||||
if (test555 == 0)
|
||||
{
|
||||
if (currentLaneDir != 0)
|
||||
break;
|
||||
}
|
||||
if (oldOppDir != 0)
|
||||
leftLane = laneNo;
|
||||
else
|
||||
{
|
||||
if (currentLaneDir == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
laneNo = widthInLanes;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (currentLaneDir != 0)
|
||||
leftLane = laneNo & 0xff;
|
||||
else
|
||||
rightLane = laneNo & 0xff;
|
||||
rightLane = laneNo;
|
||||
}
|
||||
|
||||
newLane = -1;
|
||||
|
||||
if (IS_JUNCTION_SURFACE(tmpNewRoad[0]))
|
||||
{
|
||||
int bestExit;
|
||||
|
||||
int exitFrom;
|
||||
int exitCnt;
|
||||
int exitFrom, exitCnt, bestExit;
|
||||
int rnd;
|
||||
numExits = 0;
|
||||
|
||||
cp->ai.c.changeLaneCount = 0;
|
||||
jn = GET_JUNCTION(tmpNewRoad[0]);
|
||||
@ -393,15 +403,13 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
|
||||
// check if road is valid for this junction
|
||||
// by determining connection with junction
|
||||
exitCnt = 0;
|
||||
while(exitCnt < 4)
|
||||
for(exitCnt = 0; exitCnt < 4; exitCnt++)
|
||||
{
|
||||
if(jn->ExitIdx[exitCnt] == currentRoadId)
|
||||
{
|
||||
exitFrom = exitCnt;
|
||||
break;
|
||||
}
|
||||
exitCnt++;
|
||||
}
|
||||
|
||||
if (exitFrom == -1)
|
||||
@ -411,45 +419,46 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
}
|
||||
|
||||
// check directions of exits
|
||||
//printWarning("Checking directions, exitFrom: %d, \n", exitFrom);
|
||||
exitCnt = 0;
|
||||
do {
|
||||
int exitSurfId;
|
||||
int exitIdx = (exitFrom + exitCnt + 1) % 4;
|
||||
int valid;
|
||||
numExits = 0;
|
||||
|
||||
// only need 3 cycles because we don't want make U-turns
|
||||
for (exitCnt = 0; exitCnt < 3; exitCnt++)
|
||||
{
|
||||
int exitSurfId, exitIdx, valid;
|
||||
|
||||
exitIdx = (exitFrom + exitCnt + 1) % 4;
|
||||
|
||||
valid = 0;
|
||||
exitSurfId = jn->ExitIdx[exitIdx];
|
||||
|
||||
if (exitSurfId != -1)
|
||||
{
|
||||
int turnAng;
|
||||
int exitDir;
|
||||
exitDir = ((exitIdx + 4) - exitFrom) % 4;
|
||||
//exitDir = exitDir - (exitDir / 4) * 4;
|
||||
|
||||
if (exitDir == 1)
|
||||
*turnAngle = -1024; // left
|
||||
turnAng = -1024; // left
|
||||
else if (exitDir == 2)
|
||||
*turnAngle = 0; // forward
|
||||
turnAng = 0; // forward
|
||||
else if (exitDir == 3)
|
||||
*turnAngle = 1024; // right
|
||||
turnAng = 1024; // right
|
||||
else
|
||||
*turnAngle = 0; // forward again?
|
||||
turnAng = 0; // forward again?
|
||||
|
||||
test123 = 666;
|
||||
test555 = 666;
|
||||
test42 = 666;
|
||||
|
||||
// current node direction and new direction
|
||||
turnDir = oldNode->dir + *turnAngle;
|
||||
turnDir = oldNode->dir + turnAng;
|
||||
|
||||
if (GetSurfaceRoadInfo(&roadInfo, exitSurfId))
|
||||
{
|
||||
int turnAng;
|
||||
int dx, dz;
|
||||
int laneCount;
|
||||
int numLanes;
|
||||
|
||||
laneCount = ROAD_WIDTH_IN_LANES(&roadInfo);
|
||||
numLanes = ROAD_WIDTH_IN_LANES(&roadInfo);
|
||||
|
||||
if(roadInfo.straight)
|
||||
{
|
||||
@ -460,94 +469,42 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
dx = oldNode->x - roadInfo.curve->Midx;
|
||||
dz = oldNode->z - roadInfo.curve->Midz;
|
||||
|
||||
oppDir = DIFF_ANGLES(ratan2(dx, dz), turnDir);// ((turnDir - ratan2(dx, dz)) + 2048U & 0xfff) - 2048; // [A]
|
||||
oppDir = DIFF_ANGLES(ratan2(dx, dz), turnDir);
|
||||
oppDir = (oppDir < 1) * 2048;
|
||||
}
|
||||
|
||||
turnAng = *turnAngle;
|
||||
|
||||
if (oppDir == 0)
|
||||
turnAng = -turnAng;
|
||||
|
||||
if (turnAng == 0) // going forward
|
||||
{
|
||||
if (oppDir != oldOppDir) // next road is flipped
|
||||
newLane = laneCount - (cp->ai.c.currentLane + 1);
|
||||
newLane = numLanes - (cp->ai.c.currentLane + 1);
|
||||
else
|
||||
newLane = cp->ai.c.currentLane;
|
||||
|
||||
// goes on invalid lane?
|
||||
// [A] bug fix with exitDir == 0
|
||||
if (oppDir == 0 && exitDir == 0 || !ROAD_IS_AI_LANE(&roadInfo, newLane))
|
||||
newLane = -1;
|
||||
}
|
||||
else if (turnAng == -1024) // going left
|
||||
{
|
||||
int count;
|
||||
|
||||
//printInfo("check left\n");
|
||||
|
||||
count = ROAD_HAS_FAST_LANES(&roadInfo); // lane counter
|
||||
newLane = laneCount;
|
||||
|
||||
// check if allowed to go on any of lanes
|
||||
while (count < laneCount)
|
||||
{
|
||||
if (ROAD_IS_AI_LANE(&roadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, count))
|
||||
{
|
||||
test555 = (ROAD_LANE_DIR(&roadInfo, count) ^ 1) & 1;
|
||||
newLane = count;
|
||||
|
||||
if (test555 == 0)
|
||||
{
|
||||
if (oppDir != 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oppDir == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
newLane = laneCount;
|
||||
}
|
||||
newLane = GetRightBoundLane(roadInfo, oppDir);
|
||||
}
|
||||
else if (turnAng == 1024)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = laneCount; // lane counter
|
||||
newLane = laneCount;
|
||||
|
||||
do
|
||||
{
|
||||
if (ROAD_IS_AI_LANE(&roadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, count))
|
||||
{
|
||||
test42 = (ROAD_LANE_DIR(&roadInfo, count) ^ 1) & 1;
|
||||
|
||||
if (test42 == 0)
|
||||
{
|
||||
if (oppDir != 0)
|
||||
newLane = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oppDir == 0)
|
||||
newLane = count;
|
||||
}
|
||||
|
||||
}
|
||||
count--;
|
||||
} while (count >= 0);
|
||||
newLane = GetLeftBoundLane(roadInfo, oppDir);
|
||||
}
|
||||
|
||||
// validate lane
|
||||
if (turnAng == 0 || newLane >= 0 && newLane < laneCount)
|
||||
if (newLane >= 0 && newLane < numLanes)
|
||||
{
|
||||
valid = ROAD_IS_AI_LANE(&roadInfo, newLane) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, newLane);
|
||||
}
|
||||
|
||||
if (oppDir != oldOppDir)
|
||||
{
|
||||
if (currentLaneDir == ROAD_LANE_DIR(&roadInfo, newLane))
|
||||
valid = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentLaneDir != ROAD_LANE_DIR(&roadInfo, newLane))
|
||||
valid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,10 +517,7 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
{
|
||||
validExitIdx[exitCnt] = 42;
|
||||
}
|
||||
|
||||
// only need 3 cycles because we don't want make U-turns
|
||||
exitCnt++;
|
||||
} while (exitCnt < 3);
|
||||
}
|
||||
|
||||
if (leftLane != rightLane && numExits != 1 && ROAD_LANES_COUNT(¤tRoadInfo) > 1)
|
||||
{
|
||||
@ -611,11 +565,9 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
|
||||
newRoad = jn->ExitIdx[bestExit];
|
||||
|
||||
if (turnAngle != NULL)
|
||||
{
|
||||
int invExit;
|
||||
invExit = (bestExit + 4 - exitFrom) % 4;
|
||||
//invExit = invExit - (invExit / 4) * 4;
|
||||
|
||||
if (invExit == 1)
|
||||
*turnAngle = -1024;
|
||||
@ -691,9 +643,9 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
|
||||
turnDir = oldNode->dir + *turnAngle;
|
||||
|
||||
// determine the new lane on the new road
|
||||
{
|
||||
int numLanes;
|
||||
int turnAng;
|
||||
int numLanes, turnAng;
|
||||
|
||||
numLanes = ROAD_WIDTH_IN_LANES(&roadInfo);
|
||||
turnAng = *turnAngle;
|
||||
@ -708,7 +660,7 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
dx = oldNode->x - roadInfo.curve->Midx;
|
||||
dz = oldNode->z - roadInfo.curve->Midz;
|
||||
|
||||
oppDir = DIFF_ANGLES(ratan2(dx, dz), turnDir); // (((turnDir - ratan2(dx, dz)) + 2048U & 0xfff) - 2048);
|
||||
oppDir = DIFF_ANGLES(ratan2(dx, dz), turnDir);
|
||||
oppDir = (oppDir < 1) * 2048;
|
||||
}
|
||||
|
||||
@ -737,67 +689,13 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
}
|
||||
else if (turnAng == -1024)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = ROAD_HAS_FAST_LANES(&roadInfo);
|
||||
newLane = numLanes;
|
||||
|
||||
// check if allowed to go on any of lanes
|
||||
while (count < numLanes)
|
||||
{
|
||||
if (ROAD_IS_AI_LANE(&roadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, count))
|
||||
{
|
||||
test555 = (ROAD_LANE_DIR(&roadInfo, count) ^ 1) & 1;
|
||||
newLane = count;
|
||||
|
||||
if (test555 == 0)
|
||||
{
|
||||
if (oppDir != 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oppDir == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
newLane = numLanes;
|
||||
}
|
||||
|
||||
//printWarning("car %d check left lane, chosen %d\n", cp->id, newLane);
|
||||
newLane = GetRightBoundLane(roadInfo, oppDir);
|
||||
}
|
||||
else if (turnAng == 1024)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = numLanes;
|
||||
newLane = numLanes;
|
||||
|
||||
do
|
||||
{
|
||||
if (ROAD_IS_AI_LANE(&roadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, count))
|
||||
{
|
||||
test42 = (ROAD_LANE_DIR(&roadInfo, count) ^ 1) & 1;
|
||||
|
||||
if (test42 == 0)
|
||||
{
|
||||
if (oppDir != 0)
|
||||
newLane = count;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oppDir == 0)
|
||||
newLane = count;
|
||||
newLane = GetLeftBoundLane(roadInfo, oppDir);
|
||||
}
|
||||
|
||||
}
|
||||
count--;
|
||||
} while (count >= 0);
|
||||
|
||||
//printWarning("car %d check right lane, chosen %d\n", cp->id, newLane);
|
||||
}
|
||||
|
||||
if (*turnAngle != 0)
|
||||
{
|
||||
@ -843,11 +741,23 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
{
|
||||
if (tmpNewRoad[roadCnt] != -1)
|
||||
{
|
||||
int px, pz;
|
||||
int dx, dz;
|
||||
int numLanes;
|
||||
|
||||
numLanes = 0;
|
||||
|
||||
// [A] fix lane changingg issues
|
||||
if(cp->ai.c.changeLaneCount > 0)
|
||||
{
|
||||
GetNodePos(currentRoadInfo.straight, NULL, currentRoadInfo.curve, oldNode->distAlongSegment, NULL, &px, &pz, cp->ai.c.currentLane);
|
||||
}
|
||||
else
|
||||
{
|
||||
px = oldNode->x;
|
||||
pz = oldNode->z;
|
||||
}
|
||||
|
||||
if (GetSurfaceRoadInfo(&roadInfo, tmpNewRoad[roadCnt]))
|
||||
{
|
||||
numLanes = ROAD_WIDTH_IN_LANES(&roadInfo);
|
||||
@ -855,8 +765,8 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
// determine new lane by old node position
|
||||
if(roadInfo.straight)
|
||||
{
|
||||
dx = (oldNode->x - roadInfo.straight->Midx);
|
||||
dz = (oldNode->z - roadInfo.straight->Midz);
|
||||
dx = (px - roadInfo.straight->Midx);
|
||||
dz = (pz - roadInfo.straight->Midz);
|
||||
|
||||
tmpNewLane[roadCnt] = ROAD_LANES_COUNT(&roadInfo)
|
||||
- (FIXEDH(dx * RCOS(roadInfo.straight->angle) - dz * RSIN(roadInfo.straight->angle)) + 512 >> 9);
|
||||
@ -864,8 +774,8 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
}
|
||||
else
|
||||
{
|
||||
dx = oldNode->x - roadInfo.curve->Midx;
|
||||
dz = oldNode->z - roadInfo.curve->Midz;
|
||||
dx = px - roadInfo.curve->Midx;
|
||||
dz = pz - roadInfo.curve->Midz;
|
||||
|
||||
tmpNewLane[roadCnt] = (SquareRoot0(dx * dx + dz * dz) >> 9) - roadInfo.curve->inside * 2;
|
||||
}
|
||||
@ -882,7 +792,6 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// fit new lane
|
||||
newLane = tmpNewLane[roadCnt];
|
||||
|
||||
@ -1055,11 +964,44 @@ void InitNodeList(CAR_DATA* cp, EXTRA_CIV_DATA* extraData)
|
||||
cr->distAlongSegment = extraData->distAlongSegment;
|
||||
}
|
||||
|
||||
// [A] bug fixes the incorrect lane changes
|
||||
void RemapLaneChange(CAR_DATA* cp)
|
||||
{
|
||||
CIV_ROUTE_ENTRY* currentNode;
|
||||
DRIVER2_ROAD_INFO roadInfo;
|
||||
int numLanes, dx, dz;
|
||||
int newLane;
|
||||
|
||||
if (!GetSurfaceRoadInfo(&roadInfo, cp->ai.c.currentRoad))
|
||||
return;
|
||||
|
||||
currentNode = &cp->ai.c.targetRoute[cp->ai.c.currentNode];
|
||||
numLanes = ROAD_WIDTH_IN_LANES(&roadInfo);
|
||||
|
||||
// determine lane on new road by old node position
|
||||
if (roadInfo.straight)
|
||||
{
|
||||
dx = (currentNode->x - roadInfo.straight->Midx);
|
||||
dz = (currentNode->z - roadInfo.straight->Midz);
|
||||
|
||||
newLane = ROAD_LANES_COUNT(&roadInfo)
|
||||
- (FIXEDH(dx * RCOS(roadInfo.straight->angle) - dz * RSIN(roadInfo.straight->angle)) + 512 >> 9);
|
||||
}
|
||||
else
|
||||
{
|
||||
dx = currentNode->x - roadInfo.curve->Midx;
|
||||
dz = currentNode->z - roadInfo.curve->Midz;
|
||||
|
||||
newLane = (SquareRoot0(dx * dx + dz * dz) >> 9) - roadInfo.curve->inside * 2;
|
||||
}
|
||||
|
||||
cp->ai.c.currentLane = newLane;
|
||||
}
|
||||
|
||||
// [D] [T]
|
||||
int GetNodePos(DRIVER2_STRAIGHT* straight, DRIVER2_JUNCTION* junction, DRIVER2_CURVE* curve, int distAlongPath, CAR_DATA* cp, int* x, int* z, int laneNo)
|
||||
{
|
||||
unsigned char oldLane;
|
||||
unsigned char changeLaneCount;
|
||||
u_char oldLane, changeLaneCount;
|
||||
int angle;
|
||||
int distFromCentre;
|
||||
int sideShift;
|
||||
@ -1135,13 +1077,10 @@ int GetNodePos(DRIVER2_STRAIGHT* straight, DRIVER2_JUNCTION* junction, DRIVER2_C
|
||||
// [D] [T]
|
||||
int CheckChangeLanes(DRIVER2_STRAIGHT* straight, DRIVER2_CURVE* curve, int distAlongSegment, CAR_DATA* cp, int tryToPark)
|
||||
{
|
||||
int oldLane;
|
||||
int currentLane;
|
||||
int newLane;
|
||||
int oldLane, newLane, currentLane;
|
||||
int trials;
|
||||
CAR_COSMETICS* car_cos;
|
||||
int dx;
|
||||
int dz;
|
||||
int dx, dz;
|
||||
u_int theta;
|
||||
int length;
|
||||
CAR_DATA* lcp;
|
||||
@ -2244,7 +2183,7 @@ int PingInCivCar(int minPingInDist)
|
||||
// this is closest to OG decompiled. Works different!
|
||||
//if ((
|
||||
// ((tryPingInParkedCars && allowedToPark))) ||
|
||||
// ((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(&roadInfo, i) && (((i != 0 || ((roadInfo.NumLanes & 0x40U) == 0)) && (((roadInfo.NumLanes & 0xffffff0f) * 2 - 1 != i || ((roadInfo.NumLanes & 0x80U) == 0))))))))
|
||||
|
||||
// pick only non-parkable driveable lanes if parked cars not requested
|
||||
if (tryPingInParkedCars && allowedToPark || ROAD_IS_AI_LANE(&roadInfo, i) && !allowedToPark)
|
||||
@ -2943,7 +2882,7 @@ void SetUpCivCollFlags(void)
|
||||
|
||||
if (ABS(cd[0].x.vx - cd[1].x.vx) >= dist ||
|
||||
ABS(cd[0].x.vz - cd[1].x.vz) >= dist ||
|
||||
isTanner && ABS(cd[0].x.vy - cd[1].x.vy) >= 500)
|
||||
ABS(cd[0].x.vy - cd[1].x.vy) >= 500)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -3251,10 +3190,8 @@ int CivFindPointOnPath(CAR_DATA * cp, int station, VECTOR * ppoint)
|
||||
CIV_ROUTE_ENTRY* start;
|
||||
CIV_ROUTE_ENTRY* currentNode;
|
||||
CIV_ROUTE_ENTRY* retNode;
|
||||
int dx;
|
||||
int dz;
|
||||
int sx;
|
||||
int sz;
|
||||
int dx, dz;
|
||||
int sx, sz;
|
||||
|
||||
start = cp->ai.c.pnode;
|
||||
|
||||
|
@ -25,6 +25,22 @@ CAR_COSMETICS car_cosmetics[MAX_CAR_MODELS];
|
||||
CAR_COSMETICS levelSpecCosmetics[5];
|
||||
#endif
|
||||
|
||||
#ifndef PSX
|
||||
// [A] loads car cosmetics from file
|
||||
void LoadCustomCarCosmetics(CAR_COSMETICS* dest, int modelNumber)
|
||||
{
|
||||
char filename[64];
|
||||
|
||||
sprintf(filename, "LEVELS\\%s\\CARMODEL_%d.COS", LevelNames[GameLevel], modelNumber);
|
||||
if (!FileExists(filename))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LoadfileSeg(filename, (char*)dest, 0, sizeof(CAR_COSMETICS));
|
||||
}
|
||||
#endif
|
||||
|
||||
// [D] [T]
|
||||
void ProcessCosmeticsLump(char *lump_ptr, int lump_size)
|
||||
{
|
||||
@ -51,6 +67,9 @@ void ProcessCosmeticsLump(char *lump_ptr, int lump_size)
|
||||
offset = *(int*)(lump_ptr + model * sizeof(int));
|
||||
car_cosmetics[i] = *(CAR_COSMETICS*)((u_char*)lump_ptr + offset);
|
||||
|
||||
#ifndef PSX
|
||||
LoadCustomCarCosmetics(&car_cosmetics[i], model);
|
||||
#endif
|
||||
FixCarCos(&car_cosmetics[i], model);
|
||||
}
|
||||
}
|
||||
|
@ -86,55 +86,6 @@ void FreeCutsceneBuffer();
|
||||
int IsCutsceneResident(int cutscene);
|
||||
|
||||
|
||||
#ifndef PSX
|
||||
char gUserReplayFolderList[MAX_USER_REPLAYS][48];
|
||||
int gNumUserChases = 0;
|
||||
int gUserChaseLoaded = -1;
|
||||
|
||||
// [A] user replay folders initialization
|
||||
void InitUserReplays(const char* str)
|
||||
{
|
||||
int quit;
|
||||
char* ptr;
|
||||
char* strStart;
|
||||
gNumUserChases = 0;
|
||||
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
ptr = (char*)str;
|
||||
strStart = NULL;
|
||||
memset(gUserReplayFolderList, 0, sizeof(gUserReplayFolderList));
|
||||
|
||||
quit = 0;
|
||||
|
||||
while(true)
|
||||
{
|
||||
if (strStart == NULL)
|
||||
strStart = ptr;
|
||||
|
||||
// if we're encountered string end go on
|
||||
if(*ptr == ',' || *ptr == ' ' || *ptr == '\0')
|
||||
{
|
||||
if (*ptr == '\0')
|
||||
quit = 1;
|
||||
|
||||
*ptr = '\0';
|
||||
strcpy(gUserReplayFolderList[gNumUserChases++], strStart);
|
||||
strStart = NULL;
|
||||
}
|
||||
|
||||
ptr++;
|
||||
|
||||
if (quit)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// [D] [T]
|
||||
void InitInGameCutsceneVariables(void)
|
||||
{
|
||||
@ -159,10 +110,6 @@ void InitInGameCutsceneVariables(void)
|
||||
|
||||
gSkipInGameCutscene = 0;
|
||||
|
||||
#ifndef PSX
|
||||
gUserChaseLoaded = -1;
|
||||
#endif
|
||||
|
||||
FreeCutsceneBuffer();
|
||||
}
|
||||
|
||||
@ -236,18 +183,6 @@ void DrawInGameCutscene(void)
|
||||
|
||||
if (gInGameCutsceneActive == 0 && gInGameCutsceneDelay == 0)
|
||||
{
|
||||
#ifndef PSX
|
||||
if(gInGameChaseActive && gUserChaseLoaded != -1 && (CameraCnt - frameStart) < 200)
|
||||
{
|
||||
// [A] print user chaser name on screen
|
||||
char tempStr[80];
|
||||
|
||||
sprintf(tempStr, "%s %s", G_LTXT(GTXT_GetawayIs), gUserReplayFolderList[gUserChaseLoaded]);
|
||||
|
||||
SetTextColour(128, 128, 64);
|
||||
PrintString(tempStr, gOverlayXPos, 230);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -392,56 +327,23 @@ int SelectCutsceneFile(char* filename, int init, int subindex)
|
||||
if (init)
|
||||
{
|
||||
// try load replacement bundle
|
||||
#ifndef PSX
|
||||
int userId = -1;
|
||||
|
||||
// [A] REDRIVER2 PC - custom user chases
|
||||
if (gNumUserChases)
|
||||
{
|
||||
userId = rand() % (gNumUserChases + 1);
|
||||
|
||||
// if random decides to have no user chase - get og or replacement one
|
||||
if (userId == gNumUserChases)
|
||||
userId = -1;
|
||||
}
|
||||
|
||||
// try loading user chase
|
||||
if (userId != -1)
|
||||
sprintf(filename, "REPLAYS\\UserChases\\%s\\CUT%d_N.R", (char*)gUserReplayFolderList[userId], gCurrentMissionNumber);
|
||||
|
||||
if (FileExists(filename))
|
||||
{
|
||||
gUserChaseLoaded = userId;
|
||||
gReChaseAvailable = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sprintf(filename, "REPLAYS\\ReChases\\CUT%d_N.R", gCurrentMissionNumber);
|
||||
gReChaseAvailable = FileExists(filename);
|
||||
}
|
||||
}
|
||||
|
||||
if (subindex >= 2)
|
||||
{
|
||||
if (gReChaseAvailable == 1)
|
||||
{
|
||||
sprintf(filename, "REPLAYS\\ReChases\\CUT%d_N.R", gCurrentMissionNumber);
|
||||
return FileExists(filename);
|
||||
}
|
||||
#ifndef PSX
|
||||
else if (gUserChaseLoaded != -1)
|
||||
{
|
||||
sprintf(filename, "REPLAYS\\UserChases\\%s\\CUT%d_N.R", (char*)gUserReplayFolderList[gUserChaseLoaded], gCurrentMissionNumber);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (gCurrentMissionNumber < 21)
|
||||
sprintf(filename, "REPLAYS\\CUT%d.R", gCurrentMissionNumber);
|
||||
else
|
||||
sprintf(filename, "REPLAYS\\A\\CUT%d.R", gCurrentMissionNumber);
|
||||
}
|
||||
|
||||
return FileExists(filename);
|
||||
}
|
||||
|
@ -13,16 +13,6 @@ struct CUTSCENE_HEADER
|
||||
CUTSCENE_INFO data[15];
|
||||
};
|
||||
|
||||
#ifndef PSX
|
||||
#define MAX_USER_REPLAYS 16
|
||||
|
||||
extern char gUserReplayFolderList[MAX_USER_REPLAYS][48];
|
||||
extern int gNumUserChases;
|
||||
|
||||
extern void InitUserReplays(const char* str);
|
||||
|
||||
#endif // PSX
|
||||
|
||||
extern int NumCutsceneStreams;
|
||||
extern int gSkipInGameCutscene;
|
||||
extern int gInGameCutsceneID;
|
||||
|
@ -2054,18 +2054,17 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture)
|
||||
if (z < 0)
|
||||
z = 0;
|
||||
|
||||
if (z < 10000)
|
||||
tail_width = (10000 - z) >> 0xd;
|
||||
else
|
||||
tail_width = 0;
|
||||
|
||||
addPrim(current->ot + z, poly);
|
||||
current->primptr += sizeof(POLY_FT4);
|
||||
|
||||
|
||||
if (CameraCnt <= 4 || NumPlayers > 1) // [A] don't draw trails in multiplayer
|
||||
return;
|
||||
|
||||
if (z < 10000)
|
||||
tail_width = (10000 - z) >> 13;
|
||||
else
|
||||
return;
|
||||
|
||||
if ((col->cd & 0x20) && gLightsOn)
|
||||
{
|
||||
trails = Known_Lamps[LightIndex].light_trails;
|
||||
@ -2093,8 +2092,8 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture)
|
||||
}
|
||||
|
||||
#ifndef PSX
|
||||
x = (poly->x0 + poly->x3) / 2.0f;
|
||||
y = (poly->y0 + poly->y3) / 2.0f;
|
||||
x = (poly->x0 + poly->x3) * 0.5f;
|
||||
y = (poly->y0 + poly->y3) * 0.5f;
|
||||
#else
|
||||
x = (poly->x0 + poly->x3) / 2;
|
||||
y = (poly->y0 + poly->y3) / 2;
|
||||
@ -2114,7 +2113,11 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture)
|
||||
if (size > 1 && ABS(old_x - x) + ABS(old_y - y) > 1)
|
||||
{
|
||||
int angle, width;
|
||||
VERTTYPE dx, dy;
|
||||
#ifdef PSX
|
||||
int dx, dy;
|
||||
#else
|
||||
float dx, dy;
|
||||
#endif
|
||||
|
||||
trail = (POLY_G4 *)current->primptr;
|
||||
|
||||
@ -2124,19 +2127,18 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture)
|
||||
angle = -ratan2(old_x - x,old_y - y) & 0xfff;
|
||||
width = ABS(poly->x0 - poly->x3);
|
||||
|
||||
#ifdef PSX
|
||||
dx = RCOS(angle) * width * 3;
|
||||
dy = RSIN(angle) * width * 3;
|
||||
|
||||
if (col->cd & 0x40)
|
||||
{
|
||||
dx >>= 0x10;
|
||||
dy >>= 0x10;
|
||||
dx /= 1 << 16;
|
||||
dy /= 1 << 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
dx >>= 0xf;
|
||||
dy >>= 0xf;
|
||||
dx /= 1 << 15;
|
||||
dy /= 1 << 15;
|
||||
}
|
||||
|
||||
trail->x0 = x + dx * tail_width;
|
||||
@ -2150,34 +2152,6 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture)
|
||||
|
||||
trail->x3 = old_x - dx;
|
||||
trail->y3 = old_y - dy;
|
||||
#else
|
||||
// [A] slightly bigger light trail
|
||||
dx = RCOS(angle);
|
||||
dy = RSIN(angle);
|
||||
|
||||
if (col->cd & 0x40)
|
||||
{
|
||||
dx = dx / 40000.0f;
|
||||
dy = dy / 40000.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
dx = dx / 32768.0f;
|
||||
dy = dy / 32768.0f;
|
||||
}
|
||||
|
||||
trail->x0 = x + dx * width * 3 * tail_width;
|
||||
trail->y0 = y + dy * width * 3 * tail_width;
|
||||
|
||||
trail->x1 = x - dx * width * 3 * tail_width;
|
||||
trail->y1 = y - dy * width * 3 * tail_width;
|
||||
|
||||
trail->x2 = old_x + dx * width * 3;
|
||||
trail->y2 = old_y + dy * width * 3;
|
||||
|
||||
trail->x3 = old_x - dx * width * 3;
|
||||
trail->y3 = old_y - dy * width * 3;
|
||||
#endif
|
||||
|
||||
if (col->cd & 0x18)
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ int GetSurfaceRoadInfo(DRIVER2_ROAD_INFO* outRoadInfo, int surfId)
|
||||
if(IS_CURVED_SURFACE(surfId))
|
||||
{
|
||||
outRoadInfo->curve = curve = GET_CURVE(surfId);
|
||||
outRoadInfo->ConnectIdx = &curve->ConnectIdx;
|
||||
outRoadInfo->ConnectIdx = curve->ConnectIdx;
|
||||
outRoadInfo->NumLanes = curve->NumLanes;
|
||||
outRoadInfo->LaneDirs = curve->LaneDirs;
|
||||
outRoadInfo->AILanes = curve->AILanes;
|
||||
@ -110,7 +110,7 @@ int GetSurfaceRoadInfo(DRIVER2_ROAD_INFO* outRoadInfo, int surfId)
|
||||
else if (IS_STRAIGHT_SURFACE(surfId))
|
||||
{
|
||||
outRoadInfo->straight = straight = GET_STRAIGHT(surfId);
|
||||
outRoadInfo->ConnectIdx = &straight->ConnectIdx;
|
||||
outRoadInfo->ConnectIdx = straight->ConnectIdx;
|
||||
outRoadInfo->NumLanes = straight->NumLanes;
|
||||
outRoadInfo->LaneDirs = straight->LaneDirs;
|
||||
outRoadInfo->AILanes = straight->AILanes;
|
||||
@ -119,7 +119,7 @@ int GetSurfaceRoadInfo(DRIVER2_ROAD_INFO* outRoadInfo, int surfId)
|
||||
else if (IS_JUNCTION_SURFACE(surfId))
|
||||
{
|
||||
junction = GET_JUNCTION(surfId);
|
||||
outRoadInfo->ConnectIdx = &junction->ExitIdx;
|
||||
outRoadInfo->ConnectIdx = junction->ExitIdx;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -12,20 +12,25 @@
|
||||
#define GET_CURVE(surfid) (Driver2CurvesPtr + ((surfid) & 0x1FFF))
|
||||
#define GET_JUNCTION(surfid) (Driver2JunctionsPtr + ((surfid) & 0x1FFF))
|
||||
|
||||
// AI lanes - each bit represents lane being enabled for Civ AI to be driven
|
||||
// Lane dirs - each bit represents lane direction invertion
|
||||
// NumLanes - | Lane count (4 bits - max 15) | speed limit id (2 bits - max 3) | Leftmost Lane parking | Rightmost Lane parking
|
||||
|
||||
// $DEPRECATED: as it's used to detect lane direction, use ROAD_LANE_DIR instead
|
||||
#define IS_NARROW_ROAD(rd) \
|
||||
((*(ushort*)&(rd)->NumLanes & 0xFFFF) == 0xFF01)
|
||||
|
||||
// those macros can be applied to straights and junctions
|
||||
#define ROAD_LANES_COUNT(rd) ((u_int)(rd)->NumLanes & 0xF) // lane count
|
||||
#define ROAD_WIDTH_IN_LANES(rd) (ROAD_LANES_COUNT(rd) * 2) // width in lanes
|
||||
#define ROAD_IS_AI_LANE(rd, lane) ((u_char)(rd)->AILanes >> ((lane) / 2) & 1U) // lane AI driveable flag
|
||||
#define ROAD_IS_LEFTMOST_LANE_PARKING(rd) (((u_char)(rd)->NumLanes & 0x40) != 0) // allows parking on leftmost lane
|
||||
#define ROAD_IS_RIGHTMOST_LANE_PARKING(rd) (((u_char)(rd)->NumLanes & 0x80) != 0) // allows parking on rightmost lane
|
||||
#define ROAD_LANE_DIRECTION_BIT(rd, lane) ((u_char)(rd)->LaneDirs >> ((lane) / 2) & 1U) // direction bit
|
||||
#define ROAD_SPEED_LIMIT(rd) (((u_char)(rd)->NumLanes >> 4) & 3) // speed limit id
|
||||
#define ROAD_HAS_FAST_LANES(rd) (((u_char)(rd)->NumLanes >> 6) & 1) // & 0x20; in fact speed limit check too
|
||||
|
||||
#define ROAD_LANES_COUNT(rd) ((u_int)(rd)->NumLanes & 15) // lane count
|
||||
#define ROAD_WIDTH_IN_LANES(rd) (ROAD_LANES_COUNT(rd) * 2) // width in lanes
|
||||
|
||||
#define ROAD_IS_LEFTMOST_LANE_PARKING(rd) (((u_char)(rd)->NumLanes & 0x40) != 0) // bit 7 allows parking on leftmost lane
|
||||
#define ROAD_IS_RIGHTMOST_LANE_PARKING(rd) (((u_char)(rd)->NumLanes & 0x80) != 0) // bit 8 allows parking on rightmost lane
|
||||
|
||||
#define ROAD_SPEED_LIMIT(rd) (((u_char)(rd)->NumLanes >> 4) & 3) // speed limit id
|
||||
|
||||
#define ROAD_LANE_DIR(rd, lane) \
|
||||
(((u_char)(rd)->LaneDirs == 0xFF && (rd)->NumLanes == 1) ? ((lane) & 1) : ROAD_LANE_DIRECTION_BIT(rd, lane))
|
||||
@ -38,7 +43,7 @@ struct DRIVER2_ROAD_INFO
|
||||
{
|
||||
int surfId;
|
||||
|
||||
short (*ConnectIdx)[4];
|
||||
short* ConnectIdx; // [4]
|
||||
char NumLanes;
|
||||
char LaneDirs;
|
||||
char AILanes;
|
||||
|
@ -4324,8 +4324,8 @@ int StopUserMissionEvents(MR_THREAD *thread)
|
||||
|
||||
int RunUserMissionEvents(MR_THREAD *thread)
|
||||
{
|
||||
if (gCurrentMissionNumber >= 50 && gCurrentMissionNumber <= 65)
|
||||
maxCopCars = 32;
|
||||
//if (gCurrentMissionNumber >= 50 && gCurrentMissionNumber <= 65)
|
||||
// maxCopCars = 32;
|
||||
|
||||
return (*fnMissionEventHandlers)[GameLevel](thread, 0);
|
||||
}
|
||||
|
@ -262,10 +262,11 @@ void FixCarCos(CAR_COSMETICS* carCos, int externalModelNumber)
|
||||
car_cosmetics[2].mass *= 3;
|
||||
}
|
||||
|
||||
// [A] vegas box truck
|
||||
if (GameLevel == 2 && externalModelNumber == 10)
|
||||
// [A] wibbly wobbly fuckery hacks...
|
||||
// flag certain cars that have a tendency to go CRAZY at a stand-still
|
||||
if (GameLevel == 2 && externalModelNumber == 10) // vegas box truck
|
||||
{
|
||||
carCos->extraInfo |= 4; // wibbly wobbly fuckery hack...
|
||||
carCos->extraInfo |= 4;
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,6 +335,22 @@ void GlobalTimeStep(void)
|
||||
|
||||
st = &cp->st;
|
||||
|
||||
// [A] bugfix: wibbly wobbly cars
|
||||
// (see end of FixCarCos for cars that have this flag)
|
||||
if (car_cosmetics[cp->ap.model].extraInfo & 4)
|
||||
{
|
||||
if (cp->handbrake && cp->wasOnGround && cp->hd.speed < 3)
|
||||
{
|
||||
cp->hd.aacc[0] >>= 1;
|
||||
cp->hd.aacc[1] >>= 1;
|
||||
cp->hd.aacc[2] >>= 1;
|
||||
|
||||
cp->hd.acc[0] >>= 1;
|
||||
cp->hd.acc[1] >>= 1;
|
||||
cp->hd.acc[2] >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
st->n.linearVelocity[0] += cp->hd.acc[0];
|
||||
st->n.linearVelocity[1] += cp->hd.acc[1];
|
||||
st->n.linearVelocity[2] += cp->hd.acc[2];
|
||||
|
@ -383,7 +383,7 @@ void SetupResidentModels()
|
||||
// force palette
|
||||
if (singlePal)
|
||||
PlayerStartInfo[i]->palette = 0;
|
||||
else
|
||||
else if (wantedColour[i] != -1)
|
||||
PlayerStartInfo[i]->palette = wantedColour[i];
|
||||
|
||||
// store for replay if necessary
|
||||
@ -1280,7 +1280,7 @@ void HandleTimer(MR_TIMER *timer)
|
||||
// [D] [T]
|
||||
void RegisterChaseHit(int car1, int car2)
|
||||
{
|
||||
if (!Mission.ChaseTarget || Mission.ChaseHitDelay == 0)
|
||||
if (!Mission.ChaseTarget || Mission.ChaseHitDelay != 0)
|
||||
return;
|
||||
|
||||
int player_id;
|
||||
|
@ -1719,7 +1719,7 @@ int DrawCharacter(LPPEDESTRIAN pPed)
|
||||
if (pUsedPeds->pNext == NULL && pPed->pedType == TANNER_MODEL)
|
||||
#else
|
||||
// draw a nice shadow for non-civilian peds :)
|
||||
if (pPed->pedType != CIVILIAN)
|
||||
if (pPed->pedType == TANNER_MODEL || pPed->pedType == OTHER_MODEL)
|
||||
#endif
|
||||
{
|
||||
v.vx = (pPed->position.vx - camera_position.vx) + Skel[ROOT].pvOrigPos->vx;
|
||||
|
@ -1001,7 +1001,12 @@ void DrawMultiplayerMap(void)
|
||||
map_z_offset = 0;
|
||||
|
||||
xPos = gMapXOffset;
|
||||
#ifndef PSX
|
||||
// [A] add room for speedometer
|
||||
yPos = gMapYOffset - 4;
|
||||
#else
|
||||
yPos = gMapYOffset;
|
||||
#endif
|
||||
|
||||
DrawMultiplayerTargets();
|
||||
|
||||
|
@ -33,6 +33,7 @@ struct XZDIR
|
||||
short dx, dz;
|
||||
};
|
||||
|
||||
// Fast Marching method
|
||||
ushort distanceCache[16384];
|
||||
char omap[128][16]; // obstacle map 128x128 (bit field)
|
||||
int dunyet[32][2]; // scanned cell map (32x32, multi-level bitfield)
|
||||
@ -147,7 +148,7 @@ void DebugDisplayObstacleMap()
|
||||
n.vx = player[0].pos[0];
|
||||
n.vz = player[0].pos[2];
|
||||
n.vy = pos_y;
|
||||
n.vy = MapHeight((VECTOR*)&n);
|
||||
//n.vy = MapHeight((VECTOR*)&n);
|
||||
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
@ -179,7 +180,7 @@ void DebugDisplayObstacleMap()
|
||||
|
||||
n.vx = px << 8;
|
||||
n.vz = pz << 8;
|
||||
n.vy = MapHeight((VECTOR*)&n);
|
||||
n.vy = 0;// MapHeight((VECTOR*)&n);
|
||||
|
||||
int dist = distanceCache[(n.vx >> 2 & 0x3f80U | n.vz >> 9 & 0x7fU) ^ (n.vy & 1U) * 0x2040 ^ (n.vy & 2U) << 0xc];// distanceCache[((pos_x+i & 127) * 128) + (j + pos_z & 127)];
|
||||
|
||||
@ -270,8 +271,8 @@ void WunCell(VECTOR* pbase)
|
||||
int i, j;
|
||||
|
||||
#if ENABLE_GAME_FIXES
|
||||
// [A] hack with height map (fixes some bits in Havana)
|
||||
height1 = MapHeight(pbase);
|
||||
// start with the base (player) height
|
||||
height1 = pbase->vy;
|
||||
|
||||
pbase->vx += 512;
|
||||
pbase->vz += 512;
|
||||
@ -281,7 +282,9 @@ void WunCell(VECTOR* pbase)
|
||||
pbase->vx -= 512;
|
||||
pbase->vz -= 512;
|
||||
|
||||
if (height1 - v[0].vy > 100)
|
||||
// if base height differs from map height too much (we are on bridge etc)
|
||||
// we then use base height to ensure that obstacles are locally correct
|
||||
if (ABS(height1 - v[0].vy) > 100)
|
||||
v[0].vy = height1;
|
||||
|
||||
v[0].vy += 32;
|
||||
@ -300,6 +303,17 @@ void WunCell(VECTOR* pbase)
|
||||
}
|
||||
}
|
||||
#else
|
||||
pbase->vx = pbase->vx + 512;
|
||||
pbase->vz = pbase->vz + 512;
|
||||
|
||||
height1 = MapHeight(pbase);
|
||||
|
||||
v[0].vy = height1 + 60;
|
||||
|
||||
pbase->vx = pbase->vx - 512;
|
||||
pbase->vz = pbase->vz - 512;
|
||||
v[1].vy = v[0].vy;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
@ -321,14 +335,10 @@ void WunCell(VECTOR* pbase)
|
||||
dz = v[0].vz + v[1].vz >> 1;
|
||||
|
||||
OMapSet(dx >> 8, dz >> 8, lineClear(&v[0], &v[1]) == 0);
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
pbase->vx -= 512;
|
||||
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -501,9 +511,15 @@ int blocked(tNode* v1, tNode* v2)
|
||||
if (slowWallTests != 0)
|
||||
return lineClear((VECTOR*)v1, (VECTOR*)v2) == 0;
|
||||
|
||||
x = v1->vx + v1->vx >> 9;
|
||||
x = v1->vx + v2->vx >> 9;
|
||||
z = v1->vz + v2->vz >> 9;
|
||||
|
||||
int prev = DONEMAP_V(x >> 2, z >> 2);
|
||||
int val = DONEMAP_GETVALUE(x >> 2, z >> 2, prev, 0);
|
||||
|
||||
if (val != 0)
|
||||
return 1;
|
||||
|
||||
return OMAP_GETVALUE(x, z);
|
||||
}
|
||||
|
||||
@ -516,10 +532,10 @@ void setDistance(tNode* n, ushort dist)
|
||||
}
|
||||
|
||||
// [A]
|
||||
void SetNodeDistanceWithParents(tNode* startNode, ushort dist);
|
||||
void pushNode(tNode* startNode, ushort dist);
|
||||
|
||||
// [D] [T]
|
||||
void iterate(void)
|
||||
int iterate(void)
|
||||
{
|
||||
tNode pathNodes[8];
|
||||
|
||||
@ -536,16 +552,14 @@ void iterate(void)
|
||||
int r;
|
||||
|
||||
if (numHeapEntries == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
popNode(&itHere);
|
||||
nbr = pathNodes;
|
||||
|
||||
// check directions
|
||||
for(dir = 0; dir < 6; dir++)
|
||||
for(dir = 0; dir < 6; dir++, nbr++)
|
||||
{
|
||||
nbr++;
|
||||
|
||||
nbr->vx = itHere.vx + dirs[dir].dx;
|
||||
nbr->vy = itHere.vy;
|
||||
nbr->vz = itHere.vz + dirs[dir].dz;
|
||||
@ -560,9 +574,7 @@ void iterate(void)
|
||||
{
|
||||
if (ABS(nbr->vy - itHere.vy) < 201)
|
||||
{
|
||||
if ((dist & 1) == 0)
|
||||
nbr->dist = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -581,18 +593,18 @@ void iterate(void)
|
||||
// now we have distance let's compute the rest of the map
|
||||
for(dir = 0; dir < 6; dir++)
|
||||
{
|
||||
if (pathNodes[dir + 1].dist != 0)
|
||||
if (pathNodes[dir].dist != 0)
|
||||
continue;
|
||||
|
||||
if (dir != 5)
|
||||
nr = pathNodes[dir + 2].dist;
|
||||
nr = pathNodes[dir + 1].dist;
|
||||
else
|
||||
nr = pathNodes[1].dist;
|
||||
nr = pathNodes[0].dist;
|
||||
|
||||
if (dir != 0)
|
||||
nl = pathNodes[dir].dist;
|
||||
nl = pathNodes[dir - 1].dist;
|
||||
else
|
||||
nl = pathNodes[6].dist;
|
||||
nl = pathNodes[5].dist;
|
||||
|
||||
// uhhmm... distance function selection?
|
||||
if (nl < 2)
|
||||
@ -627,8 +639,10 @@ void iterate(void)
|
||||
}
|
||||
}
|
||||
|
||||
SetNodeDistanceWithParents(&pathNodes[dir + 1], dist);
|
||||
pushNode(&pathNodes[dir], dist);
|
||||
}
|
||||
|
||||
return numHeapEntries > 0;
|
||||
}
|
||||
|
||||
// [D] [T]
|
||||
@ -853,7 +867,7 @@ void addCivs(void)
|
||||
}
|
||||
|
||||
// [A]
|
||||
void SetNodeDistanceWithParents(tNode* startNode, ushort dist)
|
||||
void pushNode(tNode* startNode, ushort dist)
|
||||
{
|
||||
int i;
|
||||
u_int pnode, parent;
|
||||
@ -863,6 +877,7 @@ void SetNodeDistanceWithParents(tNode* startNode, ushort dist)
|
||||
|
||||
setDistance(startNode, dist);
|
||||
|
||||
// up heap
|
||||
i = numHeapEntries + 1;
|
||||
|
||||
pnode = i;
|
||||
@ -881,7 +896,7 @@ void SetNodeDistanceWithParents(tNode* startNode, ushort dist)
|
||||
}
|
||||
|
||||
// [A]
|
||||
void ComputeDistanceFromSearchTarget(tNode* startNode)
|
||||
void pushSeedNode(tNode* startNode)
|
||||
{
|
||||
u_short dist;
|
||||
int i, dx, dz;
|
||||
@ -894,7 +909,7 @@ void ComputeDistanceFromSearchTarget(tNode* startNode)
|
||||
|
||||
dist = SquareRoot0( dx * dx + dz * dz ) >> 1;
|
||||
|
||||
SetNodeDistanceWithParents(startNode, dist);
|
||||
pushNode(startNode, dist);
|
||||
}
|
||||
|
||||
// [D] [T]
|
||||
@ -939,14 +954,21 @@ void UpdateCopMap(void)
|
||||
i = 36;
|
||||
|
||||
while (--i >= 0)
|
||||
iterate();
|
||||
{
|
||||
if (!iterate())
|
||||
{
|
||||
pathFrames = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DebugDisplayObstacleMap();
|
||||
|
||||
// remove cars
|
||||
addCivs();
|
||||
}
|
||||
else
|
||||
|
||||
if(pathFrames == 0)
|
||||
{
|
||||
// restart from new search target position
|
||||
if (player[0].playerType == 1 && (CopsCanSeePlayer != 0 || numActiveCops == 0))
|
||||
@ -1001,30 +1023,30 @@ void UpdateCopMap(void)
|
||||
|
||||
if (dz < dx + dz / 2)
|
||||
{
|
||||
ComputeDistanceFromSearchTarget(&startNode);
|
||||
pushSeedNode(&startNode);
|
||||
|
||||
startNode.vx += 256;
|
||||
startNode.vz += 512;
|
||||
|
||||
ComputeDistanceFromSearchTarget(&startNode);
|
||||
pushSeedNode(&startNode);
|
||||
|
||||
startNode.vx += 256;
|
||||
startNode.vz -= 512;
|
||||
|
||||
ComputeDistanceFromSearchTarget(&startNode);
|
||||
pushSeedNode(&startNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
ComputeDistanceFromSearchTarget(&startNode);
|
||||
pushSeedNode(&startNode);
|
||||
|
||||
startNode.vx += 256;
|
||||
startNode.vz += 512;
|
||||
|
||||
ComputeDistanceFromSearchTarget(&startNode);
|
||||
pushSeedNode(&startNode);
|
||||
|
||||
startNode.vx -= 512;
|
||||
|
||||
ComputeDistanceFromSearchTarget(&startNode);
|
||||
pushSeedNode(&startNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1282,7 +1282,7 @@ void SetupGetInCar(LPPEDESTRIAN pPed)
|
||||
|
||||
// HEY!
|
||||
CreatePedAtLocation(&pos, 8);
|
||||
Start3DSoundVolPitch(-1, SOUND_BANK_TANNER, sample, pos[0], pos[1], pos[2], 0, 4096);
|
||||
Start3DSoundVolPitch(-1, SOUND_BANK_TANNER, 5, pos[0], pos[1], pos[2], 0, 4096);
|
||||
|
||||
carToGetIn->controlFlags |= CONTROL_FLAG_WAS_PARKED;
|
||||
}
|
||||
|
@ -285,50 +285,11 @@ int LoadReplayFromBuffer(char *buffer)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef PSX
|
||||
int LoadUserAttractReplay(int mission, int userId)
|
||||
{
|
||||
char customFilename[64];
|
||||
|
||||
if (userId >= 0 && userId < gNumUserChases)
|
||||
{
|
||||
sprintf(customFilename, "REPLAYS\\User\\%s\\ATTRACT.%d", gUserReplayFolderList[userId], mission);
|
||||
|
||||
if (FileExists(customFilename))
|
||||
{
|
||||
if (Loadfile(customFilename, (char*)_other_buffer))
|
||||
return LoadReplayFromBuffer((char*)_other_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// [D] [T]
|
||||
int LoadAttractReplay(int mission)
|
||||
{
|
||||
char filename[32];
|
||||
|
||||
#ifndef PSX
|
||||
int userId = -1;
|
||||
|
||||
// [A] REDRIVER2 PC - custom attract replays
|
||||
if (gNumUserChases)
|
||||
{
|
||||
userId = rand() % (gNumUserChases + 1);
|
||||
|
||||
if (userId == gNumUserChases)
|
||||
userId = -1;
|
||||
}
|
||||
|
||||
if (LoadUserAttractReplay(mission, userId))
|
||||
{
|
||||
printInfo("Loaded custom attract replay (%d) by %s\n", mission, gUserReplayFolderList[userId]);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
sprintf(filename, "REPLAYS\\ATTRACT.%d", mission);
|
||||
|
||||
if (!FileExists(filename))
|
||||
|
@ -213,12 +213,15 @@ void AddWheelForcesDriver1(CAR_DATA* cp, CAR_LOCALS* cl)
|
||||
int player_id;
|
||||
int oldCutRoughness;
|
||||
|
||||
oldSpeed = cp->hd.speed * 3 >> 1;
|
||||
// NB: skips precision every 3rd increment or so
|
||||
int speed = cp->hd.speed * 3 >> 1;
|
||||
|
||||
if (oldSpeed < 32)
|
||||
oldSpeed = oldSpeed * -72 + 3696;
|
||||
if (speed < 32)
|
||||
oldSpeed = 4096 - (72 * speed);
|
||||
else
|
||||
oldSpeed = 1424 - oldSpeed;
|
||||
oldSpeed = 1824 - speed;
|
||||
|
||||
oldSpeed -= 400;
|
||||
|
||||
dir = cp->hd.direction;
|
||||
cdx = RSIN(dir);
|
||||
@ -528,32 +531,6 @@ void AddWheelForcesDriver1(CAR_DATA* cp, CAR_LOCALS* cl)
|
||||
else
|
||||
{
|
||||
cp->hd.wheel_speed = cdz / 64 * (cl->vel[2] / 64) + cdx / 64 * (cl->vel[0] / 64);
|
||||
|
||||
// [A] wibbly wobbly fuckery hack...
|
||||
if (car_cos->extraInfo & 4)
|
||||
{
|
||||
if (cp->thrust == 0 && cp->handbrake && (cp->hd.speed > 0 && cp->hd.speed < 4))
|
||||
{
|
||||
cp->hd.speed--;
|
||||
cp->hd.wheel_speed >>= 1;
|
||||
|
||||
cp->hd.acc[0] >>= 1;
|
||||
cp->hd.acc[1] >>= 1;
|
||||
cp->hd.acc[2] >>= 1;
|
||||
|
||||
cp->hd.aacc[0] >>= 2;
|
||||
cp->hd.aacc[1] >>= 2;
|
||||
cp->hd.aacc[2] >>= 2;
|
||||
|
||||
//cp->st.n.linearVelocity[0] >>= 1;
|
||||
//cp->st.n.linearVelocity[1] >>= 1;
|
||||
//cp->st.n.linearVelocity[2] >>= 1;
|
||||
|
||||
cp->st.n.angularVelocity[0] >>= 2;
|
||||
cp->st.n.angularVelocity[1] >>= 2;
|
||||
cp->st.n.angularVelocity[2] >>= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
#define M_BIT(x) (1 << (x))
|
||||
|
||||
// makes RGB int out of three bytes
|
||||
#define M_INT_RGB(r,g,b) (((r) << 16) | ((g) << 8) | (b))
|
||||
|
||||
//---------------------------------------
|
||||
|
||||
#if !defined( __TYPEINFOGEN__ ) && !defined( _lint ) && defined(_WIN32) // pcLint has problems with assert_offsetof()
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 8fa92c7fba6685c0e9f41804c2f5b68dee4b87e7
|
||||
Subproject commit a04825ea2c1c5c5eecac83ed97cb637d3cab8928
|
@ -565,13 +565,10 @@ int main(int argc, char** argv)
|
||||
{
|
||||
int newScrZ = gCameraDefaultScrZ;
|
||||
const char* dataFolderStr = ini_get(config, "fs", "dataFolder");
|
||||
const char* userReplaysStr = ini_get(config, "game", "userChases");
|
||||
|
||||
if(!cdImageFileName)
|
||||
cdImageFileName = ini_get(config, "cdfs", "image");
|
||||
|
||||
InitUserReplays(userReplaysStr);
|
||||
|
||||
// configure Psy-X pads
|
||||
ini_sget(config, "pad", "pad1device", "%d", &g_cfg_controllerToSlotMapping[0]);
|
||||
ini_sget(config, "pad", "pad2device", "%d", &g_cfg_controllerToSlotMapping[1]);
|
||||
|
Loading…
Reference in New Issue
Block a user