diff --git a/src/deh_soc.c b/src/deh_soc.c index f2e32e148..150d954dd 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -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); } diff --git a/src/doomstat.h b/src/doomstat.h index ee4b1c838..b43acf77b 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -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 diff --git a/src/g_demo.c b/src/g_demo.c index e56aa6c6e..eb81253b7 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -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; diff --git a/src/g_game.c b/src/g_game.c index 8439f9ecf..05ed3af40 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -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; diff --git a/src/g_game.h b/src/g_game.h index 7ad053594..a2fcebbe0 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -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]; diff --git a/src/k_battle.c b/src/k_battle.c index d554d0bdf..482bf3b74 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -241,7 +241,7 @@ void K_CheckBumpers(void) winnerscoreadd -= players[i].roundscore; } - if (bossinfo.boss) + if (K_CanChangeRules() == false) { if (nobumpers) { diff --git a/src/k_hud.c b/src/k_hud.c index 15c626d2c..0e5af2687 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -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; diff --git a/src/m_cond.c b/src/m_cond.c index 0ba429827..e9d2c71b2 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -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; diff --git a/src/m_menu.c b/src/m_menu.c index 67c04b690..b13e0c1c6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -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]; diff --git a/src/p_setup.c b/src/p_setup.c index c4c4a5dee..bdfc513d5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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);