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:
toaster 2022-09-21 22:12:36 +01:00 committed by GenericHeroGuy
parent 03d847d416
commit 07c1fbf426
10 changed files with 148 additions and 108 deletions

View file

@ -2551,7 +2551,7 @@ void reademblemdata(MYFILE *f, INT32 num)
}
else if (fastcmp(word, "TAG"))
emblemlocations[num-1].tag = (INT16)value;
else if (fastcmp(word, "MAPNUM"))
else if (fastcmp(word, "MAPNAME"))
{
emblemlocations[num-1].level = Z_StrDup(word2);
}

View file

@ -107,6 +107,23 @@ extern preciptype_t precip_freeslot;
extern preciptype_t globalweather;
extern preciptype_t curWeather;
/** Time attack information, currently a very small structure.
*/
struct recorddata_t
{
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.
};
// 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.
extern boolean modifiedgame;
extern boolean majormods;
@ -410,6 +427,10 @@ struct mapheader_t
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
// 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.
// (This is not ifdeffed so the map header structure can stay identical, just in case.)
UINT8 numCustomOptions; ///< Internal. For Lua custom value support.
@ -564,27 +585,6 @@ extern INT32 luabanks[NUM_LUABANKS];
extern INT32 nummaprings; //keep track of spawned rings/coins
/** Time attack information, currently a very small structure.
*/
struct recorddata_t
{
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.
};
//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 tokenlist; ///< List of tokens collected
extern boolean gottoken; ///< Did you get a token? Used for end of act

View file

@ -3510,7 +3510,7 @@ void G_AddGhost(char *defdemoname)
ghosts = gh;
gh->version = ghostversion;
mthing = playerstarts[0];
mthing = playerstarts[0] ? playerstarts[0] : deathmatchstarts[0]; // todo not correct but out of scope
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.
fixed_t z,f,c;

View file

