diff --git a/src/g_game.c b/src/g_game.c index 273aa87c3..a3eb8d6c1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2592,68 +2592,104 @@ void G_DoReborn(INT32 playernum) // respawn at the start mobj_t *oldmo = NULL; - if (gametype == GT_COOP && (netgame || multiplayer) && cv_playstyle.value == 2) + if (gametype == GT_COOP && (netgame || multiplayer)) { INT32 i; - for (i = 0; i < MAXPLAYERS; i++) + if (player->lives <= 0) // consider game over first { - 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 deadtimercheck = INT32_MAX; + for (i = 0; i < MAXPLAYERS; i++) { - 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; + if (!playeringame[i]) + continue; + if (players[i].exiting || players[i].lives) + break; + if (players[i].playerstate == PST_DEAD && players[i].deadtimer < deadtimercheck) + deadtimercheck = players[i].deadtimer; + } + + if (i == MAXPLAYERS && deadtimercheck >= 8*TICRATE) + { + // They're dead, Jim. + //nextmapoverride = spstage_start; + nextmapoverride = gamemap; + countdown2 = 1*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_playstyle.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; } - else - RESETMAP; } } diff --git a/src/p_inter.c b/src/p_inter.c index d0998eca2..036063b89 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2246,7 +2246,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; P_SetThingPosition(target); - if (!target->player->bot && !G_IsSpecialStage(gamemap) + if (!target->player->bot && !target->player->spectator && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives()) { target->player->lives -= 1; // Lose a life Tails 03-11-2000 diff --git a/src/p_mobj.c b/src/p_mobj.c index 3186236b3..b291bb667 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9084,11 +9084,10 @@ void P_SpawnPlayer(INT32 playernum) // spawn as spectator determination if (!G_GametypeHasSpectators()) { - // Special case for (NiGHTS) special stages! - // if stage has already started, force players to become spectators until the next stage - if (((multiplayer || netgame) && leveltime > 0) - && ((G_IsSpecialStage(gamemap) && useNightsSS) - || (gametype == GT_COOP && cv_playstyle.value == 2 && (p->jointime < 1 || p->spectator)))) + if (((multiplayer || netgame) && gametype == GT_COOP && leveltime > 0) + && ((G_IsSpecialStage(gamemap) && useNightsSS) // late join special stage + || (cv_playstyle.value == 2 && (p->jointime < 1 || p->spectator)) // late join or die in new coop + || (p->jointime > 0 && p->lives <= 0))) // game over p->spectator = true; else p->spectator = false; diff --git a/src/p_setup.c b/src/p_setup.c index 4f11c10d0..f7a202aea 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2181,6 +2181,7 @@ lumpnum_t lastloadedmaplumpnum; // for comparative savegame static void P_LevelInitStuff(void) { INT32 i; + boolean canresetlives = true; leveltime = 0; @@ -2220,9 +2221,21 @@ static void P_LevelInitStuff(void) // earthquake camera memset(&quake,0,sizeof(struct quake)); + if ((netgame || multiplayer) && gametype == GT_COOP && cv_playstyle.value == 2) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && players[i].lives > 0) + { + canresetlives = false; + break; + } + } + } + for (i = 0; i < MAXPLAYERS; i++) { - if ((netgame || multiplayer) && (gametype == GT_COMPETITION || players[i].lives <= 0)) + if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0)) { // In Co-Op, replenish a user's lives if they are depleted. players[i].lives = cv_startinglives.value; diff --git a/src/p_user.c b/src/p_user.c index 0f8fb29ae..e95d5f586 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8222,7 +8222,7 @@ static void P_DeathThink(player_t *player) player->playerstate = PST_REBORN; 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! + if (gametype == GT_COOP && (netgame || multiplayer) && cv_playstyle.value == 2) P_ConsiderAllGone(); if ((player->deadtimer > 5*TICRATE) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE))) { @@ -8286,7 +8286,7 @@ static void P_DeathThink(player_t *player) } } // In a coop game, and out of lives - else if (gametype == GT_COOP) + /*else if (gametype == GT_COOP) { for (i = 0; i < MAXPLAYERS; i++) { @@ -8294,7 +8294,7 @@ static void P_DeathThink(player_t *player) continue; if (players[i].exiting || players[i].lives) break; - if (players[i].deadtimer < deadtimercheck) + if (players[i].playerstate == PST_DEAD && players[i].deadtimer < deadtimercheck) deadtimercheck = players[i].deadtimer; } @@ -8317,7 +8317,13 @@ static void P_DeathThink(player_t *player) tokenlist = 0; token = 0; } - } + }*/ + } + + if (gametype == GT_COOP && (player->lives <= 0) && (player->deadtimer > gameovertics || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE)))) + { + player->spectator = true; + player->playerstate = PST_REBORN; } if (gametype == GT_RACE || gametype == GT_COMPETITION || (gametype == GT_COOP && (multiplayer || netgame))) @@ -9427,16 +9433,27 @@ void P_PlayerThink(player_t *player) // Make sure spectators always have a score and ring count of 0. if (player->spectator) { - player->score = 0; + if (gametype != GT_COOP) + player->score = 0; player->mo->health = 1; player->rings = 0; } - - if ((netgame || multiplayer) && player->lives <= 0) + else if ((netgame || multiplayer) && player->lives <= 0) { - // In Co-Op, replenish a user's lives if they are depleted. - // of course, this is just a cheap hack, meh... - player->lives = cv_startinglives.value; + if (gametype == GT_COOP) + { + if (!cv_steallives.value || !P_GetLives(player)) + { + player->spectator = true; + player->playerstate = PST_REBORN; + } + } + else + { + // Outside of Co-Op, replenish a user's lives if they are depleted. + // of course, this is just a cheap hack, meh... + player->lives = cv_startinglives.value; + } } if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE)