diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 80203789..71adfdf0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -793,6 +793,8 @@ void D_RegisterClientCommands(void) COM_AddCommand("displayplayer", Command_Displayplayer_f); + CV_RegisterVar(&cv_recordmultiplayerdemos); + // FIXME: not to be here.. but needs be done for config loading CV_RegisterVar(&cv_usegamma); @@ -2502,6 +2504,8 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) LUAh_MapChange(mapnumber); #endif*/ + demosaved = demodefersave = false; + demosavebutton = 0; G_InitNew(pencoremode, mapname, resetplayer, skipprecutscene); if (demoplayback && !timingdemo) precache = true; diff --git a/src/g_game.c b/src/g_game.c index 864c7f43..84b5f1ca 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -288,8 +288,8 @@ UINT32 timesBeatenWithEmeralds; //UINT32 timesBeatenUltimate; static char demoname[64]; -boolean demorecording; -boolean demoplayback; +boolean demorecording, demosaved, demodefersave, demoplayback; +tic_t demosavebutton; boolean titledemo; // Title Screen demo can be cancelled by any key boolean fromtitledemo; // SRB2Kart: Don't stop the music static UINT8 *demobuffer = NULL; @@ -334,6 +334,9 @@ boolean precache = true; // if true, load all graphics at start INT16 prevmap, nextmap; +static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}}; +consvar_t cv_recordmultiplayerdemos = {"recordmultiplayerdemos", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + static UINT8 *savebuffer; // Analog Control @@ -3206,6 +3209,9 @@ void G_ExitLevel(void) // Remove CEcho text on round end. HU_ClearCEcho(); + + if (multiplayer && demorecording && cv_recordmultiplayerdemos.value == 2) + G_SaveDemo(); } } @@ -6990,8 +6996,6 @@ void G_StopDemo(void) boolean G_CheckDemoStatus(void) { - boolean saved; - while (ghosts) { demoghost *next = ghosts->next; @@ -7040,35 +7044,41 @@ boolean G_CheckDemoStatus(void) return true; } - if (demorecording) + if (demorecording && (!multiplayer || cv_recordmultiplayerdemos.value == 2)) { - UINT8 *p = demobuffer+16; // checksum position -#ifdef NOMD5 - UINT8 i; - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - for (i = 0; i < 16; i++, p++) - *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. -#else - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file. -#endif - saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file. - free(demobuffer); - demorecording = false; - - if (modeattacking != ATTACKING_RECORD) - { - if (saved) - CONS_Printf(M_GetText("Demo %s recorded\n"), demoname); - else - CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname); - } + G_SaveDemo(); return true; } + demorecording = false; return false; } +void G_SaveDemo(void) +{ + UINT8 *p = demobuffer+16; // checksum position +#ifdef NOMD5 + UINT8 i; + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + for (i = 0; i < 16; i++, p++) + *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. +#else + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file. +#endif + demosaved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file. + free(demobuffer); + demorecording = false; + + if (modeattacking != ATTACKING_RECORD) + { + if (demosaved) + CONS_Printf(M_GetText("Demo %s recorded\n"), demoname); + else + CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname); + } +} + // // G_SetGamestate // diff --git a/src/g_game.h b/src/g_game.h index 73dcb1ce..458f166b 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -36,7 +36,9 @@ extern boolean playeringame[MAXPLAYERS]; // ====================================== // demoplaying back and demo recording -extern boolean demoplayback, titledemo, fromtitledemo, demorecording, timingdemo; +extern boolean demoplayback, titledemo, fromtitledemo, demorecording, timingdemo, demosaved, demodefersave; +extern tic_t demosavebutton; +extern consvar_t cv_recordmultiplayerdemos; // Quit after playing a demo from cmdline. extern boolean singledemo; @@ -207,6 +209,7 @@ void G_StopMetalDemo(void); ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); void G_StopDemo(void); boolean G_CheckDemoStatus(void); +void G_SaveDemo(void); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); diff --git a/src/p_tick.c b/src/p_tick.c index 7e048af5..f5d5d5b2 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -13,6 +13,7 @@ #include "doomstat.h" #include "g_game.h" +#include "g_input.h" #include "p_local.h" #include "z_zone.h" #include "s_sound.h" @@ -737,6 +738,9 @@ void P_Ticker(boolean run) G_WriteGhostTic(players[i].mo, i); } + + if (demosavebutton && demosavebutton + 3*TICRATE < leveltime && InputDown(gc_lookback, 1)) + demodefersave = true; } if (demoplayback) // Use Ghost data for consistency checks. { diff --git a/src/p_user.c b/src/p_user.c index 73caa211..d51c18af 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1835,6 +1835,9 @@ void P_DoPlayerExit(player_t *player) player->powers[pw_spacetime] = 0; player->kartstuff[k_cardanimation] = 0; // srb2kart: reset battle animation + if (player == &players[consoleplayer]) + demosavebutton = leveltime; + /*if (playeringame[player-players] && netgame && !circuitmap) CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);*/ } diff --git a/src/y_inter.c b/src/y_inter.c index 0ca17507..995cddfe 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -562,6 +562,11 @@ dotimer: string); } + if (demorecording && cv_recordmultiplayerdemos.value == 1) + V_DrawCenteredString(BASEVIDWIDTH/2, 178, V_ALLOWLOWERCASE|hilicol, "Press Look Backward to save the replay"); + else if (demosaved) + V_DrawCenteredString(BASEVIDWIDTH/2, 178, V_ALLOWLOWERCASE|hilicol, "Replay saved!"); + // Make it obvious that scrambling is happening next round. if (cv_scrambleonchange.value && cv_teamscramble.value && (intertic/TICRATE % 2 == 0)) V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, hilicol, M_GetText("Teams will be scrambled next round!")); @@ -577,6 +582,12 @@ void Y_Ticker(void) if (intertype == int_none) return; + if (demorecording && cv_recordmultiplayerdemos.value == 1 && (demodefersave || InputDown(gc_lookback, 1))) + { + demodefersave = false; + G_SaveDemo(); + } + // Check for pause or menu up in single player if (paused || P_AutoPause()) return;