Merge branch 'separate-spb-attack-records' into 'master'

Separate/Encoreize SPB Attack records from normal Time Attack records

Closes #836

See merge request KartKrew/Kart!1875
This commit is contained in:
Oni 2024-02-23 06:44:38 +00:00
commit 9491c54e9d
10 changed files with 236 additions and 150 deletions

View file

@ -149,11 +149,17 @@ 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
recordtimes_t spbattack; ///< Best times for SPB Attack
};
#define KARTSPEED_AUTO -1

View file

@ -388,10 +388,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
@ -429,7 +429,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;
}
@ -437,7 +437,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)
@ -538,21 +538,24 @@ void G_TickTimeStickerMedals(void)
void G_UpdateRecords(void)
{
UINT8 earnedEmblems;
recordtimes_t *record = (encoremode == true) ?
&mapheaderinfo[gamemap-1]->records.spbattack :
&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
@ -581,6 +584,12 @@ static void G_UpdateRecordReplays(void)
{
char *gpath;
char lastdemo[256], bestdemo[256];
const char *modeprefix = "";
if (encoremode)
{
modeprefix = "spb-";
}
if (players[consoleplayer].pflags & PF_NOCONTEST)
{
@ -600,7 +609,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))
{
@ -613,7 +622,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))
@ -625,7 +634,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))

View file

