Support for additional spawn points in Take-A-Ride.

- Added REPLAY_EXTRA_DATA to store necessary information

- Setup macros for spawn point stuff so PSX version isn't affected

- Fixed 'Player 2' text bug

- Custom location selected using L1/R1 on car select screen
This commit is contained in:
Fireboyd78 2020-12-03 15:56:49 -08:00
parent a225c7252c
commit af44163a4a
9 changed files with 352 additions and 30 deletions

View File

@ -307,6 +307,7 @@ void GameStart(void)
// [A] // [A]
wantedWeather = -1; wantedWeather = -1;
wantedTimeOfDay = -1; wantedTimeOfDay = -1;
wantedStartPos = -1;
gHaveStoredData = 0; gHaveStoredData = 0;

View File

@ -72,16 +72,197 @@
int scr_z = 0; int scr_z = 0;
int levelstartpos[8][4] = { #ifndef PSX
{ 0x12B1, 0xFFFFFC00, 0xFFFC9794, 0}, char *levelstartnames[8][NUM_START_POINTS] = {
{ 0xFFFC74AC, 0x800, 0xFFFC6961, 0}, //
{ 0x383CB, 0xFFFFFC00, 0xABE1E, 0}, // Chicago
{ 0x165EF, 0xFFFFFC00, 0xFFFAB3D9, 0}, //
{ 0x24548, 0x1813, 0xFFFE4A80, 0}, {
{ 0xFFFD67F0, 0x1813, 0x58228, 0}, "Downtown",
{ 0xFFFFD6FC, 0xFFFFE7ED, 0xFFFFA980, 0}, "Greektown",
{ 0xFFFFDCDD, 0xFFFFE7ED, 0xF8A7, 0}, "Chinatown",
"Safehouse",
},
//
// Havana
//
{
NULL,
NULL,
NULL,
NULL,
},
//
// Vegas
//
{
NULL,
NULL,
NULL,
NULL,
},
//
// Rio
//
{
NULL,
NULL,
NULL,
NULL,
},
//
// ???
//
{
NULL,
NULL,
NULL,
NULL,
},
//
// ???
//
{
NULL,
NULL,
NULL,
NULL,
},
//
// ???
//
{
NULL,
NULL,
NULL,
NULL,
},
//
// ???
//
{
NULL,
NULL,
NULL,
NULL,
},
}; };
#endif
#ifndef PSX
#define BEGIN_SPAWN_POINTS {
#define END_SPAWN_POINTS },
#define SPAWN_POINT(...) { __VA_ARGS__ },
#define DEFAULT_SPAWN(...) SPAWN_POINT(__VA_ARGS__)
#else
#define BEGIN_SPAWN_POINTS
#define END_SPAWN_POINTS
#define SPAWN_POINT(...)
#define DEFAULT_SPAWN(...) { __VA_ARGS__ },
#endif
LONGVECTOR levelstartpos[8][NUM_START_POINTS + 1] = {
//
// Chicago
//
BEGIN_SPAWN_POINTS
//SPAWN_POINT(-64840, -1024, -161500, 0) // Downtown car park
//SPAWN_POINT(6216, 0, -222456, 0) // Grant Park (default)
SPAWN_POINT(-95500, 1024, -40225, 0) // Downtown
SPAWN_POINT(-299895, 1024, -122195, 0) // Greektown
SPAWN_POINT(-95980, 0, -501540, 0) // Chinatown
SPAWN_POINT(16800, -1144, 142075, 0) // Safehouse
DEFAULT_SPAWN(4785, -1024, -223340, 0)
END_SPAWN_POINTS
//
// Havana
//
BEGIN_SPAWN_POINTS
SPAWN_POINT(-232276, 2048, -235167, 0) // TODO
SPAWN_POINT(-232276, 2048, -235167, 0) // TODO
SPAWN_POINT(-232276, 2048, -235167, 0) // TODO
SPAWN_POINT(-232276, 2048, -235167, 0) // TODO
DEFAULT_SPAWN(-232276, 2048, -235167, 0)
END_SPAWN_POINTS
//
// Vegas
//
BEGIN_SPAWN_POINTS
SPAWN_POINT(230347, -1024, 704030, 0) // TODO
SPAWN_POINT(230347, -1024, 704030, 0) // TODO
SPAWN_POINT(230347, -1024, 704030, 0) // TODO
SPAWN_POINT(230347, -1024, 704030, 0) // TODO
DEFAULT_SPAWN(230347, -1024, 704030, 0)
END_SPAWN_POINTS
//
// Rio
//
BEGIN_SPAWN_POINTS
SPAWN_POINT(91631, -1024, -347175, 0) // TODO
SPAWN_POINT(91631, -1024, -347175, 0) // TODO
SPAWN_POINT(91631, -1024, -347175, 0) // TODO
SPAWN_POINT(91631, -1024, -347175, 0) // TODO
DEFAULT_SPAWN(91631, -1024, -347175, 0)
END_SPAWN_POINTS
//
// ???
//
BEGIN_SPAWN_POINTS
SPAWN_POINT(148808, 6163, -112000, 0) // TODO
SPAWN_POINT(148808, 6163, -112000, 0) // TODO
SPAWN_POINT(148808, 6163, -112000, 0) // TODO
SPAWN_POINT(148808, 6163, -112000, 0) // TODO
DEFAULT_SPAWN(148808, 6163, -112000, 0)
END_SPAWN_POINTS
//
// ???
//
BEGIN_SPAWN_POINTS
SPAWN_POINT(-170000, 6163, 361000, 0) // TODO
SPAWN_POINT(-170000, 6163, 361000, 0) // TODO
SPAWN_POINT(-170000, 6163, 361000, 0) // TODO
SPAWN_POINT(-170000, 6163, 361000, 0) // TODO
DEFAULT_SPAWN(-170000, 6163, 361000, 0)
END_SPAWN_POINTS
//
// ???
//
BEGIN_SPAWN_POINTS
SPAWN_POINT(-10500, -6163, -22144, 0) // TODO
SPAWN_POINT(-10500, -6163, -22144, 0) // TODO
SPAWN_POINT(-10500, -6163, -22144, 0) // TODO
SPAWN_POINT(-10500, -6163, -22144, 0) // TODO
DEFAULT_SPAWN(-10500, -6163, -22144, 0)
END_SPAWN_POINTS
//
// ???
//
BEGIN_SPAWN_POINTS
SPAWN_POINT(-8995, -6163, 63655, 0) // TODO
SPAWN_POINT(-8995, -6163, 63655, 0) // TODO
SPAWN_POINT(-8995, -6163, 63655, 0) // TODO
SPAWN_POINT(-8995, -6163, 63655, 0) // TODO
DEFAULT_SPAWN(-8995, -6163, 63655, 0)
END_SPAWN_POINTS
};
#ifndef PSX
char * GetLevelStartName(int level, int startpos)
{
if (startpos == -1)
return "Default";
return (startpos < NUM_START_POINTS) ? levelstartnames[level][startpos] : NULL;
}
#endif
XZPAIR gStartPos = { 0 }; XZPAIR gStartPos = { 0 };
@ -3262,6 +3443,13 @@ void InitGameVariables(void)
ClearMem((char*)&lightsOnDelay, sizeof(lightsOnDelay)); ClearMem((char*)&lightsOnDelay, sizeof(lightsOnDelay));
int startpos = 0;
if (NumPlayers == 2)
startpos = NUM_START_POINTS; // fallback to default
else if (wantedStartPos != -1)
startpos = wantedStartPos;
PlayerStartInfo[0] = &ReplayStreams[0].SourceType; PlayerStartInfo[0] = &ReplayStreams[0].SourceType;
#ifdef CUTSCENE_RECORDER #ifdef CUTSCENE_RECORDER
@ -3277,11 +3465,11 @@ void InitGameVariables(void)
PlayerStartInfo[0]->controlType = CONTROL_TYPE_PLAYER; PlayerStartInfo[0]->controlType = CONTROL_TYPE_PLAYER;
PlayerStartInfo[0]->flags = 0; PlayerStartInfo[0]->flags = 0;
PlayerStartInfo[0]->rotation = levelstartpos[GameLevel][1]; PlayerStartInfo[0]->rotation = levelstartpos[GameLevel][startpos][1];
PlayerStartInfo[0]->position.vy = 0; PlayerStartInfo[0]->position.vy = 0;
PlayerStartInfo[0]->position.vx = levelstartpos[GameLevel][0]; PlayerStartInfo[0]->position.vx = levelstartpos[GameLevel][startpos][0];
PlayerStartInfo[0]->position.vz = levelstartpos[GameLevel][2]; PlayerStartInfo[0]->position.vz = levelstartpos[GameLevel][startpos][2];
numPlayersToCreate = 1; numPlayersToCreate = 1;
@ -3296,11 +3484,11 @@ void InitGameVariables(void)
PlayerStartInfo[1]->controlType = CONTROL_TYPE_PLAYER; PlayerStartInfo[1]->controlType = CONTROL_TYPE_PLAYER;
PlayerStartInfo[1]->flags = 0; PlayerStartInfo[1]->flags = 0;
PlayerStartInfo[1]->rotation = levelstartpos[GameLevel][1]; PlayerStartInfo[1]->rotation = levelstartpos[GameLevel][startpos][1];
PlayerStartInfo[1]->position.vy = 0; PlayerStartInfo[1]->position.vy = 0;
PlayerStartInfo[1]->position.vx = levelstartpos[GameLevel][0] + 600; PlayerStartInfo[1]->position.vx = levelstartpos[GameLevel][startpos][0] + 600;
PlayerStartInfo[1]->position.vz = levelstartpos[GameLevel][2]; PlayerStartInfo[1]->position.vz = levelstartpos[GameLevel][startpos][2];
numPlayersToCreate = NumPlayers; numPlayersToCreate = NumPlayers;
} }

View File

@ -29,6 +29,10 @@ extern int DawnCount;
extern int ObjectDrawnValue; extern int ObjectDrawnValue;
extern int ObjectDrawnCounter; extern int ObjectDrawnCounter;
#ifndef PSX
extern char * GetLevelStartName(int level, int startpos);
#endif
extern void SsSetSerialVol(short s_num, short voll, short volr); // TEMPORARY extern void SsSetSerialVol(short s_num, short voll, short volr); // TEMPORARY
typedef void(*occlFunc)(int *comp_val); typedef void(*occlFunc)(int *comp_val);

View File

@ -193,6 +193,7 @@ int wantedCar[2] = { -1, -1 };
// [A] // [A]
int wantedTimeOfDay = -1; int wantedTimeOfDay = -1;
int wantedWeather = -1; int wantedWeather = -1;
int wantedStartPos = -1;
MS_TARGET* MissionTargets; MS_TARGET* MissionTargets;
unsigned long* MissionScript; unsigned long* MissionScript;
@ -502,10 +503,13 @@ void LoadMission(int missionnum)
if (gCutsceneAsReplay == 0) if (gCutsceneAsReplay == 0)
#endif #endif
{ {
PlayerStartInfo[0]->rotation = MissionHeader->playerStartRotation; if (wantedStartPos == -1)
{
PlayerStartInfo[0]->rotation = MissionHeader->playerStartRotation;
PlayerStartInfo[0]->position.vx = MissionHeader->playerStartPosition.x; PlayerStartInfo[0]->position.vx = MissionHeader->playerStartPosition.x;
PlayerStartInfo[0]->position.vz = MissionHeader->playerStartPosition.y; PlayerStartInfo[0]->position.vz = MissionHeader->playerStartPosition.y;
}
#ifdef DEBUG_OPTIONS #ifdef DEBUG_OPTIONS
if(gStartPos.x != 0 && gStartPos.z != 0) if(gStartPos.x != 0 && gStartPos.z != 0)
@ -3592,15 +3596,15 @@ void PreProcessTargets(void)
{ {
PlayerStartInfo[1] = &ReplayStreams[1].SourceType; PlayerStartInfo[1] = &ReplayStreams[1].SourceType;
ReplayStreams[1].SourceType.type = 1; PlayerStartInfo[1]->type = 1;
ReplayStreams[1].SourceType.position.vx = target->data[3]; PlayerStartInfo[1]->position.vx = target->data[3];
ReplayStreams[1].SourceType.position.vy = 0; PlayerStartInfo[1]->position.vy = 0;
ReplayStreams[1].SourceType.position.vz = target->data[4]; PlayerStartInfo[1]->position.vz = target->data[4];
ReplayStreams[1].SourceType.rotation = target->data[5]; PlayerStartInfo[1]->rotation = target->data[5];
ReplayStreams[1].SourceType.model = target->data[7]; PlayerStartInfo[1]->model = target->data[7];
ReplayStreams[1].SourceType.palette = target->data[8]; PlayerStartInfo[1]->palette = target->data[8];
ReplayStreams[1].SourceType.controlType = CONTROL_TYPE_PLAYER; PlayerStartInfo[1]->controlType = CONTROL_TYPE_PLAYER;
ReplayStreams[1].SourceType.flags = 0; PlayerStartInfo[1]->flags = 0;
if (target->data[9] & 3) if (target->data[9] & 3)
target->data[11] = -1; target->data[11] = -1;

View File

@ -65,6 +65,7 @@ extern MR_MISSION Mission;
extern int wantedCar[2]; extern int wantedCar[2];
extern int wantedTimeOfDay; extern int wantedTimeOfDay;
extern int wantedWeather; extern int wantedWeather;
extern int wantedStartPos;
extern int multiplayerregions[4]; extern int multiplayerregions[4];
extern int MaxPlayerDamage[2]; extern int MaxPlayerDamage[2];

View File

@ -249,7 +249,47 @@ int SaveReplayToBuffer(char *buffer)
header->HaveStoredData = 0x91827364; // -0x6e7d8c9c header->HaveStoredData = 0x91827364; // -0x6e7d8c9c
memcpy(pt, &MissionStartData, sizeof(MISSION_DATA)); memcpy(pt, &MissionStartData, sizeof(MISSION_DATA));
} }
#ifndef PSX
REPLAY_EXTRA_DATA extraData;
int extras = 0;
// set default values (-1 = disabled)
// if no overrides are set, the replay will contain junk data instead
memset(&extraData, -1, sizeof(REPLAY_EXTRA_DATA));
if (wantedTimeOfDay != -1)
{
extraData.wantedTimeOfDay = wantedTimeOfDay;
extras++;
}
if (wantedWeather != -1)
{
extraData.wantedWeather = wantedWeather;
extras++;
}
if (wantedStartPos != -1)
{
extraData.wantedStartPos = wantedStartPos;
extras++;
}
//
// TODO: max civ cars, max cops?
//
if (extras > 0)
{
// copy our overrides over
memcpy(&header->extraData, &extraData, sizeof(REPLAY_EXTRA_DATA));
// inform the use of one or more overrides
// once set, the game uses ALL known overrides!
header->HaveExtraData = 0xF12EB12D;
}
#endif
#ifdef PSX #ifdef PSX
return 0x3644; // size? return 0x3644; // size?
#else #else
@ -592,6 +632,16 @@ int LoadReplayFromBuffer(char *buffer)
memcpy(&MissionStartData, pt, sizeof(MISSION_DATA)); memcpy(&MissionStartData, pt, sizeof(MISSION_DATA));
gHaveStoredData = 1; gHaveStoredData = 1;
} }
#ifndef PSX
if (header->HaveExtraData == 0xF12EB12D)
{
wantedStartPos = header->extraData.wantedStartPos;
wantedTimeOfDay = header->extraData.wantedTimeOfDay;
wantedWeather = header->extraData.wantedWeather;
//
// TODO: max civ cars, max cops?
}
#endif
return 1; return 1;
} }

