mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-27 04:21:47 +00:00
Move two of the three remaining NUMMAPS arrays part of the mapheader_t struct
- mapvisited and recorddata_t (previously mainrecords) - Changed how gamedata is saved and loaded - Change the versioncheck (funny hex provided by chengi) AND call it `developringdata.dat` in develop builds - Fix a bunch of off-by-ones in condition and emblem data ALSO, for Time Attack: - Fix menu not showing off your times - Now save times even when gamedata modified, since the menu didn't care (come back to it?) - Don't save times or do intermission screen if the Capsule Attack ended because you lost all your bumpers - Fix a crash adding ghosts in Capsule Attack
This commit is contained in:
parent
b8f3e64ca1
commit
60355d9efd
11 changed files with 179 additions and 106 deletions
|
|
@ -2334,7 +2334,7 @@ void reademblemdata(MYFILE *f, INT32 num)
|
||||||
}
|
}
|
||||||
else if (fastcmp(word, "TAG"))
|
else if (fastcmp(word, "TAG"))
|
||||||
emblemlocations[num-1].tag = (INT16)value;
|
emblemlocations[num-1].tag = (INT16)value;
|
||||||
else if (fastcmp(word, "MAPNUM"))
|
else if (fastcmp(word, "MAPNAME"))
|
||||||
{
|
{
|
||||||
emblemlocations[num-1].level = Z_StrDup(word2);
|
emblemlocations[num-1].level = Z_StrDup(word2);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,23 @@ extern preciptype_t precip_freeslot;
|
||||||
extern preciptype_t globalweather;
|
extern preciptype_t globalweather;
|
||||||
extern preciptype_t curWeather;
|
extern preciptype_t curWeather;
|
||||||
|
|
||||||
|
/** Time attack information, currently a very small structure.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
tic_t time; ///< Time in which the level was finished.
|
||||||
|
tic_t lap; ///< Best lap time for this level.
|
||||||
|
//UINT32 score; ///< Score when the level was finished.
|
||||||
|
//UINT16 rings; ///< Rings when the level was finished.
|
||||||
|
} recorddata_t;
|
||||||
|
|
||||||
|
// mapvisited is now a set of flags that says what we've done in the map.
|
||||||
|
#define MV_VISITED (1)
|
||||||
|
#define MV_BEATEN (1<<1)
|
||||||
|
#define MV_ENCORE (1<<2)
|
||||||
|
#define MV_MAX (MV_VISITED|MV_BEATEN|MV_ENCORE)
|
||||||
|
#define MV_MP ((MV_MAX+1)<<1)
|
||||||
|
|
||||||
// Set if homebrew PWAD stuff has been added.
|
// Set if homebrew PWAD stuff has been added.
|
||||||
extern boolean modifiedgame;
|
extern boolean modifiedgame;
|
||||||
extern boolean majormods;
|
extern boolean majormods;
|
||||||
|
|
@ -402,6 +419,10 @@ typedef struct
|
||||||
fixed_t mobj_scale; ///< Replacement for TOL_ERZ3
|
fixed_t mobj_scale; ///< Replacement for TOL_ERZ3
|
||||||
fixed_t default_waypoint_radius; ///< 0 is a special value for DEFAULT_WAYPOINT_RADIUS, but scaled with mobjscale
|
fixed_t default_waypoint_radius; ///< 0 is a special value for DEFAULT_WAYPOINT_RADIUS, but scaled with mobjscale
|
||||||
|
|
||||||
|
// Record data (modified liberally, saved to gamedata)
|
||||||
|
UINT8 mapvisited; ///< A set of flags that says what we've done in the map.
|
||||||
|
recorddata_t *mainrecord; ///< Stores best time attack data
|
||||||
|
|
||||||
// Lua stuff.
|
// Lua stuff.
|
||||||
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
|
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
|
||||||
UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
|
UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
|
||||||
|
|
@ -563,27 +584,6 @@ extern INT32 luabanks[NUM_LUABANKS];
|
||||||
|
|
||||||
extern INT32 nummaprings; //keep track of spawned rings/coins
|
extern INT32 nummaprings; //keep track of spawned rings/coins
|
||||||
|
|
||||||
/** Time attack information, currently a very small structure.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
tic_t time; ///< Time in which the level was finished.
|
|
||||||
tic_t lap; ///< Best lap time for this level.
|
|
||||||
//UINT32 score; ///< Score when the level was finished.
|
|
||||||
//UINT16 rings; ///< Rings when the level was finished.
|
|
||||||
} recorddata_t;
|
|
||||||
|
|
||||||
//extern nightsdata_t *nightsrecords[NUMMAPS];
|
|
||||||
extern recorddata_t *mainrecords[NUMMAPS];
|
|
||||||
|
|
||||||
// mapvisited is now a set of flags that says what we've done in the map.
|
|
||||||
#define MV_VISITED (1)
|
|
||||||
#define MV_BEATEN (1<<1)
|
|
||||||
#define MV_ENCORE (1<<2)
|
|
||||||
#define MV_MAX (MV_VISITED|MV_BEATEN|MV_ENCORE)
|
|
||||||
#define MV_MP ((MV_MAX+1)<<1)
|
|
||||||
extern UINT8 mapvisited[NUMMAPS];
|
|
||||||
|
|
||||||
extern UINT32 token; ///< Number of tokens collected in a level
|
extern UINT32 token; ///< Number of tokens collected in a level
|
||||||
extern UINT32 tokenlist; ///< List of tokens collected
|
extern UINT32 tokenlist; ///< List of tokens collected
|
||||||
extern boolean gottoken; ///< Did you get a token? Used for end of act
|
extern boolean gottoken; ///< Did you get a token? Used for end of act
|
||||||
|
|
|
||||||
|
|
@ -3358,7 +3358,7 @@ void G_AddGhost(char *defdemoname)
|
||||||
ghosts = gh;
|
ghosts = gh;
|
||||||
|
|
||||||
gh->version = ghostversion;
|
gh->version = ghostversion;
|
||||||
mthing = playerstarts[0];
|
mthing = playerstarts[0] ? playerstarts[0] : deathmatchstarts[0]; // todo not correct but out of scope
|
||||||
I_Assert(mthing);
|
I_Assert(mthing);
|
||||||
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
|
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
|
||||||
fixed_t z,f,c;
|
fixed_t z,f,c;
|
||||||
|
|
|
||||||
160
src/g_game.c
160
src/g_game.c
|
|
@ -75,7 +75,11 @@ JoyType_t Joystick[MAXSPLITSCREENPLAYERS];
|
||||||
#define SAVEGAMESIZE (1024)
|
#define SAVEGAMESIZE (1024)
|
||||||
|
|
||||||
// SRB2kart
|
// SRB2kart
|
||||||
char gamedatafilename[64] = "ringdata.dat";
|
char gamedatafilename[64] =
|
||||||
|
#ifdef DEVELOP
|
||||||
|
"develop"
|
||||||
|
#endif
|
||||||
|
"ringdata.dat";
|
||||||
char timeattackfolder[64] = "ringracers";
|
char timeattackfolder[64] = "ringracers";
|
||||||
char customversionstring[32] = "\0";
|
char customversionstring[32] = "\0";
|
||||||
|
|
||||||
|
|
@ -215,12 +219,6 @@ tic_t totalplaytime;
|
||||||
UINT32 matchesplayed; // SRB2Kart
|
UINT32 matchesplayed; // SRB2Kart
|
||||||
boolean gamedataloaded = false;
|
boolean gamedataloaded = false;
|
||||||
|
|
||||||
// Time attack data for levels
|
|
||||||
// These are dynamically allocated for space reasons now
|
|
||||||
recorddata_t *mainrecords[NUMMAPS] = {NULL};
|
|
||||||
//nightsdata_t *nightsrecords[NUMMAPS] = {NULL};
|
|
||||||
UINT8 mapvisited[NUMMAPS];
|
|
||||||
|
|
||||||
// Temporary holding place for nights data for the current map
|
// Temporary holding place for nights data for the current map
|
||||||
//nightsdata_t ntemprecords;
|
//nightsdata_t ntemprecords;
|
||||||
|
|
||||||
|
|
@ -473,21 +471,23 @@ INT32 player_name_changes[MAXPLAYERS];
|
||||||
// Allocation for time and nights data
|
// Allocation for time and nights data
|
||||||
void G_AllocMainRecordData(INT16 i)
|
void G_AllocMainRecordData(INT16 i)
|
||||||
{
|
{
|
||||||
if (!mainrecords[i])
|
if (i > nummapheaders || !mapheaderinfo[i])
|
||||||
mainrecords[i] = Z_Malloc(sizeof(recorddata_t), PU_STATIC, NULL);
|
I_Error("G_AllocMainRecordData: Internal map ID %d not found (nummapheaders = %d)\n", i, nummapheaders);
|
||||||
memset(mainrecords[i], 0, sizeof(recorddata_t));
|
if (!mapheaderinfo[i]->mainrecord)
|
||||||
|
mapheaderinfo[i]->mainrecord = Z_Malloc(sizeof(recorddata_t), PU_STATIC, NULL);
|
||||||
|
memset(mapheaderinfo[i]->mainrecord, 0, sizeof(recorddata_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
// MAKE SURE YOU SAVE DATA BEFORE CALLING THIS
|
// MAKE SURE YOU SAVE DATA BEFORE CALLING THIS
|
||||||
void G_ClearRecords(void)
|
void G_ClearRecords(void)
|
||||||
{
|
{
|
||||||
INT16 i;
|
INT16 i;
|
||||||
for (i = 0; i < NUMMAPS; ++i)
|
for (i = 0; i < nummapheaders; ++i)
|
||||||
{
|
{
|
||||||
if (mainrecords[i])
|
if (mapheaderinfo[i]->mainrecord)
|
||||||
{
|
{
|
||||||
Z_Free(mainrecords[i]);
|
Z_Free(mapheaderinfo[i]->mainrecord);
|
||||||
mainrecords[i] = NULL;
|
mapheaderinfo[i]->mainrecord = NULL;
|
||||||
}
|
}
|
||||||
/*if (nightsrecords[i])
|
/*if (nightsrecords[i])
|
||||||
{
|
{
|
||||||
|
|
@ -500,20 +500,22 @@ void G_ClearRecords(void)
|
||||||
// For easy retrieval of records
|
// For easy retrieval of records
|
||||||
tic_t G_GetBestTime(INT16 map)
|
tic_t G_GetBestTime(INT16 map)
|
||||||
{
|
{
|
||||||
if (!mainrecords[map-1] || mainrecords[map-1]->time <= 0)
|
if (!mapheaderinfo[map] || !mapheaderinfo[map]->mainrecord || mapheaderinfo[map]->mainrecord->time <= 0)
|
||||||
return (tic_t)UINT32_MAX;
|
return (tic_t)UINT32_MAX;
|
||||||
|
|
||||||
return mainrecords[map-1]->time;
|
return mapheaderinfo[map]->mainrecord->time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BE RIGHT BACK
|
||||||
|
|
||||||
// Not needed
|
// Not needed
|
||||||
/*
|
/*
|
||||||
tic_t G_GetBestLap(INT16 map)
|
tic_t G_GetBestLap(INT16 map)
|
||||||
{
|
{
|
||||||
if (!mainrecords[map-1] || mainrecords[map-1]->lap <= 0)
|
if (!mapheaderinfo[map] || !mapheaderinfo[map]->mainrecord || mapheaderinfo[map]->mainrecord->lap <= 0)
|
||||||
return (tic_t)UINT32_MAX;
|
return (tic_t)UINT32_MAX;
|
||||||
|
|
||||||
return mainrecords[map-1]->lap;
|
return mapheaderinfo[map]->mainrecord->lap;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -530,7 +532,7 @@ static void G_UpdateRecordReplays(void)
|
||||||
UINT8 earnedEmblems;
|
UINT8 earnedEmblems;
|
||||||
|
|
||||||
// Record new best time
|
// Record new best time
|
||||||
if (!mainrecords[gamemap-1])
|
if (!mapheaderinfo[gamemap-1]->mainrecord)
|
||||||
G_AllocMainRecordData(gamemap-1);
|
G_AllocMainRecordData(gamemap-1);
|
||||||
|
|
||||||
if (players[consoleplayer].pflags & PF_NOCONTEST)
|
if (players[consoleplayer].pflags & PF_NOCONTEST)
|
||||||
|
|
@ -538,20 +540,20 @@ static void G_UpdateRecordReplays(void)
|
||||||
players[consoleplayer].realtime = UINT32_MAX;
|
players[consoleplayer].realtime = UINT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time))
|
if (((mapheaderinfo[gamemap-1]->mainrecord->time == 0) || (players[consoleplayer].realtime < mapheaderinfo[gamemap-1]->mainrecord->time))
|
||||||
&& (players[consoleplayer].realtime < UINT32_MAX)) // DNF
|
&& (players[consoleplayer].realtime < UINT32_MAX)) // DNF
|
||||||
{
|
{
|
||||||
mainrecords[gamemap-1]->time = players[consoleplayer].realtime;
|
mapheaderinfo[gamemap-1]->mainrecord->time = players[consoleplayer].realtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modeattacking == ATTACKING_TIME)
|
if (modeattacking == ATTACKING_TIME)
|
||||||
{
|
{
|
||||||
if ((mainrecords[gamemap-1]->lap == 0) || (bestlap < mainrecords[gamemap-1]->lap))
|
if ((mapheaderinfo[gamemap-1]->mainrecord->lap == 0) || (bestlap < mapheaderinfo[gamemap-1]->mainrecord->lap))
|
||||||
mainrecords[gamemap-1]->lap = bestlap;
|
mapheaderinfo[gamemap-1]->mainrecord->lap = bestlap;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mainrecords[gamemap-1]->lap = 0;
|
mapheaderinfo[gamemap-1]->mainrecord->lap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save demo!
|
// Save demo!
|
||||||
|
|
@ -3616,20 +3618,19 @@ void G_AddMapToBuffer(INT16 map)
|
||||||
//
|
//
|
||||||
static void G_UpdateVisited(void)
|
static void G_UpdateVisited(void)
|
||||||
{
|
{
|
||||||
boolean spec = G_IsSpecialStage(gamemap);
|
|
||||||
// Update visitation flags?
|
// Update visitation flags?
|
||||||
if ((!modifiedgame || savemoddata) // Not modified
|
if (/*(!majormods || savemoddata) // Not modified
|
||||||
&& !multiplayer && !demo.playback // SP/RA/NiGHTS mode
|
&&*/ !multiplayer && !demo.playback // SP/RA/NiGHTS mode
|
||||||
&& !(spec && stagefailed)) // Not failed the special stage
|
&& !(modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST))) // Not failed
|
||||||
{
|
{
|
||||||
UINT8 earnedEmblems;
|
UINT8 earnedEmblems;
|
||||||
|
|
||||||
// Update visitation flags
|
// Update visitation flags
|
||||||
mapvisited[gamemap-1] |= MV_BEATEN;
|
mapheaderinfo[gamemap-1]->mapvisited |= MV_BEATEN;
|
||||||
|
|
||||||
if (encoremode == true)
|
if (encoremode == true)
|
||||||
{
|
{
|
||||||
mapvisited[gamemap-1] |= MV_ENCORE;
|
mapheaderinfo[gamemap-1]->mapvisited |= MV_ENCORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modeattacking)
|
if (modeattacking)
|
||||||
|
|
@ -3910,7 +3911,9 @@ static void G_DoCompleted(void)
|
||||||
// If the current gametype has no intermission screen set, then don't start it.
|
// If the current gametype has no intermission screen set, then don't start it.
|
||||||
Y_DetermineIntermissionType();
|
Y_DetermineIntermissionType();
|
||||||
|
|
||||||
if ((skipstats && !modeattacking) || (spec && modeattacking && stagefailed) || (intertype == int_none))
|
if ((skipstats && !modeattacking)
|
||||||
|
|| (modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST))
|
||||||
|
|| (intertype == int_none))
|
||||||
{
|
{
|
||||||
G_UpdateVisited();
|
G_UpdateVisited();
|
||||||
G_HandleSaveLevel();
|
G_HandleSaveLevel();
|
||||||
|
|
@ -4142,18 +4145,19 @@ void G_LoadGameSettings(void)
|
||||||
S_InitRuntimeSounds();
|
S_InitRuntimeSounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GD_VERSIONCHECK 0xBA5ED444
|
||||||
|
|
||||||
// G_LoadGameData
|
// G_LoadGameData
|
||||||
// Loads the main data file, which stores information such as emblems found, etc.
|
// Loads the main data file, which stores information such as emblems found, etc.
|
||||||
void G_LoadGameData(void)
|
void G_LoadGameData(void)
|
||||||
{
|
{
|
||||||
size_t length;
|
size_t length;
|
||||||
INT32 i, j;
|
UINT32 i, j;
|
||||||
UINT8 modded = false;
|
UINT8 modded = false;
|
||||||
UINT8 rtemp;
|
UINT8 rtemp;
|
||||||
|
|
||||||
//For records
|
//For records
|
||||||
tic_t rectime;
|
UINT32 numgamedatamapheaders;
|
||||||
tic_t reclap;
|
|
||||||
|
|
||||||
// Clear things so previously read gamedata doesn't transfer
|
// Clear things so previously read gamedata doesn't transfer
|
||||||
// to new gamedata
|
// to new gamedata
|
||||||
|
|
@ -4184,7 +4188,7 @@ void G_LoadGameData(void)
|
||||||
save_p = savebuffer;
|
save_p = savebuffer;
|
||||||
|
|
||||||
// Version check
|
// Version check
|
||||||
if (READUINT32(save_p) != 0xFCAFE211)
|
if (READUINT32(save_p) != GD_VERSIONCHECK)
|
||||||
{
|
{
|
||||||
const char *gdfolder = "the Ring Racers folder";
|
const char *gdfolder = "the Ring Racers folder";
|
||||||
if (strcmp(srb2home,"."))
|
if (strcmp(srb2home,"."))
|
||||||
|
|
@ -4206,11 +4210,6 @@ void G_LoadGameData(void)
|
||||||
else if (modded != true && modded != false)
|
else if (modded != true && modded != false)
|
||||||
goto datacorrupt;
|
goto datacorrupt;
|
||||||
|
|
||||||
// TODO put another cipher on these things? meh, I don't care...
|
|
||||||
for (i = 0; i < NUMMAPS; i++)
|
|
||||||
if ((mapvisited[i] = READUINT8(save_p)) > MV_MAX)
|
|
||||||
goto datacorrupt;
|
|
||||||
|
|
||||||
// To save space, use one bit per collected/achieved/unlocked flag
|
// To save space, use one bit per collected/achieved/unlocked flag
|
||||||
for (i = 0; i < MAXEMBLEMS;)
|
for (i = 0; i < MAXEMBLEMS;)
|
||||||
{
|
{
|
||||||
|
|
@ -4244,16 +4243,44 @@ void G_LoadGameData(void)
|
||||||
timesBeaten = READUINT32(save_p);
|
timesBeaten = READUINT32(save_p);
|
||||||
|
|
||||||
// Main records
|
// Main records
|
||||||
for (i = 0; i < NUMMAPS; ++i)
|
numgamedatamapheaders = READUINT32(save_p);
|
||||||
|
if (numgamedatamapheaders >= NEXTMAP_SPECIAL)
|
||||||
|
goto datacorrupt;
|
||||||
|
|
||||||
|
for (i = 0; i < numgamedatamapheaders; i++)
|
||||||
{
|
{
|
||||||
|
char mapname[255];
|
||||||
|
INT16 mapnum;
|
||||||
|
tic_t rectime;
|
||||||
|
tic_t reclap;
|
||||||
|
|
||||||
|
READSTRINGN(save_p, mapname, sizeof(mapname));
|
||||||
|
mapnum = G_MapNumber(mapname);
|
||||||
|
|
||||||
|
rtemp = READUINT8(save_p);
|
||||||
rectime = (tic_t)READUINT32(save_p);
|
rectime = (tic_t)READUINT32(save_p);
|
||||||
reclap = (tic_t)READUINT32(save_p);
|
reclap = (tic_t)READUINT32(save_p);
|
||||||
|
|
||||||
if (rectime || reclap)
|
if (mapnum < nummapheaders && mapheaderinfo[mapnum])
|
||||||
{
|
{
|
||||||
G_AllocMainRecordData((INT16)i);
|
// Valid mapheader, time to populate with record data.
|
||||||
mainrecords[i]->time = rectime;
|
|
||||||
mainrecords[i]->lap = reclap;
|
if ((mapheaderinfo[mapnum]->mapvisited = rtemp) & ~MV_MAX)
|
||||||
|
goto datacorrupt;
|
||||||
|
|
||||||
|
if (rectime || reclap)
|
||||||
|
{
|
||||||
|
G_AllocMainRecordData((INT16)i);
|
||||||
|
mapheaderinfo[i]->mainrecord->time = rectime;
|
||||||
|
mapheaderinfo[i]->mainrecord->lap = reclap;
|
||||||
|
CONS_Printf("ID %d, Time = %d, Lap = %d\n", i, rectime/35, reclap/35);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Since it's not worth declaring the entire gamedata
|
||||||
|
// corrupt over extra maps, we report and move on.
|
||||||
|
CONS_Alert(CONS_WARNING, "Map with lumpname %s does not exist, time record data will be discarded", mapname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4291,7 +4318,10 @@ void G_SaveGameData(void)
|
||||||
if (!gamedataloaded)
|
if (!gamedataloaded)
|
||||||
return; // If never loaded (-nodata), don't save
|
return; // If never loaded (-nodata), don't save
|
||||||
|
|
||||||
save_p = savebuffer = (UINT8 *)malloc(GAMEDATASIZE);
|
length = (4+4+4+1+(MAXEMBLEMS)+MAXEXTRAEMBLEMS+MAXUNLOCKABLES+MAXCONDITIONSETS+4+4);
|
||||||
|
length += nummapheaders * (255+1+4+4);
|
||||||
|
|
||||||
|
save_p = savebuffer = (UINT8 *)malloc(length);
|
||||||
if (!save_p)
|
if (!save_p)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
|
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
|
||||||
|
|
@ -4309,19 +4339,15 @@ void G_SaveGameData(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Version test
|
// Version test
|
||||||
WRITEUINT32(save_p, 0xFCAFE211);
|
WRITEUINT32(save_p, GD_VERSIONCHECK); // 4
|
||||||
|
|
||||||
WRITEUINT32(save_p, totalplaytime);
|
WRITEUINT32(save_p, totalplaytime); // 4
|
||||||
WRITEUINT32(save_p, matchesplayed);
|
WRITEUINT32(save_p, matchesplayed); // 4
|
||||||
|
|
||||||
WRITEUINT8(save_p, (UINT8)savemoddata);
|
WRITEUINT8(save_p, (UINT8)savemoddata); // 1
|
||||||
|
|
||||||
// TODO put another cipher on these things? meh, I don't care...
|
|
||||||
for (i = 0; i < NUMMAPS; i++)
|
|
||||||
WRITEUINT8(save_p, (mapvisited[i] & MV_MAX));
|
|
||||||
|
|
||||||
// To save space, use one bit per collected/achieved/unlocked flag
|
// To save space, use one bit per collected/achieved/unlocked flag
|
||||||
for (i = 0; i < MAXEMBLEMS;)
|
for (i = 0; i < MAXEMBLEMS;) // MAXEMBLEMS * 1;
|
||||||
{
|
{
|
||||||
btemp = 0;
|
btemp = 0;
|
||||||
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
|
||||||
|
|
@ -4329,7 +4355,7 @@ void G_SaveGameData(void)
|
||||||
WRITEUINT8(save_p, btemp);
|
WRITEUINT8(save_p, btemp);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
for (i = 0; i < MAXEXTRAEMBLEMS;)
|
for (i = 0; i < MAXEXTRAEMBLEMS;) // MAXEXTRAEMBLEMS * 1;
|
||||||
{
|
{
|
||||||
btemp = 0;
|
btemp = 0;
|
||||||
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
|
||||||
|
|
@ -4337,7 +4363,7 @@ void G_SaveGameData(void)
|
||||||
WRITEUINT8(save_p, btemp);
|
WRITEUINT8(save_p, btemp);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
for (i = 0; i < MAXUNLOCKABLES;)
|
for (i = 0; i < MAXUNLOCKABLES;) // MAXUNLOCKABLES * 1;
|
||||||
{
|
{
|
||||||
btemp = 0;
|
btemp = 0;
|
||||||
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
|
||||||
|
|
@ -4345,7 +4371,7 @@ void G_SaveGameData(void)
|
||||||
WRITEUINT8(save_p, btemp);
|
WRITEUINT8(save_p, btemp);
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
for (i = 0; i < MAXCONDITIONSETS;)
|
for (i = 0; i < MAXCONDITIONSETS;) // MAXCONDITIONSETS * 1;
|
||||||
{
|
{
|
||||||
btemp = 0;
|
btemp = 0;
|
||||||
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
|
||||||
|
|
@ -4354,22 +4380,28 @@ void G_SaveGameData(void)
|
||||||
i += j;
|
i += j;
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITEUINT32(save_p, timesBeaten);
|
WRITEUINT32(save_p, timesBeaten); // 4
|
||||||
|
|
||||||
// Main records
|
// Main records
|
||||||
for (i = 0; i < NUMMAPS; i++)
|
WRITEUINT32(save_p, nummapheaders); // 4
|
||||||
|
|
||||||
|
for (i = 0; i < nummapheaders; i++) // nummapheaders * (255+1+4+4)
|
||||||
{
|
{
|
||||||
if (mainrecords[i])
|
// For figuring out which header to assing it to on load
|
||||||
|
WRITESTRINGN(save_p, mapheaderinfo[i]->lumpname, 255);
|
||||||
|
|
||||||
|
WRITEUINT8(save_p, (mapheaderinfo[i]->mapvisited & MV_MAX));
|
||||||
|
|
||||||
|
if (mapheaderinfo[i]->mainrecord)
|
||||||
{
|
{
|
||||||
WRITEUINT32(save_p, mainrecords[i]->time);
|
WRITEUINT32(save_p, mapheaderinfo[i]->mainrecord->time);
|
||||||
WRITEUINT32(save_p, mainrecords[i]->lap);
|
WRITEUINT32(save_p, mapheaderinfo[i]->mainrecord->lap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WRITEUINT32(save_p, 0);
|
WRITEUINT32(save_p, 0);
|
||||||
WRITEUINT32(save_p, 0);
|
WRITEUINT32(save_p, 0);
|
||||||
}
|
}
|
||||||
WRITEUINT8(save_p, 0); // compat
|
|
||||||
}
|
}
|
||||||
|
|
||||||
length = save_p - savebuffer;
|
length = save_p - savebuffer;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
extern char gamedatafilename[64];
|
extern char gamedatafilename[64];
|
||||||
extern char timeattackfolder[64];
|
extern char timeattackfolder[64];
|
||||||
extern char customversionstring[32];
|
extern char customversionstring[32];
|
||||||
#define GAMEDATASIZE (4*8192)
|
|
||||||
|
|
||||||
extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
|
extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
|
||||||
extern INT32 player_name_changes[MAXPLAYERS];
|
extern INT32 player_name_changes[MAXPLAYERS];
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
#include "m_random.h"
|
#include "m_random.h"
|
||||||
#include "r_sky.h" // skyflatnum
|
#include "r_sky.h" // skyflatnum
|
||||||
|
#include "k_grandprix.h" // K_CanChangeRules
|
||||||
|
|
||||||
// Battle overtime info
|
// Battle overtime info
|
||||||
struct battleovertime battleovertime;
|
struct battleovertime battleovertime;
|
||||||
|
|
@ -126,7 +127,7 @@ void K_CheckBumpers(void)
|
||||||
winnerscoreadd -= players[i].roundscore;
|
winnerscoreadd -= players[i].roundscore;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bossinfo.boss)
|
if (K_CanChangeRules() == false)
|
||||||
{
|
{
|
||||||
if (nobumpers)
|
if (nobumpers)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,15 @@ extern menu_t PLAY_LevelSelectDef;
|
||||||
extern menuitem_t PLAY_TimeAttack[];
|
extern menuitem_t PLAY_TimeAttack[];
|
||||||
extern menu_t PLAY_TimeAttackDef;
|
extern menu_t PLAY_TimeAttackDef;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ta_replay = 0,
|
||||||
|
ta_guest,
|
||||||
|
ta_ghosts,
|
||||||
|
ta_spacer,
|
||||||
|
ta_start,
|
||||||
|
} ta_e;
|
||||||
|
|
||||||
extern menuitem_t PLAY_TAReplay[];
|
extern menuitem_t PLAY_TAReplay[];
|
||||||
extern menu_t PLAY_TAReplayDef;
|
extern menu_t PLAY_TAReplayDef;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,7 @@ menu_t PLAY_LevelSelectDef = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// see ta_e
|
||||||
menuitem_t PLAY_TimeAttack[] =
|
menuitem_t PLAY_TimeAttack[] =
|
||||||
{
|
{
|
||||||
{IT_STRING | IT_SUBMENU, "Replay...", NULL, NULL, {.submenu = &PLAY_TAReplayDef}, 0, 0},
|
{IT_STRING | IT_SUBMENU, "Replay...", NULL, NULL, {.submenu = &PLAY_TAReplayDef}, 0, 0},
|
||||||
|
|
|
||||||
|
|
@ -2159,19 +2159,34 @@ void M_DrawTimeAttack(void)
|
||||||
|
|
||||||
V_DrawScaledPatch(149+t, 70, 0, W_CachePatchName("BESTTIME", PU_CACHE));
|
V_DrawScaledPatch(149+t, 70, 0, W_CachePatchName("BESTTIME", PU_CACHE));
|
||||||
|
|
||||||
if (currentMenu == &PLAY_TimeAttackDef)
|
if (currentMenu == &PLAY_TimeAttackDef && mapheaderinfo[map])
|
||||||
{
|
{
|
||||||
if (mapheaderinfo[map])
|
tic_t timerec = 0;
|
||||||
|
tic_t laprec = 0;
|
||||||
|
UINT32 timeheight = 82;
|
||||||
|
|
||||||
|
if ((minimap = mapheaderinfo[map]->minimapPic))
|
||||||
|
V_DrawScaledPatch(24-t, 82, 0, minimap);
|
||||||
|
|
||||||
|
if (mapheaderinfo[map]->mainrecord)
|
||||||
{
|
{
|
||||||
if ((minimap = mapheaderinfo[map]->minimapPic))
|
timerec = mapheaderinfo[map]->mainrecord->time;
|
||||||
V_DrawScaledPatch(24-t, 82, 0, minimap);
|
laprec = mapheaderinfo[map]->mainrecord->lap;
|
||||||
}
|
}
|
||||||
|
|
||||||
V_DrawRightAlignedString(rightedge-12, 82, highlightflags, "BEST LAP:");
|
if (levellist.newgametype != GT_BATTLE)
|
||||||
K_drawKartTimestamp(0, 162+t, 88, 0, 2);
|
{
|
||||||
|
V_DrawRightAlignedString(rightedge-12, timeheight, highlightflags, "BEST LAP:");
|
||||||
|
K_drawKartTimestamp(laprec, 162+t, timeheight+6, 0, 2);
|
||||||
|
timeheight += 30;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeheight += 15;
|
||||||
|
}
|
||||||
|
|
||||||
V_DrawRightAlignedString(rightedge-12, 112, highlightflags, "BEST TIME:");
|
V_DrawRightAlignedString(rightedge-12, timeheight, highlightflags, "BEST TIME:");
|
||||||
K_drawKartTimestamp(0, 162+t, 118, map, 1);
|
K_drawKartTimestamp(timerec, 162+t, timeheight+6, map, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
opty = 80;
|
opty = 80;
|
||||||
|
|
|
||||||
25
src/m_cond.c
25
src/m_cond.c
|
|
@ -81,7 +81,10 @@ void M_ClearSecrets(void)
|
||||||
{
|
{
|
||||||
INT32 i;
|
INT32 i;
|
||||||
|
|
||||||
memset(mapvisited, 0, sizeof(mapvisited));
|
for (i = 0; i < nummapheaders; ++i)
|
||||||
|
{
|
||||||
|
mapheaderinfo[i]->mapvisited = 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAXEMBLEMS; ++i)
|
for (i = 0; i < MAXEMBLEMS; ++i)
|
||||||
emblemlocations[i].collected = false;
|
emblemlocations[i].collected = false;
|
||||||
|
|
@ -129,11 +132,19 @@ UINT8 M_CheckCondition(condition_t *cn)
|
||||||
case UC_OVERALLTIME: // Requires overall time <= x
|
case UC_OVERALLTIME: // Requires overall time <= x
|
||||||
return (M_GotLowEnoughTime(cn->requirement));
|
return (M_GotLowEnoughTime(cn->requirement));
|
||||||
case UC_MAPVISITED: // Requires map x to be visited
|
case UC_MAPVISITED: // Requires map x to be visited
|
||||||
return ((mapvisited[cn->requirement - 1] & MV_VISITED) == MV_VISITED);
|
|
||||||
case UC_MAPBEATEN: // Requires map x to be beaten
|
case UC_MAPBEATEN: // Requires map x to be beaten
|
||||||
return ((mapvisited[cn->requirement - 1] & MV_BEATEN) == MV_BEATEN);
|
|
||||||
case UC_MAPENCORE: // Requires map x to be beaten in encore
|
case UC_MAPENCORE: // Requires map x to be beaten in encore
|
||||||
return ((mapvisited[cn->requirement - 1] & MV_ENCORE) == MV_ENCORE);
|
{
|
||||||
|
UINT8 mvtype = MV_VISITED;
|
||||||
|
if (cn->type == UC_MAPBEATEN)
|
||||||
|
mvtype = MV_BEATEN;
|
||||||
|
else if (cn->type == UC_MAPENCORE)
|
||||||
|
mvtype = MV_ENCORE;
|
||||||
|
|
||||||
|
return ((cn->requirement < nummapheaders)
|
||||||
|
&& (mapheaderinfo[cn->requirement])
|
||||||
|
&& ((mapheaderinfo[cn->requirement]->mapvisited & mvtype) == mvtype));
|
||||||
|
}
|
||||||
case UC_MAPTIME: // Requires time on map <= x
|
case UC_MAPTIME: // Requires time on map <= x
|
||||||
return (G_GetBestTime(cn->extrainfo1) <= (unsigned)cn->requirement);
|
return (G_GetBestTime(cn->extrainfo1) <= (unsigned)cn->requirement);
|
||||||
case UC_TRIGGER: // requires map trigger set
|
case UC_TRIGGER: // requires map trigger set
|
||||||
|
|
@ -355,7 +366,7 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa
|
||||||
if (embtype & ME_ENCORE)
|
if (embtype & ME_ENCORE)
|
||||||
flags |= MV_ENCORE;
|
flags |= MV_ENCORE;
|
||||||
|
|
||||||
res = ((mapvisited[levelnum - 1] & flags) == flags);
|
res = ((mapheaderinfo[levelnum]->mapvisited & flags) == flags);
|
||||||
|
|
||||||
emblemlocations[i].collected = res;
|
emblemlocations[i].collected = res;
|
||||||
if (res)
|
if (res)
|
||||||
|
|
@ -477,9 +488,9 @@ UINT8 M_GotLowEnoughTime(INT32 tictime)
|
||||||
if (!mapheaderinfo[i] || (mapheaderinfo[i]->menuflags & LF2_NOTIMEATTACK))
|
if (!mapheaderinfo[i] || (mapheaderinfo[i]->menuflags & LF2_NOTIMEATTACK))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!mainrecords[i] || !mainrecords[i]->time)
|
if (!mapheaderinfo[i]->mainrecord || !mapheaderinfo[i]->mainrecord->time)
|
||||||
return false;
|
return false;
|
||||||
else if ((curtics += mainrecords[i]->time) > tictime)
|
else if ((curtics += mapheaderinfo[i]->mainrecord->time) > tictime)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -408,6 +408,10 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
|
||||||
P_DeleteFlickies(num);
|
P_DeleteFlickies(num);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
mapheaderinfo[num]->mapvisited = 0;
|
||||||
|
Z_Free(mapheaderinfo[num]->mainrecord);
|
||||||
|
mapheaderinfo[num]->mainrecord = NULL;
|
||||||
|
|
||||||
mapheaderinfo[num]->customopts = NULL;
|
mapheaderinfo[num]->customopts = NULL;
|
||||||
mapheaderinfo[num]->numCustomOptions = 0;
|
mapheaderinfo[num]->numCustomOptions = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -426,6 +430,7 @@ void P_AllocMapHeader(INT16 i)
|
||||||
mapheaderinfo[i]->thumbnailPic = NULL;
|
mapheaderinfo[i]->thumbnailPic = NULL;
|
||||||
mapheaderinfo[i]->minimapPic = NULL;
|
mapheaderinfo[i]->minimapPic = NULL;
|
||||||
mapheaderinfo[i]->flickies = NULL;
|
mapheaderinfo[i]->flickies = NULL;
|
||||||
|
mapheaderinfo[i]->mainrecord = NULL;
|
||||||
nummapheaders++;
|
nummapheaders++;
|
||||||
}
|
}
|
||||||
P_ClearSingleMapHeaderInfo(i + 1);
|
P_ClearSingleMapHeaderInfo(i + 1);
|
||||||
|
|
@ -4265,9 +4270,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
||||||
skipstats = 0;
|
skipstats = 0;
|
||||||
|
|
||||||
if (!(netgame || multiplayer || demo.playback) && !majormods)
|
if (!(netgame || multiplayer || demo.playback) && !majormods)
|
||||||
mapvisited[gamemap-1] |= MV_VISITED;
|
mapheaderinfo[gamemap-1]->mapvisited |= MV_VISITED;
|
||||||
else if (!demo.playback)
|
else if (!demo.playback)
|
||||||
mapvisited[gamemap-1] |= MV_MP; // you want to record that you've been there this session, but not permanently
|
mapheaderinfo[gamemap-1]->mapvisited |= MV_MP; // you want to record that you've been there this session, but not permanently
|
||||||
|
|
||||||
G_AddMapToBuffer(gamemap-1);
|
G_AddMapToBuffer(gamemap-1);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue