Merge branch 'prisons-death-fix' into 'master'

Fix Prisons death not ending the round + Spectator bool cleanup

See merge request KartKrew/Kart!1418
This commit is contained in:
toaster 2023-08-31 18:39:05 +00:00
commit f9a488defb
14 changed files with 164 additions and 201 deletions

View file

@ -3875,22 +3875,14 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
CONS_Debug(DBG_NETPLAY, "addplayer: %d %d\n", node, newplayernum);
{
// Clear player before joining, lest some things get set incorrectly
CL_ClearPlayer(newplayernum);
G_DestroyParty(newplayernum);
G_AddPlayer(newplayernum);
//G_SpectatePlayerOnJoin(newplayernum); -- caused desyncs in this spot :(
playeringame[newplayernum] = true;
G_AddPlayer(newplayernum);
if (newplayernum+1 > doomcom->numslots)
doomcom->numslots = (INT16)(newplayernum+1);
}
if (newplayernum+1 > doomcom->numslots)
doomcom->numslots = (INT16)(newplayernum+1);
newplayer = &players[newplayernum];
newplayer->jointime = 0;
READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME);
READMEM(*p, players[newplayernum].public_key, PUBKEYLENGTH);
READMEM(*p, clientpowerlevels[newplayernum], sizeof(((serverplayer_t *)0)->powerlevels));

View file

@ -1193,14 +1193,13 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
&& LUA_HookTeamSwitch(&players[playernum], 0, false, false, false)) // fiiiine, lua can except it
{
P_DamageMobj(players[playernum].mo, NULL, NULL, 1, DMG_SPECTATOR);
players[playernum].playerstate = PST_REBORN;
players[playernum].pflags &= ~PF_WANTSTOJOIN;
players[playernum].spectator = true;
if (players[i].spectator)
{
HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false);
HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false);
FinalisePlaystateChange(playernum);
FinalisePlaystateChange(playernum);
}
}
}
}
@ -3452,6 +3451,22 @@ static void Command_ServerTeamChange_f(void)
SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
}
void P_SetPlayerSpectator(INT32 playernum)
{
//Make sure you're in the right gametype.
if (!G_GametypeHasTeams() && !G_GametypeHasSpectators())
return;
// Don't duplicate efforts.
if (players[playernum].spectator)
return;
players[playernum].spectator = true;
players[playernum].pflags &= ~PF_WANTSTOJOIN;
players[playernum].playerstate = PST_REBORN;
}
//todo: This and the other teamchange functions are getting too long and messy. Needs cleaning.
static void Got_Teamchange(UINT8 **cp, INT32 playernum)
{
@ -3523,55 +3538,38 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal team change received from player %s\n"), player_names[playernum]);
SendKick(playernum, KICK_MSG_CON_FAIL);
return;
}
//Safety first!
// (not respawning spectators here...)
wasspectator = (players[playernum].spectator == true);
if (!wasspectator && gamestate == GS_LEVEL)
{
if (players[playernum].mo)
{
P_DamageMobj(players[playernum].mo, NULL, NULL, 1,
(NetPacket.packet.newteam ? DMG_INSTAKILL : DMG_SPECTATOR));
}
//else
if (!NetPacket.packet.newteam)
{
players[playernum].playerstate = PST_REBORN;
}
}
players[playernum].pflags &= ~PF_WANTSTOJOIN;
if (!wasspectator)
{
if (gamestate == GS_LEVEL && players[playernum].mo)
{
// The following will call P_SetPlayerSpectator if successful
P_DamageMobj(players[playernum].mo, NULL, NULL, 1, DMG_SPECTATOR);
}
//...but because the above could return early under some contexts, we try again here
P_SetPlayerSpectator(playernum);
}
//Now that we've done our error checking and killed the player
//if necessary, put the player on the correct team/status.
boolean nochangeoccourred = false;
if (NetPacket.packet.newteam != 0)
{
// This serves us in both teamchange contexts.
players[playernum].pflags |= PF_WANTSTOJOIN;
}
if (G_GametypeHasTeams())
{
if (!NetPacket.packet.newteam)
{
players[playernum].ctfteam = 0;
players[playernum].spectator = true;
}
else
{
players[playernum].ctfteam = NetPacket.packet.newteam;
players[playernum].pflags |= PF_WANTSTOJOIN; //players[playernum].spectator = false;
nochangeoccourred = true;
}
}
else if (G_GametypeHasSpectators())
{
if (!NetPacket.packet.newteam)
players[playernum].spectator = true;
else
{
players[playernum].pflags |= PF_WANTSTOJOIN; //players[playernum].spectator = false;
nochangeoccourred = true;
}
// This one is, of course, specific.
players[playernum].ctfteam = NetPacket.packet.newteam;
}
if (NetPacket.packet.autobalance)
@ -3599,20 +3597,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
else if (NetPacket.packet.newteam == 0 && !wasspectator)
HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false); // "entered the game" text was moved to P_SpectatorJoinGame
/*if (G_GametypeHasTeams())
{
if (NetPacket.packet.newteam)
{
UINT8 i;
for (i = 0; i <= splitscreen; i++)
{
if (playernum == g_localplayers[i]) //CTF and Team Match colors.
CV_SetValue(&cv_playercolor[i], NetPacket.packet.newteam + 5); - -this calculation is totally wrong
}
}
}*/
if (gamestate != GS_LEVEL || nochangeoccourred == true)
if (gamestate != GS_LEVEL || wasspectator == true)
return;
FinalisePlaystateChange(playernum);

View file

@ -245,6 +245,7 @@ void D_SetupVote(void);
void D_ModifyClientVote(UINT8 player, SINT8 voted);
void D_PickVote(void);
void ObjectPlace_OnChange(void);
void P_SetPlayerSpectator(INT32 playernum);
boolean IsPlayerAdmin(INT32 playernum);
void SetAdminPlayer(INT32 playernum);
void ClearAdminPlayers(void);

View file

@ -228,10 +228,7 @@ void G_ReadDemoExtraData(void)
{
if (!playeringame[p])
{
CL_ClearPlayer(p);
playeringame[p] = true;
G_AddPlayer(p);
players[p].spectator = true;
}
for (i = 0; i < MAXAVAILABILITY; i++)
@ -253,28 +250,34 @@ void G_ReadDemoExtraData(void)
switch (i) {
case DXD_PST_PLAYING:
if (players[p].bot)
if (players[p].spectator == true)
{
players[p].spectator = false;
}
else
{
players[p].pflags |= PF_WANTSTOJOIN;
if (players[p].bot)
{
players[p].spectator = false;
}
else
{
players[p].pflags |= PF_WANTSTOJOIN;
}
}
//CONS_Printf("player %s is despectating on tic %d\n", player_names[p], leveltime);
break;
case DXD_PST_SPECTATING:
players[p].pflags &= ~PF_WANTSTOJOIN; // double-fuck you
if (players[p].spectator != true)
if (players[p].spectator)
{
//CONS_Printf("player %s is spectating on tic %d\n", player_names[p], leveltime);
players[p].spectator = true;
if (players[p].mo)
P_DamageMobj(players[p].mo, NULL, NULL, 1, DMG_INSTAKILL);
else
players[p].playerstate = PST_REBORN;
players[p].pflags &= ~PF_WANTSTOJOIN;
}
else
{
if (players[p].mo)
{
P_DamageMobj(players[p].mo, NULL, NULL, 1, DMG_SPECTATOR);
}
P_SetPlayerSpectator(p);
}
break;
case DXD_PST_LEFT:
@ -3420,7 +3423,7 @@ void G_DoPlayDemo(const char *defdemoname)
if (!playeringame[displayplayers[0]] || players[displayplayers[0]].spectator)
displayplayers[0] = consoleplayer = serverplayer = p;
playeringame[p] = true;
G_AddPlayer(p);
players[p].spectator = spectator;
if (flags & DEMO_KICKSTART)

View file

@ -127,6 +127,8 @@ extern UINT8 demo_writerng;
#define DXD_COLOR 0x10 // color changed
#define DXD_FOLLOWER 0x20 // follower was changed
#define DXD_ADDPLAYER (DXD_JOINDATA|DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN|DXD_FOLLOWER)
#define DXD_WEAPONPREF 0x80 // netsynced playsim settings were changed
#define DXD_PST_PLAYING 0x01

View file

@ -2831,9 +2831,6 @@ void G_DoReborn(INT32 playernum)
{
player_t *player = &players[playernum];
// Make sure objectplace is OFF when you first start the level!
OP_ResetObjectplace();
{
// respawn at the start
mobj_t *oldmo = NULL;
@ -2854,11 +2851,53 @@ void G_DoReborn(INT32 playernum)
}
}
// These are the barest esentials.
// This func probably doesn't even need to know if the player is a bot.
void G_AddPlayer(INT32 playernum)
{
player_t *p = &players[playernum];
p->playerstate = PST_REBORN;
demo_extradata[playernum] |= DXD_JOINDATA|DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN|DXD_FOLLOWER; // Set everything
CL_ClearPlayer(playernum);
G_DestroyParty(playernum);
playeringame[playernum] = true;
player_t *newplayer = &players[playernum];
newplayer->playerstate = PST_REBORN;
newplayer->jointime = 0;
demo_extradata[playernum] |= DXD_ADDPLAYER;
}
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)
@ -3277,7 +3316,7 @@ boolean G_GametypeHasSpectators(void)
#ifdef DEVELOP
return true;
#endif
return (netgame || (multiplayer && demo.netgame));
return (netgame || (demo.playback && demo.netgame));
}
//

