From 8fb1ffe5fe6ca0ba876a4b6672bb72f979091d59 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 17 Feb 2023 14:40:44 +0000 Subject: [PATCH 1/8] Got_NameAndColor: If the player's skin is changed by the packet, make them a spectator. - Doesn't apply on join, intro camera spin turnaround, or outside of GS_LEVEL. - Extract some of Got_TeamChange's behaviour into a new FinalisePlaystateChange function. --- src/d_netcmd.c | 102 +++++++++++++++++++++++++++++++------------------ 1 file changed, 65 insertions(+), 37 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a3f28a3ba..857b2251d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1616,6 +1616,47 @@ static void SendNameAndColor(UINT8 n) SendNetXCmdForPlayer(n, XD_NAMEANDCOLOR, buf, p - buf); } +static void FinalisePlaystateChange(INT32 playernum) +{ + demo_extradata[playernum] |= DXD_PLAYSTATE; + + // Clear player score and rings if a spectator. + if (players[playernum].spectator) + { + if (gametyperules & GTR_POINTLIMIT) // SRB2kart + { + players[playernum].roundscore = 0; + K_CalculateBattleWanted(); + } + + K_PlayerForfeit(playernum, true); + + if (players[playernum].mo) + players[playernum].mo->health = 1; + + K_StripItems(&players[playernum]); + } + + // Reset away view (some code referenced from P_SpectatorJoinGame) + { + UINT8 i = 0; + INT32 *localplayertable = (splitscreen_partied[consoleplayer] ? splitscreen_party[consoleplayer] : g_localplayers); + + for (i = 0; i <= r_splitscreen; i++) + { + if (localplayertable[i] == playernum) + { + LUA_HookViewpointSwitch(players+playernum, players+playernum, true); + displayplayers[i] = playernum; + break; + } + } + } + + K_CheckBumpers(); // SRB2Kart + P_CheckRacers(); // also SRB2Kart +} + static void Got_NameAndColor(UINT8 **cp, INT32 playernum) { player_t *p = &players[playernum]; @@ -1693,8 +1734,31 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) CV_StealthSet(&cv_skin[localplayer], skins[forcedskin].name); } else + { + UINT8 oldskin = players[playernum].skin; + SetPlayerSkinByNum(playernum, skin); + // The following is a miniature subset of Got_Teamchange. + if ((gamestate == GS_LEVEL) // In a level? + && (G_GametypeHasSpectators() && players[playernum].spectator == false) // not a spectator but could be? + && (players[playernum].jointime > 1) // permit on join + && (leveltime > introtime) // permit during intro turnaround + && (players[playernum].skin != oldskin) // a skin change actually happened? + && LUA_HookTeamSwitch(&players[playernum], 0, false, false, false)) // fiiiine, lua can except it + { + P_DamageMobj(players[playernum].mo, NULL, NULL, 1, DMG_SPECTATOR); + players[playernum].playerstate = PST_REBORN; + + players[playernum].pflags &= ~PF_WANTSTOJOIN; + players[playernum].spectator = true; + + HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false); + + FinalisePlaystateChange(playernum); + } + } + // set follower colour: // Don't bother doing garbage and kicking if we receive None, // this is both silly and a waste of time, @@ -3764,22 +3828,6 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) else if (NetPacket.packet.newteam == 0) HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false); // "entered the game" text was moved to P_SpectatorJoinGame - // Reset away view (some code referenced from P_SpectatorJoinGame) - { - UINT8 i = 0; - INT32 *localplayertable = (splitscreen_partied[consoleplayer] ? splitscreen_party[consoleplayer] : g_localplayers); - - for (i = 0; i <= r_splitscreen; i++) - { - if (localplayertable[i] == playernum) - { - LUA_HookViewpointSwitch(players+playernum, players+playernum, true); - displayplayers[i] = playernum; - break; - } - } - } - /*if (G_GametypeHasTeams()) { if (NetPacket.packet.newteam) @@ -3796,27 +3844,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) if (gamestate != GS_LEVEL) return; - demo_extradata[playernum] |= DXD_PLAYSTATE; - - // Clear player score and rings if a spectator. - if (players[playernum].spectator) - { - if (gametyperules & GTR_POINTLIMIT) // SRB2kart - { - players[playernum].roundscore = 0; - K_CalculateBattleWanted(); - } - - K_PlayerForfeit(playernum, true); - - if (players[playernum].mo) - players[playernum].mo->health = 1; - - K_StripItems(&players[playernum]); - } - - K_CheckBumpers(); // SRB2Kart - P_CheckRacers(); // also SRB2Kart + FinalisePlaystateChange(playernum); } // From 7d2accb04467515c89409144119f5d31e7373c4e Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 17 Feb 2023 14:41:47 +0000 Subject: [PATCH 2/8] Got_TeamChange: only do mobj kill/PST_REBORN stuff in GS_LEVEL. --- src/d_netcmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 857b2251d..addb333eb 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3764,7 +3764,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) //Safety first! // (not respawning spectators here...) - if (!players[playernum].spectator) + if (!players[playernum].spectator && gamestate == GS_LEVEL) { if (players[playernum].mo) { From 05ee3df2f419342201967b58ad325f2fc01d9f33 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 17 Feb 2023 15:50:25 +0000 Subject: [PATCH 3/8] d_netcmd.c: Tidy up conditions for changing skin/color. - Got_NameAndColor: Incorporate check for cv_restrictskinchange and FREE PLAY - CanChangeSkin: Boil away all the useless conditions, combine with CanChangeSkinWhilePlaying --- src/d_netcmd.c | 95 +++++++++++++++----------------------------------- src/d_netcmd.h | 3 +- 2 files changed, 30 insertions(+), 68 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index addb333eb..fba65ba3b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1347,8 +1347,10 @@ static void SetPlayerName(INT32 playernum, char *newname) } } -UINT8 CanChangeSkin(INT32 playernum) +boolean CanChangeSkin(INT32 playernum) { + (void)playernum; + // Of course we can change if we're not playing if (!Playing() || !addedtogame) return true; @@ -1357,59 +1359,7 @@ UINT8 CanChangeSkin(INT32 playernum) if (cv_forceskin.value != -1) return false; - // Can change skin in intermission and whatnot. - if (gamestate != GS_LEVEL) - return true; - - // Server has skin change restrictions. - if (cv_restrictskinchange.value) - { - UINT8 i; - - // Can change skin during initial countdown. - if (leveltime < starttime) - return true; - - // Not in game, so you can change - if (players[playernum].spectator) - return true; - - // Check for freeeplay - for (i = 0; i < MAXPLAYERS; i++) - { - if (i == consoleplayer) - continue; - if (playeringame[i] && !players[i].spectator && gamestate == GS_LEVEL) - return false; // Not freeplay! - } - - // if we've gotten here, then it's freeplay, and switching anytime is fair game. - return true; - } - // if restrictskinchange is off and we're trying to change skins, don't allow changing skins while moving after the race has started. - else if (gamestate == GS_LEVEL && leveltime >= starttime) - return (!P_PlayerMoving(playernum)); - - - return true; -} - -boolean CanChangeSkinWhilePlaying(INT32 playernum) -{ - INT32 i; - - // Force skin in effect. - if ((cv_forceskin.value != -1)) - return false; - - for (i = 0; i < MAXPLAYERS; ++i) - { - if (D_IsPlayerHumanAndGaming(i) && - !P_IsLocalPlayer(&players[i])) - { - return CanChangeSkin(playernum); - } - } + // ... there used to be a lot more here, but it's now handled in Got_NameAndColor. return true; } @@ -1741,21 +1691,34 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) // The following is a miniature subset of Got_Teamchange. if ((gamestate == GS_LEVEL) // In a level? + && (cv_restrictskinchange.value) // Skin changes are restricted? && (G_GametypeHasSpectators() && players[playernum].spectator == false) // not a spectator but could be? && (players[playernum].jointime > 1) // permit on join && (leveltime > introtime) // permit during intro turnaround - && (players[playernum].skin != oldskin) // a skin change actually happened? - && LUA_HookTeamSwitch(&players[playernum], 0, false, false, false)) // fiiiine, lua can except it + && (players[playernum].skin != oldskin)) // a skin change actually happened? { - P_DamageMobj(players[playernum].mo, NULL, NULL, 1, DMG_SPECTATOR); - players[playernum].playerstate = PST_REBORN; + for (i = 0; i < MAXPLAYERS; ++i) + { + if (i == playernum) + continue; + if (!D_IsPlayerHumanAndGaming(i)) + continue; + break; + } - players[playernum].pflags &= ~PF_WANTSTOJOIN; - players[playernum].spectator = true; + if (i != MAXPLAYERS // Someone on your server who isn't you? + && LUA_HookTeamSwitch(&players[playernum], 0, false, false, false)) // fiiiine, lua can except it + { + P_DamageMobj(players[playernum].mo, NULL, NULL, 1, DMG_SPECTATOR); + players[playernum].playerstate = PST_REBORN; - HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false); + players[playernum].pflags &= ~PF_WANTSTOJOIN; + players[playernum].spectator = true; - FinalisePlaystateChange(playernum); + HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false); + + FinalisePlaystateChange(playernum); + } } } @@ -6272,7 +6235,7 @@ static void Skin_OnChange(void) return; } - if (CanChangeSkinWhilePlaying(consoleplayer)) + if (CanChangeSkin(consoleplayer)) { SendNameAndColor(0); } @@ -6293,7 +6256,7 @@ static void Skin2_OnChange(void) if (!Playing() || !splitscreen) return; // do whatever you want - if (CanChangeSkinWhilePlaying(g_localplayers[1])) + if (CanChangeSkin(g_localplayers[1])) SendNameAndColor(1); else { @@ -6307,7 +6270,7 @@ static void Skin3_OnChange(void) if (!Playing() || splitscreen < 2) return; // do whatever you want - if (CanChangeSkinWhilePlaying(g_localplayers[2])) + if (CanChangeSkin(g_localplayers[2])) SendNameAndColor(2); else { @@ -6321,7 +6284,7 @@ static void Skin4_OnChange(void) if (!Playing() || splitscreen < 3) return; // do whatever you want - if (CanChangeSkinWhilePlaying(g_localplayers[3])) + if (CanChangeSkin(g_localplayers[3])) SendNameAndColor(3); else { diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 9bc858ac7..c9006a7ba 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -285,8 +285,7 @@ void LiveStudioAudience(void); void D_Cheat(INT32 playernum, INT32 cheat, ...); // used for the player setup menu -UINT8 CanChangeSkin(INT32 playernum); -boolean CanChangeSkinWhilePlaying(INT32 playernum); +boolean CanChangeSkin(INT32 playernum); #ifdef __cplusplus } // extern "C" From 4d607ccdec6a56816dd6607fde9941c482ce0e15 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 17 Feb 2023 16:36:38 +0000 Subject: [PATCH 4/8] Tidy up conditions for forceskin to not include !K_CanChangeRules or Playing. --- src/d_netcmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index fba65ba3b..e4223c5ea 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1356,7 +1356,7 @@ boolean CanChangeSkin(INT32 playernum) return true; // Force skin in effect. - if (cv_forceskin.value != -1) + if (cv_forceskin.value != -1 && K_CanChangeRules(true)) return false; // ... there used to be a lot more here, but it's now handled in Got_NameAndColor. @@ -6107,7 +6107,7 @@ static void Command_Automate_Set(void) static void ForceSkin_OnChange(void) { // NOT in SP, silly! - if (!(netgame || multiplayer)) + if (!Playing() || !K_CanChangeRules(true)) return; if (cv_forceskin.value < 0) From 04746751098dcb0ffd3249561b5eb5c672a2c283 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 17 Feb 2023 17:07:33 +0000 Subject: [PATCH 5/8] Character Select menu: Forceskin is now reflected on the menu Matches cvar updates in real time, so can't change what's written to setup_chargrid --- src/k_menudraw.c | 54 ++++++++++++++++++++++++------------ src/menus/play-char-select.c | 53 ++++++++++++++++++++++++++++------- 2 files changed, 79 insertions(+), 28 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index e09bc5873..32476585a 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -50,6 +50,7 @@ #include "k_follower.h" #include "d_player.h" // KITEM_ constants #include "doomstat.h" // MAXSPLITSCREENPLAYERS +#include "k_grandprix.h" // K_CanChangeRules #include "i_joy.h" // for joystick menu controls @@ -1689,6 +1690,7 @@ void M_DrawCharacterSelect(void) INT16 quadx, quady; INT16 skin; INT32 basex = optionsmenu.profile != NULL ? 64 : 0; + boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1); if (setup_numplayers > 0) { @@ -1696,26 +1698,29 @@ void M_DrawCharacterSelect(void) } // We have to loop twice -- first time to draw the drop shadows, a second time to draw the icons. - for (i = 0; i < 9; i++) + if (forceskin == false) { - for (j = 0; j < 9; j++) + for (i = 0; i < 9; i++) { - skin = setup_chargrid[i][j].skinlist[setup_page]; - quadx = 4 * (i / 3); - quady = 4 * (j / 3); - - // Here's a quick little cheat to save on drawing time! - // Don't draw a shadow if it'll get covered by another icon - if ((i % 3 < 2) && (j % 3 < 2)) + for (j = 0; j < 9; j++) { - if ((setup_chargrid[i+1][j].skinlist[setup_page] != -1) - && (setup_chargrid[i][j+1].skinlist[setup_page] != -1) - && (setup_chargrid[i+1][j+1].skinlist[setup_page] != -1)) - continue; - } + skin = setup_chargrid[i][j].skinlist[setup_page]; + quadx = 4 * (i / 3); + quady = 4 * (j / 3); - if (skin != -1) - V_DrawScaledPatch(basex+ 82 + (i*16) + quadx + 1, 22 + (j*16) + quady + 1, 0, W_CachePatchName("ICONBACK", PU_CACHE)); + // Here's a quick little cheat to save on drawing time! + // Don't draw a shadow if it'll get covered by another icon + if ((i % 3 < 2) && (j % 3 < 2)) + { + if ((setup_chargrid[i+1][j].skinlist[setup_page] != -1) + && (setup_chargrid[i][j+1].skinlist[setup_page] != -1) + && (setup_chargrid[i+1][j+1].skinlist[setup_page] != -1)) + continue; + } + + if (skin != -1) + V_DrawScaledPatch(basex+ 82 + (i*16) + quadx + 1, 22 + (j*16) + quady + 1, 0, W_CachePatchName("ICONBACK", PU_CACHE)); + } } } @@ -1725,8 +1730,22 @@ void M_DrawCharacterSelect(void) // Draw the icons now for (i = 0; i < 9; i++) { + if ((forceskin == true) && (i != skins[cv_forceskin.value].kartspeed-1)) + continue; + for (j = 0; j < 9; j++) { + if (forceskin == true) + { + if (j != skins[cv_forceskin.value].kartweight-1) + continue; + skin = cv_forceskin.value; + } + else + { + skin = setup_chargrid[i][j].skinlist[setup_page]; + } + for (k = 0; k < setup_numplayers; k++) { if (setup_player[k].mdepth < CSSTEP_ASKCHANGES) @@ -1736,7 +1755,6 @@ void M_DrawCharacterSelect(void) break; // k == setup_numplayers means no one has it selected } - skin = setup_chargrid[i][j].skinlist[setup_page]; quadx = 4 * (i / 3); quady = 4 * (j / 3); @@ -1752,7 +1770,7 @@ void M_DrawCharacterSelect(void) V_DrawMappedPatch(basex + 82 + (i*16) + quadx, 22 + (j*16) + quady, 0, faceprefix[skin][FACE_RANK], colormap); // draw dot if there are more alts behind there! - if (setup_page+1 < setup_chargrid[i][j].numskins) + if (forceskin == false && setup_page+1 < setup_chargrid[i][j].numskins) V_DrawScaledPatch(basex + 82 + (i*16) + quadx, 22 + (j*16) + quady + 11, 0, W_CachePatchName("ALTSDOT", PU_CACHE)); } } diff --git a/src/menus/play-char-select.c b/src/menus/play-char-select.c index 0fd67dc45..50da1bfde 100644 --- a/src/menus/play-char-select.c +++ b/src/menus/play-char-select.c @@ -4,6 +4,7 @@ #include "../k_menu.h" #include "../r_skins.h" #include "../s_sound.h" +#include "../k_grandprix.h" // K_CanChangeRules menuitem_t PLAY_CharSelect[] = { @@ -789,6 +790,7 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num) { UINT8 numclones; INT32 skin; + boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1); if (cv_splitdevice.value) num = 0; @@ -848,19 +850,35 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num) if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) { - skin = setup_chargrid[p->gridx][p->gridy].skinlist[setup_page]; - if (setup_page >= setup_chargrid[p->gridx][p->gridy].numskins || skin == -1) + if (forceskin) { - S_StartSound(NULL, sfx_s3k7b); //sfx_s3kb2 + if ((p->gridx != skins[cv_forceskin.value].kartspeed-1) + || (p->gridy != skins[cv_forceskin.value].kartweight-1)) + { + S_StartSound(NULL, sfx_s3k7b); //sfx_s3kb2 + } + else + { + p->mdepth = CSSTEP_COLORS; + S_StartSound(NULL, sfx_s3k63); + } } else { - if (setup_page+1 == setup_chargrid[p->gridx][p->gridy].numskins) - p->mdepth = CSSTEP_COLORS; // Skip clones menu if there are none on this page. + skin = setup_chargrid[p->gridx][p->gridy].skinlist[setup_page]; + if (setup_page >= setup_chargrid[p->gridx][p->gridy].numskins || skin == -1) + { + S_StartSound(NULL, sfx_s3k7b); //sfx_s3kb2 + } else - p->mdepth = CSSTEP_ALTS; + { + if (setup_page+1 == setup_chargrid[p->gridx][p->gridy].numskins) + p->mdepth = CSSTEP_COLORS; // Skip clones menu if there are none on this page. + else + p->mdepth = CSSTEP_ALTS; - S_StartSound(NULL, sfx_s3k63); + S_StartSound(NULL, sfx_s3k63); + } } M_SetMenuDelay(num); @@ -884,7 +902,7 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num) M_SetMenuDelay(num); } - if (num == 0 && setup_numplayers == 1 && setup_maxpage) // ONLY one player. + if (num == 0 && setup_numplayers == 1 && setup_maxpage && !forceskin) // ONLY one player. { if (M_MenuButtonPressed(num, MBT_L)) { @@ -961,6 +979,8 @@ static void M_HandleCharRotate(setup_player_t *p, UINT8 num) static void M_HandleColorRotate(setup_player_t *p, UINT8 num) { + boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1); + if (cv_splitdevice.value) num = 0; @@ -987,7 +1007,8 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num) } else if (M_MenuBackPressed(num)) { - if (setup_chargrid[p->gridx][p->gridy].numskins == 1) + if (forceskin + || setup_chargrid[p->gridx][p->gridy].numskins == 1) { p->mdepth = CSSTEP_CHARS; // Skip clones menu } @@ -1253,6 +1274,7 @@ static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num) boolean M_CharacterSelectHandler(INT32 choice) { INT32 i; + boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1); (void)choice; @@ -1318,7 +1340,18 @@ boolean M_CharacterSelectHandler(INT32 choice) } // Just makes it easier to access later - p->skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]; + if (forceskin) + { + if (p->gridx != skins[cv_forceskin.value].kartspeed-1 + || p->gridy != skins[cv_forceskin.value].kartweight-1) + p->skin = -1; + else + p->skin = cv_forceskin.value; + } + else + { + p->skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]; + } // Keep profile colour. /*if (p->mdepth < CSSTEP_COLORS) From c71d4cbeaab5ca9e71e4243cb3a0e6341578f916 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 17 Feb 2023 17:11:14 +0000 Subject: [PATCH 6/8] M_SpecificMenuRestore: Catch prevMenu corruption for mid-game Character Select --- src/k_menufunc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 338dfb35f..39570b209 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -433,6 +433,9 @@ menu_t *M_SpecificMenuRestore(menu_t *torestore) M_MPOptSelectInit(-1); } + // One last catch. + PLAY_CharSelectDef.prevMenu = &MainDef; + return torestore; } From ff29d446eb93cc0de59b58d8039ef9bb10cead08 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 17 Feb 2023 17:19:27 +0000 Subject: [PATCH 7/8] `forcecharacter`: Rename to end the snickering. --- src/d_netcmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index e4223c5ea..a664e1d63 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -494,7 +494,7 @@ consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_NETVAR|CV_CALL|CV_NO static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {MAX_LAPS, "MAX"}, {0, "Map default"}, {0, NULL}}; consvar_t cv_numlaps = CVAR_INIT ("numlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, numlaps_cons_t, NumLaps_OnChange); -consvar_t cv_forceskin = CVAR_INIT ("forceskin", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange); +consvar_t cv_forceskin = CVAR_INIT ("forcecharacter", "None", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange); consvar_t cv_downloading = CVAR_INIT ("downloading", "On", 0, CV_OnOff, NULL); consvar_t cv_allowexitlevel = CVAR_INIT ("allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL); @@ -6111,10 +6111,10 @@ static void ForceSkin_OnChange(void) return; if (cv_forceskin.value < 0) - CONS_Printf("The server has lifted the forced skin restrictions.\n"); + CONS_Printf("The server has lifted the forced character restrictions.\n"); else { - CONS_Printf("The server is restricting all players to skin \"%s\".\n",cv_forceskin.string); + CONS_Printf("The server is restricting all players to \"%s\".\n",cv_forceskin.string); ForceAllSkins(cv_forceskin.value); } } From 9e494e45d091e388237555dacf3e1db77906dcdc Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 17 Feb 2023 18:15:25 +0000 Subject: [PATCH 8/8] D_IsPlayerHumanAndGaming means they're *human*, ie not a bot :face_holding_back_tears: --- src/d_netcmd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a664e1d63..a635b80b6 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1701,7 +1701,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) { if (i == playernum) continue; - if (!D_IsPlayerHumanAndGaming(i)) + if (!playeringame[i]) + continue; + if (players[i].spectator) continue; break; }