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
29
src/k_menu.h
29
src/k_menu.h
|
|
@ -133,7 +133,7 @@ typedef struct menu_s
|
|||
void (*drawroutine)(void); // draw routine
|
||||
void (*tickroutine)(void); // ticker routine
|
||||
boolean (*quitroutine)(void); // called before quit a menu return true if we can
|
||||
boolean (*inputroutine)(INT32); // if set, called every frame in the input handler. Returning true overwrites normal input handling.
|
||||
boolean (*inputroutine)(INT32); // if set, called every frame in the input handler. Returning true overwrites normal input handling.
|
||||
} menu_t;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -196,6 +196,12 @@ extern menu_t PLAY_MP_RoomSelectDef;
|
|||
extern menuitem_t PLAY_BattleGamemodesMenu[];
|
||||
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 menu_t PAUSE_PlaybackMenuDef;
|
||||
|
||||
|
|
@ -402,6 +408,24 @@ void M_MPRoomSelect(INT32 choice);
|
|||
void M_MPRoomSelectTick(void);
|
||||
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
|
||||
|
||||
extern tic_t playback_last_menu_interaction_leveltime;
|
||||
|
|
@ -443,6 +467,9 @@ void M_DrawMPHost(void);
|
|||
void M_DrawMPJoinIP(void);
|
||||
void M_DrawMPRoomSelect(void);
|
||||
|
||||
// Pause menu:
|
||||
void M_DrawPause(void);
|
||||
|
||||
// Replay Playback
|
||||
void M_DrawPlaybackMenu(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -252,10 +252,10 @@ menuitem_t PLAY_MP_JoinIP[] =
|
|||
NULL, NULL, 0, 0},
|
||||
|
||||
{IT_STRING, "servip2", "The last 3 IPs you've succesfully joined are displayed here.",
|
||||
NULL, NULL, 0, 0},
|
||||
NULL, NULL, 0, 0},
|
||||
|
||||
{IT_STRING, "servip3", "The last 3 IPs you've succesfully joined are displayed here.",
|
||||
NULL, NULL, 0, 0},
|
||||
NULL, NULL, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -296,6 +296,93 @@ menu_t PLAY_MP_RoomSelectDef = {
|
|||
// 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[] =
|
||||
{
|
||||
{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
|
||||
//
|
||||
|
||||
// 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;
|
||||
|
||||
void M_DrawPlaybackMenu(void)
|
||||
|
|
|
|||
115
src/k_menufunc.c
115
src/k_menufunc.c
|
|
@ -1219,6 +1219,12 @@ void M_StartControlPanel(void)
|
|||
currentMenu = &MainDef;
|
||||
itemOn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For now let's just always open the same pause menu.
|
||||
M_OpenPauseMenu();
|
||||
}
|
||||
|
||||
#if 0
|
||||
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.
|
||||
// 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)
|
||||
{
|
||||
|
|
@ -2465,9 +2472,15 @@ void M_CupSelectHandler(INT32 choice)
|
|||
grandprixinfo.initalize = true;
|
||||
|
||||
paused = false;
|
||||
SV_StartSinglePlayerServer();
|
||||
multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this...
|
||||
netgame = levellist.netgame; // ^ ditto.
|
||||
|
||||
// Don't restart the server if we're already in a game lol
|
||||
if (gamestate == GS_MENU)
|
||||
{
|
||||
SV_StartSinglePlayerServer();
|
||||
multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this...
|
||||
netgame = levellist.netgame; // ^ ditto.
|
||||
}
|
||||
|
||||
D_MapChange(
|
||||
grandprixinfo.cup->levellist[0] + 1,
|
||||
GT_RACE,
|
||||
|
|
@ -2593,16 +2606,20 @@ void M_LevelSelectHandler(INT32 choice)
|
|||
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
|
||||
// Early fadeout to let the sound finish playing
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false);
|
||||
|
||||
paused = false;
|
||||
SV_StartSinglePlayerServer();
|
||||
multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this...
|
||||
netgame = levellist.netgame; // ^ ditto.
|
||||
|
||||
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
|
||||
F_WipeStartScreen();
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
F_WipeEndScreen();
|
||||
F_RunWipe(wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false);
|
||||
|
||||
SV_StartSinglePlayerServer();
|
||||
multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this...
|
||||
netgame = levellist.netgame; // ^ ditto.
|
||||
}
|
||||
|
||||
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false);
|
||||
|
||||
|
|
@ -2855,6 +2872,78 @@ void M_EndModeAttackRun(void)
|
|||
#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
|
||||
void M_SetPlaybackMenuPointer(void)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue