mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Pause menu start + map switching
This commit is contained in:
parent
b750ef11dd
commit
e560bffcf7
4 changed files with 361 additions and 16 deletions
27
src/k_menu.h
27
src/k_menu.h
|
|
@ -196,6 +196,12 @@ extern menu_t PLAY_MP_RoomSelectDef;
|
||||||
extern menuitem_t PLAY_BattleGamemodesMenu[];
|
extern menuitem_t PLAY_BattleGamemodesMenu[];
|
||||||
extern menu_t PLAY_BattleGamemodesDef;
|
extern menu_t PLAY_BattleGamemodesDef;
|
||||||
|
|
||||||
|
extern menuitem_t PAUSE_Main[];
|
||||||
|
extern menu_t PAUSE_MainDef;
|
||||||
|
|
||||||
|
extern menuitem_t PAUSE_GamemodesMenu[];
|
||||||
|
extern menu_t PAUSE_GamemodesDef;
|
||||||
|
|
||||||
extern menuitem_t PAUSE_PlaybackMenu[];
|
extern menuitem_t PAUSE_PlaybackMenu[];
|
||||||
extern menu_t PAUSE_PlaybackMenuDef;
|
extern menu_t PAUSE_PlaybackMenuDef;
|
||||||
|
|
||||||
|
|
@ -402,6 +408,24 @@ void M_MPRoomSelect(INT32 choice);
|
||||||
void M_MPRoomSelectTick(void);
|
void M_MPRoomSelectTick(void);
|
||||||
void M_MPRoomSelectInit(INT32 choice);
|
void M_MPRoomSelectInit(INT32 choice);
|
||||||
|
|
||||||
|
// Pause menu:
|
||||||
|
|
||||||
|
// Keep track of some pause menu data for visual goodness.
|
||||||
|
extern struct pausemenu_s {
|
||||||
|
|
||||||
|
tic_t ticker; // How long the menu's been open for
|
||||||
|
INT16 offset; // To make the icons move smoothly when we transition!
|
||||||
|
|
||||||
|
INT16 openoffset; // Used when you open / close the menu to slide everything in.
|
||||||
|
boolean closing; // When this is set, the open offset goes backwards to close the menu smoothly.
|
||||||
|
} pausemenu;
|
||||||
|
|
||||||
|
void M_OpenPauseMenu(void);
|
||||||
|
void M_QuitPauseMenu(void);
|
||||||
|
|
||||||
|
boolean M_PauseInputs(INT32 ch);
|
||||||
|
void M_PauseTick(void);
|
||||||
|
|
||||||
// Replay Playback
|
// Replay Playback
|
||||||
|
|
||||||
extern tic_t playback_last_menu_interaction_leveltime;
|
extern tic_t playback_last_menu_interaction_leveltime;
|
||||||
|
|
@ -443,6 +467,9 @@ void M_DrawMPHost(void);
|
||||||
void M_DrawMPJoinIP(void);
|
void M_DrawMPJoinIP(void);
|
||||||
void M_DrawMPRoomSelect(void);
|
void M_DrawMPRoomSelect(void);
|
||||||
|
|
||||||
|
// Pause menu:
|
||||||
|
void M_DrawPause(void);
|
||||||
|
|
||||||
// Replay Playback
|
// Replay Playback
|
||||||
void M_DrawPlaybackMenu(void);
|
void M_DrawPlaybackMenu(void);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,93 @@ menu_t PLAY_MP_RoomSelectDef = {
|
||||||
// In-game/pause menus
|
// In-game/pause menus
|
||||||
// -------------------
|
// -------------------
|
||||||
|
|
||||||
|
// ESC pause menu
|
||||||
|
// Since there's no descriptions to each item, we'll use the descriptions as the names of the patches we want to draw for each option :)
|
||||||
|
|
||||||
|
menuitem_t PAUSE_Main[] =
|
||||||
|
{
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "ADDONS", "M_ICOADD",
|
||||||
|
NULL, NULL, 0, 0},
|
||||||
|
|
||||||
|
{IT_STRING | IT_SUBMENU, "CHANGE MAP", "M_ICOMAP",
|
||||||
|
NULL, &PAUSE_GamemodesDef, 0, 0},
|
||||||
|
|
||||||
|
#ifdef HAVE_DISCORDRPC
|
||||||
|
{IT_STRING | IT_CALL, "DISCORD REQUESTS", "M_ICODIS",
|
||||||
|
NULL, NULL, 0, 0},
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "RESUME GAME", "M_ICOUNP",
|
||||||
|
NULL, M_QuitPauseMenu, 0, 0},
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "SPECTATE", "M_ICOSPC",
|
||||||
|
NULL, NULL, 0, 0},
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "ENTER GAME", "M_ICOENT",
|
||||||
|
NULL, NULL, 0, 0},
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "CANCEL JOIN", "M_ICOSPC",
|
||||||
|
NULL, NULL, 0, 0},
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "PLAYER SETUP", "M_ICOCHR",
|
||||||
|
NULL, NULL, 0, 0},
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "OPTIONS", "M_ICOOPT",
|
||||||
|
NULL, NULL, 0, 0},
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "EXIT GAME", "M_ICOEXT",
|
||||||
|
NULL, NULL, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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_switchmap,
|
||||||
|
#ifdef HAVE_DISCORDRPC
|
||||||
|
mpause_discordrequests,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mpause_continue,
|
||||||
|
mpause_spectate,
|
||||||
|
mpause_entergame,
|
||||||
|
mpause_canceljoin,
|
||||||
|
mpause_psetup,
|
||||||
|
mpause_options,
|
||||||
|
|
||||||
|
mpause_title,
|
||||||
|
} mpause_e;
|
||||||
|
|
||||||
|
|
||||||
|
menu_t PAUSE_MainDef = {
|
||||||
|
sizeof (PAUSE_Main) / sizeof (menuitem_t),
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
PAUSE_Main,
|
||||||
|
0, 0,
|
||||||
|
1, 10, // For transition with some menus!
|
||||||
|
M_DrawPause,
|
||||||
|
M_PauseTick,
|
||||||
|
NULL,
|
||||||
|
M_PauseInputs
|
||||||
|
};
|
||||||
|
|
||||||
|
// PAUSE : Map switching gametype selection (In case you want to pick from battle / race...)
|
||||||
|
menuitem_t PAUSE_GamemodesMenu[] =
|
||||||
|
{
|
||||||
|
{IT_STRING | IT_CALL, "Race", "Select which gamemode to choose a new map from.",
|
||||||
|
NULL, M_LevelSelectInit, 0, GT_RACE},
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "Battle", "Select which gamemode to choose a new map from.",
|
||||||
|
NULL, M_LevelSelectInit, 0, GT_BATTLE},
|
||||||
|
|
||||||
|
{IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
menu_t PAUSE_GamemodesDef = KARTGAMEMODEMENU(PAUSE_GamemodesMenu, &PAUSE_MainDef);
|
||||||
|
|
||||||
|
// Replay popup menu
|
||||||
menuitem_t PAUSE_PlaybackMenu[] =
|
menuitem_t PAUSE_PlaybackMenu[] =
|
||||||
{
|
{
|
||||||
{IT_CALL | IT_STRING, "Hide Menu (Esc)", NULL, "M_PHIDE", M_SelectableClearMenus, 0, 0},
|
{IT_CALL | IT_STRING, "Hide Menu (Esc)", NULL, "M_PHIDE", M_SelectableClearMenus, 0, 0},
|
||||||
|
|
|
||||||
142
src/k_menudraw.c
142
src/k_menudraw.c
|
|
@ -1589,6 +1589,148 @@ void M_DrawMPRoomSelect(void)
|
||||||
// INGAME / PAUSE MENUS
|
// INGAME / PAUSE MENUS
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// PAUSE
|
||||||
|
|
||||||
|
// PAUSE MAIN MENU
|
||||||
|
void M_DrawPause(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
SINT8 i;
|
||||||
|
SINT8 itemsdrawn = 0;
|
||||||
|
SINT8 countdown = 0;
|
||||||
|
INT16 ypos = -50; // Draw 3 items from selected item (y=100 - 3 items spaced by 50 px each... you get the idea.)
|
||||||
|
INT16 dypos;
|
||||||
|
|
||||||
|
INT16 offset = menutransition.tics ? floor(pow(2, (double)menutransition.tics)) : pausemenu.openoffset;
|
||||||
|
INT16 arrxpos = 150 + 2*offset; // To draw the background arrow.
|
||||||
|
|
||||||
|
INT16 j = 0;
|
||||||
|
char word1[MAXSTRINGLENGTH];
|
||||||
|
INT16 word1len = 0;
|
||||||
|
char word2[MAXSTRINGLENGTH];
|
||||||
|
INT16 word2len = 0;
|
||||||
|
boolean sok = false;
|
||||||
|
|
||||||
|
patch_t *pausebg = W_CachePatchName("M_STRIPU", PU_CACHE);
|
||||||
|
patch_t *vertbg = W_CachePatchName("M_STRIPV", PU_CACHE);
|
||||||
|
patch_t *pausetext = W_CachePatchName("M_PAUSET", PU_CACHE);
|
||||||
|
|
||||||
|
patch_t *arrstart = W_CachePatchName("M_PTIP", PU_CACHE);
|
||||||
|
patch_t *arrfill = W_CachePatchName("M_PFILL", PU_CACHE);
|
||||||
|
|
||||||
|
//V_DrawFadeScreen(0xFF00, 16);
|
||||||
|
|
||||||
|
// "PAUSED"
|
||||||
|
V_DrawFixedPatch(-offset*FRACUNIT, 0, FRACUNIT, V_ADD, pausebg, NULL);
|
||||||
|
V_DrawFixedPatch(-offset*FRACUNIT, 0, FRACUNIT, 0, pausetext, NULL);
|
||||||
|
|
||||||
|
// Vertical Strip:
|
||||||
|
V_DrawFixedPatch((230 + offset)<<FRACBITS, 0, FRACUNIT, V_ADD, vertbg, NULL);
|
||||||
|
|
||||||
|
// Okay that's cool but which icon do we draw first? let's roll back from itemOn!
|
||||||
|
// At most we'll draw 7 items, 1 in the center, 3 above, 3 below.
|
||||||
|
// Which means... let's count down from itemOn
|
||||||
|
for (i = itemOn; countdown < 3; countdown++)
|
||||||
|
{
|
||||||
|
//CONS_Printf("pass %d: %d\n", countdown, i);
|
||||||
|
i--;
|
||||||
|
if (i < 0)
|
||||||
|
i = currentMenu->numitems-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aaaaand now we can start drawing!
|
||||||
|
// Reminder that we set the patches of the options to the description since we're not using that. I'm smart, I know...
|
||||||
|
|
||||||
|
// Draw the background arrow
|
||||||
|
V_DrawFixedPatch(arrxpos<<FRACBITS, 100<<FRACBITS, FRACUNIT, 0, arrstart, NULL);
|
||||||
|
|
||||||
|
while ((arrxpos - arrfill->width) < BASEVIDWIDTH)
|
||||||
|
{
|
||||||
|
V_DrawFixedPatch(arrxpos<<FRACBITS, 100<<FRACBITS, FRACUNIT, 0, arrfill, NULL);
|
||||||
|
arrxpos += arrfill->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (itemsdrawn < 7)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (currentMenu->menuitems[i].status & IT_DISPLAY)
|
||||||
|
{
|
||||||
|
case IT_STRING:
|
||||||
|
{
|
||||||
|
|
||||||
|
char iconame[9]; // 8 chars + \0
|
||||||
|
patch_t *pp;
|
||||||
|
|
||||||
|
if (i == itemOn)
|
||||||
|
{
|
||||||
|
strcpy(iconame, currentMenu->menuitems[i].tooltip);
|
||||||
|
iconame[7] = '2'; // Yes this is a stupid hack. Replace the last character with a 2 when we're selecting this graphic.
|
||||||
|
|
||||||
|
pp = W_CachePatchName(iconame, PU_CACHE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pp = W_CachePatchName(currentMenu->menuitems[i].tooltip, PU_CACHE);
|
||||||
|
|
||||||
|
// 294 - 261 = 33
|
||||||
|
// We need to move 33 px in 50 tics which means we move 33/50 = 0.66 px every tic = 2/3 of the offset.
|
||||||
|
// trust me i graduated highschool!!!!
|
||||||
|
|
||||||
|
// Multiply by -1 or 1 depending on whether we're below or above 100 px.
|
||||||
|
// This double ternary is awful, yes.
|
||||||
|
|
||||||
|
dypos = ypos + pausemenu.offset;
|
||||||
|
V_DrawFixedPatch( ((i == itemOn ? (294 - pausemenu.offset*2/3 * (dypos > 100 ? 1 : -1)) : 261) + offset) << FRACBITS, (dypos)*FRACUNIT, FRACUNIT, 0, pp, NULL);
|
||||||
|
|
||||||
|
ypos += 50;
|
||||||
|
itemsdrawn++; // We drew that!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
i++; // Regardless of whether we drew or not, go to the next item in the menu.
|
||||||
|
if (i > currentMenu->numitems)
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the string!
|
||||||
|
// ...but first get what we need to get.
|
||||||
|
while (currentMenu->menuitems[itemOn].text[j] && j < MAXSTRINGLENGTH)
|
||||||
|
{
|
||||||
|
char c = currentMenu->menuitems[itemOn].text[j];
|
||||||
|
|
||||||
|
if (c == ' ')
|
||||||
|
{
|
||||||
|
sok = true;
|
||||||
|
j++;
|
||||||
|
continue; // We don't care about this :moyai:
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sok)
|
||||||
|
{
|
||||||
|
word2[word2len] = c;
|
||||||
|
word2len++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
word1[word1len] = c;
|
||||||
|
word1len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
word1[word1len] = '\0';
|
||||||
|
word2[word2len] = '\0';
|
||||||
|
|
||||||
|
// If there's no 2nd word, take this opportunity to center this line of text.
|
||||||
|
if (word1len)
|
||||||
|
V_DrawCenteredLSTitleHighString(220 + offset*2, 75 + (!word2len ? 10 : 0), 0, word1);
|
||||||
|
|
||||||
|
if (word2len)
|
||||||
|
V_DrawCenteredLSTitleLowString(220 + offset*2, 103, 0, word2);
|
||||||
|
}
|
||||||
|
|
||||||
tic_t playback_last_menu_interaction_leveltime = 0;
|
tic_t playback_last_menu_interaction_leveltime = 0;
|
||||||
|
|
||||||
void M_DrawPlaybackMenu(void)
|
void M_DrawPlaybackMenu(void)
|
||||||
|
|
|
||||||
|
|
@ -1219,6 +1219,12 @@ void M_StartControlPanel(void)
|
||||||
currentMenu = &MainDef;
|
currentMenu = &MainDef;
|
||||||
itemOn = 0;
|
itemOn = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For now let's just always open the same pause menu.
|
||||||
|
M_OpenPauseMenu();
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
else if (modeattacking)
|
else if (modeattacking)
|
||||||
{
|
{
|
||||||
|
|
@ -2354,7 +2360,8 @@ static void M_LevelListFromGametype(INT16 gt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init level select for use in local play using the last choice we made.
|
// Init level select for use in local play using the last choice we made.
|
||||||
// For the online MP version, see M_MPSetupNetgameMapSelect()
|
// For the online MP version used to START HOSTING A GAME, see M_MPSetupNetgameMapSelect()
|
||||||
|
// (We still use this one midgame)
|
||||||
|
|
||||||
void M_LevelSelectInit(INT32 choice)
|
void M_LevelSelectInit(INT32 choice)
|
||||||
{
|
{
|
||||||
|
|
@ -2465,9 +2472,15 @@ void M_CupSelectHandler(INT32 choice)
|
||||||
grandprixinfo.initalize = true;
|
grandprixinfo.initalize = true;
|
||||||
|
|
||||||
paused = false;
|
paused = false;
|
||||||
|
|
||||||
|
// Don't restart the server if we're already in a game lol
|
||||||
|
if (gamestate == GS_MENU)
|
||||||
|
{
|
||||||
SV_StartSinglePlayerServer();
|
SV_StartSinglePlayerServer();
|
||||||
multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this...
|
multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this...
|
||||||
netgame = levellist.netgame; // ^ ditto.
|
netgame = levellist.netgame; // ^ ditto.
|
||||||
|
}
|
||||||
|
|
||||||
D_MapChange(
|
D_MapChange(
|
||||||
grandprixinfo.cup->levellist[0] + 1,
|
grandprixinfo.cup->levellist[0] + 1,
|
||||||
GT_RACE,
|
GT_RACE,
|
||||||
|
|
@ -2593,16 +2606,20 @@ void M_LevelSelectHandler(INT32 choice)
|
||||||
|
|
||||||
S_StartSound(NULL, sfx_s3k63);
|
S_StartSound(NULL, sfx_s3k63);
|
||||||
|
|
||||||
|
paused = false;
|
||||||
|
|
||||||
|
if (gamestate == GS_MENU) // Don't restart the server if we're already in a game lol. Don't fade out either.
|
||||||
|
{
|
||||||
// Early fadeout to let the sound finish playing
|
// Early fadeout to let the sound finish playing
|
||||||
F_WipeStartScreen();
|
F_WipeStartScreen();
|
||||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||||
F_WipeEndScreen();
|
F_WipeEndScreen();
|
||||||
F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false);
|
F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false);
|
||||||
|
|
||||||
paused = false;
|
|
||||||
SV_StartSinglePlayerServer();
|
SV_StartSinglePlayerServer();
|
||||||
multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this...
|
multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this...
|
||||||
netgame = levellist.netgame; // ^ ditto.
|
netgame = levellist.netgame; // ^ ditto.
|
||||||
|
}
|
||||||
|
|
||||||
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false);
|
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false);
|
||||||
|
|
||||||
|
|
@ -2855,6 +2872,78 @@ void M_EndModeAttackRun(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct pausemenu_s pausemenu;
|
||||||
|
|
||||||
|
// Pause menu!
|
||||||
|
void M_OpenPauseMenu(void)
|
||||||
|
{
|
||||||
|
currentMenu = &PAUSE_MainDef;
|
||||||
|
|
||||||
|
// Ready the variables
|
||||||
|
pausemenu.ticker = 0;
|
||||||
|
|
||||||
|
pausemenu.offset = 0;
|
||||||
|
pausemenu.openoffset = 256;
|
||||||
|
pausemenu.closing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M_QuitPauseMenu(void)
|
||||||
|
{
|
||||||
|
// M_PauseTick actually handles the quitting when it's been long enough.
|
||||||
|
pausemenu.closing = true;
|
||||||
|
pausemenu.openoffset = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M_PauseTick(void)
|
||||||
|
{
|
||||||
|
pausemenu.offset /= 2;
|
||||||
|
|
||||||
|
if (pausemenu.closing)
|
||||||
|
{
|
||||||
|
pausemenu.openoffset *= 2;
|
||||||
|
if (pausemenu.openoffset > 255)
|
||||||
|
M_ClearMenus(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pausemenu.openoffset /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean M_PauseInputs(INT32 ch)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (pausemenu.closing)
|
||||||
|
return true; // Don't allow inputs.
|
||||||
|
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
|
||||||
|
case KEY_UPARROW:
|
||||||
|
{
|
||||||
|
pausemenu.offset -= 50; // Each item is spaced by 50 px
|
||||||
|
M_PrevOpt();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case KEY_DOWNARROW:
|
||||||
|
{
|
||||||
|
pausemenu.offset += 50; // Each item is spaced by 50 px
|
||||||
|
M_NextOpt();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case KEY_ESCAPE:
|
||||||
|
{
|
||||||
|
M_QuitPauseMenu();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Replay Playback Menu
|
// Replay Playback Menu
|
||||||
void M_SetPlaybackMenuPointer(void)
|
void M_SetPlaybackMenuPointer(void)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue