mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
- 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
625 lines
16 KiB
C
625 lines
16 KiB
C
/// \file menus/play-local-race-time-attack.c
|
|
/// \brief Race Time Attack Menu
|
|
|
|
#include "../k_menu.h"
|
|
#include "../r_local.h" // SplitScreen_OnChange
|
|
#include "../s_sound.h"
|
|
#include "../f_finale.h" // F_WipeStartScreen
|
|
#include "../v_video.h"
|
|
#include "../d_main.h" // srb2home
|
|
#include "../m_misc.h" // M_MkdirEach
|
|
#include "../z_zone.h" // Z_StrDup/Z_Free
|
|
#include "../m_cond.h"
|
|
|
|
struct timeattackmenu_s timeattackmenu;
|
|
|
|
void M_TimeAttackTick(void)
|
|
{
|
|
timeattackmenu.ticker++;
|
|
if (timeattackmenu.spbflicker > 0)
|
|
{
|
|
timeattackmenu.spbflicker--;
|
|
}
|
|
}
|
|
|
|
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 && M_EncoreAttackTogglePermitted())
|
|
{
|
|
CV_AddValue(&cv_dummyspbattack, 1);
|
|
timeattackmenu.spbflicker = TICRATE/6;
|
|
if (cv_dummyspbattack.value)
|
|
{
|
|
S_StartSound(NULL, sfx_s3k9f);
|
|
S_StopSoundByID(NULL, sfx_s3k92);
|
|
}
|
|
else
|
|
{
|
|
S_StartSound(NULL, sfx_s3k92);
|
|
S_StopSoundByID(NULL, sfx_s3k9f);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
if (menucmd[pid].dpad_lr != 0
|
|
&& !((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|
|
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)
|
|
)
|
|
{
|
|
if (menucmd[pid].dpad_lr > 0)
|
|
{
|
|
levellist.cursor++;
|
|
if (levellist.cursor >= levellist.mapcount)
|
|
{
|
|
M_LevelSelectCupSwitch(true, false);
|
|
levellist.cursor = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
levellist.cursor--;
|
|
if (levellist.cursor < 0)
|
|
{
|
|
M_LevelSelectCupSwitch(false, false);
|
|
levellist.cursor = levellist.mapcount-1;
|
|
}
|
|
}
|
|
|
|
M_LevelSelectScrollDest();
|
|
levellist.slide.start = 0;
|
|
|
|
M_LevelSelected(levellist.cursor, false);
|
|
itemOn = ta_start;
|
|
|
|
S_StartSound(NULL, sfx_s3k5b);
|
|
M_SetMenuDelay(pid);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// see ta_e
|
|
menuitem_t PLAY_TimeAttack[] =
|
|
{
|
|
{IT_STRING | IT_SUBMENU, "Replay...", NULL, "MENUI006", {.submenu = &PLAY_TAReplayDef}, 0, 0},
|
|
{IT_STRING | IT_SUBMENU, "Guest...", NULL, "MENUI006", {.submenu = &PLAY_TAReplayGuestDef}, 0, 0},
|
|
{IT_STRING | IT_SUBMENU, "Ghosts...", NULL, "MENUI006", {.submenu = &PLAY_TAGhostsDef}, 0, 0},
|
|
{IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0},
|
|
{IT_STRING | IT_CALL, "Start", NULL, "MENUI006", {.routine = M_StartTimeAttack}, 0, 0},
|
|
};
|
|
|
|
menu_t PLAY_TimeAttackDef = {
|
|
sizeof(PLAY_TimeAttack) / sizeof(menuitem_t),
|
|
&PLAY_LevelSelectDef,
|
|
0,
|
|
PLAY_TimeAttack,
|
|
0, 0,
|
|
0, 0,
|
|
0,
|
|
NULL,
|
|
2, 5,
|
|
M_DrawTimeAttack,
|
|
NULL,
|
|
M_TimeAttackTick,
|
|
NULL,
|
|
NULL,
|
|
M_TimeAttackInputs
|
|
};
|
|
|
|
|
|
typedef enum
|
|
{
|
|
tareplay_header = 0,
|
|
tareplay_besttime,
|
|
tareplay_bestlap,
|
|
tareplay_last,
|
|
tareplay_gap1,
|
|
tareplay_guest,
|
|
tareplay_staff,
|
|
tareplay_gap2,
|
|
tareplay_back
|
|
} tareplay_e;
|
|
|
|
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},
|
|
{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},
|
|
|
|
{IT_STRING | IT_SUBMENU, "Back", NULL, "MENUI006", {.submenu = &PLAY_TimeAttackDef}, 0, 0},
|
|
};
|
|
|
|
menu_t PLAY_TAReplayDef = {
|
|
sizeof(PLAY_TAReplay) / sizeof(menuitem_t),
|
|
&PLAY_TimeAttackDef,
|
|
0,
|
|
PLAY_TAReplay,
|
|
0, 0,
|
|
0, 0,
|
|
0,
|
|
NULL,
|
|
2, 5,
|
|
M_DrawTimeAttack,
|
|
NULL,
|
|
M_TimeAttackTick,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
typedef enum
|
|
{
|
|
taguest_header = 0,
|
|
taguest_besttime,
|
|
taguest_bestlap,
|
|
taguest_last,
|
|
taguest_gap1,
|
|
taguest_delete,
|
|
taguest_gap2,
|
|
taguest_back
|
|
} taguest_e;
|
|
|
|
menuitem_t PLAY_TAReplayGuest[] =
|
|
{
|
|
{IT_HEADERTEXT|IT_HEADER, "Save as guest...", NULL, "MENUI006", {NULL}, 0, 0},
|
|
|
|
{IT_STRING | IT_CALL, "Best Time", NULL, "MENUI006", {.routine = M_SetGuestReplay}, 0, 0},
|
|
{IT_STRING | IT_CALL, "Best Lap", NULL, "MENUI006", {.routine = M_SetGuestReplay}, 0, 0},
|
|
{IT_STRING | IT_CALL, "Last Run", NULL, "MENUI006", {.routine = M_SetGuestReplay}, 0, 0},
|
|
|
|
{IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0},
|
|
{IT_STRING | IT_CALL, "Delete Guest", NULL, "MENUI006", {.routine = M_SetGuestReplay}, 0, 0},
|
|
|
|
{IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0},
|
|
{IT_STRING | IT_SUBMENU, "Back", NULL, "MENUI006", {.submenu = &PLAY_TimeAttackDef}, 0, 0},
|
|
|
|
};
|
|
|
|
menu_t PLAY_TAReplayGuestDef = {
|
|
sizeof(PLAY_TAReplayGuest) / sizeof(menuitem_t),
|
|
&PLAY_TimeAttackDef,
|
|
0,
|
|
PLAY_TAReplayGuest,
|
|
0, 0,
|
|
0, 0,
|
|
0,
|
|
NULL,
|
|
2, 5,
|
|
M_DrawTimeAttack,
|
|
NULL,
|
|
M_TimeAttackTick,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
typedef enum
|
|
{
|
|
taghost_besttime = 0,
|
|
taghost_bestlap,
|
|
taghost_last,
|
|
taghost_guest,
|
|
taghost_staff,
|
|
taghost_gap1,
|
|
taghost_back
|
|
} taghost_e;
|
|
|
|
menuitem_t PLAY_TAGhosts[] =
|
|
{
|
|
{IT_STRING | IT_CVAR, "Best Time", NULL, "MENUI006", {.cvar = &cv_ghost_besttime}, 0, 0},
|
|
{IT_STRING | IT_CVAR, "Best Lap", NULL, "MENUI006", {.cvar = &cv_ghost_bestlap}, 0, 0},
|
|
{IT_STRING | IT_CVAR, "Last", NULL, "MENUI006", {.cvar = &cv_ghost_last}, 0, 0},
|
|
{IT_DISABLED, "Guest", NULL, "MENUI006", {.cvar = &cv_ghost_guest}, 0, 0},
|
|
{IT_DISABLED, "Staff", NULL, "MENUI006", {.cvar = &cv_ghost_staff}, 0, 0},
|
|
|
|
{IT_HEADERTEXT|IT_HEADER, "", NULL, NULL, {NULL}, 0, 0},
|
|
{IT_STRING | IT_SUBMENU, "Back", NULL, "MENUI006", {.submenu = &PLAY_TimeAttackDef}, 0, 0},
|
|
};
|
|
|
|
menu_t PLAY_TAGhostsDef = {
|
|
sizeof(PLAY_TAGhosts) / sizeof(menuitem_t),
|
|
&PLAY_TimeAttackDef,
|
|
0,
|
|
PLAY_TAGhosts,
|
|
0, 0,
|
|
0, 0,
|
|
0,
|
|
NULL,
|
|
2, 5,
|
|
M_DrawTimeAttack,
|
|
NULL,
|
|
M_TimeAttackTick,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
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)
|
|
{
|
|
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 (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();
|
|
}
|
|
|
|
void M_HandleStaffReplay(INT32 choice)
|
|
{
|
|
if (choice == 2)
|
|
{
|
|
mapheader_t *mapheader;
|
|
staffbrief_t *staffbrief;
|
|
const char* lumpname = NULL;
|
|
restoreMenu = &PLAY_TimeAttackDef;
|
|
|
|
M_ClearMenus(true);
|
|
demo.loadfiles = false;
|
|
demo.ignorefiles = true; // Just assume that record attack replays have the files needed
|
|
|
|
mapheader = mapheaderinfo[levellist.choosemap];
|
|
staffbrief = mapheader->ghostBrief[cv_dummystaff.value];
|
|
|
|
lumpname = W_CheckNameForNumPwad(staffbrief->wad, staffbrief->lump);
|
|
|
|
G_DoPlayDemo(lumpname);
|
|
return;
|
|
}
|
|
|
|
M_ChangeCvarDirect(choice, &cv_dummystaff);
|
|
}
|
|
|
|
void M_ReplayTimeAttack(INT32 choice)
|
|
{
|
|
const char *which;
|
|
|
|
restoreMenu = &PLAY_TimeAttackDef;
|
|
|
|
M_ClearMenus(true);
|
|
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:
|
|
case tareplay_besttime:
|
|
which = "time-best";
|
|
break;
|
|
case tareplay_bestlap:
|
|
which = "lap-best";
|
|
break;
|
|
case tareplay_last:
|
|
which = "last";
|
|
break;
|
|
case tareplay_guest:
|
|
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%s.lmp", srb2home, timeattackfolder, G_BuildMapName(levellist.choosemap+1), cv_skin[0].string, modeprefix, which));
|
|
}
|
|
|
|
static const char *TA_GuestReplay_Str = NULL;
|
|
|
|
static void M_WriteGuestReplay(INT32 ch)
|
|
{
|
|
char *gpath, *rguest;
|
|
|
|
UINT8 *buf;
|
|
size_t len = 0;
|
|
|
|
if (ch != MA_YES)
|
|
return;
|
|
|
|
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%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);
|
|
Z_Free(gpath);
|
|
return;
|
|
}
|
|
}
|
|
|
|
rguest = Z_StrDup(va("%s-%sguest.lmp", gpath, modeprefix));
|
|
|
|
if (FIL_FileExists(rguest))
|
|
{
|
|
remove(rguest);
|
|
}
|
|
|
|
if (len)
|
|
{
|
|
FIL_WriteFile(rguest, buf, len);
|
|
}
|
|
|
|
Z_Free(rguest);
|
|
Z_Free(gpath);
|
|
|
|
M_PrepareTimeAttack(false);
|
|
M_SetupNextMenu(&PLAY_TimeAttackDef, false);
|
|
|
|
// TODO the following isn't showing up and I'm not sure why
|
|
//M_StartMessage("Guest Replay", va("Guest replay data %s.", (len ? "saved" : "erased")), NULL, MM_NOTHING, NULL, NULL);
|
|
}
|
|
|
|
|
|
void M_SetGuestReplay(INT32 choice)
|
|
{
|
|
switch (choice)
|
|
{
|
|
case taguest_besttime:
|
|
TA_GuestReplay_Str = "time-best";
|
|
break;
|
|
case taguest_bestlap:
|
|
TA_GuestReplay_Str = "lap-best";
|
|
break;
|
|
case taguest_last:
|
|
TA_GuestReplay_Str = "last";
|
|
break;
|
|
|
|
case taguest_delete:
|
|
default:
|
|
TA_GuestReplay_Str = NULL;
|
|
break;
|
|
}
|
|
|
|
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);
|
|
}
|
|
else if (TA_GuestReplay_Str != NULL)
|
|
{
|
|
M_WriteGuestReplay(MA_YES);
|
|
}
|
|
}
|
|
|
|
void M_StartTimeAttack(INT32 choice)
|
|
{
|
|
char *gpath;
|
|
char nameofdemo[256];
|
|
const char *modeprefix = "";
|
|
|
|
(void)choice;
|
|
|
|
modeattacking = ATTACKING_TIME;
|
|
|
|
if ((gametypes[levellist.newgametype]->rules & GTR_CIRCUIT)
|
|
&& (mapheaderinfo[levellist.choosemap]->numlaps != 1))
|
|
{
|
|
modeattacking |= ATTACKING_LAP;
|
|
}
|
|
|
|
if (cv_dummyspbattack.value)
|
|
{
|
|
if (levellist.newgametype == GT_RACE)
|
|
{
|
|
modeattacking |= ATTACKING_SPB;
|
|
}
|
|
modeprefix = "spb-";
|
|
}
|
|
|
|
// Still need to reset devmode
|
|
cht_debug = 0;
|
|
|
|
if (demo.playback)
|
|
G_StopDemo();
|
|
|
|
splitscreen = 0;
|
|
SplitScreen_OnChange();
|
|
|
|
S_StartSound(NULL, sfx_s3k63);
|
|
|
|
paused = false;
|
|
|
|
S_StopMusicCredit();
|
|
|
|
// Early fadeout to let the sound finish playing
|
|
F_WipeStartScreen();
|
|
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
|
F_WipeEndScreen();
|
|
F_RunWipe(wipe_level_toblack, wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false);
|
|
|
|
SV_StartSinglePlayerServer(levellist.newgametype, false);
|
|
|
|
gpath = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s",
|
|
srb2home, timeattackfolder);
|
|
M_MkdirEach(gpath, M_PathParts(gpath) - 3, 0755);
|
|
|
|
strcat(gpath, PATHSEP);
|
|
strcat(gpath, G_BuildMapName(levellist.choosemap+1));
|
|
|
|
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));
|
|
else
|
|
G_RecordDemo(nameofdemo);
|
|
|
|
restoreMenu = &PLAY_TimeAttackDef;
|
|
|
|
M_ClearMenus(true);
|
|
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummyspbattack.value == 1), 1, 1, false, false);
|
|
|
|
G_UpdateTimeStickerMedals(levellist.choosemap, true);
|
|
}
|