mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Stereo mode
- Minimum viable implementation
- New horizontal menu
- FUTURE WORK: visuals are extremely basic
- Accessible from both Extras and in-game Pause if SECRET_SOUNDTEST is unlocked
- Rather than the Shadow-the-Hedgehog style free select of SRB2's Sound Test, it's a Best Of The Hacks And Fan Music Sega CD player.
- Back
- Exit menu
- Stop
- Stops Stereo music entirely
- Pause
- Pauses Stereo music without losing place in sequence
- FUTURE WORK: This should probably just pause the actual player ala minimised viewport
- Play
- Begins Stereo music on non-NULL musicdef entry
- Track
- For NULL soundtest entry:
- Switches between sfx
- For musicdefs with multiple tracks:
- Switches between them
- Prev and Next
- Changes musicdef entry
- FUTURE WORK: This is extremely naive and doesn't respect the following
- Cup order
- Unlocks
- Overrides all game-requested music changes when in Play or Pause mode
- This makes it an actual fun in-game feature as a menuification of the `tunes` command, not just a pure novelty.
This commit is contained in:
parent
afff038e34
commit
8f592c196f
9 changed files with 351 additions and 3 deletions
|
|
@ -426,10 +426,14 @@ extern menuitem_t MISC_ChallengesStatsDummyMenu[];
|
|||
extern menu_t MISC_ChallengesDef;
|
||||
extern menu_t MISC_StatisticsDef;
|
||||
|
||||
extern menuitem_t MISC_SoundTest[];
|
||||
extern menu_t MISC_SoundTestDef;
|
||||
|
||||
// We'll need this since we're gonna have to dynamically enable and disable options depending on which state we're in.
|
||||
typedef enum
|
||||
{
|
||||
mpause_addons = 0,
|
||||
mpause_stereo,
|
||||
mpause_changegametype,
|
||||
mpause_switchmap,
|
||||
mpause_restartmap,
|
||||
|
|
@ -1203,6 +1207,9 @@ void M_Statistics(INT32 choice);
|
|||
void M_DrawStatistics(void);
|
||||
boolean M_StatisticsInputs(INT32 ch);
|
||||
|
||||
void M_SoundTest(INT32 choice);
|
||||
void M_DrawSoundTest(void);
|
||||
|
||||
// These defines make it a little easier to make menus
|
||||
#define DEFAULTMENUSTYLE(source, prev, x, y)\
|
||||
{\
|
||||
|
|
|
|||
|
|
@ -5925,3 +5925,54 @@ void M_DrawStatistics(void)
|
|||
}
|
||||
|
||||
#undef STATSSTEP
|
||||
|
||||
void M_DrawSoundTest(void)
|
||||
{
|
||||
INT32 x = currentMenu->x - menutransition.tics*48, y, i, w, cursorx = 0;
|
||||
|
||||
if (gamestate == GS_MENU)
|
||||
{
|
||||
patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE);
|
||||
V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL);
|
||||
}
|
||||
|
||||
y = 50;
|
||||
|
||||
if (soundtest.current != NULL)
|
||||
{
|
||||
V_DrawThinString(x, y, (soundtest.playing ? highlightflags : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->title);
|
||||
V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("%d", soundtest.currenttrack));
|
||||
if (soundtest.current->author)
|
||||
V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->author);
|
||||
if (soundtest.current->source)
|
||||
V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->source);
|
||||
if (soundtest.current->composers)
|
||||
V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->composers);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *sfxstr = (cv_soundtest.value) ? S_sfx[cv_soundtest.value].name : "N/A";
|
||||
V_DrawThinString(x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE, sfxstr);
|
||||
V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("%d", cv_soundtest.value));
|
||||
}
|
||||
|
||||
y = currentMenu->y;
|
||||
|
||||
for (i = 0; i < currentMenu->numitems; i++)
|
||||
{
|
||||
w = V_ThinStringWidth(currentMenu->menuitems[i].text, V_6WIDTHSPACE);
|
||||
if (i == itemOn)
|
||||
{
|
||||
cursorx = x + w/2;
|
||||
V_DrawThinString(x, y, V_6WIDTHSPACE|highlightflags, currentMenu->menuitems[i].text);
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawThinString(x, y, V_6WIDTHSPACE, currentMenu->menuitems[i].text);
|
||||
}
|
||||
x += w + 8;
|
||||
}
|
||||
|
||||
V_DrawCharacter(cursorx - 4, currentMenu->y - 8 - (skullAnimCounter/5),
|
||||
'\x1B' | V_SNAPTOTOP|highlightflags, false); // up arrow
|
||||
}
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ void M_PlayMenuJam(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (Playing())
|
||||
if (Playing() || soundtest.playing)
|
||||
return;
|
||||
|
||||
if (refMenu != NULL && refMenu->music != NULL)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ menuitem_t EXTRAS_Main[] =
|
|||
|
||||
{IT_STRING | IT_CALL, NULL, NULL,
|
||||
NULL, {.routine = M_ReplayHut}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, NULL, NULL,
|
||||
NULL, {.routine = M_SoundTest}, 0, 0},
|
||||
};
|
||||
|
||||
// the extras menu essentially reuses the options menu stuff
|
||||
|
|
@ -49,6 +52,8 @@ struct extrasmenu_s extrasmenu;
|
|||
|
||||
void M_InitExtras(INT32 choice)
|
||||
{
|
||||
UINT32 maxvalid = 2;
|
||||
|
||||
(void)choice;
|
||||
|
||||
extrasmenu.ticker = 0;
|
||||
|
|
@ -82,6 +87,7 @@ void M_InitExtras(INT32 choice)
|
|||
EXTRAS_Main[3].status = IT_STRING | IT_CALL;
|
||||
EXTRAS_Main[3].text = "Egg TV";
|
||||
EXTRAS_Main[3].tooltip = "Watch the replays you've saved throughout your many races & battles!";
|
||||
maxvalid = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -89,7 +95,25 @@ void M_InitExtras(INT32 choice)
|
|||
EXTRAS_Main[3].text = EXTRAS_Main[3].tooltip = "???";
|
||||
if (EXTRAS_MainDef.lastOn == 3)
|
||||
{
|
||||
EXTRAS_MainDef.lastOn = 2;
|
||||
EXTRAS_MainDef.lastOn = maxvalid;
|
||||
}
|
||||
}
|
||||
|
||||
// Stereo Mode
|
||||
if (M_SecretUnlocked(SECRET_SOUNDTEST, true))
|
||||
{
|
||||
EXTRAS_Main[4].status = IT_STRING | IT_CALL;
|
||||
EXTRAS_Main[4].text = "Stereo Mode";
|
||||
EXTRAS_Main[4].tooltip = "You can listen to your favourite tunes here!";
|
||||
maxvalid = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
EXTRAS_Main[4].status = IT_STRING | IT_TRANSTEXT;
|
||||
EXTRAS_Main[4].text = EXTRAS_Main[4].tooltip = "???";
|
||||
if (EXTRAS_MainDef.lastOn == 4)
|
||||
{
|
||||
EXTRAS_MainDef.lastOn = maxvalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
level-select.c
|
||||
gametype.c
|
||||
manual.c
|
||||
sound-test.c
|
||||
message-box.c
|
||||
pause-game.c
|
||||
pause-replay.c
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ menuitem_t PAUSE_Main[] =
|
|||
{IT_STRING | IT_CALL, "ADDONS", "M_ICOADD",
|
||||
NULL, {.routine = M_Addons}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_CALL, "STEREO MODE", "M_ICOSTM",
|
||||
NULL, {.routine = M_SoundTest}, 0, 0},
|
||||
|
||||
{IT_STRING | IT_KEYHANDLER, "GAMETYPE", "M_ICOGAM",
|
||||
NULL, {.routine = M_HandlePauseMenuGametype}, 0, 0},
|
||||
|
||||
|
|
@ -111,6 +114,7 @@ void M_OpenPauseMenu(void)
|
|||
// By default, disable anything sensitive:
|
||||
|
||||
PAUSE_Main[mpause_addons].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_stereo].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_changegametype].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_switchmap].status = IT_DISABLED;
|
||||
PAUSE_Main[mpause_restartmap].status = IT_DISABLED;
|
||||
|
|
@ -127,6 +131,11 @@ void M_OpenPauseMenu(void)
|
|||
|
||||
Dummymenuplayer_OnChange(); // Make sure the consvar is within bounds of the amount of splitscreen players we have.
|
||||
|
||||
if (M_SecretUnlocked(SECRET_SOUNDTEST, true))
|
||||
{
|
||||
PAUSE_Main[mpause_stereo].status = IT_STRING | IT_CALL;
|
||||
}
|
||||
|
||||
if (K_CanChangeRules(false))
|
||||
{
|
||||
PAUSE_Main[mpause_psetup].status = IT_STRING | IT_CALL;
|
||||
|
|
|
|||
145
src/menus/transient/sound-test.c
Normal file
145
src/menus/transient/sound-test.c
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/// \file menus/transient/sound-test.c
|
||||
/// \brief Stereo Mode menu
|
||||
|
||||
#include "../../k_menu.h"
|
||||
#include "../../s_sound.h"
|
||||
|
||||
static void M_SoundTestMainControl(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
// Sound test exception
|
||||
if (soundtest.current == NULL || soundtest.current->numtracks == 0)
|
||||
{
|
||||
if (currentMenu->menuitems[itemOn].mvar1 == 1) // Play
|
||||
{
|
||||
soundtest.playing = true;
|
||||
//soundtest.sequence = true;
|
||||
S_UpdateSoundTestDef(false, false);
|
||||
}
|
||||
else if (cv_soundtest.value != 0)
|
||||
{
|
||||
S_StopSounds();
|
||||
|
||||
if (currentMenu->menuitems[itemOn].mvar1 == 0) // Stop
|
||||
{
|
||||
CV_SetValue(&cv_soundtest, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMenu->menuitems[itemOn].mvar1 == 1) // Play
|
||||
{
|
||||
S_SoundTestPlay();
|
||||
}
|
||||
else if (soundtest.playing == true)
|
||||
{
|
||||
S_SoundTestStop((currentMenu->menuitems[itemOn].mvar1 == 2));
|
||||
}
|
||||
}
|
||||
|
||||
static void M_SoundTestNextPrev(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
S_UpdateSoundTestDef((currentMenu->menuitems[itemOn].mvar1 < 0), false);
|
||||
}
|
||||
|
||||
static void M_SoundTestTrack(INT32 choice)
|
||||
{
|
||||
const UINT8 numtracks = (soundtest.current != NULL) ? soundtest.current->numtracks : 0;
|
||||
|
||||
if (numtracks == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Soundtest exception
|
||||
if (numtracks == 0)
|
||||
{
|
||||
S_StopSounds();
|
||||
|
||||
if (choice == -1) // Extra
|
||||
{
|
||||
if (cv_soundtest.value != 0)
|
||||
CV_SetValue(&cv_soundtest, 0);
|
||||
}
|
||||
else if (choice == 2) // Confirm
|
||||
{
|
||||
if (cv_soundtest.value != 0)
|
||||
S_StartSound(NULL, cv_soundtest.value);
|
||||
}
|
||||
else // Up or Down
|
||||
{
|
||||
CV_AddValue(&cv_soundtest, ((choice == 0) ? -1 : 1));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (choice == -1) // Extra
|
||||
{
|
||||
soundtest.currenttrack = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Confirm resets the current instance
|
||||
if (choice == 0) // Down
|
||||
{
|
||||
soundtest.currenttrack--;
|
||||
if (soundtest.currenttrack < 0)
|
||||
soundtest.currenttrack = numtracks-1;
|
||||
}
|
||||
else if (choice == 1) // Up
|
||||
{
|
||||
soundtest.currenttrack++;
|
||||
if (soundtest.currenttrack >= numtracks)
|
||||
soundtest.currenttrack = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (soundtest.playing)
|
||||
{
|
||||
S_SoundTestPlay();
|
||||
}
|
||||
}
|
||||
|
||||
menuitem_t MISC_SoundTest[] =
|
||||
{
|
||||
{IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0},
|
||||
{IT_STRING | IT_CALL, "Stop", NULL, NULL, {.routine = M_SoundTestMainControl}, 0, 0},
|
||||
{IT_STRING | IT_CALL, "Pause", NULL, NULL, {.routine = M_SoundTestMainControl}, 2, 0},
|
||||
{IT_STRING | IT_CALL, "Play", NULL, NULL, {.routine = M_SoundTestMainControl}, 1, 0},
|
||||
{IT_STRING | IT_ARROWS, "Track", NULL, NULL, {.routine = M_SoundTestTrack}, 0, 0},
|
||||
{IT_STRING | IT_CALL, "Prev", NULL, NULL, {.routine = M_SoundTestNextPrev}, -1, 0},
|
||||
{IT_STRING | IT_CALL, "Next", NULL, NULL, {.routine = M_SoundTestNextPrev}, 1, 0},
|
||||
};
|
||||
|
||||
menu_t MISC_SoundTestDef = {
|
||||
sizeof (MISC_SoundTest)/sizeof (menuitem_t),
|
||||
&MainDef,
|
||||
0,
|
||||
MISC_SoundTest,
|
||||
42, BASEVIDHEIGHT/2,
|
||||
0, 0,
|
||||
MBF_UD_LR_FLIPPED|MBF_SOUNDLESS,
|
||||
".",
|
||||
98, 0,
|
||||
M_DrawSoundTest,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void M_SoundTest(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
// I reserve the right to add some sort of setup here -- toast 250323
|
||||
|
||||
MISC_SoundTestDef.prevMenu = currentMenu;
|
||||
M_SetupNextMenu(&MISC_SoundTestDef, false);
|
||||
}
|
||||
101
src/s_sound.c
101
src/s_sound.c
|
|
@ -1360,9 +1360,108 @@ static tic_t pause_starttic;
|
|||
|
||||
musicdef_t *musicdefstart = NULL;
|
||||
struct cursongcredit cursongcredit; // Currently displayed song credit info
|
||||
struct soundtest soundtest; // Sound Test (sound test)
|
||||
|
||||
void S_UpdateSoundTestDef(boolean reverse, boolean skipnull)
|
||||
{
|
||||
musicdef_t *newdef;
|
||||
|
||||
// Naive implementation for now.
|
||||
|
||||
newdef = (soundtest.current != NULL
|
||||
&& (skipnull == false || soundtest.current->next != NULL))
|
||||
? soundtest.current->next
|
||||
: musicdefstart;
|
||||
|
||||
if (reverse == false)
|
||||
{
|
||||
// Due to how musicdefs are populated, we have to traverse backwards when attempting forwards.
|
||||
musicdef_t *def;
|
||||
|
||||
if (soundtest.current == musicdefstart)
|
||||
{
|
||||
newdef = NULL;
|
||||
if (skipnull == false)
|
||||
{
|
||||
goto conclusion;
|
||||
}
|
||||
}
|
||||
|
||||
for (def = musicdefstart; def; def = def->next)
|
||||
{
|
||||
if (def->next != soundtest.current)
|
||||
continue;
|
||||
|
||||
newdef = def;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
conclusion:
|
||||
soundtest.current = newdef;
|
||||
soundtest.currenttrack = 0;
|
||||
|
||||
if (soundtest.playing == true)
|
||||
{
|
||||
if (newdef == NULL)
|
||||
{
|
||||
S_SoundTestStop(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
S_SoundTestPlay();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void S_SoundTestPlay(void)
|
||||
{
|
||||
soundtest.privilegedrequest = true;
|
||||
|
||||
S_StopMusic();
|
||||
|
||||
soundtest.playing = true;
|
||||
|
||||
S_ChangeMusicInternal(soundtest.current->name[soundtest.currenttrack], true);
|
||||
S_ShowMusicCredit();
|
||||
|
||||
soundtest.privilegedrequest = false;
|
||||
}
|
||||
|
||||
void S_SoundTestStop(boolean pause)
|
||||
{
|
||||
if (soundtest.playing == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
soundtest.privilegedrequest = true;
|
||||
|
||||
S_StopMusic();
|
||||
cursongcredit.def = NULL;
|
||||
|
||||
if (pause == false)
|
||||
{
|
||||
soundtest.playing = false;
|
||||
soundtest.current = NULL;
|
||||
soundtest.currenttrack = 0;
|
||||
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
P_RestoreMusic(&players[consoleplayer]);
|
||||
}
|
||||
}
|
||||
|
||||
soundtest.privilegedrequest = false;
|
||||
}
|
||||
|
||||
boolean S_PlaysimMusicDisabled(void)
|
||||
{
|
||||
return (demo.rewinding // Don't mess with music while rewinding!
|
||||
if (soundtest.privilegedrequest)
|
||||
return false;
|
||||
|
||||
return (soundtest.playing // Ring Racers: Stereo Mode
|
||||
|| demo.rewinding // Don't mess with music while rewinding!
|
||||
|| demo.title); // SRB2Kart: Demos don't interrupt title screen music
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -200,6 +200,18 @@ extern struct cursongcredit
|
|||
fixed_t old_x;
|
||||
} cursongcredit;
|
||||
|
||||
extern struct soundtest
|
||||
{
|
||||
boolean playing; // Music is playing?
|
||||
boolean privilegedrequest; // Overrides S_PlaysimMusicDisabled w/o changing every function signature
|
||||
musicdef_t *current; // Current selected music definition
|
||||
SINT8 currenttrack; // Current selected music track for definition
|
||||
} soundtest;
|
||||
|
||||
void S_UpdateSoundTestDef(boolean reverse, boolean skipnull);
|
||||
void S_SoundTestPlay(void);
|
||||
void S_SoundTestStop(boolean pause);
|
||||
|
||||
boolean S_PlaysimMusicDisabled(void);
|
||||
|
||||
extern musicdef_t *musicdefstart;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue