Fix weird visual artifacting caused by restarting the level in co-op, which was a direct result of my code being messy. This is significantly better to deal with, anyways.

This commit is contained in:
toasterbabe 2017-07-03 15:43:29 +01:00
parent ca76dd41f8
commit 50496970d1
6 changed files with 88 additions and 135 deletions

View File

@ -891,6 +891,7 @@ static inline void resynch_write_others(resynchend_pak *rst)
UINT8 i;
rst->ingame = 0;
rst->outofcoop = 0;
for (i = 0; i < MAXPLAYERS; ++i)
{
@ -907,6 +908,8 @@ static inline void resynch_write_others(resynchend_pak *rst)
if (!players[i].spectator)
rst->ingame |= (1<<i);
if (players[i].outofcoop)
rst->outofcoop |= (1<<i);
rst->ctfteam[i] = (INT32)LONG(players[i].ctfteam);
rst->score[i] = (UINT32)LONG(players[i].score);
rst->numboxes[i] = SHORT(players[i].numboxes);
@ -923,11 +926,13 @@ static inline void resynch_read_others(resynchend_pak *p)
{
UINT8 i;
UINT32 loc_ingame = (UINT32)LONG(p->ingame);
UINT32 loc_outofcoop = (UINT32)LONG(p->outofcoop);
for (i = 0; i < MAXPLAYERS; ++i)
{
// We don't care if they're in the game or not, just write all the data.
players[i].spectator = !(loc_ingame & (1<<i));
players[i].outofcoop = (loc_outofcoop & (1<<i));
players[i].ctfteam = (INT32)LONG(p->ctfteam[i]); // no, 0 does not mean spectator, at least not in Match
players[i].score = (UINT32)LONG(p->score[i]);
players[i].numboxes = SHORT(p->numboxes[i]);

View File

@ -136,6 +136,7 @@ typedef struct
fixed_t flagz[2];
UINT32 ingame; // Spectator bit for each player
UINT32 outofcoop; // outofcoop bit for each player
INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams)
// Resynch game scores and the like all at once

View File

@ -471,6 +471,7 @@ typedef struct player_s
angle_t awayviewaiming; // Used for cut-away view
boolean spectator;
boolean outofcoop;
UINT8 bot;
tic_t jointime; // Timer when player joins game to change skin/color

View File

@ -2090,6 +2090,7 @@ void G_PlayerReborn(INT32 player)
UINT32 availabilities;
tic_t jointime;
boolean spectator;
boolean outofcoop;
INT16 bot;
SINT8 pity;
@ -2100,6 +2101,7 @@ void G_PlayerReborn(INT32 player)
exiting = players[player].exiting;
jointime = players[player].jointime;
spectator = players[player].spectator;
outofcoop = players[player].outofcoop;
pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE));
// As long as we're not in multiplayer, carry over cheatcodes from map to map
@ -2154,6 +2156,7 @@ void G_PlayerReborn(INT32 player)
p->ctfteam = ctfteam;
p->jointime = jointime;
p->spectator = spectator;
p->outofcoop = outofcoop;
// save player config truth reborn
p->skincolor = skincolor;
@ -2489,26 +2492,13 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
}
}
#ifdef HAVE_BLUA
#define RESETMAP {\
LUAh_MapChange();\
G_DoLoadLevel(true);\
return;\
}
#else
#define RESETMAP {\
G_DoLoadLevel(true);\
return;\
}
#endif
//
// G_DoReborn
//
void G_DoReborn(INT32 playernum)
{
player_t *player = &players[playernum];
boolean starpost = false;
boolean resetlevel = false;
if (modeattacking)
{
@ -2534,8 +2524,64 @@ void G_DoReborn(INT32 playernum)
B_RespawnBot(playernum);
if (oldmo)
G_ChangePlayerReferences(oldmo, players[playernum].mo);
return;
}
else if (countdowntimeup || (!multiplayer && gametype == GT_COOP))
if (countdowntimeup || (!multiplayer && gametype == GT_COOP))
resetlevel = true;
else if (gametype == GT_COOP && (netgame || multiplayer))
{
INT32 i;
if (player->lives <= 0) // consider game over first
{
INT32 deadtimercheck = INT32_MAX;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (players[i].exiting || players[i].lives > 0)
break;
if (players[i].playerstate == PST_DEAD && players[i].deadtimer < deadtimercheck)
deadtimercheck = players[i].deadtimer;
}
if (!countdown2 && i == MAXPLAYERS && deadtimercheck >= 8*TICRATE)
{
// They're dead, Jim.
//nextmapoverride = spstage_start;
nextmapoverride = gamemap;
countdown2 = TICRATE;
skipstats = true;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
players[i].score = 0;
}
//emeralds = 0;
tokenbits = 0;
tokenlist = 0;
token = 0;
}
}
if (cv_coopstarposts.value == 2)
{
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 (i == MAXPLAYERS)
resetlevel = true;
}
}
if (resetlevel)
{
// reload the level from scratch
if (countdowntimeup)
@ -2557,9 +2603,6 @@ void G_DoReborn(INT32 playernum)
// Do a wipe
wipegamestate = -1;
if (player->starposttime)
starpost = true;
if (camera.chase)
P_ResetCamera(&players[displayplayer], &camera);
if (camera2.chase && splitscreen)
@ -2579,7 +2622,7 @@ void G_DoReborn(INT32 playernum)
CON_ClearHUD();
// Starpost support
G_SpawnPlayer(playernum, starpost);
G_SpawnPlayer(playernum, (player->starposttime));
if (botingame)
{ // Bots respawn next to their master.
@ -2588,123 +2631,25 @@ void G_DoReborn(INT32 playernum)
}
}
else
RESETMAP;
{
#ifdef HAVE_BLUA
LUAh_MapChange();
#endif
G_DoLoadLevel(true);
return;
}
}
else
{
// respawn at the start
mobj_t *oldmo = NULL;
if (gametype == GT_COOP && (netgame || multiplayer))
{
INT32 i;
if (player->lives <= 0) // consider game over first
{
INT32 deadtimercheck = INT32_MAX;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (players[i].exiting || players[i].lives > 0)
break;
if (players[i].playerstate == PST_DEAD && players[i].deadtimer < deadtimercheck)
deadtimercheck = players[i].deadtimer;
}
if (!countdown2 && i == MAXPLAYERS && deadtimercheck >= 8*TICRATE)
{
// They're dead, Jim.
//nextmapoverride = spstage_start;
nextmapoverride = gamemap;
countdown2 = TICRATE;
skipstats = true;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
players[i].score = 0;
}
//emeralds = 0;
tokenbits = 0;
tokenlist = 0;
token = 0;
}
}
if (cv_coopstarposts.value == 2)
{
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 (i == MAXPLAYERS)
{
if (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD)
{
INT32 j;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
players[i].playerstate = PST_REBORN;
}
P_LoadThingsOnly();
P_ClearStarPost(player->starpostnum);
// Do a wipe
wipegamestate = -1;
if (camera.chase)
P_ResetCamera(&players[displayplayer], &camera);
if (camera2.chase && splitscreen)
P_ResetCamera(&players[secondarydisplayplayer], &camera2);
// clear cmd building stuff
memset(gamekeydown, 0, sizeof (gamekeydown));
for (j = 0; j < JOYAXISSET; j++)
{
joyxmove[j] = joyymove[j] = 0;
joy2xmove[j] = joy2ymove[j] = 0;
}
mousex = mousey = 0;
mouse2x = mouse2y = 0;
// clear hud messages remains (usually from game startup)
CON_ClearHUD();
// Starpost support
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
G_SpawnPlayer(i, (players[i].starposttime != 0));
}
return;
}
else
RESETMAP;
}
}
}
// Not resetting map, so return to level music
if (!countdown2
&& player->lives <= 0
&& !cv_cooplives.value) // not allowed for life steal because no way to come back from zero group lives without addons, which should call this anyways
P_RestoreMultiMusic(player);
if (player->starposttime)
starpost = true;
// first dissasociate the corpse
if (player->mo)
{
@ -2713,7 +2658,7 @@ void G_DoReborn(INT32 playernum)
P_RemoveMobj(player->mo);
}
G_SpawnPlayer(playernum, starpost);
G_SpawnPlayer(playernum, (player->starposttime));
if (oldmo)
G_ChangePlayerReferences(oldmo, players[playernum].mo);
}

View File

@ -9099,14 +9099,12 @@ void P_SpawnPlayer(INT32 playernum)
// spawn as spectator determination
if (!G_GametypeHasSpectators())
{
if (((multiplayer || netgame) && gametype == GT_COOP) // only question status in coop
p->spectator = p->outofcoop =
(((multiplayer || netgame) && gametype == GT_COOP) // only question status in coop
&& ((leveltime > 0
&& ((G_IsSpecialStage(gamemap) && useNightsSS) // late join special stage
|| (cv_coopstarposts.value == 2 && (p->jointime < 1 || p->spectator)))) // late join or die in new coop
|| ((!cv_cooplives.value || !P_GetLives(p)) && p->lives <= 0))) // game over and can't redistribute lives
p->spectator = true;
else
p->spectator = false;
|| (cv_coopstarposts.value == 2 && (p->jointime < 1 || p->outofcoop)))) // late join or die in new coop
|| ((!cv_cooplives.value || !P_GetLives(p)) && p->lives <= 0))); // game over and can't redistribute lives
}
else if (netgame && p->jointime < 1)
p->spectator = true;

View File

@ -8214,7 +8214,8 @@ static void P_ConsiderAllGone(void)
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].spectator = true;
players[lastdeadplayer].outofcoop = true;
players[lastdeadplayer].playerstate = PST_REBORN;
}
}
@ -8287,7 +8288,8 @@ static void P_DeathThink(player_t *player)
P_ConsiderAllGone();
if ((player->deadtimer > 5*TICRATE) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE)))
{
player->spectator = true;
//player->spectator = true;
player->outofcoop = true;
player->playerstate = PST_REBORN;
}
}
@ -8352,7 +8354,8 @@ static void P_DeathThink(player_t *player)
if (gametype == GT_COOP && (player->lives <= 0) && (player->deadtimer >= 8*TICRATE || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))))
{
player->spectator = true;
//player->spectator = true;
player->outofcoop = true;
player->playerstate = PST_REBORN;
}
@ -9099,7 +9102,7 @@ boolean P_SpectatorJoinGame(player_t *player)
P_RemoveMobj(player->mo);
player->mo = NULL;
}
player->spectator = false;
player->spectator = player->outofcoop = false;
player->playerstate = PST_REBORN;
if (gametype == GT_TAG)