musiccountdown

A system for level completion jingles.
- G_Ticker
    - Call P_EndingMusic after a certain amount of time has elapsed to begin a jingle
    - Play O_RACENT after the jingle's completion instead of baking it or an equivalent into the music
- P_EndingMusic
    - Change the function signature to not take a player
    - Pick from a series of const char* jingles, instead of sprintfing into a buffer
        - _first
        - _win
        - _lose
        - RETIRE
    - Simplifying logic to handle intermission music
This commit is contained in:
toaster 2023-04-30 21:47:07 +01:00
parent 74d6445a56
commit 581567dfae
7 changed files with 139 additions and 105 deletions

View file

@ -669,7 +669,7 @@ extern const tic_t bulbtime;
extern UINT8 numbulbs; extern UINT8 numbulbs;
extern tic_t raceexittime; extern tic_t raceexittime;
extern tic_t battleexittime; #define MUSICCOUNTDOWNMAX (raceexittime - (TICRATE/2))
extern INT32 hyudorotime; extern INT32 hyudorotime;
extern INT32 stealtime; extern INT32 stealtime;
@ -694,7 +694,7 @@ extern UINT8 maxXtraLife; // Max extra lives from rings
extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations
// For racing // For racing
extern tic_t racecountdown, exitcountdown; extern tic_t racecountdown, exitcountdown, musiccountdown;
#define DEFAULT_GRAVITY (4*FRACUNIT/5) #define DEFAULT_GRAVITY (4*FRACUNIT/5)
extern fixed_t gravity; extern fixed_t gravity;

View file

@ -249,8 +249,7 @@ tic_t starttime = 3;
const tic_t bulbtime = TICRATE/2; const tic_t bulbtime = TICRATE/2;
UINT8 numbulbs = 1; UINT8 numbulbs = 1;
tic_t raceexittime = 5*TICRATE + (2*TICRATE/3); tic_t raceexittime = 7*TICRATE + (TICRATE/2);
tic_t battleexittime = 8*TICRATE;
INT32 hyudorotime = 7*TICRATE; INT32 hyudorotime = 7*TICRATE;
INT32 stealtime = TICRATE/2; INT32 stealtime = TICRATE/2;
@ -277,7 +276,7 @@ mobj_t *hunt1;
mobj_t *hunt2; mobj_t *hunt2;
mobj_t *hunt3; mobj_t *hunt3;
tic_t racecountdown, exitcountdown; // for racing tic_t racecountdown, exitcountdown, musiccountdown; // for racing
fixed_t gravity; fixed_t gravity;
fixed_t mapobjectscale; fixed_t mapobjectscale;
@ -2392,6 +2391,19 @@ void G_Ticker(boolean run)
if (Playing() == true) if (Playing() == true)
{ {
if (musiccountdown > 1)
{
musiccountdown--;
if (musiccountdown == 1)
{
S_ChangeMusicInternal("racent", true);
}
else if (musiccountdown == (MUSICCOUNTDOWNMAX - (3*TICRATE)/2))
{
P_EndingMusic();
}
}
K_TickMidVote(); K_TickMidVote();
} }
} }
@ -4447,11 +4459,6 @@ static void G_DoCompleted(void)
} }
} }
// See Y_StartIntermission timer handling
if ((gametyperules & GTR_CIRCUIT) && ((multiplayer && demo.playback) || j == r_splitscreen+1) && (!K_CanChangeRules(false) || cv_inttime.value > 0))
// play some generic music if there's no win/cool/lose music going on (for exitlevel commands)
S_ChangeMusicInternal("racent", true);
if (automapactive) if (automapactive)
AM_Stop(); AM_Stop();
@ -5542,7 +5549,7 @@ void G_InitNew(UINT8 pencoremode, INT32 map, boolean resetplayer, boolean skippr
// Clear a bunch of variables // Clear a bunch of variables
redscore = bluescore = lastmap = 0; redscore = bluescore = lastmap = 0;
racecountdown = exitcountdown = mapreset = exitfadestarted = 0; racecountdown = exitcountdown = musiccountdown = mapreset = exitfadestarted = 0;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {

View file

@ -188,7 +188,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean fromAir, angle_t oldPitch, an
void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative); void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative);
void P_RestoreMusic(player_t *player); void P_RestoreMusic(player_t *player);
boolean P_EndingMusic(player_t *player); void P_EndingMusic(void);
mobj_t *P_SpawnGhostMobj(mobj_t *mobj); mobj_t *P_SpawnGhostMobj(mobj_t *mobj);
INT32 P_GivePlayerRings(player_t *player, INT32 num_rings); INT32 P_GivePlayerRings(player_t *player, INT32 num_rings);
INT32 P_GivePlayerSpheres(player_t *player, INT32 num_spheres); INT32 P_GivePlayerSpheres(player_t *player, INT32 num_spheres);

