From 567a7cf4f1623b0816e4110e01eff5f47a2f954d Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 1 Mar 2024 06:03:15 -0800 Subject: [PATCH 1/5] Add G_LocalSplitscreenPartyMember --- src/g_party.cpp | 7 +++++++ src/g_party.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/g_party.cpp b/src/g_party.cpp index 307250e5c..6f83841c0 100644 --- a/src/g_party.cpp +++ b/src/g_party.cpp @@ -323,3 +323,10 @@ UINT8 G_LocalSplitscreenPartyPosition(UINT8 player) return party.find(player) - party.begin(); } + +UINT8 G_LocalSplitscreenPartyMember(UINT8 player, UINT8 index) +{ + SRB2_ASSERT(index < local_party[player].size()); + + return local_party[player][index]; +} diff --git a/src/g_party.h b/src/g_party.h index cfda1755e..56816031b 100644 --- a/src/g_party.h +++ b/src/g_party.h @@ -65,6 +65,9 @@ UINT8 G_PartyPosition(UINT8 player); // UINT8 G_LocalSplitscreenPartyPosition(UINT8 player); +// +UINT8 G_LocalSplitscreenPartyMember(UINT8 player, UINT8 index); + // // Globals // From 1eb5dabbd069008e60a97adf9ff39d473223bada Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 1 Mar 2024 06:00:40 -0800 Subject: [PATCH 2/5] Improve displayplayers command - Tabulate data - Show party members --- src/d_netcmd.c | 100 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 25 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0523c2079..5f68e5961 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -6226,35 +6226,85 @@ static void Got_Cheat(const UINT8 **cp, INT32 playernum) } } +static const char *displayplayer_compose_col(int playernum) +{ + return va("\x84(%d) \x83%s\x80", playernum, player_names[playernum]); +} + +static int displayplayer_col_len(const char *text) +{ + int n = strlen(text); + int k = n; + int i; + for (i = 0; i < n; ++i) + { + if (!isprint(text[i])) + k--; + } + return k; +} + +static void displayplayer_calc_col(int *col, const char *text) +{ + if (text && text[0] != ' ') + { + int n = displayplayer_col_len(text); + if (*col < n) + *col = n; + } +} + +static void displayplayer_print_col(int *col, const char *text) +{ + if (text) + { + if (*col) + { + int n = *col - displayplayer_col_len(text); + CONS_Printf("%s%*s ", text, n, ""); + } + } + else + CONS_Printf("\n"); +} + +static void displayplayer_iter_table(int table[5], void(*col_cb)(int*,const char*)) +{ + int i; + + col_cb(&table[0], ""); + for (i = 0; i < 4; ++i) + col_cb(&table[1 + i], va(" %d", i)); + col_cb(NULL, NULL); + + col_cb(&table[0], "g_local"); + for (i = 0; i <= splitscreen; ++i) + col_cb(&table[1 + i], displayplayer_compose_col(g_localplayers[i])); + col_cb(NULL, NULL); + + col_cb(&table[0], "display"); + for (i = 0; i <= r_splitscreen; ++i) + col_cb(&table[1 + i], displayplayer_compose_col(displayplayers[i])); + col_cb(NULL, NULL); + + col_cb(&table[0], "local party"); + for (i = 0; i < G_LocalSplitscreenPartySize(consoleplayer); ++i) + col_cb(&table[1 + i], displayplayer_compose_col(G_LocalSplitscreenPartyMember(consoleplayer, i))); + col_cb(NULL, NULL); + + col_cb(&table[0], "final party"); + for (i = 0; i < G_PartySize(consoleplayer); ++i) + col_cb(&table[1 + i], displayplayer_compose_col(G_PartyMember(consoleplayer, i))); + col_cb(NULL, NULL); +} + /** Prints the number of displayplayers[0]. - * - * \todo Possibly remove this; it was useful for debugging at one point. */ static void Command_Displayplayer_f(void) { - int playernum; - int i; - for (i = 0; i <= splitscreen; ++i) - { - playernum = g_localplayers[i]; - CONS_Printf( - "local player %d: \x84(%d) \x83%s\x80\n", - i, - playernum, - player_names[playernum] - ); - } - CONS_Printf("\x83----------------------------------------\x80\n"); - for (i = 0; i <= r_splitscreen; ++i) - { - playernum = displayplayers[i]; - CONS_Printf( - "display player %d: \x84(%d) \x83%s\x80\n", - i, - playernum, - player_names[playernum] - ); - } + int table[5] = {0}; + displayplayer_iter_table(table, displayplayer_calc_col); + displayplayer_iter_table(table, displayplayer_print_col); } /** Quits a game and returns to the title screen. From 3179183df795d4d813b53db051653c66e2a28e68 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 1 Mar 2024 06:04:20 -0800 Subject: [PATCH 3/5] Replays: do not initialize displayplayers to INT32_MAX - Only demo playback does this and it's a mystery why --- src/g_demo.cpp | 6 ++---- src/g_game.c | 7 ------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/g_demo.cpp b/src/g_demo.cpp index fea181a6a..650aa4d53 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -3200,15 +3200,13 @@ void G_DoPlayDemo(const char *defdemoname) // didn't start recording right away. demo.deferstart = false; - displayplayers[0] = consoleplayer = 0; + consoleplayer = 0; memset(playeringame,0,sizeof(playeringame)); + memset(displayplayers,0,sizeof(displayplayers)); // Load players that were in-game when the map started p = READUINT8(demobuf.p); - for (i = 1; i < MAXSPLITSCREENPLAYERS; i++) - displayplayers[i] = INT32_MAX; - while (p != 0xFF) { UINT8 flags = READUINT8(demobuf.p); diff --git a/src/g_game.c b/src/g_game.c index 7b80267e4..1ce8c1dbe 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1648,13 +1648,6 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) viewnum = playersviewable; r_splitscreen = viewnum-1; - /* Prepare extra views for G_FindView to pass. */ - for (viewd = splits+1; viewd < viewnum; ++viewd) - { - displayplayerp = (&displayplayers[viewd-1]); - (*displayplayerp) = INT32_MAX; - } - R_ExecuteSetViewSize(); } From adebfb000c9b277e2f35c3406db2ccb9e120ed97 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 1 Mar 2024 06:05:52 -0800 Subject: [PATCH 4/5] Replays: keep party in sync with current viewpoints - More and more parts of the game rely on parties - Parties are assumed to match the displayplayers - This fixes A/B/C/D nametags --- src/d_netcmd.c | 11 +++++++++-- src/g_demo.cpp | 31 ++++++++++++++++++++++++++++++ src/g_demo.h | 2 ++ src/g_game.c | 9 +++++++-- src/menus/transient/pause-replay.c | 6 +++--- 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 5f68e5961..768c461de 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1838,8 +1838,15 @@ static void Command_SetViews_f(void) // Even if the splits go beyond the real number of // splitscreen players, displayplayers was filled // with duplicates of P1 (see Got_AddPlayer). - r_splitscreen = newsplits-1; - R_ExecuteSetViewSize(); + if (demo.playback) + { + G_SyncDemoParty(consoleplayer, newsplits-1); + } + else + { + r_splitscreen = newsplits-1; + R_ExecuteSetViewSize(); + } // If promoting (outside of replays), make sure the // camera is in the correct position. diff --git a/src/g_demo.cpp b/src/g_demo.cpp index 650aa4d53..c649320df 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -47,6 +47,7 @@ #include "lua_hook.h" #include "md5.h" // demo checksums #include "p_saveg.h" // savebuffer_t +#include "g_party.h" // SRB2Kart #include "d_netfil.h" // nameonly @@ -4096,3 +4097,33 @@ boolean G_CheckDemoTitleEntry(void) return true; } + +void G_SyncDemoParty(INT32 rem, INT32 newsplitscreen) +{ + int r_splitscreen_copy = r_splitscreen; + INT32 displayplayers_copy[MAXSPLITSCREENPLAYERS]; + memcpy(displayplayers_copy, displayplayers, sizeof displayplayers); + + // If we switch away from someone's view, that player + // should be removed from the party. + // However, it is valid to have the player on multiple + // viewports. + + // Remove this player + G_LeaveParty(rem); + + // And reset the rest of the party + for (int i = 0; i <= r_splitscreen_copy; ++i) + G_LeaveParty(displayplayers_copy[i]); + + // Restore the party, without the removed player, and + // with the order matching displayplayers + for (int i = 0; i <= newsplitscreen; ++i) + G_JoinParty(consoleplayer, displayplayers_copy[i]); + + // memcpy displayplayers back to preserve duplicates + // (G_JoinParty will not create duplicates itself) + r_splitscreen = newsplitscreen; + memcpy(displayplayers, displayplayers_copy, sizeof displayplayers); + R_ExecuteSetViewSize(); +} diff --git a/src/g_demo.h b/src/g_demo.h index 68d7bb6ed..4405589e1 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -243,6 +243,8 @@ typedef enum DEMO_ATTRACT_CREDITS } demoAttractMode_t; +void G_SyncDemoParty(INT32 rem, INT32 newsplitscreen); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/g_game.c b/src/g_game.c index 1ce8c1dbe..26a2c387a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1685,8 +1685,13 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) } } - if (viewnum == 1 && demo.playback) - consoleplayer = displayplayers[0]; + if (demo.playback) + { + if (viewnum == 1) + consoleplayer = displayplayers[0]; + + G_SyncDemoParty(olddisplayplayer, r_splitscreen); + } // change statusbar also if playing back demo if (demo.quitafterplaying) diff --git a/src/menus/transient/pause-replay.c b/src/menus/transient/pause-replay.c index 138127e8e..9c0c777a7 100644 --- a/src/menus/transient/pause-replay.c +++ b/src/menus/transient/pause-replay.c @@ -9,6 +9,7 @@ #include "../../p_local.h" // P_InitCameraCmd #include "../../d_main.h" // D_StartTitle #include "../../k_credits.h" +#include "../../g_demo.h" static void M_PlaybackTick(void); @@ -220,13 +221,12 @@ void M_PlaybackSetViews(INT32 choice) { if (choice == 0) { - r_splitscreen--; + G_SyncDemoParty(displayplayers[r_splitscreen], r_splitscreen - 1); } else { - r_splitscreen = 0; + G_SyncDemoParty(consoleplayer, 0); } - R_ExecuteSetViewSize(); } } From e00b676dd8ca709e1913f7c1ee7b4ab18b2c079d Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 1 Mar 2024 16:56:42 -0800 Subject: [PATCH 5/5] Replays: fix camera reset when promoting splits - Off-by-one error --- src/g_game.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 26a2c387a..aa60e5b1d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1672,18 +1672,22 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) /* Focus our target view first so that we don't take its player. */ (*displayplayerp) = playernum; - if ((*displayplayerp) != olddisplayplayer) - { - G_FixCamera(viewnum); - } + /* If a viewpoint changes, reset the camera to clear uninitialized memory. */ if (viewnum > splits) { - for (viewd = splits+1; viewd < viewnum; ++viewd) + for (viewd = splits+1; viewd <= viewnum; ++viewd) { G_FixCamera(viewd); } } + else + { + if ((*displayplayerp) != olddisplayplayer) + { + G_FixCamera(viewnum); + } + } if (demo.playback) {