diff --git a/src/g_demo.cpp b/src/g_demo.cpp index fea181a6a..56a0f83e9 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -110,7 +110,7 @@ demoghost *ghosts = NULL; // DEMO RECORDING // -#define DEMOVERSION 0x0008 +#define DEMOVERSION 0x0009 #define DEMOHEADER "\xF0" "KartReplay" "\x0F" #define DF_ATTACKMASK (ATTACKING_TIME|ATTACKING_LAP|ATTACKING_SPB) // This demo contains time/lap data @@ -2205,6 +2205,18 @@ void G_BeginRecording(void) WRITEUINT8(demobuf.p, grandprixinfo.eventmode); } + // Save netUnlocked from actual unlocks + // (netUnlocked is used in m_cond.c M_CheckNetUnlockByID) + WRITEUINT32(demobuf.p, MAXUNLOCKABLES); + for (size_t unlockindex = 0; unlockindex < MAXUNLOCKABLES; unlockindex++) + { + UINT8 unlock = gamedata->unlocked[unlockindex]; + WRITEUINT8(demobuf.p, unlock); + } + + // Save "mapmusrng" used for altmusic selection + WRITEUINT8(demobuf.p, mapmusrng); + // Now store some info for each in-game player // Lat' 12/05/19: Do note that for the first game you load, everything that gets saved here is total garbage; @@ -3163,6 +3175,21 @@ void G_DoPlayDemo(const char *defdemoname) grandprixinfo.eventmode = static_cast(READUINT8(demobuf.p)); } + // Load unlocks into netUnlocked + { + UINT32 unlockables = READUINT32(demobuf.p); + UINT32 unlocksread = std::min(unlockables, MAXUNLOCKABLES); + for (size_t i = 0; i < unlocksread; i++) + { + netUnlocked[i] = static_cast(READUINT8(demobuf.p)); + } + // skip remainder + demobuf.p += unlockables - unlocksread; + } + + // Load "mapmusrng" used for altmusic selection + mapmusrng = READUINT8(demobuf.p); + // Sigh ... it's an empty demo. if (*demobuf.p == DEMOMARKER) { @@ -3911,11 +3938,12 @@ boolean G_CheckDemoStatus(void) G_FinishExitLevel(); else { + UINT8 wasmodeattacking = modeattacking; G_StopDemo(); if (timedemo_quit) COM_ImmedExecute("quit"); - else if (modeattacking) + else if (wasmodeattacking) M_EndModeAttackRun(); else if (demo.attract == DEMO_ATTRACT_CREDITS) F_ContinueCredits(); diff --git a/src/m_cond.c b/src/m_cond.c index a306e4844..345641454 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -3270,7 +3270,7 @@ boolean M_CheckNetUnlockByID(UINT16 unlockid) return true; // default permit } - if (netgame) + if (netgame || demo.playback) { return netUnlocked[unlockid]; } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 8305d680b..8b195aa46 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -8177,20 +8177,33 @@ void P_ResetLevelMusic(void) { UINT8 idx = 0; - if (mapheaderinfo[gamemap-1]->musname_size > 1) + mapheader_t* mapheader = mapheaderinfo[gamemap - 1]; + + // To keep RNG in sync, we will always pull from RNG, even if unused + UINT32 random = P_Random(PR_MUSICSELECT); + + if (demo.playback) + { + // mapmusrng has already been set by the demo; just make sure it's valid + if (mapmusrng >= mapheader->musname_size) + { + mapmusrng = 0; + } + return; + } + + if (mapheader->musname_size > 1) { UINT8 tempmapmus[MAXMUSNAMES], tempmapmus_size = 1, i; tempmapmus[0] = 0; - for (i = 1; i < mapheaderinfo[gamemap-1]->musname_size; i++) + for (i = 1; i < mapheader->musname_size; i++) { - if (mapheaderinfo[gamemap-1]->cache_muslock[i-1] < MAXUNLOCKABLES - && !M_CheckNetUnlockByID(mapheaderinfo[gamemap-1]->cache_muslock[i-1])) + if (mapheader->cache_muslock[i-1] < MAXUNLOCKABLES + && !M_CheckNetUnlockByID(mapheader->cache_muslock[i-1])) continue; - //CONS_Printf("TEST - %u\n", i); - tempmapmus[tempmapmus_size++] = i; } @@ -8204,9 +8217,8 @@ void P_ResetLevelMusic(void) } else { - idx = P_RandomKey(PR_MUSICSELECT, tempmapmus_size); + idx = random % tempmapmus_size; } - //CONS_Printf("Rolled position %u, maps to %u\n", mapmusrng, tempmapmus[mapmusrng]); idx = tempmapmus[idx]; } } @@ -8216,7 +8228,13 @@ void P_ResetLevelMusic(void) void P_LoadLevelMusic(void) { - const char *music = mapheaderinfo[gamemap-1]->musname[mapmusrng]; + mapheader_t* mapheader = mapheaderinfo[gamemap-1]; + const char *music = mapheader->musname[0]; + + if (mapmusrng < mapheader->musname_size) + { + music = mapheader->musname[mapmusrng]; + } if (gametyperules & GTR_NOPOSITION || modeattacking != ATTACKING_NONE) {