diff --git a/src/Makefile b/src/Makefile index f4a77aedd..d106def5b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -467,7 +467,6 @@ DBGNAME?=$(EXENAME).debug # $(OBJDIR)/dstrings.o \ # not too sophisticated dependency -# SRB2kart kart.o on line 433 below OBJS:=$(i_main_o) \ $(OBJDIR)/comptime.o \ $(OBJDIR)/string.o \ @@ -496,7 +495,9 @@ OBJS:=$(i_main_o) \ $(OBJDIR)/m_cheat.o \ $(OBJDIR)/m_cond.o \ $(OBJDIR)/m_fixed.o \ - $(OBJDIR)/m_menu.o \ + $(OBJDIR)/k_menudef.o \ + $(OBJDIR)/k_menufunc.o \ + $(OBJDIR)/k_menudraw.o \ $(OBJDIR)/m_misc.o \ $(OBJDIR)/m_random.o \ $(OBJDIR)/m_queue.o \ diff --git a/src/command.c b/src/command.c index 6d9c86d3e..e3fc0c292 100644 --- a/src/command.c +++ b/src/command.c @@ -21,7 +21,7 @@ #include "command.h" #include "console.h" #include "z_zone.h" -#include "m_menu.h" +#include "k_menu.h" #include "m_misc.h" #include "m_fixed.h" #include "m_argv.h" @@ -75,7 +75,7 @@ CV_PossibleValue_t kartspeed_cons_t[] = { // Filter consvars by EXECVERSION // First implementation is 2 (1.0.2), so earlier configs default at 1 (1.0.0) -// Also set CV_HIDEN during runtime, after config is loaded +// Also set CV_HIDDEN during runtime, after config is loaded static boolean execversion_enabled = false; consvar_t cv_execversion = {"execversion","1",CV_CALL,CV_Unsigned, CV_EnforceExecVersion, 0, NULL, NULL, 0, 0, NULL}; @@ -1112,7 +1112,7 @@ void CV_RegisterVar(consvar_t *variable) } // link the variable in - if (!(variable->flags & CV_HIDEN)) + if (!(variable->flags & CV_HIDDEN)) { variable->next = consvar_vars; consvar_vars = variable; @@ -1628,6 +1628,7 @@ void CV_AddValue(consvar_t *var, INT32 increment) if (var->PossibleValue) { +#if 0 if (var == &cv_nextmap) { // Special case for the nextmap variable, used only directly from the menu @@ -1662,9 +1663,12 @@ void CV_AddValue(consvar_t *var, INT32 increment) return; } } + else +#endif + #define MINVAL 0 #define MAXVAL 1 - else if (var->PossibleValue[MINVAL].strvalue && !strcmp(var->PossibleValue[MINVAL].strvalue, "MIN")) + if (var->PossibleValue[MINVAL].strvalue && !strcmp(var->PossibleValue[MINVAL].strvalue, "MIN")) { // SRB2Kart #ifdef PARANOIA if (!var->PossibleValue[MAXVAL].strvalue) diff --git a/src/command.h b/src/command.h index 6b5d513ef..d7a0109e2 100644 --- a/src/command.h +++ b/src/command.h @@ -95,7 +95,7 @@ typedef enum CV_SHOWMODIF = 128, // say something when modified CV_SHOWMODIFONETIME = 256, // same but will be reset to 0 when modified, set in toggle CV_NOSHOWHELP = 512, // Don't show variable in the HELP list Tails 08-13-2002 - CV_HIDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console + CV_HIDDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console // can only be set when we have the pointer to it // used on menus CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on. diff --git a/src/console.c b/src/console.c index 1defa7e82..341145ab1 100644 --- a/src/console.c +++ b/src/console.c @@ -32,7 +32,7 @@ #include "z_zone.h" #include "i_system.h" #include "d_main.h" -#include "m_menu.h" +#include "k_menu.h" #include "filesrch.h" #ifdef _WINDOWS @@ -140,28 +140,6 @@ static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, { {0, NULL}}; consvar_t cons_backcolor = {"con_backcolor", "Black", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t menuhighlight_cons_t[] = -{ - {0, "Game type"}, - {V_YELLOWMAP, "Always yellow"}, - {V_PURPLEMAP, "Always purple"}, - {V_GREENMAP, "Always green"}, - {V_BLUEMAP, "Always blue"}, - {V_REDMAP, "Always red"}, - {V_GRAYMAP, "Always gray"}, - {V_ORANGEMAP, "Always orange"}, - {V_SKYMAP, "Always sky-blue"}, - {V_GOLDMAP, "Always gold"}, - {V_LAVENDERMAP, "Always lavender"}, - {V_AQUAMAP, "Always aqua-green"}, - {V_MAGENTAMAP, "Always magenta"}, - {V_PINKMAP, "Always pink"}, - {V_BROWNMAP, "Always brown"}, - {V_TANMAP, "Always tan"}, - {0, NULL} -}; -consvar_t cons_menuhighlight = {"menuhighlight", "Game type", CV_SAVE, menuhighlight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; - static void CON_Print(char *msg); // @@ -406,7 +384,6 @@ void CON_Init(void) CV_RegisterVar(&cons_height); CV_RegisterVar(&cons_backpic); CV_RegisterVar(&cons_backcolor); - CV_RegisterVar(&cons_menuhighlight); COM_AddCommand("bind", CONS_Bind_f); } else diff --git a/src/console.h b/src/console.h index 7ed585177..7b17965ae 100644 --- a/src/console.h +++ b/src/console.h @@ -36,7 +36,7 @@ extern INT32 con_clearlines; // lines of top of screen to refresh extern boolean con_hudupdate; // hud messages have changed, need refresh extern UINT32 con_scalefactor; // console text scale factor -extern consvar_t cons_backcolor, cons_menuhighlight; +extern consvar_t cons_backcolor; extern UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *orangemap,\ *skymap, *goldmap, *lavendermap, *aquamap, *magentamap, *pinkmap, *brownmap, *tanmap; diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 4d61194c4..59bb87aac 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -28,7 +28,7 @@ #include "hu_stuff.h" #include "keys.h" #include "g_input.h" // JOY1 -#include "m_menu.h" +#include "k_menu.h" #include "console.h" #include "d_netfil.h" #include "byteptr.h" diff --git a/src/d_main.c b/src/d_main.c index 098a2bf33..065ee07fa 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -52,7 +52,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "i_system.h" #include "i_video.h" #include "m_argv.h" -#include "m_menu.h" +#include "k_menu.h" #include "m_misc.h" #include "p_setup.h" #include "p_saveg.h" @@ -1187,7 +1187,9 @@ void D_SRB2Main(void) // Setup character tables // Have to be done here before files are loaded +#ifdef USEPLAYERMENU M_InitCharacterTables(); +#endif // load wad, including the main wad file CONS_Printf("W_InitMultipleFiles(): Adding main IWAD and PWADs.\n"); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 11c4547de..95cb9e543 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -20,7 +20,7 @@ #include "g_game.h" #include "hu_stuff.h" #include "g_input.h" -#include "m_menu.h" +#include "k_menu.h" #include "r_local.h" #include "r_things.h" #include "p_local.h" @@ -300,8 +300,8 @@ consvar_t cv_joyscale2 = {"joyscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2, consvar_t cv_joyscale3 = {"joyscale3", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale3, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_joyscale4 = {"joyscale4", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale4, 0, NULL, NULL, 0, 0, NULL}; #else -consvar_t cv_joyscale = {"joyscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save -consvar_t cv_joyscale2 = {"joyscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save +consvar_t cv_joyscale = {"joyscale", "1", CV_SAVE|CV_HIDDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save +consvar_t cv_joyscale2 = {"joyscale2", "1", CV_SAVE|CV_HIDDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save #endif #if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) consvar_t cv_mouse2port = {"mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -794,18 +794,22 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_playername); CV_RegisterVar(&cv_playercolor); CV_RegisterVar(&cv_skin); // r_things.c (skin NAME) + // secondary player (splitscreen) CV_RegisterVar(&cv_playername2); CV_RegisterVar(&cv_playercolor2); CV_RegisterVar(&cv_skin2); + // third player CV_RegisterVar(&cv_playername3); CV_RegisterVar(&cv_playercolor3); CV_RegisterVar(&cv_skin3); + // fourth player CV_RegisterVar(&cv_playername4); CV_RegisterVar(&cv_playercolor4); CV_RegisterVar(&cv_skin4); + // preferred number of players CV_RegisterVar(&cv_splitplayers); @@ -839,7 +843,7 @@ void D_RegisterClientCommands(void) // FIXME: not to be here.. but needs be done for config loading CV_RegisterVar(&cv_usegamma); - // m_menu.c + // k_menu.c //CV_RegisterVar(&cv_compactscoreboard); CV_RegisterVar(&cv_chatheight); CV_RegisterVar(&cv_chatwidth); @@ -925,10 +929,12 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_usejoystick2); CV_RegisterVar(&cv_usejoystick3); CV_RegisterVar(&cv_usejoystick4); + #ifdef LJOYSTICK CV_RegisterVar(&cv_joyport); CV_RegisterVar(&cv_joyport2); #endif + CV_RegisterVar(&cv_joyscale); CV_RegisterVar(&cv_joyscale2); CV_RegisterVar(&cv_joyscale3); @@ -3958,7 +3964,7 @@ static void Got_Removal(UINT8 **cp, INT32 playernum) } // Join password stuff -consvar_t cv_dummyjoinpassword = {"dummyjoinpassword", "", CV_HIDEN|CV_NOSHOWHELP|CV_PASSWORD, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_dummyjoinpassword = {"dummyjoinpassword", "", CV_HIDDEN|CV_NOSHOWHELP|CV_PASSWORD, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; #define NUMJOINCHALLENGES 32 static UINT8 joinpassmd5[MD5_LEN+1]; diff --git a/src/d_netfil.c b/src/d_netfil.c index 155700807..2b70e728e 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -56,7 +56,7 @@ #include "byteptr.h" #include "p_setup.h" #include "m_misc.h" -#include "m_menu.h" +#include "k_menu.h" #include "md5.h" #include "filesrch.h" diff --git a/src/dehacked.c b/src/dehacked.c index d94f6d91c..5932e7ead 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -19,7 +19,7 @@ #include "m_argv.h" #include "z_zone.h" #include "w_wad.h" -#include "m_menu.h" +#include "k_menu.h" #include "m_misc.h" #include "filesrch.h" // for refreshdirmenu #include "f_finale.h" @@ -34,6 +34,7 @@ #include "lua_script.h" #include "lua_hook.h" #include "d_clisrv.h" +#include "r_things.h" #include "m_cond.h" @@ -432,7 +433,8 @@ static void readAnimTex(MYFILE *f, INT32 num) } */ -static boolean findFreeSlot(INT32 *num) +#ifdef USEPLAYERMENU +static boolean findPlayerFreeSlot(INT32 *num) { // Send the character select entry to a free slot. while (*num < MAXSKINS && PlayerMenu[*num].status != IT_DISABLED) @@ -475,7 +477,7 @@ static void readPlayer(MYFILE *f, INT32 num) { char *playertext = NULL; - if (!slotfound && (slotfound = findFreeSlot(&num)) == false) + if (!slotfound && (slotfound = findPlayerFreeSlot(&num)) == false) goto done; PlayerMenu[num].status = IT_CALL; @@ -525,7 +527,7 @@ static void readPlayer(MYFILE *f, INT32 num) /*if (fastcmp(word, "PLAYERNAME")) { - if (!slotfound && (slotfound = findFreeSlot(&num)) == false) + if (!slotfound && (slotfound = findPlayerFreeSlot(&num)) == false) goto done; DEH_WriteUndoline(word, description[num].text, UNDO_NONE); strlcpy(description[num].text, word2, sizeof (description[num].text)); @@ -547,7 +549,7 @@ static void readPlayer(MYFILE *f, INT32 num) } */ /*else*/ if (fastcmp(word, "PICNAME")) { - if (!slotfound && (slotfound = findFreeSlot(&num)) == false) + if (!slotfound && (slotfound = findPlayerFreeSlot(&num)) == false) goto done; DEH_WriteUndoline(word, &description[num].picname[0], UNDO_NONE); PlayerMenu[num].status = IT_CALL; @@ -571,7 +573,7 @@ static void readPlayer(MYFILE *f, INT32 num) ... Or use MENUPOSITION first, that works too. Hell, you could edit multiple character slots in a single section that way, due to how SOC editing works. */ - if (i != IT_DISABLED && !slotfound && (slotfound = findFreeSlot(&num)) == false) + if (i != IT_DISABLED && !slotfound && (slotfound = findPlayerFreeSlot(&num)) == false) goto done; DEH_WriteUndoline(word, va("%d", PlayerMenu[num].status), UNDO_NONE); PlayerMenu[num].status = (INT16)i; @@ -579,7 +581,7 @@ static void readPlayer(MYFILE *f, INT32 num) else if (fastcmp(word, "SKINNAME")) { // Send to free slot. - if (!slotfound && (slotfound = findFreeSlot(&num)) == false) + if (!slotfound && (slotfound = findPlayerFreeSlot(&num)) == false) goto done; DEH_WriteUndoline(word, description[num].skinname, UNDO_NONE); PlayerMenu[num].status = IT_CALL; @@ -600,6 +602,7 @@ static void readPlayer(MYFILE *f, INT32 num) done: Z_Free(s); } +#endif static int freeslotusage[2][2] = {{0, 0}, {0, 0}}; // [S_, MT_][max, previous .wad's max] @@ -3452,6 +3455,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) continue; } word2 = strtok(NULL, " "); +#ifdef USEPLAYERMENU if (fastcmp(word, "CHARACTER")) { if (word2) { @@ -3472,6 +3476,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) // This is not a major mod. continue; } +#endif if (word2) { strupr(word2); @@ -8933,8 +8938,7 @@ struct { {"CV_SHOWMODIF",CV_SHOWMODIF}, {"CV_SHOWMODIFONETIME",CV_SHOWMODIFONETIME}, {"CV_NOSHOWHELP",CV_NOSHOWHELP}, - {"CV_HIDEN",CV_HIDEN}, - {"CV_HIDDEN",CV_HIDEN}, + {"CV_HIDDEN",CV_HIDDEN}, {"CV_CHEAT",CV_CHEAT}, // v_video flags diff --git a/src/f_finale.c b/src/f_finale.c index d45a9cfa9..956c2db94 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -24,7 +24,7 @@ #include "w_wad.h" #include "z_zone.h" #include "i_system.h" -#include "m_menu.h" +#include "k_menu.h" #include "dehacked.h" #include "g_input.h" #include "console.h" diff --git a/src/f_wipe.c b/src/f_wipe.c index 1ea2ec2fa..4faf61146 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -26,7 +26,7 @@ #include "z_zone.h" #include "i_system.h" -#include "m_menu.h" +#include "k_menu.h" #include "console.h" #include "d_main.h" #include "m_misc.h" // movie mode diff --git a/src/filesrch.c b/src/filesrch.c index d132e9fb4..22c6228c1 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -32,7 +32,7 @@ #include "d_netfil.h" #include "m_misc.h" #include "z_zone.h" -#include "m_menu.h" // Addons_option_Onchange +#include "k_menu.h" // Addons_option_Onchange #if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX) diff --git a/src/filesrch.h b/src/filesrch.h index 4cb92b238..8bfc92d1d 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -6,7 +6,7 @@ #include "doomdef.h" #include "d_netfil.h" -#include "m_menu.h" // MAXSTRINGLENGTH +#include "k_menu.h" // MAXSTRINGLENGTH extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type; diff --git a/src/g_game.c b/src/g_game.c index cb4131e6d..fcb815d3a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -30,7 +30,7 @@ #include "g_game.h" #include "m_cheat.h" #include "m_misc.h" -#include "m_menu.h" +#include "k_menu.h" #include "m_argv.h" #include "hu_stuff.h" #include "st_stuff.h" @@ -3831,9 +3831,11 @@ void G_AfterIntermission(void) { G_StopDemo(); +#if 0 if (demo.inreplayhut) M_ReplayHut(0); else +#endif D_StartTitle(); return; @@ -4327,7 +4329,7 @@ static void M_ForceLoadGameResponse(INT32 ch) Z_Free(savebuffer); save_p = savebuffer = NULL; startonmapnum = 0; - M_SetupNextMenu(&SP_LoadDef); + M_SetupNextMenu(&SP_LoadDef, false); return; } diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 9e454bcd5..99453853d 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -24,7 +24,7 @@ #include "../z_zone.h" #include "../console.h" #include "../v_video.h" -#include "../m_menu.h" +#include "../k_menu.h" #include "../i_system.h" #include "../m_argv.h" #include "../i_video.h" diff --git a/src/hu_stuff.c b/src/hu_stuff.c index cf3cc5872..44ed3ae81 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -15,7 +15,7 @@ #include "byteptr.h" #include "hu_stuff.h" -#include "m_menu.h" // gametype_cons_t +#include "k_menu.h" // gametype_cons_t #include "m_cond.h" // emblems #include "d_clisrv.h" @@ -111,7 +111,7 @@ static patch_t *tokenicon; // misc vars //------------------------------------------- -// crosshair 0 = off, 1 = cross, 2 = angle, 3 = point, see m_menu.c +// crosshair 0 = off, 1 = cross, 2 = angle, 3 = point, see k_menu.c static patch_t *crosshair[HU_CROSSHAIRS]; // 3 precached crosshair graphics // song credits static patch_t *songcreditbg; @@ -1624,7 +1624,7 @@ static void HU_drawChatLog(INT32 offset) INT32 x = chatx+2, y, dx = 0, dy = 0; UINT32 i = 0; INT32 chat_topy, chat_bottomy; - INT32 highlight = HU_GetHighlightColor(); + INT32 highlight = V_YELLOWMAP; boolean atbottom = false; // make sure that our scroll position isn't "illegal"; @@ -2947,9 +2947,7 @@ static void HU_DrawRankings(void) V_DrawFadeScreen(0xFF00, 16); // A little more readable, and prevents cheating the fades under other circumstances. - if (cons_menuhighlight.value) - hilicol = cons_menuhighlight.value; - else if (modeattacking) + if (modeattacking) hilicol = V_ORANGEMAP; else hilicol = ((gametype == GT_RACE) ? V_SKYMAP : V_REDMAP); diff --git a/src/m_menu.h b/src/k_menu.h similarity index 61% rename from src/m_menu.h rename to src/k_menu.h index 3789f261c..863838127 100644 --- a/src/m_menu.h +++ b/src/k_menu.h @@ -9,68 +9,15 @@ // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file m_menu.h +/// \file k_menu.h /// \brief Menu widget stuff, selection and such -#ifndef __X_MENU__ -#define __X_MENU__ +#ifndef __K_MENU__ +#define __K_MENU__ #include "d_event.h" #include "command.h" -#include "r_things.h" // for SKINNAMESIZE - -// -// MENUS -// -// Called by main loop, -// saves config file and calls I_Quit when user exits. -// Even when the menu is not displayed, -// this can resize the view and change game parameters. -// Does all the real work of the menu interaction. -boolean M_Responder(event_t *ev); - -// Called by main loop, only used for menu (skull cursor) animation. -void M_Ticker(void); - -// Called by main loop, draws the menus directly into the screen buffer. -void M_Drawer(void); - -// Called by D_SRB2Main, loads the config file. -void M_Init(void); - -// Called by D_SRB2Main also, sets up the playermenu and description tables. -void M_InitCharacterTables(void); - -// Called by intro code to force menu up upon a keypress, -// does nothing if menu is already up. -void M_StartControlPanel(void); - -// Called upon end of a mode attack run -void M_EndModeAttackRun(void); - -// Called on new server add, or other reasons -void M_SortServerList(void); - -// Draws a box with a texture inside as background for messages -void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines); - -// the function to show a message box typing with the string inside -// string must be static (not in the stack) -// routine is a function taking a INT32 in parameter -typedef enum -{ - MM_NOTHING = 0, // is just displayed until the user do someting - MM_YESNO, // routine is called with only 'y' or 'n' in param - MM_EVENTHANDLER // the same of above but without 'y' or 'n' restriction - // and routine is void routine(event_t *) (ex: set control) -} menumessagetype_t; -void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype); - -// Called by linux_x/i_video_xshm.c -void M_QuitResponse(INT32 ch); - -// Determines whether to show a level in the list -boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt); +#include "doomstat.h" // MAXSPLITSCREENPLAYERS // flags for items in the menu // menu handle (what we do when key is pressed @@ -141,179 +88,220 @@ typedef union // typedef struct menuitem_s { - // show IT_xxx - UINT16 status; + UINT16 status; // show IT_xxx - const char *patch; - const char *text; // used when FONTBxx lump is found + const char *text; // option title + const char *tooltip; // description of option used by K_MenuTooltips + const char *patch; // image of option used by K_MenuPreviews -// FIXME: should be itemaction_t - void *itemaction; + void *itemaction; // FIXME: should be itemaction_t // extra variables UINT8 mvar1; + UINT8 mvar2; } menuitem_t; -extern menuitem_t PlayerMenu[MAXSKINS]; - typedef struct menu_s { - const char *menutitlepic; INT16 numitems; // # of menu items struct menu_s *prevMenu; // previous menu - menuitem_t *menuitems; // menu items - void (*drawroutine)(void); // draw routine - INT16 x, y; // x, y of menu INT16 lastOn; // last item user was on in menu + menuitem_t *menuitems; // menu items + INT16 x, y; // x, y of menu + INT16 transitionInTics; // tics for transitions in + INT16 transitionOutTics; // tics for transitions out + void (*drawroutine)(void); // draw routine boolean (*quitroutine)(void); // called before quit a menu return true if we can } menu_t; -void M_SetupNextMenu(menu_t *menudef); -void M_ClearMenus(boolean callexitmenufunc); +typedef enum +{ + MM_NOTHING = 0, // is just displayed until the user do someting + MM_YESNO, // routine is called with only 'y' or 'n' in param + MM_EVENTHANDLER // the same of above but without 'y' or 'n' restriction + // and routine is void routine(event_t *) (ex: set control) +} menumessagetype_t; + +// =========== +// PROTOTYPING +// =========== + +// K_MENUDEF.C +extern menuitem_t MainMenu[]; +extern menu_t MainDef; + +typedef enum +{ + play = 0, + extra, + options, + quitkart +} main_e; + +extern menuitem_t PLAY_MainMenu[]; +extern menu_t PLAY_MainDef; + +extern menuitem_t PLAY_CharSelect[]; +extern menu_t PLAY_CharSelectDef; + +extern menuitem_t PLAY_Gamemodes[]; +extern menu_t PLAY_GamemodesDef; + +extern menuitem_t PLAY_RaceGamemodesMenu[]; +extern menu_t PLAY_RaceGamemodesDef; + +extern menuitem_t PAUSE_PlaybackMenu[]; +extern menu_t PAUSE_PlaybackMenuDef; + +typedef enum +{ + playback_hide, + playback_rewind, + playback_pause, + playback_fastforward, + playback_backframe, + playback_resume, + playback_advanceframe, + playback_viewcount, + playback_view1, + playback_view2, + playback_view3, + playback_view4, + playback_quit +} playback_e; + + +// K_MENUFUNC.C extern menu_t *currentMenu; -extern menu_t MainDef; -extern menu_t SP_LoadDef; +extern char dummystaffname[22]; -// Call upon joystick hotplug -void M_SetupJoystickMenu(INT32 choice); -extern menu_t OP_JoystickSetDef; +extern INT16 itemOn; // menu item skull is on, Hack by Tails 09-18-2002 +extern INT16 skullAnimCounter; // skull animation counter -// Stuff for customizing the player select screen -typedef struct -{ - char notes[441]; - char picname[8]; - char skinname[SKINNAMESIZE*2+2]; // skin&skin\0 -} description_t; +extern struct menutransition_s { + INT16 tics; + INT16 dest; + struct menu_s *newmenu; + boolean in; +} menutransition; -// mode descriptions for video mode menu -typedef struct -{ - INT32 modenum; // video mode number in the vidmodes list - const char *desc; // XXXxYYY - UINT8 goodratio; // aspect correct if 1 -} modedesc_t; - -// savegame struct for save game menu -typedef struct -{ - char playername[37]; - char levelname[32]; - UINT8 actnum; - UINT8 skincolor; - UINT8 skinnum; - UINT8 botskin; - UINT8 botcolor; - UINT8 numemeralds; - INT32 lives; - INT32 continues; - INT32 gamemap; - UINT8 netgame; -} saveinfo_t; - -extern description_t description[MAXSKINS]; +extern boolean menuwipe; extern consvar_t cv_showfocuslost; extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort; extern CV_PossibleValue_t gametype_cons_t[]; -extern char dummystaffname[22]; - -extern INT16 startmap; -extern INT32 ultimate_selectable; - -#define MAXSAVEGAMES 31 //note: last save game is "no save" -#define NOSAVESLOT MAXSAVEGAMES-1 //slot where Play Without Saving appears - -void M_ForceSaveSlotSelected(INT32 sslot); - -void M_CheatActivationResponder(INT32 ch); - -// Screenshot menu updating void Moviemode_mode_Onchange(void); void Screenshot_option_Onchange(void); - -// Addons menu updating void Addons_option_Onchange(void); -void M_ReplayHut(INT32 choice); -void M_SetPlaybackMenuPointer(void); +void M_SortServerList(void); -INT32 HU_GetHighlightColor(void); +boolean M_Responder(event_t *ev); +void M_StartControlPanel(void); +void M_ClearMenus(boolean callexitmenufunc); +void M_SelectableClearMenus(INT32 choice); +void M_SetupNextMenu(menu_t *menudef, boolean nofade); +void M_GoBack(INT32 choice); +void M_Ticker(void); +void M_Init(void); + +menu_t MessageDef; +void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype); +void M_StopMessage(INT32 choice); + +void M_HandleImageDef(INT32 choice); + +void M_QuitResponse(INT32 ch); +void M_QuitSRB2(INT32 choice); + +// If you want to waste a bunch of memory for a limit no one will hit, feel free to boost this to MAXSKINS :P +// I figure this will be enough clone characters to fit onto the character select. +// (If someone runs into it after release I'll probably boost it, though.) +#define MAXCLONES MAXSKINS/16 + +extern struct setup_chargrid_s { + SINT8 skinlist[MAXCLONES]; + UINT8 numskins; +} setup_chargrid[9][9]; + +typedef struct setup_player_s +{ + SINT8 gridx, gridy; + SINT8 skin; + SINT8 clonenum; + UINT8 color; + UINT8 mdepth; +} setup_player_t; + +extern setup_player_t setup_player[MAXSPLITSCREENPLAYERS]; + +extern UINT8 setup_numplayers; + +typedef enum +{ + SPLITCV_SKIN = 0, + SPLITCV_COLOR, + SPLITCV_NAME, + SPLITCV_MAX +} splitscreencvars_t; +consvar_t *setup_playercvars[MAXSPLITSCREENPLAYERS][SPLITCV_MAX]; + +void M_CharacterSelectInit(INT32 choice); +void M_CharacterSelectHandler(INT32 choice); +boolean M_CharacterSelectQuit(void); + +void M_EndModeAttackRun(void); +void M_SetPlaybackMenuPointer(void); +void M_PlaybackRewind(INT32 choice); +void M_PlaybackPause(INT32 choice); +void M_PlaybackFastForward(INT32 choice); +void M_PlaybackAdvance(INT32 choice); +void M_PlaybackSetViews(INT32 choice); +void M_PlaybackAdjustView(INT32 choice); +void M_PlaybackQuit(INT32 choice); + +void M_ReplayHut(INT32 choice); + +// M_MENUDRAW.C + +void M_Drawer(void); +void M_DrawGenericMenu(void); +void M_DrawKartGamemodeMenu(void); +void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines); +void M_DrawMessageMenu(void); +void M_DrawImageDef(void); + +void M_DrawCharacterSelect(void); + +void M_DrawPlaybackMenu(void); // These defines make it a little easier to make menus -#define KARTGAMEMODEMENU(header, source, prev)\ +#define DEFAULTMENUSTYLE(source, prev, x, y)\ {\ - header,\ - sizeof(source)/sizeof(menuitem_t),\ + sizeof(source) / sizeof(menuitem_t),\ prev,\ - source,\ - M_DrawKartGamemodeMenu,\ - 0, 0,\ 0,\ - NULL\ -} - -#define DEFAULTMENUSTYLE(header, source, prev, x, y)\ -{\ - header,\ - sizeof(source)/sizeof(menuitem_t),\ - prev,\ source,\ + x, y,\ + 0, 0,\ M_DrawGenericMenu,\ - x, y,\ - 0,\ NULL\ } -#define PAUSEMENUSTYLE(source, x, y)\ -{\ - NULL,\ - sizeof(source)/sizeof(menuitem_t),\ - NULL,\ - source,\ - M_DrawPauseMenu,\ - x, y,\ - 0,\ - NULL\ -} -#define MAPICONMENUSTYLE(header, source, prev)\ +#define KARTGAMEMODEMENU(source, prev)\ {\ - header,\ - sizeof (source)/sizeof (menuitem_t),\ + sizeof(source) / sizeof(menuitem_t),\ prev,\ - source,\ - M_DrawServerMenu,\ - 24,40,\ 0,\ - NULL\ -} - -#define CONTROLMENUSTYLE(source, prev)\ -{\ - "M_CONTRO",\ - sizeof (source)/sizeof (menuitem_t),\ - prev,\ source,\ - M_DrawControl,\ - 26, 40,\ - 0,\ - NULL\ -} - -#define IMAGEDEF(source)\ -{\ - NULL,\ - sizeof (source)/sizeof (menuitem_t),\ - NULL,\ - source,\ - M_DrawImageDef,\ 0, 0,\ - 0,\ + 10, 10,\ + M_DrawKartGamemodeMenu,\ NULL\ } -#endif //__X_MENU__ +#endif //__K_MENU__ diff --git a/src/k_menudef.c b/src/k_menudef.c new file mode 100644 index 000000000..07cd413b9 --- /dev/null +++ b/src/k_menudef.c @@ -0,0 +1,132 @@ +/// \file k_menudef.c +/// \brief SRB2Kart menu definitions + +#include "k_menu.h" +#include "screen.h" // BASEVIDWIDTH + +// ========================================================================== +// ORGANIZATION START. +// ========================================================================== +// Note: Never should we be jumping from one category of menu options to another +// without first going to the Main Menu. +// Note: Ignore the above if you're working with the Pause menu. +// Note: (Prefix)_MainMenu should be the target of all Main Menu options that +// point to submenus. + +// --------- +// Main Menu +// --------- +menuitem_t MainMenu[] = +{ + {IT_STRING | IT_CALL, "Play", "Cut to the chase and start playing!", + NULL, M_CharacterSelectInit, 48, 0}, + + {IT_STRING, "Extra", "Check out some bonus features.", + NULL, NULL, 80, 0}, + + {IT_STRING, "Option", "Configure your controls, settings, and preferences.", + NULL, NULL, 112, 0}, + + {IT_STRING | IT_CALL, "Quit", "Exit SRB2Kart.", + NULL, M_QuitSRB2, 160, 0}, +}; + +menu_t MainDef = KARTGAMEMODEMENU(MainMenu, NULL); + +// --------- +// Play Menu +// --------- + +menuitem_t PLAY_CharSelect[] = +{ + {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_CharacterSelectHandler, 0, 0}, +}; + +menu_t PLAY_CharSelectDef = { + sizeof (PLAY_CharSelect) / sizeof (menuitem_t), + &MainDef, + 0, + PLAY_CharSelect, + 0, 0, + 0, 0, + M_DrawCharacterSelect, + M_CharacterSelectQuit +}; + +menuitem_t PLAY_MainMenu[] = +{ + {IT_STRING | IT_SUBMENU, "Local Play", "Play only on this computer.", + NULL, &PLAY_GamemodesDef, 64, 0}, + + {IT_STRING, "Online", "Connect to other computers.", + NULL, NULL, 96, 0}, + + {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 160, 0}, +}; + +menu_t PLAY_MainDef = KARTGAMEMODEMENU(PLAY_MainMenu, &PLAY_CharSelectDef); + +menuitem_t PLAY_GamemodesMenu[] = +{ + {IT_STRING | IT_SUBMENU, "Race", "A competition for the best time!", + NULL, &PLAY_RaceGamemodesDef, 64, 0}, + + {IT_STRING, "Battle", "Clash against other players in a survival match!", + NULL, NULL, 96, 0}, + + {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 160, 0}, +}; + +menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef); + +menuitem_t PLAY_RaceGamemodesMenu[] = +{ + {IT_STRING, "Grand Prix", "Compete for the best rank over five races!", + NULL, NULL, 48, 0}, + + {IT_STRING, "Match Race", "Pick your own settings in a specialized single race.", + NULL, NULL, 80, 0}, + + {IT_STRING, "Time Attack", "Race against ghosts for the best time, no fluff.", + NULL, NULL, 112, 0}, + + {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 160, 0}, +}; + +menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_GamemodesDef); + +// ------------------- +// In-game/pause menus +// ------------------- + +menuitem_t PAUSE_PlaybackMenu[] = +{ + {IT_CALL | IT_STRING, "Hide Menu", NULL, "M_PHIDE", M_SelectableClearMenus, 0, 0}, + + {IT_CALL | IT_STRING, "Rewind", NULL, "M_PREW", M_PlaybackRewind, 20, 0}, + {IT_CALL | IT_STRING, "Pause", NULL, "M_PPAUSE", M_PlaybackPause, 36, 0}, + {IT_CALL | IT_STRING, "Fast-Forward", NULL, "M_PFFWD", M_PlaybackFastForward, 52, 0}, + + {IT_CALL | IT_STRING, "Backup Frame", NULL, "M_PSTEPB", M_PlaybackRewind, 20, 0}, + {IT_CALL | IT_STRING, "Resume", NULL, "M_PRESUM", M_PlaybackPause, 36, 0}, + {IT_CALL | IT_STRING, "Advance Frame", NULL, "M_PFADV", M_PlaybackAdvance, 52, 0}, + + {IT_ARROWS | IT_STRING, "View Count", NULL, "M_PVIEWS", M_PlaybackSetViews, 72, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint", NULL, "M_PNVIEW", M_PlaybackAdjustView, 88, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 2", NULL, "M_PNVIEW", M_PlaybackAdjustView, 104, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 3", NULL, "M_PNVIEW", M_PlaybackAdjustView, 120, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 4", NULL, "M_PNVIEW", M_PlaybackAdjustView, 136, 0}, + + {IT_CALL | IT_STRING, "Stop Playback", NULL, "M_PEXIT", M_PlaybackQuit, 156, 0}, +}; + +menu_t PAUSE_PlaybackMenuDef = { + sizeof (PAUSE_PlaybackMenu) / sizeof (menuitem_t), + NULL, + 0, + PAUSE_PlaybackMenu, + BASEVIDWIDTH/2 - 88, 2, + 0, 0, + M_DrawPlaybackMenu, + NULL +}; diff --git a/src/k_menudraw.c b/src/k_menudraw.c new file mode 100644 index 000000000..abf696764 --- /dev/null +++ b/src/k_menudraw.c @@ -0,0 +1,844 @@ +/// \file k_menudraw.c +/// \brief SRB2Kart's menu drawer functions + +#ifdef __GNUC__ +#include +#endif + +#include "k_menu.h" + +#include "doomdef.h" +#include "d_main.h" +#include "d_netcmd.h" +#include "console.h" +#include "r_local.h" +#include "hu_stuff.h" +#include "g_game.h" +#include "g_input.h" +#include "m_argv.h" + +// Data. +#include "sounds.h" +#include "s_sound.h" +#include "i_system.h" + +// Addfile +#include "filesrch.h" + +#include "v_video.h" +#include "i_video.h" +#include "keys.h" +#include "z_zone.h" +#include "w_wad.h" +#include "p_local.h" +#include "p_setup.h" +#include "f_finale.h" + +#ifdef HWRENDER +#include "hardware/hw_main.h" +#endif + +#include "d_net.h" +#include "mserv.h" +#include "m_misc.h" +#include "m_anigif.h" +#include "byteptr.h" +#include "st_stuff.h" +#include "i_sound.h" +#include "k_kart.h" // SRB2kart +#include "d_player.h" // KITEM_ constants +#include "doomstat.h" // MAXSPLITSCREENPLAYERS + +#include "i_joy.h" // for joystick menu controls + +// Condition Sets +#include "m_cond.h" + +// And just some randomness for the exits. +#include "m_random.h" + +#if defined(HAVE_SDL) +#include "SDL.h" +#if SDL_VERSION_ATLEAST(2,0,0) +#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG +#endif +#endif + +#ifdef PC_DOS +#include // for snprintf +int snprintf(char *str, size_t n, const char *fmt, ...); +//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); +#endif + +// flags for text highlights +#define highlightflags V_ORANGEMAP +#define recommendedflags V_GREENMAP +#define warningflags V_GRAYMAP + +#define SKULLXOFF -32 +#define LINEHEIGHT 16 +#define STRINGHEIGHT 8 +#define FONTBHEIGHT 20 +#define SMALLLINEHEIGHT 8 +#define SLIDER_RANGE 10 +#define SLIDER_WIDTH (8*SLIDER_RANGE+6) +#define SERVERS_PER_PAGE 11 + +// +// M_Drawer +// Called after the view has been rendered, +// but before it has been blitted. +// +void M_Drawer(void) +{ + if (currentMenu == &MessageDef) + menuactive = true; + + if (menuwipe) + F_WipeStartScreen(); + + if (menuactive) + { + if (gamestate == GS_MENU) // draw BG + V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("MENUBG", PU_CACHE), NULL); + else if (!WipeInAction && currentMenu != &PAUSE_PlaybackMenuDef) + V_DrawFadeScreen(0xFF00, 16); // now that's more readable with a faded background (yeah like Quake...) + + if (currentMenu->drawroutine) + currentMenu->drawroutine(); // call current menu Draw routine + + // draw non-green resolution border + if ((gamestate == GS_MENU) && ((vid.width % BASEVIDWIDTH != 0) || (vid.height % BASEVIDHEIGHT != 0))) + V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("WEIRDRES", PU_CACHE), NULL); + + // Draw version down in corner + // ... but only in the MAIN MENU. I'm a picky bastard. + if (currentMenu == &MainDef) + { + if (customversionstring[0] != '\0') + { + V_DrawThinString(vid.dupx, vid.height - 20*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT, "Mod version:"); + V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring); + } + else + { +#ifdef DEVELOP // Development -- show revision / branch info + V_DrawThinString(vid.dupx, vid.height - 20*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, compbranch); + V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision); +#else // Regular build + V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s", VERSIONSTRING)); +#endif + } + } + } + + if (menuwipe) + { + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipe_menu_final], false, "FADEMAP0", true); + menuwipe = false; + } + + // focus lost notification goes on top of everything, even the former everything + if (window_notinfocus && cv_showfocuslost.value) + { + M_DrawTextBox((BASEVIDWIDTH/2) - (60), (BASEVIDHEIGHT/2) - (16), 13, 2); + if (gamestate == GS_LEVEL && (P_AutoPause() || paused)) + V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), highlightflags, "Game Paused"); + else + V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), highlightflags, "Focus Lost"); + } +} + +// ========================================================================== +// GENERIC MENUS +// ========================================================================== + +// +// M_DrawMenuTooltips +// +// Draw a banner across the top of the screen, with a description of the current option displayed +// +static void M_DrawMenuTooltips(void) +{ + V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("MENUHINT", PU_CACHE), NULL); + if (currentMenu->menuitems[itemOn].tooltip != NULL) + V_DrawCenteredThinString(BASEVIDWIDTH/2, 12, V_ALLOWLOWERCASE|V_6WIDTHSPACE, currentMenu->menuitems[itemOn].tooltip); +} + +// +// M_DrawMenuPreviews +// +// Draw a box with a preview image of the current option +// +static void M_DrawMenuPreviews(void) +{ + V_DrawFixedPatch(172<menuitems[itemOn].patch != NULL) + V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName(currentMenu->menuitems[itemOn].patch, PU_CACHE), NULL); +} + +// Converts a string into question marks. +// Used for the secrets menu, to hide yet-to-be-unlocked stuff. +static const char *M_CreateSecretMenuOption(const char *str) +{ + static char qbuf[32]; + int i; + + for (i = 0; i < 31; ++i) + { + if (!str[i]) + { + qbuf[i] = '\0'; + return qbuf; + } + else if (str[i] != ' ') + qbuf[i] = '?'; + else + qbuf[i] = ' '; + } + + qbuf[31] = '\0'; + return qbuf; +} + +// +// M_DrawGenericMenu +// +// Default, generic text-based list menu, used for Options +// +void M_DrawGenericMenu(void) +{ + INT32 x = 0, y = 0, w, i, cursory = 0; + + M_DrawMenuTooltips(); + + for (i = 0; i < currentMenu->numitems; i++) + { + if (i == itemOn) + cursory = y; + + switch (currentMenu->menuitems[i].status & IT_DISPLAY) + { + case IT_PATCH: + if (currentMenu->menuitems[i].patch && currentMenu->menuitems[i].patch[0]) + { + if (currentMenu->menuitems[i].status & IT_CENTER) + { + patch_t *p; + p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); + V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p); + } + else + { + V_DrawScaledPatch(x, y, 0, + W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE)); + } + } + /* FALLTHRU */ + case IT_NOTHING: + case IT_DYBIGSPACE: + y = currentMenu->y + currentMenu->menuitems[i].mvar1;//+= LINEHEIGHT; + break; +#if 0 + case IT_BIGSLIDER: + M_DrawThermo(x, y, (consvar_t *)currentMenu->menuitems[i].itemaction); + y += LINEHEIGHT; + break; +#endif + case IT_STRING: + case IT_WHITESTRING: + if (currentMenu->menuitems[i].mvar1) + y = currentMenu->y+currentMenu->menuitems[i].mvar1; + if (i == itemOn) + cursory = y; + + if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) + V_DrawString(x, y, 0, currentMenu->menuitems[i].text); + else + V_DrawString(x, y, highlightflags, currentMenu->menuitems[i].text); + + // Cvar specific handling + switch (currentMenu->menuitems[i].status & IT_TYPE) + case IT_CVAR: + { + consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + char asterisks[MAXSTRINGLENGTH+1]; + size_t sl; + switch (currentMenu->menuitems[i].status & IT_CVARTYPE) + { +#if 0 + case IT_CV_SLIDER: + M_DrawSlider(x, y, cv, (i == itemOn)); + case IT_CV_NOPRINT: // color use this + case IT_CV_INVISSLIDER: // monitor toggles use this + break; +#endif + case IT_CV_PASSWORD: + if (i == itemOn) + { + V_DrawRightAlignedThinString(x + MAXSTRINGLENGTH*8 + 10, y, V_ALLOWLOWERCASE, va(M_GetText("Tab: %s password"), cv->value ? "hide" : "show")); + } + + if (!cv->value || i != itemOn) + { + sl = strlen(cv->string); + memset(asterisks, '*', sl); + memset(asterisks + sl, 0, MAXSTRINGLENGTH+1-sl); + + M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); + V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, asterisks); + if (skullAnimCounter < 4 && i == itemOn) + V_DrawCharacter(x + 8 + V_StringWidth(asterisks, 0), y + 12, + '_' | 0x80, false); + y += 16; + break; + } + /* fallthru */ + case IT_CV_STRING: + M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); + V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string); + if (skullAnimCounter < 4 && i == itemOn) + V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 12, + '_' | 0x80, false); + y += 16; + break; + default: + w = V_StringWidth(cv->string, 0); + V_DrawString(BASEVIDWIDTH - x - w, y, + ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? warningflags : highlightflags), cv->string); + if (i == itemOn) + { + V_DrawCharacter(BASEVIDWIDTH - x - 10 - w - (skullAnimCounter/5), y, + '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, + '\x1D' | highlightflags, false); // right arrow + } + break; + } + break; + } + y += STRINGHEIGHT; + break; + case IT_STRING2: + V_DrawString(x, y, 0, currentMenu->menuitems[i].text); + /* FALLTHRU */ + case IT_DYLITLSPACE: + y += SMALLLINEHEIGHT; + break; + case IT_GRAYPATCH: + if (currentMenu->menuitems[i].patch && currentMenu->menuitems[i].patch[0]) + V_DrawMappedPatch(x, y, 0, + W_CachePatchName(currentMenu->menuitems[i].patch,PU_CACHE), graymap); + y += LINEHEIGHT; + break; + case IT_TRANSTEXT: + if (currentMenu->menuitems[i].mvar1) + y = currentMenu->y+currentMenu->menuitems[i].mvar1; + /* FALLTHRU */ + case IT_TRANSTEXT2: + V_DrawString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text); + y += SMALLLINEHEIGHT; + break; + case IT_QUESTIONMARKS: + if (currentMenu->menuitems[i].mvar1) + y = currentMenu->y+currentMenu->menuitems[i].mvar1; + + V_DrawString(x, y, V_TRANSLUCENT|V_OLDSPACING, M_CreateSecretMenuOption(currentMenu->menuitems[i].text)); + y += SMALLLINEHEIGHT; + break; + case IT_HEADERTEXT: // draws 16 pixels to the left, in yellow text + if (currentMenu->menuitems[i].mvar1) + y = currentMenu->y+currentMenu->menuitems[i].mvar1; + + V_DrawString(x-16, y, highlightflags, currentMenu->menuitems[i].text); + y += SMALLLINEHEIGHT; + break; + } + } + + // DRAW THE SKULL CURSOR + if (((currentMenu->menuitems[itemOn].status & IT_DISPLAY) == IT_PATCH) + || ((currentMenu->menuitems[itemOn].status & IT_DISPLAY) == IT_NOTHING)) + { + V_DrawScaledPatch(currentMenu->x + SKULLXOFF, cursory - 5, 0, + W_CachePatchName("M_CURSOR", PU_CACHE)); + } + else + { + V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, + W_CachePatchName("M_CURSOR", PU_CACHE)); + V_DrawString(currentMenu->x, cursory, highlightflags, currentMenu->menuitems[itemOn].text); + } +} + +// +// M_DrawKartGamemodeMenu +// +// Huge gamemode-selection list for main menu +// +void M_DrawKartGamemodeMenu(void) +{ + INT16 i, x = 170; + + M_DrawMenuTooltips(); + M_DrawMenuPreviews(); + + if (menutransition.tics) + x -= 24 * menutransition.tics; + + for (i = 0; i < currentMenu->numitems; i++) + { + switch (currentMenu->menuitems[i].status & IT_DISPLAY) + { + case IT_STRING: + V_DrawRightAlignedGamemodeString(x, currentMenu->menuitems[i].mvar1, 0, currentMenu->menuitems[i].text, + (i == itemOn) ? SKINCOLOR_PLAGUE : SKINCOLOR_PIGEON); + break; + } + } +} + +#define MAXMSGLINELEN 256 + +// +// Draw a textbox, like Quake does, because sometimes it's difficult +// to read the text with all the stuff in the background... +// +void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines) +{ + // Solid color textbox. + V_DrawFill(x+5, y+5, width*8+6, boxlines*8+6, 159); + //V_DrawFill(x+8, y+8, width*8, boxlines*8, 31); +} + +// +// M_DrawMessageMenu +// +// Generic message prompt +// +void M_DrawMessageMenu(void) +{ + INT32 y = currentMenu->y; + size_t i, start = 0; + INT16 max; + char string[MAXMSGLINELEN]; + INT32 mlines; + const char *msg = currentMenu->menuitems[0].text; + + mlines = currentMenu->lastOn>>8; + max = (INT16)((UINT8)(currentMenu->lastOn & 0xFF)*8); + + M_DrawTextBox(currentMenu->x, y - 8, (max+7)>>3, mlines); + + while (*(msg+start)) + { + size_t len = strlen(msg+start); + + for (i = 0; i < len; i++) + { + if (*(msg+start+i) == '\n') + { + memset(string, 0, MAXMSGLINELEN); + if (i >= MAXMSGLINELEN) + { + CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg); + return; + } + else + { + strncpy(string,msg+start, i); + string[i] = '\0'; + start += i; + i = (size_t)-1; //added : 07-02-98 : damned! + start++; + } + break; + } + } + + if (i == strlen(msg+start)) + { + if (i >= MAXMSGLINELEN) + { + CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg); + return; + } + else + { + strcpy(string, msg + start); + start += i; + } + } + + V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string); + y += 8; //SHORT(hu_font[0]->height); + } +} + +// Draw an Image Def. Aka, Help images. +// Defines what image is used in (menuitem_t)->patch. +// You can even put multiple images in one menu! +void M_DrawImageDef(void) +{ + // Grr. Need to autodetect for pic_ts. + pic_t *pictest = (pic_t *)W_CachePatchName(currentMenu->menuitems[itemOn].patch, PU_CACHE); + if (!pictest->zero) + V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].patch)); + else + { + patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].patch, PU_CACHE); + if (patch->height <= BASEVIDHEIGHT) + V_DrawScaledPatch(0,0,0,patch); + else + V_DrawSmallScaledPatch(0,0,0,patch); + } + + if (currentMenu->menuitems[itemOn].mvar1) + { + V_DrawString(2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", (itemOn<<1)-1)); // intentionally not highlightflags, unlike below + V_DrawRightAlignedString(BASEVIDWIDTH-2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", itemOn<<1)); // ditto + } + else + { + INT32 x = BASEVIDWIDTH>>1, y = (BASEVIDHEIGHT>>1) - 4; + x += (itemOn ? 1 : -1)*((BASEVIDWIDTH>>2) + 10); + V_DrawCenteredString(x, y-10, highlightflags, "USE ARROW KEYS"); + V_DrawCharacter(x - 10 - (skullAnimCounter/5), y, + '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(x + 2 + (skullAnimCounter/5), y, + '\x1D' | highlightflags, false); // right arrow + V_DrawCenteredString(x, y+10, highlightflags, "TO LEAF THROUGH"); + } +} + +// +// PLAY MENUS +// + +static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y) +{ + const fixed_t rad = 32<mdepth == 2) + numoptions = setup_chargrid[p->gridx][p->gridy].numskins; + else + { + numoptions = 16; + patch = W_CachePatchName("COLORSPH", PU_CACHE); + } + + angamt /= numoptions*2; + + for (i = 0; i < numoptions; i++) + { + fixed_t cx = x << FRACBITS, cy = y << FRACBITS; + fixed_t ang = -(angamt * i); + UINT8 *colormap; + INT16 n; + + ang += 90; + + cx += FixedMul(rad, FINECOSINE(FixedAngle(ang << FRACBITS) >> ANGLETOFINESHIFT)); + cy += FixedMul(rad, FINESINE(FixedAngle(ang << FRACBITS) >> ANGLETOFINESHIFT)) >> 2; + + if (p->mdepth == 2) + { + SINT8 skin; + + cx -= 8<clonenum + i) % setup_chargrid[p->gridx][p->gridy].numskins; + + skin = setup_chargrid[p->gridx][p->gridy].skinlist[n]; + + colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE); + patch = facerankprefix[skin]; + } + else + { + cx -= 4<color + i) % (MAXSKINCOLORS-1)); + colormap = R_GetTranslationColormap(TC_DEFAULT, n, GTC_MENUCACHE); + } + + V_DrawFixedPatch(cx, cy, FRACUNIT, 0, patch, colormap); + } +} + +static void M_DrawCharSelectPreview(UINT8 num) +{ + INT16 x = 11, y = 5; + char letter = 'A' + num; + SINT8 skin; + UINT8 color; + UINT8 *colormap; + patch_t *sprpatch; + spritedef_t *sprdef; + spriteframe_t *sprframe; + setup_player_t *p = &setup_player[num]; + + if (num & 1) + x += 233; + + if (num > 1) + y += 99; + + V_DrawScaledPatch(x, y+6, V_TRANSLUCENT, W_CachePatchName("PREVBACK", PU_CACHE)); + + if (p->mdepth > 0) + { + skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]; + + color = p->color; + colormap = R_GetTranslationColormap(skin, color, GTC_MENUCACHE); + + if (skin != -1) + { + statenum_t st = S_KART_WALK1; + UINT32 flags = 0; + UINT32 frame; + + if (skullAnimCounter & 1) + st++; + + sprdef = &skins[skin].spritedef; + + if (sprdef->numframes) // No frames ?? + { + frame = states[st].frame & FF_FRAMEMASK; + if (frame >= sprdef->numframes) // Walking animation missing + frame = 0; // Try to use standing frame + + sprframe = &sprdef->spriteframes[frame]; + sprpatch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE); + if (sprframe->flip & 1) // Only for first sprite + flags |= V_FLIP; // This sprite is left/right flipped! + + // Flip for left-side players + if (!(num & 1)) + flags ^= V_FLIP; + + if (skins[skin].flags & SF_HIRES) + { + V_DrawFixedPatch((x+32)<mdepth == 2 || p->mdepth == 3) + M_DrawCharSelectCircle(p, x+32, y+48); + } + + V_DrawScaledPatch(x+9, y+2, 0, W_CachePatchName("FILEBACK", PU_CACHE)); + V_DrawScaledPatch(x, y, 0, W_CachePatchName(va("CHARSEL%c", letter), PU_CACHE)); + + if (p->mdepth == 0 && (skullAnimCounter/5)) + V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PSTART", PU_CACHE)); +} + +void M_DrawCharacterSelect(void) +{ + UINT8 i, j, k; + UINT16 quadx, quady; + SINT8 skin; + + // We have to loop twice -- first time to draw the drop shadows, a second time to draw the icons. + for (i = 0; i < 9; i++) + { + for (j = 0; j < 9; j++) + { + skin = setup_chargrid[i][j].skinlist[0]; + quadx = 4 * (i / 3); + quady = 4 * (j / 3); + + // Here's a quick little cheat to save on drawing time! + // Don't draw a shadow if it'll get covered by another icon + if ((i % 3 < 2) && (j % 3 < 2)) + { + if ((setup_chargrid[i+1][j].skinlist[0] != -1) + && (setup_chargrid[i][j+1].skinlist[0] != -1) + && (setup_chargrid[i+1][j+1].skinlist[0] != -1)) + continue; + } + + if (skin != -1) + V_DrawScaledPatch(82 + (i*16) + quadx + 1, 22 + (j*16) + quady + 1, 0, W_CachePatchName("ICONBACK", PU_CACHE)); + } + } + + // Draw this inbetween. These drop shadows should be covered by the stat graph, but the icons shouldn't. + V_DrawScaledPatch(3, 2, 0, W_CachePatchName("STATGRPH", PU_CACHE)); + + // Draw the icons now + for (i = 0; i < 9; i++) + { + for (j = 0; j < 9; j++) + { + for (k = 0; k < setup_numplayers; k++) + { + if (setup_player[k].gridx == i && setup_player[k].gridy == j) + break; // k == setup_numplayers means no one has it selected + } + + skin = setup_chargrid[i][j].skinlist[0]; + quadx = 4 * (i / 3); + quady = 4 * (j / 3); + + if (skin != -1) + { + UINT8 *colormap; + + if (k == setup_numplayers) + colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GREY, GTC_MENUCACHE); + else + colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE); + + V_DrawMappedPatch(82 + (i*16) + quadx, 22 + (j*16) + quady, 0, facerankprefix[skin], colormap); + } + } + } + + // Draw a preview for each player + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + M_DrawCharSelectPreview(i); +} + +// +// INGAME / PAUSE MENUS +// +void M_DrawPlaybackMenu(void) +{ + INT16 i; + patch_t *icon = NULL; + UINT8 *activemap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GOLD, GTC_MENUCACHE); + + // Toggle items + if (paused && !demo.rewinding) + { + PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = PAUSE_PlaybackMenu[playback_rewind].status = IT_DISABLED; + PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = PAUSE_PlaybackMenu[playback_backframe].status = IT_CALL|IT_STRING; + + if (itemOn >= playback_rewind && itemOn <= playback_fastforward) + itemOn += playback_backframe - playback_rewind; + } + else + { + PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = PAUSE_PlaybackMenu[playback_rewind].status = IT_CALL|IT_STRING; + PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = PAUSE_PlaybackMenu[playback_backframe].status = IT_DISABLED; + + if (itemOn >= playback_backframe && itemOn <= playback_advanceframe) + itemOn -= playback_backframe - playback_rewind; + } + + if (modeattacking) + { + for (i = playback_viewcount; i <= playback_view4; i++) + PAUSE_PlaybackMenu[i].status = IT_DISABLED; + + //PAUSE_PlaybackMenu[playback_moreoptions].mvar1 = 72; + //PAUSE_PlaybackMenu[playback_quit].mvar1 = 88; + PAUSE_PlaybackMenu[playback_quit].mvar1 = 72; + + //currentMenu->x = BASEVIDWIDTH/2 - 52; + currentMenu->x = BASEVIDWIDTH/2 - 44; + } + else + { + PAUSE_PlaybackMenu[playback_viewcount].status = IT_ARROWS|IT_STRING; + + for (i = 0; i <= splitscreen; i++) + PAUSE_PlaybackMenu[playback_view1+i].status = IT_ARROWS|IT_STRING; + for (i = splitscreen+1; i < 4; i++) + PAUSE_PlaybackMenu[playback_view1+i].status = IT_DISABLED; + + //PAUSE_PlaybackMenu[playback_moreoptions].mvar1 = 156; + //PAUSE_PlaybackMenu[playback_quit].mvar1 = 172; + PAUSE_PlaybackMenu[playback_quit].mvar1 = 156; + + //currentMenu->x = BASEVIDWIDTH/2 - 94; + currentMenu->x = BASEVIDWIDTH/2 - 88; + } + + // wip + //M_DrawTextBox(currentMenu->x-68, currentMenu->y-7, 15, 15); + //M_DrawCenteredMenu(); + + for (i = 0; i < currentMenu->numitems; i++) + { + UINT8 *inactivemap = NULL; + + if (i >= playback_view1 && i <= playback_view4) + { + if (modeattacking) continue; + + if (splitscreen >= i - playback_view1) + { + INT32 ply = displayplayers[i - playback_view1]; + + icon = facerankprefix[players[ply].skin]; + if (i != itemOn) + inactivemap = R_GetTranslationColormap(players[ply].skin, players[ply].skincolor, GTC_MENUCACHE); + } + else if (currentMenu->menuitems[i].patch && W_CheckNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) + icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); + } + else if (currentMenu->menuitems[i].status == IT_DISABLED) + continue; + else if (currentMenu->menuitems[i].patch && W_CheckNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) + icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); + + if ((i == playback_fastforward && cv_playbackspeed.value > 1) || (i == playback_rewind && demo.rewinding)) + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].mvar1, currentMenu->y, V_SNAPTOTOP, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JAWZ, GTC_MENUCACHE)); + else + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].mvar1, currentMenu->y, V_SNAPTOTOP, icon, (i == itemOn) ? activemap : inactivemap); + + if (i == itemOn) + { + V_DrawCharacter(currentMenu->x + currentMenu->menuitems[i].mvar1 + 4, currentMenu->y + 14, + '\x1A' | V_SNAPTOTOP|highlightflags, false); + + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, V_SNAPTOTOP|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + + if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_ARROWS) + { + char *str; + + if (!(i == playback_viewcount && splitscreen == 3)) + V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 28 - (skullAnimCounter/5), + '\x1A' | V_SNAPTOTOP|highlightflags, false); // up arrow + + if (!(i == playback_viewcount && splitscreen == 0)) + V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 48 + (skullAnimCounter/5), + '\x1B' | V_SNAPTOTOP|highlightflags, false); // down arrow + + switch (i) + { + case playback_viewcount: + str = va("%d", splitscreen+1); + break; + + case playback_view1: + case playback_view2: + case playback_view3: + case playback_view4: + str = player_names[displayplayers[i - playback_view1]]; // 0 to 3 + break; + + default: // shouldn't ever be reached but whatever + continue; + } + + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 38, V_SNAPTOTOP|V_ALLOWLOWERCASE|highlightflags, str); + } + } + } +} diff --git a/src/k_menufunc.c b/src/k_menufunc.c new file mode 100644 index 000000000..10dd84f2b --- /dev/null +++ b/src/k_menufunc.c @@ -0,0 +1,2021 @@ +/// \file k_menufunc.c +/// \brief SRB2Kart's menu functions + +#ifdef __GNUC__ +#include +#endif + +#include "k_menu.h" + +#include "doomdef.h" +#include "d_main.h" +#include "d_netcmd.h" +#include "console.h" +#include "r_local.h" +#include "hu_stuff.h" +#include "g_game.h" +#include "g_input.h" +#include "m_argv.h" + +// Data. +#include "sounds.h" +#include "s_sound.h" +#include "i_system.h" + +// Addfile +#include "filesrch.h" + +#include "v_video.h" +#include "i_video.h" +#include "keys.h" +#include "z_zone.h" +#include "w_wad.h" +#include "p_local.h" +#include "p_setup.h" +#include "f_finale.h" + +#ifdef HWRENDER +#include "hardware/hw_main.h" +#endif + +#include "d_net.h" +#include "mserv.h" +#include "m_misc.h" +#include "m_anigif.h" +#include "byteptr.h" +#include "st_stuff.h" +#include "i_sound.h" +#include "k_kart.h" // SRB2kart +#include "d_player.h" // KITEM_ constants +#include "doomstat.h" // MAXSPLITSCREENPLAYERS + +#include "i_joy.h" // for joystick menu controls + +// Condition Sets +#include "m_cond.h" + +// And just some randomness for the exits. +#include "m_random.h" + +#if defined(HAVE_SDL) +#include "SDL.h" +#if SDL_VERSION_ATLEAST(2,0,0) +#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG +#endif +#endif + +#ifdef PC_DOS +#include // for snprintf +int snprintf(char *str, size_t n, const char *fmt, ...); +//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); +#endif + +// ========================================================================== +// GLOBAL VARIABLES +// ========================================================================== + +boolean menuactive = false; +boolean fromlevelselect = false; + +// current menudef +menu_t *currentMenu = &MainDef; + +char dummystaffname[22]; + +INT16 itemOn = 0; // menu item skull is on, Hack by Tails 09-18-2002 +INT16 skullAnimCounter = 10; // skull animation counter +struct menutransition_s menutransition; // Menu transition properties + +// finish wipes between screens +boolean menuwipe = false; + +// lock out further input in a tic when important buttons are pressed +// (in other words -- stop bullshit happening by mashing buttons in fades) +static boolean noFurtherInput = false; + +// ========================================================================== +// CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE. +// ========================================================================== + +// Consvar onchange functions +static void Nextmap_OnChange(void); +static void Newgametype_OnChange(void); +static void Dummymenuplayer_OnChange(void); +//static void Dummymares_OnChange(void); +static void Dummystaff_OnChange(void); + +consvar_t cv_showfocuslost = {"showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL }; + +static CV_PossibleValue_t serversort_cons_t[] = { + {0,"Ping"}, + {1,"Modified State"}, + {2,"Most Players"}, + {3,"Least Players"}, + {4,"Max Player Slots"}, + {5,"Gametype"}, + {0,NULL} +}; +consvar_t cv_serversort = {"serversort", "Ping", CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL}; + +// autorecord demos for time attack +static consvar_t cv_autorecord = {"autorecord", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; + +CV_PossibleValue_t ghost_cons_t[] = {{0, "Hide"}, {1, "Show Character"}, {2, "Show All"}, {0, NULL}}; +CV_PossibleValue_t ghost2_cons_t[] = {{0, "Hide"}, {1, "Show"}, {0, NULL}}; + +consvar_t cv_ghost_besttime = {"ghost_besttime", "Show All", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ghost_bestlap = {"ghost_bestlap", "Show All", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ghost_last = {"ghost_last", "Show All", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ghost_guest = {"ghost_guest", "Show", CV_SAVE, ghost2_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ghost_staff = {"ghost_staff", "Show", CV_SAVE, ghost2_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static void Splitplayers_OnChange(void); +CV_PossibleValue_t splitplayers_cons_t[] = {{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {0, NULL}}; +consvar_t cv_splitplayers = {"splitplayers", "One", CV_CALL, splitplayers_cons_t, Splitplayers_OnChange, 0, NULL, NULL, 0, 0, NULL}; + +//Console variables used solely in the menu system. +//todo: add a way to use non-console variables in the menu +// or make these consvars legitimate like color or skin. +static CV_PossibleValue_t map_cons_t[] = { + {0,"MIN"}, + {NUMMAPS, "MAX"}, + {0, NULL} +}; +consvar_t cv_nextmap = {"nextmap", "1", CV_HIDDEN|CV_CALL, map_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}}; +consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL}; + +// This gametype list is integral for many different reasons. +// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! +CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; +consvar_t cv_newgametype = {"newgametype", "Race", CV_HIDDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t dummymenuplayer_cons_t[] = {{0, "NOPE"}, {1, "P1"}, {2, "P2"}, {3, "P3"}, {4, "P4"}, {0, NULL}}; +static consvar_t cv_dummymenuplayer = {"dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t dummyteam_cons_t[] = {{0, "Spectator"}, {1, "Red"}, {2, "Blue"}, {0, NULL}}; +static consvar_t cv_dummyteam = {"dummyteam", "Spectator", CV_HIDDEN, dummyteam_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t dummyspectate_cons_t[] = {{0, "Spectator"}, {1, "Playing"}, {0, NULL}}; +static consvar_t cv_dummyspectate = {"dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"}, {0, NULL}}; +static consvar_t cv_dummyscramble = {"dummyscramble", "Random", CV_HIDDEN, dummyscramble_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + +static CV_PossibleValue_t dummystaff_cons_t[] = {{0, "MIN"}, {100, "MAX"}, {0, NULL}}; +static consvar_t cv_dummystaff = {"dummystaff", "0", CV_HIDDEN|CV_CALL, dummystaff_cons_t, Dummystaff_OnChange, 0, NULL, NULL, 0, 0, NULL}; + +// ========================================================================== +// CVAR ONCHANGE EVENTS GO HERE +// ========================================================================== +// (there's only a couple anyway) + +// Prototypes +#if 0 +static INT32 M_FindFirstMap(INT32 gtype); +static INT32 M_GetFirstLevelInList(void); +#endif + +// Nextmap. Used for Time Attack. +static void Nextmap_OnChange(void) +{ + char *leveltitle; + + // Update the string in the consvar. + Z_Free(cv_nextmap.zstring); + leveltitle = G_BuildMapTitle(cv_nextmap.value); + cv_nextmap.string = cv_nextmap.zstring = leveltitle ? leveltitle : Z_StrDup(G_BuildMapName(cv_nextmap.value)); + +#if 0 + if (currentMenu == &SP_TimeAttackDef) + { + // see also p_setup.c's P_LoadRecordGhosts + const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; + char *gpath = malloc(glen); + INT32 i; + UINT8 active; + + if (!gpath) + return; + + sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)); + + CV_StealthSetValue(&cv_dummystaff, 0); + + active = false; + SP_TimeAttackMenu[taguest].status = IT_DISABLED; + SP_TimeAttackMenu[tareplay].status = IT_DISABLED; + //SP_TimeAttackMenu[taghost].status = IT_DISABLED; + + // Check if file exists, if not, disable REPLAY option + for (i = 0; i < 4; i++) + { + SP_ReplayMenu[i].status = IT_DISABLED; + SP_GuestReplayMenu[i].status = IT_DISABLED; + } + SP_ReplayMenu[4].status = IT_DISABLED; + + SP_GhostMenu[3].status = IT_DISABLED; + SP_GhostMenu[4].status = IT_DISABLED; + + if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, cv_chooseskin.string))) { + SP_ReplayMenu[0].status = IT_WHITESTRING|IT_CALL; + SP_GuestReplayMenu[0].status = IT_WHITESTRING|IT_CALL; + active |= 3; + } + if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, cv_chooseskin.string))) { + SP_ReplayMenu[1].status = IT_WHITESTRING|IT_CALL; + SP_GuestReplayMenu[1].status = IT_WHITESTRING|IT_CALL; + active |= 3; + } + if (FIL_FileExists(va("%s-%s-last.lmp", gpath, cv_chooseskin.string))) { + SP_ReplayMenu[2].status = IT_WHITESTRING|IT_CALL; + SP_GuestReplayMenu[2].status = IT_WHITESTRING|IT_CALL; + active |= 3; + } + + if (FIL_FileExists(va("%s-guest.lmp", gpath))) + { + SP_ReplayMenu[3].status = IT_WHITESTRING|IT_CALL; + SP_GuestReplayMenu[3].status = IT_WHITESTRING|IT_CALL; + SP_GhostMenu[3].status = IT_STRING|IT_CVAR; + active |= 3; + } + + CV_SetValue(&cv_dummystaff, 1); + if (cv_dummystaff.value) + { + SP_ReplayMenu[4].status = IT_WHITESTRING|IT_KEYHANDLER; + SP_GhostMenu[4].status = IT_STRING|IT_CVAR; + CV_StealthSetValue(&cv_dummystaff, 1); + active |= 1; + } + + if (active) { + if (active & 1) + SP_TimeAttackMenu[tareplay].status = IT_WHITESTRING|IT_SUBMENU; + if (active & 2) + SP_TimeAttackMenu[taguest].status = IT_WHITESTRING|IT_SUBMENU; + } + else if (itemOn == tareplay) // Reset lastOn so replay isn't still selected when not available. + { + currentMenu->lastOn = itemOn; + itemOn = tastart; + } + + if (mapheaderinfo[cv_nextmap.value-1] && mapheaderinfo[cv_nextmap.value-1]->forcecharacter[0] != '\0') + CV_Set(&cv_chooseskin, mapheaderinfo[cv_nextmap.value-1]->forcecharacter); + + free(gpath); + } +#endif +} + +static void Dummymenuplayer_OnChange(void) +{ + if (cv_dummymenuplayer.value < 1) + CV_StealthSetValue(&cv_dummymenuplayer, splitscreen+1); + else if (cv_dummymenuplayer.value > splitscreen+1) + CV_StealthSetValue(&cv_dummymenuplayer, 1); +} + +static void Dummystaff_OnChange(void) +{ + lumpnum_t l; + + dummystaffname[0] = '\0'; + + if ((l = W_CheckNumForName(va("%sS01",G_BuildMapName(cv_nextmap.value)))) == LUMPERROR) + { + CV_StealthSetValue(&cv_dummystaff, 0); + return; + } + else + { + char *temp = dummystaffname; + UINT8 numstaff = 1; + while (numstaff < 99 && (l = W_CheckNumForName(va("%sS%02u",G_BuildMapName(cv_nextmap.value),numstaff+1))) != LUMPERROR) + numstaff++; + + if (cv_dummystaff.value < 1) + CV_StealthSetValue(&cv_dummystaff, numstaff); + else if (cv_dummystaff.value > numstaff) + CV_StealthSetValue(&cv_dummystaff, 1); + + if ((l = W_CheckNumForName(va("%sS%02u",G_BuildMapName(cv_nextmap.value), cv_dummystaff.value))) == LUMPERROR) + return; // shouldn't happen but might as well check... + + G_UpdateStaffGhostName(l); + + while (*temp) + temp++; + + sprintf(temp, " - %d", cv_dummystaff.value); + } +} + +// Newgametype. Used for gametype changes. +static void Newgametype_OnChange(void) +{ +#if 0 + if (cv_nextmap.value && menuactive) + { + if (!mapheaderinfo[cv_nextmap.value-1]) + P_AllocMapHeader((INT16)(cv_nextmap.value-1)); + + if ((cv_newgametype.value == GT_RACE && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_RACE)) + || (cv_newgametype.value == GT_MATCH && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_MATCH))) + { + INT32 value = 0; + + switch (cv_newgametype.value) + { + default: + case GT_RACE: + value = TOL_RACE; + break; + case GT_MATCH: + value = TOL_MATCH; + break; + } + + CV_SetValue(&cv_nextmap, M_FindFirstMap(value)); + } + } +#endif +} + +void Screenshot_option_Onchange(void) +{ +#if 0 + OP_ScreenshotOptionsMenu[op_screenshot_folder].status = + (cv_screenshot_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); +#endif +} + +void Moviemode_mode_Onchange(void) +{ +#if 0 + INT32 i, cstart, cend; + for (i = op_screenshot_gif_start; i <= op_screenshot_apng_end; ++i) + OP_ScreenshotOptionsMenu[i].status = IT_DISABLED; + + switch (cv_moviemode.value) + { + case MM_GIF: + cstart = op_screenshot_gif_start; + cend = op_screenshot_gif_end; + break; + case MM_APNG: + cstart = op_screenshot_apng_start; + cend = op_screenshot_apng_end; + break; + default: + return; + } + for (i = cstart; i <= cend; ++i) + OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR; +#endif +} + +void Addons_option_Onchange(void) +{ +#if 0 + OP_AddonsOptionsMenu[op_addons_folder].status = + (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); +#endif +} + +void M_SortServerList(void) +{ +#if 0 +#ifndef NONET + switch(cv_serversort.value) + { + case 0: // Ping. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_time); + break; + case 1: // Modified state. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_modified); + break; + case 2: // Most players. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer_reverse); + break; + case 3: // Least players. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_numberofplayer); + break; + case 4: // Max players. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_maxplayer_reverse); + break; + case 5: // Gametype. + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametype); + break; + } +#endif +#endif +} + +// ========================================================================= +// BASIC MENU HANDLING +// ========================================================================= + +static void M_ChangeCvar(INT32 choice) +{ + consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; + + if (choice == -1) + { + if (cv == &cv_playercolor) + { + SINT8 skinno = R_SkinAvailable(cv_chooseskin.string); + if (skinno != -1) + CV_SetValue(cv,skins[skinno].prefcolor); + return; + } + CV_Set(cv,cv->defaultvalue); + return; + } + + choice = (choice<<1) - 1; + + if (((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_SLIDER) + ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_INVISSLIDER) + ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_NOMOD)) + { + CV_SetValue(cv,cv->value+choice); + } + else if (cv->flags & CV_FLOAT) + { + char s[20]; + sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); + CV_Set(cv,s); + } + else + { +#ifndef NONET + if (cv == &cv_nettimeout || cv == &cv_jointimeout) + choice *= (TICRATE/7); + else if (cv == &cv_maxsend) + choice *= 512; + else if (cv == &cv_maxping) + choice *= 50; +#endif + CV_AddValue(cv,choice); + } +} + +static boolean M_ChangeStringCvar(INT32 choice) +{ + consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; + char buf[MAXSTRINGLENGTH]; + size_t len; + + if (shiftdown && choice >= 32 && choice <= 127) + choice = shiftxform[choice]; + + switch (choice) + { + case KEY_BACKSPACE: + len = strlen(cv->string); + if (len > 0) + { + S_StartSound(NULL, sfx_s3k5b); // Tails + M_Memcpy(buf, cv->string, len); + buf[len-1] = 0; + CV_Set(cv, buf); + } + return true; + case KEY_DEL: + if (cv->string[0]) + { + S_StartSound(NULL, sfx_s3k5b); // Tails + CV_Set(cv, ""); + } + return true; + default: + if (choice >= 32 && choice <= 127) + { + len = strlen(cv->string); + if (len < MAXSTRINGLENGTH - 1) + { + S_StartSound(NULL, sfx_s3k5b); // Tails + M_Memcpy(buf, cv->string, len); + buf[len++] = (char)choice; + buf[len] = 0; + CV_Set(cv, buf); + } + return true; + } + break; + } + return false; +} + +static void M_NextOpt(void) +{ + INT16 oldItemOn = itemOn; // prevent infinite loop + + if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) + ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value = 0; + + do + { + if (itemOn + 1 > currentMenu->numitems - 1) + itemOn = 0; + else + itemOn++; + } while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE); +} + +static void M_PrevOpt(void) +{ + INT16 oldItemOn = itemOn; // prevent infinite loop + + if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) + ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value = 0; + + do + { + if (!itemOn) + itemOn = currentMenu->numitems - 1; + else + itemOn--; + } while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE); +} + +// +// M_Responder +// +boolean M_Responder(event_t *ev) +{ + INT32 ch = -1; +// INT32 i; + static tic_t joywait = 0, mousewait = 0; + static INT32 pjoyx = 0, pjoyy = 0; + static INT32 pmousex = 0, pmousey = 0; + static INT32 lastx = 0, lasty = 0; + void (*routine)(INT32 choice); // for some casting problem + + if (dedicated || (demo.playback && demo.title) + || gamestate == GS_INTRO || gamestate == GS_CUTSCENE || gamestate == GS_GAMEEND + || gamestate == GS_CREDITS || gamestate == GS_EVALUATION) + return false; + + if (noFurtherInput) + { + // Ignore input after enter/escape/other buttons + // (but still allow shift keyup so caps doesn't get stuck) + return false; + } + else if (ev->type == ev_keydown) + { + ch = ev->data1; + + // added 5-2-98 remap virtual keys (mouse & joystick buttons) + switch (ch) + { + case KEY_MOUSE1: + //case KEY_JOY1: + //case KEY_JOY1 + 2: + ch = KEY_ENTER; + break; + /*case KEY_JOY1 + 3: // Brake can function as 'n' for message boxes now. + ch = 'n'; + break;*/ + case KEY_MOUSE1 + 1: + //case KEY_JOY1 + 1: + ch = KEY_BACKSPACE; + break; + case KEY_HAT1: + ch = KEY_UPARROW; + break; + case KEY_HAT1 + 1: + ch = KEY_DOWNARROW; + break; + case KEY_HAT1 + 2: + ch = KEY_LEFTARROW; + break; + case KEY_HAT1 + 3: + ch = KEY_RIGHTARROW; + break; + } + } + else if (menuactive) + { + if (ev->type == ev_joystick && ev->data1 == 0 && joywait < I_GetTime()) + { + const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone.value) >> FRACBITS; + if (ev->data3 != INT32_MAX) + { + if (Joystick.bGamepadStyle || abs(ev->data3) > jdeadzone) + { + if (ev->data3 < 0 && pjoyy >= 0) + { + ch = KEY_UPARROW; + joywait = I_GetTime() + NEWTICRATE/7; + } + else if (ev->data3 > 0 && pjoyy <= 0) + { + ch = KEY_DOWNARROW; + joywait = I_GetTime() + NEWTICRATE/7; + } + pjoyy = ev->data3; + } + else + pjoyy = 0; + } + + if (ev->data2 != INT32_MAX) + { + if (Joystick.bGamepadStyle || abs(ev->data2) > jdeadzone) + { + if (ev->data2 < 0 && pjoyx >= 0) + { + ch = KEY_LEFTARROW; + joywait = I_GetTime() + NEWTICRATE/17; + } + else if (ev->data2 > 0 && pjoyx <= 0) + { + ch = KEY_RIGHTARROW; + joywait = I_GetTime() + NEWTICRATE/17; + } + pjoyx = ev->data2; + } + else + pjoyx = 0; + } + } + else if (ev->type == ev_mouse && mousewait < I_GetTime()) + { + pmousey += ev->data3; + if (pmousey < lasty-30) + { + ch = KEY_DOWNARROW; + mousewait = I_GetTime() + NEWTICRATE/7; + pmousey = lasty -= 30; + } + else if (pmousey > lasty + 30) + { + ch = KEY_UPARROW; + mousewait = I_GetTime() + NEWTICRATE/7; + pmousey = lasty += 30; + } + + pmousex += ev->data2; + if (pmousex < lastx - 30) + { + ch = KEY_LEFTARROW; + mousewait = I_GetTime() + NEWTICRATE/7; + pmousex = lastx -= 30; + } + else if (pmousex > lastx+30) + { + ch = KEY_RIGHTARROW; + mousewait = I_GetTime() + NEWTICRATE/7; + pmousex = lastx += 30; + } + } + } + + if (ch == -1) + return false; + else if (ch == gamecontrol[gc_systemmenu][0] || ch == gamecontrol[gc_systemmenu][1]) // allow remappable ESC key + ch = KEY_ESCAPE; + else if ((ch == gamecontrol[gc_accelerate][0] || ch == gamecontrol[gc_accelerate][1]) && ch >= KEY_MOUSE1) + ch = KEY_ENTER; + + // F-Keys + if (!menuactive) + { + noFurtherInput = true; + + switch (ch) + { +#if 0 + case KEY_F1: // Help key + Command_Manual_f(); + return true; + + case KEY_F2: // Empty + return true; + + case KEY_F3: // Toggle HUD + CV_SetValue(&cv_showhud, !cv_showhud.value); + return true; + + case KEY_F4: // Sound Volume + if (modeattacking) + return true; + M_StartControlPanel(); + M_Options(0); + currentMenu = &OP_SoundOptionsDef; + itemOn = 0; + return true; + +#ifndef DC + case KEY_F5: // Video Mode + if (modeattacking) + return true; + M_StartControlPanel(); + M_Options(0); + M_VideoModeMenu(0); + return true; +#endif + + case KEY_F6: // Empty + return true; + + case KEY_F7: // Options + if (modeattacking) + return true; + M_StartControlPanel(); + M_Options(0); + M_SetupNextMenu(&OP_MainDef, false); + return true; + + // Screenshots on F8 now handled elsewhere + // Same with Moviemode on F9 + + case KEY_F10: // Quit SRB2 + M_QuitSRB2(0); + return true; + + case KEY_F11: // Gamma Level + CV_AddValue(&cv_usegamma, 1); + return true; + + // Spymode on F12 handled in game logic +#endif + case KEY_ESCAPE: // Pop up menu + if (chat_on) + { + HU_clearChatChars(); + chat_on = false; + } + else + M_StartControlPanel(); + return true; + } + + noFurtherInput = false; // turns out we didn't care + return false; + } + + + if ((ch == gamecontrol[gc_brake][0] || ch == gamecontrol[gc_brake][1]) && ch >= KEY_MOUSE1) // do this here, otherwise brake opens the menu mid-game + ch = KEY_ESCAPE; + + routine = currentMenu->menuitems[itemOn].itemaction; + + // Handle menuitems which need a specific key handling + if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER) + { + if (shiftdown && ch >= 32 && ch <= 127) + ch = shiftxform[ch]; + routine(ch); + return true; + } + + if (currentMenu->menuitems[itemOn].status == IT_MSGHANDLER) + { + if (currentMenu->menuitems[itemOn].mvar1 != MM_EVENTHANDLER) + { + if (ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE || ch == KEY_ENTER) + { + if (routine) + routine(ch); + M_StopMessage(0); + noFurtherInput = true; + return true; + } + return true; + } + else + { + // dirty hack: for customising controls, I want only buttons/keys, not moves + if (ev->type == ev_mouse || ev->type == ev_mouse2 || ev->type == ev_joystick + || ev->type == ev_joystick2 || ev->type == ev_joystick3 || ev->type == ev_joystick4) + return true; + if (routine) + { + void (*otherroutine)(event_t *sev) = currentMenu->menuitems[itemOn].itemaction; + otherroutine(ev); //Alam: what a hack + } + return true; + } + } + + // BP: one of the more big hack i have never made + if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR) + { + if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING || (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) + { + if (ch == KEY_TAB && (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) + ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value ^= 1; + + if (shiftdown && ch >= 32 && ch <= 127) + ch = shiftxform[ch]; + if (M_ChangeStringCvar(ch)) + return true; + else + routine = NULL; + } + else + routine = M_ChangeCvar; + } + + if (currentMenu == &PAUSE_PlaybackMenuDef) + { + // Flip left/right with up/down for the playback menu, since it's a horizontal icon row. + switch (ch) + { + case KEY_LEFTARROW: ch = KEY_UPARROW; break; + case KEY_UPARROW: ch = KEY_RIGHTARROW; break; + case KEY_RIGHTARROW: ch = KEY_DOWNARROW; break; + case KEY_DOWNARROW: ch = KEY_LEFTARROW; break; + default: break; + } + } + + // Keys usable within menu + switch (ch) + { + case KEY_DOWNARROW: + M_NextOpt(); + S_StartSound(NULL, sfx_s3k5b); + return true; + + case KEY_UPARROW: + M_PrevOpt(); + S_StartSound(NULL, sfx_s3k5b); + return true; + + case KEY_LEFTARROW: + if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS + || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) + { +#if 0 + if (currentMenu != &OP_SoundOptionsDef || itemOn > 3) +#endif + S_StartSound(NULL, sfx_s3k5b); + routine(0); + } + return true; + + case KEY_RIGHTARROW: + if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS + || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) + { +#if 0 + if (currentMenu != &OP_SoundOptionsDef || itemOn > 3) +#endif + S_StartSound(NULL, sfx_s3k5b); + routine(1); + } + return true; + + case KEY_ENTER: + noFurtherInput = true; + currentMenu->lastOn = itemOn; + +#if 0 + if (currentMenu == &PAUSE_PlaybackMenuDef) + { + boolean held = (boolean)playback_enterheld; + playback_enterheld = TICRATE/7; + if (held) + return true; + } +#endif + + if (routine) + { + S_StartSound(NULL, sfx_s3k5b); + + if (((currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_CALL + || (currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_SUBMENU) + && (currentMenu->menuitems[itemOn].status & IT_CALLTYPE)) + { + if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && majormods) + { + M_StartMessage(M_GetText("This cannot be done with complex add-ons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); + return true; + } + } + + switch (currentMenu->menuitems[itemOn].status & IT_TYPE) + { + case IT_CVAR: + case IT_ARROWS: + routine(1); // right arrow + break; + case IT_CALL: + routine(itemOn); + break; + case IT_SUBMENU: + currentMenu->lastOn = itemOn; + M_SetupNextMenu((menu_t *)currentMenu->menuitems[itemOn].itemaction, false); + break; + } + } + + return true; + + case KEY_ESCAPE: + //case KEY_JOY1 + 2: + M_GoBack(0); + return true; + + case KEY_BACKSPACE: +#if 0 + if ((currentMenu->menuitems[itemOn].status) == IT_CONTROL) + { + // detach any keys associated with the game control + G_ClearControlKeys(setupcontrols, currentMenu->menuitems[itemOn].mvar1); + S_StartSound(NULL, sfx_shldls); + return true; + } +#endif + + if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS + || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) + { + consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; + + if (cv == &cv_chooseskin + || cv == &cv_dummystaff + || cv == &cv_nextmap + || cv == &cv_newgametype) + return true; + +#if 0 + if (currentMenu != &OP_SoundOptionsDef || itemOn > 3) +#endif + S_StartSound(NULL, sfx_s3k5b); + + routine(-1); + return true; + } + + return false; + + default: + break; + } + + return true; +} + +// +// M_StartControlPanel +// +void M_StartControlPanel(void) +{ + // intro might call this repeatedly + if (menuactive) + { + CON_ToggleOff(); // move away console + return; + } + + if (gamestate == GS_TITLESCREEN) // Set up menu state + { + G_SetGamestate(GS_MENU); + + gameaction = ga_nothing; + paused = false; + CON_ToggleOff(); + + S_ChangeMusicInternal("menu", true); + } + + menuactive = true; + + if (demo.playback) + { + currentMenu = &PAUSE_PlaybackMenuDef; + } + else if (!Playing()) + { + currentMenu = &MainDef; + itemOn = 0; + } +#if 0 + else if (modeattacking) + { + currentMenu = &MAPauseDef; + itemOn = mapause_continue; + } + else if (!(netgame || multiplayer)) // Single Player + { + if (gamestate != GS_LEVEL) // intermission, so gray out stuff. + SPauseMenu[spause_retry].status = IT_GRAYEDOUT; + else + { + //INT32 numlives = 2; + + /*if (&players[consoleplayer]) + { + numlives = players[consoleplayer].lives; + if (players[consoleplayer].playerstate != PST_LIVE) + ++numlives; + } + + // The list of things that can disable retrying is (was?) a little too complex + // for me to want to use the short if statement syntax + if (numlives <= 1 || G_IsSpecialStage(gamemap)) + SPauseMenu[spause_retry].status = (IT_GRAYEDOUT); + else*/ + SPauseMenu[spause_retry].status = (IT_STRING | IT_CALL); + } + + currentMenu = &SPauseDef; + itemOn = spause_continue; + } + else // multiplayer + { + MPauseMenu[mpause_switchmap].status = IT_DISABLED; + MPauseMenu[mpause_addons].status = IT_DISABLED; + MPauseMenu[mpause_scramble].status = IT_DISABLED; + MPauseMenu[mpause_psetupsplit].status = IT_DISABLED; + MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED; + MPauseMenu[mpause_psetupsplit3].status = IT_DISABLED; + MPauseMenu[mpause_psetupsplit4].status = IT_DISABLED; + MPauseMenu[mpause_spectate].status = IT_DISABLED; + MPauseMenu[mpause_entergame].status = IT_DISABLED; + MPauseMenu[mpause_canceljoin].status = IT_DISABLED; + MPauseMenu[mpause_switchteam].status = IT_DISABLED; + MPauseMenu[mpause_switchspectate].status = IT_DISABLED; + MPauseMenu[mpause_psetup].status = IT_DISABLED; + MISC_ChangeTeamMenu[0].status = IT_DISABLED; + MISC_ChangeSpectateMenu[0].status = IT_DISABLED; + // Reset these in case splitscreen messes things up + MPauseMenu[mpause_switchteam].mvar1 = 48; + MPauseMenu[mpause_switchspectate].mvar1 = 48; + MPauseMenu[mpause_options].mvar1 = 64; + MPauseMenu[mpause_title].mvar1 = 80; + MPauseMenu[mpause_quit].mvar1 = 88; + Dummymenuplayer_OnChange(); + + if ((server || IsPlayerAdmin(consoleplayer))) + { + MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL; + MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL; + if (G_GametypeHasTeams()) + MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU; + } + + if (splitscreen) + { + MPauseMenu[mpause_psetupsplit].status = MPauseMenu[mpause_psetupsplit2].status = IT_STRING | IT_CALL; + MISC_ChangeTeamMenu[0].status = MISC_ChangeSpectateMenu[0].status = IT_STRING|IT_CVAR; + + if (netgame) + { + if (G_GametypeHasTeams()) + { + MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU; + MPauseMenu[mpause_switchteam].mvar1 += ((splitscreen+1) * 8); + MPauseMenu[mpause_options].mvar1 += 8; + MPauseMenu[mpause_title].mvar1 += 8; + MPauseMenu[mpause_quit].mvar1 += 8; + } + else if (G_GametypeHasSpectators()) + { + MPauseMenu[mpause_switchspectate].status = IT_STRING | IT_SUBMENU; + MPauseMenu[mpause_switchspectate].mvar1 += ((splitscreen+1) * 8); + MPauseMenu[mpause_options].mvar1 += 8; + MPauseMenu[mpause_title].mvar1 += 8; + MPauseMenu[mpause_quit].mvar1 += 8; + } + } + + if (splitscreen > 1) + { + MPauseMenu[mpause_psetupsplit3].status = IT_STRING | IT_CALL; + + MPauseMenu[mpause_options].mvar1 += 8; + MPauseMenu[mpause_title].mvar1 += 8; + MPauseMenu[mpause_quit].mvar1 += 8; + + if (splitscreen > 2) + { + MPauseMenu[mpause_psetupsplit4].status = IT_STRING | IT_CALL; + MPauseMenu[mpause_options].mvar1 += 8; + MPauseMenu[mpause_title].mvar1 += 8; + MPauseMenu[mpause_quit].mvar1 += 8; + } + } + } + else + { + MPauseMenu[mpause_psetup].status = IT_STRING | IT_CALL; + + if (G_GametypeHasTeams()) + MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU; + else if (G_GametypeHasSpectators()) + { + if (!players[consoleplayer].spectator) + MPauseMenu[mpause_spectate].status = IT_STRING | IT_CALL; + else if (players[consoleplayer].pflags & PF_WANTSTOJOIN) + MPauseMenu[mpause_canceljoin].status = IT_STRING | IT_CALL; + else + MPauseMenu[mpause_entergame].status = IT_STRING | IT_CALL; + } + else // in this odd case, we still want something to be on the menu even if it's useless + MPauseMenu[mpause_spectate].status = IT_GRAYEDOUT; + } + + currentMenu = &MPauseDef; + itemOn = mpause_continue; + } +#endif + + CON_ToggleOff(); // move away console +} + +// +// M_ClearMenus +// +void M_ClearMenus(boolean callexitmenufunc) +{ + if (!menuactive) + return; + + if (currentMenu->quitroutine && callexitmenufunc && !currentMenu->quitroutine()) + return; // we can't quit this menu (also used to set parameter from the menu) + +#ifndef DC // Save the config file. I'm sick of crashing the game later and losing all my changes! + COM_BufAddText(va("saveconfig \"%s\" -silent\n", configfile)); +#endif //Alam: But not on the Dreamcast's VMUs + + if (currentMenu == &MessageDef) // Oh sod off! + currentMenu = &MainDef; // Not like it matters + + if (gamestate == GS_MENU) // Back to title screen + D_StartTitle(); + + menuactive = false; +} + +void M_SelectableClearMenus(INT32 choice) +{ + (void)choice; + M_ClearMenus(true); +} + +// +// M_SetupNextMenu +// +void M_SetupNextMenu(menu_t *menudef, boolean notransition) +{ + INT16 i; + + if (!notransition) + { + if (currentMenu->transitionOutTics) + { + menutransition.tics = 0; + menutransition.dest = currentMenu->transitionOutTics; + menutransition.in = false; + menutransition.newmenu = menudef; + return; // Don't change menu yet, the transition will call this again + } + else if (gamestate == GS_MENU) + { + menuwipe = true; + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipe_menu_toblack], false, "FADEMAP0", false); + } + } + + if (currentMenu->quitroutine) + { + // If you're going from a menu to itself, why are you running the quitroutine? You're not quitting it! -SH + if (currentMenu != menudef && !currentMenu->quitroutine()) + return; // we can't quit this menu (also used to set parameter from the menu) + } + + currentMenu = menudef; + itemOn = currentMenu->lastOn; + + // in case of... + if (itemOn >= currentMenu->numitems) + itemOn = currentMenu->numitems - 1; + + // the curent item can be disabled, + // this code go up until an enabled item found + if ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE) + { + for (i = 0; i < currentMenu->numitems; i++) + { + if ((currentMenu->menuitems[i].status & IT_TYPE) != IT_SPACE) + { + itemOn = i; + break; + } + } + } +} + +void M_GoBack(INT32 choice) +{ + (void)choice; + + noFurtherInput = true; + currentMenu->lastOn = itemOn; + + if (currentMenu->prevMenu) + { + //If we entered the game search menu, but didn't enter a game, + //make sure the game doesn't still think we're in a netgame. + if (!Playing() && netgame && multiplayer) + { + MSCloseUDPSocket(); // Clean up so we can re-open the connection later. + netgame = false; + multiplayer = false; + } + + M_SetupNextMenu(currentMenu->prevMenu, false); + } + else + M_ClearMenus(true); +} + +// +// M_Ticker +// +void M_Ticker(void) +{ + if (menutransition.tics != 0 || menutransition.dest != 0) + { + noFurtherInput = true; + + if (menutransition.tics < menutransition.dest) + menutransition.tics++; + else if (menutransition.tics > menutransition.dest) + menutransition.tics--; + + // If dest is non-zero, we've started transition and want to switch menus + // If dest is zero, we're mid-transition and want to end it + if (menutransition.tics == menutransition.dest && menutransition.newmenu != NULL) + { + M_SetupNextMenu(menutransition.newmenu, true); + + if (menutransition.newmenu->transitionInTics) + { + menutransition.tics = currentMenu->transitionOutTics; + menutransition.dest = 0; + menutransition.in = true; + menutransition.newmenu = NULL; + } + else if (gamestate == GS_MENU) + { + memset(&menutransition, 0, sizeof(menutransition)); + + menuwipe = true; + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + F_WipeEndScreen(); + F_RunWipe(wipedefs[wipe_menu_toblack], false, "FADEMAP0", false); + } + } + } + else + { + // reset input trigger + noFurtherInput = false; + } + + if (dedicated) + return; + + if (--skullAnimCounter <= 0) + skullAnimCounter = 8; + +#if 0 + if (currentMenu == &PAUSE_PlaybackMenuDef) + { + if (playback_enterheld > 0) + playback_enterheld--; + } + else + playback_enterheld = 0; + + //added : 30-01-98 : test mode for five seconds + if (vidm_testingmode > 0) + { + // restore the previous video mode + if (--vidm_testingmode == 0) + setmodeneeded = vidm_previousmode + 1; + } +#endif +} + +// +// M_Init +// +void M_Init(void) +{ + //COM_AddCommand("manual", Command_Manual_f); + + CV_RegisterVar(&cv_nextmap); + CV_RegisterVar(&cv_newgametype); + CV_RegisterVar(&cv_chooseskin); + CV_RegisterVar(&cv_autorecord); + + if (dedicated) + return; + + // Menu hacks + CV_RegisterVar(&cv_dummymenuplayer); + CV_RegisterVar(&cv_dummyteam); + CV_RegisterVar(&cv_dummyspectate); + CV_RegisterVar(&cv_dummyscramble); + CV_RegisterVar(&cv_dummystaff); + +#if 0 +#ifdef HWRENDER + // Permanently hide some options based on render mode + if (rendermode == render_soft) + OP_VideoOptionsMenu[op_video_ogl].status = + OP_VideoOptionsMenu[op_video_kartman].status = + OP_VideoOptionsMenu[op_video_md2] .status = IT_DISABLED; +#endif +#endif + +#ifndef NONET + CV_RegisterVar(&cv_serversort); +#endif + + //todo put this somewhere better... + CV_RegisterVar(&cv_allcaps); +} + +// ================================================== +// MESSAGE BOX (aka: a hacked, cobbled together menu) +// ================================================== +// Because this is just a "fake" menu, these definitions are not with the others +static menuitem_t MessageMenu[] = +{ + // TO HACK + {0, NULL, NULL, NULL, NULL, 0, 0} +}; + +menu_t MessageDef = +{ + 1, // # of menu items + NULL, // previous menu (TO HACK) + 0, // lastOn, flags (TO HACK) + MessageMenu, // menuitem_t -> + 0, 0, // x, y (TO HACK) + 0, 0, // transition tics + M_DrawMessageMenu, // drawing routine -> + NULL +}; + +// +// M_StringHeight +// +// Find string height from hu_font chars +// +static inline size_t M_StringHeight(const char *string) +{ + size_t h = 8, i; + + for (i = 0; i < strlen(string); i++) + if (string[i] == '\n') + h += 8; + + return h; +} + +// default message handler +void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype) +{ + size_t max = 0, start = 0, i, strlines; + static char *message = NULL; + Z_Free(message); + message = Z_StrDup(string); + DEBFILE(message); + + // Rudementary word wrapping. + // Simple and effective. Does not handle nonuniform letter sizes, colors, etc. but who cares. + strlines = 0; + for (i = 0; message[i]; i++) + { + if (message[i] == ' ') + { + start = i; + max += 4; + } + else if (message[i] == '\n') + { + strlines = i; + start = 0; + max = 0; + continue; + } + else + max += 8; + + // Start trying to wrap if presumed length exceeds the screen width. + if (max >= BASEVIDWIDTH && start > 0) + { + message[start] = '\n'; + max -= (start-strlines)*8; + strlines = start; + start = 0; + } + } + + start = 0; + max = 0; + + M_StartControlPanel(); // can't put menuactive to true + + if (currentMenu == &MessageDef) // Prevent recursion + MessageDef.prevMenu = ((demo.playback) ? &PAUSE_PlaybackMenuDef : &MainDef); + else + MessageDef.prevMenu = currentMenu; + + MessageDef.menuitems[0].text = message; + MessageDef.menuitems[0].mvar1 = (UINT8)itemtype; + if (!routine && itemtype != MM_NOTHING) itemtype = MM_NOTHING; + switch (itemtype) + { + case MM_NOTHING: + MessageDef.menuitems[0].status = IT_MSGHANDLER; + MessageDef.menuitems[0].itemaction = M_StopMessage; + break; + case MM_YESNO: + MessageDef.menuitems[0].status = IT_MSGHANDLER; + MessageDef.menuitems[0].itemaction = routine; + break; + case MM_EVENTHANDLER: + MessageDef.menuitems[0].status = IT_MSGHANDLER; + MessageDef.menuitems[0].itemaction = routine; + break; + } + //added : 06-02-98: now draw a textbox around the message + // compute lenght max and the numbers of lines + for (strlines = 0; *(message+start); strlines++) + { + for (i = 0;i < strlen(message+start);i++) + { + if (*(message+start+i) == '\n') + { + if (i > max) + max = i; + start += i; + i = (size_t)-1; //added : 07-02-98 : damned! + start++; + break; + } + } + + if (i == strlen(message+start)) + start += i; + } + + MessageDef.x = (INT16)((BASEVIDWIDTH - 8*max-16)/2); + MessageDef.y = (INT16)((BASEVIDHEIGHT - M_StringHeight(message))/2); + + MessageDef.lastOn = (INT16)((strlines<<8)+max); + + //M_SetupNextMenu(); + currentMenu = &MessageDef; + itemOn = 0; +} + +void M_StopMessage(INT32 choice) +{ + (void)choice; + if (menuactive) + M_SetupNextMenu(MessageDef.prevMenu, true); +} + +// ========= +// IMAGEDEFS +// ========= + +// Handles the ImageDefs. Just a specialized function that +// uses left and right movement. +void M_HandleImageDef(INT32 choice) +{ + boolean exitmenu = false; + + switch (choice) + { + case KEY_RIGHTARROW: + if (itemOn >= (INT16)(currentMenu->numitems-1)) + break; + S_StartSound(NULL, sfx_s3k5b); + itemOn++; + break; + + case KEY_LEFTARROW: + if (!itemOn) + break; + + S_StartSound(NULL, sfx_s3k5b); + itemOn--; + break; + + case KEY_ESCAPE: + case KEY_ENTER: + exitmenu = true; + break; + } + + if (exitmenu) + { + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu, false); + else + M_ClearMenus(true); + } +} + +// ========= +// MAIN MENU +// ========= + +// Quit Game +static INT32 quitsounds[] = +{ + // holy shit we're changing things up! + // srb2kart: you ain't seen nothing yet + sfx_kc2e, + sfx_kc2f, + sfx_cdfm01, + sfx_ddash, + sfx_s3ka2, + sfx_s3k49, + sfx_slip, + sfx_tossed, + sfx_s3k7b, + sfx_itrolf, + sfx_itrole, + sfx_cdpcm9, + sfx_s3k4e, + sfx_s259, + sfx_3db06, + sfx_s3k3a, + sfx_peel, + sfx_cdfm28, + sfx_s3k96, + sfx_s3kc0s, + sfx_cdfm39, + sfx_hogbom, + sfx_kc5a, + sfx_kc46, + sfx_s3k92, + sfx_s3k42, + sfx_kpogos, + sfx_screec +}; + +void M_QuitResponse(INT32 ch) +{ + tic_t ptime; + INT32 mrand; + + if (ch != 'y' && ch != KEY_ENTER) + return; + + if (!(netgame || cv_debug)) + { + mrand = M_RandomKey(sizeof(quitsounds) / sizeof(INT32)); + if (quitsounds[mrand]) + S_StartSound(NULL, quitsounds[mrand]); + + //added : 12-02-98: do that instead of I_WaitVbl which does not work + ptime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds Tails 03-26-2001 + while (ptime > I_GetTime()) + { + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + V_DrawSmallScaledPatch(0, 0, 0, W_CachePatchName("GAMEQUIT", PU_CACHE)); // Demo 3 Quit Screen Tails 06-16-2001 + I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001 + I_Sleep(); + } + } + + I_Quit(); +} + +void M_QuitSRB2(INT32 choice) +{ + // We pick index 0 which is language sensitive, or one at random, + // between 1 and maximum number. + (void)choice; + M_StartMessage("Are you sure you want to quit playing?\n\n(Press 'Y' to exit)", M_QuitResponse, MM_YESNO); +} + +// ========= +// PLAY MENU +// ========= + +// Character Select! +struct setup_chargrid_s setup_chargrid[9][9]; +setup_player_t setup_player[MAXSPLITSCREENPLAYERS]; +UINT8 setup_numplayers = 0; +consvar_t *setup_playercvars[MAXSPLITSCREENPLAYERS][SPLITCV_MAX]; + +void M_CharacterSelectInit(INT32 choice) +{ + UINT8 i, j; + + (void)choice; + + memset(setup_chargrid, -1, sizeof(setup_chargrid)); + memset(setup_player, 0, sizeof(setup_player)); + + for (i = 0; i < 9; i++) + { + for (j = 0; j < 9; j++) + setup_chargrid[i][j].numskins = 0; + } + + // Keep these in a table for the sake of my sanity later + setup_playercvars[0][SPLITCV_SKIN] = &cv_skin; + setup_playercvars[1][SPLITCV_SKIN] = &cv_skin2; + setup_playercvars[2][SPLITCV_SKIN] = &cv_skin3; + setup_playercvars[3][SPLITCV_SKIN] = &cv_skin4; + + setup_playercvars[0][SPLITCV_COLOR] = &cv_playercolor; + setup_playercvars[1][SPLITCV_COLOR] = &cv_playercolor2; + setup_playercvars[2][SPLITCV_COLOR] = &cv_playercolor3; + setup_playercvars[3][SPLITCV_COLOR] = &cv_playercolor4; + + setup_playercvars[0][SPLITCV_NAME] = &cv_playername; + setup_playercvars[1][SPLITCV_NAME] = &cv_playername2; + setup_playercvars[2][SPLITCV_NAME] = &cv_playername3; + setup_playercvars[3][SPLITCV_NAME] = &cv_playername4; + + for (i = 0; i < numskins; i++) + { + UINT8 x = skins[i].kartspeed-1; + UINT8 y = skins[i].kartweight-1; + + if (setup_chargrid[x][y].numskins >= MAXCLONES) + CONS_Alert(CONS_ERROR, "Max character alts reached for %d,%d\n", x+1, y+1); + else + { + setup_chargrid[x][y].skinlist[setup_chargrid[x][y].numskins] = i; + setup_chargrid[x][y].numskins++; + } + + for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) + { + if (setup_playercvars[j][SPLITCV_SKIN]->value == i) + { + setup_player[j].gridx = x; + setup_player[j].gridy = y; + setup_player[j].color = skins[i].prefcolor; + } + } + } + + setup_player[0].mdepth = 1; + setup_numplayers = 1; + + M_SetupNextMenu(&PLAY_CharSelectDef, false); +} + +static void M_HandleCharacterGrid(INT32 choice, setup_player_t *p) +{ + switch (choice) + { + case KEY_DOWNARROW: + p->gridy++; + if (p->gridy > 8) + p->gridy = 0; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_UPARROW: + p->gridy--; + if (p->gridy < 0) + p->gridy = 8; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_RIGHTARROW: + p->gridx++; + if (p->gridx > 8) + p->gridx = 0; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_LEFTARROW: + p->gridx--; + if (p->gridx < 0) + p->gridx = 8; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_ENTER: + if (setup_chargrid[p->gridx][p->gridy].numskins == 0) + S_StartSound(NULL, sfx_s3k5b); + else + { + p->mdepth++; + if (setup_chargrid[p->gridx][p->gridy].numskins == 1) + p->mdepth++; // Skip clones menu + S_StartSound(NULL, sfx_s3k5b); + } + break; + case KEY_ESCAPE: + p->mdepth--; + S_StartSound(NULL, sfx_s3k5b); + break; + default: + break; + } +} + +static void M_HandleCharRotate(INT32 choice, setup_player_t *p) +{ + UINT8 numclones = setup_chargrid[p->gridx][p->gridy].numskins; + + switch (choice) + { + case KEY_RIGHTARROW: + p->clonenum++; + if (p->clonenum >= numclones) + p->clonenum = 0; + + //p->skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_LEFTARROW: + p->clonenum--; + if (p->clonenum < 0) + p->clonenum = numclones-1; + + //p->skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_ENTER: + p->mdepth++; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_ESCAPE: + p->mdepth--; + S_StartSound(NULL, sfx_s3k5b); + break; + default: + break; + } +} + +static void M_HandleColorRotate(INT32 choice, setup_player_t *p) +{ + switch (choice) + { + case KEY_RIGHTARROW: + p->color++; + if (p->color >= MAXSKINCOLORS) + p->color = 1; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_LEFTARROW: + p->color--; + if (p->color < 1) + p->color = MAXSKINCOLORS-1; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_ENTER: + p->mdepth++; + S_StartSound(NULL, sfx_s3k5b); + break; + case KEY_ESCAPE: + p->mdepth--; + if (setup_chargrid[p->gridx][p->gridy].numskins <= 1) + p->mdepth--; // Skip clones menu + S_StartSound(NULL, sfx_s3k5b); + break; + default: + break; + } +} + +void M_CharacterSelectHandler(INT32 choice) +{ + UINT8 i; + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + setup_player_t *p = &setup_player[i]; + + if (i > 0) + break; // temp + + switch (p->mdepth) + { + case 0: // Enter Game + if (choice == KEY_ENTER) + setup_player[i].mdepth++; + break; + case 1: // Character Select grid + M_HandleCharacterGrid(choice, p); + break; + case 2: // Select clone + M_HandleCharRotate(choice, p); + break; + case 3: // Select color + M_HandleColorRotate(choice, p); + break; + default: // Unready + if (choice == KEY_ESCAPE) + setup_player[i].mdepth--; + break; + } + + if (p->mdepth < 2) + p->clonenum = 0; + + // Just makes it easier to access later + p->skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]; + + if (p->mdepth < 3) + p->color = skins[p->skin].prefcolor; + + if (p->mdepth == 0) + break; + else + setup_numplayers = i+1; + } + + // If the first player unjoins, then we get outta here + if (setup_player[0].mdepth == 0) + { + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu, false); + else + M_ClearMenus(true); + } + else + { + boolean setupnext = false; + + for (i = 0; i < setup_numplayers; i++) + { + if (setup_player[i].mdepth >= 4) + setupnext = true; + else + { + // Someone's not ready yet. + setupnext = false; + break; + } + } + + if (setupnext) + { + for (i = 0; i < setup_numplayers; i++) + { + CV_StealthSetValue(setup_playercvars[i][SPLITCV_SKIN], setup_player[i].skin); + CV_StealthSetValue(setup_playercvars[i][SPLITCV_COLOR], setup_player[i].color); + } + + M_SetupNextMenu(&PLAY_MainDef, false); + } + } +} + +boolean M_CharacterSelectQuit(void) +{ + M_CharacterSelectInit(0); + return true; +} + +// ===================== +// PAUSE / IN-GAME MENUS +// ===================== +void M_EndModeAttackRun(void) +{ +#if 0 + M_ModeAttackEndGame(0); +#endif +} + +// Replay Playback Menu +void M_SetPlaybackMenuPointer(void) +{ + itemOn = playback_pause; +} + +void M_PlaybackRewind(INT32 choice) +{ + static tic_t lastconfirmtime; + + (void)choice; + + if (!demo.rewinding) + { + if (paused) + { + G_ConfirmRewind(leveltime-1); + paused = true; + S_PauseAudio(); + } + else + demo.rewinding = paused = true; + } + else if (lastconfirmtime + TICRATE/2 < I_GetTime()) + { + lastconfirmtime = I_GetTime(); + G_ConfirmRewind(leveltime); + } + + CV_SetValue(&cv_playbackspeed, 1); +} + +void M_PlaybackPause(INT32 choice) +{ + (void)choice; + + paused = !paused; + + if (demo.rewinding) + { + G_ConfirmRewind(leveltime); + paused = true; + S_PauseAudio(); + } + else if (paused) + S_PauseAudio(); + else + S_ResumeAudio(); + + CV_SetValue(&cv_playbackspeed, 1); +} + +void M_PlaybackFastForward(INT32 choice) +{ + (void)choice; + + if (demo.rewinding) + { + G_ConfirmRewind(leveltime); + paused = false; + S_ResumeAudio(); + } + CV_SetValue(&cv_playbackspeed, cv_playbackspeed.value == 1 ? 4 : 1); +} + +void M_PlaybackAdvance(INT32 choice) +{ + (void)choice; + + paused = false; + TryRunTics(1); + paused = true; +} + +void M_PlaybackSetViews(INT32 choice) +{ + if (choice > 0) + { + if (splitscreen < 3) + G_AdjustView(splitscreen + 2, 0, true); + } + else if (splitscreen) + { + splitscreen--; + R_ExecuteSetViewSize(); + } +} + +void M_PlaybackAdjustView(INT32 choice) +{ + G_AdjustView(itemOn - playback_viewcount, (choice > 0) ? 1 : -1, true); +} + +void M_PlaybackQuit(INT32 choice) +{ + (void)choice; + G_StopDemo(); + + if (demo.inreplayhut) + M_ReplayHut(choice); + else if (modeattacking) + M_EndModeAttackRun(); + else + D_StartTitle(); +} + + +void M_ReplayHut(INT32 choice) +{ + (void)choice; +} + +static void Splitplayers_OnChange(void) +{ +#if 0 + if (cv_splitplayers.value < setupm_pselect) + setupm_pselect = 1; +#endif +} diff --git a/src/m_cheat.c b/src/m_cheat.c index bba7cd65b..6bab3c7bd 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -22,7 +22,7 @@ #include "d_net.h" #include "m_cheat.h" -#include "m_menu.h" +#include "k_menu.h" #include "m_random.h" #include "m_misc.h" diff --git a/src/m_menu.c b/src/m_menu.c deleted file mode 100644 index 342bbf4d5..000000000 --- a/src/m_menu.c +++ /dev/null @@ -1,9684 +0,0 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2011-2016 by Matthew "Inuyasha" Walsh. -// Copyright (C) 1999-2018 by Sonic Team Junior. -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- -/// \file m_menu.c -/// \brief XMOD's extremely revamped menu system. - -#ifdef __GNUC__ -#include -#endif - -#include "m_menu.h" - -#include "doomdef.h" -#include "d_main.h" -#include "d_netcmd.h" -#include "console.h" -#include "r_local.h" -#include "hu_stuff.h" -#include "g_game.h" -#include "g_input.h" -#include "m_argv.h" - -// Data. -#include "sounds.h" -#include "s_sound.h" -#include "i_system.h" - -// Addfile -#include "filesrch.h" - -#include "v_video.h" -#include "i_video.h" -#include "keys.h" -#include "z_zone.h" -#include "w_wad.h" -#include "p_local.h" -#include "p_setup.h" -#include "f_finale.h" - -#ifdef HWRENDER -#include "hardware/hw_main.h" -#endif - -#include "d_net.h" -#include "mserv.h" -#include "m_misc.h" -#include "m_anigif.h" -#include "byteptr.h" -#include "st_stuff.h" -#include "i_sound.h" -#include "k_kart.h" // SRB2kart -#include "d_player.h" // KITEM_ constants - -#include "i_joy.h" // for joystick menu controls - -// Condition Sets -#include "m_cond.h" - -// And just some randomness for the exits. -#include "m_random.h" - -#if defined(HAVE_SDL) -#include "SDL.h" -#if SDL_VERSION_ATLEAST(2,0,0) -#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG -#endif -#endif - -#ifdef PC_DOS -#include // for snprintf -int snprintf(char *str, size_t n, const char *fmt, ...); -//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); -#endif - -#define SKULLXOFF -32 -#define LINEHEIGHT 16 -#define STRINGHEIGHT 8 -#define FONTBHEIGHT 20 -#define SMALLLINEHEIGHT 8 -#define SLIDER_RANGE 10 -#define SLIDER_WIDTH (8*SLIDER_RANGE+6) -#define SERVERS_PER_PAGE 11 - -typedef enum -{ - QUITMSG = 0, - QUITMSG1, - QUITMSG2, - QUITMSG3, - QUITMSG4, - QUITMSG5, - QUITMSG6, - QUITMSG7, - - QUIT2MSG, - QUIT2MSG1, - QUIT2MSG2, - QUIT2MSG3, - QUIT2MSG4, - QUIT2MSG5, - QUIT2MSG6, - - QUIT3MSG, - QUIT3MSG1, - QUIT3MSG2, - QUIT3MSG3, - QUIT3MSG4, - QUIT3MSG5, - QUIT3MSG6, - NUM_QUITMESSAGES -} text_enum; - -const char *quitmsg[NUM_QUITMESSAGES]; - -// Stuff for customizing the player select screen Tails 09-22-2003 -description_t description[MAXSKINS]; - -//static char *char_notes = NULL; -//static fixed_t char_scroll = 0; - -boolean menuactive = false; -boolean fromlevelselect = false; - -typedef enum -{ - LLM_CREATESERVER, - LLM_LEVELSELECT, - LLM_RECORDATTACK, - LLM_NIGHTSATTACK -} levellist_mode_t; - -levellist_mode_t levellistmode = LLM_CREATESERVER; -UINT8 maplistoption = 0; - -static char joystickInfo[8][29]; -#ifndef NONET -static UINT32 serverlistpage; -#endif - -//static saveinfo_t savegameinfo[MAXSAVEGAMES]; // Extra info about the save games. - -INT16 startmap; // Mario, NiGHTS, or just a plain old normal game? - -static INT16 itemOn = 1; // menu item skull is on, Hack by Tails 09-18-2002 -static INT16 skullAnimCounter = 10; // skull animation counter - -static boolean menuwipe = false; // finish wipes between screens - -static UINT8 setupcontrolplayer; -static INT32 (*setupcontrols)[2]; // pointer to the gamecontrols of the player being edited - -// shhh... what am I doing... nooooo! -static INT32 vidm_testingmode = 0; -static INT32 vidm_previousmode; -static INT32 vidm_selected = 0; -static INT32 vidm_nummodes; -static INT32 vidm_column_size; - -// -// PROTOTYPES -// - -static void M_StopMessage(INT32 choice); - -#ifndef NONET -static void M_HandleServerPage(INT32 choice); -static void M_RoomMenu(INT32 choice); -#endif - -// Prototyping is fun, innit? -// ========================================================================== -// NEEDED FUNCTION PROTOTYPES GO HERE -// ========================================================================== - -// the haxor message menu -menu_t MessageDef; - -menu_t SPauseDef; - -#define lsheadingheight 16 - -menu_t PY_MainDef; - -// Extra - -static void M_Statistics(INT32 choice); -static char *M_GetConditionString(condition_t cond); - -menu_t EX_MainDef, EX_UnlockChecklistDef; -menu_t EX_LevelStatsDef; - -// Misc. Main Menu -#if 0 // Bring this back when we have actual single-player -static void M_SinglePlayerMenu(INT32 choice); -#endif -static void M_Options(INT32 choice); -static void M_Manual(INT32 choice); -static void M_SelectableClearMenus(INT32 choice); -static void M_Retry(INT32 choice); -static void M_EndGame(INT32 choice); -static void M_MapChange(INT32 choice); -static void M_ChangeLevel(INT32 choice); -static void M_ConfirmSpectate(INT32 choice); -static void M_ConfirmEnterGame(INT32 choice); -static void M_ConfirmTeamScramble(INT32 choice); -static void M_ConfirmTeamChange(INT32 choice); -static void M_ConfirmSpectateChange(INT32 choice); -static void M_Credits(INT32 choice); -static void M_QuitSRB2(INT32 choice); -menu_t SP_MainDef, MP_MainDef, OP_MainDef; -menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef, MISC_ChangeSpectateDef; - -// Single Player -static void M_TimeAttack(INT32 choice); -static boolean M_QuitTimeAttackMenu(void); -static void M_HandleStaffReplay(INT32 choice); -static void M_ReplayTimeAttack(INT32 choice); -static void M_ChooseTimeAttack(INT32 choice); -static void M_ModeAttackRetry(INT32 choice); -static void M_ModeAttackEndGame(INT32 choice); -static void M_SetGuestReplay(INT32 choice); - -static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef; - -// Multiplayer -#ifndef NONET -static void M_StartServerMenu(INT32 choice); -static void M_ConnectMenu(INT32 choice); -static void M_ConnectMenuModChecks(INT32 choice); -static void M_Refresh(INT32 choice); -static void M_Connect(INT32 choice); -static void M_ChooseRoom(INT32 choice); -#endif -static void M_StartOfflineServerMenu(INT32 choice); -static void M_StartServer(INT32 choice); -static void M_SetupMultiPlayer(INT32 choice); -static void M_SetupMultiPlayer2(INT32 choice); -static void M_SetupMultiPlayer3(INT32 choice); -static void M_SetupMultiPlayer4(INT32 choice); -static void M_SetupMultiHandler(INT32 choice); - -// Options -// Split into multiple parts due to size -// Controls -menu_t OP_ControlsDef, OP_AllControlsDef; -menu_t OP_MouseOptionsDef, OP_Mouse2OptionsDef; -menu_t OP_Joystick1Def, OP_Joystick2Def, OP_Joystick3Def, OP_Joystick4Def; -static void M_VideoModeMenu(INT32 choice); -static void M_Setup1PControlsMenu(INT32 choice); -static void M_Setup2PControlsMenu(INT32 choice); -static void M_Setup3PControlsMenu(INT32 choice); -static void M_Setup4PControlsMenu(INT32 choice); - -static void M_Setup1PJoystickMenu(INT32 choice); -static void M_Setup2PJoystickMenu(INT32 choice); -static void M_Setup3PJoystickMenu(INT32 choice); -static void M_Setup4PJoystickMenu(INT32 choice); - -static void M_AssignJoystick(INT32 choice); -static void M_ChangeControl(INT32 choice); -static void M_ResetControls(INT32 choice); - -// Video & Sound -menu_t OP_VideoOptionsDef, OP_VideoModeDef; -#ifdef HWRENDER -menu_t OP_OpenGLOptionsDef, OP_OpenGLFogDef, OP_OpenGLColorDef; -#endif -menu_t OP_SoundOptionsDef; -//static void M_RestartAudio(void); - -//Misc -menu_t OP_DataOptionsDef, OP_ScreenshotOptionsDef, OP_EraseDataDef; -menu_t OP_HUDOptionsDef, OP_ChatOptionsDef; -menu_t OP_GameOptionsDef, OP_ServerOptionsDef; -#ifndef NONET -menu_t OP_AdvServerOptionsDef; -#endif -//menu_t OP_NetgameOptionsDef, OP_GametypeOptionsDef; -menu_t OP_MonitorToggleDef; -static void M_ScreenshotOptions(INT32 choice); -static void M_EraseData(INT32 choice); - -static void M_Addons(INT32 choice); -static void M_AddonsOptions(INT32 choice); -static patch_t *addonsp[NUM_EXT+5]; - -#define numaddonsshown 4 - -// Replay hut -menu_t EX_ReplayHutDef; -menu_t OP_ReplayOptionsDef; -static void M_HandleReplayHutList(INT32 choice); -static void M_DrawReplayHut(void); -static void M_DrawReplayStartMenu(void); -static boolean M_QuitReplayHut(void); -static void M_HutStartReplay(INT32 choice); - -static void M_DrawPlaybackMenu(void); -static void M_PlaybackRewind(INT32 choice); -static void M_PlaybackPause(INT32 choice); -static void M_PlaybackFastForward(INT32 choice); -static void M_PlaybackAdvance(INT32 choice); -static void M_PlaybackSetViews(INT32 choice); -static void M_PlaybackAdjustView(INT32 choice); -static void M_PlaybackQuit(INT32 choice); - -static UINT8 playback_enterheld = 0; // horrid hack to prevent holding the button from being extremely fucked - -// Drawing functions -static void M_DrawKartGamemodeMenu(void); -static void M_DrawGenericMenu(void); -static void M_DrawAddons(void); -static void M_DrawSoundOptions(void); -static void M_DrawChecklist(void); -static void M_DrawPauseMenu(void); -static void M_DrawLevelSelectOnly(boolean leftfade, boolean rightfade); -static void M_DrawServerMenu(void); -static void M_DrawImageDef(void); -static void M_DrawLevelStats(void); -static void M_DrawTimeAttackMenu(void); -static void M_DrawControl(void); -static void M_DrawVideoMenu(void); -static void M_DrawHUDOptions(void); -static void M_DrawVideoMode(void); -static void M_DrawMonitorToggles(void); -#ifdef HWRENDER -static void M_OGL_DrawFogMenu(void); -static void M_OGL_DrawColorMenu(void); -#endif -static void M_DrawMPMainMenu(void); -#ifndef NONET -static void M_DrawConnectMenu(void); -static void M_DrawRoomMenu(void); -#endif -static void M_DrawJoystick(void); -static void M_DrawSetupMultiPlayerMenu(void); - -// Handling functions -#ifndef NONET -static boolean M_CancelConnect(void); -#endif -static boolean M_QuitMultiPlayerMenu(void); -static void M_HandleAddons(INT32 choice); -static void M_HandleSoundTest(INT32 choice); -static void M_HandleImageDef(INT32 choice); -//static void M_HandleLoadSave(INT32 choice); -static void M_HandleLevelStats(INT32 choice); -#ifndef NONET -static void M_HandleConnectIP(INT32 choice); -#endif -static void M_HandleSetupMultiPlayer(INT32 choice); -#ifdef HWRENDER -static void M_HandleFogColor(INT32 choice); -#endif -static void M_HandleVideoMode(INT32 choice); -static void M_HandleMonitorToggles(INT32 choice); - -// Consvar onchange functions -static void Nextmap_OnChange(void); -static void Newgametype_OnChange(void); -static void Dummymenuplayer_OnChange(void); -//static void Dummymares_OnChange(void); -static void Dummystaff_OnChange(void); - -// ========================================================================== -// CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE. -// ========================================================================== - -consvar_t cv_showfocuslost = {"showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL }; - -static CV_PossibleValue_t map_cons_t[] = { - {0,"MIN"}, - {NUMMAPS, "MAX"}, - {0, NULL} -}; -consvar_t cv_nextmap = {"nextmap", "1", CV_HIDEN|CV_CALL, map_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL}; - -static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}}; -consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL}; - -// This gametype list is integral for many different reasons. -// When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! -CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; - -consvar_t cv_newgametype = {"newgametype", "Race", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL}; - -static CV_PossibleValue_t serversort_cons_t[] = { - {0,"Ping"}, - {1,"Modified State"}, - {2,"Most Players"}, - {3,"Least Players"}, - {4,"Max Player Slots"}, - {5,"Gametype"}, - {0,NULL} -}; -consvar_t cv_serversort = {"serversort", "Ping", CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL}; - -// autorecord demos for time attack -static consvar_t cv_autorecord = {"autorecord", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; - -CV_PossibleValue_t ghost_cons_t[] = {{0, "Hide"}, {1, "Show Character"}, {2, "Show All"}, {0, NULL}}; -CV_PossibleValue_t ghost2_cons_t[] = {{0, "Hide"}, {1, "Show"}, {0, NULL}}; - -consvar_t cv_ghost_besttime = {"ghost_besttime", "Show All", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ghost_bestlap = {"ghost_bestlap", "Show All", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ghost_last = {"ghost_last", "Show All", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ghost_guest = {"ghost_guest", "Show", CV_SAVE, ghost2_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ghost_staff = {"ghost_staff", "Show", CV_SAVE, ghost2_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; - -//Console variables used solely in the menu system. -//todo: add a way to use non-console variables in the menu -// or make these consvars legitimate like color or skin. -static void Splitplayers_OnChange(void); -CV_PossibleValue_t splitplayers_cons_t[] = {{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {0, NULL}}; -consvar_t cv_splitplayers = {"splitplayers", "One", CV_CALL, splitplayers_cons_t, Splitplayers_OnChange, 0, NULL, NULL, 0, 0, NULL}; - -static CV_PossibleValue_t dummymenuplayer_cons_t[] = {{0, "NOPE"}, {1, "P1"}, {2, "P2"}, {3, "P3"}, {4, "P4"}, {0, NULL}}; -static CV_PossibleValue_t dummyteam_cons_t[] = {{0, "Spectator"}, {1, "Red"}, {2, "Blue"}, {0, NULL}}; -static CV_PossibleValue_t dummyspectate_cons_t[] = {{0, "Spectator"}, {1, "Playing"}, {0, NULL}}; -static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"}, {0, NULL}}; -static CV_PossibleValue_t ringlimit_cons_t[] = {{0, "MIN"}, {9999, "MAX"}, {0, NULL}}; -static CV_PossibleValue_t liveslimit_cons_t[] = {{0, "MIN"}, {99, "MAX"}, {0, NULL}}; -/*static CV_PossibleValue_t dummymares_cons_t[] = { - {-1, "END"}, {0,"Overall"}, {1,"Mare 1"}, {2,"Mare 2"}, {3,"Mare 3"}, {4,"Mare 4"}, {5,"Mare 5"}, {6,"Mare 6"}, {7,"Mare 7"}, {8,"Mare 8"}, {0,NULL} -};*/ -static CV_PossibleValue_t dummystaff_cons_t[] = {{0, "MIN"}, {100, "MAX"}, {0, NULL}}; - -static consvar_t cv_dummymenuplayer = {"dummymenuplayer", "P1", CV_HIDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummyteam = {"dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummyspectate = {"dummyspectate", "Spectator", CV_HIDEN, dummyspectate_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummyscramble = {"dummyscramble", "Random", CV_HIDEN, dummyscramble_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummyrings = {"dummyrings", "0", CV_HIDEN, ringlimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummylives = {"dummylives", "0", CV_HIDEN, liveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummycontinues = {"dummycontinues", "0", CV_HIDEN, liveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -//static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummystaff = {"dummystaff", "0", CV_HIDEN|CV_CALL, dummystaff_cons_t, Dummystaff_OnChange, 0, NULL, NULL, 0, 0, NULL}; - -// ========================================================================== -// ORGANIZATION START. -// ========================================================================== -// Note: Never should we be jumping from one category of menu options to another -// without first going to the Main Menu. -// Note: Ignore the above if you're working with the Pause menu. -// Note: (Prefix)_MainMenu should be the target of all Main Menu options that -// point to submenus. - -// --------- -// Main Menu -// --------- -static menuitem_t MainMenu[] = -{ - {IT_SUBMENU|IT_STRING, NULL, "Play", &PY_MainDef, 48}, - {IT_SUBMENU|IT_STRING, NULL, "Extra", &EX_MainDef, 80}, - {IT_CALL|IT_STRING, NULL, "Options", M_Options, 112}, - {IT_CALL|IT_STRING, NULL, "Quit", M_QuitSRB2, 160}, -}; - -typedef enum -{ - play = 0, - extra, - options, - quitkart -} main_e; - -static menuitem_t PlayMenu[] = -{ - {IT_CALL|IT_STRING, NULL, "Local Play", M_TimeAttack, 64}, - {IT_SUBMENU|IT_STRING, NULL, "Online", &MP_MainDef, 96}, - - {IT_SUBMENU|IT_STRING, NULL, "Back", &MainDef, 160}, -}; - -// --------------------------------- -// Pause Menu Mode Attacking Edition -// --------------------------------- -static menuitem_t MAPauseMenu[] = -{ - {IT_CALL|IT_STRING, NULL, "Continue", M_SelectableClearMenus, 48}, - {IT_CALL|IT_STRING, NULL, "Retry", M_ModeAttackRetry, 56}, - {IT_CALL|IT_STRING, NULL, "Abort", M_ModeAttackEndGame, 64}, -}; - -typedef enum -{ - mapause_continue, - mapause_retry, - mapause_abort -} mapause_e; - -// --------------------- -// Pause Menu MP Edition -// --------------------- -static menuitem_t MPauseMenu[] = -{ - {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8}, - {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, - {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24}, - - {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus, 40}, - {IT_CALL | IT_STRING, NULL, "P1 Setup...", M_SetupMultiPlayer, 48}, // splitscreen - {IT_CALL | IT_STRING, NULL, "P2 Setup...", M_SetupMultiPlayer2, 56}, // splitscreen - {IT_CALL | IT_STRING, NULL, "P3 Setup...", M_SetupMultiPlayer3, 64}, // splitscreen - {IT_CALL | IT_STRING, NULL, "P4 Setup...", M_SetupMultiPlayer4, 72}, // splitscreen - - {IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48}, // alone - {IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48}, // alone - {IT_STRING | IT_CALL, NULL, "Cancel Join", M_ConfirmSpectate, 48}, // alone - {IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48}, - {IT_STRING | IT_SUBMENU, NULL, "Enter/Spectate...", &MISC_ChangeSpectateDef,48}, - {IT_CALL | IT_STRING, NULL, "Player Setup...", M_SetupMultiPlayer, 56}, // alone - {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64}, - - {IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80}, - {IT_CALL | IT_STRING, NULL, "Quit Game", M_QuitSRB2, 88}, -}; - -typedef enum -{ - mpause_addons = 0, - mpause_scramble, - mpause_switchmap, - - mpause_continue, - mpause_psetupsplit, - mpause_psetupsplit2, - mpause_psetupsplit3, - mpause_psetupsplit4, - - mpause_spectate, - mpause_entergame, - mpause_canceljoin, - mpause_switchteam, - mpause_switchspectate, - mpause_psetup, - mpause_options, - - mpause_title, - mpause_quit -} mpause_e; - -// --------------------- -// Pause Menu SP Edition -// --------------------- -static menuitem_t SPauseMenu[] = -{ - {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,48}, - {IT_CALL | IT_STRING, NULL, "Retry", M_Retry, 56}, - {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64}, - - {IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80}, - {IT_CALL | IT_STRING, NULL, "Quit Game", M_QuitSRB2, 88}, -}; - -typedef enum -{ - spause_continue, - spause_retry, - spause_options, - spause_title, - spause_quit -} spause_e; - -// Playback -static menuitem_t PlaybackMenu[] = -{ - {IT_CALL | IT_STRING, "M_PHIDE", "Hide Menu", M_SelectableClearMenus, 0}, - - {IT_CALL | IT_STRING, "M_PREW", "Rewind", M_PlaybackRewind, 20}, - {IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 36}, - {IT_CALL | IT_STRING, "M_PFFWD", "Fast-Forward", M_PlaybackFastForward, 52}, - {IT_CALL | IT_STRING, "M_PSTEPB", "Backup Frame", M_PlaybackRewind, 20}, - {IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36}, - {IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 52}, - - {IT_ARROWS | IT_STRING, "M_PVIEWS", "View Count", M_PlaybackSetViews, 72}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint", M_PlaybackAdjustView, 88}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 2", M_PlaybackAdjustView, 104}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 3", M_PlaybackAdjustView, 120}, - {IT_ARROWS | IT_STRING, "M_PNVIEW", "Viewpoint 4", M_PlaybackAdjustView, 136}, - - //{IT_CALL | IT_STRING, "M_POPTS", "More Options...", M_ReplayHut, 156}, - //{IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 172}, - {IT_CALL | IT_STRING, "M_PEXIT", "Stop Playback", M_PlaybackQuit, 156}, -}; - -typedef enum -{ - playback_hide, - playback_rewind, - playback_pause, - playback_fastforward, - playback_backframe, - playback_resume, - playback_advanceframe, - playback_viewcount, - playback_view1, - playback_view2, - playback_view3, - playback_view4, - //playback_moreoptions, - playback_quit -} playback_e; - -// PLAY - -// Single Player Time Attack -static menuitem_t SP_TimeAttackMenu[] = -{ - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Name", &cv_playername, 0}, - {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 13}, - {IT_STRING|IT_CVAR, NULL, "Color", &cv_playercolor, 26}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, - - {IT_DISABLED, NULL, "Guest...", &SP_GuestReplayDef, 98}, - {IT_DISABLED, NULL, "Replay...", &SP_ReplayDef, 108}, - {IT_WHITESTRING|IT_SUBMENU, NULL, "Ghosts...", &SP_GhostDef, 118}, - {IT_WHITESTRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Start", M_ChooseTimeAttack, 130}, -}; - -enum -{ - taname, - taplayer, - tacolor, - talevel, - - taguest, - tareplay, - taghost, - tastart -}; - -static menuitem_t SP_ReplayMenu[] = -{ - {IT_WHITESTRING|IT_CALL, NULL, "Replay Best Time", M_ReplayTimeAttack, 90}, - {IT_WHITESTRING|IT_CALL, NULL, "Replay Best Lap", M_ReplayTimeAttack, 98}, - - {IT_WHITESTRING|IT_CALL, NULL, "Replay Last", M_ReplayTimeAttack, 106}, - {IT_WHITESTRING|IT_CALL, NULL, "Replay Guest", M_ReplayTimeAttack, 114}, - {IT_WHITESTRING|IT_KEYHANDLER, NULL, "Replay Staff",M_HandleStaffReplay,122}, - - {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 130} -}; - - -static menuitem_t SP_GuestReplayMenu[] = -{ - {IT_WHITESTRING|IT_CALL, NULL, "Save Best Time as Guest", M_SetGuestReplay, 94}, - {IT_WHITESTRING|IT_CALL, NULL, "Save Best Lap as Guest", M_SetGuestReplay,102}, - {IT_WHITESTRING|IT_CALL, NULL, "Save Last as Guest", M_SetGuestReplay,110}, - - {IT_WHITESTRING|IT_CALL, NULL, "Delete Guest Replay", M_SetGuestReplay,120}, - - {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 130} -}; - - -static menuitem_t SP_GhostMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Best Time", &cv_ghost_besttime, 88}, - {IT_STRING|IT_CVAR, NULL, "Best Lap", &cv_ghost_bestlap, 96}, - {IT_STRING|IT_CVAR, NULL, "Last", &cv_ghost_last, 104}, - {IT_DISABLED, NULL, "Guest", &cv_ghost_guest, 112}, - {IT_DISABLED, NULL, "Staff Attack",&cv_ghost_staff, 120}, - - {IT_WHITESTRING|IT_SUBMENU, NULL, "Back", &SP_TimeAttackDef, 130} -}; - -// EXTRAS - -static menuitem_t EX_MainMenu[] = -{ - {IT_STRING|IT_SUBMENU, NULL, "Unlocks", &EX_UnlockChecklistDef, 32}, - {IT_STRING|IT_CALL|IT_CALL_NOTMODIFIED, NULL, "Stats", M_Statistics, 64}, - {IT_STRING|IT_CALL, NULL, "Addons", M_Addons, 96}, - {IT_STRING|IT_CALL, NULL, "Replays", M_ReplayHut, 128}, - {IT_STRING|IT_SUBMENU, NULL, "Back", &MainDef, 160}, -}; - -static menuitem_t EX_UnlockChecklistMenu[] = -{ - {IT_SUBMENU|IT_STRING, NULL, "Back", &EX_MainDef, 200}, -}; - -static menuitem_t EX_LevelStatsMenu[] = -{ - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelStats, '\0'}, // dummy menuitem for the control func -}; - -static menuitem_t EX_AddonsMenu[] = -{ - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleAddons, 0}, // dummy menuitem for the control func -}; - -static menuitem_t EX_ReplayHutMenu[] = -{ - {IT_KEYHANDLER|IT_NOTHING, NULL, "", M_HandleReplayHutList, 0}, // Dummy menuitem for the replay list - {IT_NOTHING, NULL, "", NULL, 0}, // Dummy for handling wrapping to the top of the menu.. -}; - -static menuitem_t EX_ReplayStartMenu[] = -{ - {IT_CALL |IT_STRING, NULL, "Load Addons and Watch", M_HutStartReplay, 0}, - {IT_CALL |IT_STRING, NULL, "Watch Without Addons", M_HutStartReplay, 10}, - {IT_CALL |IT_STRING, NULL, "Watch Replay", M_HutStartReplay, 10}, - {IT_SUBMENU |IT_STRING, NULL, "Back", &EX_ReplayHutDef, 30}, -}; - -// OPTIONS - -static menuitem_t OP_ReplayOptionsMenu[] = -{ - {IT_CVAR|IT_STRING, NULL, "Record Replays", &cv_recordmultiplayerdemos, 0}, - {IT_CVAR|IT_STRING, NULL, "Sync Check Interval", &cv_netdemosyncquality, 10}, -}; - -// ----------------- -// Misc menu options -// ----------------- -// Prefix: MISC_ -static menuitem_t MISC_ScrambleTeamMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Scramble Method", &cv_dummyscramble, 30}, - {IT_WHITESTRING|IT_CALL, NULL, "Confirm", M_ConfirmTeamScramble, 90}, -}; - -static menuitem_t MISC_ChangeTeamMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Player", &cv_dummymenuplayer, 30}, - {IT_STRING|IT_CVAR, NULL, "Team", &cv_dummyteam, 40}, - {IT_WHITESTRING|IT_CALL, NULL, "Confirm", M_ConfirmTeamChange, 90}, -}; - -static menuitem_t MISC_ChangeSpectateMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Player", &cv_dummymenuplayer, 30}, - {IT_STRING|IT_CVAR, NULL, "Status", &cv_dummyspectate, 40}, - {IT_WHITESTRING|IT_CALL, NULL, "Confirm", M_ConfirmSpectateChange, 90}, -}; - -static menuitem_t MISC_ChangeLevelMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, - {IT_WHITESTRING|IT_CALL, NULL, "Change Level", M_ChangeLevel, 130}, -}; - -static menuitem_t MISC_HelpMenu[] = -{ - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL00", M_HandleImageDef, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL01", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL02", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL03", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL04", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL05", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL06", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL07", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL08", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL09", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL10", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL11", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL12", M_HandleImageDef, 1}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "MANUAL99", M_HandleImageDef, 0}, -}; - -// -------------------------------- -// 1 Player and all of its submenus -// -------------------------------- -// Prefix: SP_ - - - -// A rare case. -// External files modify this menu, so we can't call it static. -// And I'm too lazy to go through and rename it everywhere. ARRGH! -#define M_ChoosePlayer NULL -menuitem_t PlayerMenu[MAXSKINS]; - -// ----------------------------------- -// Multiplayer and all of its submenus -// ----------------------------------- -// Prefix: MP_ - -static menuitem_t MP_MainMenu[] = -{ - {IT_HEADER, NULL, "Players", NULL, 0}, - {IT_STRING|IT_CVAR, NULL, "Number of local players", &cv_splitplayers, 10}, - - {IT_STRING|IT_KEYHANDLER,NULL, "Player setup...", M_SetupMultiHandler,18}, - - {IT_HEADER, NULL, "Host a game", NULL, 100-24}, -#ifndef NONET - {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 110-24}, -#else - {IT_GRAYEDOUT, NULL, "Internet/LAN...", NULL, 110-24}, -#endif - {IT_STRING|IT_CALL, NULL, "Offline...", M_StartOfflineServerMenu, 118-24}, - - {IT_HEADER, NULL, "Join a game", NULL, 132-24}, -#ifndef NONET - {IT_STRING|IT_CALL, NULL, "Internet server browser...",M_ConnectMenuModChecks, 142-24}, - {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 150-24}, -#else - {IT_GRAYEDOUT, NULL, "Internet server browser...",NULL, 142-24}, - {IT_GRAYEDOUT, NULL, "Specify IPv4 address:", NULL, 150-24}, -#endif - //{IT_HEADER, NULL, "Player setup", NULL, 80}, - //{IT_STRING|IT_CALL, NULL, "Name, character, color...", M_SetupMultiPlayer, 90}, -}; - -#ifndef NONET - -static menuitem_t MP_ServerMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 0}, - {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20}, - {IT_STRING|IT_CVAR|IT_CV_PASSWORD, NULL, "Password", &cv_dummyjoinpassword, 44}, - - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, - - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, -}; - -#endif - -// Separated offline and normal servers. -static menuitem_t MP_OfflineServerMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68}, - {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, - - {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, -}; - -static menuitem_t MP_PlayerSetupMenu[] = -{ - {IT_KEYHANDLER | IT_STRING, NULL, "Name", M_HandleSetupMultiPlayer, 0}, - {IT_KEYHANDLER | IT_STRING, NULL, "Character", M_HandleSetupMultiPlayer, 16}, // Tails 01-18-2001 - {IT_KEYHANDLER | IT_STRING, NULL, "Color", M_HandleSetupMultiPlayer, 152}, -}; - -#ifndef NONET -static menuitem_t MP_ConnectMenu[] = -{ - {IT_STRING | IT_CALL, NULL, "Room...", M_RoomMenu, 4}, - {IT_STRING | IT_CVAR, NULL, "Sort By", &cv_serversort, 12}, - {IT_STRING | IT_KEYHANDLER, NULL, "Page", M_HandleServerPage, 20}, - {IT_STRING | IT_CALL, NULL, "Refresh", M_Refresh, 28}, - - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 48-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 60-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 72-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 84-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 96-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 108-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 120-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 132-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 144-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 156-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 168-4}, -}; - -enum -{ - mp_connect_room, - mp_connect_sort, - mp_connect_page, - mp_connect_refresh, - FIRSTSERVERLINE -}; - -static menuitem_t MP_RoomMenu[] = -{ - {IT_STRING | IT_CALL, NULL, "", M_ChooseRoom, 9}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 18}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 27}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 36}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 45}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 54}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 63}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 72}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 81}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 90}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 99}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 108}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 117}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 126}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 135}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 144}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 153}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 162}, -}; -#endif - -// ------------------------------------ -// Options and most (?) of its submenus -// ------------------------------------ -// Prefix: OP_ -static menuitem_t OP_MainMenu[] = -{ - {IT_SUBMENU|IT_STRING, NULL, "Control Setup...", &OP_ControlsDef, 10}, - - {IT_SUBMENU|IT_STRING, NULL, "Video Options...", &OP_VideoOptionsDef, 30}, - {IT_SUBMENU|IT_STRING, NULL, "Sound Options...", &OP_SoundOptionsDef, 40}, - - {IT_SUBMENU|IT_STRING, NULL, "HUD Options...", &OP_HUDOptionsDef, 60}, - {IT_SUBMENU|IT_STRING, NULL, "Gameplay Options...", &OP_GameOptionsDef, 70}, - {IT_SUBMENU|IT_STRING, NULL, "Server Options...", &OP_ServerOptionsDef, 80}, - - {IT_SUBMENU|IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 100}, - - {IT_CALL|IT_STRING, NULL, "Tricks & Secrets (F1)", M_Manual, 120}, - {IT_CALL|IT_STRING, NULL, "Play Credits", M_Credits, 130}, -}; - -static menuitem_t OP_ControlsMenu[] = -{ - {IT_CALL | IT_STRING, NULL, "Player 1 Controls...", M_Setup1PControlsMenu, 10}, - {IT_CALL | IT_STRING, NULL, "Player 2 Controls...", M_Setup2PControlsMenu, 20}, - - {IT_CALL | IT_STRING, NULL, "Player 3 Controls...", &M_Setup3PControlsMenu, 30}, - {IT_CALL | IT_STRING, NULL, "Player 4 Controls...", &M_Setup4PControlsMenu, 40}, - - {IT_STRING | IT_CVAR, NULL, "Controls per key", &cv_controlperkey, 60}, -}; - -static menuitem_t OP_AllControlsMenu[] = -{ - {IT_SUBMENU|IT_STRING, NULL, "Gamepad Options...", &OP_Joystick1Def, 0}, - {IT_CALL|IT_STRING, NULL, "Reset to defaults", M_ResetControls, 8}, - //{IT_SPACE, NULL, NULL, NULL, 0}, - {IT_HEADER, NULL, "Gameplay Controls", NULL, 0}, - {IT_SPACE, NULL, NULL, NULL, 0}, - {IT_CONTROL, NULL, "Accelerate", M_ChangeControl, gc_accelerate }, - {IT_CONTROL, NULL, "Turn Left", M_ChangeControl, gc_turnleft }, - {IT_CONTROL, NULL, "Turn Right", M_ChangeControl, gc_turnright }, - {IT_CONTROL, NULL, "Drift", M_ChangeControl, gc_drift }, - {IT_CONTROL, NULL, "Brake", M_ChangeControl, gc_brake }, - {IT_CONTROL, NULL, "Use/Throw Item", M_ChangeControl, gc_fire }, - {IT_CONTROL, NULL, "Aim Forward", M_ChangeControl, gc_aimforward }, - {IT_CONTROL, NULL, "Aim Backward", M_ChangeControl, gc_aimbackward}, - {IT_CONTROL, NULL, "Look Backward", M_ChangeControl, gc_lookback }, - {IT_HEADER, NULL, "Miscelleanous Controls", NULL, 0}, - {IT_SPACE, NULL, NULL, NULL, 0}, - {IT_CONTROL, NULL, "Chat", M_ChangeControl, gc_talkkey }, - //{IT_CONTROL, NULL, "Team Chat", M_ChangeControl, gc_teamkey }, - {IT_CONTROL, NULL, "Show Rankings", M_ChangeControl, gc_scores }, - {IT_CONTROL, NULL, "Change Viewpoint", M_ChangeControl, gc_viewpoint }, - {IT_CONTROL, NULL, "Reset Camera", M_ChangeControl, gc_camreset }, - {IT_CONTROL, NULL, "Toggle First-Person", M_ChangeControl, gc_camtoggle }, - {IT_CONTROL, NULL, "Pause", M_ChangeControl, gc_pause }, - {IT_CONTROL, NULL, "Screenshot", M_ChangeControl, gc_screenshot }, - {IT_CONTROL, NULL, "Toggle GIF Recording", M_ChangeControl, gc_recordgif }, - {IT_CONTROL, NULL, "Open/Close Menu (ESC)", M_ChangeControl, gc_systemmenu }, - {IT_CONTROL, NULL, "Developer Console", M_ChangeControl, gc_console }, - {IT_HEADER, NULL, "Spectator Controls", NULL, 0}, - {IT_SPACE, NULL, NULL, NULL, 0}, - {IT_CONTROL, NULL, "Become Spectator", M_ChangeControl, gc_spectate }, - {IT_CONTROL, NULL, "Look Up", M_ChangeControl, gc_lookup }, - {IT_CONTROL, NULL, "Look Down", M_ChangeControl, gc_lookdown }, - {IT_CONTROL, NULL, "Center View", M_ChangeControl, gc_centerview }, - {IT_HEADER, NULL, "Custom Lua Actions", NULL, 0}, - {IT_SPACE, NULL, NULL, NULL, 0}, - {IT_CONTROL, NULL, "Custom Action 1", M_ChangeControl, gc_custom1 }, - {IT_CONTROL, NULL, "Custom Action 2", M_ChangeControl, gc_custom2 }, - {IT_CONTROL, NULL, "Custom Action 3", M_ChangeControl, gc_custom3 }, -}; - -static menuitem_t OP_Joystick1Menu[] = -{ - {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup1PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis , 30}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis , 40}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis , 50}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis , 60}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis , 70}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis , 80}, - {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis , 90}, -}; - -static menuitem_t OP_Joystick2Menu[] = -{ - {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup2PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis2 , 30}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis2 , 40}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis2 , 50}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis2 , 60}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis2 , 70}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis2 , 80}, - {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis2 , 90}, -}; - -static menuitem_t OP_Joystick3Menu[] = -{ - {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup3PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis3 , 30}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis3 , 40}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis3 , 50}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis3 , 60}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis3 , 70}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis3 , 80}, - {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis3 , 90}, -}; - -static menuitem_t OP_Joystick4Menu[] = -{ - {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup4PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis4 , 30}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis4 , 40}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis4 , 50}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis4 , 60}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis4 , 70}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis4 , 80}, - {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis4 , 90}, -}; - -static menuitem_t OP_JoystickSetMenu[] = -{ - {IT_CALL | IT_NOTHING, "None", NULL, M_AssignJoystick, LINEHEIGHT+5}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*2)+5}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*3)+5}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*4)+5}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*5)+5}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*6)+5}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*7)+5}, - {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*8)+5}, -}; - -/*static menuitem_t OP_MouseOptionsMenu[] = -{ - {IT_STRING | IT_CVAR, NULL, "Use Mouse", &cv_usemouse, 10}, - - - {IT_STRING | IT_CVAR, NULL, "First-Person MouseLook", &cv_alwaysfreelook, 30}, - {IT_STRING | IT_CVAR, NULL, "Third-Person MouseLook", &cv_chasefreelook, 40}, - {IT_STRING | IT_CVAR, NULL, "Mouse Move", &cv_mousemove, 50}, - {IT_STRING | IT_CVAR, NULL, "Invert Mouse", &cv_invertmouse, 60}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Mouse X Speed", &cv_mousesens, 70}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Mouse Y Speed", &cv_mouseysens, 80}, -}; - -static menuitem_t OP_Mouse2OptionsMenu[] = -{ - {IT_STRING | IT_CVAR, NULL, "Use Mouse 2", &cv_usemouse2, 10}, - {IT_STRING | IT_CVAR, NULL, "Second Mouse Serial Port", - &cv_mouse2port, 20}, - {IT_STRING | IT_CVAR, NULL, "First-Person MouseLook", &cv_alwaysfreelook2, 30}, - {IT_STRING | IT_CVAR, NULL, "Third-Person MouseLook", &cv_chasefreelook2, 40}, - {IT_STRING | IT_CVAR, NULL, "Mouse Move", &cv_mousemove2, 50}, - {IT_STRING | IT_CVAR, NULL, "Invert Mouse", &cv_invertmouse2, 60}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Mouse X Speed", &cv_mousesens2, 70}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Mouse Y Speed", &cv_mouseysens2, 80}, -};*/ - -static menuitem_t OP_VideoOptionsMenu[] = -{ - {IT_STRING | IT_CALL, NULL, "Set Resolution...", M_VideoModeMenu, 10}, -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 20}, -#endif - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Gamma", &cv_usegamma, 30}, - - {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 45}, - //{IT_STRING | IT_CVAR, NULL, "NiGHTS Draw Dist", &cv_drawdist_nights, 55}, - {IT_STRING | IT_CVAR, NULL, "Weather Draw Distance",&cv_drawdist_precip, 55}, - //{IT_STRING | IT_CVAR, NULL, "Weather Density", &cv_precipdensity, 65}, - {IT_STRING | IT_CVAR, NULL, "Skyboxes", &cv_skybox, 65}, - {IT_STRING | IT_CVAR, NULL, "Field of View", &cv_fov, 75}, - - {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 90}, - {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 100}, - -#ifdef HWRENDER - {IT_STRING | IT_CVAR, NULL, "3D models", &cv_grmdls, 115}, - {IT_STRING | IT_CVAR, NULL, "Fallback Player 3D Model", &cv_grfallbackplayermodel, 125}, - {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 135}, -#endif -}; - -enum -{ - op_video_res = 0, -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - op_video_fullscreen, -#endif - op_video_gamma, - op_video_dd, - op_video_wdd, - //op_video_wd, - op_video_skybox, - op_video_fov, - op_video_fps, - op_video_vsync, -#ifdef HWRENDER - op_video_md2, - op_video_kartman, - op_video_ogl, -#endif -}; - -static menuitem_t OP_VideoModeMenu[] = -{ - {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleVideoMode, '\0'}, // dummy menuitem for the control func -}; - -#ifdef HWRENDER -static menuitem_t OP_OpenGLOptionsMenu[] = -{ - {IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 10}, - {IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 20}, - - {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 35}, - {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 45}, - {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 55}, -/*#ifdef _WINDOWS - {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 50}, -#endif -#ifdef ALAM_LIGHTING - {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 70}, -#endif*/ -}; - -#ifdef ALAM_LIGHTING -static menuitem_t OP_OpenGLLightingMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Coronas", &cv_grcoronas, 0}, - {IT_STRING|IT_CVAR, NULL, "Coronas size", &cv_grcoronasize, 10}, - {IT_STRING|IT_CVAR, NULL, "Dynamic lighting", &cv_grdynamiclighting, 20}, - {IT_STRING|IT_CVAR, NULL, "Static lighting", &cv_grstaticlighting, 30}, -}; -#endif - -static menuitem_t OP_OpenGLFogMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Fog", &cv_grfog, 10}, - {IT_STRING|IT_KEYHANDLER, NULL, "Fog Color", M_HandleFogColor, 20}, - {IT_STRING|IT_CVAR, NULL, "Fog Density", &cv_grfogdensity, 30}, - {IT_STRING|IT_CVAR, NULL, "Software Fog",&cv_grsoftwarefog,40}, -}; - -static menuitem_t OP_OpenGLColorMenu[] = -{ - {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Red", &cv_grgammared, 10}, - {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Green", &cv_grgammagreen, 20}, - {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Blue", &cv_grgammablue, 30}, -}; -#endif - -static menuitem_t OP_SoundOptionsMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "SFX", &cv_gamesounds, 10}, - {IT_STRING|IT_CVAR|IT_CV_SLIDER, - NULL, "SFX Volume", &cv_soundvolume, 18}, - - {IT_STRING|IT_CVAR, NULL, "Music", &cv_gamedigimusic, 30}, - {IT_STRING|IT_CVAR|IT_CV_SLIDER, - NULL, "Music Volume", &cv_digmusicvolume, 38}, - -/* -- :nonnathisshit: - {IT_STRING|IT_CVAR, NULL, "MIDI", &cv_gamemidimusic, 50}, - {IT_STRING|IT_CVAR|IT_CV_SLIDER, - NULL, "MIDI Volume", &cv_midimusicvolume, 58}, -#ifdef PC_DOS - {IT_STRING|IT_CVAR|IT_CV_SLIDER, - NULL, "CD Volume", &cd_volume, 40}, -#endif*/ - - //{IT_STRING|IT_CALL, NULL, "Restart Audio System", M_RestartAudio, 50}, - - {IT_STRING|IT_CVAR, NULL, "Reverse L/R Channels", &stereoreverse, 50}, - {IT_STRING|IT_CVAR, NULL, "Surround Sound", &surround, 60}, - - {IT_STRING|IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 75}, - {IT_STRING|IT_CVAR, NULL, "Character voices", &cv_kartvoices, 85}, - {IT_STRING|IT_CVAR, NULL, "Powerup Warning", &cv_kartinvinsfx, 95}, - - {IT_KEYHANDLER|IT_STRING, NULL, "Sound Test", M_HandleSoundTest, 110}, - - {IT_STRING|IT_CVAR, NULL, "Play Music While Unfocused", &cv_playmusicifunfocused, 125}, - {IT_STRING|IT_CVAR, NULL, "Play SFX While Unfocused", &cv_playsoundifunfocused, 135}, -}; - -static menuitem_t OP_DataOptionsMenu[] = -{ - {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 10}, - {IT_STRING | IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 20}, - {IT_STRING | IT_SUBMENU, NULL, "Replay Options...", &OP_ReplayOptionsDef, 30}, - - {IT_STRING | IT_SUBMENU, NULL, "Erase Data...", &OP_EraseDataDef, 50}, -}; - -static menuitem_t OP_ScreenshotOptionsMenu[] = -{ - {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_screenshot_option, 10}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_screenshot_folder, 20}, - - {IT_HEADER, NULL, "Screenshots (F8)", NULL, 50}, - {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memory, 60}, - {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_level, 70}, - {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategy, 80}, - {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 90}, - - {IT_HEADER, NULL, "Movie Mode (F9)", NULL, 105}, - {IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 115}, - - {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 125}, - {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 135}, - - {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 125}, - {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 135}, - {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 145}, - {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 155}, -}; - -enum -{ - op_screenshot_folder = 1, - op_screenshot_capture = 8, - op_screenshot_gif_start = 9, - op_screenshot_gif_end = 10, - op_screenshot_apng_start = 11, - op_screenshot_apng_end = 14, -}; - -static menuitem_t OP_EraseDataMenu[] = -{ - {IT_STRING | IT_CALL, NULL, "Erase Record Data", M_EraseData, 10}, - {IT_STRING | IT_CALL, NULL, "Erase Unlockable Data", M_EraseData, 20}, - - {IT_STRING | IT_CALL, NULL, "\x85" "Erase ALL Data", M_EraseData, 40}, -}; - -static menuitem_t OP_AddonsOptionsMenu[] = -{ - {IT_HEADER, NULL, "Menu", NULL, 0}, - {IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 10}, - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 20}, - {IT_STRING|IT_CVAR, NULL, "Identify add-ons via", &cv_addons_md5, 48}, - {IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 58}, - - {IT_HEADER, NULL, "Search", NULL, 76}, - {IT_STRING|IT_CVAR, NULL, "Matching", &cv_addons_search_type, 86}, - {IT_STRING|IT_CVAR, NULL, "Case-sensitive", &cv_addons_search_case, 96}, -}; - -enum -{ - op_addons_folder = 2, -}; - -static menuitem_t OP_HUDOptionsMenu[] = -{ - {IT_STRING | IT_CVAR, NULL, "Show HUD (F3)", &cv_showhud, 10}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "HUD Visibility", &cv_translucenthud, 20}, - - {IT_STRING | IT_SUBMENU, NULL, "Online HUD options...",&OP_ChatOptionsDef, 35}, - {IT_STRING | IT_CVAR, NULL, "Background Glass", &cons_backcolor, 45}, - - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Minimap Visibility", &cv_kartminimap, 60}, - {IT_STRING | IT_CVAR, NULL, "Speedometer Display", &cv_kartspeedometer, 70}, - {IT_STRING | IT_CVAR, NULL, "Show \"CHECK\"", &cv_kartcheck, 80}, - - {IT_STRING | IT_CVAR, NULL, "Menu Highlights", &cons_menuhighlight, 95}, - // highlight info - (GOOD HIGHLIGHT, WARNING HIGHLIGHT) - 105 (see M_DrawHUDOptions) - - {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize, 120}, - - {IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 135}, -}; - -// Ok it's still called chatoptions but we'll put ping display in here to be clean -static menuitem_t OP_ChatOptionsMenu[] = -{ - // will ANYONE who doesn't know how to use the console want to touch this one? - {IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 10}, // nonetheless... - - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Chat Box Width", &cv_chatwidth, 25}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Chat Box Height", &cv_chatheight, 35}, - - {IT_STRING | IT_CVAR, NULL, "Chat Background Tint", &cv_chatbacktint, 50}, - {IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 60}, - {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 70}, - - {IT_STRING | IT_CVAR, NULL, "Local ping display", &cv_showping, 90}, // shows ping next to framerate if we want to. -}; - -static menuitem_t OP_GameOptionsMenu[] = -{ - {IT_STRING | IT_SUBMENU, NULL, "Random Item Toggles...", &OP_MonitorToggleDef, 10}, - - {IT_STRING | IT_CVAR, NULL, "Game Speed", &cv_kartspeed, 30}, - {IT_STRING | IT_CVAR, NULL, "Frantic Items", &cv_kartfrantic, 40}, - {IT_SECRET, NULL, "Encore Mode", &cv_kartencore, 50}, - - {IT_STRING | IT_CVAR, NULL, "Number of Laps", &cv_basenumlaps, 70}, - {IT_STRING | IT_CVAR, NULL, "Exit Countdown Timer", &cv_countdowntime, 80}, - - {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 100}, - {IT_STRING | IT_CVAR, NULL, "Starting Bumpers", &cv_kartbumpers, 110}, - {IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 120}, - - {IT_STRING | IT_CVAR, NULL, "Force Character", &cv_forceskin, 140}, - {IT_STRING | IT_CVAR, NULL, "Restrict Character Changes", &cv_restrictskinchange, 150}, -}; - -static menuitem_t OP_ServerOptionsMenu[] = -{ -#ifndef NONET - {IT_STRING | IT_CVAR | IT_CV_STRING, - NULL, "Server Name", &cv_servername, 10}, -#endif - - {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 40}, - {IT_STRING | IT_CVAR, NULL, "Map Progression", &cv_advancemap, 50}, - {IT_STRING | IT_CVAR, NULL, "Voting Timer", &cv_votetime, 60}, - {IT_STRING | IT_CVAR, NULL, "Voting Rule Changes", &cv_kartvoterulechanges, 70}, - -#ifndef NONET - {IT_STRING | IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 90}, - {IT_STRING | IT_CVAR, NULL, "Allow Players to Join", &cv_allownewplayer, 100}, - {IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 110}, - {IT_STRING | IT_CVAR, NULL, "Pause Permission", &cv_pause, 120}, - {IT_STRING | IT_CVAR, NULL, "Mute All Chat", &cv_mute, 130}, - - {IT_SUBMENU|IT_STRING, NULL, "Advanced Options...", &OP_AdvServerOptionsDef,150}, -#endif -}; - -#ifndef NONET -static menuitem_t OP_AdvServerOptionsMenu[] = -{ - {IT_STRING | IT_CVAR | IT_CV_STRING, - NULL, "Server Browser Address", &cv_masterserver, 10}, - - {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 40}, - {IT_STRING | IT_CVAR, NULL, "Ping limit (ms)", &cv_maxping, 50}, - {IT_STRING | IT_CVAR, NULL, "Ping timeout (s)", &cv_pingtimeout, 60}, - {IT_STRING | IT_CVAR, NULL, "Connection timeout (tics)", &cv_nettimeout, 70}, - {IT_STRING | IT_CVAR, NULL, "Join timeout (tics)", &cv_jointimeout, 80}, - - {IT_STRING | IT_CVAR, NULL, "Max. file transfer send (KB)", &cv_maxsend, 100}, - {IT_STRING | IT_CVAR, NULL, "File transfer packet rate", &cv_downloadspeed, 110}, - - {IT_STRING | IT_CVAR, NULL, "Log join addresses", &cv_showjoinaddress, 130}, - {IT_STRING | IT_CVAR, NULL, "Log resyncs", &cv_blamecfail, 140}, - {IT_STRING | IT_CVAR, NULL, "Log file transfers", &cv_noticedownload, 150}, -}; -#endif - -/*static menuitem_t OP_NetgameOptionsMenu[] = -{ - {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 10}, - {IT_STRING | IT_CVAR, NULL, "Point Limit", &cv_pointlimit, 18}, - - {IT_STRING | IT_CVAR, NULL, "Frantic Items", &cv_kartfrantic, 34}, - - {IT_STRING | IT_CVAR, NULL, "Item Respawn", &cv_itemrespawn, 50}, - {IT_STRING | IT_CVAR, NULL, "Item Respawn Delay", &cv_itemrespawntime, 58}, - - {IT_STRING | IT_CVAR, NULL, "Player Respawn Delay", &cv_respawntime, 74}, - - {IT_STRING | IT_CVAR, NULL, "Force Skin #", &cv_forceskin, 90}, - {IT_STRING | IT_CVAR, NULL, "Restrict Skin Changes", &cv_restrictskinchange, 98}, - - //{IT_STRING | IT_CVAR, NULL, "Autobalance Teams", &cv_autobalance, 114}, - //{IT_STRING | IT_CVAR, NULL, "Scramble Teams on Map Change", &cv_scrambleonchange, 122}, -};*/ - -/*static menuitem_t OP_GametypeOptionsMenu[] = -{ - {IT_HEADER, NULL, "RACE", NULL, 2}, - {IT_STRING | IT_CVAR, NULL, "Game Speed", &cv_kartspeed, 10}, - {IT_STRING | IT_CVAR, NULL, "Encore Mode", &cv_kartencore, 18}, - {IT_STRING | IT_CVAR, NULL, "Number of Laps", &cv_numlaps, 26}, - {IT_STRING | IT_CVAR, NULL, "Use Map Lap Counts", &cv_usemapnumlaps, 34}, - - {IT_HEADER, NULL, "BATTLE", NULL, 50}, - {IT_STRING | IT_CVAR, NULL, "Starting Bumpers", &cv_kartbumpers, 58}, - {IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 66}, -};*/ - -//#define ITEMTOGGLEBOTTOMRIGHT - -static menuitem_t OP_MonitorToggleMenu[] = -{ - // Mostly handled by the drawing function. - // Instead of using this for dumb monitors, lets use the new item bools we have :V - {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers", M_HandleMonitorToggles, KITEM_SNEAKER}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Sneakers x3", M_HandleMonitorToggles, KRITEM_TRIPLESNEAKER}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Rocket Sneakers", M_HandleMonitorToggles, KITEM_ROCKETSNEAKER}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Toggle All", M_HandleMonitorToggles, 0}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas", M_HandleMonitorToggles, KITEM_BANANA}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x3", M_HandleMonitorToggles, KRITEM_TRIPLEBANANA}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Bananas x10", M_HandleMonitorToggles, KRITEM_TENFOLDBANANA}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Eggman Monitors", M_HandleMonitorToggles, KITEM_EGGMAN}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts", M_HandleMonitorToggles, KITEM_ORBINAUT}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts x3", M_HandleMonitorToggles, KRITEM_TRIPLEORBINAUT}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Orbinauts x4", M_HandleMonitorToggles, KRITEM_QUADORBINAUT}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Mines", M_HandleMonitorToggles, KITEM_MINE}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz", M_HandleMonitorToggles, KITEM_JAWZ}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Jawz x2", M_HandleMonitorToggles, KRITEM_DUALJAWZ}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Ballhogs", M_HandleMonitorToggles, KITEM_BALLHOG}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Self-Propelled Bombs", M_HandleMonitorToggles, KITEM_SPB}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Invinciblity", M_HandleMonitorToggles, KITEM_INVINCIBILITY}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Grow", M_HandleMonitorToggles, KITEM_GROW}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Shrink", M_HandleMonitorToggles, KITEM_SHRINK}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Thunder Shields", M_HandleMonitorToggles, KITEM_THUNDERSHIELD}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Hyudoros", M_HandleMonitorToggles, KITEM_HYUDORO}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Pogo Springs", M_HandleMonitorToggles, KITEM_POGOSPRING}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Super Rings", M_HandleMonitorToggles, KITEM_SUPERRING}, - {IT_KEYHANDLER | IT_NOTHING, NULL, "Kitchen Sinks", M_HandleMonitorToggles, KITEM_KITCHENSINK}, -#ifdef ITEMTOGGLEBOTTOMRIGHT - {IT_KEYHANDLER | IT_NOTHING, NULL, "---", M_HandleMonitorToggles, 255}, -#endif -}; - -// ========================================================================== -// ALL MENU DEFINITIONS GO HERE -// ========================================================================== - -// Main Menu and related -menu_t MainDef = KARTGAMEMODEMENU(NULL, MainMenu, NULL); -menu_t PY_MainDef = KARTGAMEMODEMENU(NULL, PlayMenu, &MainDef); - -menu_t PlaybackMenuDef = { - NULL, - sizeof (PlaybackMenu)/sizeof (menuitem_t), - NULL, - PlaybackMenu, - M_DrawPlaybackMenu, - //BASEVIDWIDTH/2 - 94, 2, - BASEVIDWIDTH/2 - 88, 2, - 0, - NULL -}; - -menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); -menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72); -menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); - -// MISC menus - -menu_t MISC_ScrambleTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ScrambleTeamMenu, &MPauseDef, 27, 40); -menu_t MISC_ChangeTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ChangeTeamMenu, &MPauseDef, 27, 40); -menu_t MISC_ChangeSpectateDef = DEFAULTMENUSTYLE(NULL, MISC_ChangeSpectateMenu, &MPauseDef, 27, 40); -menu_t MISC_ChangeLevelDef = MAPICONMENUSTYLE(NULL, MISC_ChangeLevelMenu, &MPauseDef); -menu_t MISC_HelpDef = IMAGEDEF(MISC_HelpMenu); - -// PLAY MENU - -menu_t MP_MainDef = -{ - "M_MULTI", - sizeof (MP_MainMenu)/sizeof (menuitem_t), - &MainDef, - MP_MainMenu, - M_DrawMPMainMenu, - 42, 30, - 0, -#ifndef NONET - M_CancelConnect -#else - NULL -#endif -}; - -menu_t MP_OfflineServerDef = MAPICONMENUSTYLE("M_MULTI", MP_OfflineServerMenu, &MP_MainDef); - -#ifndef NONET -menu_t MP_ServerDef = MAPICONMENUSTYLE("M_MULTI", MP_ServerMenu, &MP_MainDef); - -menu_t MP_ConnectDef = -{ - "M_MULTI", - sizeof (MP_ConnectMenu)/sizeof (menuitem_t), - &MP_MainDef, - MP_ConnectMenu, - M_DrawConnectMenu, - 27,24, - 0, - M_CancelConnect -}; -menu_t MP_RoomDef = -{ - "M_MULTI", - sizeof (MP_RoomMenu)/sizeof (menuitem_t), - &MP_ConnectDef, - MP_RoomMenu, - M_DrawRoomMenu, - 27, 32, - 0, - NULL -}; -#endif -menu_t MP_PlayerSetupDef = -{ - NULL, //"M_SPLAYR" - sizeof (MP_PlayerSetupMenu)/sizeof (menuitem_t), - &MP_MainDef, - MP_PlayerSetupMenu, - M_DrawSetupMultiPlayerMenu, - 36, 14, - 0, - M_QuitMultiPlayerMenu -}; - - -// TIME ATTACK - -static menu_t SP_TimeAttackDef = -{ - "M_ATTACK", - sizeof (SP_TimeAttackMenu)/sizeof (menuitem_t), - &PY_MainDef, - SP_TimeAttackMenu, - M_DrawTimeAttackMenu, - 34, 40, - 0, - M_QuitTimeAttackMenu -}; - -static menu_t SP_ReplayDef = -{ - NULL, - sizeof(SP_ReplayMenu)/sizeof(menuitem_t), - &EX_MainDef, - SP_ReplayMenu, - M_DrawTimeAttackMenu, - 34, 40, - 0, - NULL -}; - -static menu_t SP_GuestReplayDef = -{ - "M_ATTACK", - sizeof(SP_GuestReplayMenu)/sizeof(menuitem_t), - &SP_TimeAttackDef, - SP_GuestReplayMenu, - M_DrawTimeAttackMenu, - 34, 40, - 0, - NULL -}; - -static menu_t SP_GhostDef = -{ - "M_ATTACK", - sizeof(SP_GhostMenu)/sizeof(menuitem_t), - &SP_TimeAttackDef, - SP_GhostMenu, - M_DrawTimeAttackMenu, - 34, 40, - 0, - NULL -}; - -// EXTRAS MENU -menu_t EX_MainDef = KARTGAMEMODEMENU(NULL, EX_MainMenu, &MainDef); - -menu_t EX_UnlockChecklistDef = -{ - NULL, - 1, - &EX_MainDef, - EX_UnlockChecklistMenu, - M_DrawChecklist, - 280, 185, - 0, - NULL -}; - -menu_t EX_LevelStatsDef = -{ - NULL, - 1, - &EX_MainDef, - EX_LevelStatsMenu, - M_DrawLevelStats, - 280, 185, - 0, - NULL -}; - -menu_t EX_AddonsDef = -{ - NULL, - sizeof (EX_AddonsMenu)/sizeof (menuitem_t), - &EX_MainDef, - EX_AddonsMenu, - M_DrawAddons, - 50, 28, - 0, - NULL -}; - -menu_t EX_ReplayHutDef = -{ - NULL, - sizeof (EX_ReplayHutMenu)/sizeof (menuitem_t), - &EX_MainDef, - EX_ReplayHutMenu, - M_DrawReplayHut, - 30, 80, - 0, - M_QuitReplayHut -}; - -menu_t EX_ReplayStartDef = -{ - NULL, - sizeof (EX_ReplayStartMenu)/sizeof (menuitem_t), - &EX_ReplayHutDef, - EX_ReplayStartMenu, - M_DrawReplayStartMenu, - 30, 90, - 0, - NULL -}; - -// Options -menu_t OP_MainDef = -{ - "M_OPTTTL", - sizeof (OP_MainMenu)/sizeof (menuitem_t), - &MainDef, - OP_MainMenu, - M_DrawGenericMenu, - 60, 30, - 0, - NULL -}; - -menu_t OP_ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_ControlsMenu, &OP_MainDef, 60, 30); -menu_t OP_AllControlsDef = CONTROLMENUSTYLE(OP_AllControlsMenu, &OP_ControlsDef); -menu_t OP_Joystick1Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick1Menu, &OP_AllControlsDef, 60, 30); -menu_t OP_Joystick2Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick2Menu, &OP_AllControlsDef, 60, 30); -menu_t OP_Joystick3Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick3Menu, &OP_AllControlsDef, 60, 30); -menu_t OP_Joystick4Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick4Menu, &OP_AllControlsDef, 60, 30); -menu_t OP_JoystickSetDef = -{ - "M_CONTRO", - sizeof (OP_JoystickSetMenu)/sizeof (menuitem_t), - &OP_Joystick1Def, - OP_JoystickSetMenu, - M_DrawJoystick, - 50, 40, - 0, - NULL -}; - -menu_t OP_VideoOptionsDef = -{ - "M_VIDEO", - sizeof(OP_VideoOptionsMenu)/sizeof(menuitem_t), - &OP_MainDef, - OP_VideoOptionsMenu, - M_DrawVideoMenu, - 30, 30, - 0, - NULL -}; - -menu_t OP_VideoModeDef = -{ - "M_VIDEO", - 1, - &OP_VideoOptionsDef, - OP_VideoModeMenu, - M_DrawVideoMode, - 48, 26, - 0, - NULL -}; - -menu_t OP_SoundOptionsDef = -{ - "M_SOUND", - sizeof (OP_SoundOptionsMenu)/sizeof (menuitem_t), - &OP_MainDef, - OP_SoundOptionsMenu, - M_DrawSoundOptions, - 30, 30, - 0, - NULL -}; - -menu_t OP_HUDOptionsDef = -{ - "M_HUD", - sizeof (OP_HUDOptionsMenu)/sizeof (menuitem_t), - &OP_MainDef, - OP_HUDOptionsMenu, - M_DrawHUDOptions, - 30, 30, - 0, - NULL -}; - -menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE("M_HUD", OP_ChatOptionsMenu, &OP_HUDOptionsDef, 30, 30); - -menu_t OP_GameOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_GameOptionsMenu, &OP_MainDef, 30, 30); -menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, &OP_MainDef, 24, 30); -#ifndef NONET -menu_t OP_AdvServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_AdvServerOptionsMenu, &OP_ServerOptionsDef, 24, 30); -#endif - -//menu_t OP_NetgameOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_NetgameOptionsMenu, &OP_ServerOptionsDef, 30, 30); -//menu_t OP_GametypeOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_GametypeOptionsMenu, &OP_ServerOptionsDef, 30, 30); -//menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_ChatOptionsMenu, &OP_GameOptionsDef, 30, 30); -menu_t OP_MonitorToggleDef = -{ - "M_GAME", - sizeof (OP_MonitorToggleMenu)/sizeof (menuitem_t), - &OP_GameOptionsDef, - OP_MonitorToggleMenu, - M_DrawMonitorToggles, - 47, 30, - 0, - NULL -}; - -#ifdef HWRENDER -menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 30); -#ifdef ALAM_LIGHTING -menu_t OP_OpenGLLightingDef = DEFAULTMENUSTYLE("M_VIDEO", OP_OpenGLLightingMenu, &OP_OpenGLOptionsDef, 60, 40); -#endif -menu_t OP_OpenGLFogDef = -{ - "M_VIDEO", - sizeof (OP_OpenGLFogMenu)/sizeof (menuitem_t), - &OP_OpenGLOptionsDef, - OP_OpenGLFogMenu, - M_OGL_DrawFogMenu, - 60, 40, - 0, - NULL -}; -menu_t OP_OpenGLColorDef = -{ - "M_VIDEO", - sizeof (OP_OpenGLColorMenu)/sizeof (menuitem_t), - &OP_OpenGLOptionsDef, - OP_OpenGLColorMenu, - M_OGL_DrawColorMenu, - 60, 40, - 0, - NULL -}; -#endif -menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); -menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_SCSHOT", OP_ScreenshotOptionsMenu, &OP_DataOptionsDef, 30, 30); -menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30); -menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 30, 30); - -menu_t OP_ReplayOptionsDef = -{ - "M_REPOPT", - sizeof (OP_ReplayOptionsMenu)/sizeof (menuitem_t), - &OP_DataOptionsDef, - OP_ReplayOptionsMenu, - M_DrawGenericMenu, - 27, 40, - 0, - NULL -}; - -// -// M_GetGametypeColor -// -// Pretty and consistent ^u^ -// See also G_GetGametypeColor. -// - -static INT32 highlightflags, recommendedflags, warningflags; - -inline static void M_GetGametypeColor(void) -{ - INT16 gt; - - warningflags = V_REDMAP; - recommendedflags = V_GREENMAP; - - if (cons_menuhighlight.value) - { - highlightflags = cons_menuhighlight.value; - if (highlightflags == V_REDMAP) - { - warningflags = V_ORANGEMAP; - return; - } - if (highlightflags == V_GREENMAP) - { - recommendedflags = V_SKYMAP; - return; - } - return; - } - - warningflags = V_REDMAP; - recommendedflags = V_GREENMAP; - - if (modeattacking) // == ATTACKING_RECORD - { - highlightflags = V_ORANGEMAP; - return; - } - - if (currentMenu->drawroutine == M_DrawServerMenu) - gt = cv_newgametype.value; - else if (!Playing()) - { - highlightflags = V_YELLOWMAP; - return; - } - else - gt = gametype; - - if (gt == GT_MATCH) - { - highlightflags = V_REDMAP; - warningflags = V_ORANGEMAP; - return; - } - if (gt == GT_RACE) - { - highlightflags = V_SKYMAP; - return; - } - - highlightflags = V_YELLOWMAP; // FALLBACK -} - -// excuse me but I'm extremely lazy: -INT32 HU_GetHighlightColor(void) -{ - M_GetGametypeColor(); // update flag colour reguardless of the menu being opened or not. - return highlightflags; -} - -// ========================================================================== -// CVAR ONCHANGE EVENTS GO HERE -// ========================================================================== -// (there's only a couple anyway) - -// Prototypes -static INT32 M_FindFirstMap(INT32 gtype); -static INT32 M_GetFirstLevelInList(void); - -// Nextmap. Used for Time Attack. -static void Nextmap_OnChange(void) -{ - char *leveltitle; - UINT8 active; - - // Update the string in the consvar. - Z_Free(cv_nextmap.zstring); - leveltitle = G_BuildMapTitle(cv_nextmap.value); - cv_nextmap.string = cv_nextmap.zstring = leveltitle ? leveltitle : Z_StrDup(G_BuildMapName(cv_nextmap.value)); - - if (currentMenu == &SP_TimeAttackDef) - { - // see also p_setup.c's P_LoadRecordGhosts - const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; - char *gpath = malloc(glen); - INT32 i; - - if (!gpath) - return; - - sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)); - - CV_StealthSetValue(&cv_dummystaff, 0); - - active = false; - SP_TimeAttackMenu[taguest].status = IT_DISABLED; - SP_TimeAttackMenu[tareplay].status = IT_DISABLED; - //SP_TimeAttackMenu[taghost].status = IT_DISABLED; - - // Check if file exists, if not, disable REPLAY option - for (i = 0; i < 4; i++) - { - SP_ReplayMenu[i].status = IT_DISABLED; - SP_GuestReplayMenu[i].status = IT_DISABLED; - } - SP_ReplayMenu[4].status = IT_DISABLED; - - SP_GhostMenu[3].status = IT_DISABLED; - SP_GhostMenu[4].status = IT_DISABLED; - - if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, cv_chooseskin.string))) { - SP_ReplayMenu[0].status = IT_WHITESTRING|IT_CALL; - SP_GuestReplayMenu[0].status = IT_WHITESTRING|IT_CALL; - active |= 3; - } - if (FIL_FileExists(va("%s-%s-lap-best.lmp", gpath, cv_chooseskin.string))) { - SP_ReplayMenu[1].status = IT_WHITESTRING|IT_CALL; - SP_GuestReplayMenu[1].status = IT_WHITESTRING|IT_CALL; - active |= 3; - } - if (FIL_FileExists(va("%s-%s-last.lmp", gpath, cv_chooseskin.string))) { - SP_ReplayMenu[2].status = IT_WHITESTRING|IT_CALL; - SP_GuestReplayMenu[2].status = IT_WHITESTRING|IT_CALL; - active |= 3; - } - - if (FIL_FileExists(va("%s-guest.lmp", gpath))) - { - SP_ReplayMenu[3].status = IT_WHITESTRING|IT_CALL; - SP_GuestReplayMenu[3].status = IT_WHITESTRING|IT_CALL; - SP_GhostMenu[3].status = IT_STRING|IT_CVAR; - active |= 3; - } - - CV_SetValue(&cv_dummystaff, 1); - if (cv_dummystaff.value) - { - SP_ReplayMenu[4].status = IT_WHITESTRING|IT_KEYHANDLER; - SP_GhostMenu[4].status = IT_STRING|IT_CVAR; - CV_StealthSetValue(&cv_dummystaff, 1); - active |= 1; - } - - if (active) { - if (active & 1) - SP_TimeAttackMenu[tareplay].status = IT_WHITESTRING|IT_SUBMENU; - if (active & 2) - SP_TimeAttackMenu[taguest].status = IT_WHITESTRING|IT_SUBMENU; - } - else if (itemOn == tareplay) // Reset lastOn so replay isn't still selected when not available. - { - currentMenu->lastOn = itemOn; - itemOn = tastart; - } - - if (mapheaderinfo[cv_nextmap.value-1] && mapheaderinfo[cv_nextmap.value-1]->forcecharacter[0] != '\0') - CV_Set(&cv_chooseskin, mapheaderinfo[cv_nextmap.value-1]->forcecharacter); - - free(gpath); - } -} - -static void Dummymenuplayer_OnChange(void) -{ - if (cv_dummymenuplayer.value < 1) - CV_StealthSetValue(&cv_dummymenuplayer, splitscreen+1); - else if (cv_dummymenuplayer.value > splitscreen+1) - CV_StealthSetValue(&cv_dummymenuplayer, 1); -} - -/*static void Dummymares_OnChange(void) -{ - if (!nightsrecords[cv_nextmap.value-1]) - { - CV_StealthSetValue(&cv_dummymares, 0); - return; - } - else - { - UINT8 mares = nightsrecords[cv_nextmap.value-1]->nummares; - - if (cv_dummymares.value < 0) - CV_StealthSetValue(&cv_dummymares, mares); - else if (cv_dummymares.value > mares) - CV_StealthSetValue(&cv_dummymares, 0); - } -}*/ - -char dummystaffname[22]; - -static void Dummystaff_OnChange(void) -{ - lumpnum_t l; - - dummystaffname[0] = '\0'; - - if ((l = W_CheckNumForName(va("%sS01",G_BuildMapName(cv_nextmap.value)))) == LUMPERROR) - { - CV_StealthSetValue(&cv_dummystaff, 0); - return; - } - else - { - char *temp = dummystaffname; - UINT8 numstaff = 1; - while (numstaff < 99 && (l = W_CheckNumForName(va("%sS%02u",G_BuildMapName(cv_nextmap.value),numstaff+1))) != LUMPERROR) - numstaff++; - - if (cv_dummystaff.value < 1) - CV_StealthSetValue(&cv_dummystaff, numstaff); - else if (cv_dummystaff.value > numstaff) - CV_StealthSetValue(&cv_dummystaff, 1); - - if ((l = W_CheckNumForName(va("%sS%02u",G_BuildMapName(cv_nextmap.value), cv_dummystaff.value))) == LUMPERROR) - return; // shouldn't happen but might as well check... - - G_UpdateStaffGhostName(l); - - while (*temp) - temp++; - - sprintf(temp, " - %d", cv_dummystaff.value); - } -} - -// Newgametype. Used for gametype changes. -static void Newgametype_OnChange(void) -{ - if (cv_nextmap.value && menuactive) - { - if (!mapheaderinfo[cv_nextmap.value-1]) - P_AllocMapHeader((INT16)(cv_nextmap.value-1)); - - if ((cv_newgametype.value == GT_RACE && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_RACE)) || // SRB2kart - //(cv_newgametype.value == GT_COMPETITION && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_COMPETITION)) || - //(cv_newgametype.value == GT_RACE && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_RACE)) || - ((cv_newgametype.value == GT_MATCH || cv_newgametype.value == GT_TEAMMATCH) && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_MATCH))) // || - //((cv_newgametype.value == GT_TAG || cv_newgametype.value == GT_HIDEANDSEEK) && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_TAG)) || - //(cv_newgametype.value == GT_CTF && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_CTF))) - { - INT32 value = 0; - - switch (cv_newgametype.value) - { - case GT_COOP: - value = TOL_RACE; // SRB2kart - break; - case GT_COMPETITION: - value = TOL_COMPETITION; - break; - case GT_RACE: - value = TOL_RACE; - break; - case GT_MATCH: - case GT_TEAMMATCH: - value = TOL_MATCH; - break; - case GT_TAG: - case GT_HIDEANDSEEK: - value = TOL_TAG; - break; - case GT_CTF: - value = TOL_CTF; - break; - } - - CV_SetValue(&cv_nextmap, M_FindFirstMap(value)); - //CV_AddValue(&cv_nextmap, -1); - //CV_AddValue(&cv_nextmap, 1); - } - } -} - -void Screenshot_option_Onchange(void) -{ - OP_ScreenshotOptionsMenu[op_screenshot_folder].status = - (cv_screenshot_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); -} - -void Moviemode_mode_Onchange(void) -{ - INT32 i, cstart, cend; - for (i = op_screenshot_gif_start; i <= op_screenshot_apng_end; ++i) - OP_ScreenshotOptionsMenu[i].status = IT_DISABLED; - - switch (cv_moviemode.value) - { - case MM_GIF: - cstart = op_screenshot_gif_start; - cend = op_screenshot_gif_end; - break; - case MM_APNG: - cstart = op_screenshot_apng_start; - cend = op_screenshot_apng_end; - break; - default: - return; - } - for (i = cstart; i <= cend; ++i) - OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR; -} - -void Addons_option_Onchange(void) -{ - OP_AddonsOptionsMenu[op_addons_folder].status = - (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); -} - -// ========================================================================== -// END ORGANIZATION STUFF. -// ========================================================================== - -// current menudef -menu_t *currentMenu = &MainDef; - -// ========================================================================= -// BASIC MENU HANDLING -// ========================================================================= - -static void M_ChangeCvar(INT32 choice) -{ - consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; - - if (choice == -1) - { - if (cv == &cv_playercolor) - { - SINT8 skinno = R_SkinAvailable(cv_chooseskin.string); - if (skinno != -1) - CV_SetValue(cv,skins[skinno].prefcolor); - return; - } - CV_Set(cv,cv->defaultvalue); - return; - } - - choice = (choice<<1) - 1; - - if (((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_SLIDER) - ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_INVISSLIDER) - ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_NOMOD)) - { - CV_SetValue(cv,cv->value+choice); - } - else if (cv->flags & CV_FLOAT) - { - char s[20]; - sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); - CV_Set(cv,s); - } - else - { -#ifndef NONET - if (cv == &cv_nettimeout || cv == &cv_jointimeout) - choice *= (TICRATE/7); - else if (cv == &cv_maxsend) - choice *= 512; - else if (cv == &cv_maxping) - choice *= 50; -#endif - CV_AddValue(cv,choice); - } -} - -static boolean M_ChangeStringCvar(INT32 choice) -{ - consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; - char buf[MAXSTRINGLENGTH]; - size_t len; - - if (shiftdown && choice >= 32 && choice <= 127) - choice = shiftxform[choice]; - - switch (choice) - { - case KEY_BACKSPACE: - len = strlen(cv->string); - if (len > 0) - { - S_StartSound(NULL,sfx_menu1); // Tails - M_Memcpy(buf, cv->string, len); - buf[len-1] = 0; - CV_Set(cv, buf); - } - return true; - case KEY_DEL: - if (cv->string[0]) - { - S_StartSound(NULL,sfx_menu1); // Tails - CV_Set(cv, ""); - } - return true; - default: - if (choice >= 32 && choice <= 127) - { - len = strlen(cv->string); - if (len < MAXSTRINGLENGTH - 1) - { - S_StartSound(NULL,sfx_menu1); // Tails - M_Memcpy(buf, cv->string, len); - buf[len++] = (char)choice; - buf[len] = 0; - CV_Set(cv, buf); - } - return true; - } - break; - } - return false; -} - -static void M_NextOpt(void) -{ - INT16 oldItemOn = itemOn; // prevent infinite loop - - if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) - ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value = 0; - - do - { - if (itemOn + 1 > currentMenu->numitems - 1) - itemOn = 0; - else - itemOn++; - } while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE); -} - -static void M_PrevOpt(void) -{ - INT16 oldItemOn = itemOn; // prevent infinite loop - - if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) - ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value = 0; - - do - { - if (!itemOn) - itemOn = currentMenu->numitems - 1; - else - itemOn--; - } while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE); -} - -// lock out further input in a tic when important buttons are pressed -// (in other words -- stop bullshit happening by mashing buttons in fades) -static boolean noFurtherInput = false; - -static void Command_Manual_f(void) -{ - if (modeattacking) - return; - M_StartControlPanel(); - M_Manual(INT32_MAX); - itemOn = 0; -} - -// -// M_Responder -// -boolean M_Responder(event_t *ev) -{ - INT32 ch = -1; -// INT32 i; - static tic_t joywait = 0, mousewait = 0; - static INT32 pjoyx = 0, pjoyy = 0; - static INT32 pmousex = 0, pmousey = 0; - static INT32 lastx = 0, lasty = 0; - void (*routine)(INT32 choice); // for some casting problem - - if (dedicated || (demo.playback && demo.title) - || gamestate == GS_INTRO || gamestate == GS_CUTSCENE || gamestate == GS_GAMEEND - || gamestate == GS_CREDITS || gamestate == GS_EVALUATION) - return false; - - if (noFurtherInput) - { - // Ignore input after enter/escape/other buttons - // (but still allow shift keyup so caps doesn't get stuck) - return false; - } - else if (ev->type == ev_keydown) - { - ch = ev->data1; - - // added 5-2-98 remap virtual keys (mouse & joystick buttons) - switch (ch) - { - case KEY_MOUSE1: - //case KEY_JOY1: - //case KEY_JOY1 + 2: - ch = KEY_ENTER; - break; - /*case KEY_JOY1 + 3: // Brake can function as 'n' for message boxes now. - ch = 'n'; - break;*/ - case KEY_MOUSE1 + 1: - //case KEY_JOY1 + 1: - ch = KEY_BACKSPACE; - break; - case KEY_HAT1: - ch = KEY_UPARROW; - break; - case KEY_HAT1 + 1: - ch = KEY_DOWNARROW; - break; - case KEY_HAT1 + 2: - ch = KEY_LEFTARROW; - break; - case KEY_HAT1 + 3: - ch = KEY_RIGHTARROW; - break; - } - } - else if (menuactive) - { - if (ev->type == ev_joystick && ev->data1 == 0 && joywait < I_GetTime()) - { - const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone.value) >> FRACBITS; - if (ev->data3 != INT32_MAX) - { - if (Joystick.bGamepadStyle || abs(ev->data3) > jdeadzone) - { - if (ev->data3 < 0 && pjoyy >= 0) - { - ch = KEY_UPARROW; - joywait = I_GetTime() + NEWTICRATE/7; - } - else if (ev->data3 > 0 && pjoyy <= 0) - { - ch = KEY_DOWNARROW; - joywait = I_GetTime() + NEWTICRATE/7; - } - pjoyy = ev->data3; - } - else - pjoyy = 0; - } - - if (ev->data2 != INT32_MAX) - { - if (Joystick.bGamepadStyle || abs(ev->data2) > jdeadzone) - { - if (ev->data2 < 0 && pjoyx >= 0) - { - ch = KEY_LEFTARROW; - joywait = I_GetTime() + NEWTICRATE/17; - } - else if (ev->data2 > 0 && pjoyx <= 0) - { - ch = KEY_RIGHTARROW; - joywait = I_GetTime() + NEWTICRATE/17; - } - pjoyx = ev->data2; - } - else - pjoyx = 0; - } - } - else if (ev->type == ev_mouse && mousewait < I_GetTime()) - { - pmousey += ev->data3; - if (pmousey < lasty-30) - { - ch = KEY_DOWNARROW; - mousewait = I_GetTime() + NEWTICRATE/7; - pmousey = lasty -= 30; - } - else if (pmousey > lasty + 30) - { - ch = KEY_UPARROW; - mousewait = I_GetTime() + NEWTICRATE/7; - pmousey = lasty += 30; - } - - pmousex += ev->data2; - if (pmousex < lastx - 30) - { - ch = KEY_LEFTARROW; - mousewait = I_GetTime() + NEWTICRATE/7; - pmousex = lastx -= 30; - } - else if (pmousex > lastx+30) - { - ch = KEY_RIGHTARROW; - mousewait = I_GetTime() + NEWTICRATE/7; - pmousex = lastx += 30; - } - } - } - - if (ch == -1) - return false; - else if (ch == gamecontrol[gc_systemmenu][0] || ch == gamecontrol[gc_systemmenu][1]) // allow remappable ESC key - ch = KEY_ESCAPE; - else if ((ch == gamecontrol[gc_accelerate][0] || ch == gamecontrol[gc_accelerate][1]) && ch >= KEY_MOUSE1) - ch = KEY_ENTER; - - // F-Keys - if (!menuactive) - { - noFurtherInput = true; - - switch (ch) - { - case KEY_F1: // Help key - Command_Manual_f(); - return true; - - case KEY_F2: // Empty - return true; - - case KEY_F3: // Toggle HUD - CV_SetValue(&cv_showhud, !cv_showhud.value); - return true; - - case KEY_F4: // Sound Volume - if (modeattacking) - return true; - M_StartControlPanel(); - M_Options(0); - currentMenu = &OP_SoundOptionsDef; - itemOn = 0; - return true; - -#ifndef DC - case KEY_F5: // Video Mode - if (modeattacking) - return true; - M_StartControlPanel(); - M_Options(0); - M_VideoModeMenu(0); - return true; -#endif - - case KEY_F6: // Empty - return true; - - case KEY_F7: // Options - if (modeattacking) - return true; - M_StartControlPanel(); - M_Options(0); - M_SetupNextMenu(&OP_MainDef); - return true; - - // Screenshots on F8 now handled elsewhere - // Same with Moviemode on F9 - - case KEY_F10: // Quit SRB2 - M_QuitSRB2(0); - return true; - - case KEY_F11: // Gamma Level - CV_AddValue(&cv_usegamma, 1); - return true; - - // Spymode on F12 handled in game logic - - case KEY_ESCAPE: // Pop up menu - if (chat_on) - { - HU_clearChatChars(); - chat_on = false; - } - else - M_StartControlPanel(); - return true; - } - noFurtherInput = false; // turns out we didn't care - return false; - } - - if ((ch == gamecontrol[gc_brake][0] || ch == gamecontrol[gc_brake][1]) && ch >= KEY_MOUSE1) // do this here, otherwise brake opens the menu mid-game - ch = KEY_ESCAPE; - - routine = currentMenu->menuitems[itemOn].itemaction; - - // Handle menuitems which need a specific key handling - if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER) - { - if (shiftdown && ch >= 32 && ch <= 127) - ch = shiftxform[ch]; - routine(ch); - return true; - } - - if (currentMenu->menuitems[itemOn].status == IT_MSGHANDLER) - { - if (currentMenu->menuitems[itemOn].mvar1 != MM_EVENTHANDLER) - { - if (ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE || ch == KEY_ENTER) - { - if (routine) - routine(ch); - M_StopMessage(0); - noFurtherInput = true; - return true; - } - return true; - } - else - { - // dirty hack: for customising controls, I want only buttons/keys, not moves - if (ev->type == ev_mouse || ev->type == ev_mouse2 || ev->type == ev_joystick - || ev->type == ev_joystick2 || ev->type == ev_joystick3 || ev->type == ev_joystick4) - return true; - if (routine) - { - void (*otherroutine)(event_t *sev) = currentMenu->menuitems[itemOn].itemaction; - otherroutine(ev); //Alam: what a hack - } - return true; - } - } - - // BP: one of the more big hack i have never made - if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR) - { - if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING || (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) - { - if (ch == KEY_TAB && (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD) - ((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value ^= 1; - - if (shiftdown && ch >= 32 && ch <= 127) - ch = shiftxform[ch]; - if (M_ChangeStringCvar(ch)) - return true; - else - routine = NULL; - } - else - routine = M_ChangeCvar; - } - - if (currentMenu == &PlaybackMenuDef) - { - // Flip left/right with up/down for the playback menu, since it's a horizontal icon row. - switch (ch) - { - case KEY_LEFTARROW: ch = KEY_UPARROW; break; - case KEY_UPARROW: ch = KEY_RIGHTARROW; break; - case KEY_RIGHTARROW: ch = KEY_DOWNARROW; break; - case KEY_DOWNARROW: ch = KEY_LEFTARROW; break; - default: break; - } - } - - // Keys usable within menu - switch (ch) - { - case KEY_DOWNARROW: - M_NextOpt(); - S_StartSound(NULL, sfx_menu1); - /*if (currentMenu == &SP_PlayerDef) - { - Z_Free(char_notes); - char_notes = NULL; - }*/ - return true; - - case KEY_UPARROW: - M_PrevOpt(); - S_StartSound(NULL, sfx_menu1); - /*if (currentMenu == &SP_PlayerDef) - { - Z_Free(char_notes); - char_notes = NULL; - }*/ - return true; - - case KEY_LEFTARROW: - if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS - || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) - { - if (currentMenu != &OP_SoundOptionsDef || itemOn > 3) - S_StartSound(NULL, sfx_menu1); - routine(0); - } - return true; - - case KEY_RIGHTARROW: - if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS - || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) - { - if (currentMenu != &OP_SoundOptionsDef || itemOn > 3) - S_StartSound(NULL, sfx_menu1); - routine(1); - } - return true; - - case KEY_ENTER: - noFurtherInput = true; - currentMenu->lastOn = itemOn; - - if (currentMenu == &PlaybackMenuDef) - { - boolean held = (boolean)playback_enterheld; - playback_enterheld = TICRATE/7; - if (held) - return true; - } - - if (routine) - { - if (((currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_CALL - || (currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_SUBMENU) - && (currentMenu->menuitems[itemOn].status & IT_CALLTYPE)) - { - if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && majormods) - { - S_StartSound(NULL, sfx_menu1); - M_StartMessage(M_GetText("This cannot be done with complex add-ons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); - return true; - } - } - S_StartSound(NULL, sfx_menu1); - switch (currentMenu->menuitems[itemOn].status & IT_TYPE) - { - case IT_CVAR: - case IT_ARROWS: - routine(1); // right arrow - break; - case IT_CALL: - routine(itemOn); - break; - case IT_SUBMENU: - currentMenu->lastOn = itemOn; - M_SetupNextMenu((menu_t *)currentMenu->menuitems[itemOn].itemaction); - break; - } - } - return true; - - case KEY_ESCAPE: - //case KEY_JOY1 + 2: - noFurtherInput = true; - currentMenu->lastOn = itemOn; - if (currentMenu->prevMenu) - { - //If we entered the game search menu, but didn't enter a game, - //make sure the game doesn't still think we're in a netgame. - if (!Playing() && netgame && multiplayer) - { - MSCloseUDPSocket(); // Clean up so we can re-open the connection later. - netgame = false; - multiplayer = false; - } - - M_SetupNextMenu(currentMenu->prevMenu); - } - else - M_ClearMenus(true); - - return true; - - case KEY_BACKSPACE: - if ((currentMenu->menuitems[itemOn].status) == IT_CONTROL) - { - // detach any keys associated with the game control - G_ClearControlKeys(setupcontrols, currentMenu->menuitems[itemOn].mvar1); - S_StartSound(NULL, sfx_shldls); - return true; - } - - if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS - || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) - { - consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; - - if (cv == &cv_chooseskin - || cv == &cv_dummystaff - || cv == &cv_nextmap - || cv == &cv_newgametype) - return true; - - if (currentMenu != &OP_SoundOptionsDef || itemOn > 3) - S_StartSound(NULL, sfx_menu1); - routine(-1); - return true; - } - - // Why _does_ backspace go back anyway? - //currentMenu->lastOn = itemOn; - //if (currentMenu->prevMenu) - // M_SetupNextMenu(currentMenu->prevMenu); - return false; - - default: - break; - } - - return true; -} - -// -// M_Drawer -// Called after the view has been rendered, -// but before it has been blitted. -// -void M_Drawer(void) -{ - if (currentMenu == &MessageDef) - menuactive = true; - - if (menuwipe) - F_WipeStartScreen(); - - if (menuactive) - { - if (gamestate == GS_MENU) // draw BG - { - V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("WEIRDRES", PU_CACHE), NULL); - V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("MENUBG", PU_CACHE), NULL); - } - else if (!WipeInAction && currentMenu != &PlaybackMenuDef) // Replay playback has its own background - V_DrawFadeScreen(0xFF00, 16); // now that's more readable with a faded background (yeah like Quake...) - - if (currentMenu->drawroutine) - { - M_GetGametypeColor(); - currentMenu->drawroutine(); // call current menu Draw routine - } - - // Draw version down in corner - // ... but only in the MAIN MENU. I'm a picky bastard. - if (currentMenu == &MainDef) - { - if (customversionstring[0] != '\0') - { - V_DrawThinString(vid.dupx, vid.height - 20*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT, "Mod version:"); - V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring); - } - else - { -#ifdef DEVELOP // Development -- show revision / branch info - V_DrawThinString(vid.dupx, vid.height - 20*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, compbranch); - V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision); -#else // Regular build - V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s", VERSIONSTRING)); -#endif - } - } - } - - if (menuwipe) - { - F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_menu_final], false, "FADEMAP0", true); - menuwipe = false; - } - - // focus lost notification goes on top of everything, even the former everything - if (window_notinfocus && cv_showfocuslost.value) - { - M_DrawTextBox((BASEVIDWIDTH/2) - (60), (BASEVIDHEIGHT/2) - (16), 13, 2); - if (gamestate == GS_LEVEL && (P_AutoPause() || paused)) - V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), highlightflags, "Game Paused"); - else - V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), highlightflags, "Focus Lost"); - } -} - -// -// M_StartControlPanel -// -void M_StartControlPanel(void) -{ - // intro might call this repeatedly - if (menuactive) - { - CON_ToggleOff(); // move away console - return; - } - - if (gamestate == GS_TITLESCREEN) // Set up menu state - { - G_SetGamestate(GS_MENU); - - gameaction = ga_nothing; - paused = false; - CON_ToggleOff(); - - S_ChangeMusicInternal("menu", true); - } - - menuactive = true; - - if (demo.playback) - { - currentMenu = &PlaybackMenuDef; - } - else if (!Playing()) - { - currentMenu = &MainDef; - itemOn = 0; - } - else if (modeattacking) - { - currentMenu = &MAPauseDef; - itemOn = mapause_continue; - } - else if (!(netgame || multiplayer)) // Single Player - { - if (gamestate != GS_LEVEL) // intermission, so gray out stuff. - SPauseMenu[spause_retry].status = IT_GRAYEDOUT; - else - { - //INT32 numlives = 2; - - /*if (&players[consoleplayer]) - { - numlives = players[consoleplayer].lives; - if (players[consoleplayer].playerstate != PST_LIVE) - ++numlives; - } - - // The list of things that can disable retrying is (was?) a little too complex - // for me to want to use the short if statement syntax - if (numlives <= 1 || G_IsSpecialStage(gamemap)) - SPauseMenu[spause_retry].status = (IT_GRAYEDOUT); - else*/ - SPauseMenu[spause_retry].status = (IT_STRING | IT_CALL); - } - - currentMenu = &SPauseDef; - itemOn = spause_continue; - } - else // multiplayer - { - MPauseMenu[mpause_switchmap].status = IT_DISABLED; - MPauseMenu[mpause_addons].status = IT_DISABLED; - MPauseMenu[mpause_scramble].status = IT_DISABLED; - MPauseMenu[mpause_psetupsplit].status = IT_DISABLED; - MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED; - MPauseMenu[mpause_psetupsplit3].status = IT_DISABLED; - MPauseMenu[mpause_psetupsplit4].status = IT_DISABLED; - MPauseMenu[mpause_spectate].status = IT_DISABLED; - MPauseMenu[mpause_entergame].status = IT_DISABLED; - MPauseMenu[mpause_canceljoin].status = IT_DISABLED; - MPauseMenu[mpause_switchteam].status = IT_DISABLED; - MPauseMenu[mpause_switchspectate].status = IT_DISABLED; - MPauseMenu[mpause_psetup].status = IT_DISABLED; - MISC_ChangeTeamMenu[0].status = IT_DISABLED; - MISC_ChangeSpectateMenu[0].status = IT_DISABLED; - // Reset these in case splitscreen messes things up - MPauseMenu[mpause_switchteam].mvar1 = 48; - MPauseMenu[mpause_switchspectate].mvar1 = 48; - MPauseMenu[mpause_options].mvar1 = 64; - MPauseMenu[mpause_title].mvar1 = 80; - MPauseMenu[mpause_quit].mvar1 = 88; - Dummymenuplayer_OnChange(); - - if ((server || IsPlayerAdmin(consoleplayer))) - { - MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL; - MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL; - if (G_GametypeHasTeams()) - MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU; - } - - if (splitscreen) - { - MPauseMenu[mpause_psetupsplit].status = MPauseMenu[mpause_psetupsplit2].status = IT_STRING | IT_CALL; - MISC_ChangeTeamMenu[0].status = MISC_ChangeSpectateMenu[0].status = IT_STRING|IT_CVAR; - - if (netgame) - { - if (G_GametypeHasTeams()) - { - MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU; - MPauseMenu[mpause_switchteam].mvar1 += ((splitscreen+1) * 8); - MPauseMenu[mpause_options].mvar1 += 8; - MPauseMenu[mpause_title].mvar1 += 8; - MPauseMenu[mpause_quit].mvar1 += 8; - } - else if (G_GametypeHasSpectators()) - { - MPauseMenu[mpause_switchspectate].status = IT_STRING | IT_SUBMENU; - MPauseMenu[mpause_switchspectate].mvar1 += ((splitscreen+1) * 8); - MPauseMenu[mpause_options].mvar1 += 8; - MPauseMenu[mpause_title].mvar1 += 8; - MPauseMenu[mpause_quit].mvar1 += 8; - } - } - - if (splitscreen > 1) - { - MPauseMenu[mpause_psetupsplit3].status = IT_STRING | IT_CALL; - - MPauseMenu[mpause_options].mvar1 += 8; - MPauseMenu[mpause_title].mvar1 += 8; - MPauseMenu[mpause_quit].mvar1 += 8; - - if (splitscreen > 2) - { - MPauseMenu[mpause_psetupsplit4].status = IT_STRING | IT_CALL; - MPauseMenu[mpause_options].mvar1 += 8; - MPauseMenu[mpause_title].mvar1 += 8; - MPauseMenu[mpause_quit].mvar1 += 8; - } - } - } - else - { - MPauseMenu[mpause_psetup].status = IT_STRING | IT_CALL; - - if (G_GametypeHasTeams()) - MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU; - else if (G_GametypeHasSpectators()) - { - if (!players[consoleplayer].spectator) - MPauseMenu[mpause_spectate].status = IT_STRING | IT_CALL; - else if (players[consoleplayer].pflags & PF_WANTSTOJOIN) - MPauseMenu[mpause_canceljoin].status = IT_STRING | IT_CALL; - else - MPauseMenu[mpause_entergame].status = IT_STRING | IT_CALL; - } - else // in this odd case, we still want something to be on the menu even if it's useless - MPauseMenu[mpause_spectate].status = IT_GRAYEDOUT; - } - - currentMenu = &MPauseDef; - itemOn = mpause_continue; - } - - CON_ToggleOff(); // move away console -} - -void M_EndModeAttackRun(void) -{ - M_ModeAttackEndGame(0); -} - -// -// M_ClearMenus -// -void M_ClearMenus(boolean callexitmenufunc) -{ - if (!menuactive) - return; - - if (currentMenu->quitroutine && callexitmenufunc && !currentMenu->quitroutine()) - return; // we can't quit this menu (also used to set parameter from the menu) - -#ifndef DC // Save the config file. I'm sick of crashing the game later and losing all my changes! - COM_BufAddText(va("saveconfig \"%s\" -silent\n", configfile)); -#endif //Alam: But not on the Dreamcast's VMUs - - if (currentMenu == &MessageDef) // Oh sod off! - currentMenu = &MainDef; // Not like it matters - - if (gamestate == GS_MENU) // Back to title screen - D_StartTitle(); - - menuactive = false; -} - -// -// M_SetupNextMenu -// -void M_SetupNextMenu(menu_t *menudef) -{ - INT16 i; - - if (gamestate == GS_MENU) - { - menuwipe = true; - F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - F_WipeEndScreen(); - F_RunWipe(wipedefs[wipe_menu_toblack], false, "FADEMAP0", false); - } - - if (currentMenu->quitroutine) - { - // If you're going from a menu to itself, why are you running the quitroutine? You're not quitting it! -SH - if (currentMenu != menudef && !currentMenu->quitroutine()) - return; // we can't quit this menu (also used to set parameter from the menu) - } - - currentMenu = menudef; - itemOn = currentMenu->lastOn; - - // in case of... - if (itemOn >= currentMenu->numitems) - itemOn = currentMenu->numitems - 1; - - // the curent item can be disabled, - // this code go up until an enabled item found - if ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE) - { - for (i = 0; i < currentMenu->numitems; i++) - { - if ((currentMenu->menuitems[i].status & IT_TYPE) != IT_SPACE) - { - itemOn = i; - break; - } - } - } -} - -// -// M_Ticker -// -void M_Ticker(void) -{ - // reset input trigger - noFurtherInput = false; - - if (dedicated) - return; - - if (--skullAnimCounter <= 0) - skullAnimCounter = 8; - - if (currentMenu == &PlaybackMenuDef) - { - if (playback_enterheld > 0) - playback_enterheld--; - } - else - playback_enterheld = 0; - - //added : 30-01-98 : test mode for five seconds - if (vidm_testingmode > 0) - { - // restore the previous video mode - if (--vidm_testingmode == 0) - setmodeneeded = vidm_previousmode + 1; - } -} - -// -// M_Init -// -void M_Init(void) -{ - UINT8 i; - - COM_AddCommand("manual", Command_Manual_f); - - CV_RegisterVar(&cv_nextmap); - CV_RegisterVar(&cv_newgametype); - CV_RegisterVar(&cv_chooseskin); - CV_RegisterVar(&cv_autorecord); - - if (dedicated) - return; - - // Menu hacks - CV_RegisterVar(&cv_dummymenuplayer); - CV_RegisterVar(&cv_dummyteam); - CV_RegisterVar(&cv_dummyspectate); - CV_RegisterVar(&cv_dummyscramble); - CV_RegisterVar(&cv_dummyrings); - CV_RegisterVar(&cv_dummylives); - CV_RegisterVar(&cv_dummycontinues); - //CV_RegisterVar(&cv_dummymares); - CV_RegisterVar(&cv_dummystaff); - - quitmsg[QUITMSG] = M_GetText("Eggman's tied explosives\nto your girlfriend, and\nwill activate them if\nyou press the 'Y' key!\nPress 'N' to save her!\n\n(Press 'Y' to quit)"); - quitmsg[QUITMSG1] = M_GetText("What would Tails say if\nhe saw you quitting the game?\n\n(Press 'Y' to quit)"); - quitmsg[QUITMSG2] = M_GetText("Hey!\nWhere do ya think you're goin'?\n\n(Press 'Y' to quit)"); - quitmsg[QUITMSG3] = M_GetText("Forget your studies!\nPlay some more!\n\n(Press 'Y' to quit)"); - quitmsg[QUITMSG4] = M_GetText("You're trying to say you\nlike Sonic R better than\nthis, aren't you?\n\n(Press 'Y' to quit)"); - quitmsg[QUITMSG5] = M_GetText("Don't leave yet -- there's a\nsuper emerald around that corner!\n\n(Press 'Y' to quit)"); - quitmsg[QUITMSG6] = M_GetText("You'd rather work than play?\n\n(Press 'Y' to quit)"); - quitmsg[QUITMSG7] = M_GetText("Go ahead and leave. See if I care...\n*sniffle*\n\n(Press 'Y' to quit)"); - - quitmsg[QUIT2MSG] = M_GetText("If you leave now,\nEggman will take over the world!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT2MSG1] = M_GetText("On your mark,\nget set,\nhit the 'N' key!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT2MSG2] = M_GetText("Aw c'mon, just\na few more laps!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT2MSG3] = M_GetText("Did you get all those Chaos Emeralds?\n\n(Press 'Y' to quit)"); - quitmsg[QUIT2MSG4] = M_GetText("If you leave, I'll use\nmy Jawz on you!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT2MSG5] = M_GetText("Don't go!\nYou might find the hidden\nlevels!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT2MSG6] = M_GetText("Hit the 'N' key, Sonic!\nThe 'N' key!\n\n(Press 'Y' to quit)"); - - quitmsg[QUIT3MSG] = M_GetText("Are you really going to give up?\nWe certainly would never give you up.\n\n(Press 'Y' to quit)"); - quitmsg[QUIT3MSG1] = M_GetText("Come on, just ONE more netgame!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT3MSG2] = M_GetText("Press 'N' to unlock\nthe Golden Kart!\n\n(Press 'Y' to quit)"); - quitmsg[QUIT3MSG3] = M_GetText("Couldn't handle\nthe banana meta?\n\n(Press 'Y' to quit)"); - quitmsg[QUIT3MSG4] = M_GetText("Every time you press 'Y', an\nSRB2Kart Developer cries...\n\n(Press 'Y' to quit)"); - quitmsg[QUIT3MSG5] = M_GetText("You'll be back to play soon, though...\n...right?\n\n(Press 'Y' to quit)"); - quitmsg[QUIT3MSG6] = M_GetText("Aww, is Eggman's Nightclub too\ndifficult for you?\n\n(Press 'Y' to quit)"); - - // Setup PlayerMenu table - for (i = 0; i < MAXSKINS; i++) - { - PlayerMenu[i].status = (i == 0 ? IT_CALL : IT_DISABLED); - PlayerMenu[i].patch = PlayerMenu[i].text = NULL; - PlayerMenu[i].itemaction = M_ChoosePlayer; - PlayerMenu[i].mvar1 = 0; - } - -#ifdef HWRENDER - // Permanently hide some options based on render mode - if (rendermode == render_soft) - OP_VideoOptionsMenu[op_video_ogl].status = - OP_VideoOptionsMenu[op_video_kartman].status = - OP_VideoOptionsMenu[op_video_md2] .status = IT_DISABLED; -#endif - -#ifndef NONET - CV_RegisterVar(&cv_serversort); -#endif - - //todo put this somewhere better... - CV_RegisterVar(&cv_allcaps); -} - -void M_InitCharacterTables(void) -{ - UINT8 i; - - // Setup PlayerMenu table - for (i = 0; i < MAXSKINS; i++) - { - PlayerMenu[i].status = (i < 4 ? IT_CALL : IT_DISABLED); - PlayerMenu[i].patch = PlayerMenu[i].text = NULL; - PlayerMenu[i].itemaction = M_ChoosePlayer; - PlayerMenu[i].mvar1 = 0; - } - - // Setup description table - for (i = 0; i < MAXSKINS; i++) - { - if (i == 0) - { - strcpy(description[i].notes, "\x82Sonic\x80 is the fastest of the three, but also the hardest to control. Beginners beware, but experts will find Sonic very powerful.\n\n\x82""Ability:\x80 Speed Thok\nDouble jump to zoom forward with a huge burst of speed.\n\n\x82Tip:\x80 Simply letting go of forward does not slow down in SRB2. To slow down, hold the opposite direction."); - strcpy(description[i].picname, ""); - strcpy(description[i].skinname, "sonic"); - } - else if (i == 1) - { - strcpy(description[i].notes, "\x82Tails\x80 is the most mobile of the three, but has the slowest speed. Because of his mobility, he's well-\nsuited to beginners.\n\n\x82""Ability:\x80 Fly\nDouble jump to start flying for a limited time. Repetitively hit the jump button to ascend.\n\n\x82Tip:\x80 To quickly descend while flying, hit the spin button."); - strcpy(description[i].picname, ""); - strcpy(description[i].skinname, "tails"); - } - else if (i == 2) - { - strcpy(description[i].notes, "\x82Knuckles\x80 is well-\nrounded and can destroy breakable walls simply by touching them, but he can't jump as high as the other two.\n\n\x82""Ability:\x80 Glide & Climb\nDouble jump to glide in the air as long as jump is held. Glide into a wall to climb it.\n\n\x82Tip:\x80 Press spin while climbing to jump off the wall; press jump instead to jump off\nand face away from\nthe wall."); - strcpy(description[i].picname, ""); - strcpy(description[i].skinname, "knuckles"); - } - else if (i == 3) - { - strcpy(description[i].notes, "\x82Sonic & Tails\x80 team up to take on Dr. Eggman!\nControl Sonic while Tails desperately struggles to keep up.\n\nPlayer 2 can control Tails directly by setting the controls in the options menu.\nTails's directional controls are relative to Player 1's camera.\n\nTails can pick up Sonic while flying and carry him around."); - strcpy(description[i].picname, "CHRS&T"); - strcpy(description[i].skinname, "sonic&tails"); - } - else - { - strcpy(description[i].notes, "???"); - strcpy(description[i].picname, ""); - strcpy(description[i].skinname, ""); - } - } -} - -// ========================================================================== -// SPECIAL MENU OPTION DRAW ROUTINES GO HERE -// ========================================================================== - -// Converts a string into question marks. -// Used for the secrets menu, to hide yet-to-be-unlocked stuff. -static const char *M_CreateSecretMenuOption(const char *str) -{ - static char qbuf[32]; - int i; - - for (i = 0; i < 31; ++i) - { - if (!str[i]) - { - qbuf[i] = '\0'; - return qbuf; - } - else if (str[i] != ' ') - qbuf[i] = '?'; - else - qbuf[i] = ' '; - } - - qbuf[31] = '\0'; - return qbuf; -} - -static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv) -{ - INT32 xx = x, i; - lumpnum_t leftlump, rightlump, centerlump[2], cursorlump; - patch_t *p; - - leftlump = W_GetNumForName("M_THERML"); - rightlump = W_GetNumForName("M_THERMR"); - centerlump[0] = W_GetNumForName("M_THERMM"); - centerlump[1] = W_GetNumForName("M_THERMM"); - cursorlump = W_GetNumForName("M_THERMO"); - - V_DrawScaledPatch(xx, y, 0, p = W_CachePatchNum(leftlump,PU_CACHE)); - xx += SHORT(p->width) - SHORT(p->leftoffset); - for (i = 0; i < 16; i++) - { - V_DrawScaledPatch(xx, y, V_WRAPX, W_CachePatchNum(centerlump[i & 1], PU_CACHE)); - xx += 8; - } - V_DrawScaledPatch(xx, y, 0, W_CachePatchNum(rightlump, PU_CACHE)); - - xx = (cv->value - cv->PossibleValue[0].value) * (15*8) / - (cv->PossibleValue[1].value - cv->PossibleValue[0].value); - - V_DrawScaledPatch((x + 8) + xx, y, 0, W_CachePatchNum(cursorlump, PU_CACHE)); -} - -// A smaller 'Thermo', with range given as percents (0-100) -static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop) -{ - INT32 i; - INT32 range; - patch_t *p; - - for (i = 0; cv->PossibleValue[i+1].strvalue; i++); - - x = BASEVIDWIDTH - x - SLIDER_WIDTH; - - if (ontop) - { - V_DrawCharacter(x - 16 - (skullAnimCounter/5), y, - '\x1C' | highlightflags, false); // left arrow - V_DrawCharacter(x+(SLIDER_RANGE*8) + 8 + (skullAnimCounter/5), y, - '\x1D' | highlightflags, false); // right arrow - } - - if ((range = atoi(cv->defaultvalue)) != cv->value) - { - range = ((range - cv->PossibleValue[0].value) * 100 / - (cv->PossibleValue[1].value - cv->PossibleValue[0].value)); - - if (range < 0) - range = 0; - if (range > 100) - range = 100; - - // draw the default - p = W_CachePatchName("M_SLIDEC", PU_CACHE); - V_DrawScaledPatch(x - 4 + (((SLIDER_RANGE)*8 + 4)*range)/100, y, 0, p); - } - - V_DrawScaledPatch(x - 8, y, 0, W_CachePatchName("M_SLIDEL", PU_CACHE)); - - p = W_CachePatchName("M_SLIDEM", PU_CACHE); - for (i = 0; i < SLIDER_RANGE; i++) - V_DrawScaledPatch (x+i*8, y, 0,p); - - p = W_CachePatchName("M_SLIDER", PU_CACHE); - V_DrawScaledPatch(x+SLIDER_RANGE*8, y, 0, p); - - range = ((cv->value - cv->PossibleValue[0].value) * 100 / - (cv->PossibleValue[1].value - cv->PossibleValue[0].value)); - - if (range < 0) - range = 0; - if (range > 100) - range = 100; - - // draw the slider cursor - p = W_CachePatchName("M_SLIDEC", PU_CACHE); - V_DrawScaledPatch(x - 4 + (((SLIDER_RANGE)*8 + 4)*range)/100, y, 0, p); -} - -// -// Draw a textbox, like Quake does, because sometimes it's difficult -// to read the text with all the stuff in the background... -// -void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines) -{ - // Solid color textbox. - V_DrawFill(x+5, y+5, width*8+6, boxlines*8+6, 159); - //V_DrawFill(x+8, y+8, width*8, boxlines*8, 31); -/* - patch_t *p; - INT32 cx, cy, n; - INT32 step, boff; - - step = 8; - boff = 8; - - // draw left side - cx = x; - cy = y; - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_TL], PU_CACHE)); - cy += boff; - p = W_CachePatchNum(viewborderlump[BRDR_L], PU_CACHE); - for (n = 0; n < boxlines; n++) - { - V_DrawScaledPatch(cx, cy, V_WRAPY, p); - cy += step; - } - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_BL], PU_CACHE)); - - // draw middle - V_DrawFlatFill(x + boff, y + boff, width*step, boxlines*step, st_borderpatchnum); - - cx += boff; - cy = y; - while (width > 0) - { - V_DrawScaledPatch(cx, cy, V_WRAPX, W_CachePatchNum(viewborderlump[BRDR_T], PU_CACHE)); - V_DrawScaledPatch(cx, y + boff + boxlines*step, V_WRAPX, W_CachePatchNum(viewborderlump[BRDR_B], PU_CACHE)); - width--; - cx += step; - } - - // draw right side - cy = y; - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_TR], PU_CACHE)); - cy += boff; - p = W_CachePatchNum(viewborderlump[BRDR_R], PU_CACHE); - for (n = 0; n < boxlines; n++) - { - V_DrawScaledPatch(cx, cy, V_WRAPY, p); - cy += step; - } - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_BR], PU_CACHE)); -*/ -} - -// -// Draw border for the savegame description -// -/*static void M_DrawSaveLoadBorder(INT32 x,INT32 y) -{ - INT32 i; - - V_DrawScaledPatch (x-8,y+7,0,W_CachePatchName("M_LSLEFT",PU_CACHE)); - - for (i = 0;i < 24;i++) - { - V_DrawScaledPatch (x,y+7,0,W_CachePatchName("M_LSCNTR",PU_CACHE)); - x += 8; - } - - V_DrawScaledPatch (x,y+7,0,W_CachePatchName("M_LSRGHT",PU_CACHE)); -}*/ - -// horizontally centered text -static void M_CentreText(INT32 y, const char *string) -{ - INT32 x; - //added : 02-02-98 : centre on 320, because V_DrawString centers on vid.width... - x = (BASEVIDWIDTH - V_StringWidth(string, V_OLDSPACING))>>1; - V_DrawString(x,y,V_OLDSPACING,string); -} - -// -// M_DrawMapEmblems -// -// used by pause & statistics to draw a row of emblems for a map -// -static void M_DrawMapEmblems(INT32 mapnum, INT32 x, INT32 y) -{ - UINT8 lasttype = UINT8_MAX, curtype; - emblem_t *emblem = M_GetLevelEmblems(mapnum); - - while (emblem) - { - switch (emblem->type) - { - case ET_TIME: //case ET_SCORE: case ET_RINGS: - curtype = 1; break; - /*case ET_NGRADE: case ET_NTIME: - curtype = 2; break;*/ - default: - curtype = 0; break; - } - - // Shift over if emblem is of a different discipline - if (lasttype != UINT8_MAX && lasttype != curtype) - x -= 4; - lasttype = curtype; - - if (emblem->collected) - V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE)); - else - V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); - - emblem = M_GetLevelEmblems(-1); - x -= 8; - } -} - -static void M_DrawMenuTitle(void) -{ - if (currentMenu->menutitlepic) - { - patch_t *p = W_CachePatchName(currentMenu->menutitlepic, PU_CACHE); - - if (p->height > 24) // title is larger than normal - { - INT32 xtitle = (BASEVIDWIDTH - (SHORT(p->width)/2))/2; - INT32 ytitle = (30 - (SHORT(p->height)/2))/2; - - if (xtitle < 0) - xtitle = 0; - if (ytitle < 0) - ytitle = 0; - - V_DrawSmallScaledPatch(xtitle, ytitle, 0, p); - } - else - { - INT32 xtitle = (BASEVIDWIDTH - SHORT(p->width))/2; - INT32 ytitle = (30 - SHORT(p->height))/2; - - if (xtitle < 0) - xtitle = 0; - if (ytitle < 0) - ytitle = 0; - - V_DrawScaledPatch(xtitle, ytitle, 0, p); - } - } -} - -static void M_DrawKartGamemodeMenu(void) -{ - INT32 i; - - V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("MENUHINT", PU_CACHE), NULL); - V_DrawCenteredThinString(BASEVIDWIDTH/2, 12, V_ALLOWLOWERCASE|V_6WIDTHSPACE, "Configure your controls, settings, and preferences."); - - V_DrawFixedPatch(172<numitems; i++) - { - switch (currentMenu->menuitems[i].status & IT_DISPLAY) - { - case IT_STRING: - V_DrawRightAlignedGamemodeString(170, currentMenu->menuitems[i].mvar1, 0, currentMenu->menuitems[i].text, - (i == itemOn) ? SKINCOLOR_PLAGUE : SKINCOLOR_PIGEON); - break; - } - } -} - -static void M_DrawGenericMenu(void) -{ - INT32 x, y, w, i, cursory = 0; - - // DRAW MENU - x = currentMenu->x; - y = currentMenu->y; - - // draw title (or big pic) - M_DrawMenuTitle(); - - for (i = 0; i < currentMenu->numitems; i++) - { - if (i == itemOn) - cursory = y; - switch (currentMenu->menuitems[i].status & IT_DISPLAY) - { - case IT_PATCH: - if (currentMenu->menuitems[i].patch && currentMenu->menuitems[i].patch[0]) - { - if (currentMenu->menuitems[i].status & IT_CENTER) - { - patch_t *p; - p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); - V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p); - } - else - { - V_DrawScaledPatch(x, y, 0, - W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE)); - } - } - /* FALLTHRU */ - case IT_NOTHING: - case IT_DYBIGSPACE: - y = currentMenu->y+currentMenu->menuitems[i].mvar1;//+= LINEHEIGHT; - break; - case IT_BIGSLIDER: - M_DrawThermo(x, y, (consvar_t *)currentMenu->menuitems[i].itemaction); - y += LINEHEIGHT; - break; - case IT_STRING: - case IT_WHITESTRING: - if (currentMenu->menuitems[i].mvar1) - y = currentMenu->y+currentMenu->menuitems[i].mvar1; - if (i == itemOn) - cursory = y; - - if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) - V_DrawString(x, y, 0, currentMenu->menuitems[i].text); - else - V_DrawString(x, y, highlightflags, currentMenu->menuitems[i].text); - - // Cvar specific handling - switch (currentMenu->menuitems[i].status & IT_TYPE) - case IT_CVAR: - { - consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; - char asterisks[MAXSTRINGLENGTH+1]; - size_t sl; - switch (currentMenu->menuitems[i].status & IT_CVARTYPE) - { - case IT_CV_SLIDER: - M_DrawSlider(x, y, cv, (i == itemOn)); - case IT_CV_NOPRINT: // color use this - case IT_CV_INVISSLIDER: // monitor toggles use this - break; - case IT_CV_PASSWORD: - if (i == itemOn) - { - V_DrawRightAlignedThinString(x + MAXSTRINGLENGTH*8 + 10, y, V_ALLOWLOWERCASE, va(M_GetText("Tab: %s password"), cv->value ? "hide" : "show")); - } - - if (!cv->value || i != itemOn) - { - sl = strlen(cv->string); - memset(asterisks, '*', sl); - memset(asterisks + sl, 0, MAXSTRINGLENGTH+1-sl); - - M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); - V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, asterisks); - if (skullAnimCounter < 4 && i == itemOn) - V_DrawCharacter(x + 8 + V_StringWidth(asterisks, 0), y + 12, - '_' | 0x80, false); - y += 16; - break; - } - /* fallthru */ - case IT_CV_STRING: - M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); - V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string); - if (skullAnimCounter < 4 && i == itemOn) - V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 12, - '_' | 0x80, false); - y += 16; - break; - default: - w = V_StringWidth(cv->string, 0); - V_DrawString(BASEVIDWIDTH - x - w, y, - ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? warningflags : highlightflags), cv->string); - if (i == itemOn) - { - V_DrawCharacter(BASEVIDWIDTH - x - 10 - w - (skullAnimCounter/5), y, - '\x1C' | highlightflags, false); // left arrow - V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, - '\x1D' | highlightflags, false); // right arrow - } - break; - } - break; - } - y += STRINGHEIGHT; - break; - case IT_STRING2: - V_DrawString(x, y, 0, currentMenu->menuitems[i].text); - /* FALLTHRU */ - case IT_DYLITLSPACE: - y += SMALLLINEHEIGHT; - break; - case IT_GRAYPATCH: - if (currentMenu->menuitems[i].patch && currentMenu->menuitems[i].patch[0]) - V_DrawMappedPatch(x, y, 0, - W_CachePatchName(currentMenu->menuitems[i].patch,PU_CACHE), graymap); - y += LINEHEIGHT; - break; - case IT_TRANSTEXT: - if (currentMenu->menuitems[i].mvar1) - y = currentMenu->y+currentMenu->menuitems[i].mvar1; - /* FALLTHRU */ - case IT_TRANSTEXT2: - V_DrawString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text); - y += SMALLLINEHEIGHT; - break; - case IT_QUESTIONMARKS: - if (currentMenu->menuitems[i].mvar1) - y = currentMenu->y+currentMenu->menuitems[i].mvar1; - - V_DrawString(x, y, V_TRANSLUCENT|V_OLDSPACING, M_CreateSecretMenuOption(currentMenu->menuitems[i].text)); - y += SMALLLINEHEIGHT; - break; - case IT_HEADERTEXT: // draws 16 pixels to the left, in yellow text - if (currentMenu->menuitems[i].mvar1) - y = currentMenu->y+currentMenu->menuitems[i].mvar1; - - V_DrawString(x-16, y, highlightflags, currentMenu->menuitems[i].text); - y += SMALLLINEHEIGHT; - break; - } - } - - // DRAW THE SKULL CURSOR - if (((currentMenu->menuitems[itemOn].status & IT_DISPLAY) == IT_PATCH) - || ((currentMenu->menuitems[itemOn].status & IT_DISPLAY) == IT_NOTHING)) - { - V_DrawScaledPatch(currentMenu->x + SKULLXOFF, cursory - 5, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); - } - else - { - V_DrawScaledPatch(currentMenu->x - 24, cursory, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); - V_DrawString(currentMenu->x, cursory, highlightflags, currentMenu->menuitems[itemOn].text); - } -} - -static void M_DrawPauseMenu(void) -{ -#if 0 - if (!netgame && !multiplayer && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING)) - { - emblem_t *emblem_detail[3] = {NULL, NULL, NULL}; - char emblem_text[3][20]; - INT32 i; - - M_DrawTextBox(27, 16, 32, 6); - - // Draw any and all emblems at the top. - M_DrawMapEmblems(gamemap, 272, 28); - - if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0) - { - if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) - V_DrawString(40, 28, highlightflags, va("%s %s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl, mapheaderinfo[gamemap-1]->actnum)); - else - V_DrawString(40, 28, highlightflags, va("%s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl)); - } - else - { - if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) - V_DrawString(40, 28, highlightflags, va("%s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum)); - else - V_DrawString(40, 28, highlightflags, mapheaderinfo[gamemap-1]->lvlttl); - } - - // Set up the detail boxes. - { - emblem_t *emblem = M_GetLevelEmblems(gamemap); - while (emblem) - { - INT32 emblemslot; - char targettext[9], currenttext[9]; - - switch (emblem->type) - { - /*case ET_SCORE: - snprintf(targettext, 9, "%d", emblem->var); - snprintf(currenttext, 9, "%u", G_GetBestScore(gamemap)); - - targettext[8] = 0; - currenttext[8] = 0; - - emblemslot = 0; - break;*/ - case ET_TIME: - emblemslot = emblem->var; // dumb hack - snprintf(targettext, 9, "%i:%02i.%02i", - G_TicsToMinutes((tic_t)emblemslot, false), - G_TicsToSeconds((tic_t)emblemslot), - G_TicsToCentiseconds((tic_t)emblemslot)); - - emblemslot = (INT32)G_GetBestTime(gamemap); // dumb hack pt ii - if ((tic_t)emblemslot == UINT32_MAX) - snprintf(currenttext, 9, "-:--.--"); - else - snprintf(currenttext, 9, "%i:%02i.%02i", - G_TicsToMinutes((tic_t)emblemslot, false), - G_TicsToSeconds((tic_t)emblemslot), - G_TicsToCentiseconds((tic_t)emblemslot)); - - targettext[8] = 0; - currenttext[8] = 0; - - emblemslot = 1; - break; - /*case ET_RINGS: - snprintf(targettext, 9, "%d", emblem->var); - snprintf(currenttext, 9, "%u", G_GetBestRings(gamemap)); - - targettext[8] = 0; - currenttext[8] = 0; - - emblemslot = 2; - break; - case ET_NGRADE: - snprintf(targettext, 9, "%u", P_GetScoreForGrade(gamemap, 0, emblem->var)); - snprintf(currenttext, 9, "%u", G_GetBestNightsScore(gamemap, 0)); - - targettext[8] = 0; - currenttext[8] = 0; - - emblemslot = 1; - break; - case ET_NTIME: - emblemslot = emblem->var; // dumb hack pt iii - snprintf(targettext, 9, "%i:%02i.%02i", - G_TicsToMinutes((tic_t)emblemslot, false), - G_TicsToSeconds((tic_t)emblemslot), - G_TicsToCentiseconds((tic_t)emblemslot)); - - emblemslot = (INT32)G_GetBestNightsTime(gamemap, 0); // dumb hack pt iv - if ((tic_t)emblemslot == UINT32_MAX) - snprintf(currenttext, 9, "-:--.--"); - else - snprintf(currenttext, 9, "%i:%02i.%02i", - G_TicsToMinutes((tic_t)emblemslot, false), - G_TicsToSeconds((tic_t)emblemslot), - G_TicsToCentiseconds((tic_t)emblemslot)); - - targettext[8] = 0; - currenttext[8] = 0; - - emblemslot = 2; - break;*/ - default: - goto bademblem; - } - if (emblem_detail[emblemslot]) - goto bademblem; - - emblem_detail[emblemslot] = emblem; - snprintf(emblem_text[emblemslot], 20, "%8s /%8s", currenttext, targettext); - emblem_text[emblemslot][19] = 0; - - bademblem: - emblem = M_GetLevelEmblems(-1); - } - } - for (i = 0; i < 3; ++i) - { - emblem_t *emblem = emblem_detail[i]; - if (!emblem) - continue; - - if (emblem->collected) - V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE)); - else - V_DrawSmallScaledPatch(40, 44 + (i*8), 0, W_CachePatchName("NEEDIT", PU_CACHE)); - - switch (emblem->type) - { - /*case ET_SCORE: - case ET_NGRADE: - V_DrawString(56, 44 + (i*8), highlightflags, "SCORE:"); - break;*/ - case ET_TIME: - //case ET_NTIME: - V_DrawString(56, 44 + (i*8), highlightflags, "TIME:"); - break; - /*case ET_RINGS: - V_DrawString(56, 44 + (i*8), highlightflags, "RINGS:"); - break;*/ - } - V_DrawRightAlignedString(284, 44 + (i*8), V_MONOSPACE, emblem_text[i]); - } - } -#endif - - M_DrawGenericMenu(); -} - -// -// M_StringHeight -// -// Find string height from hu_font chars -// -static inline size_t M_StringHeight(const char *string) -{ - size_t h = 8, i; - - for (i = 0; i < strlen(string); i++) - if (string[i] == '\n') - h += 8; - - return h; -} - -// ========================================================================== -// Extraneous menu patching functions -// ========================================================================== - -// -// M_PatchSkinNameTable -// -// Like M_PatchLevelNameTable, but for cv_chooseskin -// -static void M_PatchSkinNameTable(void) -{ - INT32 j; - - memset(skins_cons_t, 0, sizeof (skins_cons_t)); - - for (j = 0; j < MAXSKINS; j++) - { - if (skins[j].name[0] != '\0') - { - skins_cons_t[j].strvalue = skins[j].name; - skins_cons_t[j].value = j+1; - } - else - { - skins_cons_t[j].strvalue = NULL; - skins_cons_t[j].value = 0; - break; - } - } - - j = R_SkinAvailable(cv_skin.string); - if (j == -1) - j = 0; - - CV_SetValue(&cv_chooseskin, j+1); // This causes crash sometimes?! - - return; -} - -// Call before showing any level-select menus -static void M_PrepareLevelSelect(void) -{ - if (levellistmode != LLM_CREATESERVER) - CV_SetValue(&cv_nextmap, M_GetFirstLevelInList()); - else - Newgametype_OnChange(); // Make sure to start on an appropriate map if wads have been added -} - -// -// M_CanShowLevelInList -// -// Determines whether to show a given map in the various level-select lists. -// Set gt = -1 to ignore gametype. -// -boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) -{ - // Random map! - if (mapnum == -1) - return (currentMenu != &SP_TimeAttackDef && !modeattacking); - - // Does the map exist? - if (!mapheaderinfo[mapnum]) - return false; - - // Does the map have a name? - if (!mapheaderinfo[mapnum]->lvlttl[0]) - return false; - - switch (levellistmode) - { - case LLM_CREATESERVER: - // Should the map be hidden? - if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU && mapnum+1 != gamemap) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - /*if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP)) - return true; - - if (gt == GT_COMPETITION && (mapheaderinfo[mapnum]->typeoflevel & TOL_COMPETITION)) - return true; - - if (gt == GT_CTF && (mapheaderinfo[mapnum]->typeoflevel & TOL_CTF)) - return true; - - if ((gt == GT_TAG || gt == GT_HIDEANDSEEK) && (mapheaderinfo[mapnum]->typeoflevel & TOL_TAG)) - return true;*/ - - if ((gt == GT_MATCH || gt == GT_TEAMMATCH) && (mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH)) - return true; - - if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) - return true; - - return false; - - /*case LLM_LEVELSELECT: - if (mapheaderinfo[mapnum]->levelselect != maplistoption) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - return true;*/ - case LLM_RECORDATTACK: - /*if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) - return false;*/ - - if (!(mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - if (M_SecretUnlocked(SECRET_HELLATTACK)) - return true; // now you're in hell - - if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) - return false; // map hell - - /*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false;*/ - - return true; - /*case LLM_NIGHTSATTACK: - if (!(mapheaderinfo[mapnum]->menuflags & LF2_NIGHTSATTACK)) - return false; - - if (M_MapLocked(mapnum+1)) - return false; // not unlocked - - if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false; - - return true;*/ - default: - return false; - } - - // Hmm? Couldn't decide? - return false; -} - -static INT32 M_CountLevelsToShowInList(void) -{ - INT32 mapnum, count = 0; - - for (mapnum = 0; mapnum < NUMMAPS; mapnum++) - if (M_CanShowLevelInList(mapnum, -1)) - count++; - - return count; -} - -static INT32 M_GetFirstLevelInList(void) -{ - INT32 mapnum; - - for (mapnum = 0; mapnum < NUMMAPS; mapnum++) - if (M_CanShowLevelInList(mapnum, -1)) - return mapnum + 1; - - return 1; -} - -// ================================================== -// MESSAGE BOX (aka: a hacked, cobbled together menu) -// ================================================== -static void M_DrawMessageMenu(void); - -// Because this is just a hack-ish 'menu', I'm not putting this with the others -static menuitem_t MessageMenu[] = -{ - // TO HACK - {0,NULL, NULL, NULL,0} -}; - -menu_t MessageDef = -{ - NULL, // title - 1, // # of menu items - NULL, // previous menu (TO HACK) - MessageMenu, // menuitem_t -> - M_DrawMessageMenu, // drawing routine -> - 0, 0, // x, y (TO HACK) - 0, // lastOn, flags (TO HACK) - NULL -}; - - -void M_StartMessage(const char *string, void *routine, - menumessagetype_t itemtype) -{ - size_t max = 0, start = 0, i, strlines; - static char *message = NULL; - Z_Free(message); - message = Z_StrDup(string); - DEBFILE(message); - - // Rudementary word wrapping. - // Simple and effective. Does not handle nonuniform letter sizes, colors, etc. but who cares. - strlines = 0; - for (i = 0; message[i]; i++) - { - if (message[i] == ' ') - { - start = i; - max += 4; - } - else if (message[i] == '\n') - { - strlines = i; - start = 0; - max = 0; - continue; - } - else - max += 8; - - // Start trying to wrap if presumed length exceeds the screen width. - if (max >= BASEVIDWIDTH && start > 0) - { - message[start] = '\n'; - max -= (start-strlines)*8; - strlines = start; - start = 0; - } - } - - start = 0; - max = 0; - - M_StartControlPanel(); // can't put menuactive to true - - if (currentMenu == &MessageDef) // Prevent recursion - MessageDef.prevMenu = ((demo.playback) ? &PlaybackMenuDef : &MainDef); - else - MessageDef.prevMenu = currentMenu; - - MessageDef.menuitems[0].text = message; - MessageDef.menuitems[0].mvar1 = (UINT8)itemtype; - if (!routine && itemtype != MM_NOTHING) itemtype = MM_NOTHING; - switch (itemtype) - { - case MM_NOTHING: - MessageDef.menuitems[0].status = IT_MSGHANDLER; - MessageDef.menuitems[0].itemaction = M_StopMessage; - break; - case MM_YESNO: - MessageDef.menuitems[0].status = IT_MSGHANDLER; - MessageDef.menuitems[0].itemaction = routine; - break; - case MM_EVENTHANDLER: - MessageDef.menuitems[0].status = IT_MSGHANDLER; - MessageDef.menuitems[0].itemaction = routine; - break; - } - //added : 06-02-98: now draw a textbox around the message - // compute lenght max and the numbers of lines - for (strlines = 0; *(message+start); strlines++) - { - for (i = 0;i < strlen(message+start);i++) - { - if (*(message+start+i) == '\n') - { - if (i > max) - max = i; - start += i; - i = (size_t)-1; //added : 07-02-98 : damned! - start++; - break; - } - } - - if (i == strlen(message+start)) - start += i; - } - - MessageDef.x = (INT16)((BASEVIDWIDTH - 8*max-16)/2); - MessageDef.y = (INT16)((BASEVIDHEIGHT - M_StringHeight(message))/2); - - MessageDef.lastOn = (INT16)((strlines<<8)+max); - - //M_SetupNextMenu(); - currentMenu = &MessageDef; - itemOn = 0; -} - -#define MAXMSGLINELEN 256 - -static void M_DrawMessageMenu(void) -{ - INT32 y = currentMenu->y; - size_t i, start = 0; - INT16 max; - char string[MAXMSGLINELEN]; - INT32 mlines; - const char *msg = currentMenu->menuitems[0].text; - - mlines = currentMenu->lastOn>>8; - max = (INT16)((UINT8)(currentMenu->lastOn & 0xFF)*8); - - // hack: draw background in menus - if (gamestate == GS_MENU) - V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); - - M_DrawTextBox(currentMenu->x, y - 8, (max+7)>>3, mlines); - - while (*(msg+start)) - { - size_t len = strlen(msg+start); - - for (i = 0; i < len; i++) - { - if (*(msg+start+i) == '\n') - { - memset(string, 0, MAXMSGLINELEN); - if (i >= MAXMSGLINELEN) - { - CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg); - return; - } - else - { - strncpy(string,msg+start, i); - string[i] = '\0'; - start += i; - i = (size_t)-1; //added : 07-02-98 : damned! - start++; - } - break; - } - } - - if (i == strlen(msg+start)) - { - if (i >= MAXMSGLINELEN) - { - CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg); - return; - } - else - { - strcpy(string, msg + start); - start += i; - } - } - - V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string); - y += 8; //SHORT(hu_font[0]->height); - } -} - -// default message handler -static void M_StopMessage(INT32 choice) -{ - (void)choice; - if (menuactive) - M_SetupNextMenu(MessageDef.prevMenu); -} - -// ========= -// IMAGEDEFS -// ========= - -// Draw an Image Def. Aka, Help images. -// Defines what image is used in (menuitem_t)->text. -// You can even put multiple images in one menu! -static void M_DrawImageDef(void) -{ - // this is probably what the V_DrawFixedPatch screen-fill bullshit was for, right - //V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); -- never mind, screen fade - - // Grr. Need to autodetect for pic_ts. - pic_t *pictest = (pic_t *)W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE); - if (!pictest->zero) - V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].text)); - else - { - patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].text,PU_CACHE); - if (patch->height <= BASEVIDHEIGHT) - V_DrawScaledPatch(0,0,0,patch); - else - V_DrawSmallScaledPatch(0,0,0,patch); - } - - if (currentMenu->menuitems[itemOn].mvar1) - { - V_DrawString(2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", (itemOn<<1)-1)); // intentionally not highlightflags, unlike below - V_DrawRightAlignedString(BASEVIDWIDTH-2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", itemOn<<1)); // ditto - } - else - { - INT32 x = BASEVIDWIDTH>>1, y = (BASEVIDHEIGHT>>1) - 4; - x += (itemOn ? 1 : -1)*((BASEVIDWIDTH>>2) + 10); - V_DrawCenteredString(x, y-10, highlightflags, "USE ARROW KEYS"); - V_DrawCharacter(x - 10 - (skullAnimCounter/5), y, - '\x1C' | highlightflags, false); // left arrow - V_DrawCharacter(x + 2 + (skullAnimCounter/5), y, - '\x1D' | highlightflags, false); // right arrow - V_DrawCenteredString(x, y+10, highlightflags, "TO LEAF THROUGH"); - } -} - -// Handles the ImageDefs. Just a specialized function that -// uses left and right movement. -static void M_HandleImageDef(INT32 choice) -{ - boolean exitmenu = false; - - switch (choice) - { - case KEY_RIGHTARROW: - if (itemOn >= (INT16)(currentMenu->numitems-1)) - break; - S_StartSound(NULL, sfx_menu1); - itemOn++; - break; - - case KEY_LEFTARROW: - if (!itemOn) - break; - - S_StartSound(NULL, sfx_menu1); - itemOn--; - break; - - case KEY_ESCAPE: - case KEY_ENTER: - exitmenu = true; - break; - } - - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} - -// ====================== -// MISC MAIN MENU OPTIONS -// ====================== - -static void M_AddonsOptions(INT32 choice) -{ - (void)choice; - Addons_option_Onchange(); - - M_SetupNextMenu(&OP_AddonsOptionsDef); -} - -#define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!" -#define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make add-ons!" - -static void M_Addons(INT32 choice) -{ - const char *pathname = "."; - - (void)choice; - -#if 1 - if (cv_addons_option.value == 0) - pathname = usehome ? srb2home : srb2path; - else if (cv_addons_option.value == 1) - pathname = srb2home; - else if (cv_addons_option.value == 2) - pathname = srb2path; - else -#endif - if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0') - pathname = cv_addons_folder.string; - - strlcpy(menupath, pathname, 1024); - menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1; - - if (menupath[menupathindex[menudepthleft]-2] != PATHSEP[0]) - { - menupath[menupathindex[menudepthleft]-1] = PATHSEP[0]; - menupath[menupathindex[menudepthleft]] = 0; - } - else - --menupathindex[menudepthleft]; - - if (!preparefilemenu(false, false)) - { - M_StartMessage(va("No files/folders found.\n\n%s\n\n(Press a key)\n", (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)),NULL,MM_NOTHING); - return; - } - else - dir_on[menudepthleft] = 0; - - if (addonsp[0]) // never going to have some provided but not all, saves individually checking - { - size_t i; - for (i = 0; i < NUM_EXT+5; i++) - W_UnlockCachedPatch(addonsp[i]); - } - - addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC); - addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC); - addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_STATIC); - addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC); - addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC); - addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC); -#ifdef USE_KART - addonsp[EXT_KART] = W_CachePatchName("M_FKART", PU_STATIC); -#endif - addonsp[EXT_PK3] = W_CachePatchName("M_FPK3", PU_STATIC); - addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC); - addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC); - addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_STATIC); - addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL", PU_STATIC); - addonsp[NUM_EXT+2] = W_CachePatchName("M_FLOAD", PU_STATIC); - addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_STATIC); - addonsp[NUM_EXT+4] = W_CachePatchName("M_FSAVE", PU_STATIC); - - EX_AddonsDef.prevMenu = currentMenu; - M_SetupNextMenu(&EX_AddonsDef); -} - -#define width 4 -#define vpadding 27 -#define h (BASEVIDHEIGHT-(2*vpadding)) -#define NUMCOLOURS 8 // when toast's coding it's british english hacker fucker -static void M_DrawTemperature(INT32 x, fixed_t t) -{ - INT32 y; - - // bounds check - if (t > FRACUNIT) - t = FRACUNIT; - /*else if (t < 0) -- not needed - t = 0;*/ - - // scale - if (t > 1) - t = (FixedMul(h<>FRACBITS); - - // border - V_DrawFill(x - 1, vpadding, 1, h, 0); - V_DrawFill(x + width, vpadding, 1, h, 0); - V_DrawFill(x - 1, vpadding-1, width+2, 1, 0); - V_DrawFill(x - 1, vpadding+h, width+2, 1, 0); - - // bar itself - y = h; - if (t) - for (t = h - t; y > 0; y--) - { - UINT8 colours[NUMCOLOURS] = {135, 133, 92, 77, 114, 178, 161, 162}; - UINT8 c; - if (y <= t) break; - if (y+vpadding >= BASEVIDHEIGHT/2) - c = 185; - else - c = colours[(NUMCOLOURS*(y-1))/(h/2)]; - V_DrawFill(x, y-1 + vpadding, width, 1, c); - } - - // fill the rest of the backing - if (y) - V_DrawFill(x, vpadding, width, y, 30); -} -#undef width -#undef vpadding -#undef h -#undef NUMCOLOURS - -static char *M_AddonsHeaderPath(void) -{ - UINT32 len; - static char header[1024]; - - strlcpy(header, va("%s folder%s", cv_addons_option.string, menupath+menupathindex[menudepth-1]-1), 1024); - len = strlen(header); - if (len > 34) - { - len = len-34; - header[len] = header[len+1] = header[len+2] = '.'; - } - else - len = 0; - - return header+len; -} - -#define UNEXIST S_StartSound(NULL, sfx_s26d);\ - M_SetupNextMenu(EX_AddonsDef.prevMenu);\ - M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING) - -#define CLEARNAME Z_Free(refreshdirname);\ - refreshdirname = NULL - -static boolean prevmajormods = false; - -static void M_AddonsClearName(INT32 choice) -{ - if (!majormods || prevmajormods) - { - CLEARNAME; - } - M_StopMessage(choice); -} - -// returns whether to do message draw -static boolean M_AddonsRefresh(void) -{ - if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true, false)) - { - UNEXIST; - if (refreshdirname) - { - CLEARNAME; - } - return true; - } - - if (!majormods && prevmajormods) - prevmajormods = false; - - if ((refreshdirmenu & REFRESHDIR_ADDFILE) || (majormods && !prevmajormods)) - { - char *message = NULL; - - if (refreshdirmenu & REFRESHDIR_NOTLOADED) - { - S_StartSound(NULL, sfx_s26d); - if (refreshdirmenu & REFRESHDIR_MAX) - message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you wish to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); - else - message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); - } - else if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR)) - { - S_StartSound(NULL, sfx_s224); - message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")); - } - else if (majormods && !prevmajormods) - { - S_StartSound(NULL, sfx_s221); - message = va("%c%s\x80\nGameplay has now been modified.\nIf you wish to play Record Attack mode, restart the game to clear existing add-ons.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); - prevmajormods = majormods; - } - - if (message) - { - M_StartMessage(message,M_AddonsClearName,MM_EVENTHANDLER); - return true; - } - - S_StartSound(NULL, sfx_s221); - CLEARNAME; - } - - return false; -} - -static void M_DrawAddons(void) -{ - INT32 x, y; - ssize_t i, m; - const UINT8 *flashcol = NULL; - UINT8 hilicol; - - // hack - need to refresh at end of frame to handle addfile... - if (refreshdirmenu & M_AddonsRefresh()) - { - M_DrawMessageMenu(); - return; - } - - if (Playing()) - V_DrawCenteredString(BASEVIDWIDTH/2, 5, warningflags, "Adding files mid-game may cause problems."); - else - V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)); - - if (numwadfiles <= mainwads+1) - y = 0; - else if (numwadfiles >= MAX_WADFILES) - y = FRACUNIT; - else - { - y = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))< FRACUNIT) // happens because of how we're shrinkin' it a little - y = FRACUNIT; - } - - M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y); - - // DRAW MENU - x = currentMenu->x; - y = currentMenu->y + 1; - - hilicol = V_GetStringColormap(highlightflags)[0]; - - V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), highlightflags|V_ALLOWLOWERCASE, M_AddonsHeaderPath()); - V_DrawFill(x-21, (y - 16) + (lsheadingheight - 3), MAXSTRINGLENGTH*8+6, 1, hilicol); - V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 30); - - m = (BASEVIDHEIGHT - currentMenu->y + 2) - (y - 1); - V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, m, 159); - - // scrollbar! - if (sizedirmenu <= (2*numaddonsshown + 1)) - i = 0; - else - { - ssize_t q = m; - m = ((2*numaddonsshown + 1) * m)/sizedirmenu; - if (dir_on[menudepthleft] <= numaddonsshown) // all the way up - i = 0; - else if (sizedirmenu <= (dir_on[menudepthleft] + numaddonsshown + 1)) // all the way down - i = q-m; - else - i = ((dir_on[menudepthleft] - numaddonsshown) * (q-m))/(sizedirmenu - (2*numaddonsshown + 1)); - } - - V_DrawFill(x + MAXSTRINGLENGTH*8+5 - 21, (y - 1) + i, 1, m, hilicol); - - // get bottom... - m = dir_on[menudepthleft] + numaddonsshown + 1; - if (m > (ssize_t)sizedirmenu) - m = sizedirmenu; - - // then compute top and adjust bottom if needed! - if (m < (2*numaddonsshown + 1)) - { - m = min(sizedirmenu, 2*numaddonsshown + 1); - i = 0; - } - else - i = m - (2*numaddonsshown + 1); - - if (i != 0) - V_DrawString(19, y+4 - (skullAnimCounter/5), highlightflags, "\x1A"); - - if (skullAnimCounter < 4) - flashcol = V_GetStringColormap(highlightflags); - - for (; i < m; i++) - { - UINT32 flags = V_ALLOWLOWERCASE; - if (y > BASEVIDHEIGHT) break; - if (dirmenu[i]) -#define type (UINT8)(dirmenu[i][DIR_TYPE]) - { - if (type & EXT_LOADED) - { - flags |= V_TRANSLUCENT; - V_DrawSmallScaledPatch(x-(16+4), y, V_TRANSLUCENT, addonsp[(type & ~EXT_LOADED)]); - V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+2]); - } - else - V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[(type & ~EXT_LOADED)]); - - if ((size_t)i == dir_on[menudepthleft]) - { - V_DrawFixedPatch((x-(16+4))< (charsonside*2 + 3)) - V_DrawString(x, y+4, flags, va("%.*s...%s", charsonside, dirmenu[i]+DIR_STRING, dirmenu[i]+DIR_STRING+dirmenu[i][DIR_LEN]-(charsonside+1))); -#undef charsonside - else - V_DrawString(x, y+4, flags, dirmenu[i]+DIR_STRING); - } -#undef type - y += 16; - } - - if (m != (ssize_t)sizedirmenu) - V_DrawString(19, y-12 + (skullAnimCounter/5), highlightflags, "\x1B"); - - y = BASEVIDHEIGHT - currentMenu->y + 1; - - M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1); - if (menusearch[0]) - V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1); - else - V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Type to search..."); - if (skullAnimCounter < 4) - V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8, - '_' | 0x80, false); - - x -= (21 + 5 + 16); - V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+3]); - - x = BASEVIDWIDTH - x - 16; - V_DrawSmallScaledPatch(x, y + 4, ((!majormods) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); - - if (modifiedgame) - V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]); -} - -static void M_AddonExec(INT32 ch) -{ - if (ch != 'y' && ch != KEY_ENTER) - return; - - S_StartSound(NULL, sfx_zoom); - COM_BufAddText(va("exec \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); -} - -#define len menusearch[0] -static boolean M_ChangeStringAddons(INT32 choice) -{ - if (shiftdown && choice >= 32 && choice <= 127) - choice = shiftxform[choice]; - - switch (choice) - { - case KEY_DEL: - if (len) - { - len = menusearch[1] = 0; - return true; - } - break; - case KEY_BACKSPACE: - if (len) - { - menusearch[1+--len] = 0; - return true; - } - break; - default: - if (choice >= 32 && choice <= 127) - { - if (len < MAXSTRINGLENGTH - 1) - { - menusearch[1+len++] = (char)choice; - menusearch[1+len] = 0; - return true; - } - } - break; - } - return false; -} -#undef len - -static void M_HandleAddons(INT32 choice) -{ - boolean exitmenu = false; // exit to previous menu - - if (M_ChangeStringAddons(choice)) - { - char *tempname = NULL; - if (dirmenu && dirmenu[dir_on[menudepthleft]]) - tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL -#if 0 // much slower - if (!preparefilemenu(true, false)) - { - UNEXIST; - return; - } -#else // streamlined - searchfilemenu(tempname); -#endif - } - - switch (choice) - { - case KEY_DOWNARROW: - if (dir_on[menudepthleft] < sizedirmenu-1) - dir_on[menudepthleft]++; - S_StartSound(NULL, sfx_menu1); - break; - case KEY_UPARROW: - if (dir_on[menudepthleft]) - dir_on[menudepthleft]--; - S_StartSound(NULL, sfx_menu1); - break; - case KEY_PGDN: - { - UINT8 i; - for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--) - dir_on[menudepthleft]++; - } - S_StartSound(NULL, sfx_menu1); - break; - case KEY_PGUP: - { - UINT8 i; - for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--) - dir_on[menudepthleft]--; - } - S_StartSound(NULL, sfx_menu1); - break; - case KEY_ENTER: - { - boolean refresh = true; - if (!dirmenu[dir_on[menudepthleft]]) - S_StartSound(NULL, sfx_s26d); - else - { - switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) - { - case EXT_FOLDER: - strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); - if (menudepthleft) - { - menupathindex[--menudepthleft] = strlen(menupath); - menupath[menupathindex[menudepthleft]] = 0; - - if (!preparefilemenu(false, false)) - { - S_StartSound(NULL, sfx_s224); - M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); - menupath[menupathindex[++menudepthleft]] = 0; - - if (!preparefilemenu(true, false)) - { - UNEXIST; - return; - } - } - else - { - S_StartSound(NULL, sfx_menu1); - dir_on[menudepthleft] = 1; - } - refresh = false; - } - else - { - S_StartSound(NULL, sfx_s26d); - M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); - menupath[menupathindex[menudepthleft]] = 0; - } - break; - case EXT_UP: - S_StartSound(NULL, sfx_menu1); - menupath[menupathindex[++menudepthleft]] = 0; - if (!preparefilemenu(false, false)) - { - UNEXIST; - return; - } - break; - case EXT_TXT: - M_StartMessage(va("%c%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO); - break; - case EXT_CFG: - M_AddonExec(KEY_ENTER); - break; - case EXT_LUA: -#ifndef HAVE_BLUA - S_StartSound(NULL, sfx_s26d); - M_StartMessage(va("%c%s\x80\nThis version of SRB2Kart does not\nhave support for .lua files.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING); - break; -#endif - // else intentional fallthrough - case EXT_SOC: - case EXT_WAD: -#ifdef USE_KART - case EXT_KART: -#endif - case EXT_PK3: - COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); - break; - default: - S_StartSound(NULL, sfx_s26d); - } - } - if (refresh) - refreshdirmenu |= REFRESHDIR_NORMAL; - } - break; - - case KEY_ESCAPE: - exitmenu = true; - break; - - default: - break; - } - - if (exitmenu) - { - closefilemenu(true); - - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} - -// ---- REPLAY HUT ----- -menudemo_t *demolist; - -#define DF_ENCORE 0x40 -static INT16 replayScrollTitle = 0; -static SINT8 replayScrollDelay = TICRATE, replayScrollDir = 1; - -static void PrepReplayList(void) -{ - size_t i; - - if (demolist) - Z_Free(demolist); - - demolist = Z_Calloc(sizeof(menudemo_t) * sizedirmenu, PU_STATIC, NULL); - - for (i = 0; i < sizedirmenu; i++) - { - if (dirmenu[i][DIR_TYPE] == EXT_UP) - { - demolist[i].type = MD_SUBDIR; - sprintf(demolist[i].title, "UP"); - } - else if (dirmenu[i][DIR_TYPE] == EXT_FOLDER) - { - demolist[i].type = MD_SUBDIR; - strncpy(demolist[i].title, dirmenu[i] + DIR_STRING, 64); - } - else - { - demolist[i].type = MD_NOTLOADED; - snprintf(demolist[i].filepath, 255, "%s%s", menupath, dirmenu[i] + DIR_STRING); - sprintf(demolist[i].title, "....."); - } - } -} - -void M_ReplayHut(INT32 choice) -{ - (void)choice; - - if (!demo.inreplayhut) - { - snprintf(menupath, 1024, "%s"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); - menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); - } - - if (!preparefilemenu(false, true)) - { - M_StartMessage("No replays found.\n\n(Press a key)\n", NULL, MM_NOTHING); - return; - } - else if (!demo.inreplayhut) - dir_on[menudepthleft] = 0; - - demo.inreplayhut = true; - - replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; - - PrepReplayList(); - M_SetupNextMenu(&EX_ReplayHutDef); - - demo.rewinding = false; -} - -static void M_HandleReplayHutList(INT32 choice) -{ - switch (choice) - { - case KEY_UPARROW: - if (dir_on[menudepthleft]) - dir_on[menudepthleft]--; - else - M_PrevOpt(); - - S_StartSound(NULL, sfx_menu1); - replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; - break; - - case KEY_DOWNARROW: - if (dir_on[menudepthleft] < sizedirmenu-1) - dir_on[menudepthleft]++; - else - itemOn = 0; // Not M_NextOpt because that would take us to the extra dummy item - - S_StartSound(NULL, sfx_menu1); - replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; - break; - - case KEY_ESCAPE: - M_QuitReplayHut(); - break; - - case KEY_ENTER: - switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) - { - case EXT_FOLDER: - strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); - if (menudepthleft) - { - menupathindex[--menudepthleft] = strlen(menupath); - menupath[menupathindex[menudepthleft]] = 0; - - if (!preparefilemenu(false, true)) - { - S_StartSound(NULL, sfx_s224); - M_StartMessage(va("%c%s\x80\nThis folder is empty.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); - menupath[menupathindex[++menudepthleft]] = 0; - - if (!preparefilemenu(true, true)) - { - M_QuitReplayHut(); - return; - } - } - else - { - S_StartSound(NULL, sfx_menu1); - dir_on[menudepthleft] = 1; - PrepReplayList(); - } - } - else - { - S_StartSound(NULL, sfx_s26d); - M_StartMessage(va("%c%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), M_AddonsHeaderPath()),NULL,MM_NOTHING); - menupath[menupathindex[menudepthleft]] = 0; - } - break; - case EXT_UP: - S_StartSound(NULL, sfx_menu1); - menupath[menupathindex[++menudepthleft]] = 0; - if (!preparefilemenu(false, true)) - { - M_QuitReplayHut(); - return; - } - PrepReplayList(); - break; - default: - // We can't just use M_SetupNextMenu because that'll run ReplayDef's quitroutine and boot us back to the title screen! - currentMenu->lastOn = itemOn; - currentMenu = &EX_ReplayStartDef; - - replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; - - switch (demolist[dir_on[menudepthleft]].addonstatus) - { - case DFILE_ERROR_CANNOTLOAD: - // Only show "Watch Replay Without Addons" - EX_ReplayStartMenu[0].status = IT_DISABLED; - EX_ReplayStartMenu[1].status = IT_CALL|IT_STRING; - //EX_ReplayStartMenu[1].mvar1 = 0; - EX_ReplayStartMenu[2].status = IT_DISABLED; - itemOn = 1; - break; - - case DFILE_ERROR_NOTLOADED: - case DFILE_ERROR_INCOMPLETEOUTOFORDER: - // Show "Load Addons and Watch Replay" and "Watch Replay Without Addons" - EX_ReplayStartMenu[0].status = IT_CALL|IT_STRING; - EX_ReplayStartMenu[1].status = IT_CALL|IT_STRING; - //EX_ReplayStartMenu[1].mvar1 = 10; - EX_ReplayStartMenu[2].status = IT_DISABLED; - itemOn = 0; - break; - - case DFILE_ERROR_EXTRAFILES: - case DFILE_ERROR_OUTOFORDER: - default: - // Show "Watch Replay" - EX_ReplayStartMenu[0].status = IT_DISABLED; - EX_ReplayStartMenu[1].status = IT_DISABLED; - EX_ReplayStartMenu[2].status = IT_CALL|IT_STRING; - //EX_ReplayStartMenu[2].mvar1 = 0; - itemOn = 2; - break; - } - } - - break; - } -} - -#define SCALEDVIEWWIDTH (vid.width/vid.dupx) -#define SCALEDVIEWHEIGHT (vid.height/vid.dupy) -static void DrawReplayHutReplayInfo(void) -{ - lumpnum_t lumpnum; - patch_t *patch; - UINT8 *colormap; - INT32 x, y, w, h; - - switch (demolist[dir_on[menudepthleft]].type) - { - case MD_NOTLOADED: - V_DrawCenteredString(160, 40, V_SNAPTOTOP, "Loading replay information..."); - break; - - case MD_INVALID: - V_DrawCenteredString(160, 40, V_SNAPTOTOP|warningflags, "This replay cannot be played."); - break; - - case MD_SUBDIR: - break; // Can't think of anything to draw here right now - - case MD_OUTDATED: - V_DrawThinString(17, 64, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, "Recorded on an outdated version."); - /*fallthru*/ - default: - // Draw level stuff - x = 15; y = 15; - - // A 160x100 image of the level as entry MAPxxP - //CONS_Printf("%d %s\n", demolist[dir_on[menudepthleft]].map, G_BuildMapName(demolist[dir_on[menudepthleft]].map)); - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(demolist[dir_on[menudepthleft]].map))); - if (lumpnum != LUMPERROR) - patch = W_CachePatchNum(lumpnum, PU_CACHE); - else - patch = W_CachePatchName("M_NOLVL", PU_CACHE); - - if (!(demolist[dir_on[menudepthleft]].kartspeed & DF_ENCORE)) - V_DrawSmallScaledPatch(x, y, V_SNAPTOTOP, patch); - else - { - w = SHORT(patch->width); - h = SHORT(patch->height); - V_DrawSmallScaledPatch(x+(w>>1), y, V_SNAPTOTOP|V_FLIP, patch); - - { - static angle_t rubyfloattime = 0; - const fixed_t rubyheight = FINESINE(rubyfloattime>>ANGLETOFINESHIFT); - V_DrawFixedPatch((x+(w>>2))<>2))<width), y+20, V_SNAPTOTOP, patch, colormap); - - break; - } -} - -static void M_DrawReplayHut(void) -{ - INT32 x, y, cursory = 0; - INT16 i; - INT16 replaylistitem = currentMenu->numitems-2; - boolean processed_one_this_frame = false; - - static UINT16 replayhutmenuy = 0; - - if (cv_vhseffect.value) - V_DrawVhsEffect(false); - - // Draw menu choices - x = currentMenu->x; - y = currentMenu->y; - - if (itemOn > replaylistitem) - { - itemOn = replaylistitem; - dir_on[menudepthleft] = sizedirmenu-1; - replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; - } - else if (itemOn < replaylistitem) - { - dir_on[menudepthleft] = 0; - replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; - } - - if (itemOn == replaylistitem) - { - INT32 maxy; - // Scroll menu items if needed - cursory = y + currentMenu->menuitems[replaylistitem].mvar1 + dir_on[menudepthleft]*10; - maxy = y + currentMenu->menuitems[replaylistitem].mvar1 + sizedirmenu*10; - - if (cursory > maxy - 20) - cursory = maxy - 20; - - if (cursory - replayhutmenuy > SCALEDVIEWHEIGHT-50) - replayhutmenuy += (cursory-SCALEDVIEWHEIGHT-replayhutmenuy + 51)/2; - else if (cursory - replayhutmenuy < 110) - replayhutmenuy += (max(0, cursory-110)-replayhutmenuy - 1)/2; - } - else - replayhutmenuy /= 2; - - y -= replayhutmenuy; - - // Draw static menu items - for (i = 0; i < replaylistitem; i++) - { - INT32 localy = y + currentMenu->menuitems[i].mvar1; - - if (localy < 65) - continue; - - if (i == itemOn) - cursory = localy; - - if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING) - V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT, currentMenu->menuitems[i].text); - else - V_DrawString(x, localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[i].text); - } - - y += currentMenu->menuitems[replaylistitem].mvar1; - - for (i = 0; i < (INT16)sizedirmenu; i++) - { - INT32 localy = y+i*10; - INT32 localx = x; - - if (localy < 65) - continue; - if (localy >= SCALEDVIEWHEIGHT) - break; - - if (demolist[i].type == MD_NOTLOADED && !processed_one_this_frame) - { - processed_one_this_frame = true; - G_LoadDemoInfo(&demolist[i]); - } - - if (demolist[i].type == MD_SUBDIR) - { - localx += 8; - V_DrawScaledPatch(x - 4, localy, V_SNAPTOTOP|V_SNAPTOLEFT, W_CachePatchName(dirmenu[i][DIR_TYPE] == EXT_UP ? "M_RBACK" : "M_RFLDR", PU_CACHE)); - } - - if (itemOn == replaylistitem && i == (INT16)dir_on[menudepthleft]) - { - cursory = localy; - - if (replayScrollDelay) - replayScrollDelay--; - else if (replayScrollDir > 0) - { - if (replayScrollTitle < (V_StringWidth(demolist[i].title, 0) - (SCALEDVIEWWIDTH - (x<<1)))<<1) - replayScrollTitle++; - else - { - replayScrollDelay = TICRATE; - replayScrollDir = -1; - } - } - else - { - if (replayScrollTitle > 0) - replayScrollTitle--; - else - { - replayScrollDelay = TICRATE; - replayScrollDir = 1; - } - } - - V_DrawString(localx - (replayScrollTitle>>1), localy, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags|V_ALLOWLOWERCASE, demolist[i].title); - } - else - V_DrawString(localx, localy, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE, demolist[i].title); - } - - // Draw scrollbar - y = sizedirmenu*10 + currentMenu->menuitems[replaylistitem].mvar1 + 30; - if (y > SCALEDVIEWHEIGHT-80) - { - V_DrawFill(BASEVIDWIDTH-4, 75, 4, SCALEDVIEWHEIGHT-80, V_SNAPTOTOP|V_SNAPTORIGHT|159); - V_DrawFill(BASEVIDWIDTH-3, 76 + (SCALEDVIEWHEIGHT-80) * replayhutmenuy / y, 2, (((SCALEDVIEWHEIGHT-80) * (SCALEDVIEWHEIGHT-80))-1) / y - 1, V_SNAPTOTOP|V_SNAPTORIGHT|149); - } - - // Draw the cursor - V_DrawScaledPatch(currentMenu->x - 24, cursory, V_SNAPTOTOP|V_SNAPTOLEFT, - W_CachePatchName("M_CURSOR", PU_CACHE)); - V_DrawString(currentMenu->x, cursory, V_SNAPTOTOP|V_SNAPTOLEFT|highlightflags, currentMenu->menuitems[itemOn].text); - - // Now draw some replay info! - V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|159); - - if (itemOn == replaylistitem) - { - DrawReplayHutReplayInfo(); - } -} - -static void M_DrawReplayStartMenu(void) -{ - const char *warning; - UINT8 i; - - M_DrawGenericMenu(); - -#define STARTY 62-(replayScrollTitle>>1) - // Draw rankings beyond first - for (i = 1; i < MAXPLAYERS && demolist[dir_on[menudepthleft]].standings[i].ranking; i++) - { - patch_t *patch; - UINT8 *colormap; - - V_DrawRightAlignedString(BASEVIDWIDTH-100, STARTY + i*20, V_SNAPTOTOP|highlightflags, va("%2d", demolist[dir_on[menudepthleft]].standings[i].ranking)); - V_DrawThinString(BASEVIDWIDTH-96, STARTY + i*20, V_SNAPTOTOP|V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].standings[i].name); - - if (demolist[dir_on[menudepthleft]].standings[i].timeorscore == UINT32_MAX-1) - V_DrawThinString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, "NO CONTEST"); - else if (demolist[dir_on[menudepthleft]].gametype == GT_RACE) - V_DrawRightAlignedString(BASEVIDWIDTH-40, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d'%02d\"%02d", - G_TicsToMinutes(demolist[dir_on[menudepthleft]].standings[i].timeorscore, true), - G_TicsToSeconds(demolist[dir_on[menudepthleft]].standings[i].timeorscore), - G_TicsToCentiseconds(demolist[dir_on[menudepthleft]].standings[i].timeorscore) - )); - else - V_DrawString(BASEVIDWIDTH-92, STARTY + i*20 + 9, V_SNAPTOTOP, va("%d", demolist[dir_on[menudepthleft]].standings[i].timeorscore)); - - // Character face! - if (W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[i].skin].facerank) != LUMPERROR) - { - patch = facerankprefix[demolist[dir_on[menudepthleft]].standings[i].skin]; - colormap = R_GetTranslationColormap( - demolist[dir_on[menudepthleft]].standings[i].skin, - demolist[dir_on[menudepthleft]].standings[i].color, - GTC_MENUCACHE); - } - else - { - patch = W_CachePatchName("M_NORANK", PU_CACHE); - colormap = R_GetTranslationColormap( - TC_RAINBOW, - demolist[dir_on[menudepthleft]].standings[i].color, - GTC_MENUCACHE); - } - - V_DrawMappedPatch(BASEVIDWIDTH-5 - SHORT(patch->width), STARTY + i*20, V_SNAPTOTOP, patch, colormap); - } -#undef STARTY - - // Handle scrolling rankings - if (replayScrollDelay) - replayScrollDelay--; - else if (replayScrollDir > 0) - { - if (replayScrollTitle < (i*20 - SCALEDVIEWHEIGHT + 100)<<1) - replayScrollTitle++; - else - { - replayScrollDelay = TICRATE; - replayScrollDir = -1; - } - } - else - { - if (replayScrollTitle > 0) - replayScrollTitle--; - else - { - replayScrollDelay = TICRATE; - replayScrollDir = 1; - } - } - - V_DrawFill(10, 10, 300, 60, V_SNAPTOTOP|159); - DrawReplayHutReplayInfo(); - - V_DrawString(10, 72, V_SNAPTOTOP|highlightflags|V_ALLOWLOWERCASE, demolist[dir_on[menudepthleft]].title); - - // Draw a warning prompt if needed - switch (demolist[dir_on[menudepthleft]].addonstatus) - { - case DFILE_ERROR_CANNOTLOAD: - warning = "Some addons in this replay cannot be loaded.\nYou can watch anyway, but desyncs may occur."; - break; - - case DFILE_ERROR_NOTLOADED: - case DFILE_ERROR_INCOMPLETEOUTOFORDER: - warning = "Loading addons will mark your game as modified, and record attack may be unavailable.\nYou can watch without loading addons, but desyncs may occur."; - break; - - case DFILE_ERROR_EXTRAFILES: - warning = "You have addons loaded that were not present in this replay.\nYou can watch anyway, but desyncs may occur."; - break; - - case DFILE_ERROR_OUTOFORDER: - warning = "You have this replay's addons loaded, but they are out of order.\nYou can watch anyway, but desyncs may occur."; - break; - - default: - return; - } - - V_DrawSmallString(4, BASEVIDHEIGHT-14, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, warning); -} - -static boolean M_QuitReplayHut(void) -{ - if (demolist) - Z_Free(demolist); - demolist = NULL; - - demo.inreplayhut = false; - - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - - return true; -} - -static void M_HutStartReplay(INT32 choice) -{ - (void)choice; - - M_ClearMenus(false); - demo.loadfiles = (itemOn == 0); - demo.ignorefiles = (itemOn != 0); - - G_DoPlayDemo(demolist[dir_on[menudepthleft]].filepath); -} - -void M_SetPlaybackMenuPointer(void) -{ - itemOn = playback_pause; -} - -static void M_DrawPlaybackMenu(void) -{ - INT16 i; - patch_t *icon; - UINT8 *activemap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GOLD, GTC_MENUCACHE); - - // Toggle items - if (paused && !demo.rewinding) - { - PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = PlaybackMenu[playback_rewind].status = IT_DISABLED; - PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = PlaybackMenu[playback_backframe].status = IT_CALL|IT_STRING; - - if (itemOn >= playback_rewind && itemOn <= playback_fastforward) - itemOn += playback_backframe - playback_rewind; - } - else - { - PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = PlaybackMenu[playback_rewind].status = IT_CALL|IT_STRING; - PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = PlaybackMenu[playback_backframe].status = IT_DISABLED; - - if (itemOn >= playback_backframe && itemOn <= playback_advanceframe) - itemOn -= playback_backframe - playback_rewind; - } - - if (modeattacking) - { - for (i = playback_viewcount; i <= playback_view4; i++) - PlaybackMenu[i].status = IT_DISABLED; - - //PlaybackMenu[playback_moreoptions].mvar1 = 72; - //PlaybackMenu[playback_quit].mvar1 = 88; - PlaybackMenu[playback_quit].mvar1 = 72; - - //currentMenu->x = BASEVIDWIDTH/2 - 52; - currentMenu->x = BASEVIDWIDTH/2 - 44; - } - else - { - PlaybackMenu[playback_viewcount].status = IT_ARROWS|IT_STRING; - - for (i = 0; i <= splitscreen; i++) - PlaybackMenu[playback_view1+i].status = IT_ARROWS|IT_STRING; - for (i = splitscreen+1; i < 4; i++) - PlaybackMenu[playback_view1+i].status = IT_DISABLED; - - //PlaybackMenu[playback_moreoptions].mvar1 = 156; - //PlaybackMenu[playback_quit].mvar1 = 172; - PlaybackMenu[playback_quit].mvar1 = 156; - - //currentMenu->x = BASEVIDWIDTH/2 - 94; - currentMenu->x = BASEVIDWIDTH/2 - 88; - } - - // wip - //M_DrawTextBox(currentMenu->x-68, currentMenu->y-7, 15, 15); - //M_DrawCenteredMenu(); - - for (i = 0; i < currentMenu->numitems; i++) - { - UINT8 *inactivemap = NULL; - - if (i >= playback_view1 && i <= playback_view4) - { - if (modeattacking) continue; - - if (splitscreen >= i - playback_view1) - { - INT32 ply = displayplayers[i - playback_view1]; - - icon = facerankprefix[players[ply].skin]; - if (i != itemOn) - inactivemap = R_GetTranslationColormap(players[ply].skin, players[ply].skincolor, GTC_MENUCACHE); - } - else if (currentMenu->menuitems[i].patch && W_CheckNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) - icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); - else - icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp - } - else if (currentMenu->menuitems[i].status == IT_DISABLED) - continue; - else if (currentMenu->menuitems[i].patch && W_CheckNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) - icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); - else - icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp - - if ((i == playback_fastforward && cv_playbackspeed.value > 1) || (i == playback_rewind && demo.rewinding)) - V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].mvar1, currentMenu->y, V_SNAPTOTOP, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JAWZ, GTC_MENUCACHE)); - else - V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].mvar1, currentMenu->y, V_SNAPTOTOP, icon, (i == itemOn) ? activemap : inactivemap); - - if (i == itemOn) - { - V_DrawCharacter(currentMenu->x + currentMenu->menuitems[i].mvar1 + 4, currentMenu->y + 14, - '\x1A' | V_SNAPTOTOP|highlightflags, false); - - V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, V_SNAPTOTOP|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); - - if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_ARROWS) - { - char *str; - - if (!(i == playback_viewcount && splitscreen == 3)) - V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 28 - (skullAnimCounter/5), - '\x1A' | V_SNAPTOTOP|highlightflags, false); // up arrow - - if (!(i == playback_viewcount && splitscreen == 0)) - V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 48 + (skullAnimCounter/5), - '\x1B' | V_SNAPTOTOP|highlightflags, false); // down arrow - - switch (i) - { - case playback_viewcount: - str = va("%d", splitscreen+1); - break; - - case playback_view1: - case playback_view2: - case playback_view3: - case playback_view4: - str = player_names[displayplayers[i - playback_view1]]; // 0 to 3 - break; - - default: // shouldn't ever be reached but whatever - continue; - } - - V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 38, V_SNAPTOTOP|V_ALLOWLOWERCASE|highlightflags, str); - } - } - } -} - -static void M_PlaybackRewind(INT32 choice) -{ - static tic_t lastconfirmtime; - - (void)choice; - - if (!demo.rewinding) - { - if (paused) - { - G_ConfirmRewind(leveltime-1); - paused = true; - S_PauseAudio(); - } - else - demo.rewinding = paused = true; - } - else if (lastconfirmtime + TICRATE/2 < I_GetTime()) - { - lastconfirmtime = I_GetTime(); - G_ConfirmRewind(leveltime); - } - - CV_SetValue(&cv_playbackspeed, 1); -} - -static void M_PlaybackPause(INT32 choice) -{ - (void)choice; - - paused = !paused; - - if (demo.rewinding) - { - G_ConfirmRewind(leveltime); - paused = true; - S_PauseAudio(); - } - else if (paused) - S_PauseAudio(); - else - S_ResumeAudio(); - - CV_SetValue(&cv_playbackspeed, 1); -} - -static void M_PlaybackFastForward(INT32 choice) -{ - (void)choice; - - if (demo.rewinding) - { - G_ConfirmRewind(leveltime); - paused = false; - S_ResumeAudio(); - } - CV_SetValue(&cv_playbackspeed, cv_playbackspeed.value == 1 ? 4 : 1); -} - -static void M_PlaybackAdvance(INT32 choice) -{ - (void)choice; - - paused = false; - TryRunTics(1); - paused = true; -} - - -static void M_PlaybackSetViews(INT32 choice) -{ - if (choice > 0) - { - if (splitscreen < 3) - G_AdjustView(splitscreen + 2, 0, true); - } - else if (splitscreen) - { - splitscreen--; - R_ExecuteSetViewSize(); - } -} - -static void M_PlaybackAdjustView(INT32 choice) -{ - G_AdjustView(itemOn - playback_viewcount, (choice > 0) ? 1 : -1, true); -} - -static void M_PlaybackQuit(INT32 choice) -{ - (void)choice; - G_StopDemo(); - - if (demo.inreplayhut) - M_ReplayHut(choice); - else if (modeattacking) - M_EndModeAttackRun(); - else - D_StartTitle(); -} - -static void M_ChangeLevel(INT32 choice) -{ - char mapname[6]; - (void)choice; - - strlcpy(mapname, G_BuildMapName(cv_nextmap.value), sizeof (mapname)); - strlwr(mapname); - mapname[5] = '\0'; - - M_ClearMenus(true); - COM_BufAddText(va("map %s -gametype \"%s\"\n", mapname, cv_newgametype.string)); -} - -static void M_ConfirmSpectate(INT32 choice) -{ - (void)choice; - // We allow switching to spectator even if team changing is not allowed - M_ClearMenus(true); - COM_ImmedExecute("changeteam spectator"); -} - -static void M_ConfirmEnterGame(INT32 choice) -{ - (void)choice; - if (!cv_allowteamchange.value) - { - M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\nPress a key.\n"), NULL, MM_NOTHING); - return; - } - M_ClearMenus(true); - COM_ImmedExecute("changeteam playing"); -} - -static void M_ConfirmTeamScramble(INT32 choice) -{ - (void)choice; - M_ClearMenus(true); - - COM_ImmedExecute(va("teamscramble %d", cv_dummyscramble.value+1)); -} - -static void M_ConfirmTeamChange(INT32 choice) -{ - (void)choice; - - if (cv_dummymenuplayer.value > splitscreen+1) - return; - - if (!cv_allowteamchange.value && cv_dummyteam.value) - { - M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\nPress a key.\n"), NULL, MM_NOTHING); - return; - } - - M_ClearMenus(true); - - switch (cv_dummymenuplayer.value) - { - case 1: - default: - COM_ImmedExecute(va("changeteam %s", cv_dummyteam.string)); - break; - case 2: - COM_ImmedExecute(va("changeteam2 %s", cv_dummyteam.string)); - break; - case 3: - COM_ImmedExecute(va("changeteam3 %s", cv_dummyteam.string)); - break; - case 4: - COM_ImmedExecute(va("changeteam4 %s", cv_dummyteam.string)); - break; - } -} - -static void M_ConfirmSpectateChange(INT32 choice) -{ - (void)choice; - - if (cv_dummymenuplayer.value > splitscreen+1) - return; - - if (!cv_allowteamchange.value && cv_dummyspectate.value) - { - M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\nPress a key.\n"), NULL, MM_NOTHING); - return; - } - - M_ClearMenus(true); - - switch (cv_dummymenuplayer.value) - { - case 1: - default: - COM_ImmedExecute(va("changeteam %s", cv_dummyspectate.string)); - break; - case 2: - COM_ImmedExecute(va("changeteam2 %s", cv_dummyspectate.string)); - break; - case 3: - COM_ImmedExecute(va("changeteam3 %s", cv_dummyspectate.string)); - break; - case 4: - COM_ImmedExecute(va("changeteam4 %s", cv_dummyspectate.string)); - break; - } -} - -static void M_Options(INT32 choice) -{ - (void)choice; - - // if the player is not admin or server, disable gameplay & server options - OP_MainMenu[4].status = OP_MainMenu[5].status = (Playing() && !(server || IsPlayerAdmin(consoleplayer))) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); - - OP_MainMenu[8].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); // Play credits - OP_DataOptionsMenu[3].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); // Erase data - - OP_GameOptionsMenu[3].status = - (M_SecretUnlocked(SECRET_ENCORE)) ? (IT_CVAR|IT_STRING) : IT_SECRET; // cv_kartencore - - OP_MainDef.prevMenu = currentMenu; - M_SetupNextMenu(&OP_MainDef); -} - -static void M_Manual(INT32 choice) -{ - (void)choice; - - MISC_HelpDef.prevMenu = (choice == INT32_MAX ? NULL : currentMenu); - M_SetupNextMenu(&MISC_HelpDef); -} - -static void M_RetryResponse(INT32 ch) -{ - if (ch != 'y' && ch != KEY_ENTER) - return; - - if (!&players[consoleplayer] || netgame || multiplayer) // Should never happen! - return; - - M_ClearMenus(true); - G_SetRetryFlag(); -} - -static void M_Retry(INT32 choice) -{ - (void)choice; - M_StartMessage(M_GetText("Start this race over?\n\n(Press 'Y' to confirm)\n"),M_RetryResponse,MM_YESNO); -} - -static void M_SelectableClearMenus(INT32 choice) -{ - (void)choice; - M_ClearMenus(true); -} - -// ======== -// SKY ROOM -// ======== - -UINT8 skyRoomMenuTranslations[MAXUNLOCKABLES]; - -static char *M_GetConditionString(condition_t cond) -{ - switch(cond.type) - { - case UC_PLAYTIME: - return va("Play for %i:%02i:%02i", - G_TicsToHours(cond.requirement), - G_TicsToMinutes(cond.requirement, false), - G_TicsToSeconds(cond.requirement)); - case UC_MATCHESPLAYED: - return va("Play %d matches", cond.requirement); - case UC_GAMECLEAR: - if (cond.requirement > 1) - return va("Beat game %d times", cond.requirement); - else - return va("Beat the game"); - case UC_ALLEMERALDS: - if (cond.requirement > 1) - return va("Beat game w/ all emeralds %d times", cond.requirement); - else - return va("Beat game w/ all emeralds"); - case UC_OVERALLTIME: - return va("Get overall time of %i:%02i:%02i", - G_TicsToHours(cond.requirement), - G_TicsToMinutes(cond.requirement, false), - G_TicsToSeconds(cond.requirement)); - case UC_MAPVISITED: - return va("Visit %s", G_BuildMapTitle(cond.requirement-1)); - case UC_MAPBEATEN: - return va("Beat %s", G_BuildMapTitle(cond.requirement-1)); - case UC_MAPALLEMERALDS: - return va("Beat %s w/ all emeralds", G_BuildMapTitle(cond.requirement-1)); - case UC_MAPTIME: - return va("Beat %s in %i:%02i.%02i", G_BuildMapTitle(cond.extrainfo1-1), - G_TicsToMinutes(cond.requirement, true), - G_TicsToSeconds(cond.requirement), - G_TicsToCentiseconds(cond.requirement)); - case UC_TOTALEMBLEMS: - return va("Get %d medals", cond.requirement); - case UC_EXTRAEMBLEM: - return va("Get \"%s\" medal", extraemblems[cond.requirement-1].name); - default: - return NULL; - } -} - -#define NUMCHECKLIST 23 -static void M_DrawChecklist(void) -{ - UINT32 i, line = 0, c; - INT32 lastid; - boolean secret = false; - - for (i = 0; i < MAXUNLOCKABLES; i++) - { - const char *secretname; - - secret = (!M_Achieved(unlockables[i].showconditionset - 1) && !unlockables[i].unlocked); - - if (unlockables[i].name[0] == 0 || unlockables[i].nochecklist - || !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS - || (unlockables[i].type == SECRET_HELLATTACK && secret)) // TODO: turn this into an unlockable setting instead of tying it to Hell Attack - continue; - - ++line; - secretname = M_CreateSecretMenuOption(unlockables[i].name); - - V_DrawString(8, (line*8), V_RETURN8|(unlockables[i].unlocked ? recommendedflags : warningflags), (secret ? secretname : unlockables[i].name)); - - if (conditionSets[unlockables[i].conditionset - 1].numconditions) - { - c = 0; - lastid = -1; - - for (c = 0; c < conditionSets[unlockables[i].conditionset - 1].numconditions; c++) - { - condition_t cond = conditionSets[unlockables[i].conditionset - 1].condition[c]; - UINT8 achieved = M_CheckCondition(&cond); - char *str = M_GetConditionString(cond); - const char *secretstr = M_CreateSecretMenuOption(str); - - if (!str) - continue; - - ++line; - - if (lastid == -1 || cond.id != (UINT32)lastid) - { - V_DrawString(16, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? highlightflags : 0), "*"); - V_DrawString(32, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? highlightflags : 0), (secret ? secretstr : str)); - } - else - { - V_DrawString(32, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? highlightflags : 0), (secret ? "?" : "&")); - V_DrawString(48, (line*8), V_MONOSPACE|V_ALLOWLOWERCASE|(achieved ? highlightflags : 0), (secret ? secretstr : str)); - } - - lastid = cond.id; - } - } - - ++line; - - if (line >= NUMCHECKLIST) - break; - } -} -#undef NUMCHECKLIST - -static void M_DrawSoundOptions(void) -{ - INT32 i, y = 0; - INT32 lengthstring = 0; - - M_DrawGenericMenu(); - - if (currentMenu == &OP_SoundOptionsDef) - { - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, - currentMenu->y+currentMenu->menuitems[0].mvar1, - (sound_disabled ? warningflags : highlightflags), - (sound_disabled ? "OFF" : "ON")); - - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, - currentMenu->y+currentMenu->menuitems[2].mvar1, - (digital_disabled ? warningflags : highlightflags), - (digital_disabled ? "OFF" : "ON")); - - /*V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, - currentMenu->y+currentMenu->menuitems[5].mvar1, - (midi_disabled ? warningflags : highlightflags), - (midi_disabled ? "OFF" : "ON"));*/ - - if (itemOn == 0) - lengthstring = 8*(sound_disabled ? 3 : 2); - else if (itemOn == 2) - lengthstring = 8*(digital_disabled ? 3 : 2); - /*else if (itemOn == 5) - lengthstring = 8*(midi_disabled ? 3 : 2);*/ - } - - for (i = 0; i < currentMenu->numitems; ++i) - { - if (currentMenu->menuitems[i].itemaction == M_HandleSoundTest) - { - y = currentMenu->menuitems[i].mvar1; - break; - } - } - - if (y) - { - y += currentMenu->y; - - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, y, highlightflags, cv_soundtest.string); - if (cv_soundtest.value) - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, y + 8, highlightflags, S_sfx[cv_soundtest.value].name); - - if (i == itemOn) - lengthstring = V_StringWidth(cv_soundtest.string, 0); - } - - if (lengthstring) - { - V_DrawCharacter(BASEVIDWIDTH - currentMenu->x - 10 - lengthstring - (skullAnimCounter/5), currentMenu->y+currentMenu->menuitems[itemOn].mvar1, - '\x1C' | highlightflags, false); // left arrow - V_DrawCharacter(BASEVIDWIDTH - currentMenu->x + 2 + (skullAnimCounter/5), currentMenu->y+currentMenu->menuitems[itemOn].mvar1, - '\x1D' | highlightflags, false); // right arrow - } -} - -static void M_HandleSoundTest(INT32 choice) -{ - boolean exitmenu = false; // exit to previous menu - - switch (choice) - { - case KEY_DOWNARROW: - M_NextOpt(); - S_StartSound(NULL, sfx_menu1); - break; - case KEY_UPARROW: - M_PrevOpt(); - S_StartSound(NULL, sfx_menu1); - break; - case KEY_BACKSPACE: - case KEY_ESCAPE: - exitmenu = true; - break; - - case KEY_RIGHTARROW: - CV_AddValue(&cv_soundtest, 1); - break; - case KEY_LEFTARROW: - CV_AddValue(&cv_soundtest, -1); - break; - case KEY_ENTER: - S_StopSounds(); - S_StartSound(NULL, cv_soundtest.value); - break; - - default: - break; - } - - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} - -static void M_Credits(INT32 choice) -{ - (void)choice; - cursaveslot = -2; - M_ClearMenus(true); - F_StartCredits(); -} - -// ================== -// SINGLE PLAYER MENU -// ================== - -#if 0 // Bring this back when we have actual single-player -static void M_SinglePlayerMenu(INT32 choice) -{ - (void)choice; - SP_MainMenu[sprecordattack].status = - (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET; - /*SP_MainMenu[spnightsmode].status = - (M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET;*/ - - M_SetupNextMenu(&SP_MainDef); -} -#endif - -// =============== -// STATISTICS MENU -// =============== - -static INT32 statsLocation; -static INT32 statsMax; -static INT16 statsMapList[NUMMAPS+1]; - -static void M_Statistics(INT32 choice) -{ - INT16 i, j = 0; - - (void)choice; - - memset(statsMapList, 0, sizeof(statsMapList)); - - for (i = 0; i < NUMMAPS; i++) - { - if (!mapheaderinfo[i] || mapheaderinfo[i]->lvlttl[0] == '\0') - continue; - - if (!(mapheaderinfo[i]->typeoflevel & TOL_RACE) // TOL_SP - || (mapheaderinfo[i]->menuflags & (LF2_HIDEINSTATS|LF2_HIDEINMENU))) - continue; - - if (M_MapLocked(i+1)) // !mapvisited[i] - continue; - - statsMapList[j++] = i; - } - statsMapList[j] = -1; - statsMax = j - 11 + numextraemblems; - statsLocation = 0; - - if (statsMax < 0) - statsMax = 0; - - M_SetupNextMenu(&EX_LevelStatsDef); -} - -static void M_DrawStatsMaps(int location) -{ - INT32 y = 80, i = -1; - INT16 mnum; - extraemblem_t *exemblem; - boolean dotopname = true, dobottomarrow = (location < statsMax); - - if (location) - V_DrawCharacter(10, y-(skullAnimCounter/5), - '\x1A' | highlightflags, false); // up arrow - - while (statsMapList[++i] != -1) - { - if (location) - { - --location; - continue; - } - else if (dotopname) - { - V_DrawString(20, y, highlightflags, "LEVEL NAME"); - V_DrawString(256, y, highlightflags, "MEDALS"); - y += 8; - dotopname = false; - } - - mnum = statsMapList[i]; - M_DrawMapEmblems(mnum+1, 295, y); - - if (mapheaderinfo[mnum]->levelflags & LF_NOZONE) - V_DrawString(20, y, 0, va("%s %s", - mapheaderinfo[mnum]->lvlttl, - mapheaderinfo[mnum]->actnum)); - else - V_DrawString(20, y, 0, va("%s %s %s", - mapheaderinfo[mnum]->lvlttl, - (mapheaderinfo[mnum]->zonttl[0] ? mapheaderinfo[mnum]->zonttl : "ZONE"), - mapheaderinfo[mnum]->actnum)); - - y += 8; - - if (y >= BASEVIDHEIGHT-8) - goto bottomarrow; - } - if (dotopname && !location) - { - V_DrawString(20, y, highlightflags, "LEVEL NAME"); - V_DrawString(256, y, highlightflags, "MEDALS"); - y += 8; - } - else if (location) - --location; - - // Extra Emblems - for (i = -2; i < numextraemblems; ++i) - { - if (i == -1) - { - V_DrawString(20, y, highlightflags, "EXTRA MEDALS"); - if (location) - { - y += 8; - location++; - } - } - if (location) - { - --location; - continue; - } - - if (i >= 0) - { - exemblem = &extraemblems[i]; - - if (exemblem->collected) - V_DrawSmallMappedPatch(295, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_MENUCACHE)); - else - V_DrawSmallScaledPatch(295, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); - - V_DrawString(20, y, 0, va("%s", exemblem->description)); - } - - y += 8; - - if (y >= BASEVIDHEIGHT-8) - goto bottomarrow; - } -bottomarrow: - if (dobottomarrow) - V_DrawCharacter(10, y-8 + (skullAnimCounter/5), - '\x1B' | highlightflags, false); // down arrow -} - -static void M_DrawLevelStats(void) -{ - char beststr[40]; - - tic_t besttime = 0; - - INT32 i; - INT32 mapsunfinished = 0; - - M_DrawMenuTitle(); - - V_DrawString(20, 24, highlightflags, "Total Play Time:"); - V_DrawCenteredString(BASEVIDWIDTH/2, 32, 0, va("%i hours, %i minutes, %i seconds", - G_TicsToHours(totalplaytime), - G_TicsToMinutes(totalplaytime, false), - G_TicsToSeconds(totalplaytime))); - V_DrawString(20, 42, highlightflags, "Total Matches:"); - V_DrawRightAlignedString(BASEVIDWIDTH-16, 42, 0, va("%i played", matchesplayed)); - - for (i = 0; i < NUMMAPS; i++) - { - if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) - continue; - - if (!mainrecords[i] || mainrecords[i]->time <= 0) - { - mapsunfinished++; - continue; - } - - besttime += mainrecords[i]->time; - } - - V_DrawString(20, 62, highlightflags, "Combined time records:"); - - sprintf(beststr, "%i:%02i:%02i.%02i", G_TicsToHours(besttime), G_TicsToMinutes(besttime, false), G_TicsToSeconds(besttime), G_TicsToCentiseconds(besttime)); - V_DrawRightAlignedString(BASEVIDWIDTH-16, 62, (mapsunfinished ? warningflags : 0), beststr); - - if (mapsunfinished) - V_DrawRightAlignedString(BASEVIDWIDTH-16, 70, warningflags, va("(%d unfinished)", mapsunfinished)); - else - V_DrawRightAlignedString(BASEVIDWIDTH-16, 70, recommendedflags, "(complete)"); - - V_DrawString(32, 70, 0, va("x %d/%d", M_CountEmblems(), numemblems+numextraemblems)); - V_DrawSmallScaledPatch(20, 70, 0, W_CachePatchName("GOTITA", PU_STATIC)); - - M_DrawStatsMaps(statsLocation); -} - -// Handle statistics. -static void M_HandleLevelStats(INT32 choice) -{ - boolean exitmenu = false; // exit to previous menu - - switch (choice) - { - case KEY_DOWNARROW: - S_StartSound(NULL, sfx_menu1); - if (statsLocation < statsMax) - ++statsLocation; - break; - - case KEY_UPARROW: - S_StartSound(NULL, sfx_menu1); - if (statsLocation) - --statsLocation; - break; - - case KEY_PGDN: - S_StartSound(NULL, sfx_menu1); - statsLocation += (statsLocation+13 >= statsMax) ? statsMax-statsLocation : 13; - break; - - case KEY_PGUP: - S_StartSound(NULL, sfx_menu1); - statsLocation -= (statsLocation < 13) ? statsLocation : 13; - break; - - case KEY_ESCAPE: - exitmenu = true; - break; - } - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} - -// =========== -// MODE ATTACK -// =========== - -// Drawing function for Time Attack -void M_DrawTimeAttackMenu(void) -{ - INT32 i, x, y, cursory = 0; - UINT16 dispstatus; - - S_ChangeMusicInternal("menu", true); // Eww, but needed for when user hits escape during demo playback - - M_DrawMenuTitle(); - if (currentMenu == &SP_TimeAttackDef) - M_DrawLevelSelectOnly(true, false); - - // draw menu (everything else goes on top of it) - // Sadly we can't just use generic mode menus because we need some extra hacks - x = currentMenu->x; - y = currentMenu->y; - - // Character face! - if (W_CheckNumForName(skins[cv_chooseskin.value-1].facewant) != LUMPERROR) - { - UINT8 *colormap = R_GetTranslationColormap(cv_chooseskin.value-1, cv_playercolor.value, GTC_MENUCACHE); - V_DrawMappedPatch(BASEVIDWIDTH-x - SHORT(facewantprefix[cv_chooseskin.value-1]->width), y, 0, facewantprefix[cv_chooseskin.value-1], colormap); - } - - for (i = 0; i < currentMenu->numitems; ++i) - { - dispstatus = (currentMenu->menuitems[i].status & IT_DISPLAY); - if (dispstatus != IT_STRING && dispstatus != IT_WHITESTRING) - continue; - - y = currentMenu->y+currentMenu->menuitems[i].mvar1; - if (i == itemOn) - cursory = y; - - V_DrawString(x, y, (dispstatus == IT_WHITESTRING) ? highlightflags : 0 , currentMenu->menuitems[i].text); - - // Cvar specific handling - if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_CVAR) - { - consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; - if (currentMenu->menuitems[i].status & IT_CV_STRING) - { - M_DrawTextBox(x + 32, y - 8, MAXPLAYERNAME, 1); - V_DrawString(x + 40, y, V_ALLOWLOWERCASE, cv->string); - if (itemOn == i && skullAnimCounter < 4) // blink cursor - V_DrawCharacter(x + 40 + V_StringWidth(cv->string, V_ALLOWLOWERCASE), y, '_',false); - } - else - { - const char *str = ((cv == &cv_chooseskin) ? skins[cv_chooseskin.value-1].realname : cv->string); - INT32 soffset = 40, strw = V_StringWidth(str, 0); - - // hack to keep the menu from overlapping the level icon - if (currentMenu != &SP_TimeAttackDef || cv == &cv_nextmap) - soffset = 0; - - // Should see nothing but strings - V_DrawString(BASEVIDWIDTH - x - soffset - strw, y, highlightflags, str); - - if (i == itemOn) - { - V_DrawCharacter(BASEVIDWIDTH - x - soffset - 10 - strw - (skullAnimCounter/5), y, - '\x1C' | highlightflags, false); // left arrow - V_DrawCharacter(BASEVIDWIDTH - x - soffset + 2 + (skullAnimCounter/5), y, - '\x1D' | highlightflags, false); // right arrow - } - } - } - else if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_KEYHANDLER && cv_dummystaff.value) // bad hacky assumption: IT_KEYHANDLER is assumed to be staff ghost selector - { - INT32 strw = V_StringWidth(dummystaffname, V_ALLOWLOWERCASE); - V_DrawString(BASEVIDWIDTH - x - strw, y, highlightflags|V_ALLOWLOWERCASE, dummystaffname); - if (i == itemOn) - { - V_DrawCharacter(BASEVIDWIDTH - x - 10 - strw - (skullAnimCounter/5), y, - '\x1C' | highlightflags, false); // left arrow - V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, - '\x1D' | highlightflags, false); // right arrow - } - } - } - - x = currentMenu->x; - y = currentMenu->y; - - // DRAW THE SKULL CURSOR - V_DrawScaledPatch(x - 24, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE)); - V_DrawString(x, cursory, highlightflags, currentMenu->menuitems[itemOn].text); - - // Level record list - if (cv_nextmap.value) - { - INT32 dupadjust = (vid.width/vid.dupx); - tic_t lap = 0, time = 0; - if (mainrecords[cv_nextmap.value-1]) - { - lap = mainrecords[cv_nextmap.value-1]->lap; - time = mainrecords[cv_nextmap.value-1]->time; - } - - V_DrawFill((BASEVIDWIDTH - dupadjust)>>1, 78, dupadjust, 36, 159); - - V_DrawRightAlignedString(149, 80, highlightflags, "BEST LAP:"); - K_drawKartTimestamp(lap, 19, 86, 0, 2); - - V_DrawRightAlignedString(292, 80, highlightflags, "BEST TIME:"); - K_drawKartTimestamp(time, 162, 86, cv_nextmap.value, 1); - } - /*{ - char beststr[40]; - emblem_t *em; - - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->time) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(mainrecords[cv_nextmap.value-1]->time, true), - G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->time), - G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->time)); - - V_DrawString(64, y+48, highlightflags, "BEST TIME:"); - V_DrawRightAlignedString(BASEVIDWIDTH - 64 - 24 - 8, y+48, V_ALLOWLOWERCASE, beststr); - - if (!mainrecords[cv_nextmap.value-1] || !mainrecords[cv_nextmap.value-1]->lap) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(mainrecords[cv_nextmap.value-1]->lap, true), - G_TicsToSeconds(mainrecords[cv_nextmap.value-1]->lap), - G_TicsToCentiseconds(mainrecords[cv_nextmap.value-1]->lap)); - - V_DrawString(64, y+56, highlightflags, "BEST LAP:"); - V_DrawRightAlignedString(BASEVIDWIDTH - 64 - 24 - 8, y+56, V_ALLOWLOWERCASE, beststr); - - // Draw record emblems. - em = M_GetLevelEmblems(cv_nextmap.value); - while (em) - { - switch (em->type) - { - case ET_TIME: break; - default: - goto skipThisOne; - } - - if (em->collected) - V_DrawMappedPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_MENUCACHE)); - else - V_DrawScaledPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName("NEEDIT", PU_CACHE)); - - skipThisOne: - em = M_GetLevelEmblems(-1); - } - }*/ - - // ALWAYS DRAW player name, level name, skin and color even when not on this menu! - if (currentMenu != &SP_TimeAttackDef) - { - consvar_t *ncv; - - for (i = 0; i < 4; ++i) - { - y = currentMenu->y+SP_TimeAttackMenu[i].mvar1; - V_DrawString(x, y, V_TRANSLUCENT, SP_TimeAttackMenu[i].text); - ncv = (consvar_t *)SP_TimeAttackMenu[i].itemaction; - if (SP_TimeAttackMenu[i].status & IT_CV_STRING) - { - M_DrawTextBox(x + 32, y - 8, MAXPLAYERNAME, 1); - V_DrawString(x + 40, y, V_TRANSLUCENT|V_ALLOWLOWERCASE, ncv->string); - } - else - { - const char *str = ((ncv == &cv_chooseskin) ? skins[cv_chooseskin.value-1].realname : ncv->string); - INT32 soffset = 40, strw = V_StringWidth(str, 0); - - // hack to keep the menu from overlapping the level icon - if (ncv == &cv_nextmap) - soffset = 0; - - // Should see nothing but strings - V_DrawString(BASEVIDWIDTH - x - soffset - strw, y, highlightflags|V_TRANSLUCENT, str); - } - } - } -} - -// Going to Time Attack menu... -static void M_TimeAttack(INT32 choice) -{ - (void)choice; - - memset(skins_cons_t, 0, sizeof (skins_cons_t)); - - levellistmode = LLM_RECORDATTACK; // Don't be dependent on cv_newgametype - - if (M_CountLevelsToShowInList() == 0) - { - M_StartMessage(M_GetText("No record-attackable levels found.\n"),NULL,MM_NOTHING); - return; - } - - M_PatchSkinNameTable(); - - M_PrepareLevelSelect(); - M_SetupNextMenu(&SP_TimeAttackDef); - - if (cv_nextmap.value) - Nextmap_OnChange(); - else - CV_AddValue(&cv_nextmap, 1); - - itemOn = tastart; // "Start" is selected. -} - -static boolean M_QuitTimeAttackMenu(void) -{ - // you know what? always putting these in the buffer won't hurt anything. - COM_BufAddText(va("skin \"%s\"\n", cv_chooseskin.string)); - return true; -} - -// Player has selected the "START" from the time attack screen -static void M_ChooseTimeAttack(INT32 choice) -{ - char *gpath; - const size_t glen = strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; - char nameofdemo[256]; - (void)choice; - emeralds = 0; - M_ClearMenus(true); - modeattacking = ATTACKING_RECORD; - - I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); - I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755); - - if ((gpath = malloc(glen)) == NULL) - I_Error("Out of memory for replay filepath\n"); - - sprintf(gpath,"replay"PATHSEP"%s"PATHSEP"%s", timeattackfolder, G_BuildMapName(cv_nextmap.value)); - snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, cv_chooseskin.string); - - if (!cv_autorecord.value) - remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo)); - else - G_RecordDemo(nameofdemo); - - G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), (UINT8)(cv_chooseskin.value-1), 0, false); -} - -static void M_HandleStaffReplay(INT32 choice) -{ - boolean exitmenu = false; // exit to previous menu - lumpnum_t l = W_CheckNumForName(va("%sS%02u",G_BuildMapName(cv_nextmap.value),cv_dummystaff.value)); - - switch (choice) - { - case KEY_DOWNARROW: - M_NextOpt(); - S_StartSound(NULL, sfx_menu1); - break; - case KEY_UPARROW: - M_PrevOpt(); - S_StartSound(NULL, sfx_menu1); - break; - case KEY_BACKSPACE: - case KEY_ESCAPE: - exitmenu = true; - break; - case KEY_RIGHTARROW: - CV_AddValue(&cv_dummystaff, 1); - S_StartSound(NULL, sfx_menu1); - break; - case KEY_LEFTARROW: - CV_AddValue(&cv_dummystaff, -1); - S_StartSound(NULL, sfx_menu1); - break; - case KEY_ENTER: - if (l == LUMPERROR) - break; - M_ClearMenus(true); - modeattacking = ATTACKING_RECORD; - demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed - G_DoPlayDemo(va("%sS%02u",G_BuildMapName(cv_nextmap.value),cv_dummystaff.value)); - break; - default: - break; - } - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} - -// Player has selected the "REPLAY" from the time attack screen -static void M_ReplayTimeAttack(INT32 choice) -{ - const char *which; - M_ClearMenus(true); - modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows - demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed - - if (currentMenu == &SP_ReplayDef) - { - switch(choice) { - default: - case 0: // best time - which = "time-best"; - break; - case 1: // best lap - which = "lap-best"; - break; - case 2: // last - which = "last"; - break; - case 3: // guest - // srb2/replay/main/map01-guest.lmp - G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))); - return; - } - // srb2/replay/main/map01-sonic-time-best.lmp - G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which)); - } - /*else if (currentMenu == &SP_NightsReplayDef) - { - switch(choice) { - default: - case 0: // best score - which = "score-best"; - break; - case 1: // best time - which = "time-best"; - break; - case 2: // last - which = "last"; - break; - case 3: // staff - return; // M_HandleStaffReplay - case 4: // guest - which = "guest"; - break; - } - // srb2/replay/main/map01-score-best.lmp - G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which)); - }*/ -} - -static void M_EraseGuest(INT32 choice) -{ - const char *rguest = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)); - (void)choice; - if (FIL_FileExists(rguest)) - remove(rguest); - /*if (currentMenu == &SP_NightsGuestReplayDef) - M_SetupNextMenu(&SP_NightsAttackDef); - else*/ - M_SetupNextMenu(&SP_TimeAttackDef); - CV_AddValue(&cv_nextmap, -1); - CV_AddValue(&cv_nextmap, 1); - M_StartMessage(M_GetText("Guest replay data erased.\n"),NULL,MM_NOTHING); -} - -static void M_OverwriteGuest(const char *which) -{ - char *rguest = Z_StrDup(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))); - UINT8 *buf; - size_t len; - len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, which), &buf); - if (!len) { - return; - } - if (FIL_FileExists(rguest)) { - M_StopMessage(0); - remove(rguest); - } - FIL_WriteFile(rguest, buf, len); - Z_Free(rguest); - /*if (currentMenu == &SP_NightsGuestReplayDef) - M_SetupNextMenu(&SP_NightsAttackDef); - else*/ - M_SetupNextMenu(&SP_TimeAttackDef); - CV_AddValue(&cv_nextmap, -1); - CV_AddValue(&cv_nextmap, 1); - M_StartMessage(M_GetText("Guest replay data saved.\n"),NULL,MM_NOTHING); -} - -static void M_OverwriteGuest_Time(INT32 choice) -{ - (void)choice; - M_OverwriteGuest("time-best"); -} - -static void M_OverwriteGuest_Lap(INT32 choice) -{ - (void)choice; - M_OverwriteGuest("lap-best"); -} - -/* SRB2Kart -static void M_OverwriteGuest_Score(INT32 choice) -{ - (void)choice; - M_OverwriteGuest("score-best"); -} - -static void M_OverwriteGuest_Rings(INT32 choice) -{ - (void)choice; - M_OverwriteGuest("rings-best"); -}*/ - -static void M_OverwriteGuest_Last(INT32 choice) -{ - (void)choice; - M_OverwriteGuest("last"); -} - -static void M_SetGuestReplay(INT32 choice) -{ - void (*which)(INT32); - switch(choice) - { - case 0: // best time - which = M_OverwriteGuest_Time; - break; - case 1: // best lap - which = M_OverwriteGuest_Lap; - break; - case 2: // last - which = M_OverwriteGuest_Last; - break; - case 3: // guest - default: - M_StartMessage(M_GetText("Are you sure you want to\ndelete the guest replay data?\n\n(Press 'Y' to confirm)\n"),M_EraseGuest,MM_YESNO); - return; - } - if (FIL_FileExists(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)))) - M_StartMessage(M_GetText("Are you sure you want to\noverwrite the guest replay data?\n\n(Press 'Y' to confirm)\n"),which,MM_YESNO); - else - which(0); -} - -static void M_ModeAttackRetry(INT32 choice) -{ - (void)choice; - G_CheckDemoStatus(); // Cancel recording - if (modeattacking == ATTACKING_RECORD) - M_ChooseTimeAttack(0); - /*else if (modeattacking == ATTACKING_NIGHTS) - M_ChooseNightsAttack(0);*/ -} - -static void M_ModeAttackEndGame(INT32 choice) -{ - (void)choice; - G_CheckDemoStatus(); // Cancel recording - - if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING) - Command_ExitGame_f(); - - G_SetGamestate(GS_MENU); - - gameaction = ga_nothing; - paused = false; - CON_ToggleOff(); - - S_ChangeMusicInternal("menu", true); - - M_StartControlPanel(); - - switch(modeattacking) - { - default: - case ATTACKING_RECORD: - currentMenu = &SP_TimeAttackDef; - break; - /*case ATTACKING_NIGHTS: - currentMenu = &SP_NightsAttackDef; - break;*/ - } - itemOn = currentMenu->lastOn; - - modeattacking = ATTACKING_NONE; - // Update replay availability. - CV_AddValue(&cv_nextmap, 1); - CV_AddValue(&cv_nextmap, -1); -} - -// ======== -// END GAME -// ======== - -static void M_ExitGameResponse(INT32 ch) -{ - if (ch != 'y' && ch != KEY_ENTER) - return; - - //Command_ExitGame_f(); - G_SetExitGameFlag(); - M_ClearMenus(true); -} - -static void M_EndGame(INT32 choice) -{ - (void)choice; - if (demo.playback) - return; - - if (!Playing()) - return; - - M_StartMessage(M_GetText("Are you sure you want to end the game?\n\n(Press 'Y' to confirm)\n"), M_ExitGameResponse, MM_YESNO); -} - -//=========================================================================== -// Connect Menu -//=========================================================================== - -#define SERVERHEADERHEIGHT 44 -#define SERVERLINEHEIGHT 12 - -#define S_LINEY(n) currentMenu->y + SERVERHEADERHEIGHT + (n * SERVERLINEHEIGHT) - -#ifndef NONET -static UINT32 localservercount; - -static void M_HandleServerPage(INT32 choice) -{ - boolean exitmenu = false; // exit to previous menu - - switch (choice) - { - case KEY_DOWNARROW: - M_NextOpt(); - S_StartSound(NULL, sfx_menu1); - break; - case KEY_UPARROW: - M_PrevOpt(); - S_StartSound(NULL, sfx_menu1); - break; - case KEY_BACKSPACE: - case KEY_ESCAPE: - exitmenu = true; - break; - - case KEY_ENTER: - case KEY_RIGHTARROW: - S_StartSound(NULL, sfx_menu1); - if ((serverlistpage + 1) * SERVERS_PER_PAGE < serverlistcount) - serverlistpage++; - break; - case KEY_LEFTARROW: - S_StartSound(NULL, sfx_menu1); - if (serverlistpage > 0) - serverlistpage--; - break; - - default: - break; - } - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} - -static void M_Connect(INT32 choice) -{ - // do not call menuexitfunc - M_ClearMenus(false); - - COM_BufAddText(va("connect node %d\n", serverlist[choice-FIRSTSERVERLINE + serverlistpage * SERVERS_PER_PAGE].node)); -} - -static void M_Refresh(INT32 choice) -{ - (void)choice; - - // Display a little "please wait" message. - M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Searching for servers..."); - V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait."); - I_OsPolling(); - I_UpdateNoBlit(); - if (rendermode == render_soft) - I_FinishUpdate(); // page flip or blit buffer - - // note: this is the one case where 0 is a valid room number - // because it corresponds to "All" - CL_UpdateServerList(!(ms_RoomId < 0), ms_RoomId); - - // first page of servers - serverlistpage = 0; -} - -static INT32 menuRoomIndex = 0; - -static void M_DrawRoomMenu(void) -{ - const char *rmotd; - - // use generic drawer for cursor, items and title - M_DrawGenericMenu(); - - V_DrawString(currentMenu->x - 16, currentMenu->y, highlightflags, M_GetText("Select a room")); - - M_DrawTextBox(144, 24, 20, 20); - - if (itemOn == 0) - rmotd = M_GetText("Don't connect to the Master Server."); - else - rmotd = room_list[itemOn-1].motd; - - rmotd = V_WordWrap(0, 20*8, 0, rmotd); - V_DrawString(144+8, 32, V_ALLOWLOWERCASE|V_RETURN8, rmotd); -} - -static void M_DrawConnectMenu(void) -{ - UINT16 i; - const char *gt = "Unknown"; - const char *spd = ""; - INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE; - - for (i = FIRSTSERVERLINE; i < min(localservercount, SERVERS_PER_PAGE)+FIRSTSERVERLINE; i++) - MP_ConnectMenu[i].status = IT_STRING | IT_SPACE; - - if (!numPages) - numPages = 1; - - // Room name - if (ms_RoomId < 0) - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].mvar1, - highlightflags, (itemOn == mp_connect_room) ? "" : ""); - else - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].mvar1, - highlightflags, room_list[menuRoomIndex].name); -#undef mp_server_room - } -#endif -} - -static void M_MapChange(INT32 choice) -{ - (void)choice; - - levellistmode = LLM_CREATESERVER; - - CV_SetValue(&cv_newgametype, gametype); - CV_SetValue(&cv_nextmap, gamemap); - - M_PrepareLevelSelect(); - M_SetupNextMenu(&MISC_ChangeLevelDef); -} - -static void M_StartOfflineServerMenu(INT32 choice) -{ - (void)choice; - levellistmode = LLM_CREATESERVER; - M_PrepareLevelSelect(); - M_SetupNextMenu(&MP_OfflineServerDef); -} - -#ifndef NONET -static void M_StartServerMenu(INT32 choice) -{ - (void)choice; - levellistmode = LLM_CREATESERVER; - M_PrepareLevelSelect(); - ms_RoomId = -1; - M_SetupNextMenu(&MP_ServerDef); - -} - -// ============== -// CONNECT VIA IP -// ============== - -static char setupm_ip[28]; -#endif -static UINT8 setupm_pselect = 1; - -// Draw the funky Connect IP menu. Tails 11-19-2002 -// So much work for such a little thing! -static void M_DrawMPMainMenu(void) -{ - INT32 x = currentMenu->x; - INT32 y = currentMenu->y; - - // use generic drawer for cursor, items and title - M_DrawGenericMenu(); - -#ifndef NONET -#if MAXPLAYERS != 16 -Update the maxplayers label... -#endif - V_DrawRightAlignedString(BASEVIDWIDTH-x, y+MP_MainMenu[4].mvar1, - ((itemOn == 4) ? highlightflags : 0), "(2-16 players)"); -#endif - - V_DrawRightAlignedString(BASEVIDWIDTH-x, y+MP_MainMenu[5].mvar1, - ((itemOn == 5) ? highlightflags : 0), - "(2-4 players)" - ); - -#ifndef NONET - y += MP_MainMenu[8].mvar1; - - V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 159); - - // draw name string - V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip); - - // draw text cursor for name - if (itemOn == 8 - && skullAnimCounter < 4) //blink cursor - V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_ALLOWLOWERCASE),y+12,'_',false); -#endif - - // character bar, ripped off the color bar :V - { -#define iconwidth 32 -#define spacingwidth 32 -#define incrwidth (iconwidth + spacingwidth) - UINT8 i = 0, pskin, pcol; - // player arrangement width, but there's also a chance i'm a furry, shhhhhh - const INT32 paw = iconwidth + 3*incrwidth; - INT32 trans = 0; - UINT8 *colmap; - x = BASEVIDWIDTH/2 - paw/2; - y = currentMenu->y + 32; - - while (++i <= 4) - { - switch (i) - { - default: - pskin = R_SkinAvailable(cv_skin.string); - pcol = cv_playercolor.value; - break; - case 2: - pskin = R_SkinAvailable(cv_skin2.string); - pcol = cv_playercolor2.value; - break; - case 3: - pskin = R_SkinAvailable(cv_skin3.string); - pcol = cv_playercolor3.value; - break; - case 4: - pskin = R_SkinAvailable(cv_skin4.string); - pcol = cv_playercolor4.value; - break; - } - - if (pskin >= MAXSKINS) - pskin = 0; - - if (!trans && i > cv_splitplayers.value) - trans = V_TRANSLUCENT; - - colmap = R_GetTranslationColormap(pskin, pcol, GTC_MENUCACHE); - - V_DrawFixedPatch(x< 7) - cursorframe = 0; - V_DrawFixedPatch(x< 1) - { - if (--setupm_pselect < 1) - setupm_pselect = cv_splitplayers.value; - S_StartSound(NULL,sfx_menu1); // Tails - } - break; - - case KEY_RIGHTARROW: - if (cv_splitplayers.value > 1) - { - if (++setupm_pselect > cv_splitplayers.value) - setupm_pselect = 1; - S_StartSound(NULL,sfx_menu1); // Tails - } - break; - - case KEY_DOWNARROW: - M_NextOpt(); - S_StartSound(NULL,sfx_menu1); // Tails - break; - - case KEY_UPARROW: - M_PrevOpt(); - S_StartSound(NULL,sfx_menu1); // Tails - break; - - case KEY_ENTER: - { - S_StartSound(NULL,sfx_menu1); // Tails - currentMenu->lastOn = itemOn; - switch (setupm_pselect) - { - case 2: - M_SetupMultiPlayer2(0); - return; - case 3: - M_SetupMultiPlayer3(0); - return; - case 4: - M_SetupMultiPlayer4(0); - return; - default: - M_SetupMultiPlayer(0); - return; - } - break; - } - - case KEY_ESCAPE: - exitmenu = true; - break; - } - - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu (currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} - -#ifndef NONET - -// Tails 11-19-2002 -static void M_ConnectIP(INT32 choice) -{ - (void)choice; - - if (*setupm_ip == 0) - { - M_StartMessage("You must specify an IP address.\n", NULL, MM_NOTHING); - return; - } - - M_ClearMenus(true); - - COM_BufAddText(va("connect \"%s\"\n", setupm_ip)); - - // A little "please wait" message. - M_DrawTextBox(56, BASEVIDHEIGHT/2-12, 24, 2); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Connecting to server..."); - I_OsPolling(); - I_UpdateNoBlit(); - if (rendermode == render_soft) - I_FinishUpdate(); // page flip or blit buffer -} - -// Tails 11-19-2002 -static void M_HandleConnectIP(INT32 choice) -{ - size_t l; - boolean exitmenu = false; // exit to previous menu and send name change - - switch (choice) - { - case KEY_DOWNARROW: - M_NextOpt(); - S_StartSound(NULL,sfx_menu1); // Tails - break; - - case KEY_UPARROW: - M_PrevOpt(); - S_StartSound(NULL,sfx_menu1); // Tails - break; - - case KEY_ENTER: - S_StartSound(NULL,sfx_menu1); // Tails - currentMenu->lastOn = itemOn; - M_ConnectIP(1); - break; - - case KEY_ESCAPE: - exitmenu = true; - break; - - case KEY_BACKSPACE: - if ((l = strlen(setupm_ip)) != 0) - { - S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l-1] = 0; - } - break; - - case KEY_DEL: - if (setupm_ip[0]) - { - S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[0] = 0; - } - break; - - default: - l = strlen(setupm_ip); - if (l >= 28-1) - break; - - // Rudimentary number and period enforcing - also allows letters so hostnames can be used instead - if ((choice >= '-' && choice <= ':') || (choice >= 'A' && choice <= 'Z') || (choice >= 'a' && choice <= 'z')) - { - S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l] = (char)choice; - setupm_ip[l+1] = 0; - } - else if (choice >= 199 && choice <= 211 && choice != 202 && choice != 206) //numpad too! - { - char keypad_translation[] = {'7','8','9','-','4','5','6','+','1','2','3','0','.'}; - choice = keypad_translation[choice - 199]; - S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l] = (char)choice; - setupm_ip[l+1] = 0; - } - break; - } - - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu (currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} -#endif //!NONET - -// ======================== -// MULTIPLAYER PLAYER SETUP -// ======================== -// Tails 03-02-2002 - -static INT32 multi_tics; -static state_t *multi_state; - -// this is set before entering the MultiPlayer setup menu, -// for either player 1 or 2 -static char setupm_name[MAXPLAYERNAME+1]; -static player_t *setupm_player; -static consvar_t *setupm_cvskin; -static consvar_t *setupm_cvcolor; -static consvar_t *setupm_cvname; -static INT32 setupm_fakeskin; -static INT32 setupm_fakecolor; - -static void M_DrawSetupMultiPlayerMenu(void) -{ - INT32 mx, my, st, flags = 0; - spritedef_t *sprdef; - spriteframe_t *sprframe; - patch_t *statbg = W_CachePatchName("K_STATBG", PU_CACHE); - patch_t *statlr = W_CachePatchName("K_STATLR", PU_CACHE); - patch_t *statud = W_CachePatchName("K_STATUD", PU_CACHE); - patch_t *statdot = W_CachePatchName("K_SDOT0", PU_CACHE); - patch_t *patch; - UINT8 frame; - UINT8 speed; - UINT8 weight; - UINT8 i; - const UINT8 *flashcol = V_GetStringColormap(highlightflags); - INT32 statx, staty; - - mx = MP_PlayerSetupDef.x; - my = MP_PlayerSetupDef.y; - - statx = (BASEVIDWIDTH - mx - 118); - staty = (my+62); - - // use generic drawer for cursor, items and title - M_DrawGenericMenu(); - - // draw name string - M_DrawTextBox(mx + 32, my - 8, MAXPLAYERNAME, 1); - V_DrawString(mx + 40, my, V_ALLOWLOWERCASE, setupm_name); - - // draw text cursor for name - if (!itemOn && skullAnimCounter < 4) // blink cursor - V_DrawCharacter(mx + 40 + V_StringWidth(setupm_name, V_ALLOWLOWERCASE), my, '_',false); - - // draw skin string - st = V_StringWidth(skins[setupm_fakeskin].realname, 0); - V_DrawString(BASEVIDWIDTH - mx - st, my + 16, - ((MP_PlayerSetupMenu[2].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|highlightflags|V_ALLOWLOWERCASE, - skins[setupm_fakeskin].realname); - if (itemOn == 1) - { - V_DrawCharacter(BASEVIDWIDTH - mx - 10 - st - (skullAnimCounter/5), my + 16, - '\x1C' | highlightflags, false); // left arrow - V_DrawCharacter(BASEVIDWIDTH - mx + 2 + (skullAnimCounter/5), my + 16, - '\x1D' | highlightflags, false); // right arrow - } - - // draw the name of the color you have chosen - // Just so people don't go thinking that "Default" is Green. - st = V_StringWidth(KartColor_Names[setupm_fakecolor], 0); - V_DrawString(BASEVIDWIDTH - mx - st, my + 152, highlightflags|V_ALLOWLOWERCASE, KartColor_Names[setupm_fakecolor]); // SRB2kart - if (itemOn == 2) - { - V_DrawCharacter(BASEVIDWIDTH - mx - 10 - st - (skullAnimCounter/5), my + 152, - '\x1C' | highlightflags, false); // left arrow - V_DrawCharacter(BASEVIDWIDTH - mx + 2 + (skullAnimCounter/5), my + 152, - '\x1D' | highlightflags, false); // right arrow - } - - // SRB2Kart: draw the stat backer - // labels - V_DrawThinString(statx+16, staty, V_6WIDTHSPACE|highlightflags, "Acceleration"); - V_DrawThinString(statx+91, staty, V_6WIDTHSPACE|highlightflags, "Max Speed"); - V_DrawThinString(statx, staty+12, V_6WIDTHSPACE|highlightflags, "Handling"); - V_DrawThinString(statx+7, staty+77, V_6WIDTHSPACE|highlightflags, "Weight"); - // label arrows - V_DrawFixedPatch((statx+64)<= MAXSKINCOLORS) - col -= MAXSKINCOLORS-1; - x += w; - } - } -#undef indexwidth - - // character bar, ripped off the color bar :V - if (setupm_fakecolor) // inverse should never happen -#define iconwidth 32 - { - const INT32 icons = 4; - INT32 k = -icons; - INT16 col = setupm_fakeskin - icons; - INT32 x = BASEVIDWIDTH/2 - ((icons+1)*24) - 4; - fixed_t scale = FRACUNIT/2; - INT32 offx = 8, offy = 8; - patch_t *cursor; - static UINT8 cursorframe = 0; - patch_t *face; - UINT8 *colmap; - - if (skullAnimCounter % 4 == 0) - cursorframe++; - if (cursorframe > 7) - cursorframe = 0; - - cursor = W_CachePatchName(va("K_BHILI%d", cursorframe+1), PU_CACHE); - - if (col < 0) - col += numskins; - while (k <= icons) - { - if (!(k++)) - { - scale = FRACUNIT; - face = facewantprefix[col]; - offx = 12; - offy = 0; - } - else - { - scale = FRACUNIT/2; - face = facerankprefix[col]; - offx = 8; - offy = 8; - } - colmap = R_GetTranslationColormap(col, setupm_fakecolor, GTC_MENUCACHE); - V_DrawFixedPatch((x+offx)<= numskins) - col -= numskins; - x += FixedMul(iconwidth<nextstate; - if (st != S_NULL) - multi_state = &states[st]; - multi_tics = multi_state->tics; - if (multi_tics == -1) - multi_tics = 15; - } - - // skin 0 is default player sprite - if (R_SkinAvailable(skins[setupm_fakeskin].name) != -1) - sprdef = &skins[R_SkinAvailable(skins[setupm_fakeskin].name)].spritedef; - else - sprdef = &skins[0].spritedef; - - if (!sprdef->numframes) // No frames ?? - return; // Can't render! - - frame = multi_state->frame & FF_FRAMEMASK; - if (frame >= sprdef->numframes) // Walking animation missing - frame = 0; // Try to use standing frame - - sprframe = &sprdef->spriteframes[frame]; - patch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE); - if (sprframe->flip & 1) // Only for first sprite - flags |= V_FLIP; // This sprite is left/right flipped! - - // draw box around guy - V_DrawFill(mx + 43 - (charw/2), my+65, charw, 84, 159); - - // draw player sprite - if (setupm_fakecolor) // inverse should never happen - { - UINT8 *colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor, GTC_MENUCACHE); - - if (skins[setupm_fakeskin].flags & SF_HIRES) - { - V_DrawFixedPatch((mx+43)< 127 || itemOn != 0) - break; - l = strlen(setupm_name); - if (l < MAXPLAYERNAME) - { - S_StartSound(NULL,sfx_menu1); // Tails - setupm_name[l] =(char)choice; - setupm_name[l+1] =0; - } - break; - } - - // check skin - if (setupm_fakeskin < 0) - setupm_fakeskin = numskins-1; - if (setupm_fakeskin > numskins-1) - setupm_fakeskin = 0; - - // check color - if (setupm_fakecolor < 1) - setupm_fakecolor = MAXSKINCOLORS-1; - if (setupm_fakecolor > MAXSKINCOLORS-1) - setupm_fakecolor = 1; - - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu (currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} - -// start the multiplayer setup menu -static void M_SetupMultiPlayer(INT32 choice) -{ - (void)choice; - - multi_state = &states[mobjinfo[MT_PLAYER].seestate]; - multi_tics = multi_state->tics; - strcpy(setupm_name, cv_playername.string); - - // set for player 1 - setupm_player = &players[consoleplayer]; - setupm_cvskin = &cv_skin; - setupm_cvcolor = &cv_playercolor; - setupm_cvname = &cv_playername; - - // For whatever reason this doesn't work right if you just use ->value - setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); - if (setupm_fakeskin == -1) - setupm_fakeskin = 0; - setupm_fakecolor = setupm_cvcolor->value; - - // disable skin changes if we can't actually change skins - if (!CanChangeSkin(consoleplayer)) - MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); - else - MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); - - MP_PlayerSetupDef.prevMenu = currentMenu; - M_SetupNextMenu(&MP_PlayerSetupDef); -} - -// start the multiplayer setup menu, for secondary player (splitscreen mode) -static void M_SetupMultiPlayer2(INT32 choice) -{ - (void)choice; - - multi_state = &states[mobjinfo[MT_PLAYER].seestate]; - multi_tics = multi_state->tics; - strcpy (setupm_name, cv_playername2.string); - - // set for splitscreen secondary player - setupm_player = &players[displayplayers[1]]; - setupm_cvskin = &cv_skin2; - setupm_cvcolor = &cv_playercolor2; - setupm_cvname = &cv_playername2; - - // For whatever reason this doesn't work right if you just use ->value - setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); - if (setupm_fakeskin == -1) - setupm_fakeskin = 0; - setupm_fakecolor = setupm_cvcolor->value; - - // disable skin changes if we can't actually change skins - if (splitscreen && !CanChangeSkin(displayplayers[1])) - MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); - else - MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER | IT_STRING); - - MP_PlayerSetupDef.prevMenu = currentMenu; - M_SetupNextMenu(&MP_PlayerSetupDef); -} - -// start the multiplayer setup menu, for third player (splitscreen mode) -static void M_SetupMultiPlayer3(INT32 choice) -{ - (void)choice; - - multi_state = &states[mobjinfo[MT_PLAYER].seestate]; - multi_tics = multi_state->tics; - strcpy(setupm_name, cv_playername3.string); - - // set for splitscreen third player - setupm_player = &players[displayplayers[2]]; - setupm_cvskin = &cv_skin3; - setupm_cvcolor = &cv_playercolor3; - setupm_cvname = &cv_playername3; - - // For whatever reason this doesn't work right if you just use ->value - setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); - if (setupm_fakeskin == -1) - setupm_fakeskin = 0; - setupm_fakecolor = setupm_cvcolor->value; - - // disable skin changes if we can't actually change skins - if (splitscreen > 1 && !CanChangeSkin(displayplayers[2])) - MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); - else - MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER | IT_STRING); - - MP_PlayerSetupDef.prevMenu = currentMenu; - M_SetupNextMenu(&MP_PlayerSetupDef); -} - -// start the multiplayer setup menu, for third player (splitscreen mode) -static void M_SetupMultiPlayer4(INT32 choice) -{ - (void)choice; - - multi_state = &states[mobjinfo[MT_PLAYER].seestate]; - multi_tics = multi_state->tics; - strcpy(setupm_name, cv_playername4.string); - - // set for splitscreen fourth player - setupm_player = &players[displayplayers[3]]; - setupm_cvskin = &cv_skin4; - setupm_cvcolor = &cv_playercolor4; - setupm_cvname = &cv_playername4; - - // For whatever reason this doesn't work right if you just use ->value - setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); - if (setupm_fakeskin == -1) - setupm_fakeskin = 0; - setupm_fakecolor = setupm_cvcolor->value; - - // disable skin changes if we can't actually change skins - if (splitscreen > 2 && !CanChangeSkin(displayplayers[3])) - MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT); - else - MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER | IT_STRING); - - MP_PlayerSetupDef.prevMenu = currentMenu; - M_SetupNextMenu(&MP_PlayerSetupDef); -} - -static boolean M_QuitMultiPlayerMenu(void) -{ - size_t l; - // send name if changed - if (strcmp(setupm_name, setupm_cvname->string)) - { - // remove trailing whitespaces - for (l= strlen(setupm_name)-1; - (signed)l >= 0 && setupm_name[l] ==' '; l--) - setupm_name[l] =0; - COM_BufAddText (va("%s \"%s\"\n",setupm_cvname->name,setupm_name)); - } - // you know what? always putting these in the buffer won't hurt anything. - COM_BufAddText (va("%s \"%s\"\n",setupm_cvskin->name,skins[setupm_fakeskin].name)); - COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor)); - return true; -} - -// ================= -// DATA OPTIONS MENU -// ================= -static UINT8 erasecontext = 0; - -static void M_EraseDataResponse(INT32 ch) -{ - if (ch != 'y' && ch != KEY_ENTER) - return; - - S_StartSound(NULL, sfx_itrole); // bweh heh heh - - // Delete the data - if (erasecontext == 2) - { - // SRB2Kart: This actually needs to be done FIRST, so that you don't immediately regain playtime/matches extras - totalplaytime = 0; - matchesplayed = 0; - F_StartIntro(); - } - if (erasecontext != 1) - G_ClearRecords(); - if (erasecontext != 0) - M_ClearSecrets(); - M_ClearMenus(true); -} - -static void M_EraseData(INT32 choice) -{ - const char *eschoice, *esstr = M_GetText("Are you sure you want to erase\n%s?\n\n(Press 'Y' to confirm)\n"); - - erasecontext = (UINT8)choice; - - if (choice == 0) - eschoice = M_GetText("Record Attack data"); - else if (choice == 1) - eschoice = M_GetText("Extras data"); - else - eschoice = M_GetText("ALL game data"); - - M_StartMessage(va(esstr, eschoice),M_EraseDataResponse,MM_YESNO); -} - -static void M_ScreenshotOptions(INT32 choice) -{ - (void)choice; - Screenshot_option_Onchange(); - Moviemode_mode_Onchange(); - - M_SetupNextMenu(&OP_ScreenshotOptionsDef); -} - -// ============= -// JOYSTICK MENU -// ============= - -// Start the controls menu, setting it up for either the console player, -// or the secondary splitscreen player - -static void M_DrawJoystick(void) -{ - INT32 i, compareval4, compareval3, compareval2, compareval; - - M_DrawGenericMenu(); - - for (i = 0; i < 8; i++) - { - M_DrawTextBox(OP_JoystickSetDef.x-8, OP_JoystickSetDef.y+LINEHEIGHT*i-12, 28, 1); - //M_DrawSaveLoadBorder(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i); - -#ifdef JOYSTICK_HOTPLUG - if (atoi(cv_usejoystick4.string) > I_NumJoys()) - compareval4 = atoi(cv_usejoystick4.string); - else - compareval4 = cv_usejoystick4.value; - - if (atoi(cv_usejoystick3.string) > I_NumJoys()) - compareval3 = atoi(cv_usejoystick3.string); - else - compareval3 = cv_usejoystick3.value; - - if (atoi(cv_usejoystick2.string) > I_NumJoys()) - compareval2 = atoi(cv_usejoystick2.string); - else - compareval2 = cv_usejoystick2.value; - - if (atoi(cv_usejoystick.string) > I_NumJoys()) - compareval = atoi(cv_usejoystick.string); - else - compareval = cv_usejoystick.value; -#else - compareval4 = cv_usejoystick4.value; - compareval3 = cv_usejoystick3.value; - compareval2 = cv_usejoystick2.value; - compareval = cv_usejoystick.value -#endif - - if ((setupcontrolplayer == 4 && (i == compareval4)) - || (setupcontrolplayer == 3 && (i == compareval3)) - || (setupcontrolplayer == 2 && (i == compareval2)) - || (setupcontrolplayer == 1 && (i == compareval))) - V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,V_GREENMAP,joystickInfo[i]); - else - V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,0,joystickInfo[i]); - } -} - -void M_SetupJoystickMenu(INT32 choice) -{ - INT32 i = 0; - const char *joyNA = "Unavailable"; - INT32 n = I_NumJoys(); - (void)choice; - - strcpy(joystickInfo[i], "None"); - - for (i = 1; i < 8; i++) - { - if (i <= n && (I_GetJoyName(i)) != NULL) - strncpy(joystickInfo[i], I_GetJoyName(i), 28); - else - strcpy(joystickInfo[i], joyNA); - -#ifdef JOYSTICK_HOTPLUG - // We use cv_usejoystick.string as the USER-SET var - // and cv_usejoystick.value as the INTERNAL var - // - // In practice, if cv_usejoystick.string == 0, this overrides - // cv_usejoystick.value and always disables - // - // Update cv_usejoystick.string here so that the user can - // properly change this value. - if (i == cv_usejoystick.value) - CV_SetValue(&cv_usejoystick, i); - if (i == cv_usejoystick2.value) - CV_SetValue(&cv_usejoystick2, i); - if (i == cv_usejoystick3.value) - CV_SetValue(&cv_usejoystick3, i); - if (i == cv_usejoystick4.value) - CV_SetValue(&cv_usejoystick4, i); -#endif - } - - M_SetupNextMenu(&OP_JoystickSetDef); -} - -static void M_Setup1PJoystickMenu(INT32 choice) -{ - setupcontrolplayer = 1; - OP_JoystickSetDef.prevMenu = &OP_Joystick1Def; - M_SetupJoystickMenu(choice); -} - -static void M_Setup2PJoystickMenu(INT32 choice) -{ - setupcontrolplayer = 2; - OP_JoystickSetDef.prevMenu = &OP_Joystick2Def; - M_SetupJoystickMenu(choice); -} - -static void M_Setup3PJoystickMenu(INT32 choice) -{ - setupcontrolplayer = 3; - OP_JoystickSetDef.prevMenu = &OP_Joystick3Def; - M_SetupJoystickMenu(choice); -} - -static void M_Setup4PJoystickMenu(INT32 choice) -{ - setupcontrolplayer = 4; - OP_JoystickSetDef.prevMenu = &OP_Joystick4Def; - M_SetupJoystickMenu(choice); -} - -static void M_AssignJoystick(INT32 choice) -{ -#ifdef JOYSTICK_HOTPLUG - INT32 oldchoice, oldstringchoice; - INT32 numjoys = I_NumJoys(); - - if (setupcontrolplayer == 4) - { - oldchoice = oldstringchoice = atoi(cv_usejoystick4.string) > numjoys ? atoi(cv_usejoystick4.string) : cv_usejoystick4.value; - CV_SetValue(&cv_usejoystick4, choice); - - // Just in case last-minute changes were made to cv_usejoystick.value, - // update the string too - // But don't do this if we're intentionally setting higher than numjoys - if (choice <= numjoys) - { - CV_SetValue(&cv_usejoystick4, cv_usejoystick4.value); - - // reset this so the comparison is valid - if (oldchoice > numjoys) - oldchoice = cv_usejoystick4.value; - - if (oldchoice != choice) - { - if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick4, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - - if (oldstringchoice == - (atoi(cv_usejoystick4.string) > numjoys ? atoi(cv_usejoystick4.string) : cv_usejoystick4.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); - } - } - } - else if (setupcontrolplayer == 3) - { - oldchoice = oldstringchoice = atoi(cv_usejoystick3.string) > numjoys ? atoi(cv_usejoystick3.string) : cv_usejoystick3.value; - CV_SetValue(&cv_usejoystick3, choice); - - // Just in case last-minute changes were made to cv_usejoystick.value, - // update the string too - // But don't do this if we're intentionally setting higher than numjoys - if (choice <= numjoys) - { - CV_SetValue(&cv_usejoystick3, cv_usejoystick3.value); - - // reset this so the comparison is valid - if (oldchoice > numjoys) - oldchoice = cv_usejoystick3.value; - - if (oldchoice != choice) - { - if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick3, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - - if (oldstringchoice == - (atoi(cv_usejoystick3.string) > numjoys ? atoi(cv_usejoystick3.string) : cv_usejoystick3.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); - } - } - } - else if (setupcontrolplayer == 2) - { - oldchoice = oldstringchoice = atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value; - CV_SetValue(&cv_usejoystick2, choice); - - // Just in case last-minute changes were made to cv_usejoystick.value, - // update the string too - // But don't do this if we're intentionally setting higher than numjoys - if (choice <= numjoys) - { - CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); - - // reset this so the comparison is valid - if (oldchoice > numjoys) - oldchoice = cv_usejoystick2.value; - - if (oldchoice != choice) - { - if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick2, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - - if (oldstringchoice == - (atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); - } - } - } - else if (setupcontrolplayer == 1) - { - oldchoice = oldstringchoice = atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value; - CV_SetValue(&cv_usejoystick, choice); - - // Just in case last-minute changes were made to cv_usejoystick.value, - // update the string too - // But don't do this if we're intentionally setting higher than numjoys - if (choice <= numjoys) - { - CV_SetValue(&cv_usejoystick, cv_usejoystick.value); - - // reset this so the comparison is valid - if (oldchoice > numjoys) - oldchoice = cv_usejoystick.value; - - if (oldchoice != choice) - { - if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - - if (oldstringchoice == - (atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); - } - } - } -#else - if (setupcontrolplayer == 4) - CV_SetValue(&cv_usejoystick4, choice); - else if (setupcontrolplayer == 3) - CV_SetValue(&cv_usejoystick3, choice); - else if (setupcontrolplayer == 2) - CV_SetValue(&cv_usejoystick2, choice); - else if (setupcontrolplayer == 1) - CV_SetValue(&cv_usejoystick, choice); -#endif -} - -// ============= -// CONTROLS MENU -// ============= - -static void M_Setup1PControlsMenu(INT32 choice) -{ - (void)choice; - setupcontrolplayer = 1; - setupcontrols = gamecontrol; // was called from main Options (for console player, then) - currentMenu->lastOn = itemOn; - - // Set proper gamepad options - OP_AllControlsMenu[0].itemaction = &OP_Joystick1Def; - - // Unhide P1-only controls - OP_AllControlsMenu[15].status = IT_CONTROL; // Chat - //OP_AllControlsMenu[16].status = IT_CONTROL; // Team-chat - OP_AllControlsMenu[16].status = IT_CONTROL; // Rankings - //OP_AllControlsMenu[17].status = IT_CONTROL; // Viewpoint - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_CONTROL; // Pause - OP_AllControlsMenu[21].status = IT_CONTROL; // Screenshot - OP_AllControlsMenu[22].status = IT_CONTROL; // GIF - OP_AllControlsMenu[23].status = IT_CONTROL; // System Menu - OP_AllControlsMenu[24].status = IT_CONTROL; // Console - /*OP_AllControlsMenu[25].status = IT_HEADER; // Spectator Controls header - OP_AllControlsMenu[26].status = IT_SPACE; // Spectator Controls space - OP_AllControlsMenu[27].status = IT_CONTROL; // Spectate - OP_AllControlsMenu[28].status = IT_CONTROL; // Look Up - OP_AllControlsMenu[29].status = IT_CONTROL; // Look Down - OP_AllControlsMenu[30].status = IT_CONTROL; // Center View - */ - - M_SetupNextMenu(&OP_AllControlsDef); -} - -static void M_Setup2PControlsMenu(INT32 choice) -{ - (void)choice; - setupcontrolplayer = 2; - setupcontrols = gamecontrolbis; - currentMenu->lastOn = itemOn; - - // Set proper gamepad options - OP_AllControlsMenu[0].itemaction = &OP_Joystick2Def; - - // Hide P1-only controls - OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat - //OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat - OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause - OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot - OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // GIF - OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // System Menu - OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // Console - /*OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Spectator Controls header - OP_AllControlsMenu[26].status = IT_GRAYEDOUT2; // Spectator Controls space - OP_AllControlsMenu[27].status = IT_GRAYEDOUT2; // Spectate - OP_AllControlsMenu[28].status = IT_GRAYEDOUT2; // Look Up - OP_AllControlsMenu[29].status = IT_GRAYEDOUT2; // Look Down - OP_AllControlsMenu[30].status = IT_GRAYEDOUT2; // Center View - */ - - M_SetupNextMenu(&OP_AllControlsDef); -} - -static void M_Setup3PControlsMenu(INT32 choice) -{ - (void)choice; - setupcontrolplayer = 3; - setupcontrols = gamecontrol3; - currentMenu->lastOn = itemOn; - - // Set proper gamepad options - OP_AllControlsMenu[0].itemaction = &OP_Joystick3Def; - - // Hide P1-only controls - OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat - //OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat - OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause - OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot - OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // GIF - OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // System Menu - OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // Console - /*OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Spectator Controls header - OP_AllControlsMenu[26].status = IT_GRAYEDOUT2; // Spectator Controls space - OP_AllControlsMenu[27].status = IT_GRAYEDOUT2; // Spectate - OP_AllControlsMenu[28].status = IT_GRAYEDOUT2; // Look Up - OP_AllControlsMenu[29].status = IT_GRAYEDOUT2; // Look Down - OP_AllControlsMenu[30].status = IT_GRAYEDOUT2; // Center View - */ - - M_SetupNextMenu(&OP_AllControlsDef); -} - -static void M_Setup4PControlsMenu(INT32 choice) -{ - (void)choice; - setupcontrolplayer = 4; - setupcontrols = gamecontrol4; - currentMenu->lastOn = itemOn; - - // Set proper gamepad options - OP_AllControlsMenu[0].itemaction = &OP_Joystick4Def; - - // Hide P1-only controls - OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat - //OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat - OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause - OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot - OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // GIF - OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // System Menu - OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // Console - /*OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Spectator Controls header - OP_AllControlsMenu[26].status = IT_GRAYEDOUT2; // Spectator Controls space - OP_AllControlsMenu[27].status = IT_GRAYEDOUT2; // Spectate - OP_AllControlsMenu[28].status = IT_GRAYEDOUT2; // Look Up - OP_AllControlsMenu[29].status = IT_GRAYEDOUT2; // Look Down - OP_AllControlsMenu[30].status = IT_GRAYEDOUT2; // Center View - */ - - M_SetupNextMenu(&OP_AllControlsDef); -} - -#define controlheight 18 - -// Draws the Customise Controls menu -static void M_DrawControl(void) -{ - char tmp[50]; - INT32 x, y, i, max, cursory = 0, iter; - INT32 keys[2]; - - x = currentMenu->x; - y = currentMenu->y; - - /*i = itemOn - (controlheight/2); - if (i < 0) - i = 0; - */ - - iter = (controlheight/2); - for (i = itemOn; ((iter || currentMenu->menuitems[i].status == IT_GRAYEDOUT2) && i > 0); i--) - { - if (currentMenu->menuitems[i].status != IT_GRAYEDOUT2) - iter--; - } - if (currentMenu->menuitems[i].status == IT_GRAYEDOUT2) - i--; - - iter += (controlheight/2); - for (max = itemOn; (iter && max < currentMenu->numitems); max++) - { - if (currentMenu->menuitems[max].status != IT_GRAYEDOUT2) - iter--; - } - - if (iter) - { - iter += (controlheight/2); - for (i = itemOn; ((iter || currentMenu->menuitems[i].status == IT_GRAYEDOUT2) && i > 0); i--) - { - if (currentMenu->menuitems[i].status != IT_GRAYEDOUT2) - iter--; - } - } - - /*max = i + controlheight; - if (max > currentMenu->numitems) - { - max = currentMenu->numitems; - if (max < controlheight) - i = 0; - else - i = max - controlheight; - }*/ - - // draw title (or big pic) - M_DrawMenuTitle(); - - M_CentreText(28, - (setupcontrolplayer > 1 ? va("\x86""Set controls for ""\x82""Player %d", setupcontrolplayer) : - "\x86""Press ""\x82""ENTER""\x86"" to change, ""\x82""BACKSPACE""\x86"" to clear")); - - if (i) - V_DrawCharacter(currentMenu->x - 16, y-(skullAnimCounter/5), - '\x1A' | highlightflags, false); // up arrow - if (max != currentMenu->numitems) - V_DrawCharacter(currentMenu->x - 16, y+(SMALLLINEHEIGHT*(controlheight-1))+(skullAnimCounter/5) + (skullAnimCounter/5), - '\x1B' | highlightflags, false); // down arrow - - for (; i < max; i++) - { - if (currentMenu->menuitems[i].status == IT_GRAYEDOUT2) - continue; - - if (i == itemOn) - cursory = y; - - if (currentMenu->menuitems[i].status == IT_CONTROL) - { - V_DrawString(x, y, ((i == itemOn) ? highlightflags : 0), currentMenu->menuitems[i].text); - keys[0] = setupcontrols[currentMenu->menuitems[i].mvar1][0]; - keys[1] = setupcontrols[currentMenu->menuitems[i].mvar1][1]; - - tmp[0] ='\0'; - if (keys[0] == KEY_NULL && keys[1] == KEY_NULL) - { - strcpy(tmp, "---"); - } - else - { - if (keys[0] != KEY_NULL) - strcat (tmp, G_KeynumToString (keys[0])); - - if (keys[0] != KEY_NULL && keys[1] != KEY_NULL) - strcat(tmp,", "); - - if (keys[1] != KEY_NULL) - strcat (tmp, G_KeynumToString (keys[1])); - - } - V_DrawRightAlignedString(BASEVIDWIDTH-currentMenu->x, y, highlightflags, tmp); - } - /*else if (currentMenu->menuitems[i].status == IT_GRAYEDOUT2) - V_DrawString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text);*/ - else if ((currentMenu->menuitems[i].status == IT_HEADER) && (i != max-1)) - V_DrawString(19, y+6, highlightflags, currentMenu->menuitems[i].text); - else if (currentMenu->menuitems[i].status & IT_STRING) - V_DrawString(x, y, ((i == itemOn) ? highlightflags : 0), currentMenu->menuitems[i].text); - - y += SMALLLINEHEIGHT; - } - - V_DrawScaledPatch(currentMenu->x - 20, cursory, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); -} - -#undef controlheight - -static INT32 controltochange; -static char controltochangetext[33]; - -static void M_ChangecontrolResponse(event_t *ev) -{ - INT32 control; - INT32 found; - INT32 ch = ev->data1; - - // ESCAPE cancels; dummy out PAUSE - if (ch != KEY_ESCAPE && ch != KEY_PAUSE) - { - - switch (ev->type) - { - // ignore mouse/joy movements, just get buttons - case ev_mouse: - case ev_mouse2: - case ev_joystick: - case ev_joystick2: - case ev_joystick3: - case ev_joystick4: - ch = KEY_NULL; // no key - break; - - // keypad arrows are converted for the menu in cursor arrows - // so use the event instead of ch - case ev_keydown: - ch = ev->data1; - break; - - default: - break; - } - - control = controltochange; - - // check if we already entered this key - found = -1; - if (setupcontrols[control][0] ==ch) - found = 0; - else if (setupcontrols[control][1] ==ch) - found = 1; - if (found >= 0) - { - // replace mouse and joy clicks by double clicks - if (ch >= KEY_MOUSE1 && ch <= KEY_MOUSE1+MOUSEBUTTONS) - setupcontrols[control][found] = ch-KEY_MOUSE1+KEY_DBLMOUSE1; - else if (ch >= KEY_JOY1 && ch <= KEY_JOY1+JOYBUTTONS) - setupcontrols[control][found] = ch-KEY_JOY1+KEY_DBLJOY1; - else if (ch >= KEY_2MOUSE1 && ch <= KEY_2MOUSE1+MOUSEBUTTONS) - setupcontrols[control][found] = ch-KEY_2MOUSE1+KEY_DBL2MOUSE1; - else if (ch >= KEY_2JOY1 && ch <= KEY_2JOY1+JOYBUTTONS) - setupcontrols[control][found] = ch-KEY_2JOY1+KEY_DBL2JOY1; - else if (ch >= KEY_3JOY1 && ch <= KEY_3JOY1+JOYBUTTONS) - setupcontrols[control][found] = ch-KEY_3JOY1+KEY_DBL3JOY1; - else if (ch >= KEY_4JOY1 && ch <= KEY_4JOY1+JOYBUTTONS) - setupcontrols[control][found] = ch-KEY_4JOY1+KEY_DBL4JOY1; - } - else - { - // check if change key1 or key2, or replace the two by the new - found = 0; - if (setupcontrols[control][0] == KEY_NULL) - found++; - if (setupcontrols[control][1] == KEY_NULL) - found++; - if (found == 2) - { - found = 0; - setupcontrols[control][1] = KEY_NULL; //replace key 1,clear key2 - } - (void)G_CheckDoubleUsage(ch, true); - setupcontrols[control][found] = ch; - } - S_StartSound(NULL, sfx_s221); - } - else if (ch == KEY_PAUSE) - { - // This buffer assumes a 125-character message plus a 32-character control name (per controltochangetext buffer size) - static char tmp[158]; - menu_t *prev = currentMenu->prevMenu; - - if (controltochange == gc_pause) - sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nyou may select another key. \n\nHit another key for\n%s\nESC for Cancel"), - controltochangetext); - else - sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nit is not configurable. \n\nHit another key for\n%s\nESC for Cancel"), - controltochangetext); - - M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER); - currentMenu->prevMenu = prev; - - S_StartSound(NULL, sfx_s3k42); - return; - } - else - S_StartSound(NULL, sfx_s224); - - M_StopMessage(0); -} - -static void M_ChangeControl(INT32 choice) -{ - // This buffer assumes a 35-character message (per below) plus a max control name limit of 32 chars (per controltochangetext) - // If you change the below message, then change the size of this buffer! - static char tmp[68]; - - controltochange = currentMenu->menuitems[choice].mvar1; - sprintf(tmp, M_GetText("Hit the new key for\n%s\nESC for Cancel"), - currentMenu->menuitems[choice].text); - strlcpy(controltochangetext, currentMenu->menuitems[choice].text, 33); - - M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER); -} - -static void M_ResetControlsResponse(INT32 ch) -{ - INT32 i; - - if (ch != 'y' && ch != KEY_ENTER) - return; - - // clear all controls - for (i = 0; i < num_gamecontrols; i++) - { - switch (setupcontrolplayer) - { - case 4: - G_ClearControlKeys(gamecontrol4, i); - break; - case 3: - G_ClearControlKeys(gamecontrol3, i); - break; - case 2: - G_ClearControlKeys(gamecontrolbis, i); - break; - case 1: - default: - G_ClearControlKeys(gamecontrol, i); - break; - } - } - - // Setup original defaults - G_Controldefault(setupcontrolplayer); - - // Setup gamepad option defaults (yucky) - switch (setupcontrolplayer) - { - case 4: - CV_StealthSet(&cv_usejoystick4, cv_usejoystick4.defaultvalue); - CV_StealthSet(&cv_turnaxis4, cv_turnaxis4.defaultvalue); - CV_StealthSet(&cv_moveaxis4, cv_moveaxis4.defaultvalue); - CV_StealthSet(&cv_brakeaxis4, cv_brakeaxis4.defaultvalue); - CV_StealthSet(&cv_aimaxis4, cv_aimaxis4.defaultvalue); - CV_StealthSet(&cv_lookaxis4, cv_lookaxis4.defaultvalue); - CV_StealthSet(&cv_fireaxis4, cv_fireaxis4.defaultvalue); - CV_StealthSet(&cv_driftaxis4, cv_driftaxis4.defaultvalue); - break; - case 3: - CV_StealthSet(&cv_usejoystick3, cv_usejoystick3.defaultvalue); - CV_StealthSet(&cv_turnaxis3, cv_turnaxis3.defaultvalue); - CV_StealthSet(&cv_moveaxis3, cv_moveaxis3.defaultvalue); - CV_StealthSet(&cv_brakeaxis3, cv_brakeaxis3.defaultvalue); - CV_StealthSet(&cv_aimaxis3, cv_aimaxis3.defaultvalue); - CV_StealthSet(&cv_lookaxis3, cv_lookaxis3.defaultvalue); - CV_StealthSet(&cv_fireaxis3, cv_fireaxis3.defaultvalue); - CV_StealthSet(&cv_driftaxis3, cv_driftaxis3.defaultvalue); - break; - case 2: - CV_StealthSet(&cv_usejoystick2, cv_usejoystick2.defaultvalue); - CV_StealthSet(&cv_turnaxis2, cv_turnaxis2.defaultvalue); - CV_StealthSet(&cv_moveaxis2, cv_moveaxis2.defaultvalue); - CV_StealthSet(&cv_brakeaxis2, cv_brakeaxis2.defaultvalue); - CV_StealthSet(&cv_aimaxis2, cv_aimaxis2.defaultvalue); - CV_StealthSet(&cv_lookaxis2, cv_lookaxis2.defaultvalue); - CV_StealthSet(&cv_fireaxis2, cv_fireaxis2.defaultvalue); - CV_StealthSet(&cv_driftaxis2, cv_driftaxis2.defaultvalue); - break; - case 1: - default: - CV_StealthSet(&cv_usejoystick, cv_usejoystick.defaultvalue); - CV_StealthSet(&cv_turnaxis, cv_turnaxis.defaultvalue); - CV_StealthSet(&cv_moveaxis, cv_moveaxis.defaultvalue); - CV_StealthSet(&cv_brakeaxis, cv_brakeaxis.defaultvalue); - CV_StealthSet(&cv_aimaxis, cv_aimaxis.defaultvalue); - CV_StealthSet(&cv_lookaxis, cv_lookaxis.defaultvalue); - CV_StealthSet(&cv_fireaxis, cv_fireaxis.defaultvalue); - CV_StealthSet(&cv_driftaxis, cv_driftaxis.defaultvalue); - break; - } - - S_StartSound(NULL, sfx_s224); -} - -static void M_ResetControls(INT32 choice) -{ - (void)choice; - M_StartMessage(va(M_GetText("Reset Player %d's controls to defaults?\n\n(Press 'Y' to confirm)\n"), setupcontrolplayer), M_ResetControlsResponse, MM_YESNO); -} - -// ===== -// SOUND -// ===== - -/*static void M_RestartAudio(void) -{ - COM_ImmedExecute("restartaudio"); -}*/ - -// =============== -// VIDEO MODE MENU -// =============== - -//added : 30-01-98: -#define MAXCOLUMNMODES 12 //max modes displayed in one column -#define MAXMODEDESCS (MAXCOLUMNMODES*3) - -static modedesc_t modedescs[MAXMODEDESCS]; - -static void M_VideoModeMenu(INT32 choice) -{ - INT32 i, j, vdup, nummodes, width, height; - const char *desc; - - (void)choice; - - memset(modedescs, 0, sizeof(modedescs)); - -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - VID_PrepareModeList(); // FIXME: hack -#endif - vidm_nummodes = 0; - vidm_selected = 0; - nummodes = VID_NumModes(); - -#ifdef _WINDOWS - // clean that later: skip windowed mode 0, video modes menu only shows FULL SCREEN modes - if (nummodes <= NUMSPECIALMODES) - i = 0; // unless we have nothing - else - i = NUMSPECIALMODES; -#else - // DOS does not skip mode 0, because mode 0 is ALWAYS present - i = 0; -#endif - for (; i < nummodes && vidm_nummodes < MAXMODEDESCS; i++) - { - desc = VID_GetModeName(i); - if (desc) - { - vdup = 0; - - // when a resolution exists both under VGA and VESA, keep the - // VESA mode, which is always a higher modenum - for (j = 0; j < vidm_nummodes; j++) - { - if (!strcmp(modedescs[j].desc, desc)) - { - // mode(0): 320x200 is always standard VGA, not vesa - if (modedescs[j].modenum) - { - modedescs[j].modenum = i; - vdup = 1; - - if (i == vid.modenum) - vidm_selected = j; - } - else - vdup = 1; - - break; - } - } - - if (!vdup) - { - modedescs[vidm_nummodes].modenum = i; - modedescs[vidm_nummodes].desc = desc; - - if (i == vid.modenum) - vidm_selected = vidm_nummodes; - - // Pull out the width and height - sscanf(desc, "%u%*c%u", &width, &height); - - // Show multiples of 320x200 as green. - if (SCR_IsAspectCorrect(width, height)) - modedescs[vidm_nummodes].goodratio = 1; - - vidm_nummodes++; - } - } - } - - vidm_column_size = (vidm_nummodes+2) / 3; - - M_SetupNextMenu(&OP_VideoModeDef); -} - -static void M_DrawVideoMenu(void) -{ - M_DrawGenericMenu(); - - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + OP_VideoOptionsMenu[0].mvar1, - (SCR_IsAspectCorrect(vid.width, vid.height) ? recommendedflags : highlightflags), - va("%dx%d", vid.width, vid.height)); -} - -static void M_DrawHUDOptions(void) -{ - const char *str0 = ")"; - const char *str1 = " Warning highlight"; - const char *str2 = ","; - const char *str3 = "Good highlight"; - INT32 x = BASEVIDWIDTH - currentMenu->x + 2, y = currentMenu->y + 105; - INT32 w0 = V_StringWidth(str0, 0), w1 = V_StringWidth(str1, 0), w2 = V_StringWidth(str2, 0), w3 = V_StringWidth(str3, 0); - - M_DrawGenericMenu(); - - x -= w0; - V_DrawString(x, y, highlightflags, str0); - x -= w1; - V_DrawString(x, y, warningflags, str1); - x -= w2; - V_DrawString(x, y, highlightflags, str2); - x -= w3; - V_DrawString(x, y, recommendedflags, str3); - V_DrawRightAlignedString(x, y, highlightflags, "("); -} - -// Draw the video modes list, a-la-Quake -static void M_DrawVideoMode(void) -{ - INT32 i, j, row, col; - - // draw title - M_DrawMenuTitle(); - - V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y, - highlightflags, "Choose mode, reselect to change default"); - - row = 41; - col = OP_VideoModeDef.y + 14; - for (i = 0; i < vidm_nummodes; i++) - { - if (i == vidm_selected) - V_DrawString(row, col, highlightflags, modedescs[i].desc); - // Show multiples of 320x200 as green. - else - V_DrawString(row, col, (modedescs[i].goodratio) ? recommendedflags : 0, modedescs[i].desc); - - col += 8; - if ((i % vidm_column_size) == (vidm_column_size-1)) - { - row += 7*13; - col = OP_VideoModeDef.y + 14; - } - } - - if (vidm_testingmode > 0) - { - INT32 testtime = (vidm_testingmode/TICRATE) + 1; - - M_CentreText(OP_VideoModeDef.y + 116, - va("Previewing mode %c%dx%d", - (SCR_IsAspectCorrect(vid.width, vid.height)) ? 0x83 : 0x80, - vid.width, vid.height)); - M_CentreText(OP_VideoModeDef.y + 138, - "Press ENTER again to keep this mode"); - M_CentreText(OP_VideoModeDef.y + 150, - va("Wait %d second%s", testtime, (testtime > 1) ? "s" : "")); - M_CentreText(OP_VideoModeDef.y + 158, - "or press ESC to return"); - - } - else - { - M_CentreText(OP_VideoModeDef.y + 116, - va("Current mode is %c%dx%d", - (SCR_IsAspectCorrect(vid.width, vid.height)) ? 0x83 : 0x80, - vid.width, vid.height)); - M_CentreText(OP_VideoModeDef.y + 124, - va("Default mode is %c%dx%d", - (SCR_IsAspectCorrect(cv_scr_width.value, cv_scr_height.value)) ? 0x83 : 0x80, - cv_scr_width.value, cv_scr_height.value)); - - V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 138, - recommendedflags, "Marked modes are recommended."); - V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 146, - highlightflags, "Other modes may have visual errors."); - V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 158, - highlightflags, "Larger modes may have performance issues."); - } - - // Draw the cursor for the VidMode menu - i = 41 - 10 + ((vidm_selected / vidm_column_size)*7*13); - j = OP_VideoModeDef.y + 14 + ((vidm_selected % vidm_column_size)*8); - - V_DrawScaledPatch(i - 8, j, 0, - W_CachePatchName("M_CURSOR", PU_CACHE)); -} - -// special menuitem key handler for video mode list -static void M_HandleVideoMode(INT32 ch) -{ - if (vidm_testingmode > 0) switch (ch) - { - // change back to the previous mode quickly - case KEY_ESCAPE: - setmodeneeded = vidm_previousmode + 1; - vidm_testingmode = 0; - break; - - case KEY_ENTER: - S_StartSound(NULL, sfx_menu1); - vidm_testingmode = 0; // stop testing - } - - else switch (ch) - { - case KEY_DOWNARROW: - S_StartSound(NULL, sfx_menu1); - if (++vidm_selected >= vidm_nummodes) - vidm_selected = 0; - break; - - case KEY_UPARROW: - S_StartSound(NULL, sfx_menu1); - if (--vidm_selected < 0) - vidm_selected = vidm_nummodes - 1; - break; - - case KEY_LEFTARROW: - S_StartSound(NULL, sfx_menu1); - vidm_selected -= vidm_column_size; - if (vidm_selected < 0) - vidm_selected = (vidm_column_size*3) + vidm_selected; - if (vidm_selected >= vidm_nummodes) - vidm_selected = vidm_nummodes - 1; - break; - - case KEY_RIGHTARROW: - S_StartSound(NULL, sfx_menu1); - vidm_selected += vidm_column_size; - if (vidm_selected >= (vidm_column_size*3)) - vidm_selected %= vidm_column_size; - if (vidm_selected >= vidm_nummodes) - vidm_selected = vidm_nummodes - 1; - break; - - case KEY_ENTER: - S_StartSound(NULL, sfx_menu1); - if (vid.modenum == modedescs[vidm_selected].modenum) - SCR_SetDefaultMode(); - else - { - vidm_testingmode = 15*TICRATE; - vidm_previousmode = vid.modenum; - if (!setmodeneeded) // in case the previous setmode was not finished - setmodeneeded = modedescs[vidm_selected].modenum + 1; - } - break; - - case KEY_ESCAPE: // this one same as M_Responder - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - break; - - default: - break; - } -} - -// =============== -// Monitor Toggles -// =============== -static consvar_t *kartitemcvs[NUMKARTRESULTS-1] = { - &cv_sneaker, - &cv_rocketsneaker, - &cv_invincibility, - &cv_banana, - &cv_eggmanmonitor, - &cv_orbinaut, - &cv_jawz, - &cv_mine, - &cv_ballhog, - &cv_selfpropelledbomb, - &cv_grow, - &cv_shrink, - &cv_thundershield, - &cv_hyudoro, - &cv_pogospring, - &cv_superring, - &cv_kitchensink, - &cv_triplesneaker, - &cv_triplebanana, - &cv_decabanana, - &cv_tripleorbinaut, - &cv_quadorbinaut, - &cv_dualjawz -}; - -static tic_t shitsfree = 0; - -static void M_DrawMonitorToggles(void) -{ - const INT32 edges = 4; - const INT32 height = 4; - const INT32 spacing = 35; - const INT32 column = itemOn/height; - //const INT32 row = itemOn%height; - INT32 leftdraw, rightdraw, totaldraw; - INT32 x = currentMenu->x, y = currentMenu->y+(spacing/4); - INT32 onx = 0, ony = 0; - consvar_t *cv; - INT32 i, translucent, drawnum; - - M_DrawMenuTitle(); - - // Find the available space around column - leftdraw = rightdraw = column; - totaldraw = 0; - for (i = 0; (totaldraw < edges*2 && i < edges*4); i++) - { - if (rightdraw+1 < (currentMenu->numitems/height)+1) - { - rightdraw++; - totaldraw++; - } - if (leftdraw-1 >= 0) - { - leftdraw--; - totaldraw++; - } - } - - for (i = leftdraw; i <= rightdraw; i++) - { - INT32 j; - - for (j = 0; j < height; j++) - { - const INT32 thisitem = (i*height)+j; - - if (thisitem >= currentMenu->numitems) - continue; - - if (thisitem == itemOn) - { - onx = x; - ony = y; - y += spacing; - continue; - } - -#ifdef ITEMTOGGLEBOTTOMRIGHT - if (currentMenu->menuitems[thisitem].mvar1 == 255) - { - V_DrawScaledPatch(x, y, V_TRANSLUCENT, W_CachePatchName("K_ISBG", PU_CACHE)); - continue; - } -#endif - if (currentMenu->menuitems[thisitem].mvar1 == 0) - { - V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE)); - V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISTOGL", PU_CACHE)); - continue; - } - - cv = kartitemcvs[currentMenu->menuitems[thisitem].mvar1-1]; - translucent = (cv->value ? 0 : V_TRANSLUCENT); - - switch (currentMenu->menuitems[thisitem].mvar1) - { - case KRITEM_DUALJAWZ: - drawnum = 2; - break; - case KRITEM_TRIPLESNEAKER: - case KRITEM_TRIPLEBANANA: - case KRITEM_TRIPLEORBINAUT: - drawnum = 3; - break; - case KRITEM_QUADORBINAUT: - drawnum = 4; - break; - case KRITEM_TENFOLDBANANA: - drawnum = 10; - break; - default: - drawnum = 0; - break; - } - - if (cv->value) - V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE)); - else - V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBGD", PU_CACHE)); - - if (drawnum != 0) - { - V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISMUL", PU_CACHE)); - V_DrawScaledPatch(x, y, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].mvar1, true), PU_CACHE)); - V_DrawString(x+24, y+31, V_ALLOWLOWERCASE|translucent, va("x%d", drawnum)); - } - else - V_DrawScaledPatch(x, y, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].mvar1, true), PU_CACHE)); - - y += spacing; - } - - x += spacing; - y = currentMenu->y+(spacing/4); - } - - { -#ifdef ITEMTOGGLEBOTTOMRIGHT - if (currentMenu->menuitems[itemOn].mvar1 == 255) - { - V_DrawScaledPatch(onx-1, ony-2, V_TRANSLUCENT, W_CachePatchName("K_ITBG", PU_CACHE)); - if (shitsfree) - { - INT32 trans = V_TRANSLUCENT; - if (shitsfree-1 > TICRATE-5) - trans = ((10-TICRATE)+shitsfree-1)<menuitems[itemOn].mvar1 == 0) - { - V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBG", PU_CACHE)); - V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITTOGL", PU_CACHE)); - } - else - { - cv = kartitemcvs[currentMenu->menuitems[itemOn].mvar1-1]; - translucent = (cv->value ? 0 : V_TRANSLUCENT); - - switch (currentMenu->menuitems[itemOn].mvar1) - { - case KRITEM_DUALJAWZ: - drawnum = 2; - break; - case KRITEM_TRIPLESNEAKER: - case KRITEM_TRIPLEBANANA: - drawnum = 3; - break; - case KRITEM_TENFOLDBANANA: - drawnum = 10; - break; - default: - drawnum = 0; - break; - } - - if (cv->value) - V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBG", PU_CACHE)); - else - V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBGD", PU_CACHE)); - - if (drawnum != 0) - { - V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITMUL", PU_CACHE)); - V_DrawScaledPatch(onx-1, ony-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[itemOn].mvar1, false), PU_CACHE)); - V_DrawScaledPatch(onx+27, ony+39, translucent, W_CachePatchName("K_ITX", PU_CACHE)); - V_DrawKartString(onx+37, ony+34, translucent, va("%d", drawnum)); - } - else - V_DrawScaledPatch(onx-1, ony-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[itemOn].mvar1, false), PU_CACHE)); - } - } - - if (shitsfree) - shitsfree--; - - V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y, highlightflags, va("* %s *", currentMenu->menuitems[itemOn].text)); -} - -static void M_HandleMonitorToggles(INT32 choice) -{ - const INT32 width = 6, height = 4; - INT32 column = itemOn/height, row = itemOn%height; - INT16 next; - UINT8 i; - boolean exitmenu = false; - - switch (choice) - { - case KEY_RIGHTARROW: - S_StartSound(NULL, sfx_menu1); - column++; - if (((column*height)+row) >= currentMenu->numitems) - column = 0; - next = min(((column*height)+row), currentMenu->numitems-1); - itemOn = next; - break; - - case KEY_LEFTARROW: - S_StartSound(NULL, sfx_menu1); - column--; - if (column < 0) - column = width-1; - if (((column*height)+row) >= currentMenu->numitems) - column--; - next = max(((column*height)+row), 0); - if (next >= currentMenu->numitems) - next = currentMenu->numitems-1; - itemOn = next; - break; - - case KEY_DOWNARROW: - S_StartSound(NULL, sfx_menu1); - row = (row+1) % height; - if (((column*height)+row) >= currentMenu->numitems) - row = 0; - next = min(((column*height)+row), currentMenu->numitems-1); - itemOn = next; - break; - - case KEY_UPARROW: - S_StartSound(NULL, sfx_menu1); - row = (row-1) % height; - if (row < 0) - row = height-1; - if (((column*height)+row) >= currentMenu->numitems) - row--; - next = max(((column*height)+row), 0); - if (next >= currentMenu->numitems) - next = currentMenu->numitems-1; - itemOn = next; - break; - - case KEY_ENTER: -#ifdef ITEMTOGGLEBOTTOMRIGHT - if (currentMenu->menuitems[itemOn].mvar1 == 255) - { - //S_StartSound(NULL, sfx_s26d); - if (!shitsfree) - { - shitsfree = TICRATE; - S_StartSound(NULL, sfx_itfree); - } - } - else -#endif - if (currentMenu->menuitems[itemOn].mvar1 == 0) - { - INT32 v = cv_sneaker.value; - S_StartSound(NULL, sfx_s1b4); - for (i = 0; i < NUMKARTRESULTS-1; i++) - { - if (kartitemcvs[i]->value == v) - CV_AddValue(kartitemcvs[i], 1); - } - } - else - { - S_StartSound(NULL, sfx_s1ba); - CV_AddValue(kartitemcvs[currentMenu->menuitems[itemOn].mvar1-1], 1); - } - break; - - case KEY_ESCAPE: - exitmenu = true; - break; - } - - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} - -// ========= -// Quit Game -// ========= -static INT32 quitsounds[] = -{ - // holy shit we're changing things up! - // srb2kart: you ain't seen nothing yet - sfx_kc2e, - sfx_kc2f, - sfx_cdfm01, - sfx_ddash, - sfx_s3ka2, - sfx_s3k49, - sfx_slip, - sfx_tossed, - sfx_s3k7b, - sfx_itrolf, - sfx_itrole, - sfx_cdpcm9, - sfx_s3k4e, - sfx_s259, - sfx_3db06, - sfx_s3k3a, - sfx_peel, - sfx_cdfm28, - sfx_s3k96, - sfx_s3kc0s, - sfx_cdfm39, - sfx_hogbom, - sfx_kc5a, - sfx_kc46, - sfx_s3k92, - sfx_s3k42, - sfx_kpogos, - sfx_screec -}; - -void M_QuitResponse(INT32 ch) -{ - tic_t ptime; - INT32 mrand; - - if (ch != 'y' && ch != KEY_ENTER) - return; - if (!(netgame || cv_debug)) - { - mrand = M_RandomKey(sizeof(quitsounds)/sizeof(INT32)); - if (quitsounds[mrand]) S_StartSound(NULL, quitsounds[mrand]); - - //added : 12-02-98: do that instead of I_WaitVbl which does not work - ptime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds Tails 03-26-2001 - while (ptime > I_GetTime()) - { - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - V_DrawSmallScaledPatch(0, 0, 0, W_CachePatchName("GAMEQUIT", PU_CACHE)); // Demo 3 Quit Screen Tails 06-16-2001 - I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001 - I_Sleep(); - } - } - I_Quit(); -} - -static void M_QuitSRB2(INT32 choice) -{ - // We pick index 0 which is language sensitive, or one at random, - // between 1 and maximum number. - (void)choice; - M_StartMessage(quitmsg[M_RandomKey(NUM_QUITMESSAGES)], M_QuitResponse, MM_YESNO); -} - -#ifdef HWRENDER -// ===================================================================== -// OpenGL specific options -// ===================================================================== - -#define FOG_COLOR_ITEM 1 -// =================== -// M_OGL_DrawFogMenu() -// =================== -static void M_OGL_DrawFogMenu(void) -{ - INT32 mx, my; - - mx = currentMenu->x; - my = currentMenu->y; - M_DrawGenericMenu(); // use generic drawer for cursor, items and title - V_DrawString(BASEVIDWIDTH - mx - V_StringWidth(cv_grfogcolor.string, 0), - my + currentMenu->menuitems[FOG_COLOR_ITEM].mvar1, highlightflags, cv_grfogcolor.string); - // blink cursor on FOG_COLOR_ITEM if selected - if (itemOn == FOG_COLOR_ITEM && skullAnimCounter < 4) - V_DrawCharacter(BASEVIDWIDTH - mx, - my + currentMenu->menuitems[FOG_COLOR_ITEM].mvar1, '_' | 0x80,false); -} - -// ===================== -// M_OGL_DrawColorMenu() -// ===================== -static void M_OGL_DrawColorMenu(void) -{ - INT32 mx, my; - - mx = currentMenu->x; - my = currentMenu->y; - M_DrawGenericMenu(); // use generic drawer for cursor, items and title - V_DrawString(mx, my + currentMenu->menuitems[0].mvar1 - 10, - highlightflags, "Gamma correction"); -} - -//=================== -// M_HandleFogColor() -//=================== -static void M_HandleFogColor(INT32 choice) -{ - size_t i, l; - char temp[8]; - boolean exitmenu = false; // exit to previous menu and send name change - - switch (choice) - { - case KEY_DOWNARROW: - S_StartSound(NULL, sfx_menu1); - itemOn++; - break; - - case KEY_UPARROW: - S_StartSound(NULL, sfx_menu1); - itemOn--; - break; - - case KEY_ESCAPE: - exitmenu = true; - break; - - case KEY_BACKSPACE: - S_StartSound(NULL, sfx_menu1); - strcpy(temp, cv_grfogcolor.string); - strcpy(cv_grfogcolor.zstring, "000000"); - l = strlen(temp)-1; - for (i = 0; i < l; i++) - cv_grfogcolor.zstring[i + 6 - l] = temp[i]; - break; - - default: - if ((choice >= '0' && choice <= '9') || (choice >= 'a' && choice <= 'f') - || (choice >= 'A' && choice <= 'F')) - { - S_StartSound(NULL, sfx_menu1); - strcpy(temp, cv_grfogcolor.string); - strcpy(cv_grfogcolor.zstring, "000000"); - l = strlen(temp); - for (i = 0; i < l; i++) - cv_grfogcolor.zstring[5 - i] = temp[l - i]; - cv_grfogcolor.zstring[5] = (char)choice; - } - break; - } - - if (exitmenu) - { - if (currentMenu->prevMenu) - M_SetupNextMenu(currentMenu->prevMenu); - else - M_ClearMenus(true); - } -} -#endif diff --git a/src/m_misc.c b/src/m_misc.c index f4a4ec291..6e53dc2ad 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -42,7 +42,7 @@ #include "m_anigif.h" // So that the screenshot menu auto-updates... -#include "m_menu.h" +#include "k_menu.h" #ifdef HWRENDER #include "hardware/hw_main.h" diff --git a/src/mserv.c b/src/mserv.c index c7344b16a..20a66ad4e 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -87,7 +87,7 @@ #include "i_tcp.h" #include "i_system.h" #include "byteptr.h" -#include "m_menu.h" +#include "k_menu.h" #include "m_argv.h" // Alam is going to kill me <3 #include "m_misc.h" // GetRevisionString() diff --git a/src/p_setup.c b/src/p_setup.c index 50260d4de..3dcfff839 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2598,7 +2598,7 @@ static void P_ForceCharacter(const char *forcecharskin) static void P_LoadRecordGhosts(void) { - // see also m_menu.c's Nextmap_OnChange + // see also k_menu.c's Nextmap_OnChange const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; char *gpath = malloc(glen); INT32 i; diff --git a/src/r_main.c b/src/r_main.c index 0d14bed73..17a82d4d4 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -23,7 +23,7 @@ #include "p_local.h" #include "keys.h" #include "i_video.h" -#include "m_menu.h" +#include "k_menu.h" #include "am_map.h" #include "d_main.h" #include "v_video.h" diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index e5f1c23fc..d1144c53b 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -61,7 +61,7 @@ #include "../i_system.h" #include "../v_video.h" #include "../m_argv.h" -#include "../m_menu.h" +#include "../k_menu.h" #include "../d_main.h" #include "../s_sound.h" #include "../i_sound.h" // midi pause/unpause @@ -1081,9 +1081,11 @@ void I_GetEvent(void) CONS_Debug(DBG_GAMELOGIC, "Joystick3 device index: %d\n", JoyInfo3.oldjoy); CONS_Debug(DBG_GAMELOGIC, "Joystick4 device index: %d\n", JoyInfo4.oldjoy); +#if 0 // update the menu if (currentMenu == &OP_JoystickSetDef) M_SetupJoystickMenu(0); +#endif if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) SDL_JoystickClose(newjoy); @@ -1242,9 +1244,11 @@ void I_GetEvent(void) CONS_Debug(DBG_GAMELOGIC, "Joystick3 device index: %d\n", JoyInfo3.oldjoy); CONS_Debug(DBG_GAMELOGIC, "Joystick4 device index: %d\n", JoyInfo4.oldjoy); +#if 0 // update the menu if (currentMenu == &OP_JoystickSetDef) M_SetupJoystickMenu(0); +#endif break; case SDL_QUIT: I_Quit(); diff --git a/src/st_stuff.c b/src/st_stuff.c index e59846aed..2b4f87c01 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -25,7 +25,7 @@ #include "hu_stuff.h" #include "s_sound.h" #include "i_system.h" -#include "m_menu.h" +#include "k_menu.h" #include "m_cheat.h" #include "p_setup.h" // NiGHTS grading #include "k_kart.h" // SRB2kart @@ -2045,11 +2045,11 @@ static void ST_overlayDrawer(void) void ST_DrawDemoTitleEntry(void) { - static UINT8 skullAnimCounter = 0; + static UINT8 anim = 0; char *nametodraw; - skullAnimCounter++; - skullAnimCounter %= 8; + anim++; + anim %= 8; nametodraw = demo.titlename; while (V_StringWidth(nametodraw, 0) > MAXSTRINGLENGTH*8 - 8) @@ -2059,7 +2059,7 @@ void ST_DrawDemoTitleEntry(void) #define y (BASEVIDHEIGHT/2) M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, nametodraw); - if (skullAnimCounter < 4) + if (anim < 4) V_DrawCharacter(x + 8 + V_StringWidth(nametodraw, 0), y + 12, '_' | 0x80, false); diff --git a/src/y_inter.c b/src/y_inter.c index c270f04ab..128fb8563 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -26,7 +26,7 @@ #include "w_wad.h" #include "y_inter.h" #include "z_zone.h" -#include "m_menu.h" +#include "k_menu.h" #include "m_misc.h" #include "i_system.h" #include "p_setup.h" @@ -39,7 +39,6 @@ #include "m_random.h" // M_RandomKey #include "g_input.h" // PLAYER1INPUTDOWN #include "k_kart.h" // colortranslations -#include "console.h" // cons_menuhighlight #include "lua_hook.h" // IntermissionThinker hook #ifdef HWRENDER @@ -363,9 +362,7 @@ void Y_IntermissionDrawer(void) if (!splitscreen) whiteplayer = demo.playback ? displayplayers[0] : consoleplayer; - if (cons_menuhighlight.value) - hilicol = cons_menuhighlight.value; - else if (modeattacking) + if (modeattacking) hilicol = V_ORANGEMAP; else hilicol = ((intertype == int_race) ? V_SKYMAP : V_REDMAP); @@ -1198,9 +1195,7 @@ void Y_VoteDrawer(void) if (timer) { INT32 hilicol, tickdown = (timer+1)/TICRATE; - if (cons_menuhighlight.value) - hilicol = cons_menuhighlight.value; - else if (gametype == GT_RACE) + if (gametype == GT_RACE) hilicol = V_SKYMAP; else //if (gametype == GT_MATCH) hilicol = V_REDMAP;