mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-03-20 18:01:16 +00:00
Merge branch 'internal-musicplus-jingle' into musicplus-aug2019
This commit is contained in:
commit
bddafbeece
11 changed files with 622 additions and 74 deletions
|
@ -8696,6 +8696,23 @@ struct {
|
|||
{"GT_HIDEANDSEEK",GT_HIDEANDSEEK},
|
||||
{"GT_CTF",GT_CTF},
|
||||
|
||||
// Jingles (jingletype_t)
|
||||
{"JT_NONE",JT_NONE},
|
||||
{"JT_OTHER",JT_OTHER},
|
||||
{"JT_MASTER",JT_MASTER},
|
||||
{"JT_1UP",JT_1UP},
|
||||
{"JT_SHOES",JT_SHOES},
|
||||
{"JT_INV",JT_INV},
|
||||
{"JT_MINV",JT_MINV},
|
||||
{"JT_DROWN",JT_DROWN},
|
||||
{"JT_SUPER",JT_SUPER},
|
||||
{"JT_GOVER",JT_GOVER},
|
||||
{"JT_NIGHTSTIMEOUT",JT_NIGHTSTIMEOUT},
|
||||
{"JT_SSTIMEOUT",JT_SSTIMEOUT},
|
||||
// {"JT_LCLEAR",JT_LCLEAR},
|
||||
// {"JT_RACENT",JT_RACENT},
|
||||
// {"JT_CONTSC",JT_CONTSC},
|
||||
|
||||
// Player state (playerstate_t)
|
||||
{"PST_LIVE",PST_LIVE}, // Playing or camping.
|
||||
{"PST_DEAD",PST_DEAD}, // Dead on the ground, view follows killer.
|
||||
|
|
|
@ -4104,12 +4104,11 @@ void A_Invincibility(mobj_t *actor)
|
|||
|
||||
if (P_IsLocalPlayer(player) && !player->powers[pw_super])
|
||||
{
|
||||
S_StopMusic();
|
||||
if (mariomode)
|
||||
G_GhostAddColor(GHC_INVINCIBLE);
|
||||
strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14);
|
||||
S_StartCaption(sfx_None, -1, player->powers[pw_invulnerability]);
|
||||
S_ChangeMusicInternal((mariomode) ? "_minv" : "_inv", false);
|
||||
P_PlayJingle(player, (mariomode) ? JT_MINV : JT_INV);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4143,10 +4142,7 @@ void A_SuperSneakers(mobj_t *actor)
|
|||
if (S_SpeedMusic(0.0f) && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC))
|
||||
S_SpeedMusic(1.4f);
|
||||
else
|
||||
{
|
||||
S_StopMusic();
|
||||
S_ChangeMusicInternal("_shoes", false);
|
||||
}
|
||||
P_PlayJingle(player, JT_SHOES);
|
||||
strlcpy(S_sfx[sfx_None].caption, "Speed shoes", 12);
|
||||
S_StartCaption(sfx_None, -1, player->powers[pw_sneakers]);
|
||||
}
|
||||
|
|
|
@ -1700,7 +1700,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
// Eaten by player!
|
||||
if ((!player->bot) && (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1))
|
||||
{
|
||||
player->powers[pw_underwater] = underwatertics + 1;
|
||||
P_RestoreMusic(player);
|
||||
}
|
||||
|
||||
if (player->powers[pw_underwater] < underwatertics + 1)
|
||||
player->powers[pw_underwater] = underwatertics + 1;
|
||||
|
@ -2467,10 +2470,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
gameovermus = true;
|
||||
|
||||
if (gameovermus)
|
||||
{
|
||||
S_StopMusic(); // Stop the Music! Tails 03-14-2000
|
||||
S_ChangeMusicInternal("_gover", false); // Yousa dead now, Okieday? Tails 03-14-2000
|
||||
}
|
||||
P_PlayJingle(target->player, JT_GOVER); // Yousa dead now, Okieday? Tails 03-14-2000
|
||||
|
||||
if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking) && numgameovers < maxgameovers)
|
||||
{
|
||||
|
@ -2918,7 +2918,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source)
|
|||
S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS.
|
||||
}
|
||||
else
|
||||
S_ChangeMusicInternal((((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? "_ntime" : "_drown"), false);
|
||||
P_PlayJingle(player, ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? JT_NIGHTSTIMEOUT : JT_SSTIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -208,6 +208,47 @@ boolean P_GetLives(player_t *player);
|
|||
boolean P_SpectatorJoinGame(player_t *player);
|
||||
void P_RestoreMultiMusic(player_t *player);
|
||||
|
||||
/// ------------------------
|
||||
/// Jingle stuff
|
||||
/// ------------------------
|
||||
|
||||
typedef enum
|
||||
{
|
||||
JT_NONE, // Null state
|
||||
JT_OTHER, // Other state
|
||||
JT_MASTER, // Main level music
|
||||
JT_1UP, // Extra life
|
||||
JT_SHOES, // Speed shoes
|
||||
JT_INV, // Invincibility
|
||||
JT_MINV, // Mario Invincibility
|
||||
JT_DROWN, // Drowning
|
||||
JT_SUPER, // Super Sonic
|
||||
JT_GOVER, // Game Over
|
||||
JT_NIGHTSTIMEOUT, // NiGHTS Time Out (10 seconds)
|
||||
JT_SSTIMEOUT, // NiGHTS Special Stage Time Out (10 seconds)
|
||||
|
||||
// these are not jingles
|
||||
// JT_LCLEAR, // Level Clear
|
||||
// JT_RACENT, // Multiplayer Intermission
|
||||
// JT_CONTSC, // Continue
|
||||
|
||||
NUMJINGLES
|
||||
} jingletype_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char musname[7];
|
||||
boolean looping;
|
||||
} jingle_t;
|
||||
|
||||
extern jingle_t jingleinfo[NUMJINGLES];
|
||||
|
||||
#define JINGLEPOSTFADE 1000
|
||||
|
||||
void P_PlayJingle(player_t *player, jingletype_t jingletype);
|
||||
boolean P_EvaluateMusicStatus(UINT16 status);
|
||||
void P_PlayJingleMusic(player_t *player, const char *musname, UINT16 musflags, boolean looping, UINT16 status);
|
||||
|
||||
//
|
||||
// P_MOBJ
|
||||
//
|
||||
|
|
|
@ -601,13 +601,20 @@ void P_Ticker(boolean run)
|
|||
OP_ObjectplaceMovement(&players[0]);
|
||||
P_MoveChaseCamera(&players[0], &camera, false);
|
||||
P_MapEnd();
|
||||
S_SetStackAdjustmentStart();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for pause or menu up in single player
|
||||
if (paused || P_AutoPause())
|
||||
{
|
||||
S_SetStackAdjustmentStart();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!S_MusicPaused())
|
||||
S_AdjustMusicStackTics();
|
||||
|
||||
postimgtype = postimgtype2 = postimg_none;
|
||||
|
||||
|
|
221
src/p_user.c
221
src/p_user.c
|
@ -56,6 +56,29 @@
|
|||
static void P_NukeAllPlayers(player_t *player);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Jingle stuff.
|
||||
//
|
||||
|
||||
jingle_t jingleinfo[NUMJINGLES] = {
|
||||
// {musname, looping, reset, nest}
|
||||
{"" , false}, // JT_NONE
|
||||
{"" , false}, // JT_OTHER
|
||||
{"" , false}, // JT_MASTER
|
||||
{"_1up" , false},
|
||||
{"_shoes" , true},
|
||||
{"_inv" , false},
|
||||
{"_minv" , false},
|
||||
{"_drown" , false},
|
||||
{"_super" , true},
|
||||
{"_gover" , false},
|
||||
{"_ntime" , false}, // JT_NIGHTSTIMEOUT
|
||||
{"_drown" , false} // JT_SSTIMEOUT
|
||||
// {"_clear" , false},
|
||||
// {"_inter" , true},
|
||||
// {"_conti" , true}
|
||||
};
|
||||
|
||||
//
|
||||
// Movement.
|
||||
//
|
||||
|
@ -696,7 +719,10 @@ static void P_DeNightserizePlayer(player_t *player)
|
|||
S_SetMusicPosition(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
music_stack_fadein = 0; // HACK: Change fade-in for restore music
|
||||
P_RestoreMusic(player);
|
||||
}
|
||||
|
||||
P_RunDeNightserizeExecutors(player->mo);
|
||||
}
|
||||
|
@ -753,7 +779,10 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
|
|||
S_SetInternalMusicVolume(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
music_stack_fadein = 0; // HACK: Change fade-in for restore music
|
||||
P_RestoreMusic(player);
|
||||
}
|
||||
|
||||
P_SetPlayerMobjState(player->mo, S_PLAY_NIGHTS_TRANS1);
|
||||
|
||||
|
@ -1219,10 +1248,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings)
|
|||
{
|
||||
player->powers[pw_super] = 1;
|
||||
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC) && P_IsLocalPlayer(player))
|
||||
{
|
||||
S_StopMusic();
|
||||
S_ChangeMusicInternal("_super", true);
|
||||
}
|
||||
P_PlayJingle(player, JT_SUPER);
|
||||
|
||||
S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi
|
||||
|
||||
|
@ -1388,14 +1414,115 @@ void P_PlayLivesJingle(player_t *player)
|
|||
else
|
||||
{
|
||||
if (player)
|
||||
player->powers[pw_extralife] = extralifetics+1;
|
||||
S_StopMusic(); // otherwise it won't restart if this is done twice in a row
|
||||
player->powers[pw_extralife] = extralifetics + 1;
|
||||
strlcpy(S_sfx[sfx_None].caption, "One-up", 7);
|
||||
S_StartCaption(sfx_None, -1, extralifetics+1);
|
||||
S_ChangeMusicInternal("_1up", false);
|
||||
P_PlayJingle(player, JT_1UP);
|
||||
}
|
||||
}
|
||||
|
||||
void P_PlayJingle(player_t *player, jingletype_t jingletype)
|
||||
{
|
||||
const char *musname = jingleinfo[jingletype].musname;
|
||||
UINT16 musflags = 0;
|
||||
boolean looping = jingleinfo[jingletype].looping;
|
||||
|
||||
char newmusic[7];
|
||||
strncpy(newmusic, musname, 7);
|
||||
#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
|
||||
if(LUAh_MusicJingle(jingletype, newmusic, &musflags, &looping))
|
||||
return;
|
||||
#endif
|
||||
newmusic[6] = 0;
|
||||
|
||||
P_PlayJingleMusic(player, newmusic, musflags, looping, jingletype);
|
||||
}
|
||||
|
||||
//
|
||||
// P_PlayJingleMusic
|
||||
//
|
||||
void P_PlayJingleMusic(player_t *player, const char *musname, UINT16 musflags, boolean looping, UINT16 status)
|
||||
{
|
||||
// If gamestate != GS_LEVEL, always play the jingle (1-up intermission)
|
||||
if (gamestate == GS_LEVEL && !P_IsLocalPlayer(player))
|
||||
return;
|
||||
|
||||
S_RetainMusic(musname, musflags, looping, 0, status);
|
||||
S_StopMusic();
|
||||
S_ChangeMusicInternal(musname, looping);
|
||||
}
|
||||
|
||||
boolean P_EvaluateMusicStatus(UINT16 status)
|
||||
{
|
||||
// \todo lua hook
|
||||
int i;
|
||||
boolean result = false;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!P_IsLocalPlayer(&players[i]))
|
||||
continue;
|
||||
|
||||
switch(status)
|
||||
{
|
||||
case JT_1UP: // Extra life
|
||||
result = (players[i].powers[pw_extralife] > 1);
|
||||
break;
|
||||
|
||||
case JT_SHOES: // Speed shoes
|
||||
if (players[i].powers[pw_sneakers] > 1 && !players[i].powers[pw_super])
|
||||
{
|
||||
//strlcpy(S_sfx[sfx_None].caption, "Speed shoes", 12);
|
||||
//S_StartCaption(sfx_None, -1, players[i].powers[pw_sneakers]);
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
result = false;
|
||||
break;
|
||||
|
||||
case JT_INV: // Invincibility
|
||||
case JT_MINV: // Mario Invincibility
|
||||
if (players[i].powers[pw_invulnerability] > 1)
|
||||
{
|
||||
//strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14);
|
||||
//S_StartCaption(sfx_None, -1, players[i].powers[pw_invulnerability]);
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
result = false;
|
||||
break;
|
||||
|
||||
case JT_DROWN: // Drowning
|
||||
result = (players[i].powers[pw_underwater] && players[i].powers[pw_underwater] <= 11*TICRATE + 1);
|
||||
break;
|
||||
|
||||
case JT_SUPER: // Super Sonic
|
||||
result = (players[i].powers[pw_super] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC));
|
||||
break;
|
||||
|
||||
case JT_GOVER: // Game Over
|
||||
result = (players[i].lives <= 0);
|
||||
break;
|
||||
|
||||
case JT_NIGHTSTIMEOUT: // NiGHTS Time Out (10 seconds)
|
||||
case JT_SSTIMEOUT:
|
||||
result = (players[i].nightstime && players[i].nightstime <= 10*TICRATE);
|
||||
break;
|
||||
|
||||
case JT_NONE: // Null state
|
||||
case JT_OTHER: // Other state
|
||||
case JT_MASTER: // Main level music
|
||||
default:
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// P_RestoreMusic
|
||||
//
|
||||
|
@ -1406,17 +1533,30 @@ void P_RestoreMusic(player_t *player)
|
|||
if (!P_IsLocalPlayer(player)) // Only applies to a local player
|
||||
return;
|
||||
|
||||
S_SpeedMusic(1.0f);
|
||||
|
||||
// Jingles have a priority in this order, so follow it
|
||||
// and as a default case, go down the music stack.
|
||||
|
||||
// Extra life
|
||||
if (player->powers[pw_extralife] > 1)
|
||||
return;
|
||||
S_SpeedMusic(1.0f);
|
||||
if (player->powers[pw_super] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC))
|
||||
S_ChangeMusicInternal("_super", true);
|
||||
|
||||
// Super
|
||||
else if (player->powers[pw_super] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC)
|
||||
&& !S_RecallMusic(JT_SUPER, false))
|
||||
P_PlayJingle(player, JT_SUPER);
|
||||
|
||||
// Invulnerability
|
||||
else if (player->powers[pw_invulnerability] > 1)
|
||||
{
|
||||
strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14);
|
||||
S_StartCaption(sfx_None, -1, player->powers[pw_invulnerability]);
|
||||
S_ChangeMusicInternal((mariomode) ? "_minv" : "_inv", false);
|
||||
if (!S_RecallMusic(JT_INV, false) && !S_RecallMusic(JT_MINV, false))
|
||||
P_PlayJingle(player, (mariomode) ? JT_MINV : JT_INV);
|
||||
}
|
||||
|
||||
// Shoes
|
||||
else if (player->powers[pw_sneakers] > 1 && !player->powers[pw_super])
|
||||
{
|
||||
strlcpy(S_sfx[sfx_None].caption, "Speed shoes", 12);
|
||||
|
@ -1424,13 +1564,19 @@ void P_RestoreMusic(player_t *player)
|
|||
if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)
|
||||
{
|
||||
S_SpeedMusic(1.4f);
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
if (!S_RecallMusic(JT_MASTER, true))
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
}
|
||||
else
|
||||
S_ChangeMusicInternal("_shoes", true);
|
||||
else if (!S_RecallMusic(JT_SHOES, false))
|
||||
P_PlayJingle(player, JT_SHOES);
|
||||
}
|
||||
else
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
|
||||
// Default
|
||||
else if (!S_RecallMusic(JT_NONE, false)) // go down the stack
|
||||
{
|
||||
CONS_Debug(DBG_BASIC, "Cannot find any music in resume stack!\n");
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1760,9 +1906,12 @@ void P_SwitchShield(player_t *player, UINT16 shieldtype)
|
|||
if (shieldtype & SH_PROTECTWATER)
|
||||
{
|
||||
if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1)
|
||||
{
|
||||
player->powers[pw_underwater] = 0;
|
||||
P_RestoreMusic(player);
|
||||
|
||||
player->powers[pw_underwater] = 0;
|
||||
}
|
||||
else
|
||||
player->powers[pw_underwater] = 0;
|
||||
|
||||
if (player->powers[pw_spacetime] > 1)
|
||||
{
|
||||
|
@ -2603,10 +2752,6 @@ static void P_CheckQuicksand(player_t *player)
|
|||
//
|
||||
static void P_CheckSneakerAndLivesTimer(player_t *player)
|
||||
{
|
||||
if ((player->powers[pw_underwater] <= 11*TICRATE + 1)
|
||||
&& (player->powers[pw_underwater] > 1))
|
||||
return; // don't restore music if drowning music is playing
|
||||
|
||||
if (player->powers[pw_extralife] == 1) // Extra Life!
|
||||
P_RestoreMusic(player);
|
||||
|
||||
|
@ -2674,16 +2819,16 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
|
|||
if (!(player->mo->eflags & MFE_UNDERWATER) && player->powers[pw_underwater])
|
||||
{
|
||||
if (player->powers[pw_underwater] <= 12*TICRATE + 1)
|
||||
{
|
||||
player->powers[pw_underwater] = 0;
|
||||
P_RestoreMusic(player);
|
||||
|
||||
player->powers[pw_underwater] = 0;
|
||||
}
|
||||
else
|
||||
player->powers[pw_underwater] = 0;
|
||||
}
|
||||
|
||||
if (player->powers[pw_spacetime] > 1 && !P_InSpaceSector(player->mo))
|
||||
{
|
||||
P_RestoreMusic(player);
|
||||
player->powers[pw_spacetime] = 0;
|
||||
}
|
||||
|
||||
// Underwater audio cues
|
||||
if (P_IsLocalPlayer(player) && !player->bot)
|
||||
|
@ -2696,8 +2841,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
|
|||
if (player->powers[pw_underwater] == 11*TICRATE + 1
|
||||
&& player == &players[consoleplayer])
|
||||
{
|
||||
S_StopMusic();
|
||||
S_ChangeMusicInternal("_drown", false);
|
||||
P_PlayJingle(player, JT_DROWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2744,10 +2888,6 @@ static void P_CheckInvincibilityTimer(player_t *player)
|
|||
P_SpawnShieldOrb(player);
|
||||
}
|
||||
|
||||
if ((player->powers[pw_underwater] <= 11*TICRATE + 1)
|
||||
&& (player->powers[pw_underwater] > 1))
|
||||
return; // don't restore music if drowning music is playing
|
||||
|
||||
if (!player->powers[pw_super] || (mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC))
|
||||
P_RestoreMusic(player);
|
||||
}
|
||||
|
@ -3961,6 +4101,8 @@ static void P_DoSuperStuff(player_t *player)
|
|||
{
|
||||
player->powers[pw_super] = 0;
|
||||
P_SetPlayerMobjState(player->mo, S_PLAY_STND);
|
||||
music_stack_noposition = true; // HACK: Do not reposition next music
|
||||
music_stack_fadeout = MUSICRATE/2; // HACK: Fade out current music
|
||||
P_RestoreMusic(player);
|
||||
P_SpawnShieldOrb(player);
|
||||
|
||||
|
@ -4042,6 +4184,8 @@ static void P_DoSuperStuff(player_t *player)
|
|||
}
|
||||
|
||||
// Resume normal music if you're the console player
|
||||
music_stack_noposition = true; // HACK: Do not reposition next music
|
||||
music_stack_fadeout = MUSICRATE/2; // HACK: Fade out current music
|
||||
P_RestoreMusic(player);
|
||||
|
||||
// If you had a shield, restore its visual significance.
|
||||
|
@ -6610,7 +6754,7 @@ static void P_NiGHTSMovement(player_t *player)
|
|||
S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS.
|
||||
}
|
||||
else
|
||||
S_ChangeMusicInternal((((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? "_ntime" : "_drown"), false);
|
||||
P_PlayJingle(player, ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? JT_NIGHTSTIMEOUT : JT_SSTIMEOUT);
|
||||
}
|
||||
|
||||
if (player->mo->z < player->mo->floorz)
|
||||
|
@ -10496,7 +10640,7 @@ void P_PlayerThink(player_t *player)
|
|||
// If 11 seconds are left on the timer,
|
||||
// begin the drown music for countdown!
|
||||
if (countdown == 11*TICRATE - 1 && P_IsLocalPlayer(player))
|
||||
S_ChangeMusicInternal("_drown", false);
|
||||
P_PlayJingle(player, JT_DROWN);
|
||||
|
||||
// If you've hit the countdown and you haven't made
|
||||
// it to the exit, you're a goner!
|
||||
|
@ -10985,9 +11129,12 @@ void P_PlayerThink(player_t *player)
|
|||
if (player->powers[pw_underwater] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER)))
|
||||
{
|
||||
if (player->powers[pw_underwater] <= 12*TICRATE+1)
|
||||
{
|
||||
player->powers[pw_underwater] = 0;
|
||||
P_RestoreMusic(player); //incase they were about to drown
|
||||
|
||||
player->powers[pw_underwater] = 0;
|
||||
}
|
||||
else
|
||||
player->powers[pw_underwater] = 0;
|
||||
}
|
||||
else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer
|
||||
player->powers[pw_underwater]--;
|
||||
|
|
328
src/s_sound.c
328
src/s_sound.c
|
@ -62,6 +62,8 @@ static void GameDigiMusic_OnChange(void);
|
|||
|
||||
static void ModFilter_OnChange(void);
|
||||
|
||||
static lumpnum_t S_GetMusicLumpNum(const char *mname);
|
||||
|
||||
// commands for music and sound servers
|
||||
#ifdef MUSSERV
|
||||
consvar_t musserver_cmd = {"musserver_cmd", "musserver", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
@ -1398,6 +1400,8 @@ static boolean queue_looping;
|
|||
static UINT32 queue_position;
|
||||
static UINT32 queue_fadeinms;
|
||||
|
||||
static tic_t pause_starttic;
|
||||
|
||||
/// ------------------------
|
||||
/// Music Status
|
||||
/// ------------------------
|
||||
|
@ -1496,10 +1500,304 @@ UINT32 S_GetMusicPosition(void)
|
|||
return I_GetSongPosition();
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Stacking (Jingles)
|
||||
/// In this section: mazmazz doesn't know how to do dynamic arrays or struct pointers!
|
||||
/// ------------------------
|
||||
|
||||
static musicstack_t *music_stacks = NULL;
|
||||
static musicstack_t *last_music_stack = NULL;
|
||||
|
||||
void S_SetStackAdjustmentStart(void)
|
||||
{
|
||||
if (!pause_starttic)
|
||||
pause_starttic = gametic;
|
||||
}
|
||||
|
||||
void S_AdjustMusicStackTics(void)
|
||||
{
|
||||
if (pause_starttic)
|
||||
{
|
||||
musicstack_t *mst;
|
||||
for (mst = music_stacks; mst; mst = mst->next)
|
||||
mst->tic += gametic - pause_starttic;
|
||||
pause_starttic = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void S_ResetMusicStack(void)
|
||||
{
|
||||
musicstack_t *mst, *mst_next;
|
||||
for (mst = music_stacks; mst; mst = mst_next)
|
||||
{
|
||||
mst_next = mst->next;
|
||||
Z_Free(mst);
|
||||
}
|
||||
music_stacks = last_music_stack = NULL;
|
||||
}
|
||||
|
||||
static void S_RemoveMusicStackEntry(musicstack_t *entry)
|
||||
{
|
||||
musicstack_t *mst;
|
||||
for (mst = music_stacks; mst; mst = mst->next)
|
||||
{
|
||||
if (mst == entry)
|
||||
{
|
||||
// Remove ourselves from the chain and link
|
||||
// prev and next together
|
||||
|
||||
if (mst->prev)
|
||||
mst->prev->next = mst->next;
|
||||
else
|
||||
music_stacks = mst->next;
|
||||
|
||||
if (mst->next)
|
||||
mst->next->prev = mst->prev;
|
||||
else
|
||||
last_music_stack = mst->prev;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
Z_Free(entry);
|
||||
}
|
||||
|
||||
static void S_RemoveMusicStackEntryByStatus(UINT16 status)
|
||||
{
|
||||
musicstack_t *mst, *mst_next;
|
||||
|
||||
if (!status)
|
||||
return;
|
||||
|
||||
for (mst = music_stacks; mst; mst = mst_next)
|
||||
{
|
||||
mst_next = mst->next;
|
||||
if (mst->status == status)
|
||||
S_RemoveMusicStackEntry(mst);
|
||||
}
|
||||
}
|
||||
|
||||
static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status)
|
||||
{
|
||||
musicstack_t *mst, *new_mst;
|
||||
|
||||
// if the first entry is empty, force master onto it
|
||||
if (!music_stacks)
|
||||
{
|
||||
music_stacks = Z_Calloc(sizeof (*mst), PU_MUSIC, NULL);
|
||||
strncpy(music_stacks->musname, (status == JT_MASTER ? mname : mapmusname), 7);
|
||||
music_stacks->musflags = (status == JT_MASTER ? mflags : mapmusflags);
|
||||
music_stacks->looping = (status == JT_MASTER ? looping : true);
|
||||
music_stacks->position = (status == JT_MASTER ? position : S_GetMusicPosition());
|
||||
music_stacks->tic = gametic;
|
||||
music_stacks->status = JT_MASTER;
|
||||
music_stacks->mlumpnum = S_GetMusicLumpNum(music_stacks->musname);
|
||||
|
||||
if (status == JT_MASTER)
|
||||
return; // we just added the user's entry here
|
||||
}
|
||||
|
||||
// look for an empty slot to park ourselves
|
||||
for (mst = music_stacks; mst->next; mst = mst->next);
|
||||
|
||||
// create our new entry
|
||||
new_mst = Z_Calloc(sizeof (*new_mst), PU_MUSIC, NULL);
|
||||
strncpy(new_mst->musname, mname, 7);
|
||||
new_mst->musname[6] = 0;
|
||||
new_mst->musflags = mflags;
|
||||
new_mst->looping = looping;
|
||||
new_mst->position = position;
|
||||
new_mst->tic = gametic;
|
||||
new_mst->status = status;
|
||||
new_mst->mlumpnum = S_GetMusicLumpNum(new_mst->musname);
|
||||
|
||||
mst->next = new_mst;
|
||||
new_mst->prev = mst;
|
||||
new_mst->next = NULL;
|
||||
last_music_stack = new_mst;
|
||||
}
|
||||
|
||||
static musicstack_t *S_GetMusicStackEntry(UINT16 status, boolean fromfirst, INT16 startindex)
|
||||
{
|
||||
musicstack_t *mst, *start_mst = NULL, *mst_next;
|
||||
|
||||
// if the first entry is empty, force master onto it
|
||||
// fixes a memory corruption bug
|
||||
if (!music_stacks && status != JT_MASTER)
|
||||
S_AddMusicStackEntry(mapmusname, mapmusflags, true, S_GetMusicPosition(), JT_MASTER);
|
||||
|
||||
if (startindex >= 0)
|
||||
{
|
||||
INT16 i = 0;
|
||||
for (mst = music_stacks; mst && i <= startindex; mst = mst->next, i++)
|
||||
start_mst = mst;
|
||||
}
|
||||
else
|
||||
start_mst = (fromfirst ? music_stacks : last_music_stack);
|
||||
|
||||
for (mst = start_mst; mst; mst = mst_next)
|
||||
{
|
||||
mst_next = (fromfirst ? mst->next : mst->prev);
|
||||
|
||||
if (!status || mst->status == status)
|
||||
{
|
||||
if (P_EvaluateMusicStatus(mst->status))
|
||||
{
|
||||
if (!S_MusicExists(mst->musname, !midi_disabled, !digital_disabled)) // paranoia
|
||||
S_RemoveMusicStackEntry(mst); // then continue
|
||||
else
|
||||
return mst;
|
||||
}
|
||||
else
|
||||
S_RemoveMusicStackEntry(mst); // then continue
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void S_RetainMusic(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status)
|
||||
{
|
||||
musicstack_t *mst;
|
||||
|
||||
if (!status) // we use this as a null indicator, don't push
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Music stack entry must have a nonzero status.\n");
|
||||
return;
|
||||
}
|
||||
else if (status == JT_MASTER) // enforce only one JT_MASTER
|
||||
{
|
||||
for (mst = music_stacks; mst; mst = mst->next)
|
||||
{
|
||||
if (mst->status == JT_MASTER)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Music stack can only have one JT_MASTER entry.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // remove any existing status
|
||||
S_RemoveMusicStackEntryByStatus(status);
|
||||
|
||||
S_AddMusicStackEntry(mname, mflags, looping, position, status);
|
||||
}
|
||||
|
||||
boolean S_RecallMusic(UINT16 status, boolean fromfirst)
|
||||
{
|
||||
UINT32 newpos = 0;
|
||||
boolean mapmuschanged = false;
|
||||
musicstack_t *result;
|
||||
musicstack_t *entry = Z_Calloc(sizeof (*result), PU_MUSIC, NULL);
|
||||
|
||||
if (status)
|
||||
result = S_GetMusicStackEntry(status, fromfirst, -1);
|
||||
else
|
||||
result = S_GetMusicStackEntry(JT_NONE, false, -1);
|
||||
|
||||
if (result && !S_MusicExists(result->musname, !midi_disabled, !digital_disabled))
|
||||
{
|
||||
Z_Free(entry);
|
||||
return false; // music doesn't exist, so don't do anything
|
||||
}
|
||||
|
||||
// make a copy of result, since we make modifications to our copy
|
||||
if (result)
|
||||
{
|
||||
*entry = *result;
|
||||
strncpy(entry->musname, result->musname, 7);
|
||||
}
|
||||
|
||||
// no result, just grab mapmusname
|
||||
if (!result || !entry->musname[0] || ((status == JT_MASTER || (music_stacks ? !music_stacks->status : false)) && !entry->status))
|
||||
{
|
||||
strncpy(entry->musname, mapmusname, 7);
|
||||
entry->musflags = mapmusflags;
|
||||
entry->looping = true;
|
||||
entry->position = mapmusposition;
|
||||
entry->tic = gametic;
|
||||
entry->status = JT_MASTER;
|
||||
entry->mlumpnum = S_GetMusicLumpNum(entry->musname);
|
||||
}
|
||||
|
||||
if (entry->status == JT_MASTER)
|
||||
{
|
||||
mapmuschanged = strnicmp(entry->musname, mapmusname, 7);
|
||||
S_ResetMusicStack();
|
||||
}
|
||||
else if (!entry->status)
|
||||
{
|
||||
Z_Free(entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mapmuschanged && strncmp(entry->musname, S_MusicName(), 7)) // don't restart music if we're already playing it
|
||||
{
|
||||
if (music_stack_fadeout)
|
||||
S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, music_stack_fadeout, 0);
|
||||
else
|
||||
{
|
||||
S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, 0, music_stack_fadein);
|
||||
|
||||
if (!music_stack_noposition) // HACK: Global boolean to toggle position resuming, e.g., de-superize
|
||||
{
|
||||
UINT32 poslapse = 0;
|
||||
|
||||
// To prevent the game from jumping past the end of the music, we need
|
||||
// to check if we can get the song's length. Otherwise, if the lapsed resume time goes
|
||||
// over a LOOPPOINT, mixer_sound.c will be unable to calculate the new resume position.
|
||||
if (S_GetMusicLength())
|
||||
poslapse = (UINT32)((float)(gametic - entry->tic)/(float)TICRATE*(float)MUSICRATE);
|
||||
|
||||
newpos = entry->position + poslapse;
|
||||
}
|
||||
|
||||
// If the newly recalled music lumpnum does not match the lumpnum that we stored in stack,
|
||||
// then discard the new position. That way, we will not recall an invalid position
|
||||
// when the music is replaced or digital/MIDI is toggled.
|
||||
if (newpos > 0 && S_MusicPlaying() && S_GetMusicLumpNum(entry->musname) == entry->mlumpnum)
|
||||
S_SetMusicPosition(newpos);
|
||||
else
|
||||
{
|
||||
S_StopFadingMusic();
|
||||
S_SetInternalMusicVolume(100);
|
||||
}
|
||||
}
|
||||
music_stack_noposition = false;
|
||||
music_stack_fadeout = 0;
|
||||
music_stack_fadein = JINGLEPOSTFADE;
|
||||
}
|
||||
|
||||
Z_Free(entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Playback
|
||||
/// ------------------------
|
||||
|
||||
static lumpnum_t S_GetMusicLumpNum(const char *mname)
|
||||
{
|
||||
if (!S_DigMusicDisabled() && S_DigExists(mname))
|
||||
return W_GetNumForName(va("o_%s", mname));
|
||||
else if (!S_MIDIMusicDisabled() && S_MIDIExists(mname))
|
||||
return W_GetNumForName(va("d_%s", mname));
|
||||
else if (S_DigMusicDisabled() && S_DigExists(mname))
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, "Digital music is disabled!\n");
|
||||
return LUMPERROR;
|
||||
}
|
||||
else if (S_MIDIMusicDisabled() && S_MIDIExists(mname))
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, "MIDI music is disabled!\n");
|
||||
return LUMPERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), mname);
|
||||
return LUMPERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean S_LoadMusic(const char *mname)
|
||||
{
|
||||
lumpnum_t mlumpnum;
|
||||
|
@ -1508,25 +1806,10 @@ static boolean S_LoadMusic(const char *mname)
|
|||
if (S_MusicDisabled())
|
||||
return false;
|
||||
|
||||
if (!S_DigMusicDisabled() && S_DigExists(mname))
|
||||
mlumpnum = W_GetNumForName(va("o_%s", mname));
|
||||
else if (!S_MIDIMusicDisabled() && S_MIDIExists(mname))
|
||||
mlumpnum = W_GetNumForName(va("d_%s", mname));
|
||||
else if (S_DigMusicDisabled() && S_DigExists(mname))
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, "Digital music is disabled!\n");
|
||||
mlumpnum = S_GetMusicLumpNum(mname);
|
||||
|
||||
if (mlumpnum == LUMPERROR)
|
||||
return false;
|
||||
}
|
||||
else if (S_MIDIMusicDisabled() && S_MIDIExists(mname))
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, "MIDI music is disabled!\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), mname);
|
||||
return false;
|
||||
}
|
||||
|
||||
// load & register it
|
||||
mdata = W_CacheLumpNum(mlumpnum, PU_MUSIC);
|
||||
|
@ -1716,6 +1999,8 @@ void S_PauseAudio(void)
|
|||
#else
|
||||
I_StopCD();
|
||||
#endif
|
||||
|
||||
S_SetStackAdjustmentStart();
|
||||
}
|
||||
|
||||
void S_ResumeAudio(void)
|
||||
|
@ -1725,6 +2010,8 @@ void S_ResumeAudio(void)
|
|||
|
||||
// resume cd music
|
||||
I_ResumeCD();
|
||||
|
||||
S_AdjustMusicStackTics();
|
||||
}
|
||||
|
||||
void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume)
|
||||
|
@ -1811,6 +2098,11 @@ void S_StartEx(boolean reset)
|
|||
if (cv_resetmusic.value || reset)
|
||||
S_StopMusic();
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
|
||||
S_ResetMusicStack();
|
||||
music_stack_noposition = false;
|
||||
music_stack_fadeout = 0;
|
||||
music_stack_fadein = JINGLEPOSTFADE;
|
||||
}
|
||||
|
||||
static void Command_Tunes_f(void)
|
||||
|
|
|
@ -188,6 +188,34 @@ boolean S_SetMusicPosition(UINT32 position);
|
|||
// Get Position of Music
|
||||
UINT32 S_GetMusicPosition(void);
|
||||
|
||||
//
|
||||
// Music Stacking (Jingles)
|
||||
//
|
||||
|
||||
typedef struct musicstack_s
|
||||
{
|
||||
char musname[7];
|
||||
UINT16 musflags;
|
||||
boolean looping;
|
||||
UINT32 position;
|
||||
tic_t tic;
|
||||
UINT16 status;
|
||||
lumpnum_t mlumpnum;
|
||||
|
||||
struct musicstack_s *prev;
|
||||
struct musicstack_s *next;
|
||||
} musicstack_t;
|
||||
|
||||
char music_stack_nextmusname[7];
|
||||
boolean music_stack_noposition;
|
||||
UINT32 music_stack_fadeout;
|
||||
UINT32 music_stack_fadein;
|
||||
|
||||
void S_SetStackAdjustmentStart(void);
|
||||
void S_AdjustMusicStackTics(void);
|
||||
void S_RetainMusic(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status);
|
||||
boolean S_RecallMusic(UINT16 status, boolean fromfirst);
|
||||
|
||||
//
|
||||
// Music Playback
|
||||
//
|
||||
|
|
|
@ -64,7 +64,6 @@
|
|||
#include "../m_menu.h"
|
||||
#include "../d_main.h"
|
||||
#include "../s_sound.h"
|
||||
#include "../i_sound.h" // midi pause/unpause
|
||||
#include "../i_joy.h"
|
||||
#include "../st_stuff.h"
|
||||
#include "../g_game.h"
|
||||
|
@ -573,7 +572,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
|
|||
// Tell game we got focus back, resume music if necessary
|
||||
window_notinfocus = false;
|
||||
if (!paused)
|
||||
I_ResumeSong(); //resume it
|
||||
S_ResumeAudio(); //resume it
|
||||
|
||||
if (!firsttimeonmouse)
|
||||
{
|
||||
|
@ -585,7 +584,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
|
|||
{
|
||||
// Tell game we lost focus, pause music
|
||||
window_notinfocus = true;
|
||||
I_PauseSong();
|
||||
S_PauseAudio();
|
||||
|
||||
if (!disable_mouse)
|
||||
{
|
||||
|
|
|
@ -106,6 +106,7 @@ static UINT32 fading_timer;
|
|||
static UINT32 fading_duration;
|
||||
static INT32 fading_id;
|
||||
static void (*fading_callback)(void);
|
||||
static boolean fading_nocleanup;
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
static Music_Emu *gme;
|
||||
|
@ -203,7 +204,12 @@ static void var_cleanup(void)
|
|||
songpaused = is_looping =\
|
||||
is_fading = false;
|
||||
|
||||
fading_callback = NULL;
|
||||
// HACK: See music_loop, where we want the fade timing to proceed after a non-looping
|
||||
// song has stopped playing
|
||||
if (!fading_nocleanup)
|
||||
fading_callback = NULL;
|
||||
else
|
||||
fading_nocleanup = false; // use it once, set it back immediately
|
||||
|
||||
internal_volume = 100;
|
||||
}
|
||||
|
@ -236,6 +242,8 @@ void I_StartupSound(void)
|
|||
return;
|
||||
}
|
||||
|
||||
fading_nocleanup = false;
|
||||
|
||||
var_cleanup();
|
||||
|
||||
music = NULL;
|
||||
|
@ -685,7 +693,15 @@ static void music_loop(void)
|
|||
music_bytes = (UINT32)(loop_point*44100.0L*4); //assume 44.1khz, 4-byte length (see I_GetSongPosition)
|
||||
}
|
||||
else
|
||||
{
|
||||
// HACK: Let fade timing proceed beyond the end of a
|
||||
// non-looping song. This is a specific case where the timing
|
||||
// should persist after stopping a song, so I don't believe
|
||||
// this should apply every time the user stops a song.
|
||||
// This is auto-unset in var_cleanup, called by I_StopSong
|
||||
fading_nocleanup = true;
|
||||
I_StopSong();
|
||||
}
|
||||
}
|
||||
|
||||
static UINT32 music_fade(UINT32 interval, void *param)
|
||||
|
@ -1381,7 +1397,10 @@ boolean I_PlaySong(boolean looping)
|
|||
|
||||
void I_StopSong(void)
|
||||
{
|
||||
I_StopFadingSong();
|
||||
// HACK: See music_loop on why we want fade timing to proceed
|
||||
// after end of song
|
||||
if (!fading_nocleanup)
|
||||
I_StopFadingSong();
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
|
@ -1522,6 +1541,8 @@ void I_StopFadingSong(void)
|
|||
SDL_RemoveTimer(fading_id);
|
||||
is_fading = false;
|
||||
fading_source = fading_target = fading_timer = fading_duration = fading_id = 0;
|
||||
// don't unset fading_nocleanup here just yet; fading_callback is cleaned up
|
||||
// in var_cleanup()
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "fabdxlib.h"
|
||||
#include "win_main.h"
|
||||
#include "win_dbg.h"
|
||||
#include "../i_sound.h" // midi pause/unpause
|
||||
#include "../s_sound.h" // pause sound with handling
|
||||
#include "../g_input.h" // KEY_MOUSEWHEELxxx
|
||||
#include "../screen.h" // for BASEVID*
|
||||
|
||||
|
@ -110,9 +110,9 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
|
|||
|
||||
// pause music when alt-tab
|
||||
if (appActive && !paused)
|
||||
I_ResumeSong();
|
||||
S_ResumeAudio();
|
||||
else if (!paused)
|
||||
I_PauseSong();
|
||||
S_PauseAudio();
|
||||
{
|
||||
HANDLE ci = GetStdHandle(STD_INPUT_HANDLE);
|
||||
DWORD mode;
|
||||
|
|
Loading…
Reference in a new issue