From 834150585b2977a05c9789acc8ace8006d5affe7 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 29 Dec 2022 21:30:04 +0000 Subject: [PATCH] Rework demo time/laptime handling * `ATTACKING_` constants have been changed to be flags - `ATTACKING_TIME` contains time data for all gametypes - `ATTACKING_LAPS` contains laps data for `GTR_CIRCUIT` on maps with more than 1 lap * `demoflags` now contains raw `ATTACKING_` flags * Best time/best lap demo files will now be saved properly again (broken since `new-menus`) * Ghosts will now be loaded properly again (broken since `unlockables-undefeatable`) --- src/doomstat.h | 6 +- src/g_demo.c | 140 +++++++++++++++++++---------------------------- src/g_game.c | 50 ++++++++++------- src/k_menufunc.c | 12 ++-- src/p_setup.c | 17 +++--- 5 files changed, 104 insertions(+), 121 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 9222e7381..63739358f 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -131,9 +131,9 @@ extern boolean usedCheats; extern boolean imcontinuing; // Temporary flag while continuing extern boolean metalrecording; -#define ATTACKING_NONE 0 -#define ATTACKING_TIME 1 -#define ATTACKING_CAPSULES 2 +#define ATTACKING_NONE 0 +#define ATTACKING_TIME 1 +#define ATTACKING_LAP (1<<1) extern UINT8 modeattacking; // menu demo things diff --git a/src/g_demo.c b/src/g_demo.c index e47d8ba28..ddf0b342f 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -120,18 +120,14 @@ demoghost *ghosts = NULL; #define DEMOVERSION 0x0007 #define DEMOHEADER "\xF0" "KartReplay" "\x0F" -#define DF_GHOST 0x01 // This demo contains ghost data too! -#define DF_TIMEATTACK 0x02 // This demo is from Time Attack and contains its final completion time & best lap! -#define DF_BREAKTHECAPSULES 0x04 // This demo is from Break the Capsules and contains its final completion time! -#define DF_ATTACKMASK 0x06 // This demo is from ??? attack and contains ??? +#define DF_ATTACKMASK (ATTACKING_TIME|ATTACKING_LAP) // This demo contains time/lap data -// 0x08 free +#define DF_GHOST 0x08 // This demo contains ghost data too! #define DF_NONETMP 0x10 // multiplayer but not netgame #define DF_LUAVARS 0x20 // this demo contains extra lua vars -#define DF_ATTACKSHIFT 1 #define DF_ENCORE 0x40 #define DF_MULTIPLAYER 0x80 // This demo was recorded in multiplayer mode! @@ -2339,10 +2335,19 @@ void G_BeginRecording(void) memset(name,0,sizeof(name)); demo_p = demobuffer; - demoflags = DF_GHOST|(multiplayer ? DF_MULTIPLAYER : (modeattacking<>DF_ATTACKSHIFT) + if ((demoflags & DF_ATTACKMASK)) { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_TIME: // 1 - demotime_p = demo_p; + demotime_p = demo_p; + + if (demoflags & ATTACKING_TIME) WRITEUINT32(demo_p,UINT32_MAX); // time + if (demoflags & ATTACKING_LAP) WRITEUINT32(demo_p,UINT32_MAX); // lap - break; - case ATTACKING_CAPSULES: // 2 - demotime_p = demo_p; - WRITEUINT32(demo_p,UINT32_MAX); // time - break; - default: // 3 - break; + } + else + { + demotime_p = NULL; } for (i = 0; i < PRNUMCLASS; i++) @@ -2600,18 +2602,15 @@ void G_SetDemoTime(UINT32 ptime, UINT32 plap) { if (!demo.recording || !demotime_p) return; - if (demoflags & DF_TIMEATTACK) + if (demoflags & ATTACKING_TIME) { WRITEUINT32(demotime_p, ptime); + } + if (demoflags & ATTACKING_LAP) + { WRITEUINT32(demotime_p, plap); - demotime_p = NULL; - } - else if (demoflags & DF_BREAKTHECAPSULES) - { - WRITEUINT32(demotime_p, ptime); - (void)plap; - demotime_p = NULL; } + demotime_p = NULL; } // Returns bitfield: @@ -2622,7 +2621,8 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) { UINT8 *buffer,*p; UINT8 flags; - UINT32 oldtime, newtime, oldlap, newlap; + UINT32 oldtime = UINT32_MAX, newtime = UINT32_MAX; + UINT32 oldlap = UINT32_MAX, newlap = UINT32_MAX; UINT16 oldversion; size_t bufsize ATTRUNUSED; UINT8 c; @@ -2658,17 +2658,16 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) G_SkipDemoSkins(&p); - aflags = flags & (DF_TIMEATTACK|DF_BREAKTHECAPSULES); + aflags = flags & DF_ATTACKMASK; I_Assert(aflags); - if (flags & DF_TIMEATTACK) - uselaps = true; // get around uninitalized error + if (aflags & ATTACKING_LAP) + uselaps = true; - newtime = READUINT32(p); + if (aflags & ATTACKING_TIME) + newtime = READUINT32(p); if (uselaps) newlap = READUINT32(p); - else - newlap = UINT32_MAX; Z_Free(buffer); @@ -2724,11 +2723,10 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname) G_SkipDemoSkins(&p); - oldtime = READUINT32(p); + if (flags & ATTACKING_TIME) + oldtime = READUINT32(p); if (uselaps) oldlap = READUINT32(p); - else - oldlap = 0; Z_Free(buffer); @@ -3136,7 +3134,7 @@ void G_DoPlayDemo(char *defdemoname) return; } - modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT; + modeattacking = (demoflags & DF_ATTACKMASK); multiplayer = !!(demoflags & DF_MULTIPLAYER); demo.netgame = (multiplayer && !(demoflags & DF_NONETMP)); CON_ToggleOff(); @@ -3144,21 +3142,10 @@ void G_DoPlayDemo(char *defdemoname) hu_demotime = UINT32_MAX; hu_demolap = UINT32_MAX; - switch (modeattacking) - { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_TIME: // 1 - hu_demotime = READUINT32(demo_p); - hu_demolap = READUINT32(demo_p); - break; - case ATTACKING_CAPSULES: // 2 - hu_demotime = READUINT32(demo_p); - break; - default: // 3 - modeattacking = ATTACKING_NONE; - break; - } + if (modeattacking & ATTACKING_TIME) + hu_demotime = READUINT32(demo_p); + if (modeattacking & ATTACKING_LAP) + hu_demolap = READUINT32(demo_p); // Random seed for (i = 0; i < PRNUMCLASS; i++) @@ -3545,19 +3532,10 @@ void G_AddGhost(char *defdemoname) return; } - switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) - { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_TIME: // 1 - p += 8; // demo time, lap - break; - case ATTACKING_CAPSULES: // 2 - p += 4; // demo time - break; - default: // 3 - break; - } + if (flags & ATTACKING_TIME) + p += 4; + if (flags & ATTACKING_LAP) + p += 4; for (i = 0; i < PRNUMCLASS; i++) { @@ -3587,9 +3565,10 @@ void G_AddGhost(char *defdemoname) p++; // player number - doesn't really need to be checked, TODO maybe support adding multiple players' ghosts at once // any invalidating flags? - if ((READUINT8(p) & (DEMO_SPECTATOR|DEMO_BOT)) != 0) + i = READUINT8(p); + if ((i & (DEMO_SPECTATOR|DEMO_BOT)) != 0) { - CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); + CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot (spectator/bot)\n"), pdemoname); Z_Free(skinlist); Z_Free(pdemoname); Z_Free(buffer); @@ -3600,6 +3579,8 @@ void G_AddGhost(char *defdemoname) M_Memcpy(name, p, 16); p += 16; + p += MAXAVAILABILITY; + // Skin i = READUINT8(p); if (i < worknumskins) @@ -3620,7 +3601,7 @@ void G_AddGhost(char *defdemoname) if (READUINT8(p) != 0xFF) { - CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); + CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot (bad terminator)\n"), pdemoname); Z_Free(skinlist); Z_Free(pdemoname); Z_Free(buffer); @@ -3761,19 +3742,10 @@ void G_UpdateStaffGhostName(lumpnum_t l) G_SkipDemoSkins(&p); - switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) - { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_TIME: // 1 - p += 8; // demo time, lap - break; - case ATTACKING_CAPSULES: // 2 - p += 4; // demo time - break; - default: // 3 - break; - } + if (flags & ATTACKING_TIME) + p += 4; + if (flags & ATTACKING_LAP) + p += 4; for (i = 0; i < PRNUMCLASS; i++) { diff --git a/src/g_game.c b/src/g_game.c index 2c7f85efb..8ba6a4aa5 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -520,13 +520,18 @@ static void G_UpdateRecordReplays(void) players[consoleplayer].realtime = UINT32_MAX; } - if (((mapheaderinfo[gamemap-1]->mainrecord->time == 0) || (players[consoleplayer].realtime < mapheaderinfo[gamemap-1]->mainrecord->time)) - && (players[consoleplayer].realtime < UINT32_MAX)) // DNF + if (modeattacking & ATTACKING_TIME) { - mapheaderinfo[gamemap-1]->mainrecord->time = players[consoleplayer].realtime; + if (((mapheaderinfo[gamemap-1]->mainrecord->time == 0) || (players[consoleplayer].realtime < mapheaderinfo[gamemap-1]->mainrecord->time)) + && (players[consoleplayer].realtime < UINT32_MAX)) // DNF + mapheaderinfo[gamemap-1]->mainrecord->time = players[consoleplayer].realtime; + } + else + { + mapheaderinfo[gamemap-1]->mainrecord->time = 0; } - if (modeattacking == ATTACKING_TIME) + if (modeattacking & ATTACKING_LAP) { if ((mapheaderinfo[gamemap-1]->mainrecord->lap == 0) || (bestlap < mapheaderinfo[gamemap-1]->mainrecord->lap)) mapheaderinfo[gamemap-1]->mainrecord->lap = bestlap; @@ -549,27 +554,32 @@ static void G_UpdateRecordReplays(void) strcat(gpath, PATHSEP); strcat(gpath, G_BuildMapName(gamemap)); - snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, cv_chooseskin.string); + snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, cv_skin[0].string); - gpath = Z_StrDup(gpath); - - if (FIL_FileExists(lastdemo)) + if (modeattacking != ATTACKING_NONE && FIL_FileExists(lastdemo)) { UINT8 *buf; - size_t len = FIL_ReadFile(lastdemo, &buf); + size_t len; - snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, cv_chooseskin.string); - if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) - { // Better time, save this demo. - if (FIL_FileExists(bestdemo)) - remove(bestdemo); - FIL_WriteFile(bestdemo, buf, len); - CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); + gpath = Z_StrDup(gpath); + + len = FIL_ReadFile(lastdemo, &buf); + + if (modeattacking & ATTACKING_TIME) + { + snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, cv_skin[0].string); + if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) + { // Better time, save this demo. + if (FIL_FileExists(bestdemo)) + remove(bestdemo); + FIL_WriteFile(bestdemo, buf, len); + CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); + } } - if (modeattacking == ATTACKING_TIME) + if (modeattacking & ATTACKING_LAP) { - snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_chooseskin.string); + snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_skin[0].string); if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)) { // Better lap time, save this demo. if (FIL_FileExists(bestdemo)) @@ -582,9 +592,9 @@ static void G_UpdateRecordReplays(void) //CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo); Z_Free(buf); - } - Z_Free(gpath); + Z_Free(gpath); + } // Check emblems when level data is updated if ((earnedEmblems = M_CheckLevelEmblems())) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 3ffc8403a..abd3baa99 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -4056,14 +4056,12 @@ void M_StartTimeAttack(INT32 choice) (void)choice; - switch (levellist.newgametype) + modeattacking = ATTACKING_TIME; + + if ((gametypes[levellist.newgametype]->rules & GTR_CIRCUIT) + && (mapheaderinfo[levellist.choosemap]->numlaps != 1)) { - case GT_BATTLE: - modeattacking = ATTACKING_CAPSULES; - break; - default: - modeattacking = ATTACKING_TIME; - break; + modeattacking |= ATTACKING_LAP; } // Still need to reset devmode diff --git a/src/p_setup.c b/src/p_setup.c index e09141271..36a589f22 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -6993,20 +6993,23 @@ static void P_LoadRecordGhosts(void) gpath = Z_StrDup(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap))); // Best Time ghost - if (cv_ghost_besttime.value) + if (modeattacking & ATTACKING_TIME) { - for (i = 0; i < numskins; ++i) + if (cv_ghost_besttime.value) { - if (cv_ghost_besttime.value == 1 && players[consoleplayer].skin != i) - continue; + for (i = 0; i < numskins; ++i) + { + if (cv_ghost_besttime.value == 1 && players[consoleplayer].skin != i) + continue; - if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i].name))) + G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name)); + } } } // Best Lap ghost - if (modeattacking != ATTACKING_CAPSULES) + if (modeattacking & ATTACKING_LAP) { if (cv_ghost_bestlap.value) {