diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f08c7554..aa28524a 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2522,18 +2522,12 @@ static void Command_Teamchange_f(void) return; } - if (G_GametypeHasTeams()) - { - if (NetPacket.packet.newteam == (unsigned)players[consoleplayer].ctfteam || - (players[consoleplayer].spectator && !NetPacket.packet.newteam)) - error = true; - } - else if (G_GametypeHasSpectators()) - { - if ((players[consoleplayer].spectator && !NetPacket.packet.newteam) || - (!players[consoleplayer].spectator && NetPacket.packet.newteam == 3)) - error = true; - } + if (players[consoleplayer].spectator && !(players[consoleplayer].pflags & PF_WANTSTOJOIN) && !NetPacket.packet.newteam) + error = true; + else if (G_GametypeHasTeams() && NetPacket.packet.newteam == (unsigned)players[consoleplayer].ctfteam) + error = true; + else if (G_GametypeHasSpectators() && !players[consoleplayer].spectator && NetPacket.packet.newteam == 3) + error = true; #ifdef PARANOIA else I_Error("Invalid gametype after initial checks!"); @@ -2619,18 +2613,12 @@ static void Command_Teamchange2_f(void) return; } - if (G_GametypeHasTeams()) - { - if (NetPacket.packet.newteam == (unsigned)players[secondarydisplayplayer].ctfteam || - (players[secondarydisplayplayer].spectator && !NetPacket.packet.newteam)) - error = true; - } - else if (G_GametypeHasSpectators()) - { - if ((players[secondarydisplayplayer].spectator && !NetPacket.packet.newteam) || - (!players[secondarydisplayplayer].spectator && NetPacket.packet.newteam == 3)) - error = true; - } + if (players[secondarydisplayplayer].spectator && !(players[secondarydisplayplayer].pflags & PF_WANTSTOJOIN) && !NetPacket.packet.newteam) + error = true; + else if (G_GametypeHasTeams() && NetPacket.packet.newteam == (unsigned)players[secondarydisplayplayer].ctfteam) + error = true; + else if (G_GametypeHasSpectators() && !players[secondarydisplayplayer].spectator && NetPacket.packet.newteam == 3) + error = true; #ifdef PARANOIA else I_Error("Invalid gametype after initial checks!"); @@ -2716,18 +2704,12 @@ static void Command_Teamchange3_f(void) return; } - if (G_GametypeHasTeams()) - { - if (NetPacket.packet.newteam == (unsigned)players[thirddisplayplayer].ctfteam || - (players[thirddisplayplayer].spectator && !NetPacket.packet.newteam)) - error = true; - } - else if (G_GametypeHasSpectators()) - { - if ((players[thirddisplayplayer].spectator && !NetPacket.packet.newteam) || - (!players[thirddisplayplayer].spectator && NetPacket.packet.newteam == 3)) - error = true; - } + if (players[thirddisplayplayer].spectator && !(players[thirddisplayplayer].pflags & PF_WANTSTOJOIN) && !NetPacket.packet.newteam) + error = true; + else if (G_GametypeHasTeams() && NetPacket.packet.newteam == (unsigned)players[thirddisplayplayer].ctfteam) + error = true; + else if (G_GametypeHasSpectators() && !players[thirddisplayplayer].spectator && NetPacket.packet.newteam == 3) + error = true; #ifdef PARANOIA else I_Error("Invalid gametype after initial checks!"); @@ -2813,18 +2795,12 @@ static void Command_Teamchange4_f(void) return; } - if (G_GametypeHasTeams()) - { - if (NetPacket.packet.newteam == (unsigned)players[fourthdisplayplayer].ctfteam || - (players[fourthdisplayplayer].spectator && !NetPacket.packet.newteam)) - error = true; - } - else if (G_GametypeHasSpectators()) - { - if ((players[fourthdisplayplayer].spectator && !NetPacket.packet.newteam) || - (!players[fourthdisplayplayer].spectator && NetPacket.packet.newteam == 3)) - error = true; - } + if (players[fourthdisplayplayer].spectator && !(players[fourthdisplayplayer].pflags & PF_WANTSTOJOIN) && !NetPacket.packet.newteam) + error = true; + else if (G_GametypeHasTeams() && NetPacket.packet.newteam == (unsigned)players[fourthdisplayplayer].ctfteam) + error = true; + else if (G_GametypeHasSpectators() && !players[fourthdisplayplayer].spectator && NetPacket.packet.newteam == 3) + error = true; #ifdef PARANOIA else I_Error("Invalid gametype after initial checks!"); @@ -3024,24 +3000,23 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } // Prevent multiple changes in one go. - if (G_TagGametype()) + if (players[playernum].spectator && !(players[playernum].pflags & PF_WANTSTOJOIN) && !NetPacket.packet.newteam) + return; + else if (G_TagGametype()) { if (((players[playernum].pflags & PF_TAGIT) && NetPacket.packet.newteam == 1) || (!(players[playernum].pflags & PF_TAGIT) && NetPacket.packet.newteam == 2) || - (players[playernum].spectator && NetPacket.packet.newteam == 0) || (!players[playernum].spectator && NetPacket.packet.newteam == 3)) return; } else if (G_GametypeHasTeams()) { - if ((NetPacket.packet.newteam && (NetPacket.packet.newteam == (unsigned)players[playernum].ctfteam)) || - (players[playernum].spectator && !NetPacket.packet.newteam)) + if (NetPacket.packet.newteam && (NetPacket.packet.newteam == (unsigned)players[playernum].ctfteam)) return; } else if (G_GametypeHasSpectators()) { - if ((players[playernum].spectator && !NetPacket.packet.newteam) || - (!players[playernum].spectator && NetPacket.packet.newteam == 3)) + if (!players[playernum].spectator && NetPacket.packet.newteam == 3) return; } else @@ -3113,19 +3088,26 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } //Safety first! - if (players[playernum].mo) + // (not respawning spectators here...) + if (!players[playernum].spectator) { - if (!players[playernum].spectator) - P_DamageMobj(players[playernum].mo, NULL, NULL, 10000); - /*else + if (players[playernum].mo) { - P_RemoveMobj(players[playernum].mo); - players[playernum].mo = NULL; + //if (!players[playernum].spectator) + P_DamageMobj(players[playernum].mo, NULL, NULL, 10000); + /*else + { + if (players[playernum].mo) + { + P_RemoveMobj(players[playernum].mo); + players[playernum].mo = NULL; + } + players[playernum].playerstate = PST_REBORN; + }*/ + } + else players[playernum].playerstate = PST_REBORN; - }*/ } - else - players[playernum].playerstate = PST_REBORN; //Now that we've done our error checking and killed the player //if necessary, put the player on the correct team/status. @@ -3210,6 +3192,8 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) } else if (NetPacket.packet.newteam == 3) /*CONS_Printf(M_GetText("%s entered the game.\n"), player_names[playernum])*/; + else if (players[playernum].pflags & PF_WANTSTOJOIN) + players[playernum].pflags &= ~PF_WANTSTOJOIN; else CONS_Printf(M_GetText("%s became a spectator.\n"), player_names[playernum]); diff --git a/src/g_game.c b/src/g_game.c index cfd845d7..beb40ba5 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2175,7 +2175,9 @@ void G_Ticker(boolean run) if (run) { - if (G_GametypeHasSpectators() && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING)) + if (G_GametypeHasSpectators() + && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING // definitely good + || gamestate == GS_WAITINGPLAYERS)) // definitely a problem if we don't do it at all in this gamestate, but might need more protection? K_CheckSpectateStatus(); if (pausedelay) diff --git a/src/k_kart.c b/src/k_kart.c index a0ace271..308435f2 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1133,6 +1133,9 @@ void K_RespawnChecker(player_t *player) { ticcmd_t *cmd = &player->cmd; + if (player->spectator) + return; + if (player->kartstuff[k_respawn] > 3) { player->kartstuff[k_respawn]--; @@ -4058,40 +4061,65 @@ void K_CheckBumpers(void) void K_CheckSpectateStatus(void) { UINT8 respawnlist[MAXPLAYERS]; - UINT8 i, no = 0; - UINT8 numingame = 0; + UINT8 i, numingame = 0, numjoiners = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; + // Get the number of players in game, and the players to be de-spectated. + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; - if (!players[i].spectator) - { + if (!players[i].spectator) + { numingame++; if (gamestate != GS_LEVEL) continue; if (numingame < 2) continue; - if (G_RaceGametype() && players[i].laps > 0) + if (G_RaceGametype() && players[i].laps) return; - } + continue; + } + else if (!(players[i].pflags & PF_WANTSTOJOIN)) + continue; - if (cv_allowteamchange.value && !(players[i].pflags & PF_WANTSTOJOIN)) - continue; + respawnlist[numjoiners++] = i; + } - respawnlist[no++] = i; - } + // literally zero point in going any further if nobody is joining + if (!numjoiners) + return; + + // Check if there are any conditions that should prevent de-spectating. + // WHAT? NO, you just made it loop again, what's the point?!! + /*if ((gamestate == GS_LEVEL) && (numingame > 1)) + { + // If anyone's on lap two or up in a race gametype, HALT. + if (G_RaceGametype()) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].laps) + continue; + + return; + } + } + }*/ // Reset the match if you're in an empty server - if (gamestate == GS_LEVEL && (numingame < 2 && numingame+no >= 2)) + if (gamestate == GS_LEVEL && (numingame < 2 && numingame+numjoiners >= 2)) { CONS_Printf("Here comes a new challenger! Resetting map in 10 seconds...\n"); mapreset = 10*TICRATE; // Even though only the server uses this for game logic, set for everyone for HUD in the future } - while (no) - P_SpectatorJoinGame(&players[respawnlist[--no]]); + // Finally, we can de-spectate everyone! + for (i = 0; i < numjoiners; i++) + P_SpectatorJoinGame(&players[respawnlist[i]]); } //} diff --git a/src/m_menu.c b/src/m_menu.c index a88ddfbd..48857e20 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -535,6 +535,7 @@ static menuitem_t MPauseMenu[] = {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48}, {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48}, + {IT_STRING | IT_CALL, NULL, "Cancel Join", M_ConfirmSpectate, 48}, {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48}, {IT_CALL | IT_STRING, NULL, "Player Setup...", M_SetupMultiPlayer, 56}, // alone {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64}, @@ -557,6 +558,7 @@ typedef enum #endif mpause_spectate, mpause_entergame, + mpause_canceljoin, mpause_switchteam, mpause_psetup, mpause_options, @@ -2842,6 +2844,7 @@ void M_StartControlPanel(void) #endif MPauseMenu[mpause_spectate].status = IT_DISABLED; MPauseMenu[mpause_entergame].status = IT_DISABLED; + MPauseMenu[mpause_canceljoin].status = IT_DISABLED; MPauseMenu[mpause_switchteam].status = IT_DISABLED; MPauseMenu[mpause_psetup].status = IT_DISABLED; // Reset these in case splitscreen messes things up @@ -2889,7 +2892,14 @@ void M_StartControlPanel(void) if (G_GametypeHasTeams()) MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU; else if (G_GametypeHasSpectators()) - MPauseMenu[((&players[consoleplayer] && players[consoleplayer].spectator) ? mpause_entergame : mpause_spectate)].status = IT_STRING | IT_CALL; + { + if (!players[consoleplayer].spectator) + MPauseMenu[mpause_spectate].status = IT_STRING | IT_CALL; + else if (players[consoleplayer].pflags & PF_WANTSTOJOIN) + MPauseMenu[mpause_canceljoin].status = IT_STRING | IT_CALL; + else + MPauseMenu[mpause_entergame].status = IT_STRING | IT_CALL; + } else // in this odd case, we still want something to be on the menu even if it's useless MPauseMenu[mpause_spectate].status = IT_GRAYEDOUT; } @@ -4207,11 +4217,11 @@ static void M_ConfirmSpectate(INT32 choice) static void M_ConfirmEnterGame(INT32 choice) { (void)choice; - if (!cv_allowteamchange.value) + /*if (!cv_allowteamchange.value) { M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\nPress a key.\n"), NULL, MM_NOTHING); return; - } + }*/ M_ClearMenus(true); COM_ImmedExecute("changeteam playing"); } diff --git a/src/p_mobj.c b/src/p_mobj.c index e9603c43..6ee05e57 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9830,8 +9830,12 @@ void P_SpawnPlayer(INT32 playernum) // spawn as spectator determination if (!G_GametypeHasSpectators()) p->spectator = false; - else if (netgame && p->jointime <= 1 && pcount > 1) + else if (netgame && p->jointime <= 1 && pcount) + { p->spectator = true; + if (pcount == 1) + p->pflags |= PF_WANTSTOJOIN; + } else if (multiplayer && !netgame) { // If you're in a team game and you don't have a team assigned yet... @@ -9912,41 +9916,35 @@ void P_SpawnPlayer(INT32 playernum) overheadarrow->flags2 |= MF2_DONTDRAW; P_SetScale(overheadarrow, mobj->destscale); - if (p->spectator) // HEY! No being cheap... + if (p->spectator && pcount > 1) // HEY! No being cheap... p->kartstuff[k_bumper] = 0; else if (p->kartstuff[k_bumper] > 0 || leveltime < 1 || (p->jointime <= 1 && pcount <= 1)) { - INT32 i; - angle_t newangle; - angle_t diff; - fixed_t newx; - fixed_t newy; - mobj_t *mo; - if (leveltime < 1 || (p->jointime <= 1 && pcount <= 1)) // Start of the map? p->kartstuff[k_bumper] = cv_kartbumpers.value; // Reset those bumpers! - if (p->kartstuff[k_bumper] <= 1) - diff = 0; - else - diff = FixedAngle(360*FRACUNIT/p->kartstuff[k_bumper]); - - newangle = mobj->angle; - newx = mobj->x + P_ReturnThrustX(mobj, newangle + ANGLE_180, 64*FRACUNIT); - newy = mobj->y + P_ReturnThrustY(mobj, newangle + ANGLE_180, 64*FRACUNIT); - - for (i = 0; i < p->kartstuff[k_bumper]; i++) + if (p->kartstuff[k_bumper]) { - mo = P_SpawnMobj(newx, newy, mobj->z, MT_BATTLEBUMPER); - mo->threshold = i; - P_SetTarget(&mo->target, mobj); - mo->angle = (diff * (i-1)); - mo->color = mobj->color; - if (mobj->flags2 & MF2_DONTDRAW) - mo->flags2 |= MF2_DONTDRAW; - else - mo->flags2 &= ~MF2_DONTDRAW; + INT32 i; + angle_t diff = FixedAngle(360*FRACUNIT/p->kartstuff[k_bumper]); + angle_t newangle = mobj->angle; + fixed_t newx = mobj->x + P_ReturnThrustX(mobj, newangle + ANGLE_180, 64*FRACUNIT); + fixed_t newy = mobj->y + P_ReturnThrustY(mobj, newangle + ANGLE_180, 64*FRACUNIT); + mobj_t *mo; + + for (i = 0; i < p->kartstuff[k_bumper]; i++) + { + mo = P_SpawnMobj(newx, newy, mobj->z, MT_BATTLEBUMPER); + mo->threshold = i; + P_SetTarget(&mo->target, mobj); + mo->angle = (diff * (i-1)); + mo->color = mobj->color; + if (mobj->flags2 & MF2_DONTDRAW) + mo->flags2 |= MF2_DONTDRAW; + else + mo->flags2 &= ~MF2_DONTDRAW; + } } } else if (p->kartstuff[k_bumper] <= 0) diff --git a/src/p_user.c b/src/p_user.c index 03ea25a4..fc98c4b9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8812,7 +8812,7 @@ boolean P_SpectatorJoinGame(player_t *player) { if (P_IsLocalPlayer(player)) CONS_Printf(M_GetText("Server does not allow team change.\n")); - player->powers[pw_flashing] = 2*TICRATE; //to prevent message spam. + //player->powers[pw_flashing] = TICRATE + 1; //to prevent message spam. } // Team changing in Team Match and CTF // Pressing fire assigns you to a team that needs players if allowed. @@ -9301,7 +9301,7 @@ void P_PlayerThink(player_t *player) if ((netgame || splitscreen) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing]) { player->pflags ^= PF_WANTSTOJOIN; - player->powers[pw_flashing] = 2*TICRATE; + //player->powers[pw_flashing] = TICRATE + 1; /*if (P_SpectatorJoinGame(player)) return; // player->mo was removed.*/ }