From a1c7b219093a7bb14ac03038b447463eed2948be Mon Sep 17 00:00:00 2001 From: Roman Fomin Date: Wed, 10 Aug 2022 13:50:15 +0700 Subject: [PATCH] More demo playback QOL (#692) * implement negative -skipsec * restart level/demo key also restarts demo playback * rename the new demo* variables to playback_* * disable skipping demo playback in multiplayer, add checks for connected players --- src/d_loop.c | 44 +++++++++++++++++++++++++++-- src/d_main.c | 26 ++++++++--------- src/d_net.c | 21 -------------- src/doomstat.h | 10 ++++--- src/g_game.c | 76 +++++++++++++++++++++++++++++++++++++++----------- src/hu_stuff.c | 4 +-- src/hu_stuff.h | 2 +- src/i_video.c | 29 +++++++++++-------- src/m_argv.c | 16 +++++++++-- src/m_menu.c | 13 +++++---- src/p_setup.c | 10 +++---- 11 files changed, 164 insertions(+), 87 deletions(-) diff --git a/src/d_loop.c b/src/d_loop.c index 34a9e33d..c0fc2c74 100644 --- a/src/d_loop.c +++ b/src/d_loop.c @@ -109,13 +109,14 @@ static int player_class; static int GetAdjustedTime(void) { - if (new_sync && offsetms) + // Use the adjustments from net_client.c only if we are + // using the new sync mode. + + if (new_sync && net_client_connected) { int time_ms; time_ms = I_GetTimeMS(); - // Use the adjustments from net_client.c only if we are - // using the new sync mode. time_ms += (offsetms / FRACUNIT); @@ -522,6 +523,26 @@ boolean D_InitNetGame(net_connect_data_t *connect_data) return result; } +boolean D_CheckNetConnect(void) +{ + return net_client_connected; +} + +void D_CheckNetPlaybackSkip(void) +{ + if (!net_client_connected) + { + return; + } + + if (fastdemo || PLAYBACK_SKIP) + { + printf("Demo playback skipping is suppressed in multiplayer.\n"); + fastdemo = false; + playback_warp = -1; + playback_skiptics = 0; + } +} // // D_QuitNetGame @@ -633,6 +654,23 @@ static boolean PlayersInGame(void) return result; } +int D_GetPlayersInNetGame(void) +{ + int i; + int result = 0; + + if (net_client_connected) + { + for (i = 0; i < NET_MAXPLAYERS; ++i) + { + if (local_playeringame[i]) + ++result; + } + } + + return result; +} + // When using ticdup, certain values must be cleared out when running // the duplicate ticcmds. diff --git a/src/d_main.c b/src/d_main.c index 853bfdf8..cdda1859 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -223,7 +223,7 @@ void D_Display (void) int wipestart; boolean done, wipe, redrawsbar; - if (demobar && DEMOSKIP) + if (demobar && PLAYBACK_SKIP) { if (HU_DemoProgressBar(false)) { @@ -1815,7 +1815,7 @@ static void D_EndDoom(void) } // [FG] fast-forward demo to the desired map -int demowarp = -1; +int playback_warp = -1; // // D_DoomMain @@ -2317,7 +2317,7 @@ void D_DoomMain(void) autostart = true; } // [FG] fast-forward demo to the desired map - demowarp = startmap; + playback_warp = startmap; } //jff 1/22/98 add command line parms to disable sound and music @@ -2503,11 +2503,6 @@ void D_DoomMain(void) I_InitJoystick(); I_InitSound(); - if (fastdemo) - { - I_SetFastdemoTimer(true); - } - puts("NET_Init: Init network subsystem."); NET_Init(); @@ -2562,18 +2557,16 @@ void D_DoomMain(void) if (sscanf(myargv[p+1], "%f:%f", &min, &sec) == 2) { - demoskip_tics = (int) ((60 * min + sec) * TICRATE); + playback_skiptics = (int) ((60 * min + sec) * TICRATE); } else if (sscanf(myargv[p+1], "%f", &sec) == 1) { - demoskip_tics = (int) (sec * TICRATE); + playback_skiptics = (int) (sec * TICRATE); } else { I_Error("Invalid parameter '%s' for -skipsec, should be min:sec", myargv[p+1]); } - - demoskip_tics = abs(demoskip_tics); } // start the apropriate game based on parms @@ -2660,10 +2653,15 @@ void D_DoomMain(void) else { // [FG] no demo playback - demowarp = -1; - demoskip_tics = -1; + playback_warp = -1; + playback_skiptics = 0; } + if (fastdemo) + { + I_SetFastdemoTimer(true); + } + // [FG] init graphics (WIDESCREENDELTA) before HUD widgets I_InitGraphics(); diff --git a/src/d_net.c b/src/d_net.c index 2503b596..a9e787ac 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -292,26 +292,5 @@ void D_CheckNetGame (void) printf("player %i of %i (%i nodes)\n", consoleplayer+1, settings.num_players, settings.num_players); - - // Show players here; the server might have specified a time limit -/* - if (timelimit > 0 && deathmatch) - { - // Gross hack to work like Vanilla: - - if (timelimit == 20 && M_CheckParm("-avg")) - { - printf("Austin Virtual Gaming: Levels will end " - "after 20 minutes\n"); - } - else - { - printf("Levels will end after %d minute", timelimit); - if (timelimit > 1) - printf("s"); - printf(".\n"); - } - } -*/ } diff --git a/src/doomstat.h b/src/doomstat.h index f2fc7a6b..67a3e463 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -203,6 +203,8 @@ extern boolean respawnmonsters; // Netgame? Only true if >1 player. extern boolean netgame; +extern boolean D_CheckNetConnect(void); + // Flag: true only if started as net deathmatch. // An enum might handle altdeath/cooperative better. extern boolean deathmatch; @@ -298,13 +300,13 @@ extern boolean timingdemo; // Run tick clock at fastest speed possible while playing demo. killough extern boolean fastdemo; // [FG] fast-forward demo to the desired map -extern int demowarp; +extern int playback_warp; // fast-forward demo to the next map -extern boolean demonext; +extern boolean playback_nextlevel; // skipping demo -extern int demoskip_tics; +extern int playback_skiptics; -#define DEMOSKIP (demowarp >= 0 || demoskip_tics > 0 || demonext) +#define PLAYBACK_SKIP (playback_warp >= 0 || playback_skiptics || playback_nextlevel) extern boolean strictmode, default_strictmode; diff --git a/src/g_game.c b/src/g_game.c index 7c940dfd..87fd3230 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -313,26 +313,35 @@ void G_EnableWarp(boolean warp) } } -int demoskip_tics = -1; +static int playback_levelstarttic; +int playback_skiptics = 0; static void G_DemoSkipTics(void) { static boolean warp = false; - if (demoskip_tics == -1) + if (!playback_skiptics || !playback_totaltics) return; - if (demowarp >= 0) + if (playback_warp >= 0) warp = true; - if (demowarp == -1) + if (playback_warp == -1) { - if ((warp && demoskip_tics < gametic - levelstarttic) || - (!warp && demoskip_tics < gametic)) + if (playback_skiptics < 0) + { + if (warp) + playback_skiptics = playback_totaltics - playback_levelstarttic + playback_skiptics; + else + playback_skiptics = playback_totaltics + playback_skiptics; + } + + if ((warp && playback_skiptics < playback_tic - playback_levelstarttic) || + (!warp && playback_skiptics < playback_tic)) { G_EnableWarp(false); S_RestartMusic(); - demoskip_tics = -1; + playback_skiptics = 0; } } } @@ -705,6 +714,8 @@ static void G_DoLoadLevel(void) levelstarttic = gametic; // for time calculation + playback_levelstarttic = playback_tic; + if (!demo_compatibility && demo_version < 203) // killough 9/29/98 basetic = gametic; @@ -839,7 +850,6 @@ boolean G_Responder(event_t* ev) if (M_InputActivated(input_menu_reloadlevel) && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && - !demoplayback && !deathmatch && !menuactive) { @@ -872,7 +882,7 @@ boolean G_Responder(event_t* ev) return true; } - if (M_InputActivated(input_demo_join)) + if (M_InputActivated(input_demo_join) && !PLAYBACK_SKIP && !fastdemo) { sendjoin = true; return true; @@ -978,12 +988,27 @@ boolean G_Responder(event_t* ev) return false; } +int D_GetPlayersInNetGame(void); + +static void CheckPlayersInNetGame(void) +{ + int i; + int playerscount = 0; + for (i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i]) + ++playerscount; + } + + if (playerscount != D_GetPlayersInNetGame()) + I_Error("Not enough players to continue the demo."); +} + // // DEMO RECORDING // -// [crispy] demo progress bar -int defdemotics = 0, deftotaldemotics; +int playback_tic = 0, playback_totaltics = 0; static char *defdemoname; @@ -993,6 +1018,9 @@ static char *defdemoname; // demo under a different name static void G_JoinDemo(void) { + if (netgame) + CheckPlayersInNetGame(); + if (!orig_demoname) { byte *actualbuffer = demobuffer; @@ -1048,7 +1076,7 @@ static void G_ReadDemoTiccmd(ticcmd_t *cmd) players[consoleplayer].message = "Game Saved (Suppressed)"; } - defdemotics++; + playback_tic++; } } @@ -1646,12 +1674,12 @@ static void G_DoPlayDemo(void) { byte *demo_ptr = demo_p; - deftotaldemotics = defdemotics = 0; + playback_totaltics = playback_tic = 0; while (*demo_ptr != DEMOMARKER && (demo_ptr - demobuffer) < lumplength) { demo_ptr += (longtics ? 5 : 4); - deftotaldemotics++; + playback_totaltics++; } } @@ -2185,6 +2213,15 @@ void G_Ticker(void) if (demoplayback && cmd->buttons & BT_JOIN) G_JoinDemo(); + // catch BTS_RELOAD for demo playback restart + if (demoplayback && + cmd->buttons & BT_SPECIAL && cmd->buttons & BT_SPECIALMASK && + cmd->buttons & BTS_RELOAD) + { + playback_tic = 0; + gameaction = ga_playdemo; + } + if (demoplayback) G_ReadDemoTiccmd(cmd); @@ -3152,7 +3189,7 @@ void G_InitNew(skill_t skill, int episode, int map) // [FG] total time for all completed levels totalleveltimes = 0; - defdemotics = 0; + playback_tic = 0; //jff 4/16/98 force marks on automap cleared every new level start AM_clearMarks(); @@ -3620,13 +3657,17 @@ void G_BeginRecording(void) // G_PlayDemo // +void D_CheckNetPlaybackSkip(void); + void G_DeferedPlayDemo(char* name) { defdemoname = name; gameaction = ga_playdemo; + D_CheckNetPlaybackSkip(); + // [FG] fast-forward demo to the desired map - if (demowarp >= 0 || demoskip_tics > 0) + if (playback_warp >= 0 || playback_skiptics) { G_EnableWarp(true); } @@ -3729,6 +3770,9 @@ boolean G_CheckDemoStatus(void) { if (demorecording) { + if (netgame) + CheckPlayersInNetGame(); + demoplayback = false; // clear progress demo bar diff --git a/src/hu_stuff.c b/src/hu_stuff.c index f3e21ded..a7778c06 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1082,10 +1082,10 @@ static void HU_DrawCrosshair(void) // [crispy] print a bar indicating demo progress at the bottom of the screen boolean HU_DemoProgressBar(boolean force) { - const int progress = SCREENWIDTH * defdemotics / deftotaldemotics; + const int progress = SCREENWIDTH * playback_tic / playback_totaltics; static int old_progress = 0; - if (progress - old_progress) + if (old_progress < progress) { old_progress = progress; } diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 42e6d80a..213e8af8 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -89,7 +89,7 @@ extern int hud_timests; // Time/STS above status bar extern boolean message_centered; // center messages extern boolean message_colorized; // colorize player messages -extern int defdemotics, deftotaldemotics; +extern int playback_tic, playback_totaltics; extern int crispy_hud; diff --git a/src/i_video.c b/src/i_video.c index a23b8772..ef30c03b 100644 --- a/src/i_video.c +++ b/src/i_video.c @@ -1009,7 +1009,7 @@ void I_BeginRead(unsigned int bytes) static void I_DrawDiskIcon(void) { - if (!disk_icon || !in_graphics_mode || DEMOSKIP) + if (!disk_icon || !in_graphics_mode || PLAYBACK_SKIP) return; if (disk_to_draw >= DISK_ICON_THRESHOLD) @@ -1032,7 +1032,7 @@ void I_EndRead(void) static void I_RestoreDiskBackground(void) { - if (!disk_icon || !in_graphics_mode || DEMOSKIP) + if (!disk_icon || !in_graphics_mode || PLAYBACK_SKIP) return; if (disk_to_restore) @@ -1383,6 +1383,7 @@ static void I_InitGraphicsMode(void) if (firsttime) { + int p, tmp_scalefactor; firsttime = false; //! @@ -1421,8 +1422,8 @@ static void I_InitGraphicsMode(void) // Don't scale up the screen. Implies -window. // - if (M_CheckParm("-1")) - scalefactor = 1; + if ((p = M_CheckParm("-1"))) + tmp_scalefactor = 1; //! // @category video @@ -1430,8 +1431,8 @@ static void I_InitGraphicsMode(void) // Double up the screen to 2x its normal size. Implies -window. // - else if (M_CheckParm("-2")) - scalefactor = 2; + else if ((p = M_CheckParm("-2"))) + tmp_scalefactor = 2; //! // @category video @@ -1439,12 +1440,16 @@ static void I_InitGraphicsMode(void) // Triple up the screen to 3x its normal size. Implies -window. // - else if (M_CheckParm("-3")) - scalefactor = 3; - else if (M_CheckParm("-4")) - scalefactor = 4; - else if (M_CheckParm("-5")) - scalefactor = 5; + else if ((p = M_CheckParm("-3"))) + tmp_scalefactor = 3; + else if ((p = M_CheckParm("-4"))) + tmp_scalefactor = 4; + else if ((p = M_CheckParm("-5"))) + tmp_scalefactor = 5; + + // -skipsec can take a negative number as a parameter + if (p && strcasecmp("-skipsec", myargv[p - 1])) + scalefactor = tmp_scalefactor; //! // @category video diff --git a/src/m_argv.c b/src/m_argv.c index 9c785c13..a9ff36f5 100644 --- a/src/m_argv.c +++ b/src/m_argv.c @@ -178,10 +178,20 @@ void M_CheckCommandLine(void) else if (!strcasecmp(myargv[p], "-warp")) { check = CheckNumArgs(p, 1); - if (!check) - I_Error("No parameter for '-warp'."); - else + if (check) p = check; + else + I_Error("No parameter for '-warp'."); + } + // -skipsec can be negative + else if (!strcasecmp(myargv[p], "-skipsec") && p + 1 < myargc) + { + float min, sec; + if (sscanf(myargv[p + 1], "%f:%f", &min, &sec) == 2 || + sscanf(myargv[p + 1], "%f", &sec) == 1) + p += 2; + else + I_Error("No parameter for '-skipsec'."); } // -turbo has default value else if (!strcasecmp(myargv[p], "-turbo")) diff --git a/src/m_menu.c b/src/m_menu.c index c709bdc0..228c8bf7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5347,9 +5347,9 @@ boolean M_Responder (event_t* ev) // [FG] reload current level / go to next level if (M_InputActivated(input_menu_nextlevel)) { - if (demoplayback && singledemo && !DEMOSKIP) + if (demoplayback && singledemo && !PLAYBACK_SKIP) { - demonext = true; + playback_nextlevel = true; G_EnableWarp(true); return true; } @@ -5359,7 +5359,8 @@ boolean M_Responder (event_t* ev) if (M_InputActivated(input_demo_fforward)) { - if (demoplayback && singledemo && !DEMOSKIP && !fastdemo) + if (demoplayback && !PLAYBACK_SKIP && !fastdemo + && !D_CheckNetConnect()) { static boolean fastdemo_timer = false; fastdemo_timer = !fastdemo_timer; @@ -5368,7 +5369,7 @@ boolean M_Responder (event_t* ev) } } - if (M_InputActivated(input_speed_up) && (!netgame || demoplayback) + if (M_InputActivated(input_speed_up) && !D_CheckNetConnect() && !strictmode) { realtic_clock_rate += 10; @@ -5377,7 +5378,7 @@ boolean M_Responder (event_t* ev) I_SetTimeScale(realtic_clock_rate); } - if (M_InputActivated(input_speed_down) && (!netgame || demoplayback) + if (M_InputActivated(input_speed_down) && !D_CheckNetConnect() && !strictmode) { realtic_clock_rate -= 10; @@ -5386,7 +5387,7 @@ boolean M_Responder (event_t* ev) I_SetTimeScale(realtic_clock_rate); } - if (M_InputActivated(input_speed_default) && (!netgame || demoplayback) + if (M_InputActivated(input_speed_default) && !D_CheckNetConnect() && !strictmode) { realtic_clock_rate = 100; diff --git a/src/p_setup.c b/src/p_setup.c index 2e02e6eb..d1a7bb84 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1501,7 +1501,7 @@ static boolean P_LoadReject(int lumpnum, int totallines) // killough 5/3/98: reformatted, cleaned up // fast-forward demo to the next map -boolean demonext = false; +boolean playback_nextlevel = false; void P_SetupLevel(int episode, int map, int playermask, skill_t skill) { @@ -1522,13 +1522,13 @@ void P_SetupLevel(int episode, int map, int playermask, skill_t skill) players[consoleplayer].viewz = 1; // [FG] fast-forward demo to the desired map - if (demowarp == map || demonext) + if (playback_warp == map || playback_nextlevel) { - if (demoskip_tics == -1) + if (!playback_skiptics) G_EnableWarp(false); - demowarp = -1; - demonext = false; + playback_warp = -1; + playback_nextlevel = false; } // Make sure all sounds are stopped before Z_FreeTags.