@ -210,12 +210,6 @@ tic_t totalplaytime;
UINT32 matchesplayed; // SRB2Kart
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
//nightsdata_t ntemprecords;
@ -539,21 +533,23 @@ INT32 player_name_changes[MAXPLAYERS];
// Allocation for time and nights data
void G_AllocMainRecordData(INT16 i)
{
if (!mainrecords[i])
mainrecords[i] = Z_Malloc(sizeof(recorddata_t), PU_STATIC, NULL);
memset(mainrecords[i], 0, sizeof(recorddata_t));
if (i > nummapheaders || !mapheaderinfo[i])
I_Error("G_AllocMainRecordData: Internal map ID %d not found (nummapheaders = %d)\n", i, nummapheaders);
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
void G_ClearRecords(void)
{
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]);
mainrecords[i] = NULL;
Z_Free(mapheaderinfo[i]->mainrecord);
mapheaderinfo[i]->mainrecord = NULL;
}
/*if (nightsrecords[i])
{
@ -566,20 +562,22 @@ void G_ClearRecords(void)
// For easy retrieval of records
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 mainrecords[map-1]->time;
return mapheaderinfo[map]->mainrecord->time;
}
// BE RIGHT BACK
// Not needed
/*
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 mainrecords[map-1]->lap;
return mapheaderinfo[map]->mainrecord->lap;
}
*/
@ -595,7 +593,7 @@ static void G_UpdateRecordReplays(void)
UINT8 earnedEmblems;
// Record new best time
if (!mainrecords[gamemap-1])
if (!mapheaderinfo[gamemap-1]->mainrecord)
G_AllocMainRecordData(gamemap-1);
if (players[consoleplayer].pflags & PF_NOCONTEST)
@ -603,20 +601,20 @@ static void G_UpdateRecordReplays(void)
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
{
mainrecords[gamemap-1]->time = players[consoleplayer].realtime;
mapheaderinfo[gamemap-1]->mainrecord->time = players[consoleplayer].realtime;
}
if (modeattacking == ATTACKING_TIME)
{
if ((mainrecords[gamemap-1]->lap == 0) || (bestlap < mainrecords[gamemap-1]->lap))
mainrecords[gamemap-1]->lap = bestlap;
if ((mapheaderinfo[gamemap-1]->mainrecord->lap == 0) || (bestlap < mapheaderinfo[gamemap-1]->mainrecord->lap))
mapheaderinfo[gamemap-1]->mainrecord->lap = bestlap;
}
else
{
mainrecords[gamemap-1]->lap = 0;
mapheaderinfo[gamemap-1]->mainrecord->lap = 0;
}
// Save demo!
@ -3759,20 +3757,19 @@ void G_AddMapToBuffer(INT16 map)
//
static void G_UpdateVisited(void)
{
boolean spec = G_IsSpecialStage(gamemap);
// Update visitation flags?
if ((!modifiedgame || savemoddata) // Not modified
&& !multiplayer && !demo.playback // SP/RA/NiGHTS mode
&& !(spec && stagefailed)) // Not failed the special stage
if (/*(!majormods || savemoddata) // Not modified
&&*/ !multiplayer && !demo.playback // SP/RA/NiGHTS mode
&& !(modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST))) // Not failed
{
UINT8 earnedEmblems;
// Update visitation flags
mapvisited[gamemap-1] |= MV_BEATEN;
mapheaderinfo[gamemap-1]->mapvisited |= MV_BEATEN;
if (encoremode == true)
{
mapvisited[gamemap-1] |= MV_ENCORE;
mapheaderinfo[gamemap-1]->mapvisited |= MV_ENCORE;
}
if (modeattacking)
@ -4053,7 +4050,9 @@ static void G_DoCompleted(void)
// If the current gametype has no intermission screen set, then don't start it.
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_HandleSaveLevel();
@ -4285,18 +4284,19 @@ void G_LoadGameSettings(void)
S_InitRuntimeSounds();
}
#define GD_VERSIONCHECK 0xBA5ED444
// G_LoadGameData
// Loads the main data file, which stores information such as emblems found, etc.
void G_LoadGameData(void)
{
INT32 i, j;
UINT32 i, j;
UINT8 modded = false;
UINT8 rtemp;
savebuffer_t save = {0};
//For records
tic_t rectime;
tic_t reclap;
UINT32 numgamedatamapheaders;
// Clear things so previously read gamedata doesn't transfer
// to new gamedata
@ -4327,7 +4327,7 @@ void G_LoadGameData(void)
return;
// Version check
if (READUINT32(save.p) != 0xFCAFE211)
if (READUINT32(save.p) != GD_VERSIONCHECK)
{
const char *gdfolder = "the SRB2Kart folder";
if (strcmp(srb2home,"."))
@ -4355,11 +4355,6 @@ void G_LoadGameData(void)
else if (modded != true && modded != false)
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
for (i = 0; i < MAXEMBLEMS;)
{
@ -4393,16 +4388,44 @@ void G_LoadGameData(void)
timesBeaten = READUINT32(save.p);
// 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[MAXMAPLUMPNAME];
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);
reclap = (tic_t)READUINT32(save.p);
if (rectime || reclap)
if (mapnum < nummapheaders && mapheaderinfo[mapnum])
{
G_AllocMainRecordData((INT16)i);
mainrecords[i]->time = rectime;
mainrecords[i]->lap = reclap;
// Valid mapheader, time to populate with record data.
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);
}
}
@ -4439,12 +4462,12 @@ void G_SaveGameData(void)
if (!gamedataloaded)
return; // If never loaded (-nodata), don't save
length = 4+4+4+(PWRLV_NUMTYPES*2)+1+(NUMMAPS)
length = 4+4+4+(PWRLV_NUMTYPES*2)+1
+ BIT_ARRAY_SIZE(MAXEMBLEMS)
+ BIT_ARRAY_SIZE(MAXEXTRAEMBLEMS)
+ BIT_ARRAY_SIZE(MAXUNLOCKABLES)
+ BIT_ARRAY_SIZE(MAXCONDITIONSETS)
+ 4+(NUMMAPS*9);
+ 4+4+(nummapheaders*(MAXMAPLUMPNAME+1+4+4));
if (P_SaveBufferAlloc(&save, length) == false)
{
@ -4463,22 +4486,18 @@ void G_SaveGameData(void)
#endif
// Version test
WRITEUINT32(save.p, 0xFCAFE211);
WRITEUINT32(save.p, GD_VERSIONCHECK); // 4
WRITEUINT32(save.p, totalplaytime);
WRITEUINT32(save.p, matchesplayed);
WRITEUINT32(save.p, totalplaytime); // 4
WRITEUINT32(save.p, matchesplayed); // 4
for (i = 0; i < PWRLV_NUMTYPES; i++)
WRITEUINT16(save.p, vspowerlevel[i]);
WRITEUINT8(save.p, (UINT8)savemoddata);
// 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));
WRITEUINT8(save.p, (UINT8)savemoddata); // 1
// To save space, use one bit per collected/achieved/unlocked flag
for (i = 0; i < MAXEMBLEMS;)
for (i = 0; i < MAXEMBLEMS;) // BIT_ARRAY_SIZE(MAXEMBLEMS)
{
btemp = 0;
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
@ -4486,7 +4505,7 @@ void G_SaveGameData(void)
WRITEUINT8(save.p, btemp);
i += j;
}
for (i = 0; i < MAXEXTRAEMBLEMS;)
for (i = 0; i < MAXEXTRAEMBLEMS;) // BIT_ARRAY_SIZE(MAXEXTRAEMBLEMS)
{
btemp = 0;
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
@ -4494,7 +4513,7 @@ void G_SaveGameData(void)
WRITEUINT8(save.p, btemp);
i += j;
}
for (i = 0; i < MAXUNLOCKABLES;)
for (i = 0; i < MAXUNLOCKABLES;) // BIT_ARRAY_SIZE(MAXUNLOCKABLES)
{
btemp = 0;
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
@ -4502,7 +4521,7 @@ void G_SaveGameData(void)
WRITEUINT8(save.p, btemp);
i += j;
}
for (i = 0; i < MAXCONDITIONSETS;)
for (i = 0; i < MAXCONDITIONSETS;) // BIT_ARRAY_SIZE(MAXCONDITIONSETS)
{
btemp = 0;
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
@ -4511,22 +4530,28 @@ void G_SaveGameData(void)
i += j;
}
WRITEUINT32(save.p, timesBeaten);
WRITEUINT32(save.p, timesBeaten); // 4
// Main records
for (i = 0; i < NUMMAPS; i++)
WRITEUINT32(save.p, nummapheaders); // 4
for (i = 0; i < nummapheaders; i++) // nummapheaders * (MAXMAPLUMPNAME+1+4+4)
{
if (mainrecords[i])
// For figuring out which header to assing it to on load
WRITESTRING(save.p, mapheaderinfo[i]->lumpname);
WRITEUINT8(save.p, (mapheaderinfo[i]->mapvisited & MV_MAX));
if (mapheaderinfo[i]->mainrecord)
{
WRITEUINT32(save.p, mainrecords[i]->time);
WRITEUINT32(save.p, mainrecords[i]->lap);
WRITEUINT32(save.p, mapheaderinfo[i]->mainrecord->time);
WRITEUINT32(save.p, mapheaderinfo[i]->mainrecord->lap);
}
else
{
WRITEUINT32(save.p, 0);
WRITEUINT32(save.p, 0);
}
WRITEUINT8(save.p, 0); // compat
}
length = save.p - save.buffer;

View file

@ -27,7 +27,6 @@ extern "C" {
extern char gamedatafilename[64];
extern char timeattackfolder[64];
extern char customversionstring[32];
#define GAMEDATASIZE (4*8192)
extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
extern INT32 player_name_changes[MAXPLAYERS];

View file

@ -241,7 +241,7 @@ void K_CheckBumpers(void)
winnerscoreadd -= players[i].roundscore;
}
if (bossinfo.boss)
if (K_CanChangeRules() == false)
{
if (nobumpers)
{

View file

@ -1454,7 +1454,7 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
else if ((drawtime/TICRATE) & 1)
V_DrawKartString(TX, TY+3, splitflags, va("99'59\"99"));
if (emblemmap && (modeattacking || (mode == 1)) && !demo.playback) // emblem time!
if ((modeattacking || (mode == 1)) && !demo.playback) // emblem time!
{
INT32 workx = TX + 96, worky = TY+18;
SINT8 curemb = 0;

View file

@ -146,7 +146,10 @@ void M_ClearSecrets(void)
{
INT32 i;
memset(mapvisited, 0, sizeof(mapvisited));
for (i = 0; i < nummapheaders; ++i)
{
mapheaderinfo[i]->mapvisited = 0;
}
for (i = 0; i < MAXEMBLEMS; ++i)
emblemlocations[i].collected = false;
@ -181,11 +184,19 @@ UINT8 M_CheckCondition(condition_t *cn)
case UC_OVERALLTIME: // Requires overall time <= x
return (M_GotLowEnoughTime(cn->requirement));
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
return ((mapvisited[cn->requirement - 1] & MV_BEATEN) == MV_BEATEN);
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
return (G_GetBestTime(cn->extrainfo1) <= (unsigned)cn->requirement);
case UC_TRIGGER: // requires map trigger set
@ -407,7 +418,7 @@ UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separa
if (embtype & ME_ENCORE)
flags |= MV_ENCORE;
res = ((mapvisited[levelnum - 1] & flags) == flags);
res = ((mapheaderinfo[levelnum]->mapvisited & flags) == flags);
emblemlocations[i].collected = res;
if (res)
@ -524,9 +535,9 @@ UINT8 M_GotLowEnoughTime(INT32 tictime)
if (!mapheaderinfo[i] || (mapheaderinfo[i]->menuflags & LF2_NOTIMEATTACK))
continue;
if (!mainrecords[i] || !mainrecords[i]->time)
if (!mapheaderinfo[i]->mainrecord || !mapheaderinfo[i]->mainrecord->time)
return false;
else if ((curtics += mainrecords[i]->time) > tictime)
else if ((curtics += mapheaderinfo[i]->mainrecord->time) > tictime)
return false;
}
return true;
@ -545,7 +556,7 @@ emblem_t *M_GetLevelEmblems(INT32 mapnum)
static INT32 map = -1;
static INT32 i = -1;
if (mapnum > 0)
if (mapnum >= 0)
{
map = mapnum;
i = numemblems;

View file

@ -4519,7 +4519,7 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt)
if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU)
return false; // map hell
if ((mapheaderinfo[mapnum]->menuflags & LF2_VISITNEEDED) && !mapvisited[mapnum])
if ((mapheaderinfo[mapnum]->menuflags & LF2_VISITNEEDED) && !mapheaderinfo[mapnum]->mapvisited)
return false;
return true;
@ -7712,13 +7712,13 @@ static void M_DrawLevelStats(void)
if (!mapheaderinfo[i] || (mapheaderinfo[i]->menuflags & LF2_NOTIMEATTACK))
continue;
if (!mainrecords[i] || mainrecords[i]->time <= 0)
if (!mapheaderinfo[i]->mainrecord || mapheaderinfo[i]->mainrecord->time <= 0)
{
mapsunfinished++;
continue;
}
besttime += mainrecords[i]->time;
besttime += mapheaderinfo[i]->mainrecord->time;
}
V_DrawString(20, 70, highlightflags, "Combined time records:");
@ -7957,10 +7957,10 @@ void M_DrawTimeAttackMenu(void)
{
INT32 dupadjust = (vid.width/vid.dupx);
tic_t lap = 0, time = 0;
if (mainrecords[cv_nextmap.value-1])
if (mapheaderinfo[cv_nextmap.value-1]->mainrecord)
{
lap = mainrecords[cv_nextmap.value-1]->lap;
time = mainrecords[cv_nextmap.value-1]->time;
lap = mapheaderinfo[cv_nextmap.value-1]->mainrecord->lap;
time = mapheaderinfo[cv_nextmap.value-1]->mainrecord->time;
}
V_DrawFill((BASEVIDWIDTH - dupadjust)>>1, 78, dupadjust, 36, 159);
@ -7968,11 +7968,11 @@ void M_DrawTimeAttackMenu(void)
if (levellistmode != LLM_ITEMBREAKER)
{
V_DrawRightAlignedString(149, 80, highlightflags, "BEST LAP:");
K_drawKartTimestamp(lap, 19, 86, 0, 2);
K_drawKartTimestamp(lap, 19, 86, -1, 2);
}
V_DrawRightAlignedString(292, 80, highlightflags, "BEST TIME:");
K_drawKartTimestamp(time, 162, 86, cv_nextmap.value, 1);
K_drawKartTimestamp(time, 162, 86, cv_nextmap.value-1, 1);
}
/*{
char beststr[40];

View file

@ -448,6 +448,10 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
// see p_setup.c - prevents replacing maps in addons with different versions
mapheaderinfo[num]->alreadyExists = exists;
mapheaderinfo[num]->mapvisited = 0;
Z_Free(mapheaderinfo[num]->mainrecord);
mapheaderinfo[num]->mainrecord = NULL;
mapheaderinfo[num]->customopts = NULL;
mapheaderinfo[num]->numCustomOptions = 0;
}
@ -466,6 +470,7 @@ void P_AllocMapHeader(INT16 i)
mapheaderinfo[i]->thumbnailPic = NULL;
mapheaderinfo[i]->minimapPic = NULL;
mapheaderinfo[i]->flickies = NULL;
mapheaderinfo[i]->mainrecord = NULL;
nummapheaders++;
}
P_ClearSingleMapHeaderInfo(i + 1);
@ -8398,9 +8403,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
R_PrecacheLevel();
if (!(netgame || multiplayer || demo.playback) && !majormods)
mapvisited[gamemap-1] |= MV_VISITED;
mapheaderinfo[gamemap-1]->mapvisited |= MV_VISITED;
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);