diff --git a/src/dehacked.c b/src/dehacked.c index e2df11142..002ad8071 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1205,6 +1205,8 @@ static void readlevelheader(MYFILE *f, INT32 num) mapheaderinfo[num-1]->skynum = (INT16)i; else if (fastcmp(word, "INTERSCREEN")) strncpy(mapheaderinfo[num-1]->interscreen, word2, 8); + else if (fastcmp(word, "MUSICINTERFADEOUT")) + mapheaderinfo[num-1]->musicinterfadeout = (UINT32)get_number(word2); else if (fastcmp(word, "PRECUTSCENENUM")) mapheaderinfo[num-1]->precutscenenum = (UINT8)i; else if (fastcmp(word, "CUTSCENENUM")) diff --git a/src/doomstat.h b/src/doomstat.h index d6fd046b4..cbeb4de42 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -246,6 +246,9 @@ typedef struct UINT8 numGradedMares; ///< Internal. For grade support. nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. + // Music stuff. + UINT32 musicinterfadeout; ///< Fade out level music on intermission screen in milliseconds + // Lua stuff. // (This is not ifdeffed so the map header structure can stay identical, just in case.) UINT8 numCustomOptions; ///< Internal. For Lua custom value support. diff --git a/src/g_game.c b/src/g_game.c index 6be4cf96e..0c53d17ff 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3541,7 +3541,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean { // Clear a bunch of variables tokenlist = token = sstimer = redscore = bluescore = lastmap = 0; - countdown = countdown2 = 0; + countdown = countdown2 = exitfadestarted = 0; for (i = 0; i < MAXPLAYERS; i++) { diff --git a/src/lua_maplib.c b/src/lua_maplib.c index a1d7994bf..b68574a7f 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1211,7 +1211,9 @@ static int mapheaderinfo_get(lua_State *L) if (!header->interscreen[i]) break; lua_pushlstring(L, header->interscreen, i); - } else if (fastcmp(field,"runsoc")) + } else if (fastcmp(field,"musicinterfadeout")) + lua_pushinteger(L, header->musicinterfadeout); + else if (fastcmp(field,"runsoc")) lua_pushstring(L, header->runsoc); else if (fastcmp(field,"scriptname")) lua_pushstring(L, header->scriptname); diff --git a/src/p_setup.c b/src/p_setup.c index 6c6b9153d..424aed5bc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -227,6 +227,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->menuflags = 0; // TODO grades support for delfile (pfft yeah right) P_DeleteGrades(num); + mapheaderinfo[num]->musicinterfadeout = 0; // an even further impossibility, delfile custom opts support mapheaderinfo[num]->customopts = NULL; mapheaderinfo[num]->numCustomOptions = 0; @@ -2189,7 +2190,7 @@ static void P_LevelInitStuff(void) players[i].lives = cv_startinglives.value; } - players[i].realtime = countdown = countdown2 = 0; + players[i].realtime = countdown = countdown2 = exitfadestarted = 0; players[i].gotcontinue = false; diff --git a/src/p_user.c b/src/p_user.c index 03b037fed..1d34ba5f1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8789,6 +8789,45 @@ 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 <= 1*TICRATE && + (!multiplayer || gametype == GT_COOP ? !mapheaderinfo[gamemap-1]->musicinterfadeout : 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, total = 0, exiting = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].bot) + continue; + if (players[i].lives <= 0) + continue; + + total++; + if (players[i].exiting && players[i].exiting < 1*TICRATE+1) + exiting++; + } + + if (!total || ((4*exiting)/total) >= cv_playersforexit.value) + { + 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 diff --git a/src/s_sound.h b/src/s_sound.h index 538707ffb..852ed4c27 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -23,6 +23,12 @@ // mask used to indicate sound origin is player item pickup #define PICKUP_SOUND 0x8000 +// Game state stuff + +boolean exitfadestarted; + +// Sound stuff + extern consvar_t stereoreverse; extern consvar_t cv_soundvolume, cv_digmusicvolume, cv_midimusicvolume; extern consvar_t cv_numChannels; diff --git a/src/y_inter.c b/src/y_inter.c index e7df165bf..1f4b49ddf 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -696,7 +696,10 @@ void Y_Ticker(void) boolean anybonuses = false; if (!intertic) // first time only - S_ChangeMusicInternal("lclear", false); // don't loop it + if (mapheaderinfo[gamemap-1]->musicinterfadeout) + S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musicinterfadeout); + else + S_ChangeMusicInternal("_clear", false); // don't loop it if (intertic < TICRATE) // one second pause before tally begins return; @@ -757,7 +760,10 @@ void Y_Ticker(void) if (!intertic) // first time only { - S_ChangeMusicInternal("lclear", false); // don't loop it + if (mapheaderinfo[gamemap-1]->musicinterfadeout) + S_FadeOutStopMusic(mapheaderinfo[gamemap-1]->musicinterfadeout); + else + S_ChangeMusicInternal("_clear", false); // don't loop it tallydonetic = 0; }