From 05d8d83dcc724de7487413be30dbc3fd09a49f24 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 27 Jan 2024 04:12:36 -0800 Subject: [PATCH 1/8] Refactor recorddata_t and separate into recordtimes_t --- src/doomstat.h | 9 +++++++-- src/g_game.c | 29 +++++++++++++++-------------- src/k_menudraw.c | 11 ++++++----- src/m_cond.c | 4 ++-- src/typedef.h | 1 + 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 333bfd6f0..40240362c 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -152,11 +152,16 @@ struct skinreference_t #define MV_MYSTICMELODY (1<<4) #define MV_MAX (MV_VISITED|MV_BEATEN|MV_ENCORE|MV_SPBATTACK|MV_MYSTICMELODY) +struct recordtimes_t +{ + tic_t time; ///< Time in which the level was finished. + tic_t lap; ///< Best lap time for this level. +}; + struct recorddata_t { UINT8 mapvisited; - tic_t time; ///< Time in which the level was finished. - tic_t lap; ///< Best lap time for this level. + recordtimes_t timeattack; ///< Best times for Time Attack }; #define KARTSPEED_AUTO -1 diff --git a/src/g_game.c b/src/g_game.c index 88effe9d8..1461d4942 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -386,10 +386,10 @@ void G_ClearRecords(void) // For easy retrieval of records tic_t G_GetBestTime(INT16 map) { - if (!mapheaderinfo[map] || mapheaderinfo[map]->records.time <= 0) + if (!mapheaderinfo[map] || mapheaderinfo[map]->records.timeattack.time <= 0) return (tic_t)UINT32_MAX; - return mapheaderinfo[map]->records.time; + return mapheaderinfo[map]->records.timeattack.time; } // BE RIGHT BACK @@ -536,21 +536,22 @@ void G_TickTimeStickerMedals(void) void G_UpdateRecords(void) { UINT8 earnedEmblems; + recordtimes_t *record = &mapheaderinfo[gamemap-1]->records.timeattack; if (modeattacking & ATTACKING_TIME) { tic_t time = players[consoleplayer].realtime; if (players[consoleplayer].pflags & PF_NOCONTEST) time = UINT32_MAX; - if (((mapheaderinfo[gamemap-1]->records.time == 0) || (time < mapheaderinfo[gamemap-1]->records.time)) + if (((record->time == 0) || (time < record->time)) && (time < UINT32_MAX)) // DNF - mapheaderinfo[gamemap-1]->records.time = time; + record->time = time; } if (modeattacking & ATTACKING_LAP) { - if ((mapheaderinfo[gamemap-1]->records.lap == 0) || (bestlap < mapheaderinfo[gamemap-1]->records.lap)) - mapheaderinfo[gamemap-1]->records.lap = bestlap; + if ((record->lap == 0) || (bestlap < record->lap)) + record->lap = bestlap; } // Check emblems when level data is updated @@ -5069,8 +5070,8 @@ void G_LoadGameData(void) recorddata_t dummyrecord; dummyrecord.mapvisited = READUINT8(save.p); - dummyrecord.time = (tic_t)READUINT32(save.p); - dummyrecord.lap = (tic_t)READUINT32(save.p); + dummyrecord.timeattack.time = (tic_t)READUINT32(save.p); + dummyrecord.timeattack.lap = (tic_t)READUINT32(save.p); if (mapnum < nummapheaders && mapheaderinfo[mapnum]) { @@ -5081,8 +5082,8 @@ void G_LoadGameData(void) } else if ( (dummyrecord.mapvisited & MV_BEATEN) - || dummyrecord.time != 0 - || dummyrecord.lap != 0 + || dummyrecord.timeattack.time != 0 + || dummyrecord.timeattack.lap != 0 ) { // Invalid, but we don't want to lose all the juicy statistics. @@ -5684,8 +5685,8 @@ void G_SaveGameData(void) WRITEUINT8(save.p, mapvisitedtemp); - WRITEUINT32(save.p, mapheaderinfo[i]->records.time); - WRITEUINT32(save.p, mapheaderinfo[i]->records.lap); + WRITEUINT32(save.p, mapheaderinfo[i]->records.timeattack.time); + WRITEUINT32(save.p, mapheaderinfo[i]->records.timeattack.lap); if (--numgamedatamapheaders == 0) break; @@ -5702,8 +5703,8 @@ void G_SaveGameData(void) WRITEUINT8(save.p, unloadedmap->records.mapvisited); - WRITEUINT32(save.p, unloadedmap->records.time); - WRITEUINT32(save.p, unloadedmap->records.lap); + WRITEUINT32(save.p, unloadedmap->records.timeattack.time); + WRITEUINT32(save.p, unloadedmap->records.timeattack.lap); if (--numgamedatamapheaders == 0) break; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index da532c564..31a1e844b 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3503,8 +3503,9 @@ void M_DrawTimeAttack(void) if (currentMenu == &PLAY_TimeAttackDef) { - tic_t timerec = mapheaderinfo[map]->records.time; - tic_t laprec = mapheaderinfo[map]->records.lap; + recordtimes_t *record = &mapheaderinfo[map]->records.timeattack; + tic_t timerec = record->time; + tic_t laprec = record->lap; UINT32 timeheight = 82; if ((gametypes[levellist.newgametype]->rules & GTR_CIRCUIT) @@ -7236,13 +7237,13 @@ static void M_DrawStatsMaps(void) if (!(mapheaderinfo[i]->typeoflevel & (TOL_RACE|TOL_BATTLE|TOL_SPECIAL|TOL_VERSUS))) continue; - if (mapheaderinfo[i]->records.time <= 0) + if (mapheaderinfo[i]->records.timeattack.time <= 0) { mapsunfinished++; continue; } - besttime += mapheaderinfo[i]->records.time; + besttime += mapheaderinfo[i]->records.timeattack.time; } V_DrawRightAlignedThinString(BASEVIDWIDTH-20, 60, 0, @@ -7322,7 +7323,7 @@ static void M_DrawStatsMaps(void) ) ) { - besttime = mapheaderinfo[mnum]->records.time; + besttime = mapheaderinfo[mnum]->records.timeattack.time; if (besttime) { diff --git a/src/m_cond.c b/src/m_cond.c index 9414e73fa..0bf60d5ab 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -3470,9 +3470,9 @@ boolean M_GotLowEnoughTime(INT32 tictime) if (!mapheaderinfo[i] || (mapheaderinfo[i]->menuflags & LF2_NOTIMEATTACK)) continue; - if (!mapheaderinfo[i]->records.time) + if (!mapheaderinfo[i]->records.timeattack.time) return false; - if ((curtics += mapheaderinfo[i]->records.time) > tictime) + if ((curtics += mapheaderinfo[i]->records.timeattack.time) > tictime) return false; } return true; diff --git a/src/typedef.h b/src/typedef.h index 605103166..e866a22a9 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -123,6 +123,7 @@ TYPEDEF (precipprops_t); TYPEDEF (skinrecord_t); TYPEDEF (unloaded_skin_t); TYPEDEF (skinreference_t); +TYPEDEF (recordtimes_t); TYPEDEF (recorddata_t); TYPEDEF (cupwindata_t); TYPEDEF (scene_t); From ff07b92f18403aaf3ef247c5a38d6fd9cfd71a60 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 27 Jan 2024 04:23:38 -0800 Subject: [PATCH 2/8] Gamedata: save SPB Attack times separately from normal Time Attack Bumps gamedata version! Gamedata version 10 -> 11 --- src/doomstat.h | 1 + src/g_game.c | 22 ++++++++++++++++++++-- src/k_menudraw.c | 3 ++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 40240362c..6e3742752 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -162,6 +162,7 @@ struct recorddata_t { UINT8 mapvisited; recordtimes_t timeattack; ///< Best times for Time Attack + recordtimes_t spbattack; ///< Best times for SPB Attack }; #define KARTSPEED_AUTO -1 diff --git a/src/g_game.c b/src/g_game.c index 1461d4942..bb10672b0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -536,7 +536,9 @@ void G_TickTimeStickerMedals(void) void G_UpdateRecords(void) { UINT8 earnedEmblems; - recordtimes_t *record = &mapheaderinfo[gamemap-1]->records.timeattack; + recordtimes_t *record = (modeattacking & ATTACKING_SPB) ? + &mapheaderinfo[gamemap-1]->records.spbattack : + &mapheaderinfo[gamemap-1]->records.timeattack; if (modeattacking & ATTACKING_TIME) { @@ -4685,7 +4687,7 @@ void G_LoadGameSettings(void) } #define GD_VERSIONCHECK 0xBA5ED123 // Change every major version, as usual -#define GD_VERSIONMINOR 10 // Change every format update +#define GD_VERSIONMINOR 11 // Change every format update // You can't rearrange these without a special format update typedef enum @@ -5073,6 +5075,16 @@ void G_LoadGameData(void) dummyrecord.timeattack.time = (tic_t)READUINT32(save.p); dummyrecord.timeattack.lap = (tic_t)READUINT32(save.p); + if (versionMinor < 11) + { + memset(&dummyrecord.spbattack, 0, sizeof dummyrecord.spbattack); + } + else + { + dummyrecord.spbattack.time = (tic_t)READUINT32(save.p); + dummyrecord.spbattack.lap = (tic_t)READUINT32(save.p); + } + if (mapnum < nummapheaders && mapheaderinfo[mapnum]) { // Valid mapheader, time to populate with record data. @@ -5084,6 +5096,8 @@ void G_LoadGameData(void) (dummyrecord.mapvisited & MV_BEATEN) || dummyrecord.timeattack.time != 0 || dummyrecord.timeattack.lap != 0 + || dummyrecord.spbattack.time != 0 + || dummyrecord.spbattack.lap != 0 ) { // Invalid, but we don't want to lose all the juicy statistics. @@ -5687,6 +5701,8 @@ void G_SaveGameData(void) WRITEUINT32(save.p, mapheaderinfo[i]->records.timeattack.time); WRITEUINT32(save.p, mapheaderinfo[i]->records.timeattack.lap); + WRITEUINT32(save.p, mapheaderinfo[i]->records.spbattack.time); + WRITEUINT32(save.p, mapheaderinfo[i]->records.spbattack.lap); if (--numgamedatamapheaders == 0) break; @@ -5705,6 +5721,8 @@ void G_SaveGameData(void) WRITEUINT32(save.p, unloadedmap->records.timeattack.time); WRITEUINT32(save.p, unloadedmap->records.timeattack.lap); + WRITEUINT32(save.p, unloadedmap->records.spbattack.time); + WRITEUINT32(save.p, unloadedmap->records.spbattack.lap); if (--numgamedatamapheaders == 0) break; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 31a1e844b..682f95681 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3503,7 +3503,8 @@ void M_DrawTimeAttack(void) if (currentMenu == &PLAY_TimeAttackDef) { - recordtimes_t *record = &mapheaderinfo[map]->records.timeattack; + recorddata_t *rcp = &mapheaderinfo[map]->records; + recordtimes_t *record = cv_dummyspbattack.value ? &rcp->spbattack : &rcp->timeattack; tic_t timerec = record->time; tic_t laprec = record->lap; UINT32 timeheight = 82; From fb5e0d38ac5df0d34b582971683b06dded18be31 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 27 Jan 2024 04:25:28 -0800 Subject: [PATCH 3/8] Menus/Time Attack: fix ta_e enum --- src/k_menu.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/k_menu.h b/src/k_menu.h index 9ab7da97c..db668fb32 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -275,7 +275,6 @@ typedef enum ta_replay = 0, ta_guest, ta_ghosts, - ta_spb, ta_spacer, ta_start, } ta_e; From 2bf115cd46589d3c6aa20faee268947293cd02d2 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 27 Jan 2024 04:27:13 -0800 Subject: [PATCH 4/8] Menus/Time Attack: group "Replay Last" with "Best Time" and "Best Lap" --- src/menus/play-local-race-time-attack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/menus/play-local-race-time-attack.c b/src/menus/play-local-race-time-attack.c index 3d5225ea6..482ad3e27 100644 --- a/src/menus/play-local-race-time-attack.c +++ b/src/menus/play-local-race-time-attack.c @@ -88,8 +88,8 @@ typedef enum { tareplay_besttime = 0, tareplay_bestlap, - tareplay_gap1, tareplay_last, + tareplay_gap1, tareplay_guest, tareplay_staff, tareplay_gap2, @@ -100,8 +100,8 @@ menuitem_t PLAY_TAReplay[] = { {IT_STRING | IT_CALL, "Replay Best Time", NULL, "MENUI006", {.routine = M_ReplayTimeAttack}, 0, 0}, {IT_STRING | IT_CALL, "Replay Best Lap", NULL, "MENUI006", {.routine = M_ReplayTimeAttack}, 0, 0}, - {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, {IT_STRING | IT_CALL, "Replay Last", NULL, "MENUI006", {.routine = M_ReplayTimeAttack}, 0, 0}, + {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, {IT_STRING | IT_CALL, "Replay Guest", NULL, "MENUI006", {.routine = M_ReplayTimeAttack}, 0, 0}, {IT_STRING | IT_ARROWS, "Replay Staff", NULL, "MENUI006", {.routine = M_HandleStaffReplay}, 0, 0}, {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, From 378fb8ed0776cda7a36ea646e71ce58ba6227757 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 27 Jan 2024 04:30:35 -0800 Subject: [PATCH 5/8] Save SPB Attack replays with "spb-" in the file name - Files - spb-time-best - spb-time-lap - spb-last - Menu - Toggling SPB Attack refreshes the menu (to show/hide certain replay options) --- src/g_game.c | 12 ++- src/menus/play-local-race-time-attack.c | 99 ++++++++++++++++--------- src/p_setup.cpp | 10 ++- 3 files changed, 78 insertions(+), 43 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index bb10672b0..9397dbe7b 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -582,6 +582,12 @@ static void G_UpdateRecordReplays(void) { char *gpath; char lastdemo[256], bestdemo[256]; + const char *modeprefix = ""; + + if (modeattacking & ATTACKING_SPB) + { + modeprefix = "spb-"; + } if (players[consoleplayer].pflags & PF_NOCONTEST) { @@ -601,7 +607,7 @@ static void G_UpdateRecordReplays(void) strcat(gpath, PATHSEP); strcat(gpath, G_BuildMapName(gamemap)); - snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, cv_skin[0].string); + snprintf(lastdemo, 255, "%s-%s-%slast.lmp", gpath, cv_skin[0].string, modeprefix); if (modeattacking != ATTACKING_NONE && FIL_FileExists(lastdemo)) { @@ -614,7 +620,7 @@ static void G_UpdateRecordReplays(void) if (modeattacking & ATTACKING_TIME) { - snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, cv_skin[0].string); + snprintf(bestdemo, 255, "%s-%s-%stime-best.lmp", gpath, cv_skin[0].string, modeprefix); if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) { // Better time, save this demo. if (FIL_FileExists(bestdemo)) @@ -626,7 +632,7 @@ static void G_UpdateRecordReplays(void) if (modeattacking & ATTACKING_LAP) { - snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_skin[0].string); + snprintf(bestdemo, 255, "%s-%s-%slap-best.lmp", gpath, cv_skin[0].string, modeprefix); if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)) { // Better lap time, save this demo. if (FIL_FileExists(bestdemo)) diff --git a/src/menus/play-local-race-time-attack.c b/src/menus/play-local-race-time-attack.c index 482ad3e27..50e211224 100644 --- a/src/menus/play-local-race-time-attack.c +++ b/src/menus/play-local-race-time-attack.c @@ -11,12 +11,6 @@ #include "../z_zone.h" // Z_StrDup/Z_Free #include "../m_cond.h" -void CV_SPBAttackChanged(void); -void CV_SPBAttackChanged(void) -{ - G_UpdateTimeStickerMedals(levellist.choosemap, false); -} - struct timeattackmenu_s timeattackmenu; void M_TimeAttackTick(void) @@ -214,40 +208,24 @@ menu_t PLAY_TAGhostsDef = { NULL }; -// time attack stuff... -void M_PrepareTimeAttack(INT32 choice) +void CV_SPBAttackChanged(void); +void CV_SPBAttackChanged(void) { - (void) choice; - - timeattackmenu.ticker = 0; - - // Gametype guess - if (levellist.guessgt != MAXGAMETYPES) - { - levellist.newgametype = levellist.guessgt; - if (!(gametypes[levellist.newgametype]->tol & mapheaderinfo[levellist.choosemap]->typeoflevel)) - { - INT32 guess = G_GuessGametypeByTOL(mapheaderinfo[levellist.choosemap]->typeoflevel); - if (guess != -1) - levellist.newgametype = guess; - } - } - - if (levellist.levelsearch.timeattack == false || levellist.newgametype != GT_RACE || !M_SecretUnlocked(SECRET_SPBATTACK, true)) - CV_SetValue(&cv_dummyspbattack, 0); - - // Time-sticker Medals G_UpdateTimeStickerMedals(levellist.choosemap, false); // Menu options { // see also p_setup.c's P_LoadRecordGhosts char *gpath = Z_StrDup(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(levellist.choosemap+1))); + const char *modeprefix = ""; UINT8 active; if (!gpath) return; + if (cv_dummyspbattack.value) + modeprefix = "spb-"; + active = false; PLAY_TimeAttack[ta_guest].status = IT_DISABLED; PLAY_TimeAttack[ta_replay].status = IT_DISABLED; @@ -256,11 +234,11 @@ void M_PrepareTimeAttack(INT32 choice) // Check if file exists, if not, disable options PLAY_TAReplay[tareplay_besttime].status = PLAY_TAReplayGuest[taguest_besttime].status = IT_DISABLED; - if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, cv_skin[0].string))) + if (FIL_FileExists(va("%s-%s-%stime-best.lmp", gpath, cv_skin[0].string, modeprefix))) { PLAY_TAReplay[tareplay_besttime].status = IT_STRING|IT_CALL; PLAY_TAReplayGuest[taguest_besttime].status = IT_STRING|IT_CALL; - active |= (1|2|4); + active |= (1|2|4|8); } else if (PLAY_TAReplayGuestDef.lastOn == taguest_besttime) PLAY_TAReplayGuestDef.lastOn = taguest_back; @@ -270,23 +248,23 @@ void M_PrepareTimeAttack(INT32 choice) PLAY_TAGhosts[taghost_bestlap].status = IT_DISABLED; if ((gametypes[levellist.newgametype]->rules & GTR_CIRCUIT) && (mapheaderinfo[levellist.choosemap]->numlaps != 1) - && FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, cv_skin[0].string))) + && FIL_FileExists(va("%s-%s-%slap-best.lmp", gpath, cv_skin[0].string, modeprefix))) { PLAY_TAReplay[tareplay_bestlap].status = IT_STRING|IT_CALL; PLAY_TAReplayGuest[taguest_bestlap].status = IT_STRING|IT_CALL; PLAY_TAGhosts[taghost_bestlap].status = IT_STRING|IT_CVAR; - active |= (1|2|4); + active |= (1|2|4|8); } else if (PLAY_TAReplayGuestDef.lastOn == taguest_bestlap) PLAY_TAReplayGuestDef.lastOn = taguest_back; PLAY_TAReplay[tareplay_last].status = PLAY_TAReplayGuest[taguest_last].status = IT_DISABLED; - if (FIL_FileExists(va("%s-%s-last.lmp", gpath, cv_skin[0].string))) + if (FIL_FileExists(va("%s-%s-%slast.lmp", gpath, cv_skin[0].string, modeprefix))) { PLAY_TAReplay[tareplay_last].status = IT_STRING|IT_CALL; PLAY_TAReplayGuest[taguest_last].status = IT_STRING|IT_CALL; - active |= (1|2|4); + active |= (1|2|4|8); } else if (PLAY_TAReplayGuestDef.lastOn == taguest_last) PLAY_TAReplayGuestDef.lastOn = taguest_back; @@ -314,6 +292,9 @@ void M_PrepareTimeAttack(INT32 choice) active |= 1|4; } + if (currentMenu == &PLAY_TimeAttackDef) + PLAY_TimeAttackDef.lastOn = itemOn; + if (active & 1) PLAY_TimeAttack[ta_replay].status = IT_STRING|IT_SUBMENU; else if (PLAY_TimeAttackDef.lastOn == ta_replay) @@ -327,10 +308,42 @@ void M_PrepareTimeAttack(INT32 choice) /*else if (PLAY_TimeAttackDef.lastOn == ta_ghosts) PLAY_TimeAttackDef.lastOn = ta_start;*/ + if ((active & 8) && levellist.newgametype == GT_RACE && M_SecretUnlocked(SECRET_SPBATTACK, true)) + PLAY_TAReplay[tareplay_header].status = IT_HEADER; + + if (currentMenu == &PLAY_TimeAttackDef) + itemOn = PLAY_TimeAttackDef.lastOn; + Z_Free(gpath); } } +// time attack stuff... +void M_PrepareTimeAttack(INT32 choice) +{ + (void) choice; + + timeattackmenu.ticker = 0; + + // Gametype guess + if (levellist.guessgt != MAXGAMETYPES) + { + levellist.newgametype = levellist.guessgt; + if (!(gametypes[levellist.newgametype]->tol & mapheaderinfo[levellist.choosemap]->typeoflevel)) + { + INT32 guess = G_GuessGametypeByTOL(mapheaderinfo[levellist.choosemap]->typeoflevel); + if (guess != -1) + levellist.newgametype = guess; + } + } + + if (levellist.levelsearch.timeattack == false || levellist.newgametype != GT_RACE || !M_SecretUnlocked(SECRET_SPBATTACK, true)) + CV_StealthSetValue(&cv_dummyspbattack, 0); + + // Menu options / Time-sticker medals + CV_SPBAttackChanged(); +} + void M_HandleStaffReplay(INT32 choice) { if (choice == 2) @@ -383,7 +396,12 @@ void M_ReplayTimeAttack(INT32 choice) return; } - G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(levellist.choosemap+1), cv_skin[0].string, which)); + const char *modeprefix = ""; + + if (cv_dummyspbattack.value) + modeprefix = "spb-"; + + G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s%s.lmp", srb2home, timeattackfolder, G_BuildMapName(levellist.choosemap+1), cv_skin[0].string, modeprefix, which)); } static const char *TA_GuestReplay_Str = NULL; @@ -402,7 +420,12 @@ static void M_WriteGuestReplay(INT32 ch) if (TA_GuestReplay_Str != NULL) { - len = FIL_ReadFile(va("%s-%s-%s.lmp", gpath, cv_skin[0].string, TA_GuestReplay_Str), &buf); + const char *modeprefix = ""; + + if (cv_dummyspbattack.value) + modeprefix = "spb-"; + + len = FIL_ReadFile(va("%s-%s-%s%s.lmp", gpath, cv_skin[0].string, modeprefix, TA_GuestReplay_Str), &buf); if (!len) { M_StartMessage("Guest Replay", "Replay to copy no longer exists!", NULL, MM_NOTHING, NULL, NULL); @@ -468,6 +491,7 @@ void M_StartTimeAttack(INT32 choice) { char *gpath; char nameofdemo[256]; + const char *modeprefix = ""; (void)choice; @@ -482,6 +506,7 @@ void M_StartTimeAttack(INT32 choice) if (cv_dummyspbattack.value) { modeattacking |= ATTACKING_SPB; + modeprefix = "spb-"; } // Still need to reset devmode @@ -516,7 +541,7 @@ void M_StartTimeAttack(INT32 choice) strcat(gpath, PATHSEP); strcat(gpath, G_BuildMapName(levellist.choosemap+1)); - snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, cv_skin[0].string); + snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-%slast", gpath, cv_skin[0].string, modeprefix); if (!cv_autorecord.value) remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo)); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index f70f552ca..43171ba9e 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -7785,10 +7785,14 @@ static void P_LoadRecordGhosts(void) { // see also /menus/play-local-race-time-attack.c's M_PrepareTimeAttack char *gpath; + const char *modeprefix = ""; INT32 i; gpath = Z_StrDup(va("%s" PATHSEP "media" PATHSEP "replay" PATHSEP "%s" PATHSEP "%s", srb2home, timeattackfolder, G_BuildMapName(gamemap))); + if (modeattacking & ATTACKING_SPB) + modeprefix = "spb-"; + // Best Time ghost if (modeattacking & ATTACKING_TIME) { @@ -7799,7 +7803,7 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_besttime.value == 1 && players[consoleplayer].skin != i) continue; - P_TryAddExternalGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name)); + P_TryAddExternalGhost(va("%s-%s-%stime-best.lmp", gpath, skins[i].name, modeprefix)); } } } @@ -7814,7 +7818,7 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_bestlap.value == 1 && players[consoleplayer].skin != i) continue; - P_TryAddExternalGhost(va("%s-%s-lap-best.lmp", gpath, skins[i].name)); + P_TryAddExternalGhost(va("%s-%s-%slap-best.lmp", gpath, skins[i].name, modeprefix)); } } } @@ -7827,7 +7831,7 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_last.value == 1 && players[consoleplayer].skin != i) continue; - P_TryAddExternalGhost(va("%s-%s-last.lmp", gpath, skins[i].name)); + P_TryAddExternalGhost(va("%s-%s-%slast.lmp", gpath, skins[i].name, modeprefix)); } } From 8e07dea0070bc3ceb83efe140438c71566dcaaae Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 27 Jan 2024 04:33:08 -0800 Subject: [PATCH 6/8] Menus/Time Attack: add SPB Attack context clue in "Replay..." submenu - Add a header that says "Time Attack..." or "SPB Attack..." depending on the mode - This only applies to Race Time Attack, not Prisons or Special - Header does not appear if SPB Attack is not unlocked --- src/menus/play-local-race-time-attack.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/menus/play-local-race-time-attack.c b/src/menus/play-local-race-time-attack.c index 50e211224..64edc5959 100644 --- a/src/menus/play-local-race-time-attack.c +++ b/src/menus/play-local-race-time-attack.c @@ -80,7 +80,8 @@ menu_t PLAY_TimeAttackDef = { typedef enum { - tareplay_besttime = 0, + tareplay_header = 0, + tareplay_besttime, tareplay_bestlap, tareplay_last, tareplay_gap1, @@ -92,6 +93,7 @@ typedef enum menuitem_t PLAY_TAReplay[] = { + {IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0}, {IT_STRING | IT_CALL, "Replay Best Time", NULL, "MENUI006", {.routine = M_ReplayTimeAttack}, 0, 0}, {IT_STRING | IT_CALL, "Replay Best Lap", NULL, "MENUI006", {.routine = M_ReplayTimeAttack}, 0, 0}, {IT_STRING | IT_CALL, "Replay Last", NULL, "MENUI006", {.routine = M_ReplayTimeAttack}, 0, 0}, @@ -231,6 +233,8 @@ void CV_SPBAttackChanged(void) PLAY_TimeAttack[ta_replay].status = IT_DISABLED; PLAY_TimeAttack[ta_ghosts].status = IT_DISABLED; + PLAY_TAReplay[tareplay_header].status = IT_DISABLED; + // Check if file exists, if not, disable options PLAY_TAReplay[tareplay_besttime].status = PLAY_TAReplayGuest[taguest_besttime].status = IT_DISABLED; @@ -309,7 +313,10 @@ void CV_SPBAttackChanged(void) PLAY_TimeAttackDef.lastOn = ta_start;*/ if ((active & 8) && levellist.newgametype == GT_RACE && M_SecretUnlocked(SECRET_SPBATTACK, true)) + { PLAY_TAReplay[tareplay_header].status = IT_HEADER; + PLAY_TAReplay[tareplay_header].text = cv_dummyspbattack.value ? "SPB Attack..." : "Time Attack..."; + } if (currentMenu == &PLAY_TimeAttackDef) itemOn = PLAY_TimeAttackDef.lastOn; From b70e59755f0cb07f4a4cf2d4477c9015cae354f2 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 17 Feb 2024 23:11:58 +0000 Subject: [PATCH 7/8] Tie SPB Attack and Encore together - A method to access Encore in Time Attack - so we have SOME Encore singleplayer content on launch - Also available for Versus mode (in Special Attack) - Finally, Encore rematches have a way to access them! - Obviously will not spawn a chasing SPB, it's just a signal for "hard mode" - Relevant gametype + unlock checks have been abstracted into M_EncoreAttackTogglePermitted --- src/g_game.c | 8 +++---- src/k_menu.h | 1 + src/k_menudraw.c | 7 +++--- src/menus/play-local-race-time-attack.c | 31 +++++++++++++++++++++---- src/p_setup.cpp | 4 ++-- 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 787961210..293ed9feb 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -428,7 +428,7 @@ void G_UpdateTimeStickerMedals(UINT16 map, boolean showownrecord) } case ET_MAP: { - if (emblem->flags & ME_SPBATTACK && cv_dummyspbattack.value) + if (emblem->flags & (ME_SPBATTACK|ME_ENCORE) && cv_dummyspbattack.value) break; goto bademblem; } @@ -436,7 +436,7 @@ void G_UpdateTimeStickerMedals(UINT16 map, boolean showownrecord) goto bademblem; } - if (cv_dummyspbattack.value && !(emblem->flags & ME_SPBATTACK)) + if (cv_dummyspbattack.value && !(emblem->flags & (ME_SPBATTACK|ME_ENCORE))) return; if (!gamedata->collected[(emblem-emblemlocations)] && gonnadrawtime) @@ -537,7 +537,7 @@ void G_TickTimeStickerMedals(void) void G_UpdateRecords(void) { UINT8 earnedEmblems; - recordtimes_t *record = (modeattacking & ATTACKING_SPB) ? + recordtimes_t *record = (encoremode == true) ? &mapheaderinfo[gamemap-1]->records.spbattack : &mapheaderinfo[gamemap-1]->records.timeattack; @@ -585,7 +585,7 @@ static void G_UpdateRecordReplays(void) char lastdemo[256], bestdemo[256]; const char *modeprefix = ""; - if (modeattacking & ATTACKING_SPB) + if (encoremode) { modeprefix = "spb-"; } diff --git a/src/k_menu.h b/src/k_menu.h index a623aedb3..4451748fe 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -906,6 +906,7 @@ void M_ReplayTimeAttack(INT32 choice); void M_HandleStaffReplay(INT32 choice); void M_SetGuestReplay(INT32 choice); void M_TimeAttackTick(void); +boolean M_EncoreAttackTogglePermitted(void); boolean M_TimeAttackInputs (INT32 choice); // MP selection diff --git a/src/k_menudraw.c b/src/k_menudraw.c index f7a808c73..3eba56d73 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3530,19 +3530,20 @@ void M_DrawTimeAttack(void) K_drawKartTimestamp(timerec, 162+t, timeheight+6, 0, 1); // SPB Attack control hint + menu overlay - if (levellist.newgametype == GT_RACE && levellist.levelsearch.timeattack == true && M_SecretUnlocked(SECRET_SPBATTACK, true)) { INT32 buttonx = 162 + t; INT32 buttony = timeheight; - K_drawButtonAnim(buttonx + 35, buttony - 3, V_SNAPTOLEFT, kp_button_r, timeattackmenu.ticker); + if (M_EncoreAttackTogglePermitted()) + { + K_drawButtonAnim(buttonx + 35, buttony - 3, V_SNAPTOLEFT, kp_button_r, timeattackmenu.ticker); + } if ((timeattackmenu.spbflicker == 0 || timeattackmenu.ticker % 2) == (cv_dummyspbattack.value == 1)) { V_DrawMappedPatch(buttonx + 7, buttony - 1, 0, W_CachePatchName("K_SPBATK", PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_RED, GTC_MENUCACHE)); } } - } else opty = 80; diff --git a/src/menus/play-local-race-time-attack.c b/src/menus/play-local-race-time-attack.c index 3b5a3469e..c8395c26c 100644 --- a/src/menus/play-local-race-time-attack.c +++ b/src/menus/play-local-race-time-attack.c @@ -22,13 +22,21 @@ void M_TimeAttackTick(void) } } +boolean M_EncoreAttackTogglePermitted(void) +{ + if ((gametypes[levellist.newgametype]->rules & GTR_ENCORE) == 0) //levellist.newgametype != GT_RACE + return false; + + return M_SecretUnlocked(SECRET_SPBATTACK, true); +} + boolean M_TimeAttackInputs(INT32 ch) { const UINT8 pid = 0; const boolean buttonR = M_MenuButtonPressed(pid, MBT_R); (void) ch; - if (buttonR && levellist.newgametype == GT_RACE && M_SecretUnlocked(SECRET_SPBATTACK, true)) + if (buttonR && M_EncoreAttackTogglePermitted()) { CV_AddValue(&cv_dummyspbattack, 1); timeattackmenu.spbflicker = TICRATE/6; @@ -348,7 +356,7 @@ void CV_SPBAttackChanged(void) /*else if (PLAY_TimeAttackDef.lastOn == ta_ghosts) PLAY_TimeAttackDef.lastOn = ta_start;*/ - if ((active & 8) && levellist.newgametype == GT_RACE && M_SecretUnlocked(SECRET_SPBATTACK, true)) + if ((active & 8) && M_EncoreAttackTogglePermitted()) { PLAY_TAReplay[tareplay_header].status = IT_HEADER; PLAY_TAReplay[tareplay_header].text = cv_dummyspbattack.value ? "SPB Attack..." : "Time Attack..."; @@ -381,9 +389,19 @@ void M_PrepareTimeAttack(boolean menuupdate) } } - if (levellist.levelsearch.timeattack == false || levellist.newgametype != GT_RACE || !M_SecretUnlocked(SECRET_SPBATTACK, true)) + if (cv_dummyspbattack.value + && (levellist.levelsearch.timeattack == false || !M_EncoreAttackTogglePermitted())) + { CV_StealthSetValue(&cv_dummyspbattack, 0); + if (!menuupdate) + { + timeattackmenu.spbflicker = TICRATE/6; + S_StartSound(NULL, sfx_s3k92); + S_StopSoundByID(NULL, sfx_s3k9f); + } + } + // Menu options / Time-sticker medals CV_SPBAttackChanged(); } @@ -554,7 +572,10 @@ void M_StartTimeAttack(INT32 choice) if (cv_dummyspbattack.value) { - modeattacking |= ATTACKING_SPB; + if (levellist.newgametype == GT_RACE) + { + modeattacking |= ATTACKING_SPB; + } modeprefix = "spb-"; } @@ -598,7 +619,7 @@ void M_StartTimeAttack(INT32 choice) restoreMenu = &PLAY_TimeAttackDef; M_ClearMenus(true); - D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummygpencore.value == 1), 1, 1, false, false); + D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummyspbattack.value == 1), 1, 1, false, false); G_UpdateTimeStickerMedals(levellist.choosemap, true); } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index bd3ab8ef8..9e9e46998 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -7791,7 +7791,7 @@ static void P_LoadRecordGhosts(void) gpath = Z_StrDup(va("%s" PATHSEP "media" PATHSEP "replay" PATHSEP "%s" PATHSEP "%s", srb2home, timeattackfolder, G_BuildMapName(gamemap))); - if (modeattacking & ATTACKING_SPB) + if (encoremode) modeprefix = "spb-"; enum @@ -8294,7 +8294,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) wipegamestate = gamestate; // Don't fade if reloading the gamestate // Encore mode fade to pink to white // This is handled BEFORE sounds are stopped. - else if (encoremode && !prevencoremode && !demo.rewinding) + else if (encoremode && !prevencoremode && modeattacking == ATTACKING_NONE && !demo.rewinding) { if (rendermode != render_none) { From 80334175513c0c6582c13ed92ab325e8d842df68 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 17 Feb 2024 23:12:31 +0000 Subject: [PATCH 8/8] Y_CalculateMatchData: Only use player tally if data is valid --- src/y_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index 62c08ee29..38b0591fd 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -207,7 +207,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) i = data.num[data.numplayers]; completed[i] = true; - data.grade[i] = players[i].tally.rank; + data.grade[i] = K_PlayerTallyActive(&players[i]) ? players[i].tally.rank : GRADE_INVALID; data.color[data.numplayers] = players[i].skincolor; data.character[data.numplayers] = players[i].skin;