mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-18 23:42:11 +00:00
Merge branch 'public-musicplus-jingle' into public-notpublic-musicplus-jingle
This commit is contained in:
commit
6244489fd0
11 changed files with 574 additions and 56 deletions
|
@ -7226,6 +7226,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3230,15 +3227,16 @@ void A_WaterShield(mobj_t *actor)
|
|||
}
|
||||
|
||||
if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1)
|
||||
P_RestoreMusic(player);
|
||||
|
||||
player->powers[pw_underwater] = 0;
|
||||
|
||||
if (player->powers[pw_spacetime] > 1)
|
||||
{
|
||||
player->powers[pw_spacetime] = 0;
|
||||
player->powers[pw_underwater] = 0;
|
||||
P_RestoreMusic(player);
|
||||
}
|
||||
else
|
||||
player->powers[pw_underwater] = 0;
|
||||
|
||||
if (player->powers[pw_spacetime] > 1)
|
||||
player->powers[pw_spacetime] = 0;
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
|
|
|
@ -1429,7 +1429,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
// Eaten by player!
|
||||
if (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;
|
||||
|
@ -2088,10 +2091,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 +2466,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,6 +180,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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
208
src/p_user.c
208
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);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2025,10 +2170,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);
|
||||
|
||||
|
@ -2113,16 +2254,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)
|
||||
|
@ -2130,8 +2271,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)
|
||||
|
@ -2193,10 +2333,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);
|
||||
}
|
||||
|
@ -3418,6 +3554,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);
|
||||
|
||||
|
@ -3519,6 +3657,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.
|
||||
|
@ -5584,13 +5724,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)
|
||||
|
@ -8783,7 +8924,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
|
||||
|
@ -9104,9 +9245,12 @@ void P_PlayerThink(player_t *player)
|
|||
if (player->powers[pw_underwater] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL))
|
||||
{
|
||||
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]--;
|
||||
|
|
265
src/s_sound.c
265
src/s_sound.c
|
@ -1251,6 +1251,8 @@ static boolean queue_looping;
|
|||
static UINT32 queue_position;
|
||||
static UINT32 queue_fadeinms;
|
||||
|
||||
static tic_t pause_starttic;
|
||||
|
||||
/// ------------------------
|
||||
/// Music Status
|
||||
/// ------------------------
|
||||
|
@ -1349,6 +1351,260 @@ 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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
Z_Free(entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Playback
|
||||
/// ------------------------
|
||||
|
@ -1557,6 +1813,8 @@ void S_PauseAudio(void)
|
|||
#else
|
||||
I_StopCD();
|
||||
#endif
|
||||
|
||||
S_SetStackAdjustmentStart();
|
||||
}
|
||||
|
||||
void S_ResumeAudio(void)
|
||||
|
@ -1566,6 +1824,8 @@ void S_ResumeAudio(void)
|
|||
|
||||
// resume cd music
|
||||
I_ResumeCD();
|
||||
|
||||
S_AdjustMusicStackTics();
|
||||
}
|
||||
|
||||
void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume)
|
||||
|
@ -1651,6 +1911,11 @@ 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;
|
||||
}
|
||||
|
||||
static void Command_Tunes_f(void)
|
||||
|
|
|
@ -144,6 +144,33 @@ 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;
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -90,6 +90,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;
|
||||
|
@ -105,7 +106,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;
|
||||
}
|
||||
|
@ -137,6 +143,8 @@ void I_StartupSound(void)
|
|||
return;
|
||||
}
|
||||
|
||||
fading_nocleanup = false;
|
||||
|
||||
var_cleanup();
|
||||
|
||||
music = NULL;
|
||||
|
@ -572,7 +580,15 @@ static void music_loop(void)
|
|||
music_bytes = 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)
|
||||
|
@ -1122,7 +1138,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)
|
||||
|
@ -1240,6 +1259,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