@ -121,10 +121,10 @@ void srb2::save_ng_gamedata()
map.visited.encore = mapheaderinfo[i]->records.mapvisited & MV_ENCORE;
map.visited.spbattack = mapheaderinfo[i]->records.mapvisited & MV_SPBATTACK;
map.visited.mysticmelody = mapheaderinfo[i]->records.mapvisited & MV_MYSTICMELODY;
map.stats.timeattack.besttime = mapheaderinfo[i]->records.time;
map.stats.timeattack.bestlap = mapheaderinfo[i]->records.lap;
map.stats.spbattack.besttime = 0;
map.stats.spbattack.bestlap = 0;
map.stats.timeattack.besttime = mapheaderinfo[i]->records.timeattack.time;
map.stats.timeattack.bestlap = mapheaderinfo[i]->records.timeattack.lap;
map.stats.spbattack.besttime = mapheaderinfo[i]->records.spbattack.time;
map.stats.spbattack.bestlap = mapheaderinfo[i]->records.spbattack.lap;
ng.maps[lumpname] = std::move(map);
}
for (auto unloadedmap = unloadedmapheaders; unloadedmap; unloadedmap = unloadedmap->next)
@ -136,10 +136,10 @@ void srb2::save_ng_gamedata()
map.visited.encore = unloadedmap->records.mapvisited & MV_ENCORE;
map.visited.spbattack = unloadedmap->records.mapvisited & MV_SPBATTACK;
map.visited.mysticmelody = unloadedmap->records.mapvisited & MV_MYSTICMELODY;
map.stats.timeattack.besttime = unloadedmap->records.time;
map.stats.timeattack.bestlap = unloadedmap->records.lap;
map.stats.spbattack.besttime = 0;
map.stats.spbattack.bestlap = 0;
map.stats.timeattack.besttime = unloadedmap->records.timeattack.time;
map.stats.timeattack.bestlap = unloadedmap->records.timeattack.lap;
map.stats.spbattack.besttime = unloadedmap->records.spbattack.time;
map.stats.spbattack.bestlap = unloadedmap->records.spbattack.lap;
ng.maps[lumpname] = std::move(map);
}
for (int i = 0; i < gamedata->numspraycans; i++)
@ -536,8 +536,10 @@ void srb2::load_ng_gamedata()
dummyrecord.mapvisited |= mappair.second.visited.encore ? MV_ENCORE : 0;
dummyrecord.mapvisited |= mappair.second.visited.spbattack ? MV_SPBATTACK : 0;
dummyrecord.mapvisited |= mappair.second.visited.mysticmelody ? MV_SPBATTACK : 0;
dummyrecord.time = mappair.second.stats.timeattack.besttime;
dummyrecord.lap = mappair.second.stats.timeattack.bestlap;
dummyrecord.timeattack.time = mappair.second.stats.timeattack.besttime;
dummyrecord.timeattack.lap = mappair.second.stats.timeattack.bestlap;
dummyrecord.spbattack.time = mappair.second.stats.spbattack.besttime;
dummyrecord.spbattack.lap = mappair.second.stats.spbattack.bestlap;
if (mapnum < nummapheaders && mapheaderinfo[mapnum])
{
@ -545,7 +547,9 @@ void srb2::load_ng_gamedata()
mapheaderinfo[mapnum]->records = dummyrecord;
}
else if (dummyrecord.mapvisited & MV_BEATEN || dummyrecord.time != 0 || dummyrecord.lap != 0)
else if (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.
// Instead, update a FILO linked list of "unloaded mapheaders".

View file

@ -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

View file

@ -3508,8 +3508,10 @@ void M_DrawTimeAttack(void)
if (currentMenu == &PLAY_TimeAttackDef)
{
tic_t timerec = mapheaderinfo[map]->records.time;
tic_t laprec = mapheaderinfo[map]->records.lap;
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;
if ((gametypes[levellist.newgametype]->rules & GTR_CIRCUIT)
@ -3528,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;
@ -7546,13 +7549,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,
@ -7632,7 +7635,7 @@ static void M_DrawStatsMaps(void)
)
)
{
besttime = mapheaderinfo[mnum]->records.time;
besttime = mapheaderinfo[mnum]->records.timeattack.time;
if (besttime)
{

View file

@ -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;

View file

@ -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)
@ -28,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;
@ -122,10 +124,11 @@ menu_t PLAY_TimeAttackDef = {
typedef enum
{
tareplay_besttime = 0,
tareplay_header = 0,
tareplay_besttime,
tareplay_bestlap,
tareplay_gap1,
tareplay_last,
tareplay_gap1,
tareplay_guest,
tareplay_staff,
tareplay_gap2,
@ -134,10 +137,11 @@ 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_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},
@ -250,7 +254,122 @@ menu_t PLAY_TAGhostsDef = {
NULL
};
// time attack stuff...
void CV_SPBAttackChanged(void);
void CV_SPBAttackChanged(void)
{
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;
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;
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|8);
}
else if (PLAY_TAReplayGuestDef.lastOn == taguest_besttime)
PLAY_TAReplayGuestDef.lastOn = taguest_back;
PLAY_TAReplay[tareplay_bestlap].status =
PLAY_TAReplayGuest[taguest_bestlap].status =
PLAY_TAGhosts[taghost_bestlap].status = IT_DISABLED;
if ((gametypes[levellist.newgametype]->rules & GTR_CIRCUIT)
&& (mapheaderinfo[levellist.choosemap]->numlaps != 1)
&& 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|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-%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|8);
}
else if (PLAY_TAReplayGuestDef.lastOn == taguest_last)
PLAY_TAReplayGuestDef.lastOn = taguest_back;
PLAY_TAReplay[tareplay_guest].status =
PLAY_TAGhosts[taghost_guest].status =
PLAY_TAReplayGuest[taguest_delete].status = IT_DISABLED;
if (FIL_FileExists(va("%s-%sguest.lmp", gpath, modeprefix)))
{
PLAY_TAReplay[tareplay_guest].status = IT_STRING|IT_CALL;
PLAY_TAReplayGuest[taguest_delete].status = IT_STRING|IT_CALL;
PLAY_TAGhosts[taghost_guest].status = IT_STRING|IT_CVAR;
active |= (1|2|4);
}
else if (PLAY_TAReplayGuestDef.lastOn == taguest_delete)
PLAY_TAReplayGuestDef.lastOn = taguest_back;
PLAY_TAReplay[tareplay_staff].status =
PLAY_TAGhosts[taghost_staff].status = IT_DISABLED;
if (mapheaderinfo[levellist.choosemap]->ghostCount > 0 && !modeprefix[0])
{
PLAY_TAReplay[tareplay_staff].status = IT_STRING|IT_ARROWS;
PLAY_TAGhosts[taghost_staff].status = IT_STRING|IT_CVAR;
CV_SetValue(&cv_dummystaff, 0);
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)
PLAY_TimeAttackDef.lastOn = ta_start;
if (active & 2)
PLAY_TimeAttack[ta_guest].status = IT_STRING|IT_SUBMENU;
else if (PLAY_TimeAttackDef.lastOn == ta_guest)
PLAY_TimeAttackDef.lastOn = ta_start;
//if (active & 4) -- for possible future use
PLAY_TimeAttack[ta_ghosts].status = IT_STRING|IT_SUBMENU;
/*else if (PLAY_TimeAttackDef.lastOn == ta_ghosts)
PLAY_TimeAttackDef.lastOn = ta_start;*/
if ((active & 8) && M_EncoreAttackTogglePermitted())
{
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;
Z_Free(gpath);
}
}
/// time attack stuff...
void M_PrepareTimeAttack(boolean menuupdate)
{
if (menuupdate)
@ -270,102 +389,21 @@ void M_PrepareTimeAttack(boolean menuupdate)
}
}
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
if (cv_dummyspbattack.value
&& (levellist.levelsearch.timeattack == false || !M_EncoreAttackTogglePermitted()))
{
// 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)));
UINT8 active;
CV_StealthSetValue(&cv_dummyspbattack, 0);
if (!gpath)
return;
active = false;
PLAY_TimeAttack[ta_guest].status = IT_DISABLED;
PLAY_TimeAttack[ta_replay].status = IT_DISABLED;
PLAY_TimeAttack[ta_ghosts].status = IT_DISABLED;
// 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 (!menuupdate)
{
PLAY_TAReplay[tareplay_besttime].status = IT_STRING|IT_CALL;
PLAY_TAReplayGuest[taguest_besttime].status = IT_STRING|IT_CALL;
active |= (1|2|4);
timeattackmenu.spbflicker = TICRATE/6;
S_StartSound(NULL, sfx_s3k92);
S_StopSoundByID(NULL, sfx_s3k9f);
}
else if (PLAY_TAReplayGuestDef.lastOn == taguest_besttime)
PLAY_TAReplayGuestDef.lastOn = taguest_back;
PLAY_TAReplay[tareplay_bestlap].status =
PLAY_TAReplayGuest[taguest_bestlap].status =
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)))
{
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);
}
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)))
{
PLAY_TAReplay[tareplay_last].status = IT_STRING|IT_CALL;
PLAY_TAReplayGuest[taguest_last].status = IT_STRING|IT_CALL;
active |= (1|2|4);
}
else if (PLAY_TAReplayGuestDef.lastOn == taguest_last)
PLAY_TAReplayGuestDef.lastOn = taguest_back;
PLAY_TAReplay[tareplay_guest].status =
PLAY_TAGhosts[taghost_guest].status =
PLAY_TAReplayGuest[taguest_delete].status = IT_DISABLED;
if (FIL_FileExists(va("%s-guest.lmp", gpath)))
{
PLAY_TAReplay[tareplay_guest].status = IT_STRING|IT_CALL;
PLAY_TAReplayGuest[taguest_delete].status = IT_STRING|IT_CALL;
PLAY_TAGhosts[taghost_guest].status = IT_STRING|IT_CVAR;
active |= (1|2|4);
}
else if (PLAY_TAReplayGuestDef.lastOn == taguest_delete)
PLAY_TAReplayGuestDef.lastOn = taguest_back;
PLAY_TAReplay[tareplay_staff].status =
PLAY_TAGhosts[taghost_staff].status = IT_DISABLED;
if (mapheaderinfo[levellist.choosemap]->ghostCount > 0)
{
PLAY_TAReplay[tareplay_staff].status = IT_STRING|IT_ARROWS;
PLAY_TAGhosts[taghost_staff].status = IT_STRING|IT_CVAR;
CV_SetValue(&cv_dummystaff, 0);
active |= 1|4;
}
if (active & 1)
PLAY_TimeAttack[ta_replay].status = IT_STRING|IT_SUBMENU;
else if (PLAY_TimeAttackDef.lastOn == ta_replay)
PLAY_TimeAttackDef.lastOn = ta_start;
if (active & 2)
PLAY_TimeAttack[ta_guest].status = IT_STRING|IT_SUBMENU;
else if (PLAY_TimeAttackDef.lastOn == ta_guest)
PLAY_TimeAttackDef.lastOn = ta_start;
//if (active & 4) -- for possible future use
PLAY_TimeAttack[ta_ghosts].status = IT_STRING|IT_SUBMENU;
/*else if (PLAY_TimeAttackDef.lastOn == ta_ghosts)
PLAY_TimeAttackDef.lastOn = ta_start;*/
Z_Free(gpath);
}
// Menu options / Time-sticker medals
CV_SPBAttackChanged();
}
void M_HandleStaffReplay(INT32 choice)
@ -403,6 +441,11 @@ void M_ReplayTimeAttack(INT32 choice)
demo.loadfiles = false;
demo.ignorefiles = true; // Just assume that record attack replays have the files needed
const char *modeprefix = "";
if (cv_dummyspbattack.value)
modeprefix = "spb-";
switch (choice)
{
default:
@ -416,11 +459,11 @@ void M_ReplayTimeAttack(INT32 choice)
which = "last";
break;
case tareplay_guest:
G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(levellist.choosemap+1)));
G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%sguest.lmp", srb2home, timeattackfolder, G_BuildMapName(levellist.choosemap+1), modeprefix));
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));
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;
@ -437,9 +480,14 @@ static void M_WriteGuestReplay(INT32 ch)
gpath = Z_StrDup(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(levellist.choosemap+1)));
const char *modeprefix = "";
if (cv_dummyspbattack.value)
modeprefix = "spb-";
if (TA_GuestReplay_Str != NULL)
{
len = FIL_ReadFile(va("%s-%s-%s.lmp", gpath, cv_skin[0].string, TA_GuestReplay_Str), &buf);
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);
@ -448,7 +496,7 @@ static void M_WriteGuestReplay(INT32 ch)
}
}
rguest = Z_StrDup(va("%s-guest.lmp", gpath));
rguest = Z_StrDup(va("%s-%sguest.lmp", gpath, modeprefix));
if (FIL_FileExists(rguest))
{
@ -491,7 +539,12 @@ void M_SetGuestReplay(INT32 choice)
break;
}
if (FIL_FileExists(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(levellist.choosemap+1))))
const char *modeprefix = "";
if (cv_dummyspbattack.value)
modeprefix = "spb-";
if (FIL_FileExists(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%sguest.lmp", srb2home, timeattackfolder, G_BuildMapName(levellist.choosemap+1), modeprefix)))
{
M_StartMessage("Guest Replay", va("Are you sure you want to\n%s the guest replay data?\n", (TA_GuestReplay_Str != NULL ? "overwrite" : "delete")), &M_WriteGuestReplay, MM_YESNO, NULL, NULL);
}
@ -505,6 +558,7 @@ void M_StartTimeAttack(INT32 choice)
{
char *gpath;
char nameofdemo[256];
const char *modeprefix = "";
(void)choice;
@ -518,7 +572,11 @@ void M_StartTimeAttack(INT32 choice)
if (cv_dummyspbattack.value)
{
modeattacking |= ATTACKING_SPB;
if (levellist.newgametype == GT_RACE)
{
modeattacking |= ATTACKING_SPB;
}
modeprefix = "spb-";
}
// Still need to reset devmode
@ -551,7 +609,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));
@ -561,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);
}

