diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 33c06bb9c..7ac0d59b7 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3886,6 +3886,8 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) node = READUINT8(*p); newplayernum = READUINT8(*p); + CONS_Debug(DBG_NETPLAY, "addplayer: %d %d\n", node, newplayernum); + if (newplayernum+1 > doomcom->numslots) doomcom->numslots = (INT16)(newplayernum+1); @@ -3898,13 +3900,13 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) console = READUINT8(*p); splitscreenplayer = READUINT8(*p); + G_AddPlayer(newplayernum, console); + for (i = 0; i < MAXAVAILABILITY; i++) { newplayer->availabilities[i] = READUINT8(*p); } - G_AddPlayer(newplayernum, console); - // the server is creating my player if (node == mynode) { @@ -3936,6 +3938,13 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) players[newplayernum].splitscreenindex = splitscreenplayer; players[newplayernum].bot = false; + // Previously called at the top of this function, commented as + // "caused desyncs in this spot :(". But we can't do this in + // G_PlayerReborn, since that only runs for level contexts and + // allows people to party-crash the vote screen even when + // maxplayers is too low for them. Let's try it here...? + G_SpectatePlayerOnJoin(newplayernum); + if (netgame) { char joinmsg[256]; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 27b31bbf5..d960b66d8 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1956,7 +1956,7 @@ UINT8 CanChangeSkin(INT32 playernum) return true; // Not in game, so you can change - if (players[playernum].spectator || players[playernum].playerstate == PST_DEAD || players[playernum].playerstate == PST_REBORN) + if (players[playernum].spectator || players[playernum].playerstate == PST_DEAD || players[playernum].playerstate == PST_REBORN || players[playernum].exiting) return true; return false; diff --git a/src/g_game.c b/src/g_game.c index 77c8c20fd..b5881a60a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3053,6 +3053,8 @@ static inline void G_PlayerFinishLevel(INT32 player) legitimateexit = false; } + + p->spectatorreentry = 0; // Clean up any pending re-entry forbiddings } void G_HandleRestatMessage(restatmessage_t *rm) @@ -3199,6 +3201,15 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) tic_t laptime[LAP__MAX]; + // This needs to be first, to permit it to wipe extra information + jointime = players[player].jointime; + if (jointime <= 1) + { + // Now called in Got_AddPlayer. In case of weirdness, break glass. + // G_SpectatePlayerOnJoin(player); + betweenmaps = true; + } + score = players[player].score; lives = players[player].lives; ctfteam = players[player].ctfteam; @@ -3247,7 +3258,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_FLIPCAM)); // SRB2kart - if (betweenmaps || leveltime <= starttime || spectator == true || players[player].jointime == 0) + if (betweenmaps || leveltime <= starttime || spectator == true) { itemroulette = 0; previtemroulette = 0; @@ -4029,6 +4040,38 @@ void G_AddPlayer(INT32 playernum, INT32 console) demo_extradata[playernum] |= DXD_ADDPLAYER; // Set everything } +void G_SpectatePlayerOnJoin(INT32 playernum) +{ + // This is only ever called shortly after the above. + // That calls CL_ClearPlayer, so spectator is false by default + + if (!netgame && !G_GametypeHasTeams() && !G_GametypeHasSpectators()) + return; + + // These are handled automatically elsewhere + if (demo.playback || players[playernum].bot) + return; + + UINT8 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + // Spectators are of no consequence + if (players[i].spectator) + continue; + + // Prevent splitscreen hosters/joiners from only adding 1 player at a time in empty servers (this will also catch yourself) + if (!players[i].jointime) + continue; + + // A ha! An established player! It's time to spectate + players[playernum].spectator = true; + break; + } +} + void G_BeginLevelExit(void) { if (g_exit.hasfinished) diff --git a/src/g_game.h b/src/g_game.h index b1b8bd3ea..2b282b72a 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -268,6 +268,7 @@ void G_AdjustViewEx(UINT8 viewnum, INT32 offset, boolean onlyactive, boolean res #define G_AdjustView(v,o,oa) G_AdjustViewEx(v,o,oa, true) void G_AddPlayer(INT32 playernum, INT32 console); +void G_SpectatePlayerOnJoin(INT32 playernum); void G_SetExitGameFlag(void); void G_ClearExitGameFlag(void); diff --git a/src/k_grandprix.c b/src/k_grandprix.c index 74e220d78..dc4443ac0 100644 --- a/src/k_grandprix.c +++ b/src/k_grandprix.c @@ -19,6 +19,7 @@ #include "k_bot.h" #include "k_kart.h" #include "m_random.h" +#include "p_local.h" #include "r_things.h" #include "lua_hook.h" #include "k_battle.h" @@ -343,10 +344,15 @@ void K_UpdateGrandPrixBots(void) { continue; } - + players[i].spectator = K_BotDefaultSpectator(); } + if (grandprixinfo.wonround == false) + { + return; + } + // Find the rival. for (i = 0; i < MAXGPPLAYERS; i++) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 6cf1672c8..1d8c80e19 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -56,6 +56,8 @@ #include "k_items.h" #include "k_waypoint.h" #include "k_grandprix.h" +#include "g_party.h" +#include "k_director.h" // BlanKart #include "blan/b_soc.h" @@ -12381,64 +12383,19 @@ void P_RespawnSpecials(void) // void P_SpawnPlayer(INT32 playernum) { - UINT8 i, pcount = 0; // MAXPLAYERS if exiting + UINT8 i; player_t *p = &players[playernum]; mobj_t *mobj; + boolean justjoined = (p->jointime <= 1); + if (p->playerstate == PST_REBORN) - G_PlayerReborn(playernum, false); + G_PlayerReborn(playernum, justjoined); - for (i = 0; i < MAXPLAYERS; i++) - { - if (i == playernum) - continue; - if (!playeringame[i] || players[i].spectator) - continue; - if (players[i].exiting) - { - pcount = MAXPLAYERS; - break; - } - if (players[i].jointime <= 1) // Prevent splitscreen hosters/joiners from only adding 1 player at a time in empty servers - continue; - pcount++; - } - - // spawn as spectator determination - if (multiplayer && demo.playback) - { - ; // Don't mess with spectator values since the demo setup handles them already. - } - else if (p->bot) - { - if (K_BotDefaultSpectator()) - { - // Bots should avoid - p->spectator = true; - p->pflags &= ~PF_WANTSTOJOIN; - } - else if (p->spectator) - { - // No point in a spectating bot! - p->spectator = false; - p->pflags |= PF_WANTSTOJOIN; - } - } - else if (netgame && p->jointime <= 1 && pcount) - { - p->spectator = true; - -#if 0 - if (pcount == 1 || leveltime < starttime) - p->pflags |= PF_WANTSTOJOIN; - p->jointime = 2; -#endif - p->spectatorreentry = 0; //(cv_spectatorreentry.value * TICRATE); - } - else if (multiplayer && !netgame) + if (G_GametypeHasTeams()) { // If you're in a team game and you don't have a team assigned yet... - if (G_GametypeHasTeams() && p->ctfteam == 0) + if (!p->spectator && p->ctfteam == 0) { changeteam_union NetPacket; UINT16 usvalue; @@ -12460,20 +12417,6 @@ void P_SpawnPlayer(INT32 playernum) usvalue = SHORT(NetPacket.value.l|NetPacket.value.b); SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); } - else // Otherwise, never spectator. - { - p->spectator = false; - } - } - - if (G_GametypeHasTeams()) - { - // Fix stupid non spectator spectators. - if (!p->spectator && !p->ctfteam) - { - p->spectator = true; - p->spectatorreentry = 0; //(cv_spectatorreentry.value * TICRATE); - } // Fix team colors. // This code isn't being done right somewhere else. Oh well. diff --git a/src/p_setup.c b/src/p_setup.c index d1459a6dd..0299740e2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -9253,7 +9253,7 @@ void P_PostLoadLevel(void) K_InitGrandPrixBots(); grandprixinfo.initalize = false; } - else// if (grandprixinfo.wonround == true) + else { K_UpdateGrandPrixBots(); grandprixinfo.wonround = false; diff --git a/src/p_user.c b/src/p_user.c index 97572e232..0b70e6fbf 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2695,10 +2695,6 @@ static void P_DeathThink(player_t *player) playerGone = true; } } - else if (player->bot && K_BotDefaultSpectator()) - { - playerGone = true; - } if (playerGone == false) {