mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-18 07:22:28 +00:00
musicplus-jingle 2.2 -> 2.1 backport
This commit is contained in:
parent
e4f48cfb71
commit
c60d61a493
12 changed files with 605 additions and 63 deletions
|
@ -7190,6 +7190,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.
|
||||
|
|
|
@ -3056,10 +3056,10 @@ void A_Invincibility(mobj_t *actor)
|
|||
|
||||
if (P_IsLocalPlayer(player) && !player->powers[pw_super])
|
||||
{
|
||||
S_StopMusic();
|
||||
if (mariomode)
|
||||
G_GhostAddColor(GHC_INVINCIBLE);
|
||||
S_ChangeMusicInternal((mariomode) ? "minvnc" : "invinc", false);
|
||||
P_PlayJingle(player, (mariomode) ? JT_MINV : JT_INV);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3093,10 +3093,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2088,10 +2088,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
|||
if (target->player->lives <= 0) // Tails 03-14-2000
|
||||
{
|
||||
if (P_IsLocalPlayer(target->player)/* && target->player == &players[consoleplayer] */)
|
||||
{
|
||||
S_StopMusic(); // Stop the Music! Tails 03-14-2000
|
||||
S_ChangeMusicInternal("gmover", false); // Yousa dead now, Okieday? Tails 03-14-2000
|
||||
}
|
||||
P_PlayJingle(target->player, JT_GOVER); // Yousa dead now, Okieday? Tails 03-14-2000
|
||||
}
|
||||
}
|
||||
target->player->playerstate = PST_DEAD;
|
||||
|
@ -2466,7 +2463,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source)
|
|||
&& player->nightstime < 10*TICRATE)
|
||||
{
|
||||
//S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH
|
||||
S_ChangeMusicInternal("drown",false);
|
||||
P_PlayJingle(player, ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? JT_NIGHTSTIMEOUT : JT_SSTIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -184,6 +184,46 @@ void P_PlayLivesJingle(player_t *player);
|
|||
#define P_PlayDeathSound(s) S_StartSound(s, sfx_altdi1 + P_RandomKey(4));
|
||||
#define P_PlayVictorySound(s) S_StartSound(s, sfx_victr1 + P_RandomKey(4));
|
||||
|
||||
/// ------------------------
|
||||
/// 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
|
||||
|
|
|
@ -1514,19 +1514,33 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
|
|||
{
|
||||
M_Memcpy(process,msd->bottomtexture,8);
|
||||
process[8] = '\0';
|
||||
sd->bottomtexture = get_number(process)-1;
|
||||
sd->bottomtexture = get_number(process);
|
||||
}
|
||||
M_Memcpy(process,msd->toptexture,8);
|
||||
process[8] = '\0';
|
||||
sd->text = Z_Malloc(7, PU_LEVEL, NULL);
|
||||
|
||||
// If they type in O_ or D_ and their music name, just shrug,
|
||||
// then copy the rest instead.
|
||||
if ((process[0] == 'O' || process[0] == 'D') && process[7])
|
||||
M_Memcpy(sd->text, process+2, 6);
|
||||
else // Assume it's a proper music name.
|
||||
M_Memcpy(sd->text, process, 6);
|
||||
sd->text[6] = 0;
|
||||
if (!(msd->midtexture[0] == '-' && msd->midtexture[1] == '\0') || msd->midtexture[1] != '\0')
|
||||
{
|
||||
M_Memcpy(process,msd->midtexture,8);
|
||||
process[8] = '\0';
|
||||
sd->midtexture = get_number(process);
|
||||
}
|
||||
|
||||
// always process if back sidedef, because we need that - symbol
|
||||
sd->text = Z_Malloc(7, PU_LEVEL, NULL);
|
||||
if (i == 1 || msd->toptexture[0] != '-' || msd->toptexture[1] != '\0')
|
||||
{
|
||||
M_Memcpy(process,msd->toptexture,8);
|
||||
process[8] = '\0';
|
||||
|
||||
// If they type in O_ or D_ and their music name, just shrug,
|
||||
// then copy the rest instead.
|
||||
if ((process[0] == 'O' || process[0] == 'D') && process[7])
|
||||
M_Memcpy(sd->text, process+2, 6);
|
||||
else // Assume it's a proper music name.
|
||||
M_Memcpy(sd->text, process, 6);
|
||||
sd->text[6] = 0;
|
||||
}
|
||||
else
|
||||
sd->text[0] = 0;
|
||||
break;
|
||||
}
|
||||
case 414: // Play SFX
|
||||
|
|
58
src/p_spec.c
58
src/p_spec.c
|
@ -2419,18 +2419,60 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
// console player only unless NOCLIMB is set
|
||||
if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player)))
|
||||
{
|
||||
UINT16 tracknum = (UINT16)sides[line->sidenum[0]].bottomtexture;
|
||||
boolean musicsame = (!sides[line->sidenum[0]].text[0] || !strnicmp(sides[line->sidenum[0]].text, S_MusicName(), 7));
|
||||
UINT16 tracknum = (UINT16)max(sides[line->sidenum[0]].bottomtexture, 0);
|
||||
INT32 position = (INT32)max(sides[line->sidenum[0]].midtexture, 0);
|
||||
UINT32 prefadems = (UINT32)max(sides[line->sidenum[0]].textureoffset >> FRACBITS, 0);
|
||||
UINT32 postfadems = (UINT32)max(sides[line->sidenum[0]].rowoffset >> FRACBITS, 0);
|
||||
UINT8 fadetarget = (UINT8)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].textureoffset >> FRACBITS : 0, 0);
|
||||
INT16 fadesource = (INT16)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : 0, -1);
|
||||
|
||||
strncpy(mapmusname, sides[line->sidenum[0]].text, 7);
|
||||
mapmusname[6] = 0;
|
||||
if (line->flags & ML_EFFECT1)
|
||||
{
|
||||
// adjust for loop point if subtracting
|
||||
if (position < 0 && S_GetMusicLength() &&
|
||||
S_GetMusicPosition() > S_GetMusicLoopPoint() &&
|
||||
S_GetMusicPosition() + position < S_GetMusicLoopPoint())
|
||||
position = max(S_GetMusicLength() - (S_GetMusicLoopPoint() - (S_GetMusicPosition() + position)), 0);
|
||||
else
|
||||
position = max(S_GetMusicPosition() + position, 0);
|
||||
}
|
||||
|
||||
mapmusflags = tracknum & MUSIC_TRACKMASK;
|
||||
if (!(line->flags & ML_BLOCKMONSTERS))
|
||||
mapmusflags |= MUSIC_RELOADRESET;
|
||||
if ((line->flags & ML_EFFECT2) && fadetarget && musicsame)
|
||||
{
|
||||
if (!postfadems)
|
||||
S_SetInternalMusicVolume(fadetarget);
|
||||
else
|
||||
S_FadeMusicFromVolume(fadetarget, fadesource, postfadems);
|
||||
|
||||
mapmusposition = 0;
|
||||
if (position)
|
||||
S_SetMusicPosition(position);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(mapmusname, sides[line->sidenum[0]].text, 7);
|
||||
mapmusname[6] = 0;
|
||||
|
||||
S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4));
|
||||
mapmusflags = tracknum & MUSIC_TRACKMASK;
|
||||
if (!(line->flags & ML_BLOCKMONSTERS))
|
||||
mapmusflags |= MUSIC_RELOADRESET;
|
||||
if (line->flags & ML_BOUNCY)
|
||||
mapmusflags |= MUSIC_FORCERESET;
|
||||
|
||||
mapmusposition = position;
|
||||
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4), position,
|
||||
!(line->flags & ML_EFFECT2) ? prefadems : 0,
|
||||
!(line->flags & ML_EFFECT2) ? postfadems : 0);
|
||||
|
||||
if ((line->flags & ML_EFFECT2) && fadetarget)
|
||||
{
|
||||
if (!postfadems)
|
||||
S_SetInternalMusicVolume(fadetarget);
|
||||
else
|
||||
S_FadeMusicFromVolume(fadetarget, fadesource, postfadems);
|
||||
}
|
||||
}
|
||||
|
||||
// Except, you can use the ML_BLOCKMONSTERS flag to change this behavior.
|
||||
// if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn.
|
||||
|
|
|
@ -582,13 +582,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;
|
||||
|
||||
|
|
200
src/p_user.c
200
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
|
||||
{"xtlife" , false},
|
||||
{"shoes" , true},
|
||||
{"invinc" , false},
|
||||
{"minvnc" , false},
|
||||
{"drown" , false},
|
||||
{"supers" , true},
|
||||
{"gmover" , false},
|
||||
{"drown" , false}, // JT_NIGHTSTIMEOUT
|
||||
{"drown" , false} // JT_SSTIMEOUT
|
||||
// {"lclear" , false},
|
||||
// {"racent" , true},
|
||||
// {"contsc" , true}
|
||||
};
|
||||
|
||||
//
|
||||
// Movement.
|
||||
//
|
||||
|
@ -636,6 +659,7 @@ static void P_DeNightserizePlayer(player_t *player)
|
|||
}
|
||||
|
||||
// Restore from drowning music
|
||||
music_stack_fadein = 0; // HACK: Change fade-in for restore music
|
||||
P_RestoreMusic(player);
|
||||
}
|
||||
//
|
||||
|
@ -675,6 +699,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
|
|||
player->nightstime = player->startedtime = nighttime*TICRATE;
|
||||
player->bonustime = false;
|
||||
|
||||
music_stack_fadein = 0; // HACK: Change fade-in for restore music
|
||||
P_RestoreMusic(player);
|
||||
P_SetMobjState(player->mo->tracer, S_SUPERTRANS1);
|
||||
|
||||
|
@ -961,8 +986,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("supers", true);
|
||||
P_PlayJingle(player, JT_SUPER);
|
||||
}
|
||||
|
||||
S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi
|
||||
|
@ -1097,11 +1121,111 @@ void P_PlayLivesJingle(player_t *player)
|
|||
{
|
||||
if (player)
|
||||
player->powers[pw_extralife] = extralifetics + 1;
|
||||
S_StopMusic(); // otherwise it won't restart if this is done twice in a row
|
||||
S_ChangeMusicInternal("xtlife", 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 (!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
|
||||
//
|
||||
|
@ -1112,25 +1236,46 @@ 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("supers", 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)
|
||||
S_ChangeMusicInternal((mariomode) ? "minvnc" : "invinc", 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])
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2017,10 +2162,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);
|
||||
|
||||
|
@ -2105,15 +2246,18 @@ 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;
|
||||
P_RestoreMusic(player);
|
||||
}
|
||||
|
||||
// Underwater audio cues
|
||||
|
@ -2122,8 +2266,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);
|
||||
}
|
||||
|
||||
if (player->powers[pw_underwater] == 25*TICRATE + 1)
|
||||
|
@ -2185,10 +2328,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);
|
||||
}
|
||||
|
@ -3410,6 +3549,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);
|
||||
|
||||
|
@ -3511,6 +3652,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.
|
||||
|
@ -5576,13 +5719,14 @@ static void P_NiGHTSMovement(player_t *player)
|
|||
P_DeNightserizePlayer(player);
|
||||
S_StartScreamSound(player->mo, sfx_s3k66);
|
||||
// S_StopSoundByNum(sfx_timeup); // Kill the "out of time" music, if it's playing. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH
|
||||
music_stack_fadein = 0; // HACK: Change fade-in for restore music
|
||||
P_RestoreMusic(player); // I have my doubts that this is the right place for this...
|
||||
|
||||
return;
|
||||
}
|
||||
else if (P_IsLocalPlayer(player) && player->nightstime == 10*TICRATE)
|
||||
// S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH
|
||||
S_ChangeMusicInternal("drown",false);
|
||||
P_PlayJingle(player, ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? JT_NIGHTSTIMEOUT : JT_SSTIMEOUT);
|
||||
|
||||
|
||||
if (player->mo->z < player->mo->floorz)
|
||||
|
@ -8754,7 +8898,7 @@ void P_PlayerThink(player_t *player)
|
|||
if (countdown == 11*TICRATE - 1)
|
||||
{
|
||||
if (P_IsLocalPlayer(player))
|
||||
S_ChangeMusicInternal("drown", false);
|
||||
P_PlayJingle(player, JT_DROWN);
|
||||
}
|
||||
|
||||
// If you've hit the countdown and you haven't made
|
||||
|
|
261
src/s_sound.c
261
src/s_sound.c
|
@ -1229,6 +1229,10 @@ static boolean queue_looping;
|
|||
static UINT32 queue_position;
|
||||
static UINT32 queue_fadeinms;
|
||||
|
||||
static musicstack_t music_stack[NUMMUSICSTACKS];
|
||||
|
||||
static tic_t pause_starttic;
|
||||
|
||||
/// ------------------------
|
||||
/// Music Status
|
||||
/// ------------------------
|
||||
|
@ -1327,6 +1331,254 @@ 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 const musicstack_t empty_music_stack_entry = {{0}};
|
||||
|
||||
void S_SetStackAdjustmentStart(void)
|
||||
{
|
||||
if (!pause_starttic)
|
||||
pause_starttic = gametic;
|
||||
}
|
||||
|
||||
void S_AdjustMusicStackTics(void)
|
||||
{
|
||||
if (pause_starttic)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < NUMMUSICSTACKS-1; i++)
|
||||
{
|
||||
if (!music_stack[i].status)
|
||||
break;
|
||||
music_stack[i].tic += gametic - pause_starttic;
|
||||
}
|
||||
pause_starttic = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void S_ResetMusicStack()
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < NUMMUSICSTACKS; i++)
|
||||
music_stack[i] = empty_music_stack_entry;
|
||||
}
|
||||
|
||||
static void S_RemoveMusicStackEntry(size_t i)
|
||||
{
|
||||
for (; i < NUMMUSICSTACKS-1; i++)
|
||||
{
|
||||
strncpy(music_stack[i].musname, music_stack[i+1].musname, 7);
|
||||
music_stack[i].musname[6] = 0;
|
||||
music_stack[i].musflags = music_stack[i+1].musflags;
|
||||
music_stack[i].looping = music_stack[i+1].looping;
|
||||
music_stack[i].position = music_stack[i+1].position;
|
||||
music_stack[i].tic = music_stack[i+1].tic;
|
||||
music_stack[i].status = music_stack[i+1].status;
|
||||
|
||||
if (!music_stack[i].status)
|
||||
break;
|
||||
}
|
||||
|
||||
// clear the last slot
|
||||
music_stack[NUMMUSICSTACKS-1] = empty_music_stack_entry;
|
||||
}
|
||||
|
||||
static void S_RemoveMusicStackEntryByStatus(UINT16 status)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!status)
|
||||
return;
|
||||
|
||||
for (i = 0; i < NUMMUSICSTACKS-1; i++)
|
||||
{
|
||||
if (music_stack[i].status == status)
|
||||
{
|
||||
S_RemoveMusicStackEntry(i);
|
||||
i--; // try this position again
|
||||
}
|
||||
else if (!music_stack[i].status)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
// if the first entry is empty, force master onto it
|
||||
if (!music_stack[0].status && status != JT_MASTER)
|
||||
S_AddMusicStackEntry(mapmusname, mapmusflags, true, S_GetMusicPosition(), JT_MASTER);
|
||||
|
||||
// are all slots taken? forget the earliest one (save master) and move down the rest
|
||||
if (music_stack[NUMMUSICSTACKS-1].status)
|
||||
S_RemoveMusicStackEntry(1);
|
||||
|
||||
// look for an empty slot to park ourselves
|
||||
for (i = 0; i < NUMMUSICSTACKS; i++)
|
||||
{
|
||||
// entry doesn't exist? park ourselves here!
|
||||
if (!music_stack[i].status)
|
||||
{
|
||||
strncpy(music_stack[i].musname, mname, 7);
|
||||
music_stack[i].musname[6] = 0;
|
||||
music_stack[i].musflags = mflags;
|
||||
music_stack[i].looping = looping;
|
||||
music_stack[i].position = position;
|
||||
music_stack[i].tic = gametic;
|
||||
music_stack[i].status = status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static musicstack_t S_GetMusicStackEntry(UINT16 status, boolean fromfirst, INT16 startindex)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
// if the first entry is empty, force master onto it
|
||||
// fixes a memory corruption bug
|
||||
if (!music_stack[0].status && status != JT_MASTER)
|
||||
S_AddMusicStackEntry(mapmusname, mapmusflags, true, S_GetMusicPosition(), JT_MASTER);
|
||||
|
||||
if (startindex < 0)
|
||||
startindex = fromfirst ? 0 : NUMMUSICSTACKS-1;
|
||||
|
||||
if (fromfirst)
|
||||
{
|
||||
for (i = startindex; i < NUMMUSICSTACKS; i++)
|
||||
{
|
||||
if (!music_stack[i].status) // we're counting up, so this must mean we reached the end
|
||||
break;
|
||||
else if (!status || music_stack[i].status == status)
|
||||
{
|
||||
if (P_EvaluateMusicStatus(music_stack[i].status))
|
||||
{
|
||||
if (!S_MusicExists(music_stack[i].musname, !midi_disabled, !digital_disabled)) // paranoia
|
||||
S_RemoveMusicStackEntry(i); // then continue
|
||||
else
|
||||
return music_stack[i];
|
||||
}
|
||||
else
|
||||
S_RemoveMusicStackEntry(i); // then continue
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = startindex; i >= 0; i--)
|
||||
{
|
||||
if (!music_stack[i].status) // since we're counting down, we have to skip a few...
|
||||
continue;
|
||||
else if (!status || music_stack[i].status == status)
|
||||
{
|
||||
if (P_EvaluateMusicStatus(music_stack[i].status))
|
||||
{
|
||||
if (!S_MusicExists(music_stack[i].musname, !midi_disabled, !digital_disabled)) // paranoia
|
||||
S_RemoveMusicStackEntry(i); // then continue
|
||||
else
|
||||
return music_stack[i];
|
||||
}
|
||||
else
|
||||
S_RemoveMusicStackEntry(i); // then continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return empty_music_stack_entry;
|
||||
}
|
||||
|
||||
void S_RetainMusic(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
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 (i = 0; i < NUMMUSICSTACKS; i++)
|
||||
{
|
||||
if (music_stack[i].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 entry;
|
||||
|
||||
if (status)
|
||||
entry = S_GetMusicStackEntry(status, fromfirst, -1);
|
||||
else
|
||||
entry = S_GetMusicStackEntry(JT_NONE, false, -1);
|
||||
|
||||
if (!S_MusicExists(entry.musname, !midi_disabled, !digital_disabled))
|
||||
return false; // bad bad bad!!
|
||||
|
||||
// no result, just grab mapmusname
|
||||
if (!entry.musname[0] || ((status == JT_MASTER || !music_stack[0].status) && !entry.status))
|
||||
{
|
||||
strncpy(entry.musname, mapmusname, 7);
|
||||
entry.musflags = mapmusflags;
|
||||
entry.looping = true;
|
||||
entry.position = mapmusposition;
|
||||
entry.tic = gametic;
|
||||
entry.status = JT_MASTER;
|
||||
}
|
||||
|
||||
if (entry.status == JT_MASTER)
|
||||
{
|
||||
mapmuschanged = (boolean)strnicmp(entry.musname, mapmusname, 7);
|
||||
S_ResetMusicStack();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!entry.status)
|
||||
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
|
||||
newpos = entry.position + (S_GetMusicLength() ? (UINT32)((float)(gametic - entry.tic)/(float)TICRATE*(float)MUSICRATE) : 0);
|
||||
|
||||
if (newpos > 0 && S_MusicPlaying())
|
||||
S_SetMusicPosition(newpos);
|
||||
else
|
||||
{
|
||||
S_StopFadingMusic();
|
||||
S_SetInternalMusicVolume(100);
|
||||
}
|
||||
}
|
||||
music_stack_noposition = false;
|
||||
music_stack_fadeout = 0;
|
||||
music_stack_fadein = JINGLEPOSTFADE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Playback
|
||||
/// ------------------------
|
||||
|
@ -1529,6 +1781,8 @@ void S_PauseAudio(void)
|
|||
#else
|
||||
I_StopCD();
|
||||
#endif
|
||||
|
||||
S_SetStackAdjustmentStart();
|
||||
}
|
||||
|
||||
void S_ResumeAudio(void)
|
||||
|
@ -1538,6 +1792,8 @@ void S_ResumeAudio(void)
|
|||
|
||||
// resume cd music
|
||||
I_ResumeCD();
|
||||
|
||||
S_AdjustMusicStackTics();
|
||||
}
|
||||
|
||||
void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume)
|
||||
|
@ -1623,4 +1879,9 @@ void S_Start(void)
|
|||
if (cv_resetmusic.value)
|
||||
S_StopMusic();
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
|
||||
S_ResetMusicStack();
|
||||
music_stack_noposition = false;
|
||||
music_stack_fadeout = 0;
|
||||
music_stack_fadein = JINGLEPOSTFADE;
|
||||
}
|
||||
|
|
|
@ -140,6 +140,30 @@ boolean S_SetMusicPosition(UINT32 position);
|
|||
// Get Position of Music
|
||||
UINT32 S_GetMusicPosition(void);
|
||||
|
||||
//
|
||||
// Music Stacking (Jingles)
|
||||
//
|
||||
|
||||
typedef struct {
|
||||
char musname[7];
|
||||
UINT16 musflags;
|
||||
boolean looping;
|
||||
UINT32 position;
|
||||
tic_t tic;
|
||||
UINT16 status;
|
||||
} musicstack_t;
|
||||
|
||||
char music_stack_nextmusname[7];
|
||||
boolean music_stack_noposition;
|
||||
UINT32 music_stack_fadeout;
|
||||
UINT32 music_stack_fadein;
|
||||
#define NUMMUSICSTACKS 10 // hahaha wait until someone needs > 10 resumes
|
||||
|
||||
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
|
||||
//
|
||||
|
|
|
@ -62,7 +62,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"
|
||||
|
@ -566,7 +565,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)
|
||||
{
|
||||
|
@ -578,7 +577,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)
|
||||
{
|
||||
|
|
|
@ -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