diff --git a/src/doomstat.h b/src/doomstat.h index 06dfcca0b..87b98ab40 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -146,6 +146,7 @@ extern UINT8 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor extern tic_t countdowntimer; extern boolean countdowntimeup; +extern boolean exitfadestarted; typedef struct { diff --git a/src/g_game.c b/src/g_game.c index 632e33009..080dc188e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -146,6 +146,7 @@ UINT8 skincolor_bluering = SKINCOLOR_CORNFLOWER; tic_t countdowntimer = 0; boolean countdowntimeup = false; +boolean exitfadestarted = false; cutscene_t *cutscenes[128]; textprompt_t *textprompts[MAX_PROMPTS]; @@ -3877,7 +3878,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean { // Clear a bunch of variables numgameovers = tokenlist = token = sstimer = redscore = bluescore = lastmap = 0; - countdown = countdown2 = 0; + countdown = countdown2 = exitfadestarted = 0; for (i = 0; i < MAXPLAYERS; i++) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 5bf11134c..584403408 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6591,7 +6591,7 @@ void P_RunOverlays(void) { angle_t viewingangle; - if (players[displayplayer].awayviewtics) + if (players[displayplayer].awayviewtics && players[displayplayer].awayviewmobj != NULL && !P_MobjWasRemoved(players[displayplayer].awayviewmobj)) viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y); else if (!camera.chase && players[displayplayer].mo) viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y); diff --git a/src/p_setup.c b/src/p_setup.c index 585da2149..9c4ddd87c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2228,7 +2228,7 @@ static void P_LevelInitStuff(void) } } - countdown = countdown2 = 0; + countdown = countdown2 = exitfadestarted = 0; for (i = 0; i < MAXPLAYERS; i++) { diff --git a/src/p_user.c b/src/p_user.c index 54ca6c78c..ce2d90455 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10232,14 +10232,8 @@ void P_PlayerThink(player_t *player) if (player->flashcount) player->flashcount--; - // Re-fixed by Jimita (11-12-2018) - if (player->awayviewtics) - { + if (player->awayviewtics && player->awayviewtics != -1) player->awayviewtics--; - if (!player->awayviewtics) - player->awayviewtics = -1; - // The timer might've reached zero, but we'll run the remote view camera anyway by setting it to -1. - } /// \note do this in the cheat code if (player->pflags & PF_NOCLIP) @@ -10312,6 +10306,44 @@ void P_PlayerThink(player_t *player) if (player->exiting && countdown2) player->exiting = 5; + // Same check as below, just at 1 second before + // so we can fade music + if (!exitfadestarted && + player->exiting > 0 && player->exiting <= 1*TICRATE && + (!multiplayer || gametype == GT_COOP ? !mapheaderinfo[gamemap-1]->musinterfadeout : true) && + // don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop + (gametype == GT_RACE || gametype == GT_COMPETITION ? countdown2 == 0 : true) && // don't fade on timeout + player->lives > 0 && // don't fade on game over (competition) + P_IsLocalPlayer(player)) + { + if (cv_playersforexit.value) + { + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].bot) + continue; + if (players[i].lives <= 0) + continue; + + if (!players[i].exiting || players[i].exiting > 1*TICRATE) + break; + } + + if (i == MAXPLAYERS) + { + exitfadestarted = true; + S_FadeOutStopMusic(1*MUSICRATE); + } + } + else + { + exitfadestarted = true; + S_FadeOutStopMusic(1*MUSICRATE); + } + } + if (player->exiting == 2 || countdown2 == 2) { if (cv_playersforexit.value) // Count to be sure everyone's exited @@ -11231,9 +11263,6 @@ void P_PlayerAfterThink(player_t *player) } } - if (player->awayviewtics < 0) - player->awayviewtics = 0; - // spectator invisibility and nogravity. if ((netgame || multiplayer) && player->spectator) { diff --git a/src/r_data.c b/src/r_data.c index 838bc160c..6e2dfa0cf 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -578,16 +578,7 @@ void R_LoadTextures(void) // but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures. for (w = 0, numtextures = 0; w < numwadfiles; w++) { - if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); - } - else - { - texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1; - texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); - } + // Count the textures from TEXTURES lumps texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); while (texturesLumpPos != INT16_MAX) @@ -596,18 +587,43 @@ void R_LoadTextures(void) texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); } - // Add all the textures between TX_START and TX_END - if (texstart != INT16_MAX && texend != INT16_MAX) + // Count single-patch textures + + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); + } + else + { + texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0); + texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); + } + + if (texstart == INT16_MAX || texend == INT16_MAX) + continue; + + texstart++; // Do not count the first marker + + // PK3s have subfolders, so we can't just make a simple sum + if (wadfiles[w]->type == RET_PK3) + { + for (j = texstart; j < texend; j++) + { + if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it + numtextures++; + } + } + else // Add all the textures between TX_START and TX_END { numtextures += (UINT32)(texend - texstart); } - - // If no textures found by this point, bomb out - if (!numtextures && w == (numwadfiles - 1)) - { - I_Error("No textures detected in any WADs!\n"); - } } + + // If no textures found by this point, bomb out + if (!numtextures) + I_Error("No textures detected in any WADs!\n"); + // Allocate memory and initialize to 0 for all the textures we are initialising. // There are actually 5 buffers allocated in one for convenience. textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL); @@ -642,7 +658,7 @@ void R_LoadTextures(void) } else { - texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1; + texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0); texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); if (texturesLumpPos != INT16_MAX) @@ -652,9 +668,16 @@ void R_LoadTextures(void) if (texstart == INT16_MAX || texend == INT16_MAX) continue; + texstart++; // Do not count the first marker + // Work through each lump between the markers in the WAD. - for (j = 0; j < (texend - texstart); i++, j++) + for (j = 0; j < (texend - texstart); j++) { + if (wadfiles[w]->type == RET_PK3) + { + if (W_IsLumpFolder((UINT16)w, texstart + j)) // Check if lump is a folder + continue; // If it is then SKIP IT + } patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE); //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); @@ -684,6 +707,7 @@ void R_LoadTextures(void) texturewidthmask[i] = k - 1; textureheight[i] = texture->height << FRACBITS; + i++; } } } @@ -1293,14 +1317,23 @@ void R_ReInitColormaps(UINT16 num) { char colormap[9] = "COLORMAP"; lumpnum_t lump; + const lumpnum_t basecolormaplump = W_GetNumForName(colormap); if (num > 0 && num <= 10000) snprintf(colormap, 8, "CLM%04u", num-1); // Load in the light tables, now 64k aligned for smokie... lump = W_GetNumForName(colormap); if (lump == LUMPERROR) - lump = W_GetNumForName("COLORMAP"); - W_ReadLump(lump, colormaps); + lump = basecolormaplump; + else + { + if (W_LumpLength(lump) != W_LumpLength(basecolormaplump)) + { + CONS_Alert(CONS_WARNING, "%s lump size does not match COLORMAP, results may be unexpected.\n", colormap); + } + } + + W_ReadLumpHeader(lump, colormaps, W_LumpLength(basecolormaplump), 0U); // Init Boom colormaps. R_ClearColormaps(); diff --git a/src/w_wad.c b/src/w_wad.c index 82ef21d7f..d02ce9ce6 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -162,9 +162,15 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors) { FILE *handle; - strncpy(filenamebuf, *filename, MAX_WADPATH); - filenamebuf[MAX_WADPATH - 1] = '\0'; - *filename = filenamebuf; + // Officially, strncpy should not have overlapping buffers, since W_VerifyNMUSlumps is called after this, and it + // changes filename to point at filenamebuf, it would technically be doing that. I doubt any issue will occur since + // they point to the same location, but it's better to be safe and this is a simple change. + if (filenamebuf != *filename) + { + strncpy(filenamebuf, *filename, MAX_WADPATH); + filenamebuf[MAX_WADPATH - 1] = '\0'; + *filename = filenamebuf; + } // open wad file if ((handle = fopen(*filename, "rb")) == NULL) @@ -1133,6 +1139,22 @@ boolean W_IsLumpWad(lumpnum_t lumpnum) return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned } +// +// W_IsLumpFolder +// Is the lump a folder? (in a PK3 obviously) +// +boolean W_IsLumpFolder(UINT16 wad, UINT16 lump) +{ + if (wadfiles[wad]->type == RET_PK3) + { + const char *name = wadfiles[wad]->lumpinfo[lump].name2; + + return (name[strlen(name)-1] == '/'); // folders end in '/' + } + + return false; // non-PK3s don't have folders +} + #ifdef HAVE_ZLIB /* report a zlib or i/o error */ void zerr(int ret) diff --git a/src/w_wad.h b/src/w_wad.h index 8ffcc1d03..651738850 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -151,6 +151,7 @@ size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump); size_t W_LumpLength(lumpnum_t lumpnum); boolean W_IsLumpWad(lumpnum_t lumpnum); // for loading maps from WADs in PK3s +boolean W_IsLumpFolder(UINT16 wad, UINT16 lump); // for detecting folder "lumps" #ifdef HAVE_ZLIB void zerr(int ret); // zlib error checking