mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-15 01:01:33 +00:00
Allow Record Attack in modified games
Replays now store & validate the add-on list before loading them. Custom characters can now be allowed in Record Attack.
This commit is contained in:
parent
1a2f66acd9
commit
77576c3c5d
5 changed files with 487 additions and 35 deletions
|
@ -1643,9 +1643,14 @@ static void Command_Playdemo_f(void)
|
|||
{
|
||||
char name[256];
|
||||
|
||||
if (COM_Argc() != 2)
|
||||
if (COM_Argc() < 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("playdemo <demoname>: playback a demo\n"));
|
||||
CONS_Printf("playdemo <demoname> [-addfiles / -force]:\n");
|
||||
CONS_Printf(M_GetText(
|
||||
"Play back a demo file. The full path from your SRB2 directory must be given.\n\n"
|
||||
|
||||
"* With \"-addfiles\", any required files are added from a list contained within the demo file.\n"
|
||||
"* With \"-force\", the demo is played even if the necessary files have not been added.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1667,6 +1672,16 @@ static void Command_Playdemo_f(void)
|
|||
|
||||
CONS_Printf(M_GetText("Playing back demo '%s'.\n"), name);
|
||||
|
||||
demofileoverride = DFILE_OVERRIDE_NONE;
|
||||
if (strcmp(COM_Argv(2), "-addfiles") == 0)
|
||||
{
|
||||
demofileoverride = DFILE_OVERRIDE_LOAD;
|
||||
}
|
||||
else if (strcmp(COM_Argv(2), "-force") == 0)
|
||||
{
|
||||
demofileoverride = DFILE_OVERRIDE_SKIP;
|
||||
}
|
||||
|
||||
// Internal if no extension, external if one exists
|
||||
// If external, convert the file name to a path in SRB2's home directory
|
||||
if (FIL_CheckExtension(name))
|
||||
|
|
|
@ -3509,6 +3509,7 @@ void F_TitleScreenTicker(boolean run)
|
|||
}
|
||||
|
||||
titledemo = true;
|
||||
demofileoverride = DFILE_OVERRIDE_NONE;
|
||||
G_DoPlayDemo(dname);
|
||||
}
|
||||
}
|
||||
|
|
387
src/g_demo.c
387
src/g_demo.c
|
@ -39,6 +39,7 @@
|
|||
#include "v_video.h"
|
||||
#include "lua_hook.h"
|
||||
#include "md5.h" // demo checksums
|
||||
#include "d_netfil.h" // G_CheckDemoExtraFiles
|
||||
|
||||
boolean timingdemo; // if true, exit with report on completion
|
||||
boolean nodrawers; // for comparative timing purposes
|
||||
|
@ -49,6 +50,7 @@ static char demoname[64];
|
|||
boolean demorecording;
|
||||
boolean demoplayback;
|
||||
boolean titledemo; // Title Screen demo can be cancelled by any key
|
||||
demo_file_override_e demofileoverride;
|
||||
static UINT8 *demobuffer = NULL;
|
||||
static UINT8 *demo_p, *demotime_p;
|
||||
static UINT8 *demoend;
|
||||
|
@ -95,7 +97,7 @@ demoghost *ghosts = NULL;
|
|||
// DEMO RECORDING
|
||||
//
|
||||
|
||||
#define DEMOVERSION 0x000f
|
||||
#define DEMOVERSION 0x0010
|
||||
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
|
||||
|
||||
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
||||
|
@ -1413,6 +1415,10 @@ void G_BeginRecording(void)
|
|||
char name[MAXCOLORNAME+1];
|
||||
player_t *player = &players[consoleplayer];
|
||||
|
||||
char *filename;
|
||||
UINT8 totalfiles;
|
||||
UINT8 *m;
|
||||
|
||||
if (demo_p)
|
||||
return;
|
||||
memset(name,0,sizeof(name));
|
||||
|
@ -1435,23 +1441,43 @@ void G_BeginRecording(void)
|
|||
M_Memcpy(demo_p, mapmd5, 16); demo_p += 16;
|
||||
|
||||
WRITEUINT8(demo_p,demoflags);
|
||||
|
||||
// file list
|
||||
m = demo_p;/* file count */
|
||||
demo_p += 1;
|
||||
|
||||
totalfiles = 0;
|
||||
for (i = mainwads; ++i < numwadfiles; )
|
||||
{
|
||||
if (wadfiles[i]->important)
|
||||
{
|
||||
nameonly(( filename = va("%s", wadfiles[i]->filename) ));
|
||||
WRITESTRINGL(demo_p, filename, MAX_WADPATH);
|
||||
WRITEMEM(demo_p, wadfiles[i]->md5sum, 16);
|
||||
|
||||
totalfiles++;
|
||||
}
|
||||
}
|
||||
|
||||
WRITEUINT8(m, totalfiles);
|
||||
|
||||
switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
|
||||
{
|
||||
case ATTACKING_NONE: // 0
|
||||
break;
|
||||
case ATTACKING_RECORD: // 1
|
||||
demotime_p = demo_p;
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // time
|
||||
WRITEUINT32(demo_p,0); // score
|
||||
WRITEUINT16(demo_p,0); // rings
|
||||
break;
|
||||
case ATTACKING_NIGHTS: // 2
|
||||
demotime_p = demo_p;
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // time
|
||||
WRITEUINT32(demo_p,0); // score
|
||||
break;
|
||||
default: // 3
|
||||
break;
|
||||
case ATTACKING_NONE: // 0
|
||||
break;
|
||||
case ATTACKING_RECORD: // 1
|
||||
demotime_p = demo_p;
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // time
|
||||
WRITEUINT32(demo_p,0); // score
|
||||
WRITEUINT16(demo_p,0); // rings
|
||||
break;
|
||||
case ATTACKING_NIGHTS: // 2
|
||||
demotime_p = demo_p;
|
||||
WRITEUINT32(demo_p,UINT32_MAX); // time
|
||||
WRITEUINT32(demo_p,0); // score
|
||||
break;
|
||||
default: // 3
|
||||
break;
|
||||
}
|
||||
|
||||
WRITEUINT32(demo_p,P_GetInitSeed());
|
||||
|
@ -1590,6 +1616,177 @@ void G_BeginMetal(void)
|
|||
oldmetal.angle = mo->angle>>24;
|
||||
}
|
||||
|
||||
static void G_LoadDemoExtraFiles(UINT8 **pp)
|
||||
{
|
||||
UINT8 totalfiles;
|
||||
char filename[MAX_WADPATH];
|
||||
UINT8 md5sum[16];
|
||||
filestatus_t ncs;
|
||||
boolean toomany = false;
|
||||
boolean alreadyloaded;
|
||||
UINT8 i, j;
|
||||
|
||||
totalfiles = READUINT8((*pp));
|
||||
for (i = 0; i < totalfiles; ++i)
|
||||
{
|
||||
if (toomany)
|
||||
SKIPSTRING((*pp));
|
||||
else
|
||||
{
|
||||
strlcpy(filename, (char *)(*pp), sizeof filename);
|
||||
SKIPSTRING((*pp));
|
||||
}
|
||||
READMEM((*pp), md5sum, 16);
|
||||
|
||||
if (!toomany)
|
||||
{
|
||||
alreadyloaded = false;
|
||||
|
||||
for (j = 0; j < numwadfiles; ++j)
|
||||
{
|
||||
if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0)
|
||||
{
|
||||
alreadyloaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (alreadyloaded)
|
||||
continue;
|
||||
|
||||
if (numwadfiles >= MAX_WADFILES)
|
||||
toomany = true;
|
||||
else
|
||||
ncs = findfile(filename, md5sum, false);
|
||||
|
||||
if (toomany)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Too many files loaded to add anymore for demo playback\n"));
|
||||
if (!CON_Ready())
|
||||
M_StartMessage(M_GetText("There are too many files loaded to add this demo's addons.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
}
|
||||
else if (ncs != FS_FOUND)
|
||||
{
|
||||
if (ncs == FS_NOTFOUND)
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You do not have a copy of %s\n"), filename);
|
||||
else if (ncs == FS_MD5SUMBAD)
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Checksum mismatch on %s\n"), filename);
|
||||
else
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Unknown error finding file %s\n"), filename);
|
||||
|
||||
if (!CON_Ready())
|
||||
M_StartMessage(M_GetText("There were errors trying to add this demo's addons. Check the console for more information.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_AddWadFile(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void G_SkipDemoExtraFiles(UINT8 **pp)
|
||||
{
|
||||
UINT8 totalfiles;
|
||||
UINT8 i;
|
||||
|
||||
if (demoversion < 0x0010)
|
||||
{
|
||||
// demo has no file list
|
||||
return;
|
||||
}
|
||||
|
||||
totalfiles = READUINT8((*pp));
|
||||
for (i = 0; i < totalfiles; ++i)
|
||||
{
|
||||
SKIPSTRING((*pp));// file name
|
||||
(*pp) += 16;// md5
|
||||
}
|
||||
}
|
||||
|
||||
// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's.
|
||||
// Enabling quick prevents filesystem checks to see if needed files are available to load.
|
||||
static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick)
|
||||
{
|
||||
UINT8 totalfiles, filesloaded, nmusfilecount;
|
||||
char filename[MAX_WADPATH];
|
||||
UINT8 md5sum[16];
|
||||
boolean toomany = false;
|
||||
boolean alreadyloaded;
|
||||
UINT8 i, j;
|
||||
UINT8 error = DFILE_ERROR_NONE;
|
||||
|
||||
if (demoversion < 0x0010)
|
||||
{
|
||||
// demo has no file list
|
||||
return DFILE_ERROR_NONE;
|
||||
}
|
||||
|
||||
totalfiles = READUINT8((*pp));
|
||||
filesloaded = 0;
|
||||
for (i = 0; i < totalfiles; ++i)
|
||||
{
|
||||
if (toomany)
|
||||
SKIPSTRING((*pp));
|
||||
else
|
||||
{
|
||||
strlcpy(filename, (char *)(*pp), sizeof filename);
|
||||
SKIPSTRING((*pp));
|
||||
}
|
||||
READMEM((*pp), md5sum, 16);
|
||||
|
||||
if (!toomany)
|
||||
{
|
||||
alreadyloaded = false;
|
||||
nmusfilecount = 0;
|
||||
|
||||
for (j = 0; j < numwadfiles; ++j)
|
||||
{
|
||||
if (wadfiles[j]->important && j > mainwads)
|
||||
nmusfilecount++;
|
||||
else
|
||||
continue;
|
||||
|
||||
if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0)
|
||||
{
|
||||
alreadyloaded = true;
|
||||
|
||||
if (i != nmusfilecount-1 && error < DFILE_ERROR_OUTOFORDER)
|
||||
error |= DFILE_ERROR_OUTOFORDER;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (alreadyloaded)
|
||||
{
|
||||
filesloaded++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (numwadfiles >= MAX_WADFILES)
|
||||
error = DFILE_ERROR_CANNOTLOAD;
|
||||
else if (!quick && findfile(filename, md5sum, false) != FS_FOUND)
|
||||
error = DFILE_ERROR_CANNOTLOAD;
|
||||
else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER)
|
||||
error |= DFILE_ERROR_NOTLOADED;
|
||||
} else
|
||||
error = DFILE_ERROR_CANNOTLOAD;
|
||||
}
|
||||
|
||||
// Get final file count
|
||||
nmusfilecount = 0;
|
||||
|
||||
for (j = 0; j < numwadfiles; ++j)
|
||||
if (wadfiles[j]->important && j > mainwads)
|
||||
nmusfilecount++;
|
||||
|
||||
if (!error && filesloaded < nmusfilecount)
|
||||
error = DFILE_ERROR_EXTRAFILES;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void G_SetDemoTime(UINT32 ptime, UINT32 pscore, UINT16 prings)
|
||||
{
|
||||
if (!demorecording || !demotime_p)
|
||||
|
@ -1645,7 +1842,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
p += 2; // gamemap
|
||||
p += 16; // map md5
|
||||
flags = READUINT8(p); // demoflags
|
||||
|
||||
G_SkipDemoExtraFiles(&p);
|
||||
aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK);
|
||||
I_Assert(aflags);
|
||||
if (flags & DF_RECORDATTACK)
|
||||
|
@ -1710,6 +1907,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
p += 2; // gamemap
|
||||
p += 16; // mapmd5
|
||||
flags = READUINT8(p);
|
||||
G_SkipDemoExtraFiles(&p);
|
||||
if (!(flags & aflags))
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname);
|
||||
|
@ -1871,6 +2069,73 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
demo_p += 16; // mapmd5
|
||||
|
||||
demoflags = READUINT8(demo_p);
|
||||
|
||||
if (demoversion < 0x0010)
|
||||
{
|
||||
; // Don't do anything with files.
|
||||
}
|
||||
else if (titledemo)
|
||||
{
|
||||
// Titledemos should always play and ought to always be compatible with whatever wadlist is running.
|
||||
G_SkipDemoExtraFiles(&demo_p);
|
||||
}
|
||||
else if (demofileoverride == DFILE_OVERRIDE_LOAD)
|
||||
{
|
||||
G_LoadDemoExtraFiles(&demo_p);
|
||||
}
|
||||
else if (demofileoverride == DFILE_OVERRIDE_SKIP)
|
||||
{
|
||||
G_SkipDemoExtraFiles(&demo_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT8 error = G_CheckDemoExtraFiles(&demo_p, false);
|
||||
|
||||
if (error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case DFILE_ERROR_NOTLOADED:
|
||||
snprintf(msg, 1024,
|
||||
M_GetText("Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n"),
|
||||
pdemoname);
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_OUTOFORDER:
|
||||
snprintf(msg, 1024,
|
||||
M_GetText("Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"),
|
||||
pdemoname);
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_INCOMPLETEOUTOFORDER:
|
||||
snprintf(msg, 1024,
|
||||
M_GetText("Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n"),
|
||||
pdemoname);
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_CANNOTLOAD:
|
||||
snprintf(msg, 1024,
|
||||
M_GetText("Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"),
|
||||
pdemoname);
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_EXTRAFILES:
|
||||
snprintf(msg, 1024,
|
||||
M_GetText("You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"),
|
||||
pdemoname);
|
||||
break;
|
||||
}
|
||||
|
||||
CONS_Alert(CONS_ERROR, "%s", msg);
|
||||
M_StartMessage(msg, NULL, MM_NOTHING);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(demobuffer);
|
||||
demoplayback = false;
|
||||
titledemo = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT;
|
||||
CON_ToggleOff();
|
||||
|
||||
|
@ -2026,6 +2291,91 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
demo_start = true;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if a replay can be loaded from the menu
|
||||
//
|
||||
UINT8 G_CheckDemoForError(char *defdemoname)
|
||||
{
|
||||
lumpnum_t l;
|
||||
char *n,*pdemoname;
|
||||
|
||||
n = defdemoname+strlen(defdemoname);
|
||||
while (*n != '/' && *n != '\\' && n != defdemoname)
|
||||
n--;
|
||||
if (n != defdemoname)
|
||||
n++;
|
||||
pdemoname = ZZ_Alloc(strlen(n)+1);
|
||||
strcpy(pdemoname,n);
|
||||
|
||||
// Internal if no extension, external if one exists
|
||||
if (FIL_CheckExtension(defdemoname))
|
||||
{
|
||||
//FIL_DefaultExtension(defdemoname, ".lmp");
|
||||
if (!FIL_ReadFile(defdemoname, &demobuffer))
|
||||
{
|
||||
return DFILE_ERROR_NOTDEMO;
|
||||
}
|
||||
demo_p = demobuffer;
|
||||
}
|
||||
// load demo resource from WAD
|
||||
else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
|
||||
{
|
||||
return DFILE_ERROR_NOTDEMO;
|
||||
}
|
||||
else // it's an internal demo
|
||||
{
|
||||
demobuffer = demo_p = W_CacheLumpNum(l, PU_STATIC);
|
||||
}
|
||||
|
||||
// read demo header
|
||||
if (memcmp(demo_p, DEMOHEADER, 12))
|
||||
{
|
||||
return DFILE_ERROR_NOTDEMO;
|
||||
}
|
||||
demo_p += 12; // DEMOHEADER
|
||||
|
||||
demo_p++; // version
|
||||
demo_p++; // subversion
|
||||
demoversion = READUINT16(demo_p);
|
||||
switch(demoversion)
|
||||
{
|
||||
case 0x000d:
|
||||
case 0x000e:
|
||||
case 0x000f:
|
||||
case DEMOVERSION: // latest always supported
|
||||
break;
|
||||
#ifdef OLD22DEMOCOMPAT
|
||||
case 0x000c:
|
||||
break;
|
||||
#endif
|
||||
// too old, cannot support.
|
||||
default:
|
||||
return DFILE_ERROR_NOTDEMO;
|
||||
}
|
||||
demo_p += 16; // demo checksum
|
||||
if (memcmp(demo_p, "PLAY", 4))
|
||||
{
|
||||
return DFILE_ERROR_NOTDEMO;
|
||||
}
|
||||
demo_p += 4; // "PLAY"
|
||||
demo_p += 2; // gamemap
|
||||
demo_p += 16; // mapmd5
|
||||
|
||||
demo_p++; // demoflags
|
||||
|
||||
// Don't do anything with files.
|
||||
if (demoversion < 0x0010)
|
||||
{
|
||||
return DFILE_ERROR_NONE;
|
||||
}
|
||||
else if (titledemo)
|
||||
{
|
||||
return DFILE_ERROR_NONE;
|
||||
}
|
||||
|
||||
return G_CheckDemoExtraFiles(&demo_p, true);
|
||||
}
|
||||
|
||||
void G_AddGhost(char *defdemoname)
|
||||
{
|
||||
INT32 i;
|
||||
|
@ -2130,6 +2480,9 @@ void G_AddGhost(char *defdemoname)
|
|||
Z_Free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts.
|
||||
|
||||
switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
|
||||
{
|
||||
case ATTACKING_NONE: // 0
|
||||
|
|
22
src/g_demo.h
22
src/g_demo.h
|
@ -26,6 +26,15 @@
|
|||
extern boolean demoplayback, titledemo, demorecording, timingdemo;
|
||||
extern tic_t demostarttime;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DFILE_OVERRIDE_NONE = 0, // Show errors normally
|
||||
DFILE_OVERRIDE_LOAD, // Forcefully load demo, add files beforehand
|
||||
DFILE_OVERRIDE_SKIP, // Forcefully load demo, skip file list
|
||||
} demo_file_override_e;
|
||||
|
||||
extern demo_file_override_e demofileoverride;
|
||||
|
||||
// Quit after playing a demo from cmdline.
|
||||
extern boolean singledemo;
|
||||
extern boolean demo_start;
|
||||
|
@ -53,6 +62,18 @@ typedef enum
|
|||
GHC_RETURNSKIN // ditto
|
||||
} ghostcolor_t;
|
||||
|
||||
// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's.
|
||||
typedef enum
|
||||
{
|
||||
DFILE_ERROR_NONE = 0, // No file error
|
||||
DFILE_ERROR_NOTLOADED, // Files are not loaded, but can be without a restart.
|
||||
DFILE_ERROR_OUTOFORDER, // Files are loaded, but out of order.
|
||||
DFILE_ERROR_INCOMPLETEOUTOFORDER, // Some files are loaded out of order, but others are not.
|
||||
DFILE_ERROR_CANNOTLOAD, // Files are missing and cannot be loaded.
|
||||
DFILE_ERROR_EXTRAFILES, // Extra files outside of the replay's file list are loaded.
|
||||
DFILE_ERROR_NOTDEMO = UINT8_MAX, // This replay isn't even a replay...
|
||||
} demo_file_error_e;
|
||||
|
||||
// Record/playback tics
|
||||
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
|
||||
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
|
||||
|
@ -83,5 +104,6 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill);
|
|||
void G_StopDemo(void);
|
||||
boolean G_CheckDemoStatus(void);
|
||||
INT32 G_ConvertOldFrameFlags(INT32 frame);
|
||||
UINT8 G_CheckDemoForError(char *defdemoname);
|
||||
|
||||
#endif // __G_DEMO__
|
||||
|
|
93
src/m_menu.c
93
src/m_menu.c
|
@ -3500,10 +3500,10 @@ boolean M_Responder(event_t *ev)
|
|||
#ifndef DEVELOP
|
||||
// TODO: Replays are scary, so I left the remaining instances of this alone.
|
||||
// It'd be nice to get rid of this once and for all though!
|
||||
if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && (modifiedgame && !savemoddata) && !usedCheats)
|
||||
if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && usedCheats)
|
||||
{
|
||||
S_StartSound(NULL, sfx_skid);
|
||||
M_StartMessage(M_GetText("This cannot be done in a modified game.\n\n(Press a key)\n"), NULL, MM_NOTHING);
|
||||
M_StartMessage(M_GetText("This cannot be done in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -10449,13 +10449,23 @@ static void M_ChooseTimeAttack(INT32 choice)
|
|||
G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), (UINT8)(cv_chooseskin.value-1), false, false);
|
||||
}
|
||||
|
||||
static char ra_demoname[1024];
|
||||
|
||||
static void M_StartTimeAttackReplay(INT32 choice)
|
||||
{
|
||||
if (choice == 'y' || choice == KEY_ENTER)
|
||||
{
|
||||
M_ClearMenus(true);
|
||||
modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows
|
||||
G_DoPlayDemo(ra_demoname);
|
||||
}
|
||||
}
|
||||
|
||||
// Player has selected the "REPLAY" from the time attack screen
|
||||
static void M_ReplayTimeAttack(INT32 choice)
|
||||
{
|
||||
const char *which;
|
||||
char *demoname;
|
||||
M_ClearMenus(true);
|
||||
modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows
|
||||
UINT8 error = DFILE_ERROR_NONE;
|
||||
|
||||
if (currentMenu == &SP_ReplayDef)
|
||||
{
|
||||
|
@ -10475,11 +10485,15 @@ static void M_ReplayTimeAttack(INT32 choice)
|
|||
break;
|
||||
case 4: // guest
|
||||
// srb2/replay/main/map01-guest.lmp
|
||||
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)));
|
||||
return;
|
||||
snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
|
||||
break;
|
||||
}
|
||||
|
||||
if (choice != 4)
|
||||
{
|
||||
// srb2/replay/main/map01-sonic-time-best.lmp
|
||||
snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which);
|
||||
}
|
||||
// srb2/replay/main/map01-sonic-time-best.lmp
|
||||
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which));
|
||||
}
|
||||
else if (currentMenu == &SP_NightsReplayDef)
|
||||
{
|
||||
|
@ -10495,19 +10509,66 @@ static void M_ReplayTimeAttack(INT32 choice)
|
|||
which = "last";
|
||||
break;
|
||||
case 3: // guest
|
||||
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)));
|
||||
return;
|
||||
snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
|
||||
break;
|
||||
}
|
||||
|
||||
demoname = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which);
|
||||
if (choice != 3)
|
||||
{
|
||||
snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which);
|
||||
|
||||
#ifdef OLDNREPLAYNAME // Check for old style named NiGHTS replay if a new style replay doesn't exist.
|
||||
if (!FIL_FileExists(demoname))
|
||||
demoname = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which);
|
||||
if (!FIL_FileExists(ra_demoname))
|
||||
{
|
||||
snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which);
|
||||
}
|
||||
#endif
|
||||
|
||||
G_DoPlayDemo(demoname);
|
||||
}
|
||||
}
|
||||
|
||||
demofileoverride = DFILE_OVERRIDE_NONE;
|
||||
error = G_CheckDemoForError(ra_demoname);
|
||||
|
||||
if (error)
|
||||
{
|
||||
S_StartSound(NULL, sfx_skid);
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case DFILE_ERROR_NOTDEMO:
|
||||
M_StartMessage(M_GetText("An error occurred loading this replay.\n\n(Press a key)\n"), NULL, MM_NOTHING);
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_NOTLOADED:
|
||||
demofileoverride = DFILE_OVERRIDE_LOAD;
|
||||
M_StartMessage(M_GetText("Add-ons for this replay\nhave not been loaded.\n\nAttempt to load files?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO);
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_OUTOFORDER:
|
||||
demofileoverride = DFILE_OVERRIDE_SKIP;
|
||||
M_StartMessage(M_GetText("Add-ons for this replay\nwere loaded out of order.\n\nAttempt to playback anyway?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO);
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_INCOMPLETEOUTOFORDER:
|
||||
demofileoverride = DFILE_OVERRIDE_LOAD;
|
||||
M_StartMessage(M_GetText("Add-ons for this replay\nhave not been loaded,\nand some are in the wrong order.\n\nAttempt to load files?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO);
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_CANNOTLOAD:
|
||||
demofileoverride = DFILE_OVERRIDE_SKIP;
|
||||
M_StartMessage(M_GetText("Add-ons for this replay\ncould not be loaded.\n\nAttempt to playback anyway?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO);
|
||||
break;
|
||||
|
||||
case DFILE_ERROR_EXTRAFILES:
|
||||
demofileoverride = DFILE_OVERRIDE_SKIP;
|
||||
M_StartMessage(M_GetText("You have more files loaded\nthan the replay does.\n\nAttempt to playback anyway?\n\n(Press 'Y' to confirm)\n"), M_StartTimeAttackReplay, MM_YESNO);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
M_StartTimeAttackReplay(KEY_ENTER);
|
||||
}
|
||||
|
||||
static void M_EraseGuest(INT32 choice)
|
||||
|
|
Loading…
Reference in a new issue