diff --git a/src/g_game.c b/src/g_game.c index 2ea0fe63f..273aa87c3 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2205,8 +2205,8 @@ void G_PlayerReborn(INT32 player) p->rings = 0; // 0 rings p->panim = PA_IDLE; // standing animation - if ((netgame || multiplayer) && !p->spectator) - p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent + //if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there + //p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent if (p-players == consoleplayer) { @@ -2597,16 +2597,11 @@ void G_DoReborn(INT32 playernum) INT32 i; for (i = 0; i < MAXPLAYERS; i++) { - if (!(playeringame[i] && players[i].playerstate == PST_LIVE)) + if (!playeringame[i]) continue; - if (players[i].spectator) // Ignore spectators - continue; - - if (players[i].bot) // ignore dumb, stupid tails - continue; - - break; + if (players[i].playerstate != PST_DEAD && !players[i].spectator && players[i].mo && players[i].mo->health) + break; } if (i == MAXPLAYERS) { diff --git a/src/p_enemy.c b/src/p_enemy.c index dca5024bc..b206a7c89 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3299,12 +3299,6 @@ void A_ExtraLife(mobj_t *actor) if (!playeringame[i]) continue; - if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators - continue; - - if (players[i].bot) - continue; - P_GivePlayerLives(&players[i], 1); P_PlayLivesJingle(&players[i]); } diff --git a/src/p_inter.c b/src/p_inter.c index 0e3d3f3d8..d0998eca2 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1309,8 +1309,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) players[i].starpostangle = special->angle; players[i].starpostnum = special->health; - if (cv_playstyle.value == 2 && (P_GetLives(&players[i]) || players[i].lives > 0) && players[i].playerstate == PST_DEAD) - players[i].playerstate = PST_REBORN; + if (cv_playstyle.value == 2 && (P_GetLives(&players[i]) || players[i].lives > 0) && (players[i].playerstate == PST_DEAD || players[i].spectator)) + P_SpectatorJoinGame(&players[i]); //players[i].playerstate = PST_REBORN; } } S_StartSound(NULL, special->info->painsound); diff --git a/src/p_local.h b/src/p_local.h index 117eaee1d..2cf6dbb98 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -199,6 +199,7 @@ void P_PlayLivesJingle(player_t *player); #define P_PlayVictorySound(s) S_StartSound(s, sfx_victr1 + P_RandomKey(4)); boolean P_GetLives(player_t *player); +boolean P_SpectatorJoinGame(player_t *player); // // P_MOBJ diff --git a/src/p_mobj.c b/src/p_mobj.c index 8820eac76..b8d850857 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9086,7 +9086,9 @@ void P_SpawnPlayer(INT32 playernum) { // Special case for (NiGHTS) special stages! // if stage has already started, force players to become spectators until the next stage - if (multiplayer && netgame && G_IsSpecialStage(gamemap) && useNightsSS && leveltime > 0) + if (((multiplayer || netgame) && leveltime > 0) + && ((G_IsSpecialStage(gamemap) && useNightsSS) + || (gametype == GT_COOP && cv_playstyle.value == 2 && (p->jointime < 1 || p->spectator)))) p->spectator = true; else p->spectator = false; @@ -9134,6 +9136,9 @@ void P_SpawnPlayer(INT32 playernum) p->skincolor = skincolor_blueteam; } + if ((netgame || multiplayer) && !p->spectator) + p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent + mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER); (mobj->player = p)->mo = mobj; diff --git a/src/p_user.c b/src/p_user.c index bd7b686dc..2045e8fea 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -946,12 +946,6 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings) if (!playeringame[i]) continue; - if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators - continue; - - if (players[i].bot) - continue; - P_GivePlayerLives(&players[i], gainlives); P_PlayLivesJingle(&players[i]); } @@ -8119,9 +8113,6 @@ boolean P_GetLives(player_t *player) if (!playeringame[i]) continue; - if (players[i].spectator) // Ignore spectators - continue; - if (players[i].lives > livescheck) { maxlivesplayer = i; @@ -8143,6 +8134,41 @@ boolean P_GetLives(player_t *player) return false; } +// +// P_ConsiderAllGone +// Shamelessly lifted from TD. Thanks, Sryder! +// + +static void P_ConsiderAllGone(void) +{ + INT32 i, lastdeadplayer = -1, deadtimercheck = INT32_MAX; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + if (players[i].playerstate != PST_DEAD && !players[i].spectator && players[i].mo && players[i].mo->health) + break; + + if (players[i].lives > 0) + { + if (players[i].spectator && lastdeadplayer == -1) + ; + else if (players[i].deadtimer < deadtimercheck) + deadtimercheck = players[i].deadtimer; + else + continue; + lastdeadplayer = i; + } + } + + if (i == MAXPLAYERS && lastdeadplayer != -1 && deadtimercheck > 2*TICRATE) // the last killed player will reset the level in G_DoReborn + { + players[lastdeadplayer].spectator = true; + players[lastdeadplayer].playerstate = PST_REBORN; + } +} + // // P_DeathThink // Fall on your face when dying. @@ -8173,17 +8199,11 @@ static void P_DeathThink(player_t *player) && (netgame || multiplayer) && (player->lives <= 0)) { - for (j = 0; j < MAXPLAYERS; j++) + for (; j < MAXPLAYERS; j++) { if (!playeringame[j]) continue; - if (players[j].spectator) // Ignore spectators - continue; - - if (players[j].bot) // ignore dumb, stupid tails - continue; - if (players[j].lives > 1) break; } @@ -8195,38 +8215,18 @@ static void P_DeathThink(player_t *player) else if ((player->lives > 0 || j != MAXPLAYERS) && !G_IsSpecialStage(gamemap)) // Don't allow "click to respawn" in special stages! { if (gametype == GT_COOP && (netgame || multiplayer) && cv_playstyle.value == 2) // Shamelessly lifted from TD. Thanks, Sryder! - { - INT32 i, lastdeadplayer = -1, deadtimercheck = INT32_MAX; - for (i = 0; i < MAXPLAYERS; i++) + P_ConsiderAllGone(); + if ((player->deadtimer > 5*TICRATE) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))) { - if (!playeringame[i]) - continue; - - if (players[i].spectator) // Ignore spectators - continue; - - if (players[i].bot) // ignore dumb, stupid tails - continue; - - if (players[i].playerstate != PST_DEAD) - break; - - if (players[i].lives && players[i].deadtimer < deadtimercheck) - { - lastdeadplayer = i; - deadtimercheck = players[i].deadtimer; - } + player->spectator = true; + player->playerstate = PST_REBORN; } - - if (i == MAXPLAYERS && lastdeadplayer != -1 && deadtimercheck > 2*TICRATE) // the last killed player will reset the level in G_DoReborn - players[lastdeadplayer].playerstate = PST_REBORN; - } else { // Respawn with jump button, force respawn time (3 second default, cheat protected) in shooter modes. if (cmd->buttons & BT_JUMP) { - if (player->spectator) + if (gametype != GT_COOP && player->spectator) player->playerstate = PST_REBORN; else switch(gametype) { case GT_COOP: @@ -8254,33 +8254,39 @@ static void P_DeathThink(player_t *player) } else if ((netgame || multiplayer) && player->deadtimer == 8*TICRATE) { + + INT32 i, deadtimercheck = INT32_MAX; + // In a net/multiplayer game, and out of lives if (gametype == GT_COMPETITION) { - INT32 i; - for (i = 0; i < MAXPLAYERS; i++) + { if (playeringame[i] && !players[i].exiting && players[i].lives) break; + if (players[i].deadtimer < deadtimercheck) + deadtimercheck = players[i].deadtimer; + } - if (i == MAXPLAYERS) + if (i == MAXPLAYERS && deadtimercheck == 8*TICRATE) { // Everyone's either done with the race, or dead. if (!countdown2 || countdown2 > 1*TICRATE) countdown2 = 1*TICRATE; } } - // In a coop game, and out of lives - if (gametype == GT_COOP) + else if (gametype == GT_COOP) { - INT32 i; - for (i = 0; i < MAXPLAYERS; i++) + { if (playeringame[i] && (players[i].exiting || players[i].lives)) break; + if (players[i].deadtimer < deadtimercheck) + deadtimercheck = players[i].deadtimer; + } - if (i == MAXPLAYERS) + if (i == MAXPLAYERS && deadtimercheck == 8*TICRATE) { // They're dead, Jim. //nextmapoverride = spstage_start; @@ -8991,16 +8997,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); } -static boolean P_SpectatorJoinGame(player_t *player) +boolean P_SpectatorJoinGame(player_t *player) { - if (!G_GametypeHasSpectators() && G_IsSpecialStage(gamemap) && useNightsSS) // Special Stage spectators should NEVER be allowed to rejoin the game - { - if (P_IsLocalPlayer(player)) - CONS_Printf(M_GetText("You cannot enter the game while a special stage is in progress.\n")); - player->powers[pw_flashing] += 2*TICRATE; //to prevent message spam. - } - - else if (!cv_allowteamchange.value) + if (gametype != GT_COOP && !cv_allowteamchange.value) { if (P_IsLocalPlayer(player)) CONS_Printf(M_GetText("Server does not allow team change.\n")); @@ -9088,7 +9087,8 @@ static boolean P_SpectatorJoinGame(player_t *player) if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) displayplayer = consoleplayer; - CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); + if (gametype != GT_COOP) + CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); return true; // no more player->mo, cannot continue. } else @@ -9401,6 +9401,8 @@ void P_PlayerThink(player_t *player) if (!player->spectator) P_PlayerInSpecialSector(player); + else if (gametype == GT_COOP && (netgame || multiplayer) && cv_playstyle.value == 2) + P_ConsiderAllGone(); if (player->playerstate == PST_DEAD) { @@ -9446,7 +9448,11 @@ void P_PlayerThink(player_t *player) player->realtime = leveltime; } - if ((netgame || splitscreen) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing]) + if ((netgame || splitscreen) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing] + && (G_GametypeHasSpectators() + || !((G_IsSpecialStage(gamemap) && useNightsSS) + || (gametype == GT_COOP && cv_playstyle.value == 2) + ))) { if (P_SpectatorJoinGame(player)) return; // player->mo was removed. diff --git a/src/st_stuff.c b/src/st_stuff.c index a9c563244..30b9bdb04 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -742,9 +742,6 @@ static void ST_drawLives(void) if (!playeringame[i]) continue; - if (players[i].spectator) // Ignore spectators - continue; - if (&players[i] == stplyr) continue; @@ -1862,9 +1859,6 @@ static void ST_overlayDrawer(void) if (!playeringame[i]) continue; - if (players[i].spectator) // Ignore spectators - continue; - if (&players[i] == stplyr) continue; @@ -1988,7 +1982,7 @@ static void ST_overlayDrawer(void) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to be assigned to a team.")); else if (G_IsSpecialStage(gamemap) && useNightsSS) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("You cannot join the game until the stage has ended.")); - else + else if (!gametype == GT_COOP) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Fire to enter the game.")); V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(148), V_HUDTRANSHALF, M_GetText("Press F12 to watch another player.")); V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(164), V_HUDTRANSHALF, M_GetText("Press Jump to float and Spin to sink."));