View file

@ -7165,7 +7165,7 @@ static void P_InitLevelSettings(void)
K_UpdateShrinkCheat(&players[i]); K_UpdateShrinkCheat(&players[i]);
} }
racecountdown = exitcountdown = exitfadestarted = 0; racecountdown = exitcountdown = musiccountdown = exitfadestarted = 0;
curlap = bestlap = 0; // SRB2Kart curlap = bestlap = 0; // SRB2Kart
// Gamespeed and frantic items // Gamespeed and frantic items

View file

@ -813,7 +813,11 @@ void P_Ticker(boolean run)
} }
} }
if (K_CheckBossIntro() == true) if (musiccountdown > 0)
{
// Music is controlled by completion sequence
}
else if (K_CheckBossIntro() == true)
{ {
// Bosses have a punchy start, so no position. // Bosses have a punchy start, so no position.
if (leveltime == 3) if (leveltime == 3)

View file

@ -36,6 +36,7 @@
#include "r_splats.h" #include "r_splats.h"
#include "z_zone.h" #include "z_zone.h"
#include "w_wad.h" #include "w_wad.h"
#include "y_inter.h" // Y_DetermineIntermissionType
#include "hu_stuff.h" #include "hu_stuff.h"
// We need to affect the NiGHTS hud // We need to affect the NiGHTS hud
#include "st_stuff.h" #include "st_stuff.h"
@ -710,91 +711,105 @@ void P_PlayVictorySound(mobj_t *source)
// //
// Consistently sets ending music! // Consistently sets ending music!
// //
boolean P_EndingMusic(player_t *player) void P_EndingMusic(void)
{ {
char buffer[9]; const char *jingle = NULL;
boolean looping = true; boolean nointer = false;
boolean racetracks = !!(gametyperules & GTR_CIRCUIT); UINT8 bestPos = UINT8_MAX;
INT32 bestlocalpos, test; player_t *bestPlayer = NULL;
player_t *bestlocalplayer;
if (!P_IsLocalPlayer(player)) // Only applies to a local player SINT8 i;
return false;
if (multiplayer && demo.playback) // Don't play this in multiplayer replays
return false;
// Event - Level Finish // Event - Level Finish
// Check for if this is valid or not // Check for if this is valid or not
#define getplayerpos(p) \ for (i = 0; i <= r_splitscreen; i++)
(((players[p].position < 1) || (players[p].pflags & PF_NOCONTEST)) \
? MAXPLAYERS+1 \
: players[p].position);
if (r_splitscreen)
{ {
const UINT8 *localplayertable = G_PartyArray(consoleplayer); UINT8 pos = UINT8_MAX;
player_t *checkPlayer = NULL;
if (!((players[localplayertable[0]].exiting || (players[localplayertable[0]].pflags & PF_NOCONTEST)) checkPlayer = &players[displayplayers[i]];
|| (players[localplayertable[1]].exiting || (players[localplayertable[1]].pflags & PF_NOCONTEST)) if (!checkPlayer || checkPlayer->spectator == true)
|| ((r_splitscreen > 1) && (players[localplayertable[2]].exiting || (players[localplayertable[2]].pflags & PF_NOCONTEST))) {
|| ((r_splitscreen > 2) && (players[localplayertable[3]].exiting || (players[localplayertable[3]].pflags & PF_NOCONTEST))))) continue;
return false; }
bestlocalplayer = &players[localplayertable[0]]; if (checkPlayer->pflags & PF_NOCONTEST)
bestlocalpos = getplayerpos(localplayertable[0]); {
#define setbests(p) \ // No Contest, use special value
test = getplayerpos(p); \ ;
if (test < bestlocalpos) \ }
{ \ else if (checkPlayer->exiting)
bestlocalplayer = &players[p]; \ {
bestlocalpos = test; \ // Standard exit, use their position
} pos = checkPlayer->position;
setbests(localplayertable[1]); }
if (r_splitscreen > 1)
setbests(localplayertable[2]);
if (r_splitscreen > 2)
setbests(localplayertable[3]);
#undef setbests
}
else
{
if (!(player->exiting || (player->pflags & PF_NOCONTEST)))
return false;
bestlocalplayer = player;
bestlocalpos = getplayerpos((player-players));
}
#undef getplayerpos
if (racetracks == true && bestlocalpos == MAXPLAYERS+1)
sprintf(buffer, "k*fail"); // F-Zero death results theme
else
{
if (K_IsPlayerLosing(bestlocalplayer))
sprintf(buffer, "k*lose");
else if (bestlocalpos == 1)
sprintf(buffer, "k*win");
else else
sprintf(buffer, "k*ok"); {
// Not finished, ignore
continue;
}
if (pos <= bestPos)
{
bestPlayer = checkPlayer;
bestPos = pos;
}
} }
// See G_DoCompleted and Y_DetermineIntermissionType
nointer = ((modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST))
|| (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE));
if (bestPlayer == NULL)
{
// No jingle for you
return;
}
if (bestPos == UINT8_MAX)
{
jingle = "RETIRE";
if (G_GametypeUsesLives() == true)
{
// A retry will be happening
nointer = true;
}
}
else
{
if (bestPlayer->position == 1)
{
jingle = "_first";
}
else if (K_IsPlayerLosing(bestPlayer) == false)
{
jingle = "_win";
}
else
{
jingle = "_lose";
if (G_GametypeUsesLives() == true)
{
// A retry will be happening
nointer = true;
}
}
}
if (nointer == true)
{
// Do not set "racent" in G_Ticker
musiccountdown = 1;
}
if (jingle == NULL)
return;
S_SpeedMusic(1.0f); S_SpeedMusic(1.0f);
if (racetracks == true) S_ChangeMusicInternal(jingle, false);
{
buffer[1] = 'r';
}
else
{
buffer[1] = 'b';
looping = false;
}
S_ChangeMusicInternal(buffer, looping);
return true;
} }
// //
@ -823,8 +838,10 @@ void P_RestoreMusic(player_t *player)
} }
// Event - Level Ending // Event - Level Ending
if (P_EndingMusic(player)) if (musiccountdown > 0)
{
return; return;
}
// Event - Level Start // Event - Level Start
if ((K_CheckBossIntro() == false) if ((K_CheckBossIntro() == false)
@ -1243,9 +1260,12 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
void P_DoPlayerExit(player_t *player) void P_DoPlayerExit(player_t *player)
{ {
const boolean losing = K_IsPlayerLosing(player); const boolean losing = K_IsPlayerLosing(player);
const boolean specialout = (specialstageinfo.valid == true && losing == true);
if (player->exiting || mapreset) if (player->exiting || mapreset)
{
return; return;
}
if (P_IsLocalPlayer(player) && (!player->spectator && !demo.playback)) if (P_IsLocalPlayer(player) && (!player->spectator && !demo.playback))
{ {
@ -1260,13 +1280,19 @@ void P_DoPlayerExit(player_t *player)
K_PlayerLoseLife(player); K_PlayerLoseLife(player);
} }
if (P_IsLocalPlayer(player) && !specialout)
{
S_StopMusic();
musiccountdown = MUSICCOUNTDOWNMAX;
}
player->exiting = 1; player->exiting = 1;
if (!player->spectator) if (!player->spectator)
{ {
ClearFakePlayerSkin(player); ClearFakePlayerSkin(player);
if ((gametyperules & GTR_CIRCUIT)) // If in Race Mode, allow if ((gametyperules & GTR_CIRCUIT)) // Special Race-like handling
{ {
K_UpdateAllPlayerPositions(); K_UpdateAllPlayerPositions();
@ -1290,13 +1316,9 @@ void P_DoPlayerExit(player_t *player)
} }
} }
// See Y_StartIntermission timer handling
if (!K_CanChangeRules(false) || cv_inttime.value > 0)
P_EndingMusic(player);
if (P_CheckRacers() && !exitcountdown) if (P_CheckRacers() && !exitcountdown)
{ {
if (specialstageinfo.valid == true && losing == true) if (specialout == true)
{ {
exitcountdown = TICRATE; exitcountdown = TICRATE;
} }
@ -1306,16 +1328,9 @@ void P_DoPlayerExit(player_t *player)
} }
} }
} }
else if ((gametyperules & GTR_BUMPERS)) // Battle Mode exiting else if (!exitcountdown) // All other gametypes
{ {
if (!exitcountdown) exitcountdown = raceexittime+1;
exitcountdown = battleexittime+1;
P_EndingMusic(player);
}
else // Accidental death safeguard???
{
if (!exitcountdown)
exitcountdown = raceexittime+2;
} }
if (grandprixinfo.gp == true && player->bot == false && losing == false) if (grandprixinfo.gp == true && player->bot == false && losing == false)
@ -1334,7 +1349,9 @@ void P_DoPlayerExit(player_t *player)
} }
if (modeattacking) if (modeattacking)
{
G_UpdateRecords(); G_UpdateRecords();
}
profile_t *pr = PR_GetPlayerProfile(player); profile_t *pr = PR_GetPlayerProfile(player);
if (pr != NULL && !losing) if (pr != NULL && !losing)
@ -3801,10 +3818,16 @@ void P_DoTimeOver(player_t *player)
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_TIMEOVER); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_TIMEOVER);
} }
P_EndingMusic(player); if (P_IsLocalPlayer(player))
{
S_StopMusic();
musiccountdown = MUSICCOUNTDOWNMAX;
}
if (!exitcountdown) if (!exitcountdown)
exitcountdown = 5*TICRATE; {
exitcountdown = raceexittime;
}
} }
// SRB2Kart: These are useful functions, but we aren't using them yet. // SRB2Kart: These are useful functions, but we aren't using them yet.

View file

@ -805,7 +805,7 @@ void Y_StartIntermission(void)
if (prevmap >= nummapheaders || !mapheaderinfo[prevmap]) if (prevmap >= nummapheaders || !mapheaderinfo[prevmap])
I_Error("Y_StartIntermission: Internal map ID %d not found (nummapheaders = %d)", prevmap, nummapheaders); I_Error("Y_StartIntermission: Internal map ID %d not found (nummapheaders = %d)", prevmap, nummapheaders);
if (!(gametyperules & GTR_CIRCUIT) && (timer > 1)) if (timer > 1 && musiccountdown == 0)
S_ChangeMusicInternal("racent", true); // loop it S_ChangeMusicInternal("racent", true); // loop it
S_ShowMusicCredit(); // Always call S_ShowMusicCredit(); // Always call