View file

@ -7786,10 +7786,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 (encoremode)
modeprefix = "spb-";
enum
{
kTime = 1 << 0,
@ -7832,7 +7836,7 @@ static void P_LoadRecordGhosts(void)
if (allGhosts)
{
for (i = 0; i < numskins; ++i)
add_ghosts(fmt::format("{}-{}", gpath, skins[i].name), allGhosts);
add_ghosts(fmt::format("{}-{}{}", gpath, skins[i].name, modeprefix), allGhosts);
}
if (sameGhosts)
@ -7840,15 +7844,15 @@ static void P_LoadRecordGhosts(void)
INT32 skin = R_SkinAvailable(cv_skin[0].string);
if (skin < 0 || !R_SkinUsable(consoleplayer, skin, false))
skin = 0; // use default skin
add_ghosts(fmt::format("{}-{}", gpath, skins[skin].name), sameGhosts);
add_ghosts(fmt::format("{}-{}{}", gpath, skins[skin].name, modeprefix), sameGhosts);
}
// Guest ghost
if (cv_ghost_guest.value)
P_TryAddExternalGhost(va("%s-guest.lmp", gpath));
P_TryAddExternalGhost(va("%s-%sguest.lmp", gpath, modeprefix));
// Staff Attack ghosts
if (cv_ghost_staff.value)
if (cv_ghost_staff.value && !modeprefix[0])
{
for (i = mapheaderinfo[gamemap-1]->ghostCount; i > 0; i--)
{
@ -8290,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)
{

View file

@ -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);

View file

@ -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;