View File

@ -41,5 +41,12 @@
#define MAX_SIREN_NOISES 2 #define MAX_SIREN_NOISES 2
#define MAX_CAR_NOISES 4 #define MAX_CAR_NOISES 4
// misc. limits
#ifndef PSX
#define NUM_START_POINTS 4
#else
// no additional spawn points
#define NUM_START_POINTS 0
#endif
#endif // DRLIMITS_H #endif // DRLIMITS_H

View File

@ -964,6 +964,16 @@ struct REPLAY_PARAMETER_BLOCK
unsigned char weather; unsigned char weather;
}; };
struct REPLAY_EXTRA_DATA
{
char wantedTimeOfDay;
char wantedWeather;
char wantedStartPos;
char reserved1;
int reserved2[4];
};
struct REPLAY_SAVE_HEADER struct REPLAY_SAVE_HEADER
{ {
unsigned long magic; unsigned long magic;
@ -980,7 +990,14 @@ struct REPLAY_SAVE_HEADER
int wantedCar[2]; int wantedCar[2];
int MissionNumber; int MissionNumber;
int HaveStoredData; int HaveStoredData;
#ifndef PSX
// only valid if HaveExtraData is correct;
// otherwise, this is all junk data
REPLAY_EXTRA_DATA extraData;
int HaveExtraData;
#else
int reserved2[6]; int reserved2[6];
#endif
}; };
struct REPLAY_STREAM_HEADER struct REPLAY_STREAM_HEADER

