diff --git a/src/doomstat.h b/src/doomstat.h index 06dfcca0b9a9729b60248b3b87633e35e01d0a07..87b98ab40c979e8e819f13e94129f86bdb02d3d9 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 632e33009c7b290268ff543a1597ac327e3e7ef0..080dc188e07f4faa8e6f4b2f50003023d5648aba 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_enemy.c b/src/p_enemy.c index 38035ab7febf4ea68f602b97c6f2ef5e3a9845e9..80f79809a66920a198bae94adab2d659966cdf91 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -13026,7 +13026,14 @@ static boolean PIT_TNTExplode(mobj_t *nearby) nearby->momx = FixedMul(FixedDiv(dx, dm), explodethrust); nearby->momy = FixedMul(FixedDiv(dy, dm), explodethrust); nearby->momz = FixedMul(FixedDiv(dz, dm), explodethrust); + P_UnsetThingPosition(nearby); + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } nearby->flags = MF_NOBLOCKMAP|MF_MISSILE; + P_SetThingPosition(nearby); P_SetMobjState(nearby, nearby->info->missilestate); } } @@ -13070,8 +13077,14 @@ void A_TNTExplode(mobj_t *actor) if (LUA_CallAction("A_TNTExplode", actor)) return; #endif - + P_UnsetThingPosition(actor); + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } actor->flags = MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP; + P_SetThingPosition(actor); actor->flags2 = MF2_EXPLOSION; if (actor->info->deathsound) S_StartSound(actor, actor->info->deathsound); diff --git a/src/p_mobj.c b/src/p_mobj.c index 942096726cb07c35551c988968f48480c26cdd00..a4ba416b336b7a7bbcb00fc6e33d063f10e3c9e3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6559,7 +6559,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); @@ -9624,7 +9624,7 @@ consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, void P_SpawnPrecipitation(void) { - INT32 i, mrand; + INT32 i /*, j*/, mrand; fixed_t basex, basey, x, y, height; subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; diff --git a/src/p_setup.c b/src/p_setup.c index 585da2149b1c3c4277ceb06968b47afeea41d788..9c4ddd87c83704630c5049bc7341b9d2fed07081 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 95fcf35aa63cacbf5ce0c7241b458042671a4e6b..53a9a1d252c399932857bc16c3cf0b70406c9bae 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -10233,14 +10233,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) @@ -10313,6 +10307,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 @@ -11232,9 +11264,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 838bc160cdbf9942727ed8defe709cac25eece53..6e2dfa0cf3967d13c27b34165787ec8b0d68b1ca 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -578,6 +578,17 @@ 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++) { + // Count the textures from TEXTURES lumps + + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); + while (texturesLumpPos != INT16_MAX) + { + numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); + } + + // Count single-patch textures + if (wadfiles[w]->type == RET_PK3) { texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); @@ -585,29 +596,34 @@ 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); - while (texturesLumpPos != INT16_MAX) - { - numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); - } + if (texstart == INT16_MAX || texend == INT16_MAX) + continue; + + texstart++; // Do not count the first marker - // Add all the textures between TX_START and TX_END - if (texstart != INT16_MAX && texend != INT16_MAX) + // PK3s have subfolders, so we can't just make a simple sum + if (wadfiles[w]->type == RET_PK3) { - numtextures += (UINT32)(texend - texstart); + for (j = texstart; j < texend; j++) + { + if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it + numtextures++; + } } - - // If no textures found by this point, bomb out - if (!numtextures && w == (numwadfiles - 1)) + else // Add all the textures between TX_START and TX_END { - I_Error("No textures detected in any WADs!\n"); + numtextures += (UINT32)(texend - texstart); } } + + // 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 82ef21d7fd1123267f21c120b8ec0446f383af82..d02ce9ce6061e43f3fa229e549c4821680d8090c 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 8ffcc1d03ce42f01f67cd6ebbce649f2ffd38b4b..6517388504d39b66945f284b9bd294aa1bcaae18 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