* Make cancelling a join work on the pause menu and console. (You need to write "changeteam spectator" to cancel a PF_WANTSTOJOIN.)

* Stop respawning spectators when their PF_WANTSTOJOIN request hasn't been processed yet.
* Handle PF_WANTSTOJOIN requests in GS_WAITINGPLAYERS.
* Refactor K_CheckSpectateStatus, and make it so PF_WANTSTOJOIN requests are processed if there's only one player in the server, even if they're on lap 2 or up.
* Make the player entry mechanism in P_SpawnPlayer use the PF_WANTSTOJOIN mechanism so that it can also take advantage of the level refresh mechanism with no extra code.
	* NOTE: This does a bad hack in order to not send multiple mapchanges while the joining timer is low! If you can think of a better way to do this, please let me know/commit it.
* Change the timer until you can hit ITEM again when a spectator who has to wait to join shorter.
* (controversial, but I think necessary) - flash the ITEM text when the above-mentioned timer is nonzero.
This commit is contained in:
toaster 2018-07-21 16:45:08 +01:00
parent 75f339f6c1
commit b818c8a2cf
7 changed files with 136 additions and 118 deletions

View File

@ -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]);

View File

@ -2174,7 +2174,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)

View File

@ -4057,33 +4057,54 @@ void K_CheckBumpers(void)
void K_CheckSpectateStatus(void)
{
UINT8 respawnlist[MAXPLAYERS];
UINT8 i, no = 0;
UINT8 numingame = 0, numjoiners = 0;
UINT8 i, numingame = 0, numjoiners = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (!cv_allowteamchange.value)
return;
if (!players[i].spectator)
{
// 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)
{
numingame++;
if (gamestate != GS_LEVEL)
continue;
if (G_RaceGametype() && players[i].laps > 0)
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;
numjoiners = no; // Move the map change stuff up here when it gets a delay, and remove this redundant numjoiners var
// Check if there are any conditions that should prevent de-spectating.
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;
while (no)
P_SpectatorJoinGame(&players[respawnlist[--no]]);
if (!players[i].laps)
continue;
return;
}
}
}
// Finally, we can de-spectate everyone!
for (i = 0; i < numjoiners; i++)
P_SpectatorJoinGame(&players[respawnlist[i]]);
if (!server)
return;

View File

@ -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");
}

View File

@ -9830,8 +9830,13 @@ 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;
p->jointime = 2; // HACK???????
}
else if (multiplayer && !netgame)
{
// If you're in a team game and you don't have a team assigned yet...
@ -9912,41 +9917,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)

View File

@ -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.*/
}

View File

@ -1952,7 +1952,9 @@ static void ST_overlayDrawer(void)
{
// SRB2kart: changed positions & text
V_DrawString(2, BASEVIDHEIGHT-50, V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -"));
if (stplyr->pflags & PF_WANTSTOJOIN)
if (stplyr->powers[pw_flashing] & 1)
;
else if (stplyr->pflags & PF_WANTSTOJOIN)
V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF, M_GetText("Item - Cancel Join"));
/*else if (G_GametypeHasTeams())
V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF, M_GetText("Item - Join Team"));*/