View File

@ -20,6 +20,7 @@
#include "C/FMVPLAY.H" #include "C/FMVPLAY.H"
#include "C/SCORES.H" #include "C/SCORES.H"
#include "C/LOADSAVE.H" #include "C/LOADSAVE.H"
#include "C/MAIN.H"
#include "MEMCARD/MAIN.H" #include "MEMCARD/MAIN.H"
@ -1159,7 +1160,33 @@ void DisplayOnScreenText(void)
FEPrintStringSized(ScreenTitle, 40, 400, 0xc00, 1, 64, 64, 64); FEPrintStringSized(ScreenTitle, 40, 400, 0xc00, 1, 64, 64, 64);
} }
#ifndef PSX
else if (bDoingCarSelect)
{
if (NumPlayers == 2)
{
if (currPlayer != 1)
FEPrintStringSized("Player 2", 400, 260, 0xc00, 0, 128, 128, 128);
}
else
{
char startPos[32];
char *posname = GetLevelStartName(GameLevel, wantedStartPos);
if (posname != NULL)
{
sprintf(startPos, "Location: %s", posname);
}
else
{
sprintf(startPos, "Location: %d", wantedStartPos + 1);
}
FEPrintStringSized(startPos, 400, 260, 0xc00, 0, 128, 128, 128);
}
}
else
#endif
if (bInCutSelect) { if (bInCutSelect) {
text = CutSceneNames[cutSelection + CutAmountsTotal[currCity]]; text = CutSceneNames[cutSelection + CutAmountsTotal[currCity]];
@ -2551,9 +2578,10 @@ int CarSelectScreen(int bSetup)
} }
if (currPlayer != 1) { if (currPlayer != 1) {
#ifdef PSX
if (NumPlayers == 2) if (NumPlayers == 2)
FEPrintStringSized("Player 2", 400, 260, 0xc00, 0, 128, 128, 128); FEPrintStringSized("Player 2", 400, 260, 0xc00, 0, 128, 128, 128);
#endif
return 0; return 0;
} }
@ -2587,6 +2615,9 @@ int CarSelectScreen(int bSetup)
feVariableSave[2] = -1; feVariableSave[2] = -1;
feVariableSave[3] = -1; feVariableSave[3] = -1;
#ifndef PSX
wantedStartPos = -1;
#endif
lastCutCity = -1; lastCutCity = -1;
currSelIndex = 1; currSelIndex = 1;
@ -2617,6 +2648,8 @@ int CarSelectScreen(int bSetup)
LoadImage(&rect, (u_long*)(_frontend_buffer + currCity * 0x8000)); LoadImage(&rect, (u_long*)(_frontend_buffer + currCity * 0x8000));
DrawSync(0); DrawSync(0);
} }
wantedStartPos = -1;
#endif #endif
currPlayer = 1; currPlayer = 1;
bDoingCarSelect = 0; bDoingCarSelect = 0;
@ -2690,7 +2723,24 @@ int CarSelectScreen(int bSetup)
{ {
currSelIndex = pCurrButton->d - 1; currSelIndex = pCurrButton->d - 1;
} }
#ifndef PSX
#define LAST_START_POINT NUM_START_POINTS-1
else if (NumPlayers == 1)
{
if (fePad & 0x4)
{
FESound(2);
if (--wantedStartPos < -1)
wantedStartPos = LAST_START_POINT;
}
else if (fePad & 0x8)
{
FESound(2);
if (++wantedStartPos > LAST_START_POINT)
wantedStartPos = -1;
}
}
#endif
return 0; return 0;
} }