Merge branch 'develop-Fireboyd78' of github.com:OpenDriver2/REDRIVER2 into develop-Fireboyd78

This commit is contained in:
SoapyMan 2023-04-21 22:25:09 +06:00
commit 0287aa6722
21 changed files with 362 additions and 544 deletions

View File

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

View File

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

View File

@ -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(&currentRoadInfo, currentRoadId))
{
int widthInLanes;
int laneNo;
int count;
widthInLanes = ROAD_WIDTH_IN_LANES(&currentRoadInfo);
currentLaneDir = ROAD_LANE_DIR(&currentRoadInfo, 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(&currentRoadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(&currentRoadInfo, count))
{
test42 = ROAD_LANE_DIR(&currentRoadInfo, 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(&currentRoadInfo);
laneNo = widthInLanes;
laneNo = GetRightBoundLane(currentRoadInfo, currentLaneDir);
while (count < widthInLanes)
{
if (ROAD_IS_AI_LANE(&currentRoadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(&currentRoadInfo, count))
{
test555 = ROAD_LANE_DIR(&currentRoadInfo, 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(&currentRoadInfo) > 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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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