View file

@ -240,6 +240,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive);
void G_AdjustView(UINT8 viewnum, INT32 offset, boolean onlyactive);
void G_AddPlayer(INT32 playernum);
void G_SpectatePlayerOnJoin(INT32 playernum);
void G_SetExitGameFlag(void);
void G_ClearExitGameFlag(void);

View file

@ -127,10 +127,7 @@ void K_CheckBumpers(void)
{
if (nobumpers > 0 && nobumpers >= numingame)
{
// TODO: this would make a great debug feature for release
#ifndef DEVELOP
P_DoAllPlayersExit(PF_NOCONTEST, false);
#endif
return;
}
}
@ -142,9 +139,9 @@ void K_CheckBumpers(void)
if (numingame <= 1)
{
if ((gametyperules & GTR_PRISONS) && (K_CanChangeRules(true) == true))
if ((gametyperules & GTR_PRISONS) && !battleprisons && (K_CanChangeRules(true) == true))
{
// Reset map to turn on battle capsules
// Reset map to turn on battle prisons
if (server)
D_MapChange(gamemap, gametype, encoremode, true, 0, false, false);
}

View file

@ -47,12 +47,8 @@ void K_SetBot(UINT8 newplayernum, UINT8 skinnum, UINT8 difficulty, botStyle_e st
{
CONS_Debug(DBG_NETPLAY, "addbot: %d\n", newplayernum);
// Clear player before joining, lest some things get set incorrectly
CL_ClearPlayer(newplayernum);
G_DestroyParty(newplayernum);
playeringame[newplayernum] = true;
G_AddPlayer(newplayernum);
if (newplayernum+1 > doomcom->numslots)
doomcom->numslots = (INT16)(newplayernum+1);

View file

@ -201,7 +201,7 @@ void K_InitGrandPrixBots(void)
}
else
{
players[i].spectator = true; // force spectate for all other players, if they happen to exist?
P_SetPlayerSpectator(i); // force spectate for all other players, if they happen to exist?
}
}
}
@ -391,6 +391,11 @@ void K_UpdateGrandPrixBots(void)
players[i].spectator = !(gametyperules & GTR_BOTS) || (grandprixinfo.eventmode != GPEVENT_NONE);
}
if (grandprixinfo.wonround == false)
{
return;
}
// Find the rival.
for (i = 0; i < MAXPLAYERS; i++)
{

View file

@ -1556,7 +1556,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
P_PlayDeathSound(target);
}
if (K_Cooperative())
// Prisons Free Play: don't eliminate P1 for
// spectating. Because in Free Play, this player
// can enter the game again, and these flags would
// make them intangible.
if (K_Cooperative() && !target->player->spectator)
{
target->player->pflags |= PF_ELIMINATED;
@ -2052,35 +2056,34 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 type)
{
if (player->respawn.state != RESPAWNST_NONE)
if (type == DMG_SPECTATOR && (G_GametypeHasTeams() || G_GametypeHasSpectators()))
{
K_DoInstashield(player);
return false;
P_SetPlayerSpectator(player-players);
}
if (!player->exiting && (specialstageinfo.valid == true || modeattacking & ATTACKING_SPB))
else
{
// TODO: this would make a great debug feature for release
#ifdef DEVELOP
if (type != DMG_SPECTATOR)
if (player->respawn.state != RESPAWNST_NONE)
{
P_DoPlayerExit(player, PF_NOCONTEST);
K_DoInstashield(player);
return false;
}
if (player->exiting)
{
player->mo->destscale = 1;
player->mo->flags |= MF_NOCLIPTHING;
return false;
}
#else
P_DoPlayerExit(player, PF_NOCONTEST);
#endif
if (specialstageinfo.valid == true)
{
HU_DoTitlecardCEcho(player, "FALL OUT!", false);
P_DoPlayerExit(player, PF_NOCONTEST);
}
else if (modeattacking & ATTACKING_SPB)
{
P_DoPlayerExit(player, PF_NOCONTEST);
}
}
if (player->exiting)
{
player->mo->destscale = 1;
player->mo->flags |= MF_NOCLIPTHING;
return false;
}
switch (type)

View file

@ -11830,61 +11830,24 @@ 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, (p->jointime <= 1));
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++;
}
if (justjoined)
G_SpectatePlayerOnJoin(playernum);
// 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_PodiumSequence() == true)
; // This is too late to correct spectator status. Whatever state we're in at this point, our (dog) bed is made.
else if (!(gametyperules & GTR_BOTS)
|| (grandprixinfo.gp == true
&& grandprixinfo.eventmode != GPEVENT_NONE))
{
// Bots aren't supposed to be here.
p->spectator = true;
}
else
{
// No point in a spectating bot!
p->spectator = false;
}
}
else if (netgame && p->jointime <= 1 && pcount)
{
p->spectator = true;
}
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;
@ -11894,9 +11857,6 @@ void P_SpawnPlayer(INT32 playernum)
// yes even in splitscreen mode
p->spectator = true;
if (playernum&1) p->skincolor = skincolor_redteam;
else p->skincolor = skincolor_blueteam;
// but immediately send a team change packet.
NetPacket.packet.playernum = playernum;
NetPacket.packet.verification = true;
@ -11905,22 +11865,6 @@ void P_SpawnPlayer(INT32 playernum)
usvalue = SHORT(NetPacket.value.l|NetPacket.value.b);
SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
}
else // Otherwise, never spectator.
{
// TODO: this would make a great debug feature for release
#ifndef DEVELOP
p->spectator = false;
#endif
}
}
if (G_GametypeHasTeams())
{
// Fix stupid non spectator spectators.
if (!p->spectator && !p->ctfteam)
{
p->spectator = true;
}
// Fix team colors.
// This code isn't being done right somewhere else. Oh well.
@ -12019,8 +11963,7 @@ void P_SpawnPlayer(INT32 playernum)
S_StartSound(body, sfx_s1af);
}
// I'm not refactoring the loop at the top of this file.
pcount = 0;
UINT8 pcount = 0;
for (i = 0; i < MAXPLAYERS; ++i)
{

View file

@ -7835,6 +7835,9 @@ static void P_InitPlayers(void)
UINT8 i;
INT32 skin = -1;
// Make sure objectplace is OFF when you first start the level!
OP_ResetObjectplace();
// Are we forcing a character?
if (gametype == GT_TUTORIAL)
{
@ -7871,14 +7874,7 @@ static void P_InitPlayers(void)
// followercolor can be left alone for hopefully obvious reasons
}
if (!(gametyperules & GTR_CIRCUIT) && K_PodiumSequence() == false)
{
G_DoReborn(i);
}
else // gametype is race
{
G_SpawnPlayer(i);
}
G_SpawnPlayer(i);
players[i].xtralife = 0; // extra lives do not ever carry over from the previous round
}
@ -8559,7 +8555,7 @@ void P_PostLoadLevel(void)
K_InitGrandPrixBots();
grandprixinfo.initalize = false;
}
else if (grandprixinfo.wonround == true)
else
{
K_UpdateGrandPrixBots();
grandprixinfo.wonround = false;

View file

@ -3509,7 +3509,7 @@ boolean P_SpectatorJoinGame(player_t *player)
// Pressing fire assigns you to a team that needs players if allowed.
// Partial code reproduction from p_tick.c autobalance code.
// a surprise tool that will help us later...
if (G_GametypeHasTeams())
if (G_GametypeHasTeams() && player->ctfteam == 0)
{
INT32 z, numplayersred = 0, numplayersblue = 0;