From 726cd9757ba2e3ae68ad56c4a0989735606284ea Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 29 May 2017 21:23:00 +0100 Subject: [PATCH] Spectators in new Coop instead of staring at a dead screen all the time! Needs a bunch of changes to HUD rendering, especially in splitscreen, which doesn't try to show spectator stuff whatsoever. Also, if you're the player whose respawn determines when the map reloads, you'll see the spectator text during the front half of the fade. Unless, of course, it's 2-player mode. --- src/g_game.c | 15 ++---- src/p_enemy.c | 6 --- src/p_inter.c | 4 +- src/p_local.h | 1 + src/p_mobj.c | 7 ++- src/p_user.c | 126 ++++++++++++++++++++++++++----------------------- src/st_stuff.c | 8 +--- 7 files changed, 81 insertions(+), 86 deletions(-) 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."));